mirror of
https://github.com/pnp/sp-dev-fx-webparts.git
synced 2025-03-01 01:09:09 +00:00
Dev (#114)
* initialize * wer * asd * ok * COOOOL * asd * move most to panel * switch to react-slick * gOT cSS * poseter * asd * Leave image until user selcte to play * sdg * qwe * asd * addiing back 3d carousel * Added back 3d carousel * coverflow working * all 3 working * fixup linting * Update README.md * fix readme * Update README.md * got it working on rc0 * autoplay * qwd * rename Cpverflow to Coverflow * cdn qw * SPHttpClient.configurations.v1 * as * AS * added instructions on merging existing github procjects * added controls to set playerwidth and height * Update README.md fixup readme
This commit is contained in:
parent
27b2672a77
commit
1e20f20229
16
.github/CONTRIBUTING.md
vendored
16
.github/CONTRIBUTING.md
vendored
@ -56,7 +56,21 @@ When you are submitting a new sample, it has to follow up below guidelines
|
|||||||
Please see following wiki post from the GitHub repository wiki for exact steps on submitting new pull requests.
|
Please see following wiki post from the GitHub repository wiki for exact steps on submitting new pull requests.
|
||||||
|
|
||||||
* How to submit a PR to SharePoint repository? - Step-by-step with commands and pictures coming soon
|
* How to submit a PR to SharePoint repository? - Step-by-step with commands and pictures coming soon
|
||||||
|
## Meging your existing github projects with this repository
|
||||||
|
If the sample you wish to contrubute is tored in your own Github repository, you can use the following steps to merge it with the Psp-dev-fx-webparts repository:
|
||||||
|
- Fork the sp-dev-fx-webparts repository om hithub
|
||||||
|
- create a local git rpository
|
||||||
|
md sp-dev-fx-webparts
|
||||||
|
cd sp-dev-fx-webparts
|
||||||
|
git init
|
||||||
|
- pull your forked copy of sp-dev-fx-webparts into your local repository
|
||||||
|
git remote add origin https://github.com/yourgitaccount/sp-dev-fx-webparts.git
|
||||||
|
git pull origin dev
|
||||||
|
- pull your other project from github into the samples folder of your local copy of sp-dev-fx-webparts
|
||||||
|
git subtree add --prefix=samples/projectname https://github.com/yourgitaccount/projectname.git master
|
||||||
|
- push the changes up to your forked repository
|
||||||
|
git push orgin dev
|
||||||
|
|
||||||
## Signing the CLA
|
## Signing the CLA
|
||||||
Before we can accept your pull requests you will be asked to sign electronically Contributor License Agreement (CLA), which is prerequisite for any contributions to PnP repository. This will be one time process, so for any future contributions you will not be asked to re-sign anything. After the CLA has been signed, our PnP core team members will have a look on your submission for final verification of the submission. Please do not delete your development branch until the submission has been closed.
|
Before we can accept your pull requests you will be asked to sign electronically Contributor License Agreement (CLA), which is prerequisite for any contributions to PnP repository. This will be one time process, so for any future contributions you will not be asked to re-sign anything. After the CLA has been signed, our PnP core team members will have a look on your submission for final verification of the submission. Please do not delete your development branch until the submission has been closed.
|
||||||
|
|
||||||
|
25
samples/react-videolibrary/.editorconfig
Normal file
25
samples/react-videolibrary/.editorconfig
Normal file
@ -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
|
1
samples/react-videolibrary/.gitattributes
vendored
Normal file
1
samples/react-videolibrary/.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
* text=auto
|
32
samples/react-videolibrary/.gitignore
vendored
Normal file
32
samples/react-videolibrary/.gitignore
vendored
Normal file
@ -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
|
14
samples/react-videolibrary/.npmignore
Normal file
14
samples/react-videolibrary/.npmignore
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Folders
|
||||||
|
.vscode
|
||||||
|
coverage
|
||||||
|
node_modules
|
||||||
|
sharepoint
|
||||||
|
src
|
||||||
|
temp
|
||||||
|
|
||||||
|
# Files
|
||||||
|
*.csproj
|
||||||
|
.git*
|
||||||
|
.yo-rc.json
|
||||||
|
gulpfile.js
|
||||||
|
tsconfig.json
|
3
samples/react-videolibrary/.vscode/settings.json
vendored
Normal file
3
samples/react-videolibrary/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"typescript.check.workspaceVersion": false
|
||||||
|
}
|
7
samples/react-videolibrary/.yo-rc.json
Normal file
7
samples/react-videolibrary/.yo-rc.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"@microsoft/generator-sharepoint": {
|
||||||
|
"libraryName": "videotst",
|
||||||
|
"libraryId": "841958c7-1d50-408b-9df4-feac7165d4a0",
|
||||||
|
"framework": "react"
|
||||||
|
}
|
||||||
|
}
|
84
samples/react-videolibrary/README.md
Normal file
84
samples/react-videolibrary/README.md
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
# React Video Library
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
A set of 3 SPFX webparts that use different open-source carousels (react-3d-carousel, reactjs-coverface, and react-slick)
|
||||||
|
to display videos stored on an O365 Video Channel. The idea being to display a carousel of the thumbnail images, and then
|
||||||
|
when a user clicks on one of the thumbnails, replace the tumbnail with a video player and start the video up.
|
||||||
|
|
||||||
|
The first webpart used react-3d-carousel. The carousel looks great, but i found no way to swap out the image and replace
|
||||||
|
it with a video player. This carousel would be fine for displayin a picture library though,
|
||||||
|
|
||||||
|
The second webpart used react-slick. The carousel is not as fancy as react-3d-carousel, but i was able to to swap out the
|
||||||
|
image and replace it with a video player once a user clicked it. I had trouble with the css and getting the next and previous
|
||||||
|
buttons to show. If you run the webpart, the buttons are there, they are just not visible.
|
||||||
|
|
||||||
|
Finally I tried reactjs-coverface. It has nice scrolling through the images withe the mousweheel, and some cool 3d effects.
|
||||||
|
It was also simple to swap the image with a video player once a user clicked it (same code as react-slick). This is the best
|
||||||
|
of the three for my purposes.
|
||||||
|
|
||||||
|
|
||||||
|
In the future I want to modify this webpart to link a Sharepoint list with the video channel so that users can enter additional
|
||||||
|
metadata for the video and be anle to search/filter the videos using this metadata.
|
||||||
|
|
||||||
|
See also https://github.com/russgove/O365VideoSync. It's a console app that you can schedule to run to synchronize an Office 365 Video Channel with a sharepoint list (on prem or otherwise).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## Used SharePoint Framework Version
|
||||||
|

|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
> React, react-3d-carousel reactjs-coverface react-slick
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
Solution|Author(s)
|
||||||
|
--------|---------
|
||||||
|
react-VideoLibrary | Russell Gove
|
||||||
|
|
||||||
|
## Version history
|
||||||
|
|
||||||
|
Version|Date|Comments
|
||||||
|
-------|----|--------
|
||||||
|
0.1|December 31, 2016|Initial version
|
||||||
|
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
- Clone this repository
|
||||||
|
- in the command line run:
|
||||||
|
- `npm install`
|
||||||
|
- `tsd install`
|
||||||
|
- `gulp serve`
|
||||||
|
|
||||||
|
> Include any additional steps as needed.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
A set of 3 SPFX webparts that use different open-source carousels (react-3d-carousel, reactjs-coverface, and react-slick)
|
||||||
|
to display videos stored on an O365 Video Channel.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
|
||||||
|
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-multilist-grid" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
27
samples/react-videolibrary/config/config.json
Normal file
27
samples/react-videolibrary/config/config.json
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"entry": "./lib/webparts/videoLibrary/VideoLibraryWebPart.js",
|
||||||
|
"manifest": "./src/webparts/videoLibrary/VideoLibraryWebPart.manifest.json",
|
||||||
|
"outputPath": "./dist/video-library.bundle.js"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"entry": "./lib/webparts/videoLibraryReact3DCarousel/VideoLibraryReact3DCarouselWebPart.js",
|
||||||
|
"manifest": "./src/webparts/videoLibraryReact3DCarousel/VideoLibraryReact3DCarouselWebPart.manifest.json",
|
||||||
|
"outputPath": "./dist/video-library-react-3-d-carousel.bundle.js"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"entry": "./lib/webparts/videoLibraryCoverFlow/VideoLibraryCoverFlowWebPart.js",
|
||||||
|
"manifest": "./src/webparts/videoLibraryCoverFlow/VideoLibraryCoverFlowWebPart.manifest.json",
|
||||||
|
"outputPath": "./dist/video-library-cpver-flow.bundle.js"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"externals": {
|
||||||
|
"@microsoft/sp-module-loader": "node_modules/@microsoft/sp-module-loader/dist/sp-module-loader.js"
|
||||||
|
},
|
||||||
|
"localizedResources": {
|
||||||
|
"videoLibraryStrings": "webparts/videoLibrary/loc/{locale}.js",
|
||||||
|
"videoLibraryReact3DCarouselStrings": "webparts/videoLibraryReact3DCarousel/loc/{locale}.js",
|
||||||
|
"videoLibraryCoverFlowStrings": "webparts/videoLibraryCoverFlow/loc/{locale}.js"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"workingDir": "./temp/deploy/",
|
||||||
|
"account": "<!-- STORAGE ACCOUNT NAME -->",
|
||||||
|
"container": "videotst",
|
||||||
|
"accessKey": "<!-- ACCESS KEY -->"
|
||||||
|
}
|
10
samples/react-videolibrary/config/package-solution.json
Normal file
10
samples/react-videolibrary/config/package-solution.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"solution": {
|
||||||
|
"name": "videotst-client-side-solution",
|
||||||
|
"id": "841958c7-1d50-408b-9df4-feac7165d4a0",
|
||||||
|
"version": "1.0.0.0"
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"zippedPackage": "solution/videotst.spapp"
|
||||||
|
}
|
||||||
|
}
|
3
samples/react-videolibrary/config/prepare-deploy.json
Normal file
3
samples/react-videolibrary/config/prepare-deploy.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"deployCdnPath": "temp/deploy"
|
||||||
|
}
|
9
samples/react-videolibrary/config/serve.json
Normal file
9
samples/react-videolibrary/config/serve.json
Normal file
@ -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/"
|
||||||
|
}
|
||||||
|
}
|
50
samples/react-videolibrary/config/tslint.json
Normal file
50
samples/react-videolibrary/config/tslint.json
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
samples/react-videolibrary/config/write-manifests.json
Normal file
3
samples/react-videolibrary/config/write-manifests.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"cdnBasePath": "https://rgove3.sharepoint.com/sites/cdn/spfxapps/"
|
||||||
|
}
|
6
samples/react-videolibrary/gulpfile.js
vendored
Normal file
6
samples/react-videolibrary/gulpfile.js
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const gulp = require('gulp');
|
||||||
|
const build = require('@microsoft/sp-build-web');
|
||||||
|
|
||||||
|
build.initialize(gulp);
|
38
samples/react-videolibrary/package.json
Normal file
38
samples/react-videolibrary/package.json
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"name": "videotst",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"private": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@microsoft/sp-client-base": "~0.7.0",
|
||||||
|
"@microsoft/sp-core-library": "~0.1.2",
|
||||||
|
"@microsoft/sp-webpart-base": "~0.4.0",
|
||||||
|
"@types/webpack-env": ">=1.12.1 <1.14.0",
|
||||||
|
"@types/react": "0.14.46",
|
||||||
|
"@types/react-addons-shallow-compare": "0.14.17",
|
||||||
|
"@types/react-addons-test-utils": "0.14.15",
|
||||||
|
"@types/react-addons-update": "0.14.14",
|
||||||
|
"@types/react-dom": "0.14.18",
|
||||||
|
"office-ui-fabric-react": "0.69.0",
|
||||||
|
"react": "0.14.8",
|
||||||
|
"react-3d-carousel": "0.0.6",
|
||||||
|
"react-dom": "0.14.8",
|
||||||
|
"react-slick": "^0.14.5",
|
||||||
|
"reactjs-coverflow": "^1.0.5"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@microsoft/sp-build-web": "~0.9.0",
|
||||||
|
"@microsoft/sp-module-interfaces": "~0.7.0",
|
||||||
|
"@microsoft/sp-webpart-workbench": "~0.8.0",
|
||||||
|
"gulp": "~3.9.1",
|
||||||
|
"@types/chai": ">=3.4.34 <3.6.0",
|
||||||
|
"@types/mocha": ">=2.2.33 <2.6.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "gulp bundle",
|
||||||
|
"clean": "gulp clean",
|
||||||
|
"test": "gulp test"
|
||||||
|
}
|
||||||
|
}
|
5
samples/react-videolibrary/src/tests.js
vendored
Normal file
5
samples/react-videolibrary/src/tests.js
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
var context = require.context('.', true, /.+\.test\.js?$/);
|
||||||
|
|
||||||
|
context.keys().forEach(context);
|
||||||
|
|
||||||
|
module.exports = context;
|
167
samples/react-videolibrary/src/webparts/O365VUtilities.ts
Normal file
167
samples/react-videolibrary/src/webparts/O365VUtilities.ts
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
import {Promise} from "es6-promise"; // added fro rc0
|
||||||
|
import { IWebPartContext } from '@microsoft/sp-webpart-base';
|
||||||
|
import { SPHttpClient ,SPHttpClientConfigurations} from '@microsoft/sp-http';
|
||||||
|
export class VideoServiceSettings {
|
||||||
|
public ChannelUrlTemplate: string;
|
||||||
|
public IsVideoPortalEnabled: string;
|
||||||
|
public PlayerUrlTemplate: string;
|
||||||
|
public VideoPortalLayoutsUrl: string;
|
||||||
|
public VideoPortalUrl: string;
|
||||||
|
public O365VideoPageUrl: string;
|
||||||
|
}
|
||||||
|
export class VideoChannel {
|
||||||
|
public Description: string;
|
||||||
|
public Id: string;
|
||||||
|
public ServerRelativeUrl: string;
|
||||||
|
public TileHtmlColor: string;
|
||||||
|
public Title: string;
|
||||||
|
public YammerEnabled: string;
|
||||||
|
}
|
||||||
|
export class Video {
|
||||||
|
public ChannelID: string;
|
||||||
|
/** CreatedDate -- The date the video was originally uploaded. */
|
||||||
|
public CreatedDate: string;
|
||||||
|
public Description: string;
|
||||||
|
public DisplayFormUrl: string;
|
||||||
|
public FileName: string;
|
||||||
|
public ID: string;
|
||||||
|
public OwnerName: string;
|
||||||
|
public ServerRelativeUrl: string;
|
||||||
|
/**ThumbnailURL -- The URL of the thumbnail image of the video. */
|
||||||
|
public ThumbnailUrl: string;
|
||||||
|
/**Title -- The title of the video. */
|
||||||
|
public Title: string;
|
||||||
|
public Url: string;
|
||||||
|
public VideoDownloadUrl: string;
|
||||||
|
/**Title -- The title of the video. */
|
||||||
|
public VideoDurationInSeconds: number;
|
||||||
|
public VideoProcessingStatus: number;
|
||||||
|
public ViewCount: number;
|
||||||
|
public YammerObjectUrl: string;
|
||||||
|
}
|
||||||
|
export enum VideoProcessingStatus {
|
||||||
|
/** 0 -- (default) -- The video has not yet been processed for playback. */
|
||||||
|
NotProcessd = 0,
|
||||||
|
/**1 -- The video has been picked up and is being processed. */
|
||||||
|
BeingProcessed = 1,
|
||||||
|
/**2 -- The video is ready to play. */
|
||||||
|
Ready = 2,
|
||||||
|
/**3 -- The video encountered an error while it was being uploaded to Azure Media Services for processing. */
|
||||||
|
AzureError = 3,
|
||||||
|
/**4 -- Error -- Generic error--Unable to process the video for streaming. */
|
||||||
|
GenericError = 4,
|
||||||
|
/**5 -- Error -- Timeout error--Unable to process the video for streaming. */
|
||||||
|
TimeoutError = 5,
|
||||||
|
/**6 -- Error -- Unsupported format --The video file type is not supported for streaming playback by Azure Media Services. */
|
||||||
|
UnsupportedFormatError = 6
|
||||||
|
}
|
||||||
|
|
||||||
|
export class O365Video {
|
||||||
|
public videoServiceSettings: VideoServiceSettings;
|
||||||
|
public isInitialized: boolean;
|
||||||
|
public videoChannels: Array<VideoChannel>;
|
||||||
|
public httpClient: SPHttpClient;
|
||||||
|
public siteAbsoluteUrl: string;
|
||||||
|
constructor(context: IWebPartContext) {
|
||||||
|
this.httpClient = context.spHttpClient;
|
||||||
|
this.isInitialized = false;
|
||||||
|
this.siteAbsoluteUrl = context.pageContext.site.absoluteUrl;
|
||||||
|
}
|
||||||
|
public Initialize(): Promise<VideoServiceSettings> {
|
||||||
|
|
||||||
|
const url = this.siteAbsoluteUrl + "/_api/VideoService.Discover";
|
||||||
|
// return this.httpClient.get(url).then(response => { //pre rc0
|
||||||
|
return this.httpClient.get(url,SPHttpClient.configurations.v1).then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
console.log("Returned OK from httpClient");
|
||||||
|
debugger;
|
||||||
|
const results = response.json().then(settings => {
|
||||||
|
this.videoServiceSettings = new VideoServiceSettings();
|
||||||
|
this.videoServiceSettings.ChannelUrlTemplate = settings.ChannelUrlTemplate;
|
||||||
|
this.videoServiceSettings.IsVideoPortalEnabled = settings.IsVideoPortalEnabled;
|
||||||
|
this.videoServiceSettings.PlayerUrlTemplate = settings.PlayerUrlTemplate;
|
||||||
|
this.videoServiceSettings.VideoPortalLayoutsUrl = settings.VideoPortalLayoutsUrl;
|
||||||
|
this.videoServiceSettings.VideoPortalUrl = settings.VideoPortalUrl;
|
||||||
|
this.videoServiceSettings.O365VideoPageUrl = settings.O365VideoPageUrl;
|
||||||
|
return this.videoServiceSettings;
|
||||||
|
});
|
||||||
|
this.isInitialized = true;
|
||||||
|
return results;
|
||||||
|
} else {
|
||||||
|
this.isInitialized = true;
|
||||||
|
console.log("WARNING - failed to hit URL " + url + ". Error = " + response.statusText);
|
||||||
|
throw "Error " + response.statusText;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public getChannels(): Promise<Array<VideoChannel>> {
|
||||||
|
|
||||||
|
const url = this.videoServiceSettings.VideoPortalUrl + "/_api/VideoService/Channels";
|
||||||
|
return this.httpClient.get(url,SPHttpClient.configurations.v1).then(response => {
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
console.log("Returned OK from httpClient");
|
||||||
|
|
||||||
|
return response.json().then(channels => {
|
||||||
|
|
||||||
|
this.videoChannels = channels.value.map(c => {
|
||||||
|
const channel = new VideoChannel();
|
||||||
|
channel.Description = c.Description;
|
||||||
|
channel.Id = c.Id;
|
||||||
|
channel.ServerRelativeUrl = c.ServerRelativeUrl;
|
||||||
|
channel.TileHtmlColor = c.TileHtmlColor;
|
||||||
|
channel.Title = c.Title;
|
||||||
|
channel.YammerEnabled = c.YammerEnabled;
|
||||||
|
return channel;
|
||||||
|
});
|
||||||
|
return this.videoChannels;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log("WARNING - failed to hit URL " + url + ". Error = " + response.statusText);
|
||||||
|
throw "Error " + response.statusText;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public GetVideos(ChannelId: string): Promise<Array<Video>> {
|
||||||
|
const url = this.videoServiceSettings.VideoPortalUrl + "/_api/VideoService/Channels('" + ChannelId + "')/Videos";
|
||||||
|
return this.httpClient.get(url,SPHttpClient.configurations.v1).then(response => {
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json().then(v => {
|
||||||
|
|
||||||
|
const videos = v.value.map(c => {
|
||||||
|
let video = new Video();
|
||||||
|
video.ChannelID = c.ChannelID;
|
||||||
|
video.Description = c.Description;
|
||||||
|
video.DisplayFormUrl = c.DisplayFormUrl;
|
||||||
|
video.FileName = c.FileName;
|
||||||
|
video.ID = c.ID;
|
||||||
|
video.OwnerName = c.OwnerName;
|
||||||
|
video.ServerRelativeUrl = c.ServerRelativeUrl;
|
||||||
|
video.Title = c.Title;
|
||||||
|
video.ThumbnailUrl = c.ThumbnailUrl;
|
||||||
|
video.Url = c.Url;
|
||||||
|
video.VideoDownloadUrl = c.VideoDownloadUrl;
|
||||||
|
video.VideoDurationInSeconds = c.VideoDurationInSeconds;
|
||||||
|
video.VideoProcessingStatus = c.VideoProcessingStatus;
|
||||||
|
video.ViewCount = c.ViewCount;
|
||||||
|
video.YammerObjectUrl = c.YammerObjectUrl;
|
||||||
|
return video;
|
||||||
|
});
|
||||||
|
return videos;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log("WARNING - failed to hit URL " + url + ". Error = " + response.statusText);
|
||||||
|
throw "Error " + response.statusText;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public GetChannelByName(ChannelTitle: string): Promise<VideoChannel> {
|
||||||
|
return this.getChannels().then(channels => {
|
||||||
|
const matches = channels.filter((value, index, array) => { return value.Title === ChannelTitle; });
|
||||||
|
return matches[0];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
import { O365Video } from "../O365VUtilities";
|
||||||
|
export interface IVideoLibraryWebPartProps {
|
||||||
|
description: string;
|
||||||
|
videoChannel: string;
|
||||||
|
o365Video: O365Video;
|
||||||
|
layout:string;
|
||||||
|
duration:number;
|
||||||
|
panels:number;
|
||||||
|
}
|
@ -0,0 +1,119 @@
|
|||||||
|
.slick-slide {
|
||||||
|
height: 80vh;
|
||||||
|
background: #2196f3;
|
||||||
|
text-align: center;
|
||||||
|
color: white;
|
||||||
|
font-size: 20px;
|
||||||
|
display: table !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slick-slide div {
|
||||||
|
display: table-cell;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-0 {
|
||||||
|
background: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-1 {
|
||||||
|
background: orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-2 {
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-3{
|
||||||
|
background: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer1 {
|
||||||
|
height: 100px;
|
||||||
|
color: white;
|
||||||
|
background: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer2 {
|
||||||
|
height: 100px;
|
||||||
|
color: white;
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-container {
|
||||||
|
height: 100px;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-container div {
|
||||||
|
padding: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-enter {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
opacity: 0.01;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-enter.example-enter-active {
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity .5s ease-in;
|
||||||
|
}
|
||||||
|
.example-leave {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-leave.example-leave-active {
|
||||||
|
opacity: 0.01;
|
||||||
|
transition: opacity .5s ease-in;
|
||||||
|
}
|
||||||
|
.videoLibrary {
|
||||||
|
.container {
|
||||||
|
max-width: 700px;
|
||||||
|
margin: 0px auto;
|
||||||
|
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.listItem {
|
||||||
|
max-width: 715px;
|
||||||
|
margin: 5px auto 5px auto;
|
||||||
|
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.slides {
|
||||||
|
position: relative;
|
||||||
|
.slick-prev, .slick-next {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
}
|
||||||
|
.slick-prev {
|
||||||
|
left: 5%;
|
||||||
|
}
|
||||||
|
.slick-next {
|
||||||
|
right: 5%;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json",
|
||||||
|
|
||||||
|
"id": "f0d034d3-6b7d-4907-a6c1-357c2e2e03af",
|
||||||
|
"alias": "VideoLibraryWebPart",
|
||||||
|
"componentType": "WebPart",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"manifestVersion": 2,
|
||||||
|
|
||||||
|
"preconfiguredEntries": [{
|
||||||
|
"groupId": "f0d034d3-6b7d-4907-a6c1-357c2e2e03af",
|
||||||
|
"group": { "default": "Under Development" },
|
||||||
|
"title": { "default": "React-slick Video Library" },
|
||||||
|
"description": {
|
||||||
|
"default": "VideoLibrary implemented using react-slick -- Shows videos from an O365 Video Channel"
|
||||||
|
},
|
||||||
|
"officeFabricIconFontName": "Ribbon",
|
||||||
|
"properties": {
|
||||||
|
"description": "React-slick Video Library",
|
||||||
|
"layout":"prism",
|
||||||
|
"duration":199
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
@ -0,0 +1,116 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import * as ReactDom from "react-dom";
|
||||||
|
import {
|
||||||
|
BaseClientSideWebPart,
|
||||||
|
IPropertyPaneConfiguration ,
|
||||||
|
PropertyPaneTextField,
|
||||||
|
PropertyPaneDropdown, IPropertyPaneDropdownOption,
|
||||||
|
PropertyPaneSlider
|
||||||
|
} from "@microsoft/sp-webpart-base";
|
||||||
|
import { O365Video } from "../O365VUtilities";
|
||||||
|
import * as strings from "videoLibraryStrings";
|
||||||
|
import VideoLibrary, { IVideoLibraryProps } from "./components/VideoLibrary";
|
||||||
|
import { IVideoLibraryWebPartProps } from "./IVideoLibraryWebPartProps";
|
||||||
|
import {SPComponentLoader} from "@microsoft/sp-loader";
|
||||||
|
|
||||||
|
export default class VideoLibraryWebPart extends BaseClientSideWebPart<IVideoLibraryWebPartProps> {
|
||||||
|
private O365Video: O365Video;
|
||||||
|
private channels: Array<IPropertyPaneDropdownOption>;
|
||||||
|
private channelsFetched: boolean;
|
||||||
|
|
||||||
|
public onInit<T>(): Promise<T> {
|
||||||
|
SPComponentLoader.loadCss("https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css");
|
||||||
|
SPComponentLoader.loadCss("https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick-theme.min.css");
|
||||||
|
this.O365Video = new O365Video(this.context);
|
||||||
|
return Promise.resolve(null);
|
||||||
|
}
|
||||||
|
public render(): void {
|
||||||
|
|
||||||
|
const props: IVideoLibraryProps = {
|
||||||
|
description: this.properties.description,
|
||||||
|
videoChannel: this.properties.videoChannel,
|
||||||
|
o365Video: this.O365Video,
|
||||||
|
layout: this.properties.layout,
|
||||||
|
duration: this.properties.duration,
|
||||||
|
panels: this.properties.panels
|
||||||
|
};
|
||||||
|
const element: React.ReactElement<IVideoLibraryProps> = React.createElement(VideoLibrary, props);
|
||||||
|
|
||||||
|
ReactDom.render(element, this.domElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||||
|
|
||||||
|
debugger;
|
||||||
|
if (!this.O365Video.isInitialized) {
|
||||||
|
this.O365Video.Initialize().then(x => {
|
||||||
|
this.O365Video.getChannels().then(channels => {
|
||||||
|
this.context.propertyPane.refresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!this.channelsFetched && this.O365Video.isInitialized) {
|
||||||
|
this.O365Video.getChannels().then(channels => {
|
||||||
|
this.channels = channels.map((c, i, a) => {
|
||||||
|
let opt: IPropertyPaneDropdownOption = {
|
||||||
|
key: c.Id,
|
||||||
|
text: c.Title,
|
||||||
|
index: i,
|
||||||
|
|
||||||
|
};
|
||||||
|
return opt;
|
||||||
|
});
|
||||||
|
this.channelsFetched = true;
|
||||||
|
this.context.propertyPane.refresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
pages: [
|
||||||
|
{
|
||||||
|
header: {
|
||||||
|
description: strings.PropertyPaneDescription
|
||||||
|
},
|
||||||
|
groups: [
|
||||||
|
{
|
||||||
|
groupName: strings.BasicGroupName,
|
||||||
|
groupFields: [
|
||||||
|
PropertyPaneTextField("description", {
|
||||||
|
label: strings.DescriptionFieldLabel
|
||||||
|
}),
|
||||||
|
PropertyPaneDropdown("videoChannel", {
|
||||||
|
label: strings.VideoChannelFieldLabel,
|
||||||
|
options: this.channels,
|
||||||
|
|
||||||
|
}),
|
||||||
|
PropertyPaneDropdown("layout", {
|
||||||
|
label: strings.LayoutFieldLabel,
|
||||||
|
options: [
|
||||||
|
{ key: "prism", text: "prism" },
|
||||||
|
{ key: "clssic", text: "classic" }
|
||||||
|
]
|
||||||
|
|
||||||
|
}),
|
||||||
|
PropertyPaneSlider("duration", {
|
||||||
|
label: strings.DurationFieldLabel,
|
||||||
|
min: 1,
|
||||||
|
max: 1000
|
||||||
|
}),
|
||||||
|
PropertyPaneSlider("panels", {
|
||||||
|
label: strings.PanelsFieldLabel,
|
||||||
|
min: 1,
|
||||||
|
max: 5
|
||||||
|
}),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import { css } from "office-ui-fabric-react";
|
||||||
|
var Slick = require("react-slick");
|
||||||
|
import { IVideoLibraryWebPartProps } from "../IVideoLibraryWebPartProps";
|
||||||
|
import { Video} from "../../O365VUtilities";
|
||||||
|
export interface IVideoLibraryProps extends IVideoLibraryWebPartProps {
|
||||||
|
|
||||||
|
}
|
||||||
|
export interface IVideoLibraryState {
|
||||||
|
ease: string;
|
||||||
|
width: number;
|
||||||
|
playerUrlTemplate: string;
|
||||||
|
videos: Array<Video>;
|
||||||
|
selectedVideo: number;
|
||||||
|
|
||||||
|
}
|
||||||
|
class PrevArrow extends React.Component<any, any> {
|
||||||
|
public render() {
|
||||||
|
debugger;
|
||||||
|
return (<button>Next</button>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default class VideoLibrary extends React.Component<IVideoLibraryProps, IVideoLibraryState> {
|
||||||
|
constructor(props: IVideoLibraryProps) {
|
||||||
|
super(props);
|
||||||
|
this.afterChange = this.afterChange.bind(this);
|
||||||
|
this.playVideo = this.playVideo.bind(this);
|
||||||
|
this.state = {
|
||||||
|
ease: "linear",
|
||||||
|
width: 400,
|
||||||
|
playerUrlTemplate: null,
|
||||||
|
videos: [],
|
||||||
|
selectedVideo: -1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public componentWillMount(nextProps) {
|
||||||
|
// Load new data when the dataSource property changes.
|
||||||
|
this.props.o365Video.Initialize().then((settings) => {
|
||||||
|
debugger;
|
||||||
|
// this.state.playerUrlTemplate = settings.PlayerUrlTemplate; // this url does not work. You neeed the channel
|
||||||
|
this.state.playerUrlTemplate = settings.VideoPortalLayoutsUrl + "/VideoEmbedHost.aspx?chId={0}&vId={1}&width=640&height=360&autoPlay=true&showInfo=true";
|
||||||
|
if (this.props.videoChannel) {
|
||||||
|
this.props.o365Video.GetVideos(this.props.videoChannel).then((videos) => {
|
||||||
|
this.state.videos = videos;
|
||||||
|
this.setState(this.state);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
public afterChange(slideNumber: number) {
|
||||||
|
this.state.selectedVideo = -1;
|
||||||
|
this.setState(this.state);
|
||||||
|
}
|
||||||
|
public playVideo(event) {
|
||||||
|
debugger;
|
||||||
|
this.state.selectedVideo = parseInt(event.target.dataset.videonumber);
|
||||||
|
this.setState(this.state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public render(): JSX.Element {
|
||||||
|
if (this.state.videos.length === 0) {
|
||||||
|
return (<div />);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div >
|
||||||
|
<Slick arrows={true} afterChange={this.afterChange} width="80%" dots={true} >
|
||||||
|
{this.state.videos.map((v, i, a) => {
|
||||||
|
|
||||||
|
if (i === this.state.selectedVideo) {
|
||||||
|
const src = this.state.playerUrlTemplate.replace("{1}", v.ID).replace("{0}", v.ChannelID);
|
||||||
|
return (<iframe src={src} style={{ height: "540px", width: "200px" }} />);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (<img src={v.ThumbnailUrl} data-videonumber={i} style={{ height: "540px", width: "200px" }} onClick={this.playVideo} />);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</Slick>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
13
samples/react-videolibrary/src/webparts/videoLibrary/loc/en-us.js
vendored
Normal file
13
samples/react-videolibrary/src/webparts/videoLibrary/loc/en-us.js
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
define([], function () {
|
||||||
|
return {
|
||||||
|
"PropertyPaneDescription": "Description",
|
||||||
|
"BasicGroupName": "Group Name",
|
||||||
|
"DescriptionFieldLabel": "Description Field",
|
||||||
|
"VideoChannelFieldLabel": "Video Channel",
|
||||||
|
"ListNameFieldLabel": "List Name",
|
||||||
|
"LayoutFieldLabel": "Layout",
|
||||||
|
"DurationFieldLabel": "Transition Time",
|
||||||
|
"PanelsFieldLabel": "Panels",
|
||||||
|
"EaseFieldLabel": "Ease"
|
||||||
|
}
|
||||||
|
});
|
16
samples/react-videolibrary/src/webparts/videoLibrary/loc/mystrings.d.ts
vendored
Normal file
16
samples/react-videolibrary/src/webparts/videoLibrary/loc/mystrings.d.ts
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
declare interface IVideoLibraryStrings {
|
||||||
|
PropertyPaneDescription: string;
|
||||||
|
BasicGroupName: string;
|
||||||
|
DescriptionFieldLabel: string;
|
||||||
|
VideoChannelFieldLabel: string;
|
||||||
|
ListNameFieldLabel: string;
|
||||||
|
LayoutFieldLabel: string;
|
||||||
|
DurationFieldLabel: string;
|
||||||
|
PanelsFieldLabel: string;
|
||||||
|
EaseFieldLabel: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module "videoLibraryStrings" {
|
||||||
|
const strings: IVideoLibraryStrings;
|
||||||
|
export = strings;
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
/// <reference types="mocha" />
|
||||||
|
import { assert } from 'chai';
|
||||||
|
describe('VideoLibraryWebPart', () => {
|
||||||
|
it('should do something', () => {
|
||||||
|
assert.ok(true);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,19 @@
|
|||||||
|
import { O365Video } from "../O365VUtilities";
|
||||||
|
export interface IVideoLibraryCoverFlowWebPartProps {
|
||||||
|
description: string;
|
||||||
|
videoChannel: string;
|
||||||
|
o365Video: O365Video;
|
||||||
|
coverflowStartPosition: number;
|
||||||
|
coverflowMargin: number;
|
||||||
|
coverflowWidth: number;
|
||||||
|
coverflowEnableScroll: boolean;
|
||||||
|
iframeHeight: number;
|
||||||
|
iframeWidth: number;
|
||||||
|
coverflowHeight: number;
|
||||||
|
coverflowAnimationSpeed: number;
|
||||||
|
imgHeight: number;
|
||||||
|
imgWidth: number;
|
||||||
|
playerHeight: number;
|
||||||
|
playerWidth: number;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
.videoLibraryCpverFlow {
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 700px;
|
||||||
|
margin: 0px auto;
|
||||||
|
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.listItem {
|
||||||
|
max-width: 715px;
|
||||||
|
margin: 5px auto 5px auto;
|
||||||
|
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json",
|
||||||
|
"id": "aa6e9d44-a2a4-4632-842f-e015fffa14b7",
|
||||||
|
"alias": "VideoLibraryCverFlowWebPart",
|
||||||
|
"componentType": "WebPart",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"manifestVersion": 2,
|
||||||
|
"preconfiguredEntries": [
|
||||||
|
{
|
||||||
|
"groupId": "aa6e9d44-a2a4-4632-842f-e015fffa14b7",
|
||||||
|
"group": {
|
||||||
|
"default": "Under Development"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"default": "CoverFlow Video Library"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"default": "VideoLibrary implemented using reactjs-coverflow -- Shows videos from an O365 Video Channel"
|
||||||
|
},
|
||||||
|
"officeFabricIconFontName": "VisioLogo",
|
||||||
|
"properties": {
|
||||||
|
"description": "Coverflow Video Library",
|
||||||
|
"coverflowStartPosition": 0,
|
||||||
|
"coverflowMargin": 25,
|
||||||
|
"coverflowWidth": 800,
|
||||||
|
"coverflowHeight": 250,
|
||||||
|
"coverflowEnableScroll": true,
|
||||||
|
"iframeHeight": 215,
|
||||||
|
"iframeWidth": 300,
|
||||||
|
"playerHeight": 210,
|
||||||
|
"playerWidth": 295,
|
||||||
|
"coverflowAnimationSpeed": 0.8,
|
||||||
|
"imgHeight": 225,
|
||||||
|
"imgWidth": 185
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,166 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import * as ReactDom from 'react-dom';
|
||||||
|
import {
|
||||||
|
BaseClientSideWebPart,
|
||||||
|
IPropertyPaneConfiguration,
|
||||||
|
PropertyPaneTextField,
|
||||||
|
PropertyPaneDropdown, IPropertyPaneDropdownOption,
|
||||||
|
PropertyPaneSlider,
|
||||||
|
PropertyPaneToggle
|
||||||
|
} from "@microsoft/sp-webpart-base";
|
||||||
|
import { O365Video } from "../O365VUtilities";
|
||||||
|
import * as strings from 'videoLibraryCoverFlowStrings';
|
||||||
|
import VideoLibraryCoverFlow, { IVideoLibraryCoverFlowProps } from './components/VideoLibraryCoverFlow';
|
||||||
|
import { IVideoLibraryCoverFlowWebPartProps } from './IVideoLibraryCoverFlowWebPartProps';
|
||||||
|
debugger;
|
||||||
|
require('coverflow.css');
|
||||||
|
export default class VideoLibraryCpverFlowWebPart extends BaseClientSideWebPart<IVideoLibraryCoverFlowWebPartProps> {
|
||||||
|
private O365Video: O365Video;
|
||||||
|
private channels: Array<IPropertyPaneDropdownOption>;
|
||||||
|
private channelsFetched: boolean;
|
||||||
|
|
||||||
|
|
||||||
|
public onInit<T>(): Promise<T> {
|
||||||
|
|
||||||
|
this.O365Video = new O365Video(this.context);
|
||||||
|
return Promise.resolve(null);
|
||||||
|
}
|
||||||
|
public render(): void {
|
||||||
|
const props: IVideoLibraryCoverFlowWebPartProps = {
|
||||||
|
description: this.properties.description,
|
||||||
|
videoChannel: this.properties.videoChannel,
|
||||||
|
o365Video: this.O365Video,
|
||||||
|
iframeHeight: this.properties.iframeHeight,
|
||||||
|
iframeWidth: this.properties.iframeWidth,
|
||||||
|
playerHeight: this.properties.playerHeight,
|
||||||
|
playerWidth: this.properties.playerWidth,
|
||||||
|
imgHeight: this.properties.imgHeight,
|
||||||
|
imgWidth: this.properties.imgWidth,
|
||||||
|
coverflowWidth: this.properties.coverflowWidth,
|
||||||
|
coverflowHeight: this.properties.coverflowHeight,
|
||||||
|
coverflowMargin: this.properties.coverflowMargin,
|
||||||
|
coverflowAnimationSpeed: this.properties.coverflowAnimationSpeed,
|
||||||
|
coverflowStartPosition: this.properties.coverflowStartPosition,
|
||||||
|
coverflowEnableScroll: this.properties.coverflowEnableScroll,
|
||||||
|
};
|
||||||
|
const element: React.ReactElement<IVideoLibraryCoverFlowWebPartProps> = React.createElement(VideoLibraryCoverFlow, props);
|
||||||
|
|
||||||
|
ReactDom.render(element, this.domElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||||
|
|
||||||
|
debugger;
|
||||||
|
if (!this.O365Video.isInitialized) {
|
||||||
|
this.O365Video.Initialize().then(x => {
|
||||||
|
this.O365Video.getChannels().then(channels => {
|
||||||
|
this.context.propertyPane.refresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!this.channelsFetched && this.O365Video.isInitialized) {
|
||||||
|
this.O365Video.getChannels().then(channels => {
|
||||||
|
this.channels = channels.map((c, i, a) => {
|
||||||
|
const opt: IPropertyPaneDropdownOption = {
|
||||||
|
key: c.Id,
|
||||||
|
text: c.Title,
|
||||||
|
index: i,
|
||||||
|
|
||||||
|
};
|
||||||
|
return opt;
|
||||||
|
});
|
||||||
|
this.channelsFetched = true;
|
||||||
|
this.context.propertyPane.refresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
pages: [
|
||||||
|
{
|
||||||
|
header: {
|
||||||
|
description: strings.PropertyPaneDescription
|
||||||
|
},
|
||||||
|
groups: [
|
||||||
|
{
|
||||||
|
groupName: strings.BasicGroupName,
|
||||||
|
groupFields: [
|
||||||
|
PropertyPaneTextField('description', {
|
||||||
|
label: strings.DescriptionFieldLabel
|
||||||
|
}),
|
||||||
|
PropertyPaneDropdown("videoChannel", {
|
||||||
|
label: strings.VideoChannelFieldLabel,
|
||||||
|
options: this.channels,
|
||||||
|
}),
|
||||||
|
PropertyPaneSlider("coverflowHeight", {
|
||||||
|
label: strings.CoverflowHeightFieldLabel,
|
||||||
|
min: 100,
|
||||||
|
max: 1000
|
||||||
|
}),
|
||||||
|
PropertyPaneSlider("coverflowWidth", {
|
||||||
|
label: strings.CoverflowWidthFieldLabel,
|
||||||
|
min: 100,
|
||||||
|
max: 1900
|
||||||
|
}),
|
||||||
|
PropertyPaneSlider("coverflowMargin", {
|
||||||
|
label: strings.CoverflowMarginFieldLabel,
|
||||||
|
min: 0,
|
||||||
|
max: 100
|
||||||
|
}),
|
||||||
|
PropertyPaneSlider("coverflowAnimationSpeed", {
|
||||||
|
label: strings.CoverflowAnimationSpeedFieldLabel,
|
||||||
|
min: 0.0,
|
||||||
|
max: 1.0,
|
||||||
|
step: 0.1
|
||||||
|
}),
|
||||||
|
PropertyPaneToggle("coverflowEnableScroll", {
|
||||||
|
label: strings.CoverflowEnableScrollFieldLabel,
|
||||||
|
}),
|
||||||
|
|
||||||
|
PropertyPaneSlider("coverflowStartPosition", {
|
||||||
|
label: strings.CoverflowStartPositionFieldLabel,
|
||||||
|
min: 0,
|
||||||
|
max: 25
|
||||||
|
}),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PropertyPaneSlider("imgWidth", {
|
||||||
|
label: strings.ImgWidthFieldLabel,
|
||||||
|
min: 100,
|
||||||
|
max: 1900
|
||||||
|
}),
|
||||||
|
PropertyPaneSlider("imgHeight", {
|
||||||
|
label: strings.ImgHeightFieldLabel,
|
||||||
|
min: 100,
|
||||||
|
max: 1000
|
||||||
|
}),
|
||||||
|
PropertyPaneSlider("iframeWidth", {
|
||||||
|
label: strings.IframeWidthFieldLabel,
|
||||||
|
min: 100,
|
||||||
|
max: 1900
|
||||||
|
}),
|
||||||
|
PropertyPaneSlider("iframeHeight", {
|
||||||
|
label: strings.IframeHeightFieldLabel,
|
||||||
|
min: 100,
|
||||||
|
max: 1000
|
||||||
|
}),
|
||||||
|
PropertyPaneSlider("playerWidth", {
|
||||||
|
label: strings.PlayerWidthFieldLabel,
|
||||||
|
min: 100,
|
||||||
|
max: 1900
|
||||||
|
}),
|
||||||
|
PropertyPaneSlider("playerHeight", {
|
||||||
|
label: strings.PlayerHeightFieldLabel,
|
||||||
|
min: 100,
|
||||||
|
max: 1000
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,127 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import { css } from "office-ui-fabric-react";
|
||||||
|
var Coverflow = require('reactjs-coverflow');
|
||||||
|
import { IVideoLibraryCoverFlowWebPartProps } from "../IVideoLibraryCoverFlowWebPartProps";
|
||||||
|
import { Video } from "../../O365VUtilities";
|
||||||
|
export interface IVideoLibraryCoverFlowProps extends IVideoLibraryCoverFlowWebPartProps {
|
||||||
|
|
||||||
|
}
|
||||||
|
export interface IVideoLibraryState {
|
||||||
|
ease: string;
|
||||||
|
width: number;
|
||||||
|
playerUrlTemplate: string;
|
||||||
|
videos: Array<Video>;
|
||||||
|
selectedVideo: number;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class VideoLibrary extends React.Component<IVideoLibraryCoverFlowProps, IVideoLibraryState> {
|
||||||
|
|
||||||
|
constructor(props: IVideoLibraryCoverFlowProps) {
|
||||||
|
super(props);
|
||||||
|
this.afterChange = this.afterChange.bind(this);
|
||||||
|
this.playVideo = this.playVideo.bind(this);
|
||||||
|
this.next = this.next.bind(this);
|
||||||
|
this.previous = this.previous.bind(this);
|
||||||
|
this.state = {
|
||||||
|
ease: "linear",
|
||||||
|
width: 400,
|
||||||
|
playerUrlTemplate: null,
|
||||||
|
videos: [],
|
||||||
|
selectedVideo: -1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public componentWillMount(nextProps) {
|
||||||
|
// Load new data when the dataSource property changes.
|
||||||
|
this.props.o365Video.Initialize().then((settings) => {
|
||||||
|
debugger;
|
||||||
|
// this.state.playerUrlTemplate = settings.PlayerUrlTemplate; // this url does not work. You neeed the channel
|
||||||
|
this.state.playerUrlTemplate = settings.VideoPortalLayoutsUrl + "/VideoEmbedHost.aspx?chId={0}&vId={1}&width={2}&height={3}&autoPlay=true&showInfo=true";
|
||||||
|
if (this.props.videoChannel) {
|
||||||
|
this.props.o365Video.GetVideos(this.props.videoChannel).then((videos) => {
|
||||||
|
this.state.videos = videos;
|
||||||
|
this.setState(this.state);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
public componentWillReceiveProps(nextProps: IVideoLibraryCoverFlowProps) {
|
||||||
|
if (nextProps.videoChannel) {
|
||||||
|
this.props.o365Video.GetVideos(nextProps.videoChannel).then((videos) => {
|
||||||
|
this.state.videos = videos;
|
||||||
|
this.setState(this.state);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
public afterChange(slideNumber: number) {
|
||||||
|
this.state.selectedVideo = -1;
|
||||||
|
this.setState(this.state);
|
||||||
|
}
|
||||||
|
public playVideo(event) {
|
||||||
|
debugger;
|
||||||
|
this.state.selectedVideo = parseInt(event.target.dataset.videonumber);
|
||||||
|
this.setState(this.state);
|
||||||
|
}
|
||||||
|
public previous(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const cf = this.refs["coverflow"] as any;
|
||||||
|
cf.previous();
|
||||||
|
|
||||||
|
}
|
||||||
|
public next(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const cf = this.refs["coverflow"] as any;
|
||||||
|
cf.next();
|
||||||
|
}
|
||||||
|
public render(): JSX.Element {
|
||||||
|
debugger;
|
||||||
|
if (this.state.videos.length === 0) {
|
||||||
|
return (<div />);
|
||||||
|
}
|
||||||
|
// TODO: stop using the Iframe, use a <video> tah instead
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div >
|
||||||
|
<Coverflow style={{ width: this.props.coverflowWidth + "px", height: this.props.coverflowHeight + "px" }} ref="coverflow"
|
||||||
|
margin={this.props.coverflowMargin + "px"}
|
||||||
|
startPosition={this.props.coverflowStartPosition}
|
||||||
|
enableScroll={this.props.coverflowEnableScroll}
|
||||||
|
animationSpeed={this.props.coverflowAnimationSpeed}>
|
||||||
|
|
||||||
|
{this.state.videos.map((v, i, a) => {
|
||||||
|
|
||||||
|
if (i === this.state.selectedVideo) {
|
||||||
|
const src = this.state.playerUrlTemplate
|
||||||
|
.replace("{1}", v.ID)
|
||||||
|
.replace("{0}", v.ChannelID)
|
||||||
|
.replace("{2}", this.props.playerWidth.toString())
|
||||||
|
.replace("{3}", this.props.playerHeight.toString());
|
||||||
|
return (<iframe src={src} style={{ height: this.props.iframeHeight + "px", width: this.props.iframeWidth + "px" }} />);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (
|
||||||
|
<figure title={v.Title}>
|
||||||
|
<img
|
||||||
|
className="reactjs-coverflow_cover"
|
||||||
|
src={v.ThumbnailUrl}
|
||||||
|
data-videonumber={i}
|
||||||
|
style={{ height: this.props.imgHeight + "px", width: this.props.imgWidth + "px" }}
|
||||||
|
onClick={this.playVideo} />
|
||||||
|
<figcaption>
|
||||||
|
{v.Description}</figcaption>
|
||||||
|
</figure>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</Coverflow>
|
||||||
|
<div className="reactjs-coverflow_actions" data-radium="true" >
|
||||||
|
<button type="button" className="reactjs-coverflow_button" onClick={this.previous}>Previous</button>
|
||||||
|
<button type="button" className="reactjs-coverflow_button" onClick={this.next}>Next</button></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
.reactjs-coverflow_Coverflow {
|
||||||
|
position: relative;
|
||||||
|
background: rgba(0, 0, 0, 0.1);
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden; }
|
||||||
|
|
||||||
|
.coverflow__coverflow__2Wjhx {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0; }
|
||||||
|
|
||||||
|
.coverflow__stage__34J8j {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 0;
|
||||||
|
-webkit-transform-style: preserve-3d;
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
-webkit-perspective: 500px;
|
||||||
|
perspective: 500px; }
|
||||||
|
|
||||||
|
.reactjs-coverflow_Element {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
-webkit-box-flex: 0;
|
||||||
|
-ms-flex: 0 0 auto;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-transition: -webkit-transform 600ms ease;
|
||||||
|
transition: -webkit-transform 600ms ease;
|
||||||
|
transition: transform 600ms ease;
|
||||||
|
transition: transform 600ms ease, -webkit-transform 600ms ease;
|
||||||
|
-webkit-backface-visibility: hidden;
|
||||||
|
backface-visibility: hidden;
|
||||||
|
z-index: 9;
|
||||||
|
-ms-flex-item-align: center;
|
||||||
|
align-self: center;
|
||||||
|
-webkit-box-reflect: below 1px -webkit-linear-gradient(bottom, rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.1) 20%, transparent 30%, transparent); }
|
||||||
|
|
||||||
|
.reactjs-coverflow_cover {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.5); }
|
||||||
|
|
||||||
|
.coverflow__preloader__BEZga {
|
||||||
|
display: hidden; }
|
||||||
|
|
||||||
|
.coverflow__text {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: center;
|
||||||
|
font-size: .9em;
|
||||||
|
color: white;
|
||||||
|
padding: 5px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: rgba(0, 0, 0, 0.6); }
|
||||||
|
|
||||||
|
.coverflow__actions {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 30px;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center; }
|
||||||
|
.coverflow__actions .coverflow__button {
|
||||||
|
border: 1px solid #616161;
|
||||||
|
border-radius: 2px;
|
||||||
|
min-width: 120px;
|
||||||
|
padding: 5px;
|
||||||
|
margin: 2px;
|
||||||
|
background: #616161;
|
||||||
|
color: rgba(255, 255, 255, 0.9); }
|
||||||
|
.coverflow__actions__CkKK0 .coverflow__button__176dX:hover {
|
||||||
|
background: black;
|
||||||
|
color: white; }
|
||||||
|
|
||||||
|
@-webkit-keyframes coverflow__prevent__21uXf {
|
||||||
|
0% {
|
||||||
|
pointer-events: none; }
|
||||||
|
100% {
|
||||||
|
pointer-events: auto; } }
|
||||||
|
|
||||||
|
@keyframes coverflow__prevent__21uXf {
|
||||||
|
0% {
|
||||||
|
pointer-events: none; }
|
||||||
|
100% {
|
||||||
|
pointer-events: auto; } }
|
26
samples/react-videolibrary/src/webparts/videoLibraryCoverFlow/loc/en-us.js
vendored
Normal file
26
samples/react-videolibrary/src/webparts/videoLibraryCoverFlow/loc/en-us.js
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
define([], function () {
|
||||||
|
return {
|
||||||
|
"VideoChannelFieldLabel": "O365 Video Channel to play",
|
||||||
|
|
||||||
|
"PropertyPaneDescription": "Description",
|
||||||
|
"CoverflowWidthFieldLabel": "Overall control width (in px)",
|
||||||
|
"CoverflowHeightFieldLabel": "Overall control height (in px)",
|
||||||
|
"CoverflowMarginFieldLabel": "Margin between slides (in px)",
|
||||||
|
"CoverflowAnimationSpeedFieldLabel": "Animation Speed when scrolling",
|
||||||
|
"CoverflowEnableScrollFieldLabel": "Enable mousewheel Scrolling",
|
||||||
|
"CoverflowStartPositionFieldLabel": "Starting frame ",
|
||||||
|
|
||||||
|
"BasicGroupName": "Group Name",
|
||||||
|
"DescriptionFieldLabel": "Description Field",
|
||||||
|
|
||||||
|
|
||||||
|
"ImgWidthFieldLabel": "Static Image Width",
|
||||||
|
"ImgHeightFieldLabel": "Static Image Height",
|
||||||
|
"IframeWidthFieldLabel": "IFrame Width",
|
||||||
|
"IframeHeightFieldLabel": "IFrame Height",
|
||||||
|
"PlayerWidthFieldLabel": "Video Player Width",
|
||||||
|
"PlayerHeightFieldLabel": "Video Player Height",
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
23
samples/react-videolibrary/src/webparts/videoLibraryCoverFlow/loc/mystrings.d.ts
vendored
Normal file
23
samples/react-videolibrary/src/webparts/videoLibraryCoverFlow/loc/mystrings.d.ts
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
declare interface IVideoLibraryCoverFlowStrings {
|
||||||
|
PropertyPaneDescription: string;
|
||||||
|
BasicGroupName: string;
|
||||||
|
DescriptionFieldLabel: string;
|
||||||
|
VideoChannelFieldLabel: string;
|
||||||
|
CoverflowWidthFieldLabel: string;
|
||||||
|
CoverflowHeightFieldLabel: string;
|
||||||
|
ImgWidthFieldLabel: string;
|
||||||
|
ImgHeightFieldLabel: string;
|
||||||
|
IframeWidthFieldLabel: string;
|
||||||
|
IframeHeightFieldLabel: string;
|
||||||
|
PlayerWidthFieldLabel: string;
|
||||||
|
PlayerHeightFieldLabel: string;
|
||||||
|
CoverflowMarginFieldLabel: string;
|
||||||
|
CoverflowAnimationSpeedFieldLabel: string;
|
||||||
|
CoverflowStartPositionFieldLabel: string;
|
||||||
|
CoverflowEnableScrollFieldLabel: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'videoLibraryCoverFlowStrings' {
|
||||||
|
const strings: IVideoLibraryCoverFlowStrings;
|
||||||
|
export = strings;
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
/// <reference types="mocha" />
|
||||||
|
import { assert } from 'chai';
|
||||||
|
describe('VideoLibraryCpverFlowWebPart', () => {
|
||||||
|
it('should do something', () => {
|
||||||
|
assert.ok(true);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,9 @@
|
|||||||
|
import {O365Video } from "../O365VUtilities";
|
||||||
|
export interface IVideoLibraryReact3DCarouselWebPartProps {
|
||||||
|
description: string;
|
||||||
|
videoChannel: string;
|
||||||
|
o365Video: O365Video;
|
||||||
|
layout: string;
|
||||||
|
duration: number;
|
||||||
|
panels: number;
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
.videoLibrary {
|
||||||
|
.container {
|
||||||
|
max-width: 700px;
|
||||||
|
margin: 0px auto;
|
||||||
|
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.react-3d-carousel {
|
||||||
|
width: 400px;
|
||||||
|
height: 300px;
|
||||||
|
position: relative;
|
||||||
|
perspective: 1000px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-3d-carousel .carousel {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-3d-carousel .carousel figure {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 400px;
|
||||||
|
height: 300px;
|
||||||
|
left: 10px;
|
||||||
|
top: 10px;
|
||||||
|
border: 2px solid black;
|
||||||
|
line-height: 116px;
|
||||||
|
font-size: 80px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-3d-carousel .carousel figure {
|
||||||
|
background: hsla( 160, 100%, 50%, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.listItem {
|
||||||
|
max-width: 715px;
|
||||||
|
margin: 5px auto 5px auto;
|
||||||
|
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json",
|
||||||
|
|
||||||
|
"id": "2f1538d9-3b9a-4033-8f3b-2cdf2ec3c64e",
|
||||||
|
"alias": "VideoLibraryReact3DCarouselWebPart",
|
||||||
|
"componentType": "WebPart",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"manifestVersion": 2,
|
||||||
|
|
||||||
|
"preconfiguredEntries": [{
|
||||||
|
"groupId": "2f1538d9-3b9a-4033-8f3b-2cdf2ec3c64e",
|
||||||
|
"group": { "default": "Under Development" },
|
||||||
|
"title": { "default": "React-3d-carousel Video Library" },
|
||||||
|
"description": {
|
||||||
|
"default": "VideoLibrary implemented using react-3d-carousel -- Shows videos from an O365 Video Channel"
|
||||||
|
},
|
||||||
|
"officeFabricIconFontName": "Ribbon",
|
||||||
|
"properties": {
|
||||||
|
"description": "React-3d-carousel Video Library",
|
||||||
|
"layout":"prism",
|
||||||
|
"duration":199
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import * as ReactDom from 'react-dom';
|
||||||
|
import {
|
||||||
|
BaseClientSideWebPart,
|
||||||
|
IPropertyPaneConfiguration ,
|
||||||
|
|
||||||
|
PropertyPaneTextField,
|
||||||
|
PropertyPaneDropdown, IPropertyPaneDropdownOption,
|
||||||
|
PropertyPaneSlider
|
||||||
|
} from '@microsoft/sp-webpart-base';
|
||||||
|
import { O365Video } from "../O365VUtilities";
|
||||||
|
import * as strings from 'videoLibraryStrings';
|
||||||
|
import VideoLibrary, { IVideoLibraryProps } from './components/VideoLibraryReact3DCarousel';
|
||||||
|
import { IVideoLibraryReact3DCarouselWebPartProps } from './IVideoLibraryReact3DCarouselWebPartProps';
|
||||||
|
require("./carousel.css"); // needed to copy this to lib folder to get it displayed
|
||||||
|
export default class VideoLibraryWebPart extends BaseClientSideWebPart<IVideoLibraryReact3DCarouselWebPartProps> {
|
||||||
|
private O365Video: O365Video;
|
||||||
|
private channels: Array<IPropertyPaneDropdownOption>;
|
||||||
|
private channelsFetched: boolean;
|
||||||
|
|
||||||
|
public onInit<T>(): Promise<T> {
|
||||||
|
this.O365Video = new O365Video(this.context);
|
||||||
|
return Promise.resolve(null);
|
||||||
|
}
|
||||||
|
public render(): void {
|
||||||
|
|
||||||
|
const props: IVideoLibraryProps = {
|
||||||
|
description: this.properties.description,
|
||||||
|
videoChannel: this.properties.videoChannel,
|
||||||
|
o365Video: this.O365Video,
|
||||||
|
layout: this.properties.layout,
|
||||||
|
duration:this.properties.duration,
|
||||||
|
panels:this.properties.panels
|
||||||
|
};
|
||||||
|
const element: React.ReactElement<IVideoLibraryProps> = React.createElement(VideoLibrary, props);
|
||||||
|
|
||||||
|
ReactDom.render(element, this.domElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||||
|
debugger;
|
||||||
|
if (!this.O365Video.isInitialized) {
|
||||||
|
this.O365Video.Initialize().then(x => {
|
||||||
|
this.O365Video.getChannels().then(channels => {
|
||||||
|
this.context.propertyPane.refresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!this.channelsFetched && this.O365Video.isInitialized) {
|
||||||
|
this.O365Video.getChannels().then(channels => {
|
||||||
|
this.channels = channels.map((c, i, a) => {
|
||||||
|
let opt: IPropertyPaneDropdownOption = {
|
||||||
|
key: c.Id,
|
||||||
|
text: c.Title,
|
||||||
|
index: i,
|
||||||
|
|
||||||
|
};
|
||||||
|
return opt;
|
||||||
|
});
|
||||||
|
this.channelsFetched = true;
|
||||||
|
this.context.propertyPane.refresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
pages: [
|
||||||
|
{
|
||||||
|
header: {
|
||||||
|
description: strings.PropertyPaneDescription
|
||||||
|
},
|
||||||
|
groups: [
|
||||||
|
{
|
||||||
|
groupName: strings.BasicGroupName,
|
||||||
|
groupFields: [
|
||||||
|
PropertyPaneTextField("description", {
|
||||||
|
label: strings.DescriptionFieldLabel
|
||||||
|
}),
|
||||||
|
PropertyPaneDropdown("videoChannel", {
|
||||||
|
label: strings.VideoChannelFieldLabel,
|
||||||
|
options: this.channels,
|
||||||
|
|
||||||
|
}),
|
||||||
|
PropertyPaneDropdown("layout", {
|
||||||
|
label: strings.LayoutFieldLabel,
|
||||||
|
options: [
|
||||||
|
{ key: "prism", text: "prism" },
|
||||||
|
{ key: "clssic", text: "classic" }
|
||||||
|
]
|
||||||
|
|
||||||
|
}),
|
||||||
|
PropertyPaneSlider("duration", {
|
||||||
|
label: strings.DurationFieldLabel,
|
||||||
|
min: 1,
|
||||||
|
max: 1000
|
||||||
|
}),
|
||||||
|
PropertyPaneSlider("panels", {
|
||||||
|
label: strings.PanelsFieldLabel,
|
||||||
|
min: 1,
|
||||||
|
max: 5
|
||||||
|
}),
|
||||||
|
|
||||||
|
// PropertyPaneTextField("listName", channelDropDownProps),
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
|
||||||
|
.react-3d-carousel {
|
||||||
|
width: 400px;
|
||||||
|
height: 300px;
|
||||||
|
position: relative;
|
||||||
|
perspective: 1000px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-3d-carousel .carousel {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-3d-carousel .carousel figure {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 400px;
|
||||||
|
height: 300px;
|
||||||
|
left: 10px;
|
||||||
|
top: 10px;
|
||||||
|
border: 2px solid black;
|
||||||
|
line-height: 116px;
|
||||||
|
font-size: 80px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-3d-carousel .carousel figure {
|
||||||
|
background: hsla( 160, 100%, 50%, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-3d-carousel .prev {
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 15%;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-3d-carousel .prev:before {
|
||||||
|
content: url("http://s3.postimg.org/o6xpvkidb/chevron_left_white.png");
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 43px;
|
||||||
|
height: 49px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.react-3d-carousel .next {
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 15%;
|
||||||
|
top: 0px;
|
||||||
|
right: -5px;
|
||||||
|
}
|
||||||
|
.react-3d-carousel .next:before
|
||||||
|
{
|
||||||
|
content: url("http://s2.postimg.org/l0n6eaoad/chevron_right_white.png");
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 43px;
|
||||||
|
height: 49px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
@ -0,0 +1,92 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { css } from 'office-ui-fabric-react';
|
||||||
|
var Carousel = require('react-3d-carousel');
|
||||||
|
var Ease = require('ease-functions');
|
||||||
|
import styles from '../VideoLibraryReact3DCarousel.module.scss';
|
||||||
|
import { IVideoLibraryReact3DCarouselWebPartProps } from '../IVideoLibraryReact3DCarouselWebPartProps';
|
||||||
|
import { Video, } from "../../O365VUtilities";
|
||||||
|
export interface IVideoLibraryProps extends IVideoLibraryReact3DCarouselWebPartProps {
|
||||||
|
|
||||||
|
}
|
||||||
|
export interface IVideoLibraryState {
|
||||||
|
images: Array<string>;
|
||||||
|
|
||||||
|
ease: string;
|
||||||
|
width: number;
|
||||||
|
|
||||||
|
videos: Array<Video>;
|
||||||
|
|
||||||
|
}
|
||||||
|
export default class VideoLibrary extends React.Component<IVideoLibraryProps, IVideoLibraryState> {
|
||||||
|
constructor(props: IVideoLibraryProps) {
|
||||||
|
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.onEase = this.onEase.bind(this);
|
||||||
|
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
ease: "linear",
|
||||||
|
width: 400,
|
||||||
|
|
||||||
|
images: [],
|
||||||
|
videos: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
public componentWillMount(nextProps) {
|
||||||
|
// Load new data when the dataSource property changes.
|
||||||
|
this.props.o365Video.Initialize().then((settings) => {
|
||||||
|
if (this.props.videoChannel) {
|
||||||
|
this.props.o365Video.GetVideos(this.props.videoChannel).then((videos) => {
|
||||||
|
this.state.videos = videos;
|
||||||
|
this.state.images = videos.map((v, i, a) => {
|
||||||
|
|
||||||
|
return v.ThumbnailUrl;
|
||||||
|
});
|
||||||
|
this.setState(this.state);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public onEase(event) {
|
||||||
|
this.state.ease = event.target.value;
|
||||||
|
this.setState(this.state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public render(): JSX.Element {
|
||||||
|
const easeList = Object.keys(Ease).map(function (d) {
|
||||||
|
return (<option key={d} value={d}>{d}</option>);
|
||||||
|
});
|
||||||
|
if (this.state.images.length === 0) {
|
||||||
|
return (<div />);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className={styles.videoLibrary}>
|
||||||
|
<div className={styles.container} id="content">
|
||||||
|
<Carousel width={this.state.width}
|
||||||
|
panels={this.props.panels}
|
||||||
|
images={this.state.images}
|
||||||
|
ease={this.state.ease}
|
||||||
|
duration={this.props.duration}
|
||||||
|
layout={this.props.layout} />
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Ease
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select onChange={this.onEase} value={this.state.ease}>
|
||||||
|
{easeList}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
13
samples/react-videolibrary/src/webparts/videoLibraryReact3DCarousel/loc/en-us.js
vendored
Normal file
13
samples/react-videolibrary/src/webparts/videoLibraryReact3DCarousel/loc/en-us.js
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
define([], function () {
|
||||||
|
return {
|
||||||
|
"PropertyPaneDescription": "Description",
|
||||||
|
"BasicGroupName": "Group Name",
|
||||||
|
"DescriptionFieldLabel": "Description Field",
|
||||||
|
"VideoChannelFieldLabel": "Video Channel",
|
||||||
|
"ListNameFieldLabel": "List Name",
|
||||||
|
"LayoutFieldLabel": "Layout",
|
||||||
|
"DurationFieldLabel": "Transition Time",
|
||||||
|
"PanelsFieldLabel": "Panels",
|
||||||
|
"EaseFieldLabel": "Ease"
|
||||||
|
}
|
||||||
|
});
|
17
samples/react-videolibrary/src/webparts/videoLibraryReact3DCarousel/loc/mystrings.d.ts
vendored
Normal file
17
samples/react-videolibrary/src/webparts/videoLibraryReact3DCarousel/loc/mystrings.d.ts
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
declare interface IVideoLibraryReact3DCarouselStrings {
|
||||||
|
PropertyPaneDescription: string;
|
||||||
|
BasicGroupName: string;
|
||||||
|
DescriptionFieldLabel: string;
|
||||||
|
VideoChannelFieldLabel: string;
|
||||||
|
ListNameFieldLabel: string;
|
||||||
|
LayoutFieldLabel: string;
|
||||||
|
DurationFieldLabel: string;
|
||||||
|
PanelsFieldLabel: string;
|
||||||
|
EaseFieldLabel: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module "videoLibraryReact3DCarouselStrings" {
|
||||||
|
const strings: IVideoLibraryStrings;
|
||||||
|
export = strings;
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
/// <reference types="mocha" />
|
||||||
|
import { assert } from 'chai';
|
||||||
|
|
||||||
|
describe('VideoLibraryReact3DCarouselWebPart', () => {
|
||||||
|
it('should do something', () => {
|
||||||
|
assert.ok(true);
|
||||||
|
});
|
||||||
|
});
|
10
samples/react-videolibrary/tsconfig.json
Normal file
10
samples/react-videolibrary/tsconfig.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"module": "commonjs",
|
||||||
|
"jsx": "react",
|
||||||
|
"declaration": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"types": [ "webpack-env" ]
|
||||||
|
}
|
||||||
|
}
|
5
samples/react-videolibrary/typings.json
Normal file
5
samples/react-videolibrary/typings.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"globalDependencies": {
|
||||||
|
"react-slick": "registry:dt/react-slick#0.0.0+20161121205806"
|
||||||
|
}
|
||||||
|
}
|
13
samples/react-videolibrary/typings/@ms/odsp-webpack.d.ts
vendored
Normal file
13
samples/react-videolibrary/typings/@ms/odsp-webpack.d.ts
vendored
Normal file
@ -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;
|
||||||
|
};
|
10
samples/react-videolibrary/typings/@ms/odsp.d.ts
vendored
Normal file
10
samples/react-videolibrary/typings/@ms/odsp.d.ts
vendored
Normal file
@ -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;
|
15
samples/react-videolibrary/typings/assertion-error/assertion-error.d.ts
vendored
Normal file
15
samples/react-videolibrary/typings/assertion-error/assertion-error.d.ts
vendored
Normal file
@ -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;
|
||||||
|
}
|
631
samples/react-videolibrary/typings/knockout/knockout.d.ts
vendored
Normal file
631
samples/react-videolibrary/typings/knockout/knockout.d.ts
vendored
Normal file
@ -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;
|
||||||
|
}
|
5
samples/react-videolibrary/typings/tsd.d.ts
vendored
Normal file
5
samples/react-videolibrary/typings/tsd.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/// <reference path="@ms/odsp.d.ts" />
|
||||||
|
/// <reference path="@ms/odsp-webpack.d.ts" />
|
||||||
|
/// <reference path="assertion-error/assertion-error.d.ts" />
|
||||||
|
/// <reference path="knockout/knockout.d.ts" />
|
||||||
|
|
86
samples/react-videolibrary/videotst.njsproj
Normal file
86
samples/react-videolibrary/videotst.njsproj
Normal file
@ -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>{841958c7-1d50-408b-9df4-feac7165d4a0}</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>
|
Loading…
x
Reference in New Issue
Block a user