mirror of
https://github.com/pnp/sp-dev-fx-webparts.git
synced 2025-02-22 13:12:30 +00:00
Dev (#86)
* add samples/react-spfx-multilist-grid/ * images * images * Update README.md * images
This commit is contained in:
parent
7c44cf7f93
commit
692de70857
25
samples/react-spfx-multilist-grid/.editorconfig
Normal file
25
samples/react-spfx-multilist-grid/.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-spfx-multilist-grid/.gitattributes
vendored
Normal file
1
samples/react-spfx-multilist-grid/.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
* text=auto
|
32
samples/react-spfx-multilist-grid/.gitignore
vendored
Normal file
32
samples/react-spfx-multilist-grid/.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-spfx-multilist-grid/.npmignore
Normal file
14
samples/react-spfx-multilist-grid/.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
|
22
samples/react-spfx-multilist-grid/.vscode/settings.json
vendored
Normal file
22
samples/react-spfx-multilist-grid/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
// The number of spaces a tab is equal to.
|
||||
"editor.tabSize": 2,
|
||||
|
||||
// When enabled, will trim trailing whitespace when you save a file.
|
||||
"files.trimTrailingWhitespace": true,
|
||||
|
||||
// Controls if the editor should automatically close brackets after opening them
|
||||
"editor.autoClosingBrackets": false,
|
||||
// Configure glob patterns for excluding files and folders.
|
||||
"search.exclude": {
|
||||
"**/bower_components": true,
|
||||
"**/node_modules": true,
|
||||
"coverage": true,
|
||||
"dist": true,
|
||||
"lib-amd": true,
|
||||
"lib": true,
|
||||
"temp": true
|
||||
}
|
||||
,
|
||||
"typescript.tsdk": "./node_modules/typescript/lib"
|
||||
}
|
34
samples/react-spfx-multilist-grid/.vscode/tasks.json
vendored
Normal file
34
samples/react-spfx-multilist-grid/.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "0.1.0",
|
||||
"command": "gulp",
|
||||
"isShellCommand": true,
|
||||
"showOutput": "always",
|
||||
"args": [
|
||||
"--no-color"
|
||||
],
|
||||
"tasks": [
|
||||
{
|
||||
"taskName": "bundle",
|
||||
"isBuildCommand": true,
|
||||
"problemMatcher": [
|
||||
"$tsc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"taskName": "test",
|
||||
"isTestCommand": true,
|
||||
"problemMatcher": [
|
||||
"$tsc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"taskName": "serve",
|
||||
"isWatching": true,
|
||||
"problemMatcher": [
|
||||
"$tsc"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
7
samples/react-spfx-multilist-grid/.yo-rc.json
Normal file
7
samples/react-spfx-multilist-grid/.yo-rc.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"libraryName": "spfxreactgrid",
|
||||
"libraryId": "28bf799f-01fc-45e9-8997-f7982eaf8b53",
|
||||
"framework": "react"
|
||||
}
|
||||
}
|
66
samples/react-spfx-multilist-grid/README.md
Normal file
66
samples/react-spfx-multilist-grid/README.md
Normal file
@ -0,0 +1,66 @@
|
||||
# SPFX React Grid
|
||||
|
||||
## Summary
|
||||
An SPFX Webpart that uses React, Office-UI-Fabric, and Redux to let users edit list data from multiple Webs and Multiple Sites in a single grid.
|
||||
|
||||

|
||||
|
||||
|
||||
## 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, Redux Office-UI-Fabric
|
||||
|
||||
## Solution
|
||||
|
||||
Solution|Author(s)
|
||||
--------|---------
|
||||
react-spfx-multilist-grid | 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
|
||||
An SPFX Webpart that uses React, Office-UI-Fabric, and Redux to let users edit list data from multiple Webs and Multiple Sites in a single grid.
|
||||
|
||||
Usage:
|
||||
|
||||
1. Define the columns to be shown in the grid
|
||||

|
||||
|
||||
2. Define the lists to be edited
|
||||

|
||||
|
||||
3. Edit the info
|
||||

|
||||
|
||||
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/readme-template" />
|
||||
|
||||
|
||||
|
||||
|
BIN
samples/react-spfx-multilist-grid/UpgradeLog.htm
Normal file
BIN
samples/react-spfx-multilist-grid/UpgradeLog.htm
Normal file
Binary file not shown.
116
samples/react-spfx-multilist-grid/chalk/index.js
vendored
Normal file
116
samples/react-spfx-multilist-grid/chalk/index.js
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
'use strict';
|
||||
var escapeStringRegexp = require('escape-string-regexp');
|
||||
var ansiStyles = require('ansi-styles');
|
||||
var stripAnsi = require('strip-ansi');
|
||||
var hasAnsi = require('has-ansi');
|
||||
var supportsColor = require('supports-color');
|
||||
var defineProps = Object.defineProperties;
|
||||
var isSimpleWindowsTerm = process.platform === 'win32' && !/^xterm/i.test(process.env.TERM);
|
||||
|
||||
function Chalk(options) {
|
||||
// detect mode if not set manually
|
||||
this.enabled = !options || options.enabled === undefined ? supportsColor : options.enabled;
|
||||
}
|
||||
|
||||
// use bright blue on Windows as the normal blue color is illegible
|
||||
if (isSimpleWindowsTerm) {
|
||||
ansiStyles.blue.open = '\u001b[94m';
|
||||
}
|
||||
|
||||
var styles = (function () {
|
||||
var ret = {};
|
||||
|
||||
Object.keys(ansiStyles).forEach(function (key) {
|
||||
ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g');
|
||||
|
||||
ret[key] = {
|
||||
get: function () {
|
||||
return build.call(this, this._styles.concat(key));
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return ret;
|
||||
})();
|
||||
|
||||
var proto = defineProps(function chalk() {}, styles);
|
||||
|
||||
function build(_styles) {
|
||||
var builder = function () {
|
||||
return applyStyle.apply(builder, arguments);
|
||||
};
|
||||
|
||||
builder._styles = _styles;
|
||||
builder.enabled = this.enabled;
|
||||
// __proto__ is used because we must return a function, but there is
|
||||
// no way to create a function with a different prototype.
|
||||
/* eslint-disable no-proto */
|
||||
builder.__proto__ = proto;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
function applyStyle() {
|
||||
// support varags, but simply cast to string in case there's only one arg
|
||||
var args = arguments;
|
||||
var argsLen = args.length;
|
||||
var str = argsLen !== 0 && String(arguments[0]);
|
||||
|
||||
if (argsLen > 1) {
|
||||
// don't slice `arguments`, it prevents v8 optimizations
|
||||
for (var a = 1; a < argsLen; a++) {
|
||||
str += ' ' + args[a];
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.enabled || !str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
var nestedStyles = this._styles;
|
||||
var i = nestedStyles.length;
|
||||
|
||||
// Turns out that on Windows dimmed gray text becomes invisible in cmd.exe,
|
||||
// see https://github.com/chalk/chalk/issues/58
|
||||
// If we're on Windows and we're dealing with a gray color, temporarily make 'dim' a noop.
|
||||
var originalDim = ansiStyles.dim.open;
|
||||
if (isSimpleWindowsTerm && (nestedStyles.indexOf('gray') !== -1 || nestedStyles.indexOf('grey') !== -1)) {
|
||||
ansiStyles.dim.open = '';
|
||||
}
|
||||
|
||||
while (i--) {
|
||||
var code = ansiStyles[nestedStyles[i]];
|
||||
|
||||
// Replace any instances already present with a re-opening code
|
||||
// otherwise only the part of the string until said closing code
|
||||
// will be colored, and the rest will simply be 'plain'.
|
||||
str = code.open + str.replace(code.closeRe, code.open) + code.close;
|
||||
}
|
||||
|
||||
// Reset the original 'dim' if we changed it to work around the Windows dimmed gray issue.
|
||||
ansiStyles.dim.open = originalDim;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function init() {
|
||||
var ret = {};
|
||||
|
||||
Object.keys(styles).forEach(function (name) {
|
||||
ret[name] = {
|
||||
get: function () {
|
||||
return build.call(this, [name]);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
defineProps(Chalk.prototype, init());
|
||||
|
||||
module.exports = new Chalk();
|
||||
module.exports.styles = ansiStyles;
|
||||
module.exports.hasColor = hasAnsi;
|
||||
module.exports.stripColor = stripAnsi;
|
||||
module.exports.supportsColor = supportsColor;
|
21
samples/react-spfx-multilist-grid/chalk/license
Normal file
21
samples/react-spfx-multilist-grid/chalk/license
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
149
samples/react-spfx-multilist-grid/chalk/package.json
Normal file
149
samples/react-spfx-multilist-grid/chalk/package.json
Normal file
@ -0,0 +1,149 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
{
|
||||
"name": "chalk",
|
||||
"raw": "chalk@^1.1.1",
|
||||
"rawSpec": "^1.1.1",
|
||||
"scope": null,
|
||||
"spec": ">=1.1.1 <2.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"C:\\Users\\trwg1\\Documents\\GitHub\\spfxreactgrid\\node_modules\\har-validator"
|
||||
]
|
||||
],
|
||||
"_from": "chalk@>=1.1.1 <2.0.0",
|
||||
"_id": "chalk@1.1.3",
|
||||
"_inCache": true,
|
||||
"_installable": true,
|
||||
"_location": "/chalk",
|
||||
"_nodeVersion": "0.10.32",
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-12-west.internal.npmjs.com",
|
||||
"tmp": "tmp/chalk-1.1.3.tgz_1459210604109_0.3892582862172276"
|
||||
},
|
||||
"_npmUser": {
|
||||
"email": "i.am.qix@gmail.com",
|
||||
"name": "qix"
|
||||
},
|
||||
"_npmVersion": "2.14.2",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"name": "chalk",
|
||||
"raw": "chalk@^1.1.1",
|
||||
"rawSpec": "^1.1.1",
|
||||
"scope": null,
|
||||
"spec": ">=1.1.1 <2.0.0",
|
||||
"type": "range"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/babel-code-frame",
|
||||
"/clap",
|
||||
"/fancy-log",
|
||||
"/gulp",
|
||||
"/gulp-util",
|
||||
"/har-validator",
|
||||
"/karma-mocha-clean-reporter",
|
||||
"/log-symbols",
|
||||
"/marked-terminal",
|
||||
"/node-sass",
|
||||
"/postcss"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"_shasum": "a8115c55e4a702fe4d150abd3872822a7e09fc98",
|
||||
"_shrinkwrap": null,
|
||||
"_spec": "chalk@^1.1.1",
|
||||
"_where": "C:\\Users\\trwg1\\Documents\\GitHub\\spfxreactgrid\\node_modules\\har-validator",
|
||||
"bugs": {
|
||||
"url": "https://github.com/chalk/chalk/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": "^2.2.1",
|
||||
"escape-string-regexp": "^1.0.2",
|
||||
"has-ansi": "^2.0.0",
|
||||
"strip-ansi": "^3.0.0",
|
||||
"supports-color": "^2.0.0"
|
||||
},
|
||||
"description": "Terminal string styling done right. Much color.",
|
||||
"devDependencies": {
|
||||
"coveralls": "^2.11.2",
|
||||
"matcha": "^0.6.0",
|
||||
"mocha": "*",
|
||||
"nyc": "^3.0.0",
|
||||
"require-uncached": "^1.0.2",
|
||||
"resolve-from": "^1.0.0",
|
||||
"semver": "^4.3.3",
|
||||
"xo": "*"
|
||||
},
|
||||
"directories": {},
|
||||
"dist": {
|
||||
"shasum": "a8115c55e4a702fe4d150abd3872822a7e09fc98",
|
||||
"tarball": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"gitHead": "0d8d8c204eb87a4038219131ad4d8369c9f59d24",
|
||||
"homepage": "https://github.com/chalk/chalk#readme",
|
||||
"keywords": [
|
||||
"color",
|
||||
"colour",
|
||||
"colors",
|
||||
"terminal",
|
||||
"console",
|
||||
"cli",
|
||||
"string",
|
||||
"str",
|
||||
"ansi",
|
||||
"style",
|
||||
"styles",
|
||||
"tty",
|
||||
"formatting",
|
||||
"rgb",
|
||||
"256",
|
||||
"shell",
|
||||
"xterm",
|
||||
"log",
|
||||
"logging",
|
||||
"command-line",
|
||||
"text"
|
||||
],
|
||||
"license": "MIT",
|
||||
"maintainers": [
|
||||
{
|
||||
"email": "i.am.qix@gmail.com",
|
||||
"name": "qix"
|
||||
},
|
||||
{
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"name": "sindresorhus"
|
||||
},
|
||||
{
|
||||
"email": "sindresorhus+unicorn@gmail.com",
|
||||
"name": "unicorn"
|
||||
}
|
||||
],
|
||||
"name": "chalk",
|
||||
"optionalDependencies": {},
|
||||
"readme": "ERROR: No README data found!",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/chalk/chalk.git"
|
||||
},
|
||||
"scripts": {
|
||||
"bench": "matcha benchmark.js",
|
||||
"coverage": "nyc npm test && nyc report",
|
||||
"coveralls": "nyc npm test && nyc report --reporter=text-lcov | coveralls",
|
||||
"test": "xo && mocha"
|
||||
},
|
||||
"version": "1.1.3",
|
||||
"xo": {
|
||||
"envs": [
|
||||
"node",
|
||||
"mocha"
|
||||
]
|
||||
}
|
||||
}
|
213
samples/react-spfx-multilist-grid/chalk/readme.md
Normal file
213
samples/react-spfx-multilist-grid/chalk/readme.md
Normal file
@ -0,0 +1,213 @@
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<br>
|
||||
<img width="360" src="https://cdn.rawgit.com/chalk/chalk/19935d6484811c5e468817f846b7b3d417d7bf4a/logo.svg" alt="chalk">
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
</h1>
|
||||
|
||||
> Terminal string styling done right
|
||||
|
||||
[](https://travis-ci.org/chalk/chalk)
|
||||
[](https://coveralls.io/r/chalk/chalk?branch=master)
|
||||
[](https://www.youtube.com/watch?v=9auOCbH5Ns4)
|
||||
|
||||
|
||||
[colors.js](https://github.com/Marak/colors.js) used to be the most popular string styling module, but it has serious deficiencies like extending `String.prototype` which causes all kinds of [problems](https://github.com/yeoman/yo/issues/68). Although there are other ones, they either do too much or not enough.
|
||||
|
||||
**Chalk is a clean and focused alternative.**
|
||||
|
||||

|
||||
|
||||
|
||||
## Why
|
||||
|
||||
- Highly performant
|
||||
- Doesn't extend `String.prototype`
|
||||
- Expressive API
|
||||
- Ability to nest styles
|
||||
- Clean and focused
|
||||
- Auto-detects color support
|
||||
- Actively maintained
|
||||
- [Used by ~4500 modules](https://www.npmjs.com/browse/depended/chalk) as of July 15, 2015
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install --save chalk
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Chalk comes with an easy to use composable API where you just chain and nest the styles you want.
|
||||
|
||||
```js
|
||||
var chalk = require('chalk');
|
||||
|
||||
// style a string
|
||||
chalk.blue('Hello world!');
|
||||
|
||||
// combine styled and normal strings
|
||||
chalk.blue('Hello') + 'World' + chalk.red('!');
|
||||
|
||||
// compose multiple styles using the chainable API
|
||||
chalk.blue.bgRed.bold('Hello world!');
|
||||
|
||||
// pass in multiple arguments
|
||||
chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz');
|
||||
|
||||
// nest styles
|
||||
chalk.red('Hello', chalk.underline.bgBlue('world') + '!');
|
||||
|
||||
// nest styles of the same type even (color, underline, background)
|
||||
chalk.green(
|
||||
'I am a green line ' +
|
||||
chalk.blue.underline.bold('with a blue substring') +
|
||||
' that becomes green again!'
|
||||
);
|
||||
```
|
||||
|
||||
Easily define your own themes.
|
||||
|
||||
```js
|
||||
var chalk = require('chalk');
|
||||
var error = chalk.bold.red;
|
||||
console.log(error('Error!'));
|
||||
```
|
||||
|
||||
Take advantage of console.log [string substitution](http://nodejs.org/docs/latest/api/console.html#console_console_log_data).
|
||||
|
||||
```js
|
||||
var name = 'Sindre';
|
||||
console.log(chalk.green('Hello %s'), name);
|
||||
//=> Hello Sindre
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### chalk.`<style>[.<style>...](string, [string...])`
|
||||
|
||||
Example: `chalk.red.bold.underline('Hello', 'world');`
|
||||
|
||||
Chain [styles](#styles) and call the last one as a method with a string argument. Order doesn't matter, and later styles take precedent in case of a conflict. This simply means that `Chalk.red.yellow.green` is equivalent to `Chalk.green`.
|
||||
|
||||
Multiple arguments will be separated by space.
|
||||
|
||||
### chalk.enabled
|
||||
|
||||
Color support is automatically detected, but you can override it by setting the `enabled` property. You should however only do this in your own code as it applies globally to all chalk consumers.
|
||||
|
||||
If you need to change this in a reusable module create a new instance:
|
||||
|
||||
```js
|
||||
var ctx = new chalk.constructor({enabled: false});
|
||||
```
|
||||
|
||||
### chalk.supportsColor
|
||||
|
||||
Detect whether the terminal [supports color](https://github.com/chalk/supports-color). Used internally and handled for you, but exposed for convenience.
|
||||
|
||||
Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, add an environment variable `FORCE_COLOR` with any value to force color. Trumps `--no-color`.
|
||||
|
||||
### chalk.styles
|
||||
|
||||
Exposes the styles as [ANSI escape codes](https://github.com/chalk/ansi-styles).
|
||||
|
||||
Generally not useful, but you might need just the `.open` or `.close` escape code if you're mixing externally styled strings with your own.
|
||||
|
||||
```js
|
||||
var chalk = require('chalk');
|
||||
|
||||
console.log(chalk.styles.red);
|
||||
//=> {open: '\u001b[31m', close: '\u001b[39m'}
|
||||
|
||||
console.log(chalk.styles.red.open + 'Hello' + chalk.styles.red.close);
|
||||
```
|
||||
|
||||
### chalk.hasColor(string)
|
||||
|
||||
Check whether a string [has color](https://github.com/chalk/has-ansi).
|
||||
|
||||
### chalk.stripColor(string)
|
||||
|
||||
[Strip color](https://github.com/chalk/strip-ansi) from a string.
|
||||
|
||||
Can be useful in combination with `.supportsColor` to strip color on externally styled text when it's not supported.
|
||||
|
||||
Example:
|
||||
|
||||
```js
|
||||
var chalk = require('chalk');
|
||||
var styledString = getText();
|
||||
|
||||
if (!chalk.supportsColor) {
|
||||
styledString = chalk.stripColor(styledString);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Styles
|
||||
|
||||
### Modifiers
|
||||
|
||||
- `reset`
|
||||
- `bold`
|
||||
- `dim`
|
||||
- `italic` *(not widely supported)*
|
||||
- `underline`
|
||||
- `inverse`
|
||||
- `hidden`
|
||||
- `strikethrough` *(not widely supported)*
|
||||
|
||||
### Colors
|
||||
|
||||
- `black`
|
||||
- `red`
|
||||
- `green`
|
||||
- `yellow`
|
||||
- `blue` *(on Windows the bright version is used as normal blue is illegible)*
|
||||
- `magenta`
|
||||
- `cyan`
|
||||
- `white`
|
||||
- `gray`
|
||||
|
||||
### Background colors
|
||||
|
||||
- `bgBlack`
|
||||
- `bgRed`
|
||||
- `bgGreen`
|
||||
- `bgYellow`
|
||||
- `bgBlue`
|
||||
- `bgMagenta`
|
||||
- `bgCyan`
|
||||
- `bgWhite`
|
||||
|
||||
|
||||
## 256-colors
|
||||
|
||||
Chalk does not support anything other than the base eight colors, which guarantees it will work on all terminals and systems. Some terminals, specifically `xterm` compliant ones, will support the full range of 8-bit colors. For this the lower level [ansi-256-colors](https://github.com/jbnicolai/ansi-256-colors) package can be used.
|
||||
|
||||
|
||||
## Windows
|
||||
|
||||
If you're on Windows, do yourself a favor and use [`cmder`](http://bliker.github.io/cmder/) instead of `cmd.exe`.
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [chalk-cli](https://github.com/chalk/chalk-cli) - CLI for this module
|
||||
- [ansi-styles](https://github.com/chalk/ansi-styles/) - ANSI escape codes for styling strings in the terminal
|
||||
- [supports-color](https://github.com/chalk/supports-color/) - Detect whether a terminal supports color
|
||||
- [strip-ansi](https://github.com/chalk/strip-ansi) - Strip ANSI escape codes
|
||||
- [has-ansi](https://github.com/chalk/has-ansi) - Check if a string has ANSI escape codes
|
||||
- [ansi-regex](https://github.com/chalk/ansi-regex) - Regular expression for matching ANSI escape codes
|
||||
- [wrap-ansi](https://github.com/chalk/wrap-ansi) - Wordwrap a string with ANSI escape codes
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](http://sindresorhus.com)
|
22
samples/react-spfx-multilist-grid/config/config.json
Normal file
22
samples/react-spfx-multilist-grid/config/config.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"entries": [
|
||||
{
|
||||
"entry": "./lib/webparts/spfxReactGrid/SpfxReactGridWebPart.js",
|
||||
"manifest": "./src/webparts/spfxReactGrid/SpfxReactGridWebPart.manifest.json",
|
||||
"outputPath": "./dist/spfx-react-grid.bundle.js"
|
||||
}
|
||||
],
|
||||
"externals": {
|
||||
"@microsoft/sp-client-base": "node_modules/@microsoft/sp-client-base/dist/sp-client-base.js",
|
||||
"@microsoft/sp-client-preview": "node_modules/@microsoft/sp-client-preview/dist/sp-client-preview.js",
|
||||
"@microsoft/sp-webpart-base": "node_modules/@microsoft/sp-webpart-base/dist/sp-webpart-base.js",
|
||||
"@microsoft/sp-lodash-subset": "node_modules/@microsoft/sp-lodash-subset/dist/sp-lodash-subset.js",
|
||||
"office-ui-fabric-react": "node_modules/office-ui-fabric-react/dist/office-ui-fabric-react.js",
|
||||
"react": "node_modules/react/dist/react.min.js",
|
||||
"react-dom": "node_modules/react-dom/dist/react-dom.min.js",
|
||||
"react-dom/server": "node_modules/react-dom/dist/react-dom-server.min.js"
|
||||
},
|
||||
"localizedResources": {
|
||||
"spfxReactGridStrings": "webparts/spfxReactGrid/loc/{locale}.js"
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"workingDir": "./temp/deploy/",
|
||||
"account": "<!-- STORAGE ACCOUNT NAME -->",
|
||||
"container": "spfxreactgrid",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
{
|
||||
"solution": {
|
||||
"name": "spfxreactgrid-client-side-solution",
|
||||
"id": "28bf799f-01fc-45e9-8997-f7982eaf8b53",
|
||||
"version": "1.0.0.0"
|
||||
},
|
||||
"paths": {
|
||||
"zippedPackage": "solution/spfxreactgrid.spapp"
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"deployCdnPath": "temp/deploy"
|
||||
}
|
9
samples/react-spfx-multilist-grid/config/serve.json
Normal file
9
samples/react-spfx-multilist-grid/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/"
|
||||
}
|
||||
}
|
53
samples/react-spfx-multilist-grid/config/tslint.json
Normal file
53
samples/react-spfx-multilist-grid/config/tslint.json
Normal file
@ -0,0 +1,53 @@
|
||||
{
|
||||
// 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": false,
|
||||
|
||||
|
||||
"quotemark": false
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"cdnBasePath": "<!-- PATH TO CDN -->"
|
||||
}
|
6
samples/react-spfx-multilist-grid/gulpfile.js
vendored
Normal file
6
samples/react-spfx-multilist-grid/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-spfx-multilist-grid/package.json
Normal file
38
samples/react-spfx-multilist-grid/package.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "spfxreactgrid",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/sp-client-base": "~0.4.0",
|
||||
"@microsoft/sp-client-preview": "~0.5.0",
|
||||
"@microsoft/sp-webpart-base": "^0.1.0",
|
||||
"office-ui-fabric-react": "^0.36.0",
|
||||
"react": "0.14.8",
|
||||
"react-data-grid": "^1.0.62",
|
||||
"react-dom": "0.14.8",
|
||||
"react-redux": "^4.4.6",
|
||||
"react-router": "^2.8.1",
|
||||
"react-router-redux": "^4.0.5",
|
||||
"redux": "^3.4.0",
|
||||
"redux-localstorage": "^0.4.1",
|
||||
"redux-logger": "^2.6.0",
|
||||
"redux-promise-middleware": "^4.1.0",
|
||||
"redux-thunk": "^2.1.0",
|
||||
"sp-pnp-js": "^1.0.6",
|
||||
"underscore": "^1.8.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/sp-build-web": "~0.7.0",
|
||||
"@microsoft/sp-module-interfaces": "~0.4.0",
|
||||
"@microsoft/sp-webpart-workbench": "~0.5.0",
|
||||
"gulp": "~3.9.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "gulp bundle",
|
||||
"clean": "gulp nuke",
|
||||
"test": "gulp test"
|
||||
}
|
||||
}
|
124
samples/react-spfx-multilist-grid/spfxreactgrid.njsproj
Normal file
124
samples/react-spfx-multilist-grid/spfxreactgrid.njsproj
Normal file
@ -0,0 +1,124 @@
|
||||
<?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>{28bf799f-01fc-45e9-8997-f7982eaf8b53}</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>
|
||||
<ItemGroup>
|
||||
<Folder Include="config\" />
|
||||
<Folder Include="src\" />
|
||||
<Folder Include="src\webparts\" />
|
||||
<Folder Include="src\webparts\spfxReactGrid\" />
|
||||
<Folder Include="src\webparts\spfxReactGrid\actions\" />
|
||||
<Folder Include="src\webparts\spfxReactGrid\components\" />
|
||||
<Folder Include="src\webparts\spfxReactGrid\containers\" />
|
||||
<Folder Include="src\webparts\spfxReactGrid\loc\" />
|
||||
<Folder Include="src\webparts\spfxReactGrid\model\" />
|
||||
<Folder Include="src\webparts\spfxReactGrid\reducers\" />
|
||||
<Folder Include="src\webparts\spfxReactGrid\store\" />
|
||||
<Folder Include="src\webparts\spfxReactGrid\utils\" />
|
||||
<Folder Include="typings\" />
|
||||
<Folder Include="typings\%40ms\" />
|
||||
<Folder Include="typings\assertion-error\" />
|
||||
<Folder Include="typings\chai\" />
|
||||
<Folder Include="typings\combokeys\" />
|
||||
<Folder Include="typings\es6-collections\" />
|
||||
<Folder Include="typings\es6-promise\" />
|
||||
<Folder Include="typings\globals\" />
|
||||
<Folder Include="typings\globals\react-data-grid\" />
|
||||
<Folder Include="typings\globals\redux-promise-middleware\" />
|
||||
<Folder Include="typings\globals\redux\" />
|
||||
<Folder Include="typings\knockout\" />
|
||||
<Folder Include="typings\lodash\" />
|
||||
<Folder Include="typings\mocha\" />
|
||||
<Folder Include="typings\modules\" />
|
||||
<Folder Include="typings\modules\react-redux\" />
|
||||
<Folder Include="typings\modules\react-router-redux\" />
|
||||
<Folder Include="typings\modules\react-router\" />
|
||||
<Folder Include="typings\modules\react-select\" />
|
||||
<Folder Include="typings\modules\redux-thunk\" />
|
||||
<Folder Include="typings\node\" />
|
||||
<Folder Include="typings\react\" />
|
||||
<Folder Include="typings\systemjs\" />
|
||||
<Folder Include="typings\whatwg-fetch\" />
|
||||
</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>
|
22
samples/react-spfx-multilist-grid/spfxreactgrid.sln
Normal file
22
samples/react-spfx-multilist-grid/spfxreactgrid.sln
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.25928.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "spfxreactgrid", "spfxreactgrid.njsproj", "{28BF799F-01FC-45E9-8997-F7982EAF8B53}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{28BF799F-01FC-45E9-8997-F7982EAF8B53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{28BF799F-01FC-45E9-8997-F7982EAF8B53}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{28BF799F-01FC-45E9-8997-F7982EAF8B53}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{28BF799F-01FC-45E9-8997-F7982EAF8B53}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
BIN
samples/react-spfx-multilist-grid/src/images/ListDefinitions.PNG
Normal file
BIN
samples/react-spfx-multilist-grid/src/images/ListDefinitions.PNG
Normal file
Binary file not shown.
After Width: | Height: | Size: 37 KiB |
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
BIN
samples/react-spfx-multilist-grid/src/images/editListItems.PNG
Normal file
BIN
samples/react-spfx-multilist-grid/src/images/editListItems.PNG
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
5
samples/react-spfx-multilist-grid/src/tests.js
vendored
Normal file
5
samples/react-spfx-multilist-grid/src/tests.js
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
var context = require.context('.', true, /.+\.test\.js?$/);
|
||||
|
||||
context.keys().forEach(context);
|
||||
|
||||
module.exports = context;
|
51
samples/react-spfx-multilist-grid/src/tslint.json
Normal file
51
samples/react-spfx-multilist-grid/src/tslint.json
Normal file
@ -0,0 +1,51 @@
|
||||
{
|
||||
// Display errors as warnings
|
||||
"displayAsWarning": true,
|
||||
// The TSLint task may have been configured with several custom lint rules
|
||||
// before this config file is read (for example lint rules from the tslint-microsoft-contrib
|
||||
// project). If true, this flag will deactivate any of these rules.
|
||||
"removeExistingRules": true,
|
||||
// When true, the TSLint task is configured with some default TSLint "rules.":
|
||||
"useDefaultConfigAsBase": false,
|
||||
// Since removeExistingRules=true and useDefaultConfigAsBase=false, there will be no lint rules
|
||||
// which are active, other than the list of rules below.
|
||||
"lintConfig": {
|
||||
// Opt-in to Lint rules which help to eliminate bugs in JavaScript
|
||||
"rules": {
|
||||
"class-name": false,
|
||||
"export-name": false,
|
||||
"forin": false,
|
||||
"label-position": false,
|
||||
"label-undefined": false,
|
||||
"member-access": true,
|
||||
"no-arg": false,
|
||||
"no-console": false,
|
||||
"no-construct": false,
|
||||
"no-duplicate-case": true,
|
||||
"no-duplicate-key": false,
|
||||
"no-duplicate-variable": true,
|
||||
"no-eval": false,
|
||||
"no-function-expression": true,
|
||||
"no-internal-module": true,
|
||||
"no-shadowed-variable": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-unnecessary-semicolons": true,
|
||||
"no-unused-expression": true,
|
||||
"no-unused-imports": true,
|
||||
"no-unused-variable": true,
|
||||
"no-unreachable": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-with-statement": true,
|
||||
"semicolon": true,
|
||||
"trailing-comma": false,
|
||||
"typedef": false,
|
||||
"typedef-whitespace": false,
|
||||
"use-named-parameter": true,
|
||||
"valid-typeof": true,
|
||||
"variable-name": false,
|
||||
"whitespace": false,
|
||||
"prefer-const": false,
|
||||
"quotemark": false
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
|
||||
import ListDefinition from "./model/ListDefinition";
|
||||
import column from "./model/ColumnDefinition";
|
||||
export interface ISpfxReactGridWebPartProps {
|
||||
description: string;
|
||||
lists: ListDefinition[];
|
||||
columns: column[];
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
WorkBench-pageContent {
|
||||
max-width: inherit;
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"$schema": "../../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json",
|
||||
|
||||
"id": "72ac17a3-8735-43ff-9a3c-3be22ac2ca00",
|
||||
"componentType": "WebPart",
|
||||
"version": "0.0.1",
|
||||
"manifestVersion": 2,
|
||||
|
||||
"preconfiguredEntries": [{
|
||||
"groupId": "72ac17a3-8735-43ff-9a3c-3be22ac2ca00",
|
||||
"group": { "default": "Under Development" },
|
||||
"title": { "default": "SPFX React Grid" },
|
||||
"description": { "default": "react grid sample" },
|
||||
"officeFabricIconFontName": "Page",
|
||||
"properties": {
|
||||
"description": "SPFX React Grid"
|
||||
}
|
||||
}]
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
import * as React from "react";
|
||||
import * as ReactDom from "react-dom";
|
||||
import { Provider } from "react-redux";
|
||||
|
||||
// require("office-ui-fabric/dist/css/Fabric.css");
|
||||
// require("office-ui-fabric/dist/css/Fabric.Components.css");
|
||||
// require("office-ui-fabric/dist/components/CommandBar/CommandBar.css");
|
||||
|
||||
|
||||
import configureStore from "./store/configure-store";
|
||||
const { Router, createMemoryHistory } = require("react-router");
|
||||
|
||||
import { addLists } from "./actions/listActions";
|
||||
import { addColumns } from "./actions/columnActions";
|
||||
import { addPageContext } from "./actions/PageContextActions";
|
||||
import {
|
||||
BaseClientSideWebPart,
|
||||
IPropertyPaneSettings, IWebPartData, IHtmlProperties,
|
||||
IWebPartContext,
|
||||
PropertyPaneTextField
|
||||
} from "@microsoft/sp-webpart-base";
|
||||
import { Log } from "@microsoft/sp-client-base";
|
||||
import routes from "./store/routes";
|
||||
import * as strings from "spfxReactGridStrings";
|
||||
|
||||
|
||||
import { ISpfxReactGridWebPartProps } from "./ISpfxReactGridWebPartProps";
|
||||
const store: Redux.Store<any> = configureStore({});
|
||||
const history = createMemoryHistory(location);
|
||||
const App: React.StatelessComponent<any> = () => (
|
||||
<Provider store={store}>
|
||||
<Router history={history}>
|
||||
{routes}
|
||||
</Router>
|
||||
</Provider>
|
||||
);
|
||||
export default class SpfxReactGridWebPart extends BaseClientSideWebPart<ISpfxReactGridWebPartProps> {
|
||||
public constructor(context: IWebPartContext) {
|
||||
super(context);
|
||||
Log.verbose("SpfxReactGridWebPart", "In constructor of SpfxReactGridWebPart");
|
||||
}
|
||||
public render(): void {
|
||||
|
||||
store.dispatch(addLists(this.properties.lists));
|
||||
store.dispatch(addColumns(this.properties.columns));
|
||||
store.dispatch(addPageContext(this.context.pageContext));
|
||||
Log.verbose("SpfxReactGridWebPart", "In render of SpfxReactGridWebPart");
|
||||
ReactDom.render(App(), this.domElement);
|
||||
}
|
||||
protected deserialize(data: IWebPartData): ISpfxReactGridWebPartProps {
|
||||
const info = super.deserialize(data);
|
||||
return info;
|
||||
}
|
||||
protected onBeforeSerialize(): IHtmlProperties {
|
||||
|
||||
// this.properties.columns = [];
|
||||
// this.properties.lists =[];
|
||||
this.properties.columns = store.getState().columns;
|
||||
this.properties.lists = store.getState().lists;
|
||||
return super.onBeforeSerialize();
|
||||
}
|
||||
protected get propertyPaneSettings(): IPropertyPaneSettings {
|
||||
Log.verbose("SpfxReactGridWebPart", "In propertyPaneSettings of SpfxReactGridWebPart");
|
||||
return {
|
||||
pages: [
|
||||
{
|
||||
header: {
|
||||
description: strings.PropertyPaneDescription
|
||||
},
|
||||
groups: [
|
||||
{
|
||||
groupName: strings.BasicGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneTextField("description", {
|
||||
label: strings.DescriptionFieldLabel
|
||||
})
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,382 @@
|
||||
import {
|
||||
ADD_LISTITEM,
|
||||
ADD_LISTITEMS,
|
||||
REMOVE_LISTITEM,
|
||||
GET_LISTITEMS,
|
||||
GOT_LISTITEMS,
|
||||
GET_LISTITEMSERROR,
|
||||
|
||||
GOT_LISTITEM,
|
||||
GET_LISTITEMERROR,
|
||||
CLEAR_LISTITEMS,
|
||||
SAVE_LISTITEM,//save locally
|
||||
UNDO_LISTITEMCHANGES,
|
||||
UPDATE_LISTITEM,//save to sharepoint
|
||||
UPDATE_LISTITEM_ERROR,
|
||||
UPDATE_LISTITEM_SUCCESS,
|
||||
ADDED_NEW_ITEM_TO_SHAREPOINT,
|
||||
REMOVE_LISTITEM_SUCCESS,
|
||||
REMOVE_LISTITEM_ERROR
|
||||
|
||||
|
||||
} from "../constants";
|
||||
import "whatwg-fetch";
|
||||
import * as utils from "../utils/utils";
|
||||
|
||||
import { Web, TypedHash } from "sp-pnp-js";
|
||||
import ListItem from "../model/ListItem";
|
||||
import GridRowStatus from "../Model/GridRowStatus";
|
||||
|
||||
import ListDefinition from "../model/ListDefinition";
|
||||
export function clearListItems() {
|
||||
return {
|
||||
type: CLEAR_LISTITEMS,
|
||||
payload: {
|
||||
}
|
||||
};
|
||||
}
|
||||
export function addListItem(listItem: ListItem) {
|
||||
return {
|
||||
type: ADD_LISTITEM,
|
||||
payload: {
|
||||
listItem: listItem
|
||||
}
|
||||
};
|
||||
}
|
||||
export function removeListItem(dispatch: any, listItem: ListItem, listDefinition: ListDefinition): any {
|
||||
const weburl = utils.ParseSPField(listDefinition.webLookup).id;
|
||||
const listid = utils.ParseSPField(listDefinition.listLookup).id;
|
||||
const web = new Web(weburl);
|
||||
switch (listItem.__metadata__GridRowStatus) {
|
||||
case GridRowStatus.modified:
|
||||
case GridRowStatus.pristine:
|
||||
web.lists.getById(listid).items.getById(listItem.ID).recycle()
|
||||
.then((response) => {
|
||||
// shouwld have an option to rfresh here in cas of calculated columns
|
||||
|
||||
const gotListItems = removeListItemSuccessAction(listItem);
|
||||
dispatch(gotListItems); // need to ewname this one to be digfferent from the omported ome
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
dispatch(removeListItemErrorAction(error)); // need to ewname this one to be digfferent from the omported ome
|
||||
});
|
||||
return {
|
||||
type: REMOVE_LISTITEM,
|
||||
payload: {
|
||||
listItem: listItem
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
export function removeListItemSuccessAction(listItem) {
|
||||
|
||||
return {
|
||||
type: REMOVE_LISTITEM_SUCCESS,
|
||||
payload: {
|
||||
listItem: listItem
|
||||
}
|
||||
};
|
||||
}
|
||||
export function removeListItemErrorAction(listItem) {
|
||||
|
||||
return {
|
||||
type: REMOVE_LISTITEM_ERROR,
|
||||
payload: {
|
||||
listItem: listItem
|
||||
}
|
||||
};
|
||||
}
|
||||
export function addListItems(listItems: ListItem[]) {
|
||||
return {
|
||||
type: ADD_LISTITEMS,
|
||||
payload: {
|
||||
listItems: listItems
|
||||
}
|
||||
};
|
||||
}
|
||||
export function listDefinitionIsValid(listDefinition: ListDefinition): boolean {
|
||||
if (listDefinition.webLookup === null) {
|
||||
return false;
|
||||
}
|
||||
if (listDefinition.listLookup === null) {
|
||||
return false;
|
||||
}
|
||||
if (listDefinition.columnReferences === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Action to update a listitem in sharepoint
|
||||
*/
|
||||
export function updateListItemAction(dispatch: any, listDefinition: ListDefinition, listItem: ListItem): any {
|
||||
// listDefinition = this.getListDefinition(listItem.__metadata__ListDefinitionId);// The list Definition this item is associated with.
|
||||
const weburl = utils.ParseSPField(listDefinition.webLookup).id;
|
||||
const listid = utils.ParseSPField(listDefinition.listLookup).id;
|
||||
const web = new Web(weburl);
|
||||
let typedHash: TypedHash<string | number | boolean> = {};
|
||||
for (const columnRef of listDefinition.columnReferences) {
|
||||
let fieldName = utils.ParseSPField(columnRef.name).id;
|
||||
switch (columnRef.fieldDefinition.TypeAsString) {
|
||||
case "Lookup":
|
||||
if (listItem[fieldName]) {// field may not be set
|
||||
typedHash[fieldName + "Id"] = listItem[fieldName].Id;
|
||||
}
|
||||
break;
|
||||
case "User":
|
||||
|
||||
if (listItem[fieldName]) {// field may not be set
|
||||
typedHash[fieldName + "Id"] = listItem[fieldName].Id;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
typedHash[fieldName] = listItem[fieldName];
|
||||
}
|
||||
}
|
||||
switch (listItem.__metadata__GridRowStatus) {
|
||||
case GridRowStatus.modified:
|
||||
case GridRowStatus.pristine:// if user cjust chnage the listedef
|
||||
|
||||
const promise = web.lists.getById(listid).items.getById(listItem.ID).update(typedHash, listItem["odata.etag"])
|
||||
.then((response) => {
|
||||
|
||||
getListItem(listDefinition, listItem.ID)
|
||||
.then((r) => {
|
||||
|
||||
// srfresh here in cas of calculated columns
|
||||
r.__metadata__ListDefinitionId = listDefinition.guid; // save my listdef, so i can get the columnReferences later
|
||||
r.__metadata__GridRowStatus = GridRowStatus.pristine; // save my listdef, so i can get the columnReferences later
|
||||
const gotListItems = updateListItemSuccessAction(r);
|
||||
dispatch(gotListItems); // need to ewname this one to be digfferent from the omported ome
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
dispatch(updateListItemErrorAction(error)); // need to ewname this one to be digfferent from the omported ome
|
||||
});
|
||||
const action = {
|
||||
type: UPDATE_LISTITEM,
|
||||
payload: {
|
||||
promise: promise
|
||||
}
|
||||
};
|
||||
return action;
|
||||
case GridRowStatus.new:
|
||||
const mewpromise = web.lists.getById(listid).items.add(typedHash)
|
||||
.then((response) => {//
|
||||
|
||||
const itemId = response.data.Id;
|
||||
getListItem(listDefinition, itemId)
|
||||
.then((r) => {
|
||||
/**
|
||||
* data recived after adding an item is NOT the same as we recive from a get
|
||||
* need to fetch item and wap it in
|
||||
*/
|
||||
r.__metadata__ListDefinitionId = listDefinition.guid; // save my listdef, so i can get the columnReferences later
|
||||
r.__metadata__GridRowStatus = GridRowStatus.pristine; // save my listdef, so i can get the columnReferences later
|
||||
const actiom = addedNewItemInSharepouint(r, listItem);
|
||||
dispatch(actiom); // need to ewname this one to be digfferent from the omported ome
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
dispatch(updateListItemErrorAction(error)); // need to ewname this one to be digfferent from the omported ome
|
||||
});
|
||||
|
||||
});
|
||||
return {
|
||||
type: UPDATE_LISTITEM,
|
||||
payload: {
|
||||
promise: mewpromise
|
||||
}
|
||||
};
|
||||
default:
|
||||
return; // action called on item with ibalid state
|
||||
}
|
||||
}
|
||||
export function updateListItemErrorAction(error) {
|
||||
return {
|
||||
type: UPDATE_LISTITEM_ERROR,
|
||||
payload: {
|
||||
error: error
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* called after an item was added to the local cache, updated, then sent to sharepoint.
|
||||
* We need to replace our local copy, with the real valuse that we got back from sharepoint
|
||||
*/
|
||||
export function addedNewItemInSharepouint(listItem, localCopy) {
|
||||
return {
|
||||
type: ADDED_NEW_ITEM_TO_SHAREPOINT,
|
||||
payload: {
|
||||
listItem: listItem,
|
||||
localCopy: localCopy
|
||||
}
|
||||
};
|
||||
}
|
||||
export function updateListItemSuccessAction(listItem) {
|
||||
|
||||
return {
|
||||
type: UPDATE_LISTITEM_SUCCESS,
|
||||
payload: {
|
||||
listItem: listItem
|
||||
}
|
||||
};
|
||||
}
|
||||
export function getListItem(listDefinition: ListDefinition, itemId: number): Promise<any> {
|
||||
|
||||
|
||||
|
||||
let fieldnames = new Array<string>();
|
||||
let expands = new Array<string>();
|
||||
|
||||
for (const columnreference of listDefinition.columnReferences) {
|
||||
switch (columnreference.fieldDefinition.TypeAsString) {
|
||||
case "Lookup":
|
||||
expands.push(columnreference.fieldDefinition.InternalName);
|
||||
fieldnames.push(columnreference.fieldDefinition.InternalName + "/" + columnreference.fieldDefinition.LookupField);
|
||||
fieldnames.push(columnreference.fieldDefinition.InternalName + "/Id");
|
||||
break;
|
||||
case "User":
|
||||
// url is ?$select=Author/Name,Author/Title&$expand=Author/Id
|
||||
expands.push(columnreference.fieldDefinition.InternalName + "/Id");
|
||||
fieldnames.push(columnreference.fieldDefinition.InternalName + "/Title");
|
||||
fieldnames.push(columnreference.fieldDefinition.InternalName + "/Id");
|
||||
fieldnames.push(columnreference.fieldDefinition.InternalName + "/Name");
|
||||
break;
|
||||
default:
|
||||
|
||||
const internalName = utils.ParseSPField(columnreference.name).id;
|
||||
fieldnames.push(internalName); // need to split
|
||||
}
|
||||
}
|
||||
|
||||
const weburl = utils.ParseSPField(listDefinition.webLookup).id;
|
||||
const listid = utils.ParseSPField(listDefinition.listLookup).id;
|
||||
|
||||
const web = new Web(weburl);
|
||||
|
||||
let promise: Promise<any> = web.lists.getById(listid).items.getById(itemId).select(fieldnames.concat("GUID").concat("Id").join(",")).expand(expands.join(",")).get();
|
||||
|
||||
return promise;
|
||||
}
|
||||
export function getListItemErrorAction(error) {
|
||||
return {
|
||||
type: GET_LISTITEMERROR,
|
||||
payload: {
|
||||
error: error
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
export function gotListItemAction(item) {
|
||||
return {
|
||||
type: GOT_LISTITEM,
|
||||
payload: {
|
||||
item: item
|
||||
}
|
||||
};
|
||||
}
|
||||
export function getListItemsAction(dispatch: any, listDefinitions: Array<ListDefinition>): any {
|
||||
dispatch(clearListItems());
|
||||
|
||||
const promises: Array<Promise<any>> = new Array<Promise<any>>();
|
||||
for (const listDefinition of listDefinitions) {
|
||||
if (!listDefinitionIsValid(listDefinition)) {
|
||||
break;
|
||||
}
|
||||
let fieldnames = new Array<string>();
|
||||
let expands = new Array<string>();
|
||||
|
||||
for (const columnreference of listDefinition.columnReferences) {
|
||||
switch (columnreference.fieldDefinition.TypeAsString) {
|
||||
case "Lookup":
|
||||
expands.push(columnreference.fieldDefinition.InternalName);
|
||||
fieldnames.push(columnreference.fieldDefinition.InternalName + "/" + columnreference.fieldDefinition.LookupField);
|
||||
fieldnames.push(columnreference.fieldDefinition.InternalName + "/Id");
|
||||
break;
|
||||
case "User":
|
||||
// url is ?$select=Author/Name,Author/Title&$expand=Author/Id
|
||||
expands.push(columnreference.fieldDefinition.InternalName + "/Id");
|
||||
fieldnames.push(columnreference.fieldDefinition.InternalName + "/Title");
|
||||
fieldnames.push(columnreference.fieldDefinition.InternalName + "/Id");
|
||||
fieldnames.push(columnreference.fieldDefinition.InternalName + "/Name");
|
||||
break;
|
||||
default:
|
||||
|
||||
const internalName = utils.ParseSPField(columnreference.name).id;
|
||||
fieldnames.push(internalName); // need to split
|
||||
}
|
||||
}
|
||||
|
||||
const weburl = utils.ParseSPField(listDefinition.webLookup).id;
|
||||
const listid = utils.ParseSPField(listDefinition.listLookup).id;
|
||||
|
||||
const web = new Web(weburl);
|
||||
|
||||
const promise = web.lists.getById(listid).items.select(fieldnames.concat("GUID").concat("Id").join(",")).expand(expands.join(",")).get()
|
||||
.then((response) => {
|
||||
|
||||
const data = _.map(response, (item: any) => {
|
||||
item.__metadata__ListDefinitionId = listDefinition.guid; // save my listdef, so i can get the columnReferences later
|
||||
item.__metadata__GridRowStatus = GridRowStatus.pristine;
|
||||
return item;
|
||||
});
|
||||
console.log(data);
|
||||
const gotListItems = gotListItemsAction(data);
|
||||
dispatch(gotListItems); // need to ewname this one to be digfferent from the omported ome
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
dispatch(getListItemsErrorAction(error)); // need to ewname this one to be digfferent from the omported ome
|
||||
});
|
||||
promises.push(promise);
|
||||
|
||||
|
||||
}
|
||||
const action = {
|
||||
type: GET_LISTITEMS,
|
||||
payload: {
|
||||
promise: Promise.all(promises)
|
||||
}
|
||||
};
|
||||
return action;
|
||||
}
|
||||
export function getListItemsErrorAction(error) {
|
||||
return {
|
||||
type: GET_LISTITEMSERROR,
|
||||
payload: {
|
||||
error: error
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
export function gotListItemsAction(items) {
|
||||
return {
|
||||
type: GOT_LISTITEMS,
|
||||
payload: {
|
||||
items: items
|
||||
}
|
||||
};
|
||||
}
|
||||
export function saveListItemAction(listItem: ListItem) {
|
||||
const action = {
|
||||
type: SAVE_LISTITEM,
|
||||
payload: {
|
||||
listItem
|
||||
}
|
||||
};
|
||||
return action;
|
||||
}
|
||||
export function undoListItemChangesAction(listItem: ListItem) {
|
||||
const action = {
|
||||
type: UNDO_LISTITEMCHANGES,
|
||||
payload: {
|
||||
listItem
|
||||
}
|
||||
};
|
||||
return action;
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
import {
|
||||
GET_LOOKUPOPTIONS,
|
||||
GET_LOOKUPOPTIONS_SUCCESS,
|
||||
GET_LOOKUPOPTIONS_ERROR,
|
||||
} from "../constants";
|
||||
import "whatwg-fetch";
|
||||
import { Web } from "sp-pnp-js";
|
||||
import { LookupOptions, LookupOption, LookupOptionStatus } from "../model/LookupOptions";
|
||||
export function getLookupOptionAction(dispatch: any, lookupSite: string, lookupWebId: string, lookupListId: string, lookupField: string): any {
|
||||
|
||||
let lookupOptions = new LookupOptions(lookupSite, lookupWebId, lookupListId, lookupField);
|
||||
// first add the empty header record to the store, then issue a request to get the details
|
||||
|
||||
const web = new Web(lookupWebId);
|
||||
let fields = ["Id"];
|
||||
fields.push(lookupField);
|
||||
|
||||
const promise = web.lists.getById(lookupListId).items.select(fields.join(",")).get()
|
||||
.then((response) => {
|
||||
|
||||
const data: LookupOption[] = _.map(response, (item: any) => {
|
||||
return new LookupOption(item.Id, item[lookupField]);
|
||||
});
|
||||
lookupOptions.lookupOption = data;
|
||||
lookupOptions.status=LookupOptionStatus.fetched;
|
||||
const gotLookupOptions = gotLookupOptionAction(lookupOptions);
|
||||
|
||||
dispatch(gotLookupOptions); // need to ewname this one to be digfferent from the omported ome
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
|
||||
lookupOptions.status = LookupOptionStatus.error;
|
||||
dispatch(getLookupOptionErrorAction(error, lookupOptions)); // need to ewname this one to be digfferent from the omported ome
|
||||
});
|
||||
const action = {
|
||||
type: GET_LOOKUPOPTIONS,
|
||||
payload: {
|
||||
promise: promise,
|
||||
lookupOptions: lookupOptions
|
||||
}
|
||||
};
|
||||
return action;
|
||||
}
|
||||
function getLookupOptionErrorAction(error, lookupOptions: LookupOptions) {
|
||||
|
||||
return {
|
||||
type: GET_LOOKUPOPTIONS_ERROR,
|
||||
payload: {
|
||||
error: error,
|
||||
lookupOptions: LookupOption
|
||||
}
|
||||
};
|
||||
}
|
||||
function gotLookupOptionAction(lookupOptions: LookupOptions) {
|
||||
|
||||
return {
|
||||
type: GET_LOOKUPOPTIONS_SUCCESS,
|
||||
payload: {
|
||||
lookupOptions: lookupOptions
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
import {
|
||||
ADD_PAGECONTEXT
|
||||
} from "../constants";
|
||||
|
||||
export function addPageContext(pageContext) {
|
||||
return {
|
||||
type: ADD_PAGECONTEXT,
|
||||
payload: {
|
||||
pageContext: pageContext
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -0,0 +1,145 @@
|
||||
import {
|
||||
GOT_WEBS,
|
||||
GET_WEBS,
|
||||
GET_WEBSERROR,
|
||||
GET_LISTSFORWEB_SUCCESS,
|
||||
GET_LISTSFORWEB_ERROR,
|
||||
GET_FIELDSFORLIST_SUCCESS,
|
||||
GET_FIELDSFORLIST_ERROR
|
||||
} from "../constants";
|
||||
import "whatwg-fetch";
|
||||
import * as utils from "../utils/utils";
|
||||
import { Web as SPWeb } from "sp-pnp-js";
|
||||
import { Site as SPSite } from "sp-pnp-js";
|
||||
import { Web, WebList, WebListField } from "../model/Site";
|
||||
/**
|
||||
* Action to get all the webs within a site.
|
||||
* This cant currently be done with rest, so this returns all the subsites of the rootweb instead.
|
||||
*/
|
||||
export function getWebsAction(dispatch: any, siteUrl: string): any {
|
||||
const site: SPSite = new SPSite(siteUrl);
|
||||
const payload = site.rootWeb.webs.orderBy("Title").get()
|
||||
.then((response) => {
|
||||
const data = _.map(response, (item: any) => {
|
||||
const web: Web = new Web(item.Id, item.Title, item.Url);
|
||||
return web;
|
||||
});
|
||||
console.log(data);
|
||||
const gotWebs = gotWebsAction(siteUrl, data);
|
||||
dispatch(gotWebs); // need to ewname this one to be digfferent from the omported ome
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
dispatch(getWebsErrorAction(error)); // need to ewname this one to be digfferent from the omported ome
|
||||
});
|
||||
const action = {
|
||||
type: GET_WEBS,
|
||||
payload: {
|
||||
promise: payload
|
||||
}
|
||||
};
|
||||
return action;
|
||||
}
|
||||
export function gotWebsAction(siteUrl, items) {
|
||||
return {
|
||||
type: GOT_WEBS,
|
||||
payload: {
|
||||
siteUrl: siteUrl,
|
||||
webs: items
|
||||
}
|
||||
};
|
||||
}
|
||||
export function getWebsErrorAction(error) {
|
||||
return {
|
||||
type: GET_WEBSERROR,
|
||||
payload: {
|
||||
error: error
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function getListsForWebAction(dispatch: any, webUrl: string): any {
|
||||
const web = new SPWeb(webUrl);
|
||||
|
||||
const payload = web.lists.orderBy("Title").get()
|
||||
.then((response) => {
|
||||
|
||||
const data = _.map(response, (item: any) => {
|
||||
return new WebList(item.Id, item.Title, item.Url, );
|
||||
});
|
||||
|
||||
const gotListsForWeb = gotListsForWebAction(webUrl, data);
|
||||
dispatch(gotListsForWeb); // need to ewname this one to be digfferent from the omported ome
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
dispatch(getListsForWebActionError(error)); // need to ewname this one to be digfferent from the omported ome
|
||||
});
|
||||
const action = {
|
||||
type: GET_WEBS,
|
||||
payload: {
|
||||
promise: payload
|
||||
}
|
||||
};
|
||||
return action;
|
||||
}
|
||||
export function gotListsForWebAction(webUrl, lists) {
|
||||
return {
|
||||
type: GET_LISTSFORWEB_SUCCESS,
|
||||
payload: {
|
||||
webUrl: webUrl,
|
||||
lists: lists
|
||||
}
|
||||
};
|
||||
}
|
||||
export function getListsForWebActionError(error) {
|
||||
return {
|
||||
type: GET_LISTSFORWEB_ERROR,
|
||||
payload: {
|
||||
error: error
|
||||
}
|
||||
};
|
||||
}
|
||||
export function getFieldsForListAction(dispatch: any, webUrl: string, listId: string): any {
|
||||
const web = new SPWeb(webUrl);
|
||||
const payload = web.lists.getById(listId).fields.filter("Hidden eq false").orderBy("Title").get()
|
||||
.then((response) => {
|
||||
const data = _.map(response, (item: any) => {
|
||||
return new WebListField(item.id, new utils.ParsedSPField(item.InternalName, item.Title).toString(), item);
|
||||
});
|
||||
console.log(data);
|
||||
const gotWebs = gotFieldsForListAction(webUrl, listId, data);
|
||||
dispatch(gotWebs); // need to ewname this one to be digfferent from the omported ome
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
dispatch(getFieldsForListActionError(error, webUrl, listId)); // need to ewname this one to be digfferent from the omported ome
|
||||
});
|
||||
const action = {
|
||||
type: GET_WEBS,
|
||||
payload: {
|
||||
promise: payload
|
||||
}
|
||||
};
|
||||
return action;
|
||||
}
|
||||
export function gotFieldsForListAction(webUrl, listId, fields) {
|
||||
return {
|
||||
type: GET_FIELDSFORLIST_SUCCESS,
|
||||
payload: {
|
||||
webUrl: webUrl,
|
||||
listId: listId,
|
||||
fields: fields
|
||||
}
|
||||
};
|
||||
}
|
||||
export function getFieldsForListActionError(error, webUrl, listId) {
|
||||
return {
|
||||
type: GET_FIELDSFORLIST_ERROR,
|
||||
payload: {
|
||||
webUrl: webUrl,
|
||||
listId: listId,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -0,0 +1,55 @@
|
||||
import {
|
||||
GET_SITE_USERS,
|
||||
GET_SITE_USERS_ERROR,
|
||||
GET_SITE_USERS_SUCCESS
|
||||
} from "../constants";
|
||||
import "whatwg-fetch";
|
||||
import { Site } from "sp-pnp-js";
|
||||
import { SiteUser, SiteUsers, SiteUsersStatus } from "../model/SiteUsers";
|
||||
export function getSiteUsersAction(dispatch: any, siteUrl: string): any {
|
||||
let siteUsers = new SiteUsers(siteUrl);
|
||||
// first add the empty header record to the store, then issue a request to get the details
|
||||
const site = new Site(siteUrl);
|
||||
const promise = site.rootWeb.siteUsers.get()
|
||||
.then((response) => {
|
||||
const data: SiteUser[] = _.map(response, (item: any) => {
|
||||
return new SiteUser(item.Id, item.Title, item.LoginName);
|
||||
});
|
||||
siteUsers.siteUser = data;
|
||||
siteUsers.status = SiteUsersStatus.fetched;
|
||||
const action = gotSiteUsers(siteUsers);
|
||||
dispatch(action);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
siteUsers.status = SiteUsersStatus.error;
|
||||
dispatch(getSiteUsersErrorAction(error, siteUsers)); // need to ewname this one to be digfferent from the omported ome
|
||||
});
|
||||
const action = {
|
||||
type: GET_SITE_USERS,
|
||||
payload: {
|
||||
promise: promise,
|
||||
siteUsers: siteUsers
|
||||
}
|
||||
};
|
||||
return action;
|
||||
}
|
||||
function getSiteUsersErrorAction(error, siteUsers: SiteUsers) {
|
||||
|
||||
return {
|
||||
type: GET_SITE_USERS_ERROR,
|
||||
payload: {
|
||||
error: error,
|
||||
siteUsers: siteUsers
|
||||
}
|
||||
};
|
||||
}
|
||||
function gotSiteUsers(siteUsers: SiteUsers) {
|
||||
|
||||
return {
|
||||
type: GET_SITE_USERS_SUCCESS,
|
||||
payload: {
|
||||
siteUsers: siteUsers
|
||||
}
|
||||
};
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
// http://www.mattgreer.org/articles/typescript-react-and-redux/
|
||||
export interface Action<T> {
|
||||
readonly type: string;
|
||||
readonly payload: T;
|
||||
error?: boolean;
|
||||
meta?: any;
|
||||
}
|
||||
interface ActionCreator<T> {
|
||||
readonly type: string;
|
||||
(payload: T): Action<T>;
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
import {
|
||||
ADD_COLUMN,
|
||||
ADD_COLUMNS,
|
||||
REMOVE_COLUMN,
|
||||
REMOVE_ALLCOLUMNS,
|
||||
MOVE_COLUMN_UP,
|
||||
MOVE_COLUMN_DOWN,
|
||||
SAVE_COLUMN
|
||||
} from "../constants";
|
||||
|
||||
import ColumnDefinition from "../model/ColumnDefinition";
|
||||
export function addColumn(column: ColumnDefinition) {
|
||||
|
||||
return {
|
||||
type: ADD_COLUMN,
|
||||
payload: {
|
||||
column: column
|
||||
}
|
||||
};
|
||||
}
|
||||
export function removeColumn(column: ColumnDefinition) {
|
||||
return {
|
||||
type: REMOVE_COLUMN,
|
||||
payload: {
|
||||
column: column
|
||||
}
|
||||
};
|
||||
}
|
||||
export function moveCulumnUp(column: ColumnDefinition) {
|
||||
return {
|
||||
type: MOVE_COLUMN_UP,
|
||||
payload: {
|
||||
column: column
|
||||
}
|
||||
};
|
||||
}
|
||||
export function moveCulumnDown(column: ColumnDefinition) {
|
||||
return {
|
||||
type: MOVE_COLUMN_DOWN,
|
||||
payload: {
|
||||
column: column
|
||||
}
|
||||
};
|
||||
}
|
||||
export function removeAllColumns() {
|
||||
return {
|
||||
type: REMOVE_ALLCOLUMNS,
|
||||
payload: {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
export function addColumns(columns: ColumnDefinition[]) {
|
||||
return {
|
||||
type: ADD_COLUMNS,
|
||||
payload: {
|
||||
columns: columns
|
||||
}
|
||||
};
|
||||
}
|
||||
export function saveColumn(column: ColumnDefinition) {
|
||||
return {
|
||||
type: SAVE_COLUMN,
|
||||
payload: {
|
||||
column: column
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,52 @@
|
||||
|
||||
import {
|
||||
ADD_LIST,
|
||||
SAVE_LIST,
|
||||
ADD_LISTS,
|
||||
REMOVE_LIST,REMOVE_ALLLISTS
|
||||
|
||||
} from "../constants";
|
||||
import "whatwg-fetch";
|
||||
import ListDefinition from "../model/ListDefinition";
|
||||
export function addList(list: ListDefinition) {
|
||||
return {
|
||||
type: ADD_LIST,
|
||||
payload: {
|
||||
list: list
|
||||
}
|
||||
};
|
||||
}
|
||||
export function removeList(list: ListDefinition) {
|
||||
return {
|
||||
type: REMOVE_LIST,
|
||||
payload: {
|
||||
list: list
|
||||
}
|
||||
};
|
||||
}
|
||||
export function removeAllLists() {
|
||||
return {
|
||||
type: REMOVE_ALLLISTS,
|
||||
payload: {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
export function saveList(list: ListDefinition) {
|
||||
const action = {
|
||||
type: SAVE_LIST,
|
||||
payload: {
|
||||
list
|
||||
}
|
||||
};
|
||||
return action;
|
||||
}
|
||||
export function addLists(lists: ListDefinition[]) {
|
||||
return {
|
||||
type: ADD_LISTS,
|
||||
payload: {
|
||||
lists: lists
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
import * as React from "react";
|
||||
export interface ISelectChoices {
|
||||
value: any;
|
||||
name: string;
|
||||
}
|
||||
export interface IDropDownEditorProps extends React.Props<any> {
|
||||
value: string;
|
||||
onChange(event): void;
|
||||
choices: Array<ISelectChoices>;
|
||||
}
|
||||
export class DropDownEditor extends React.Component<IDropDownEditorProps, void> {
|
||||
constructor() {
|
||||
super();
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
}
|
||||
private handleChange(event) {
|
||||
this.props.onChange(event);
|
||||
}
|
||||
public render() {
|
||||
const { value} = this.props;
|
||||
return (
|
||||
<select value={value} onChange={this.handleChange} >
|
||||
{this.props.choices.map((choice) => {
|
||||
return (
|
||||
<option key={choice.value} value={choice.value + "#;" + choice.name} >{choice.name}</option>
|
||||
);
|
||||
}, this)
|
||||
}
|
||||
</select >
|
||||
);
|
||||
};
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
import * as React from "react";
|
||||
export interface KeyValue {
|
||||
value: any;
|
||||
displayName: string;
|
||||
}
|
||||
import { Dropdown, IDropdownOption } from "office-ui-fabric-react";
|
||||
export interface IListEditorProps extends React.Props<any> {
|
||||
selectedValue?: string;
|
||||
onChange(event): void;
|
||||
lists: Array<{ id: string, title: string }>;
|
||||
}
|
||||
export default class ListEditor extends React.Component<IListEditorProps, void> {
|
||||
constructor() {
|
||||
super();
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
}
|
||||
private handleChange(selectedItem: IDropdownOption) {
|
||||
this.props.onChange(selectedItem.key);
|
||||
}
|
||||
public render() {
|
||||
const { selectedValue, lists} = this.props;
|
||||
|
||||
let options: Array<IDropdownOption> = lists.map((list) => {
|
||||
return ({
|
||||
key: list.id + "#;" + list.title,
|
||||
text: list.title
|
||||
});
|
||||
});
|
||||
options.unshift({ key: null, text: "..Select One" });
|
||||
return (
|
||||
<Dropdown label="" selectedKey={selectedValue} options={options} onChanged={this.handleChange} >
|
||||
</Dropdown >
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,21 @@
|
||||
import * as React from "react";
|
||||
|
||||
export const SharePointLookupCellFormatter = React.createClass<{ value: string, onFocus: any }, void>({
|
||||
render(): JSX.Element {
|
||||
if (this.props.value == null) {
|
||||
return (<a href="#" data-entityid={this.props.entityid} style={{ textDecoration: "none" }}
|
||||
data-columnid={this.props.columnid} onFocus={this.props.onFocus} >
|
||||
</a>);
|
||||
}
|
||||
if (this.props.value.indexOf) {
|
||||
const displayValue = this.props.value.substring(this.props.value.indexOf("#;") + 2);
|
||||
return (<a href="#" onFocus={this.props.onFocus} style={{ textDecoration: "none" }}>
|
||||
{displayValue}
|
||||
</a>);
|
||||
}
|
||||
else {
|
||||
return (<div>Invalid Value passed to SharePointLookupCellFormatter</div>);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -0,0 +1,39 @@
|
||||
import * as React from "react";
|
||||
import { Web } from "../model/Site";
|
||||
export interface KeyValue {
|
||||
value: any;
|
||||
displayName: string;
|
||||
}
|
||||
import { Dropdown, IDropdownOption } from "office-ui-fabric-react";
|
||||
export interface IWebEditorProps extends React.Props<any> {
|
||||
selectedValue?: string;
|
||||
onChange(event): void;
|
||||
webs: Array<Web>;
|
||||
}
|
||||
export default class WebEditor extends React.Component<IWebEditorProps, void> {
|
||||
constructor() {
|
||||
super();
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
}
|
||||
private handleChange(selectedItem:IDropdownOption) {
|
||||
this.props.onChange(selectedItem.key);
|
||||
}
|
||||
public render() {
|
||||
const { selectedValue, webs} = this.props;
|
||||
|
||||
let options: Array<IDropdownOption> = webs.map((web) => {
|
||||
return ({
|
||||
key: web.url + "#;" + web.title,
|
||||
text: web.title
|
||||
});
|
||||
});
|
||||
options.unshift({ key: null, text: "..Select One" });
|
||||
return (
|
||||
<Dropdown label="" selectedKey={selectedValue} options={options} onChanged={this.handleChange} >
|
||||
</Dropdown >
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
import * as React from 'react';
|
||||
|
||||
|
||||
export interface IContainerProps extends React.Props<any> {
|
||||
size: number;
|
||||
center: boolean;
|
||||
testid?: string;
|
||||
}
|
||||
|
||||
export default function Container({
|
||||
size = 1,
|
||||
center = false,
|
||||
children = null,
|
||||
testid = ''
|
||||
}: IContainerProps) {
|
||||
return (
|
||||
<div data-testid={testid} >
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -0,0 +1,14 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export interface IContentProps extends React.Props<any> {
|
||||
isVisible: boolean;
|
||||
style?: Object;
|
||||
}
|
||||
|
||||
export default function Content({ children = null, isVisible }: IContentProps) {
|
||||
return (
|
||||
<main>
|
||||
{ isVisible ? children : null }
|
||||
</main>
|
||||
);
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
// see https://spin.atomicobject.com/2016/09/27/typed-redux-reducers-typescript-2-0/
|
||||
export type ADD_LIST = 'App/ADD_LIST';
|
||||
export const ADD_LIST: ADD_LIST = 'App/ADD_LIST';
|
||||
|
||||
|
||||
export const SAVE_LIST = "App/SAVE_LIST";
|
||||
export const ADD_LISTS = "App/ADD_LISTS";
|
||||
export const REMOVE_LIST = "App/REMOVE_LIST";
|
||||
export const REMOVE_ALLLISTS = "App/REMOVE_ALLLISTS";
|
||||
|
||||
export const ADD_LISTITEM = "App/ADD_LISTITEM";
|
||||
export const ADD_LISTITEMS = "App/ADD_LISTITEMS";
|
||||
export const GET_LISTITEMS = "App/GET_LISTITEMS";
|
||||
export const GOT_LISTITEMS = "App/GOT_LISTITEMS";
|
||||
export const GET_LISTITEM = "App/GET_LISTITEM";
|
||||
export const GOT_LISTITEM = "App/GOT_LISTITEM";
|
||||
export const GET_LISTITEMERROR = "App/GET_LISTITEM_ERROR";
|
||||
export const CLEAR_LISTITEMS = "App/CLEAR_LISTITEMS";
|
||||
export const GET_LISTITEMSERROR = "App/GET_LISTITEMS_ERROR";
|
||||
export const REMOVE_LISTITEM_SUCCESS = "App/REMOVE_LISTITEM_SUCCESS";
|
||||
export const REMOVE_LISTITEM_ERROR = "App/REMOVE_LISTITEM_ERROR";
|
||||
export const REMOVE_LISTITEM = "App/REMOVE_LISTITEM";
|
||||
/**Save listitem in store */
|
||||
export const SAVE_LISTITEM="App/SAVE_LISTITEM";
|
||||
export const UNDO_LISTITEMCHANGES="App/UNDO_LISTITEMCHANGES";
|
||||
|
||||
/** Updates item in shareepoint */
|
||||
|
||||
export const UPDATE_LISTITEM="App/UPDATE_LISTITEM";
|
||||
export const UPDATE_LISTITEM_SUCCESS="App/UPDATE_LISTITEM_SUCCESS";
|
||||
export const UPDATE_LISTITEM_ERROR="App/UPDATE_LISTITEM_ERROR";
|
||||
export const ADDED_NEW_ITEM_TO_SHAREPOINT="App/ADDED_NEW_ITEM_TO_SHAREPOINT";
|
||||
|
||||
|
||||
export const UPDATE_ALLLISTITEMS="App/UPDATE_ALLLISTITEMS";
|
||||
|
||||
export const ADD_COLUMN = "App/ADD_COLUMN";
|
||||
export const ADD_COLUMNS = "App/ADD_COLUMNS";
|
||||
export const REMOVE_COLUMN = "App/REMOVE_COLUMN";
|
||||
export const REMOVE_ALLCOLUMNS = "App/REMOVE_ALLCOLUMNS";
|
||||
export const SAVE_COLUMN = "App/SAVE_COLUMN";
|
||||
export const MOVE_COLUMN_UP = "App/MOVE_COLUMN_UP";
|
||||
export const MOVE_COLUMN_DOWN = "App/MOVE_COLUMN_DOWN";
|
||||
|
||||
|
||||
export const GET_WEBS = "App/GET_WEBS";
|
||||
export const GOT_WEBS = "App/GOT_WEBS";
|
||||
export const GET_LISTSFORWEB = "App/GET_LISTSFORWEB";
|
||||
|
||||
export type GET_LISTSFORWEB_SUCCESS = "App/GET_LISTSFORWEB_SUCCESS";
|
||||
export const GET_LISTSFORWEB_SUCCESS: GET_LISTSFORWEB_SUCCESS = "App/GET_LISTSFORWEB_SUCCESS";
|
||||
|
||||
export const GET_LISTSFORWEB_ERROR = "App/GET_LISTSFORWEB_ERROR";
|
||||
|
||||
export const GET_FIELDSFORLIST = "App/GET_FIELDSFORLIST";
|
||||
export const GET_FIELDSFORLIST_SUCCESS = "App/GET_FIELDSFORLIST_SUCCESS";
|
||||
export const GET_FIELDSFORLIST_ERROR = "App/GET_FIELDSFORLIST_ERROR";
|
||||
|
||||
export const ADD_WEBS = "App/ADD_WEBS";
|
||||
export const GET_WEBSERROR = "App/GET_WEBSERROR";
|
||||
|
||||
|
||||
export const ADD_PAGECONTEXT = "App/ADD_PAGECONTEXT";
|
||||
export const ADD_WEBPARTPROPERTIES = "App/ADD_WEBPARTPROPERTIES";
|
||||
|
||||
|
||||
export const GET_LOOKUPOPTIONS = "App/GET_LOOKUPOPTIONS";
|
||||
export const GET_LOOKUPOPTIONS_SUCCESS = "App/GET_LOOKUPOPTIONS_SUCCESS";
|
||||
export const GET_LOOKUPOPTIONS_ERROR = "App/GET_LOOKUPOPTIONS_ERROR";
|
||||
export const ADD_LOOKUPOPTIONS_REQUEST_HEADER = "App/ADD_LOOKUPOPTIONS_REQUEST_HEADER";
|
||||
|
||||
|
||||
export const GET_SITE_USERS = "App/GET_LOOKUPOPTIONS";
|
||||
export const GET_SITE_USERS_SUCCESS = "App/GET_SITE_USERS_SUCCESS";
|
||||
export const GET_SITE_USERS_ERROR = "App/GET_SITE_USERS_ERROR";
|
@ -0,0 +1,344 @@
|
||||
import * as React from "react";
|
||||
import { SharePointLookupCellFormatter } from "../components/SharePointFormatters";
|
||||
const connect = require("react-redux").connect;
|
||||
import { addColumn, removeColumn, saveColumn, removeAllColumns, moveCulumnUp, moveCulumnDown } from "../actions/columnActions";
|
||||
import ColumnDefinition from "../model/ColumnDefinition";
|
||||
import { Button, ButtonType, TextField, CommandBar, Dropdown, IDropdownOption, Toggle } from "office-ui-fabric-react";
|
||||
import Container from "../components/container";
|
||||
import { Guid, Log } from "@microsoft/sp-client-base";
|
||||
|
||||
const fieldTypes: Array<IDropdownOption> = [
|
||||
{ key: null, text: "(Selecte one)" },
|
||||
{ key: "__LISTDEFINITIONTITLE__", text: "List Title" }, //used to display the ListDefinition Title in the grid, for when users add a new item
|
||||
{ key: "Text", text: "Text" },
|
||||
{ key: "Integer", text: "Integer" },
|
||||
{ key: "Note", text: "Note" },
|
||||
{ key: "DateTime", text: "DateTime" },
|
||||
// { key: "Counter", text: "Counter" },
|
||||
{ key: "Choice", text: "Choice" },
|
||||
{ key: "Lookup", text: "Lookup" },
|
||||
// { key: "Boolean", value: "Boolean" },
|
||||
{ key: "Number", text: "Number" },
|
||||
// { key: "Currency", value: "Currency" },
|
||||
// { key: "URL", value: "URL" },
|
||||
// { key: "Computed", value: "Computed" },
|
||||
// { name: "Guid", value: "Guid" },
|
||||
// { name: "MultiChoice", value: "MultiChoice" },
|
||||
// { name: "Computed", value: "Computed" },
|
||||
// { name: "Calculated", value: "Calculated" },
|
||||
// { name: "Computed", value: "Computed" },
|
||||
// { name: "File", value: "File" },
|
||||
// { name: "Attachments", value: "Attachments" },
|
||||
{ key: "User", text: "User" },
|
||||
// { name: "ModStat", value: "ModStat" },
|
||||
// { name: "ContentTypeId", value: "ContentTypeId" },
|
||||
// { name: "WorkflowStatus", value: "WorkflowStatus" },
|
||||
// { name: "WorkflowEventType", value: "WorkflowEventType" },
|
||||
|
||||
];
|
||||
interface IColumnsPageProps extends React.Props<any> {
|
||||
columns: Array<ColumnDefinition>;
|
||||
addColumn: () => void;
|
||||
removeAllColumns: () => void;
|
||||
removeColumn: (column) => void;
|
||||
saveColumn: (Column) => void;
|
||||
moveColumnUp: (Column: ColumnDefinition) => void;
|
||||
moveColumnDown: (Column: ColumnDefinition) => void;
|
||||
}
|
||||
interface IContextMenu extends React.Props<any> {
|
||||
onRowDelete: AdazzleReactDataGrid.ColumnEventCallback;
|
||||
}
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
columns: state.columns,
|
||||
};
|
||||
}
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
addColumn: (): void => {
|
||||
const id = Guid.newGuid();
|
||||
const col: ColumnDefinition = new ColumnDefinition(id.toString(), "", 80, true);
|
||||
dispatch(addColumn(col));
|
||||
},
|
||||
saveColumn: (updatedRowData): void => {
|
||||
dispatch(saveColumn(updatedRowData));
|
||||
},
|
||||
removeColumn: (column): void => {
|
||||
|
||||
dispatch(removeColumn(column));
|
||||
},
|
||||
removeAllColumns: (column): void => {
|
||||
|
||||
dispatch(removeAllColumns());
|
||||
},
|
||||
moveColumnUp: (column): void => {
|
||||
dispatch(moveCulumnUp(column));
|
||||
},
|
||||
moveColumnDown: (column): void => {
|
||||
dispatch(moveCulumnDown(column));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export interface GridColumn {
|
||||
id: string;
|
||||
name: string;
|
||||
editable: boolean;
|
||||
width: number;
|
||||
formatter?: string;
|
||||
editor?: string;
|
||||
}
|
||||
interface IGridProps {
|
||||
editing: {
|
||||
entityid: string;
|
||||
columnid: string;
|
||||
};
|
||||
}
|
||||
class ColumnDefinitionContainer extends React.Component<IColumnsPageProps, IGridProps> {
|
||||
public constructor() {
|
||||
super();
|
||||
this.CellContents = this.CellContents.bind(this);
|
||||
this.TableDetail = this.TableDetail.bind(this);
|
||||
this.TableRow = this.TableRow.bind(this);
|
||||
this.TableRows = this.TableRows.bind(this);
|
||||
this.toggleEditing = this.toggleEditing.bind(this);
|
||||
this.handleCellUpdated = this.handleCellUpdated.bind(this);
|
||||
this.handleCellUpdatedEvent = this.handleCellUpdatedEvent.bind(this);
|
||||
this.handleRowdeleted = this.handleRowdeleted.bind(this);
|
||||
this.moveColumnUp = this.moveColumnUp.bind(this);
|
||||
this.moveColumnDown = this.moveColumnDown.bind(this);
|
||||
|
||||
}
|
||||
public gridColulumns: Array<GridColumn> = [{
|
||||
id: "guid",
|
||||
name: "guid",
|
||||
editable: true,
|
||||
width: 250
|
||||
},
|
||||
{
|
||||
id: "name",
|
||||
name: "name",
|
||||
editable: true,
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
id: "type",
|
||||
name: "type",
|
||||
editable: true,
|
||||
editor: "FieldTypesEditor",
|
||||
formatter: "",
|
||||
width: 80
|
||||
},
|
||||
{
|
||||
id: "editable",
|
||||
name: "editable",
|
||||
editable: true,
|
||||
editor: "BooleanEditor",
|
||||
formatter: "BooleanFormatter",
|
||||
width: 99
|
||||
}];
|
||||
|
||||
private handleCellUpdatedEvent(event) { //native react uses a Synthetic event
|
||||
this.handleCellUpdated(event.target.value);
|
||||
}
|
||||
private handleCellUpdated(value) { // Office UI Fabric does not use events. It just calls this method with the new value
|
||||
let {entityid, columnid} = this.state.editing;
|
||||
const entity: ColumnDefinition = this.props.columns.find((temp) => temp.guid === entityid);
|
||||
const column = this.gridColulumns.find(temp => temp.id === columnid);
|
||||
entity[column.name] = value;
|
||||
this.props.saveColumn(entity);
|
||||
|
||||
}
|
||||
|
||||
private moveColumnUp(event) {
|
||||
|
||||
Log.verbose("list-Page", "Row changed-fired when row changed or leaving cell ");
|
||||
const target = this.getParent(event.target, "TD");
|
||||
const attributes: NamedNodeMap = target.attributes;
|
||||
const entityId = attributes.getNamedItem("data-entityid").value;
|
||||
const column: ColumnDefinition = this.props.columns.find(cd => cd.guid === entityId);
|
||||
this.props.moveColumnUp(column);
|
||||
return;
|
||||
}
|
||||
private moveColumnDown(event) {
|
||||
|
||||
Log.verbose("list-Page", "Row changed-fired when row changed or leaving cell ");
|
||||
const target = this.getParent(event.target, "TD");
|
||||
const attributes: NamedNodeMap = target.attributes;
|
||||
const entityId = attributes.getNamedItem("data-entityid").value;
|
||||
const column: ColumnDefinition = this.props.columns.find(cd => cd.guid === entityId);
|
||||
this.props.moveColumnDown(column);
|
||||
return;
|
||||
}
|
||||
private handleRowdeleted(event) {
|
||||
|
||||
Log.verbose("list-Page", "Row changed-fired when row changed or leaving cell ");
|
||||
const target = this.getParent(event.target, "TD");
|
||||
const attributes: NamedNodeMap = target.attributes;
|
||||
const entityId = attributes.getNamedItem("data-entityid").value;
|
||||
const column: ColumnDefinition = this.props.columns.find(cd => cd.guid === entityId);
|
||||
this.props.removeColumn(column);
|
||||
return;
|
||||
}
|
||||
public getParent(node: Node, type: string): Node {
|
||||
while (node.nodeName !== "TD") {
|
||||
node = node.parentNode;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
public toggleEditing(event) {
|
||||
Log.verbose("list-Page", "focus event fired editing when entering cell");
|
||||
const target = this.getParent(event.target, "TD"); // walk up the Dom to the TD, thats where the IDs are stored
|
||||
const attributes: NamedNodeMap = target.attributes;
|
||||
const entityid = attributes.getNamedItem("data-entityid").value;
|
||||
const columnid = attributes.getNamedItem("data-columnid").value;
|
||||
this.setState({ "editing": { entityid: entityid, columnid: columnid } });
|
||||
}
|
||||
public CellContentsEditable(props: { entity: ColumnDefinition, gridColumn: GridColumn, cellUpdated: (newValue) => void, cellUpdatedEvent: (event: React.SyntheticEvent) => void; }): JSX.Element {
|
||||
const {entity, gridColumn, cellUpdated, cellUpdatedEvent} = props;
|
||||
if (!gridColumn.editable) {
|
||||
return (<span>
|
||||
{entity[gridColumn.name]}
|
||||
</span>);
|
||||
}
|
||||
switch (gridColumn.editor) {
|
||||
case "BooleanEditor":
|
||||
return (
|
||||
<Toggle label="" checked={entity[gridColumn.name]} onChanged={(val: boolean) => cellUpdated(val)} >
|
||||
</Toggle >
|
||||
);
|
||||
case "FieldTypesEditor":
|
||||
return (
|
||||
<Dropdown label="" selectedKey={entity[gridColumn.name]} options={fieldTypes} onChanged={(selection: IDropdownOption) => cellUpdated(selection.key)} >
|
||||
</Dropdown >
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<TextField autoFocus width={gridColumn.width}
|
||||
value={entity[gridColumn.name]}
|
||||
onChanged={cellUpdated} // this does not use eventing. It just calls the method. onChanged NOT onChange
|
||||
/>);
|
||||
}
|
||||
}
|
||||
public CellContents(props: { entity: ColumnDefinition, gridColumn: GridColumn }): JSX.Element {
|
||||
const {entity, gridColumn} = props;
|
||||
if (!gridColumn.editable) {
|
||||
return (<span>
|
||||
{entity[gridColumn.name]}
|
||||
</span>);
|
||||
}
|
||||
|
||||
switch (gridColumn.formatter) {
|
||||
|
||||
case "BooleanFormatter":
|
||||
// Does not worlk. Does not does not have onFocus
|
||||
// return (
|
||||
// <Toggle label="" checked={entity[gridColumn.name]} disabled={true} >
|
||||
// </Toggle >
|
||||
// );
|
||||
let result = (entity[gridColumn.name]) ? (<div>Yes</div>) : (<div>No</div>);
|
||||
return result;
|
||||
case "SharePointLookupCellFormatter":
|
||||
return (<SharePointLookupCellFormatter value={entity[gridColumn.name]} onFocus={this.toggleEditing} />);
|
||||
default:
|
||||
return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }}>
|
||||
{entity[gridColumn.name]}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
}
|
||||
public TableDetail(props): JSX.Element {
|
||||
const {entity, column} = props;
|
||||
if (this.state && this.state.editing && this.state.editing.entityid === entity.guid && this.state.editing.columnid === column.id && column.editable) {
|
||||
return (<td data-entityid={entity.guid} data-columnid={column.id} style={{ width: column.width, border: "1px solid red", padding: "0px" }}>
|
||||
<this.CellContentsEditable entity={entity} gridColumn={column} cellUpdated={this.handleCellUpdated} cellUpdatedEvent={this.handleCellUpdatedEvent} />
|
||||
</td>
|
||||
);
|
||||
} else {
|
||||
return (<td onClick={this.toggleEditing} data-entityid={entity.guid} data-columnid={column.id} style={{ width: column.width, border: "1px solid black", padding: "0px" }} >
|
||||
<this.CellContents key={entity.id + column.id} entity={entity} gridColumn={column} />
|
||||
</td>
|
||||
);
|
||||
}
|
||||
}
|
||||
public TableRow(props: { isFirst: boolean, isLast: boolean, entity: ColumnDefinition, columns: Array<GridColumn>, cellUpdated: (newValue) => void, cellUpdatedEvent: (event: React.SyntheticEvent) => void; }): JSX.Element {
|
||||
const {entity, columns, cellUpdated, cellUpdatedEvent, isLast, isFirst} = props;
|
||||
return (
|
||||
<tr>
|
||||
{
|
||||
columns.map(function (column) {
|
||||
return (
|
||||
<this.TableDetail key={column.id} entity={entity} column={column} cellUpdated={this.handleCellUpdated} cellUpdatedEvent={this.handleCellUpdatedEvent} />
|
||||
);
|
||||
}, this)
|
||||
}
|
||||
<td data-entityid={entity.guid} data-columnid={""} onClick={this.toggleEditing}>
|
||||
<Button
|
||||
onClick={this.handleRowdeleted}
|
||||
buttonType={ButtonType.icon}
|
||||
icon="Delete" />
|
||||
<Button
|
||||
buttonType={ButtonType.icon}
|
||||
icon="Up" disabled={isFirst}
|
||||
onClick={this.moveColumnUp} />
|
||||
<Button
|
||||
buttonType={ButtonType.icon}
|
||||
icon="Down" disabled={isLast}
|
||||
onClick={this.moveColumnDown} />
|
||||
|
||||
|
||||
</td>
|
||||
</tr>);
|
||||
};
|
||||
public TableRows(props: { entities: Array<ColumnDefinition>, columns: Array<GridColumn>, cellUpdated: (newValue) => void, cellUpdatedEvent: (event: React.SyntheticEvent) => void; }): JSX.Element {
|
||||
const {entities, columns, cellUpdated, cellUpdatedEvent} = props;
|
||||
return (
|
||||
<tbody>
|
||||
{
|
||||
entities.map(function (entity, index, all) {
|
||||
return (
|
||||
<this.TableRow isFirst={index === 0} isLast={index === all.length - 1} key={entity.guid} columns={columns} entity={entity} cellUpdated={this.handleCellUpdated} cellUpdatedEvent={this.handleCellUpdatedEvent} />
|
||||
);
|
||||
}, this)
|
||||
}
|
||||
</tbody>
|
||||
);
|
||||
}
|
||||
public render() {
|
||||
const { addColumn } = this.props;
|
||||
return (
|
||||
<Container testid="columns" size={2} center>
|
||||
<h1>Column Definitions</h1>
|
||||
<CommandBar items={[{
|
||||
key: "AddColumns",
|
||||
name: "Add a Column",
|
||||
icon: "Add",
|
||||
onClick: addColumn
|
||||
},
|
||||
{
|
||||
key: "ClearAllColums",
|
||||
name: "Remove All Columns",
|
||||
canCheck: true,
|
||||
icon: "Delete",
|
||||
onClick: this.props.removeAllColumns
|
||||
}]} />
|
||||
<table style={{ borderColor: "#600", borderWidth: "0 0 0 0", borderStyle: "solid" }}>
|
||||
<thead>
|
||||
<tr>
|
||||
{this.gridColulumns.map((column) => {
|
||||
return <th key={column.name}>{column.name}</th>;
|
||||
})}
|
||||
</tr>
|
||||
</thead>
|
||||
{
|
||||
<this.TableRows entities={this.props.columns} columns={this.gridColulumns} cellUpdated={this.handleCellUpdated} cellUpdatedEvent={this.handleCellUpdatedEvent} />
|
||||
})}
|
||||
</table>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
}
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ColumnDefinitionContainer);
|
@ -0,0 +1,472 @@
|
||||
import * as React from "react";
|
||||
import * as utils from "../utils/utils";
|
||||
const connect = require("react-redux").connect;
|
||||
import { SharePointLookupCellFormatter } from "../components/SharePointFormatters";
|
||||
import WebEditor from "../components/WebEditor";
|
||||
import ListEditor from "../components/ListEditor";
|
||||
import { addList, removeList, saveList, removeAllLists } from "../actions/listActions";
|
||||
import { getWebsAction, getListsForWebAction, getFieldsForListAction } from "../actions/SiteActions";
|
||||
import { Button, ButtonType, Dropdown, IDropdownOption, TextField, CommandBar } from "office-ui-fabric-react";
|
||||
import ListDefinition from "../model/ListDefinition";
|
||||
import { FieldDefinition } from "../model/ListDefinition";
|
||||
import { ColumnReference } from "../model/ListDefinition";
|
||||
import { Site, Web, WebList, WebListField } from "../model/Site";
|
||||
import ColumnDefinition from "../model/ColumnDefinition";
|
||||
import Container from "../components/container";
|
||||
import { Guid, Log, PageContext } from "@microsoft/sp-client-base";
|
||||
export class GridColumn {
|
||||
constructor(
|
||||
public id: string,
|
||||
public name: string,
|
||||
public title: string,
|
||||
public editable: boolean,
|
||||
public width: number,
|
||||
public type: string,
|
||||
public formatter: string = "",
|
||||
public editor?: string) { }
|
||||
}
|
||||
interface IListViewPageProps extends React.Props<any> {
|
||||
lists: Array<ListDefinition>;
|
||||
columnRefs: Array<ColumnDefinition>;
|
||||
sites: Array<Site>;
|
||||
addList: (siteUrl: string) => void;
|
||||
removeList: (List) => void;
|
||||
removeAllLists: () => void;
|
||||
saveList: (List) => void;
|
||||
getWebs: (siteUrl) => Promise<any>;
|
||||
getListsForWeb: (webUrl) => Promise<any>;
|
||||
getFieldsForList: (webUrl, listId) => Promise<any>;
|
||||
pageContext: PageContext;
|
||||
}
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
lists: state.lists,
|
||||
sites: state.sites,
|
||||
columnRefs: state.columns,
|
||||
pageContext: state.pageContext
|
||||
};
|
||||
}
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
addList: (siteUrl: string): void => {
|
||||
|
||||
const id = Guid.newGuid();
|
||||
const list: ListDefinition = new ListDefinition(id.toString(), null, null, siteUrl, null, null);
|
||||
dispatch(addList(list));
|
||||
},
|
||||
removeList: (list: ListDefinition): void => {
|
||||
dispatch(removeList(list));
|
||||
},
|
||||
removeAllLists: (): void => {
|
||||
dispatch(removeAllLists());
|
||||
},
|
||||
getWebs: (siteUrl): Promise<any> => {
|
||||
return dispatch(getWebsAction(dispatch, siteUrl));
|
||||
},
|
||||
getListsForWeb(webUrl): Promise<any> {
|
||||
return dispatch(getListsForWebAction(dispatch, webUrl));
|
||||
},
|
||||
getFieldsForList(webUrl, listId): Promise<any> {
|
||||
return dispatch(getFieldsForListAction(dispatch, webUrl, listId));
|
||||
},
|
||||
saveList: (list): void => {
|
||||
const action = saveList(list);
|
||||
dispatch(action);
|
||||
},
|
||||
};
|
||||
}
|
||||
interface IGridProps {
|
||||
editing: {
|
||||
entityid: string;
|
||||
columnid: string;
|
||||
};
|
||||
}
|
||||
class ListDefinitionContainer extends React.Component<IListViewPageProps, IGridProps> {
|
||||
public defaultColumns: Array<GridColumn> = [
|
||||
{
|
||||
id: "rowGuid",
|
||||
name: "guid",
|
||||
title: "List Definition ID",
|
||||
editable: false,
|
||||
width: 250,
|
||||
formatter: "",
|
||||
type: "Text"
|
||||
},
|
||||
{
|
||||
id: "SiteUrl",
|
||||
name: "siteUrl", // the url to the site
|
||||
title: "SiteUrl",
|
||||
editable: true,
|
||||
width: 359,
|
||||
formatter: "",
|
||||
type: "Text"
|
||||
},
|
||||
{
|
||||
id: "listDefTitle",
|
||||
name: "listDefTitle",
|
||||
title: "List Definition Title",
|
||||
editable: true,
|
||||
width: 100,
|
||||
formatter: "",
|
||||
type: "Text"
|
||||
},
|
||||
{
|
||||
id: "WebLookup",
|
||||
name: "webLookup", // the name of the field in the model
|
||||
title: "Web Containing List",
|
||||
editable: true,
|
||||
width: 300,
|
||||
editor: "WebEditor",
|
||||
formatter: "SharePointLookupCellFormatter",
|
||||
type: "Lookup"
|
||||
},
|
||||
{
|
||||
id: "listlookup",
|
||||
width: 300,
|
||||
name: "listLookup",
|
||||
title: "List",
|
||||
editable: true,
|
||||
editor: "ListEditor",
|
||||
formatter: "SharePointLookupCellFormatter",
|
||||
type: "Lookup"
|
||||
}];
|
||||
public extendedColumns: Array<GridColumn> = [];
|
||||
public constructor() {
|
||||
super();
|
||||
|
||||
this.getWebsForSite = this.getWebsForSite.bind(this);
|
||||
this.getListsForWeb = this.getListsForWeb.bind(this);
|
||||
this.getFieldsForlist = this.getFieldsForlist.bind(this);
|
||||
this.getFieldDefinition = this.getFieldDefinition.bind(this);
|
||||
|
||||
this.CellContentsEditable = this.CellContentsEditable.bind(this);
|
||||
this.CellContents = this.CellContents.bind(this);
|
||||
this.TableDetail = this.TableDetail.bind(this);
|
||||
this.TableRow = this.TableRow.bind(this);
|
||||
this.TableRows = this.TableRows.bind(this);
|
||||
this.toggleEditing = this.toggleEditing.bind(this);
|
||||
this.handleCellUpdated = this.handleCellUpdated.bind(this);
|
||||
this.handleCellUpdatedEvent = this.handleCellUpdatedEvent.bind(this);
|
||||
this.deleteList = this.deleteList.bind(this);
|
||||
this.addList = this.addList.bind(this);
|
||||
|
||||
}
|
||||
public componentWillMount(): void {
|
||||
if (this.props.sites.length === 0) {
|
||||
// prload current site, assuming user wants lists from current site
|
||||
// this.props.getWebs(this.props.pageContext.site.absoluteUrl);
|
||||
}
|
||||
this.extendedColumns = _.clone(this.defaultColumns);
|
||||
for (const columnRef of this.props.columnRefs) {
|
||||
|
||||
const newCol = new GridColumn(columnRef.guid, columnRef.name, columnRef.name, columnRef.editable, columnRef.width, columnRef.type, "FieldFormatter", "FieldEditor");
|
||||
this.extendedColumns.push(newCol);
|
||||
}
|
||||
}
|
||||
private isdeafaultColumn(columnid): boolean {
|
||||
for (const col of this.defaultColumns) {
|
||||
if (col.id === columnid) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private updateExtendedColumn(entity: ListDefinition, columnid: string, value: any) {
|
||||
const internalName = utils.ParseSPField(value).id;
|
||||
const fieldDefinition: FieldDefinition = this.getFieldDefinition(entity, internalName); // values is the fueld just selected.... get the definition for it
|
||||
for (const col of entity.columnReferences) {
|
||||
if (col.columnDefinitionId === columnid) {
|
||||
col.name = value;
|
||||
col.fieldDefinition = fieldDefinition;
|
||||
return;
|
||||
}
|
||||
}
|
||||
const x = new ColumnReference(columnid, value, fieldDefinition);
|
||||
entity.columnReferences.push(x);
|
||||
}
|
||||
public getFieldDefinition(listdef: ListDefinition, internalName: string): FieldDefinition {
|
||||
const field = this.getFieldInList(listdef, internalName);
|
||||
return field.fieldDefinition;
|
||||
}
|
||||
private handleCellUpdatedEvent(event) { //native react uses a Synthetic event
|
||||
this.handleCellUpdated(event.target.value);
|
||||
}
|
||||
private handleCellUpdated(value) { // Office UI Fabric does not use events. It just calls this method with the new value
|
||||
const {entityid, columnid} = this.state.editing;
|
||||
const entity: ListDefinition = this.props.lists.find((temp) => temp.guid === entityid);
|
||||
const column = this.extendedColumns.find(temp => temp.id === columnid);
|
||||
// if it is a default column, just set its value , otheriwse update it in the list of extended columns (i.e. sharepoint columns)
|
||||
if (this.isdeafaultColumn(columnid)) {
|
||||
/** need to save the web url if the web column was updated
|
||||
* Sharepoint rest wont let me go from an SPSite to an SPWeb using just the id. Need tis
|
||||
* I need the url to the Web.
|
||||
* hmmmm... can i construct it (dont store the Id of the we, store the path instead?)
|
||||
* need this for lookup columns.. they only stote a weid and list id...ohhhh noooo
|
||||
*/
|
||||
|
||||
entity[column.name] = value;
|
||||
|
||||
}
|
||||
else {
|
||||
this.updateExtendedColumn(entity, columnid, value);
|
||||
}
|
||||
this.props.saveList(entity);
|
||||
}
|
||||
|
||||
public addList(event): any {
|
||||
this.props.addList(this.props.pageContext.site.absoluteUrl);
|
||||
return;
|
||||
}
|
||||
public deleteList(event) {
|
||||
Log.verbose("list-Page", "Row changed-fired when row changed or leaving cell ");
|
||||
const target = this.getParent(event.target, "TD");
|
||||
const attributes: NamedNodeMap = target.attributes;
|
||||
const entity = attributes.getNamedItem("data-entityid").value;
|
||||
const list: ListDefinition = this.props.lists.find(temp => temp.guid === entity);
|
||||
this.props.removeList(list);
|
||||
return;
|
||||
}
|
||||
public getParent(node: Node, type: string): Node {
|
||||
while (node.nodeName !== "TD") {
|
||||
node = node.parentNode;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
public getWebsForSite(listDef: ListDefinition): Array<Web> {
|
||||
|
||||
for (const site of this.props.sites) {
|
||||
if (site.url === listDef.siteUrl) {
|
||||
return site.webs;
|
||||
}
|
||||
}
|
||||
// not in our cache/ go get it
|
||||
|
||||
this.props.getWebs(listDef.siteUrl);
|
||||
return [];
|
||||
}
|
||||
public getListsForWeb(listDef: ListDefinition): Array<WebList> {
|
||||
const webs = this.getWebsForSite(listDef);
|
||||
for (const web of webs) {
|
||||
if (web.url === utils.ParseSPField(listDef.webLookup).id) {
|
||||
if (web.listsFetched) {
|
||||
return web.lists;
|
||||
}
|
||||
else {
|
||||
this.props.getListsForWeb(utils.ParseSPField(listDef.webLookup).id);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
return []; // havent fetched parent yet,
|
||||
}
|
||||
public getFieldsForlist(listDef: ListDefinition, colType?: string): Array<WebListField> {
|
||||
const lists = this.getListsForWeb(listDef);
|
||||
|
||||
for (const list of lists) {
|
||||
if (list.id === utils.ParseSPField(listDef.listLookup).id) {
|
||||
if (list.fieldsFetched) {
|
||||
if (colType === undefined || colType === null) {
|
||||
return list.fields;
|
||||
} else {
|
||||
return _.filter(list.fields, (f) => f.fieldDefinition.TypeAsString === colType);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.props.getFieldsForList(utils.ParseSPField(listDef.webLookup).id, utils.ParseSPField(listDef.listLookup).id);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
return [];// havent fetched parent yet,
|
||||
|
||||
}
|
||||
/** This method is called just before we ara going to save a field in our listdef. It gets the Field Deefinition from sharepoint. */
|
||||
public getFieldInList(listDef: ListDefinition, internalName): WebListField {
|
||||
|
||||
const fields = this.getFieldsForlist(listDef);
|
||||
for (const field of fields) {
|
||||
if (utils.ParseSPField(field.name).id === internalName) {
|
||||
return field;
|
||||
}
|
||||
}
|
||||
}
|
||||
public GetColumnReferenence(listDefinition: ListDefinition, columnDefinitionId: string): ColumnReference {
|
||||
for (const columnref of listDefinition.columnReferences) {
|
||||
if (columnref.columnDefinitionId === columnDefinitionId) {
|
||||
return columnref;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public toggleEditing(event) {
|
||||
Log.verbose("list-Page", "focus event fired editing when entering cell");
|
||||
|
||||
const target = this.getParent(event.target, "TD"); // walk up the Dom to the TD, thats where the IDs are stored
|
||||
const attributes: NamedNodeMap = target.attributes;
|
||||
const entityid = attributes.getNamedItem("data-entityid").value;
|
||||
const columnid = attributes.getNamedItem("data-columnid").value;
|
||||
this.setState({ "editing": { entityid: entityid, columnid: columnid } });
|
||||
}
|
||||
public CellContentsEditable(props: { entity: ListDefinition, column: GridColumn, cellUpdated: (newValue) => void, cellUpdatedEvent: (event: React.SyntheticEvent) => void; }): JSX.Element {
|
||||
const {entity, column, cellUpdated, cellUpdatedEvent} = props;
|
||||
let columnValue;
|
||||
if (this.isdeafaultColumn(column.id)) {
|
||||
columnValue = entity[column.name];
|
||||
}
|
||||
else {
|
||||
|
||||
const colRef: ColumnReference = this.GetColumnReferenence(entity, column.id);
|
||||
if (colRef) {
|
||||
columnValue = this.GetColumnReferenence(entity, column.id).name;
|
||||
}
|
||||
}
|
||||
|
||||
switch (column.editor) {
|
||||
|
||||
case "WebEditor":
|
||||
let webs = this.getWebsForSite(entity);
|
||||
return (<WebEditor webs={webs} selectedValue={columnValue} onChange={cellUpdated} />);
|
||||
case "ListEditor":
|
||||
let lists = this.getListsForWeb(entity);// the Id portion of the WebLookup is the URL
|
||||
return (<ListEditor selectedValue={columnValue} onChange={cellUpdated} lists={lists} />);
|
||||
case "FieldEditor":
|
||||
const colType = column.type;
|
||||
let fields: Array<IDropdownOption> = this.getFieldsForlist(entity, colType).map(fld => {
|
||||
|
||||
return { key: fld.name, text: utils.ParseSPField(fld.name).value };
|
||||
});
|
||||
fields.unshift({ key: null, text: "(Select one)" });
|
||||
return (<Dropdown options={fields} label="" selectedKey={columnValue} onChanged={(selection: IDropdownOption) => cellUpdated(selection.key)} />);
|
||||
default:
|
||||
|
||||
return (
|
||||
<TextField autoFocus width={column.width}
|
||||
value={entity[column.name]}
|
||||
onChanged={cellUpdated} />);
|
||||
}
|
||||
}
|
||||
public CellContents(props: { entity: ListDefinition, column: GridColumn }): JSX.Element {
|
||||
const {entity, column} = props;
|
||||
switch (column.formatter) {
|
||||
case "SharePointLookupCellFormatter":
|
||||
return (<SharePointLookupCellFormatter value={entity[column.name]} onFocus={this.toggleEditing} />);
|
||||
default:
|
||||
|
||||
if (this.isdeafaultColumn(column.id)) {
|
||||
return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }}>
|
||||
{entity[column.name]}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
else {
|
||||
const colref = entity.columnReferences.find(cr => cr.columnDefinitionId === column.id);
|
||||
let displaytext = "";
|
||||
if (colref != null) {
|
||||
displaytext = utils.ParseSPField(colref.name).value;
|
||||
}
|
||||
return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }}>
|
||||
{displaytext}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TableDetail(props: { entity: ListDefinition, column: GridColumn, cellUpdated: (newValue) => void, cellUpdatedEvent: (event: React.SyntheticEvent) => void; }): JSX.Element {
|
||||
const {entity, column, cellUpdated, cellUpdatedEvent} = props;
|
||||
|
||||
if (this.state && this.state.editing && this.state.editing.entityid === entity.guid && this.state.editing.columnid === column.id) {
|
||||
return (<td data-entityid={entity.guid} data-columnid={column.id} style={{ width: column.width, border: "1px solid red", padding: "0px" }}>
|
||||
<this.CellContentsEditable entity={entity} column={column} cellUpdated={this.handleCellUpdated} cellUpdatedEvent={this.handleCellUpdatedEvent} />
|
||||
</td>
|
||||
);
|
||||
} else {
|
||||
return (<td data-entityid={entity.guid} data-columnid={column.id} style={{ width: column.width, border: "1px solid black", padding: "0px" }} onClick={this.toggleEditing} >
|
||||
<this.CellContents entity={entity} column={column} />
|
||||
</td>
|
||||
);
|
||||
}
|
||||
}
|
||||
public TableRow(props: { entity: ListDefinition, columns: Array<GridColumn>, cellUpdated: (newValue) => void, cellUpdatedEvent: (event: React.SyntheticEvent) => void; }): JSX.Element {
|
||||
const {entity, columns, cellUpdated, cellUpdatedEvent} = props;
|
||||
debugger;
|
||||
return (
|
||||
<tr>
|
||||
{
|
||||
columns.filter(c => c.type !== "__LISTDEFINITIONTITLE__").map(function (column) {
|
||||
return (
|
||||
<this.TableDetail key={column.id} entity={entity} column={column} cellUpdated={this.handleCellUpdated} cellUpdatedEvent={this.handleCellUpdatedEvent} />
|
||||
);
|
||||
}, this)
|
||||
}
|
||||
<td data-entityid={entity.guid} data-columnid={""}>
|
||||
<Button
|
||||
onClick={this.deleteList}
|
||||
buttonType={ButtonType.icon}
|
||||
icon="Delete" />
|
||||
|
||||
</td>
|
||||
</tr>);
|
||||
};
|
||||
public TableRows(props: { entities: Array<ListDefinition>, columns: Array<GridColumn>, cellUpdated: (newValue) => void, cellUpdatedEvent: (event: React.SyntheticEvent) => void; }): JSX.Element {
|
||||
const {entities, columns, cellUpdated, cellUpdatedEvent} = props;
|
||||
return (
|
||||
<tbody>
|
||||
{
|
||||
entities.map(function (list) {
|
||||
return (
|
||||
<this.TableRow key={list.guid} entity={list} columns={columns} cellUpdated={this.handleCellUpdated} cellUpdatedEvent={this.handleCellUpdatedEvent} />
|
||||
);
|
||||
}, this)
|
||||
}
|
||||
</tbody>
|
||||
);
|
||||
}
|
||||
|
||||
public render() {
|
||||
debugger;
|
||||
return (
|
||||
<Container testid="columns" size={2} center>
|
||||
<h1>List Definitions</h1>
|
||||
|
||||
<CommandBar items={[{
|
||||
key: "Add LIST",
|
||||
name: "Add a List",
|
||||
icon: "Add",
|
||||
onClick: this.addList
|
||||
},
|
||||
{
|
||||
key: "Clear All Lists",
|
||||
name: "Remove All Lists",
|
||||
icon: "Delete",
|
||||
onClick: this.props.removeAllLists
|
||||
},
|
||||
{
|
||||
key: "Allow All Types ",
|
||||
name: "Allow All Types ",
|
||||
canCheck: true,
|
||||
isChecked: true,
|
||||
icon: "ClearFilter"
|
||||
|
||||
}]} />
|
||||
|
||||
<table border="1">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
{this.extendedColumns.filter(c => c.type !== "__LISTDEFINITIONTITLE__").map((column) => {
|
||||
return <th key={column.name}>{column.title}</th>;
|
||||
})}
|
||||
</tr>
|
||||
</thead>
|
||||
{
|
||||
<this.TableRows entities={this.props.lists} columns={this.extendedColumns} cellUpdated={this.handleCellUpdated} cellUpdatedEvent={this.handleCellUpdatedEvent} />
|
||||
|
||||
})}
|
||||
</table>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ListDefinitionContainer);
|
@ -0,0 +1,826 @@
|
||||
import * as utils from "../utils/utils";
|
||||
import * as React from "react";
|
||||
|
||||
const connect = require("react-redux").connect;
|
||||
import {
|
||||
addListItem, removeListItem, getListItemsAction, saveListItemAction,
|
||||
undoListItemChangesAction, updateListItemAction,
|
||||
} from "../actions/listItemActions";
|
||||
import { getLookupOptionAction } from "../actions/lookupOptionsActions";
|
||||
import { getSiteUsersAction } from "../actions/siteUsersActions";
|
||||
import ListItem from "../model/ListItem";
|
||||
import ColumnDefinition from "../model/ColumnDefinition";
|
||||
import { LookupOptions, LookupOptionStatus } from "../model/LookupOptions";
|
||||
import { SiteUsers, SiteUsersStatus } from "../model/SiteUsers";
|
||||
import GridRowStatus from "../model/GridRowStatus";
|
||||
import ListDefinition from "../model/ListDefinition";
|
||||
import { Button, ButtonType, TextField, IDropdownOption, Dropdown, Spinner, SpinnerType } from "office-ui-fabric-react";
|
||||
|
||||
import { CommandBar } from "office-ui-fabric-react/lib/CommandBar";
|
||||
import { DatePicker, IDatePickerStrings } from "office-ui-fabric-react/lib/DatePicker";
|
||||
|
||||
import Container from "../components/container";
|
||||
import { Log } from "@microsoft/sp-client-base";
|
||||
|
||||
interface IListViewPageProps extends React.Props<any> {
|
||||
/** An array of ListItems fetched from sharepoint */
|
||||
siteUsers: Array<SiteUsers>;
|
||||
/** An array of ListItems fetched from sharepoint */
|
||||
listItems: Array<ListItem>;
|
||||
/** An array of LookupOptions. One for each Lookup Column */
|
||||
lookupOptions: Array<LookupOptions>;
|
||||
/** An array of columns to be displayed on the grid */
|
||||
columns: Array<ColumnDefinition>;
|
||||
/** The listDefinitions. Says which lists to pull data from */
|
||||
listDefinitions: Array<ListDefinition>;
|
||||
/** Redux Action to add a new listitem */
|
||||
addListItem: (ListItem) => void;
|
||||
/** Redux Action to add a new remove a list item */
|
||||
removeListItem: (l: ListItem, ListDef: ListDefinition) => void;
|
||||
/** Redux Action to get listitems from a specific list */
|
||||
getListItems: (listDefinitions: Array<ListDefinition>) => void;
|
||||
/** Redux Action to update a listitem in sharepoint */
|
||||
updateListItem: (ListItem: ListItem, ListDef: ListDefinition) => Promise<any>;
|
||||
/** Redux Action to get the lookup options for a specific field */
|
||||
getLookupOptionAction: (lookupSite, lookupWebId, lookupListId, lookupField) => void;
|
||||
/** Redux Action to get the lookup options for a specific field */
|
||||
getSiteUsersAction: (site) => Promise<any>;
|
||||
/** Redux Action to undo changes made to the listitem */
|
||||
undoItemChanges: (ListItem) => void;
|
||||
/** Redux Action to save the listitem in the store (NOT to sharepoint*/
|
||||
saveListItem: (ListItem) => void;
|
||||
}
|
||||
function mapStateToProps(state) {
|
||||
|
||||
return {
|
||||
listItems: state.items,
|
||||
columns: state.columns,
|
||||
listDefinitions: state.lists,
|
||||
systemStatus: state.systemStatus,
|
||||
lookupOptions: state.lookupOptions,
|
||||
siteUsers: state.siteUsers
|
||||
};
|
||||
}
|
||||
export class GridColumn {
|
||||
constructor(
|
||||
public id: string,
|
||||
public name: string,
|
||||
public editable: boolean,
|
||||
public width: number,
|
||||
public formatter: string = "",
|
||||
public editor?: string) { }
|
||||
}
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
addListItem: (listItem: ListItem): void => {
|
||||
dispatch(addListItem(listItem));
|
||||
},
|
||||
removeListItem: (listItem: ListItem, listDef: ListDefinition): void => {
|
||||
dispatch(removeListItem(dispatch, listItem, listDef));
|
||||
},
|
||||
updateListItem: (listItem: ListItem, listDef: ListDefinition): Promise<any> => {
|
||||
const action = updateListItemAction(dispatch, listDef, listItem);
|
||||
dispatch(action); // need to ewname this one to be digfferent from the omported ome
|
||||
return action.payload.promise;
|
||||
|
||||
},
|
||||
saveListItem: (listItem: ListItem): void => {
|
||||
dispatch(saveListItemAction(listItem));
|
||||
},
|
||||
undoItemChanges: (listItem: ListItem): void => {
|
||||
dispatch(undoListItemChangesAction(listItem));
|
||||
},
|
||||
|
||||
getListItems: (listDefinitions: Array<ListDefinition>): void => {
|
||||
dispatch(getListItemsAction(dispatch, listDefinitions));
|
||||
},
|
||||
getLookupOptionAction: (lookupSite, lookupWebId, lookupListId, lookupField): void => {
|
||||
dispatch(getLookupOptionAction(dispatch, lookupSite, lookupWebId, lookupListId, lookupField));
|
||||
},
|
||||
getSiteUsersAction: (site): void => {
|
||||
|
||||
const action = getSiteUsersAction(dispatch, site);
|
||||
dispatch(action);
|
||||
return action.payload.promise;
|
||||
},
|
||||
};
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
interface IGridState {
|
||||
editing: {
|
||||
/**The Sharepoint GUID of the listitem being edited */
|
||||
entityid: string;
|
||||
/**The id of the column being edited */
|
||||
columnid: string;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* This component is the Grid for editing listitems.
|
||||
*/
|
||||
class ListItemContainer extends React.Component<IListViewPageProps, IGridState> {
|
||||
public constructor() {
|
||||
super();
|
||||
this.CellContentsEditable = this.CellContentsEditable.bind(this);
|
||||
this.CellContents = this.CellContents.bind(this);
|
||||
this.TableDetail = this.TableDetail.bind(this);
|
||||
this.TableRow = this.TableRow.bind(this);
|
||||
this.TableRows = this.TableRows.bind(this);
|
||||
this.toggleEditing = this.toggleEditing.bind(this);
|
||||
this.addListItem = this.addListItem.bind(this);
|
||||
this.removeListItem = this.removeListItem.bind(this);
|
||||
this.handleCellUpdated = this.handleCellUpdated.bind(this);
|
||||
this.handleCellUpdatedEvent = this.handleCellUpdatedEvent.bind(this);
|
||||
this.undoItemChanges = this.undoItemChanges.bind(this);
|
||||
this.updateListItem = this.updateListItem.bind(this);
|
||||
this.getLookupOptions = this.getLookupOptions.bind(this);
|
||||
|
||||
}
|
||||
private addListItem(): void {
|
||||
|
||||
let listItem = new ListItem();
|
||||
for (const column of this.props.columns) {
|
||||
listItem[column.name] = null;
|
||||
}
|
||||
if (this.props.listDefinitions.length === 1) {
|
||||
listItem.__metadata__ListDefinitionId = this.props.listDefinitions[0].guid;
|
||||
} else {
|
||||
listItem.__metadata__ListDefinitionId = null;
|
||||
}
|
||||
|
||||
this.props.addListItem(listItem);
|
||||
}
|
||||
private removeListItem(event): void {
|
||||
|
||||
const parentTD = this.getParent(event.target, "TD");
|
||||
const attributes: NamedNodeMap = parentTD.attributes;
|
||||
const entityid = attributes.getNamedItem("data-entityid").value; // theid of the SPListItem
|
||||
const listItem: ListItem = this.props.listItems.find((temp) => temp.GUID === entityid); // the listItemItself
|
||||
const listDef = this.getListDefinition(listItem.__metadata__ListDefinitionId);// The list Definition this item is associated with.
|
||||
this.props.removeListItem(listItem, listDef);
|
||||
}
|
||||
/**
|
||||
* When the component Mounts, call an action to get the listitems for all the listdefinitions
|
||||
*/
|
||||
public componentWillMount() {
|
||||
|
||||
this.props.getListItems(this.props.listDefinitions);
|
||||
}
|
||||
/**
|
||||
* Method to get the parent TD of any cell,
|
||||
* The listItemId and columnID are stored as attributes of the cells parent TD.
|
||||
*/
|
||||
public getParent(node: Node, type: string): Node {
|
||||
while (node.nodeName !== "TD") {
|
||||
node = node.parentNode;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
/**
|
||||
* This event gets fired whenever a cell on the grid recieves focus.
|
||||
* The "editing" propery of this component determines which cell is being edited.
|
||||
* This method gets the clicked on (the entityid-- the id of the SPLIstItem) and the columnId (the id of the ColumnDefinition)
|
||||
* and sets them in the "editing"property of state.
|
||||
* When Component then redraws, it draws that cell as an editable (See the TableDetail method).
|
||||
*
|
||||
* If the rendering of that column in edit mode requires additional Info, dispatch a redux action to get the data.
|
||||
* (Dispatching the action from within the render mehod itself cused infinite loop)
|
||||
*
|
||||
*/
|
||||
public toggleEditing(event) {
|
||||
Log.verbose("list-Page", "focus event fired editing when entering cell");
|
||||
const target = this.getParent(event.target, "TD"); // walk up the Dom to the TD, thats where the IDs are stored
|
||||
const attributes: NamedNodeMap = target.attributes;
|
||||
const entityid = attributes.getNamedItem("data-entityid").value;
|
||||
const columnid = attributes.getNamedItem("data-columnid").value;
|
||||
if (columnid != "") { //user clicked on a column, not a button( Buttons are in a td with am column id of ""
|
||||
/**
|
||||
* Need to fire events here to get data needed for the rerender
|
||||
*/
|
||||
const listitem = this.props.listItems.find(li => li.GUID === entityid);
|
||||
const listDef = this.getListDefinition(listitem.__metadata__ListDefinitionId);
|
||||
if (listDef) {// if user just added an item we may not hava a lisdef yest
|
||||
const colref = listDef.columnReferences.find(cr => cr.columnDefinitionId === columnid);
|
||||
if (colref) {// Listname does not have a columnReference
|
||||
|
||||
switch (colref.fieldDefinition.TypeAsString) {
|
||||
case "Lookup":
|
||||
let lookupField = colref.fieldDefinition.LookupField;
|
||||
let lookupListId = colref.fieldDefinition.LookupList;
|
||||
let lookupWebId = colref.fieldDefinition.LookupWebId;
|
||||
/**
|
||||
* We are assuming here that the lookup listy is in the same web.
|
||||
*
|
||||
*/
|
||||
lookupWebId = utils.ParseSPField(listDef.webLookup).id; // temp fix. Need to use graph to get the web by id in the site
|
||||
let lookupSite = listDef.siteUrl;
|
||||
this.ensureLookupOptions(lookupSite, lookupWebId, lookupListId, lookupField);
|
||||
break;
|
||||
case "User":
|
||||
|
||||
lookupWebId = utils.ParseSPField(listDef.webLookup).id; // temp fix. Need to use graph to get the web by id in the site
|
||||
let site = listDef.siteUrl;
|
||||
this.ensureSiteUsers(site);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.setState({ "editing": { entityid: entityid, columnid: columnid } });
|
||||
}
|
||||
/**
|
||||
* This event gets fired to revert any changes made to the ListItem.
|
||||
*/
|
||||
public undoItemChanges(event): void {
|
||||
const parentTD = this.getParent(event.target, "TD"); // the listitemId and the column ID are always stored as attributes of the parent TD.
|
||||
const attributes: NamedNodeMap = parentTD.attributes;
|
||||
const entityitem = attributes.getNamedItem("data-entityid");
|
||||
const entityid = entityitem.value;
|
||||
const entity: ListItem = this.props.listItems.find((temp) => temp.GUID === entityid);
|
||||
this.props.undoItemChanges(entity);
|
||||
}
|
||||
/**
|
||||
* This event gets fired, to save the item back to SharePoint.
|
||||
*/
|
||||
public updateListItem(event): void {
|
||||
|
||||
const parentTD = this.getParent(event.target, "TD");
|
||||
const attributes: NamedNodeMap = parentTD.attributes;
|
||||
const entityid = attributes.getNamedItem("data-entityid").value; // theid of the SPListItem
|
||||
const entity: ListItem = this.props.listItems.find((temp) => temp.GUID === entityid);
|
||||
const listDef: ListDefinition = this.getListDefinition(entity.__metadata__ListDefinitionId);
|
||||
if (entity.__metadata__ListDefinitionId === entity.__metadata__OriginalValues.__metadata__ListDefinitionId
|
||||
|| entity.__metadata__GridRowStatus === GridRowStatus.new) {// List not changed
|
||||
|
||||
this.props.updateListItem(entity, listDef);
|
||||
}
|
||||
else {// list changed, add to new, delete from old (will need to do some fiorld mapping in here
|
||||
entity.__metadata__GridRowStatus = GridRowStatus.new;
|
||||
this.props.updateListItem(entity, listDef).then(response => {
|
||||
const oldListDef: ListDefinition = this.getListDefinition(entity.__metadata__OriginalValues.__metadata__ListDefinitionId);
|
||||
this.props.removeListItem(entity.__metadata__OriginalValues, oldListDef);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* This method gets called when react events are used to update a cell in the grid.
|
||||
* It just gets the value and passes it to handleCellUpdated.
|
||||
*/
|
||||
private handleCellUpdatedEvent(event) { //native react uses a Synthetic event
|
||||
this.handleCellUpdated(event.target.value);
|
||||
|
||||
}
|
||||
/**
|
||||
* This method gets called when user changes the listdefinition for an item.
|
||||
* the old fields are moved to the corresponing new fields and translated as needed
|
||||
*/
|
||||
private mapOldListFieldsToNewListFields(listItem: ListItem) {
|
||||
|
||||
const newListDef = this.getListDefinition(listItem.__metadata__ListDefinitionId);
|
||||
const oldListDef = this.getListDefinition(listItem.__metadata__OriginalValues.__metadata__ListDefinitionId);
|
||||
for (const newColRef of newListDef.columnReferences) {
|
||||
// find the old columnReference
|
||||
const oldColRef = oldListDef.columnReferences.find(cr => cr.columnDefinitionId === newColRef.columnDefinitionId);
|
||||
const newFieldName = utils.ParseSPField(newColRef.name).id;
|
||||
const oldFieldName = utils.ParseSPField(oldColRef.name).id;
|
||||
switch (newColRef.fieldDefinition.TypeAsString) {
|
||||
case "User":
|
||||
// should male a local copy befor i start messing with these.// fieldd names may overlap on old and new
|
||||
// const name = listItem.__metadata__OriginalValues[oldFieldName].Name;// the user login name
|
||||
const name = listItem[oldFieldName].Name;// the user login name
|
||||
const siteUsersOnNewSite = this.props.siteUsers.find(su => su.siteUrl === newListDef.siteUrl);
|
||||
const newUser = siteUsersOnNewSite.siteUser.find(user => user.loginName === name);
|
||||
if (newUser) {
|
||||
listItem[newFieldName].Id = newUser.id;
|
||||
listItem[newFieldName].Name = newUser.loginName;
|
||||
listItem[newFieldName].Title = newUser.value;
|
||||
}
|
||||
else {
|
||||
delete listItem[newFieldName];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
listItem[newFieldName] = listItem[oldFieldName];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This method gets called when react cells in the gid get updated.
|
||||
* Office UI Fabric does not use events. It just calls this method with the new value.
|
||||
* It reformats the data to fit the format we recievbed from SP in the first place ,
|
||||
* and dispatches an action to save the data in the store.
|
||||
*
|
||||
* Also, it saves the original version of the record, so we can undo later.
|
||||
*/
|
||||
private handleCellUpdated(value) {
|
||||
|
||||
const {entityid, columnid} = this.state.editing;
|
||||
const entity: ListItem = this.props.listItems.find((temp) => temp.GUID === entityid);
|
||||
const listDef = this.getListDefinition(entity.__metadata__ListDefinitionId);
|
||||
const titlecolumnid = this.props.columns.find(c => { return c.type === "__LISTDEFINITIONTITLE__"; }).guid;
|
||||
if (columnid === titlecolumnid) { // user just changed the listDef,
|
||||
|
||||
if (entity.__metadata__GridRowStatus === GridRowStatus.pristine) {
|
||||
if (!entity.__metadata__OriginalValues) { //SAVE orgininal values so we can undo;
|
||||
entity.__metadata__OriginalValues = _.cloneDeep(entity); // need deep if we have lookup values
|
||||
}
|
||||
}
|
||||
entity.__metadata__ListDefinitionId = value.key; // value is a DropDDownOptions
|
||||
if (entity.__metadata__GridRowStatus !== GridRowStatus.new) {
|
||||
const newListDef = this.getListDefinition(value.key);
|
||||
this.props.getSiteUsersAction(newListDef.siteUrl).then(r => {
|
||||
this.mapOldListFieldsToNewListFields(entity);
|
||||
this.props.saveListItem(entity);
|
||||
});
|
||||
} else {
|
||||
this.props.saveListItem(entity);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const columnReference = listDef.columnReferences.find(cr => cr.columnDefinitionId === columnid);
|
||||
const internalName = utils.ParseSPField(columnReference.name).id;
|
||||
if (!entity.__metadata__OriginalValues) { //SAVE orgininal values so we can undo;
|
||||
entity.__metadata__OriginalValues = _.cloneDeep(entity); // need deep if we have lookup values
|
||||
}
|
||||
if (entity.__metadata__GridRowStatus === GridRowStatus.pristine) {
|
||||
entity.__metadata__GridRowStatus = GridRowStatus.modified;
|
||||
}
|
||||
switch (columnReference.fieldDefinition.TypeAsString) {
|
||||
case "User":
|
||||
if (!entity[internalName]) {// if value was not previously set , then this is undefined//
|
||||
entity[internalName] = {};// set new value to an empty objecte
|
||||
}
|
||||
entity[internalName].Id = value.key;//and then fill in the values
|
||||
entity[internalName].Title = value.text;
|
||||
break;
|
||||
case "Choice":
|
||||
entity[internalName] = value.text;
|
||||
break;
|
||||
case "DateTime":
|
||||
|
||||
entity[internalName] = (value.getFullYear().toString()) + "-" + (value.getMonth() + 1).toString() + "-" + value.getDate().toString() + "T00:00:00Z";
|
||||
break;
|
||||
case "Lookup":
|
||||
if (!entity[internalName]) {// if value was not previously set , then this is undefined//
|
||||
entity[internalName] = {};// set new value to an empty objecte
|
||||
}
|
||||
entity[internalName]["Id"] = value.key;//and then fill in the values
|
||||
entity[internalName][columnReference.fieldDefinition.LookupField] = value.text;
|
||||
break;
|
||||
default:
|
||||
entity[internalName] = value;
|
||||
}
|
||||
this.props.saveListItem(entity);
|
||||
}
|
||||
/**
|
||||
* If the the options for a lookup list are not in the cache, fire an event to get them
|
||||
* This method is called when a lookup column receives focus.
|
||||
*/
|
||||
public ensureSiteUsers(siteUrl: string): SiteUsers {
|
||||
// see if the options are in the store, if so, return them, otherwoise dispatch an action to get them
|
||||
const siteUsers = this.props.siteUsers.find(x => {
|
||||
return (x.siteUrl === siteUrl);
|
||||
});
|
||||
if (siteUsers === undefined) {
|
||||
this.props.getSiteUsersAction(siteUrl);
|
||||
}
|
||||
return siteUsers;
|
||||
}
|
||||
/**
|
||||
* Gets the options to display for a lookupField
|
||||
* This method is called when a lookup column gets rendered... we fire the event to get the data when its focused,
|
||||
* then we use the data when it gets renderd
|
||||
*/
|
||||
public getSiteUsers(siteUrl: string): SiteUsers {
|
||||
// see if the options are in the store, if so, return them, otherwoise dispatch an action to get them
|
||||
const siteUsers = this.props.siteUsers.find(x => {
|
||||
return (x.siteUrl === siteUrl);
|
||||
});
|
||||
return siteUsers;
|
||||
}
|
||||
/**
|
||||
* If the the options for a lookup list are not in the cache, fire an event to get them
|
||||
* This method is called when a lookup column receives focus.
|
||||
*/
|
||||
public ensureLookupOptions(lookupSite: string, lookupWebId: string, lookupListId: string, lookupField: string): LookupOptions {
|
||||
// see if the options are in the store, if so, return them, otherwoise dispatch an action to get them
|
||||
const lookupoptions = this.props.lookupOptions.find(x => {
|
||||
return (x.lookupField === lookupField) &&
|
||||
(x.lookupListId === lookupListId) &&
|
||||
(x.lookupSite === lookupSite) &&
|
||||
(x.lookupWebId === lookupWebId);
|
||||
});
|
||||
if (lookupoptions === undefined) {
|
||||
this.props.getLookupOptionAction(lookupSite, lookupWebId, lookupListId, lookupField);
|
||||
}
|
||||
return lookupoptions;
|
||||
}
|
||||
/**
|
||||
* Gets the options to display for a lookupField
|
||||
* This method is called when a lookup column gets rendered... we fire the event to get the data when its focused,
|
||||
* then we use the data when it gets renderd
|
||||
*/
|
||||
public getLookupOptions(lookupSite: string, lookupWebId: string, lookupListId: string, lookupField: string): LookupOptions {
|
||||
// see if the options are in the store, if so, return them, otherwoise dispatch an action to get them
|
||||
let lookupoptions = this.props.lookupOptions.find(x => {
|
||||
return (x.lookupField === lookupField) &&
|
||||
(x.lookupListId === lookupListId) &&
|
||||
(x.lookupSite === lookupSite) &&
|
||||
(x.lookupWebId === lookupWebId);
|
||||
});
|
||||
return lookupoptions;
|
||||
}
|
||||
/**
|
||||
* Returns the ListDefinition for the given ListDefinionId
|
||||
*
|
||||
*/
|
||||
public getListDefinition(
|
||||
/** The id of the list definition to be retrieved */
|
||||
listdefid: string
|
||||
): ListDefinition {
|
||||
return this.props.listDefinitions.find(ld => ld.guid === listdefid);
|
||||
}
|
||||
/**
|
||||
* This method renders the contents of an individual cell in an editable format.
|
||||
*/
|
||||
public CellContentsEditable(props: { entity: ListItem, column: ColumnDefinition, cellUpdated: (newValue) => void, cellUpdatedEvent: (event: React.SyntheticEvent) => void; }): JSX.Element {
|
||||
|
||||
const {entity, column, cellUpdated, cellUpdatedEvent} = props;
|
||||
|
||||
if (column.type === "__LISTDEFINITIONTITLE__") {
|
||||
|
||||
const opts: Array<IDropdownOption> = this.props.listDefinitions.map(ld => {
|
||||
return { key: ld.guid, text: ld.listDefTitle };
|
||||
});
|
||||
// if (!entity.__metadata__ListDefinitionId) {
|
||||
// opts.unshift({ key: null, text: "Select one" });
|
||||
// }
|
||||
// should I have a different handler for this?
|
||||
return (
|
||||
<Dropdown options={opts} selectedKey={entity.__metadata__ListDefinitionId} label=""
|
||||
onChanged={(selection: IDropdownOption) => { cellUpdated(selection); } } />
|
||||
);
|
||||
}
|
||||
const listDef = this.getListDefinition(entity.__metadata__ListDefinitionId);
|
||||
const colref = listDef.columnReferences.find(cr => cr.columnDefinitionId === column.guid);
|
||||
const internalName = utils.ParseSPField(colref.name).id;
|
||||
const columnValue = entity[internalName];
|
||||
switch (colref.fieldDefinition.TypeAsString) {
|
||||
case "User":
|
||||
let siteUrl = listDef.siteUrl;
|
||||
let siteUsers = this.getSiteUsers(siteUrl);
|
||||
if (siteUsers) {
|
||||
switch (siteUsers.status) {
|
||||
case SiteUsersStatus.fetched:
|
||||
let options: IDropdownOption[] = siteUsers.siteUser.map((opt, index, options) => {
|
||||
return { key: opt.id, text: opt.value };
|
||||
});
|
||||
const selectedKey = columnValue ? columnValue.Id : null;
|
||||
return (
|
||||
<Dropdown label="" options={options} selectedKey={selectedKey} onChanged={(selection: IDropdownOption) => { cellUpdated(selection); } } >
|
||||
</Dropdown >
|
||||
);
|
||||
case SiteUsersStatus.fetching:
|
||||
return (
|
||||
<Spinner type={SpinnerType.normal} />
|
||||
);
|
||||
case SiteUsersStatus.error:
|
||||
return (
|
||||
<Spinner label="Error" type={SpinnerType.normal} />
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<Spinner type={SpinnerType.normal} />
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
<Spinner type={SpinnerType.normal} />
|
||||
);
|
||||
}
|
||||
/* falls through */
|
||||
case "Lookup":
|
||||
|
||||
let lookupField = colref.fieldDefinition.LookupField;
|
||||
let lookupListId = colref.fieldDefinition.LookupList;
|
||||
let lookupWebId = colref.fieldDefinition.LookupWebId;
|
||||
/**
|
||||
* We are assuming here that the lookup listy is in the same web.
|
||||
*
|
||||
*/
|
||||
lookupWebId = utils.ParseSPField(listDef.webLookup).id; // temp fix. Need to use graph to get the web by id in the site
|
||||
let lookupSite = listDef.siteUrl;
|
||||
let lookupOptions = this.getLookupOptions(lookupSite, lookupWebId, lookupListId, lookupField);
|
||||
|
||||
|
||||
if (lookupOptions) {
|
||||
switch (lookupOptions.status) {
|
||||
case LookupOptionStatus.fetched:
|
||||
let options: IDropdownOption[] = lookupOptions.lookupOption.map((opt, index, options) => {
|
||||
return { key: opt.id, text: opt.value };
|
||||
});
|
||||
return (
|
||||
<Dropdown label="" options={options} selectedKey={(columnValue ? columnValue.Id : null)} onChanged={(selection: IDropdownOption) => { cellUpdated(selection); } } >
|
||||
</Dropdown >
|
||||
);
|
||||
case LookupOptionStatus.fetching:
|
||||
return (
|
||||
<Spinner type={SpinnerType.normal} />
|
||||
);
|
||||
case LookupOptionStatus.error:
|
||||
return (
|
||||
<Spinner label="Error" type={SpinnerType.normal} />
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<Spinner type={SpinnerType.normal} />
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return (
|
||||
<Spinner type={SpinnerType.normal} />
|
||||
);
|
||||
}
|
||||
/* falls through */
|
||||
case "Choice":
|
||||
const choices = colref.fieldDefinition.Choices.map((c, i) => {
|
||||
|
||||
let opt: IDropdownOption = {
|
||||
index: i,
|
||||
key: i,
|
||||
text: c,
|
||||
isSelected: (c === columnValue)
|
||||
};
|
||||
return opt;
|
||||
});
|
||||
return (
|
||||
<Dropdown label="" selectedKey={entity[columnValue]} options={choices} onChanged={(selection: IDropdownOption) => cellUpdated(selection)} >
|
||||
</Dropdown >
|
||||
);
|
||||
case "Text":
|
||||
return (
|
||||
<input autoFocus type="text"
|
||||
value={columnValue}
|
||||
onChange={cellUpdatedEvent} />);
|
||||
case "Note":
|
||||
return (
|
||||
<TextField autoFocus
|
||||
value={columnValue}
|
||||
onChanged={cellUpdated} />);
|
||||
|
||||
case "DateTime":
|
||||
const datpickerStrings: IDatePickerStrings = {
|
||||
"months": [""],
|
||||
"shortMonths": [""],
|
||||
"days": [""],
|
||||
"shortDays": [""],
|
||||
goToToday: "yes"
|
||||
};
|
||||
let date = null;
|
||||
if (columnValue !== null) {
|
||||
const year = parseInt(columnValue.substring(0, 34));
|
||||
const month = parseInt(columnValue.substring(5, 7)) - 1;
|
||||
const day = parseInt(columnValue.substring(8, 10));
|
||||
date = new Date(year, month, day);
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<DatePicker strings={datpickerStrings} onSelectDate={cellUpdated} value={date}
|
||||
allowTextInput={true} isRequired={colref.fieldDefinition.Required}
|
||||
/>);
|
||||
default:
|
||||
return (
|
||||
<input autoFocus type="text"
|
||||
value={columnValue}
|
||||
onChange={cellUpdatedEvent} />);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method renders the contents of an individual cell in a non-editable format.
|
||||
*/
|
||||
public CellContents(props: { entity: ListItem, column: ColumnDefinition }): JSX.Element {
|
||||
const {entity, column} = props;
|
||||
if (!entity.__metadata__ListDefinitionId) { // item is new and list not yet selected
|
||||
}
|
||||
const listDef = this.getListDefinition(entity.__metadata__ListDefinitionId);
|
||||
if (column.type === "__LISTDEFINITIONTITLE__") {// this type is sued to show the listdefinition name
|
||||
if (listDef != null) {//listdef has been selected
|
||||
return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
{listDef.listDefTitle}
|
||||
</a>);
|
||||
}
|
||||
else {//listdef not yet selected
|
||||
return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
Select a list
|
||||
</a>);
|
||||
}
|
||||
}
|
||||
if (!listDef) { // cant edit columns til we select a listdef, not NO onFocus={this.toggleEditing}
|
||||
return (<a href="#" style={{ textDecoration: "none" }} >
|
||||
select a list first
|
||||
</a>
|
||||
);
|
||||
}
|
||||
const colref = listDef.columnReferences.find(cr => cr.columnDefinitionId === column.guid);
|
||||
if (colref === undefined) { //Column has not been configured for this list
|
||||
return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
'Column Not Defined'
|
||||
</a>
|
||||
);
|
||||
}
|
||||
const internalName = utils.ParseSPField(colref.name).id;
|
||||
|
||||
switch (colref.fieldDefinition.TypeAsString) {
|
||||
case "User":
|
||||
|
||||
if (entity[internalName] === undefined) { // value not set
|
||||
return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
{entity[internalName]["Title"]}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
/* falls through */
|
||||
case "Lookup":
|
||||
|
||||
if (entity[internalName] === undefined) { // value not set
|
||||
return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
{entity[internalName][colref.fieldDefinition.LookupField]}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
/* falls through */
|
||||
case "Text":
|
||||
return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
{entity[internalName]}
|
||||
</a>
|
||||
);
|
||||
/* falls through */
|
||||
case "Note":
|
||||
return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} dangerouslySetInnerHTML={{ __html: entity[internalName] }} >
|
||||
</a>
|
||||
);
|
||||
/* falls through */
|
||||
case "DateTime":
|
||||
let value: string;
|
||||
if (entity[internalName] === null) {
|
||||
return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
|
||||
</a>);
|
||||
}
|
||||
if (colref.fieldDefinition.EntityPropertyName === "DateOnly") {
|
||||
value = entity[internalName].split("T")[0];
|
||||
}
|
||||
else {
|
||||
value = entity[internalName];
|
||||
}
|
||||
return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
{value}
|
||||
</a>
|
||||
);
|
||||
/* falls through */
|
||||
default:
|
||||
return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
{entity[internalName]}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This method renders the A TD for an individual Cell. The TD contains the listItemID and the ColumnID as attributes.
|
||||
* It calls CellContentsEditable or CellContents based on whether the cell is being edited.
|
||||
* It determines if the cell is being edited by looking at this,props.editing(which got set by ToggleEditing).
|
||||
*/
|
||||
public TableDetail(props: { entity: ListItem, column: ColumnDefinition, cellUpdated: (newValue) => void, cellUpdatedEvent: (event: React.SyntheticEvent) => void; }): JSX.Element {
|
||||
|
||||
const {entity, column, cellUpdated, cellUpdatedEvent} = props;
|
||||
if (this.state && this.state.editing && this.state.editing.entityid === entity.GUID && this.state.editing.columnid === column.guid && column.editable) {
|
||||
return (<td key={entity.GUID + column.guid} data-entityid={entity.GUID} data-columnid={column.guid} style={{ border: "2px solid black", padding: "0px" }}>
|
||||
<this.CellContentsEditable entity={entity} column={column} cellUpdated={this.handleCellUpdated} cellUpdatedEvent={this.handleCellUpdatedEvent} />
|
||||
</td>
|
||||
);
|
||||
} else {
|
||||
return (<td key={entity.GUID + column.guid} data-entityid={entity.GUID} data-columnid={column.guid} style={{ border: "1px solid black", padding: "0px" }} onClick={this.toggleEditing} >
|
||||
<this.CellContents entity={entity} column={column} />
|
||||
</td>
|
||||
);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This method renders a tableRow for an individual listitem
|
||||
*/
|
||||
public TableRow(props: { entity: ListItem, columns: Array<ColumnDefinition>, cellUpdated: (newValue) => void, cellUpdatedEvent: (event: React.SyntheticEvent) => void; }): JSX.Element {
|
||||
const {entity, columns, cellUpdated, cellUpdatedEvent} = props;
|
||||
return (
|
||||
<tr>
|
||||
{
|
||||
columns.map(function (column) {
|
||||
return (
|
||||
<this.TableDetail key={column.guid} entity={entity} column={column} cellUpdated={this.handleCellUpdated} cellUpdatedEvent={this.handleCellUpdatedEvent} />
|
||||
);
|
||||
}, this)
|
||||
}
|
||||
<td data-entityid={entity.GUID} data-columnid={""} width="200" onClick={this.toggleEditing} >
|
||||
<div>
|
||||
|
||||
<Button width="20" style={{ padding: 0 }}
|
||||
onClick={this.updateListItem} alt="Save to Sharepoint"
|
||||
buttonType={ButtonType.icon}
|
||||
icon="Save" disabled={!(entity.__metadata__OriginalValues)} />
|
||||
<Button width="20" style={{ padding: 0 }}
|
||||
onClick={this.removeListItem}
|
||||
buttonType={ButtonType.icon}
|
||||
icon="Delete" />
|
||||
<Button width="20" style={{ padding: 0 }}
|
||||
// onClick={this.deleteList}
|
||||
buttonType={ButtonType.icon}
|
||||
disabled={!(entity.__metadata__OriginalValues)}
|
||||
onClick={this.undoItemChanges}
|
||||
icon="Undo" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>);
|
||||
};
|
||||
/**
|
||||
* Render rows for the listItems
|
||||
*/
|
||||
public TableRows(props: { entities: Array<ListItem>, columns: Array<ColumnDefinition>, cellUpdated: (newValue) => void, cellUpdatedEvent: (event: React.SyntheticEvent) => void; }): JSX.Element {
|
||||
const {entities, columns, cellUpdated, cellUpdatedEvent} = props;
|
||||
return (
|
||||
<tbody>
|
||||
{
|
||||
entities.map(function (list) {
|
||||
return (
|
||||
<this.TableRow key={list.GUID} entity={list} columns={columns} cellUpdated={this.handleCellUpdated} cellUpdatedEvent={this.handleCellUpdatedEvent} />
|
||||
);
|
||||
}, this)
|
||||
}
|
||||
</tbody>
|
||||
);
|
||||
}
|
||||
public render() {
|
||||
const { listItems } = this.props;
|
||||
Log.info("ListItemContainer", "In Render");
|
||||
return (
|
||||
<Container testid="columns" size={2} center>
|
||||
<CommandBar items={[{
|
||||
key: "AddItem",
|
||||
name: "Add an Item",
|
||||
icon: "Add",
|
||||
onClick: this.addListItem
|
||||
|
||||
},
|
||||
{
|
||||
key: "DleteAll",
|
||||
name: "DeleteAll",
|
||||
icon: "Delete"
|
||||
},
|
||||
{
|
||||
key: "Undo All changes",
|
||||
name: "UndoAll",
|
||||
icon: "Undo"
|
||||
},
|
||||
{
|
||||
key: "Save All ",
|
||||
name: "Save To SharePoint",
|
||||
icon: "Save"
|
||||
|
||||
}]} />
|
||||
|
||||
<table border="1">
|
||||
<thead>
|
||||
<tr>
|
||||
{this.props.columns.map((column) => {
|
||||
return <th key={column.name}>{column.name}</th>;
|
||||
})}
|
||||
</tr>
|
||||
</thead>
|
||||
{
|
||||
<this.TableRows entities={listItems} columns={this.props.columns} cellUpdated={this.handleCellUpdated} cellUpdatedEvent={this.handleCellUpdatedEvent} />
|
||||
})}
|
||||
</table>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ListItemContainer);
|
@ -0,0 +1,761 @@
|
||||
// import * as utils from "../utils/utils";
|
||||
// import * as React from "react";
|
||||
// const connect = require("react-redux").connect;
|
||||
// import {
|
||||
// addListItem, removeListItem, getListItemsAction, saveListItemAction,
|
||||
// undoListItemChangesAction, updateListItemAction,
|
||||
// } from "../actions/listItemActions";
|
||||
// import { getLookupOptionAction } from "../actions/lookupOptionsActions";
|
||||
// import { getSiteUsersAction } from "../actions/siteUsersActions";
|
||||
// import ListItem from "../model/ListItem";
|
||||
// import ColumnDefinition from "../model/ColumnDefinition";
|
||||
// import { LookupOptions, LookupOptionStatus } from "../model/LookupOptions";
|
||||
// import { SiteUsers, SiteUsersStatus } from "../model/SiteUsers";
|
||||
// import GridRowStatus from "../model/GridRowStatus";
|
||||
// import ListDefinition from "../model/ListDefinition";
|
||||
// import { FocusZone,Button, ButtonType, TextField, IDropdownOption, Dropdown, Spinner, SpinnerType, DetailsList, IColumn } from "office-ui-fabric-react";
|
||||
|
||||
// import { CommandBar } from "office-ui-fabric-react/lib/CommandBar";
|
||||
// import { DatePicker, IDatePickerStrings } from "office-ui-fabric-react/lib/DatePicker";
|
||||
|
||||
// import Container from "../components/container";
|
||||
// import { Log } from "@microsoft/sp-client-base";
|
||||
|
||||
// interface SPColumn extends IColumn {
|
||||
// editable: boolean;
|
||||
// type: string;
|
||||
// }
|
||||
// interface IListViewPageProps extends React.Props<any> {
|
||||
// /** An array of ListItems fetched from sharepoint */
|
||||
// siteUsers: Array<SiteUsers>;
|
||||
// /** An array of ListItems fetched from sharepoint */
|
||||
// listItems: Array<ListItem>;
|
||||
// /** An array of LookupOptions. One for each Lookup Column */
|
||||
// lookupOptions: Array<LookupOptions>;
|
||||
// /** An array of columns to be displayed on the grid */
|
||||
// columns: Array<ColumnDefinition>;
|
||||
// /** The listDefinitions. Says which lists to pull data from */
|
||||
// listDefinitions: Array<ListDefinition>;
|
||||
// /** Redux Action to add a new listitem */
|
||||
// addListItem: (ListItem) => void;
|
||||
// /** Redux Action to add a new remove a list item */
|
||||
// removeListItem: (l: ListItem, ListDef: ListDefinition) => void;
|
||||
// /** Redux Action to get listitems from a specific list */
|
||||
// getListItems: (listDefinitions: Array<ListDefinition>) => void;
|
||||
// /** Redux Action to update a listitem in sharepoint */
|
||||
// updateListItem: (ListItem: ListItem, ListDef: ListDefinition) => Promise<any>;
|
||||
// /** Redux Action to get the lookup options for a specific field */
|
||||
// getLookupOptionAction: (lookupSite, lookupWebId, lookupListId, lookupField) => void;
|
||||
// /** Redux Action to get the lookup options for a specific field */
|
||||
// getSiteUsersAction: (site) => Promise<any>;
|
||||
// /** Redux Action to undo changes made to the listitem */
|
||||
// undoItemChanges: (ListItem) => void;
|
||||
// /** Redux Action to save the listitem in the store (NOT to sharepoint*/
|
||||
// saveListItem: (ListItem) => void;
|
||||
// }
|
||||
// function mapStateToProps(state) {
|
||||
|
||||
// return {
|
||||
// listItems: state.items,
|
||||
// columns: state.columns,
|
||||
// listDefinitions: state.lists,
|
||||
// systemStatus: state.systemStatus,
|
||||
// lookupOptions: state.lookupOptions,
|
||||
// siteUsers: state.siteUsers
|
||||
// };
|
||||
// }
|
||||
// export class GridColumn {
|
||||
// constructor(
|
||||
// public id: string,
|
||||
// public name: string,
|
||||
// public editable: boolean,
|
||||
// public width: number,
|
||||
// public formatter: string = "",
|
||||
// public editor?: string) { }
|
||||
// }
|
||||
// function mapDispatchToProps(dispatch) {
|
||||
// return {
|
||||
// addListItem: (listItem: ListItem): void => {
|
||||
// dispatch(addListItem(listItem));
|
||||
// },
|
||||
// removeListItem: (listItem: ListItem, listDef: ListDefinition): void => {
|
||||
// dispatch(removeListItem(dispatch, listItem, listDef));
|
||||
// },
|
||||
// updateListItem: (listItem: ListItem, listDef: ListDefinition): Promise<any> => {
|
||||
// const action = updateListItemAction(dispatch, listDef, listItem);
|
||||
// dispatch(action); // need to ewname this one to be digfferent from the omported ome
|
||||
// return action.payload.promise;
|
||||
|
||||
// },
|
||||
// saveListItem: (listItem: ListItem): void => {
|
||||
// dispatch(saveListItemAction(listItem));
|
||||
// },
|
||||
// undoItemChanges: (listItem: ListItem): void => {
|
||||
// dispatch(undoListItemChangesAction(listItem));
|
||||
// },
|
||||
|
||||
// getListItems: (listDefinitions: Array<ListDefinition>): void => {
|
||||
// dispatch(getListItemsAction(dispatch, listDefinitions));
|
||||
// },
|
||||
// getLookupOptionAction: (lookupSite, lookupWebId, lookupListId, lookupField): void => {
|
||||
// dispatch(getLookupOptionAction(dispatch, lookupSite, lookupWebId, lookupListId, lookupField));
|
||||
// },
|
||||
// getSiteUsersAction: (site): void => {
|
||||
|
||||
// const action = getSiteUsersAction(dispatch, site);
|
||||
// dispatch(action);
|
||||
// return action.payload.promise;
|
||||
// },
|
||||
// };
|
||||
// }
|
||||
// /**
|
||||
// *
|
||||
// */
|
||||
// interface IGridState {
|
||||
// editing: {
|
||||
// /**The Sharepoint GUID of the listitem being edited */
|
||||
// entityid: string;
|
||||
// /**The id of the column being edited */
|
||||
// columnid: string;
|
||||
// };
|
||||
// }
|
||||
// /**
|
||||
// * This component is the Grid for editing listitems.
|
||||
// */
|
||||
// class ListItemContainerUIF extends React.Component<IListViewPageProps, IGridState> {
|
||||
// public constructor() {
|
||||
// super();
|
||||
// this.CellContentsEditable = this.CellContentsEditable.bind(this);
|
||||
// this.CellContents = this.CellContents.bind(this);
|
||||
// this.TableDetail = this.TableDetail.bind(this);
|
||||
// this.toggleEditing = this.toggleEditing.bind(this);
|
||||
// this.addListItem = this.addListItem.bind(this);
|
||||
// this.removeListItem = this.removeListItem.bind(this);
|
||||
// this.handleCellUpdated = this.handleCellUpdated.bind(this);
|
||||
// this.handleCellUpdatedEvent = this.handleCellUpdatedEvent.bind(this);
|
||||
// this.undoItemChanges = this.undoItemChanges.bind(this);
|
||||
// this.updateListItem = this.updateListItem.bind(this);
|
||||
// this.getLookupOptions = this.getLookupOptions.bind(this);
|
||||
// this.onRenderItemColumn = this.onRenderItemColumn.bind(this);
|
||||
|
||||
|
||||
// }
|
||||
// private addListItem(): void {
|
||||
|
||||
// let listItem = new ListItem();
|
||||
// for (const column of this.props.columns) {
|
||||
// listItem[column.name] === null;
|
||||
// }
|
||||
// if (this.props.listDefinitions.length === 1) {
|
||||
// listItem.__metadata__ListDefinitionId = this.props.listDefinitions[0].guid;
|
||||
// } else {
|
||||
// listItem.__metadata__ListDefinitionId = null;
|
||||
// }
|
||||
|
||||
// this.props.addListItem(listItem);
|
||||
// }
|
||||
// private removeListItem(event): void {
|
||||
|
||||
// const parentTD = this.getParent(event.target, "DIV", "spCell");
|
||||
// const attributes: NamedNodeMap = parentTD.attributes;
|
||||
// const entityid = attributes.getNamedItem("data-entityid").value; // theid of the SPListItem
|
||||
// const listItem: ListItem = this.props.listItems.find((temp) => temp.GUID === entityid); // the listItemItself
|
||||
// const listDef = this.getListDefinition(listItem.__metadata__ListDefinitionId);// The list Definition this item is associated with.
|
||||
// this.props.removeListItem(listItem, listDef);
|
||||
// }
|
||||
// /**
|
||||
// * When the component Mounts, call an action to get the listitems for all the listdefinitions
|
||||
// */
|
||||
// public componentWillMount() {
|
||||
|
||||
// this.props.getListItems(this.props.listDefinitions);
|
||||
// }
|
||||
// /**
|
||||
// * Method to get the parent span of any cell whose classnAME IS spcell
|
||||
// * The listItemId and columnID are stored as attributes of THAT SPAN
|
||||
// */
|
||||
// public getParent(node: Node, type: string, className: string): Node {
|
||||
|
||||
// while (node.nodeName !== type && node["className"] !== className) {
|
||||
// node = node.parentNode;
|
||||
// }
|
||||
// return node;
|
||||
// }
|
||||
// /**
|
||||
// * This event gets fired whenever a cell on the grid recieves focus.
|
||||
// * The "editing" propery of this component determines which cell is being edited.
|
||||
// * This method gets the clicked on (the entityid-- the id of the SPLIstItem) and the columnId (the id of the ColumnDefinition)
|
||||
// * and sets them in the "editing"property of state.
|
||||
// * When Component then redraws, it draws that cell as an editable (See the TableDetail method).
|
||||
// *
|
||||
// * If the rendering of that column in edit mode requires additional Info, dispatch a redux action to get the data.
|
||||
// * (Dispatching the action from within the render mehod itself cused infinite loop)
|
||||
// *
|
||||
// */
|
||||
// public toggleEditing(event) {
|
||||
// Log.verbose("list-Page", "focus event fired editing when entering cell");
|
||||
// const target = this.getParent(event.target, "DIV", "spCell"); // walk up the Dom to the TD, thats where the IDs are stored
|
||||
// const attributes: NamedNodeMap = target.attributes;
|
||||
// const entityid = attributes.getNamedItem("data-entityid").value;
|
||||
// const columnid = attributes.getNamedItem("data-columnid").value;
|
||||
// if (columnid != "") { //user clicked on a column, not a button( Buttons are in a td with am column id of ""
|
||||
// /**
|
||||
// * Need to fire events here to get data needed for the rerender
|
||||
// */
|
||||
// const listitem = this.props.listItems.find(li => li.GUID === entityid);
|
||||
// const listDef = this.getListDefinition(listitem.__metadata__ListDefinitionId);
|
||||
// if (listDef) {// if user just added an item we may not hava a lisdef yest
|
||||
// const colref = listDef.columnReferences.find(cr => cr.columnDefinitionId === columnid);
|
||||
// if (colref) {// Listname does not have a columnReference
|
||||
|
||||
// switch (colref.fieldDefinition.TypeAsString) {
|
||||
// case "Lookup":
|
||||
// let lookupField = colref.fieldDefinition.LookupField;
|
||||
// let lookupListId = colref.fieldDefinition.LookupList;
|
||||
// let lookupWebId = colref.fieldDefinition.LookupWebId;
|
||||
// /**
|
||||
// * We are assuming here that the lookup listy is in the same web.
|
||||
// *
|
||||
// */
|
||||
// lookupWebId = utils.ParseSPField(listDef.webLookup).id; // temp fix. Need to use graph to get the web by id in the site
|
||||
// let lookupSite = listDef.siteUrl;
|
||||
// this.ensureLookupOptions(lookupSite, lookupWebId, lookupListId, lookupField);
|
||||
// break;
|
||||
// case "User":
|
||||
|
||||
// lookupWebId = utils.ParseSPField(listDef.webLookup).id; // temp fix. Need to use graph to get the web by id in the site
|
||||
// let site = listDef.siteUrl;
|
||||
// this.ensureSiteUsers(site);
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// this.setState({ "editing": { entityid: entityid, columnid: columnid } });
|
||||
// }
|
||||
// /**
|
||||
// * This event gets fired to revert any changes made to the ListItem.
|
||||
// */
|
||||
// public undoItemChanges(event): void {
|
||||
// const parentTD = this.getParent(event.target, "DIV", "spCell"); // the listitemId and the column ID are always stored as attributes of the parent TD.
|
||||
// const attributes: NamedNodeMap = parentTD.attributes;
|
||||
// const entityitem = attributes.getNamedItem("data-entityid");
|
||||
// const entityid = entityitem.value;
|
||||
// const entity: ListItem = this.props.listItems.find((temp) => temp.GUID === entityid);
|
||||
// this.props.undoItemChanges(entity);
|
||||
// }
|
||||
// /**
|
||||
// * This event gets fired, to save the item back to SharePoint.
|
||||
// */
|
||||
// public updateListItem(event): void {
|
||||
|
||||
// const parentTD = this.getParent(event.target, "DIV", "spCell");
|
||||
// const attributes: NamedNodeMap = parentTD.attributes;
|
||||
// const entityid = attributes.getNamedItem("data-entityid").value; // theid of the SPListItem
|
||||
// const entity: ListItem = this.props.listItems.find((temp) => temp.GUID === entityid);
|
||||
// const listDef: ListDefinition = this.getListDefinition(entity.__metadata__ListDefinitionId);
|
||||
// if (entity.__metadata__ListDefinitionId === entity.__metadata__OriginalValues.__metadata__ListDefinitionId
|
||||
// || entity.__metadata__GridRowStatus === GridRowStatus.new) {// List not changed
|
||||
|
||||
// this.props.updateListItem(entity, listDef);
|
||||
// }
|
||||
// else {// list changed, add to new, delete from old (will need to do some fiorld mapping in here
|
||||
// entity.__metadata__GridRowStatus = GridRowStatus.new;
|
||||
// this.props.updateListItem(entity, listDef).then(response => {
|
||||
// const oldListDef: ListDefinition = this.getListDefinition(entity.__metadata__OriginalValues.__metadata__ListDefinitionId);
|
||||
// this.props.removeListItem(entity.__metadata__OriginalValues, oldListDef);
|
||||
// });
|
||||
// }
|
||||
|
||||
// }
|
||||
// /**
|
||||
// * This method gets called when react events are used to update a cell in the grid.
|
||||
// * It just gets the value and passes it to handleCellUpdated.
|
||||
// */
|
||||
// private handleCellUpdatedEvent(event) { //native react uses a Synthetic event
|
||||
// this.handleCellUpdated(event.target.value);
|
||||
|
||||
// }
|
||||
// /**
|
||||
// * This method gets called when user changes the listdefinition for an item.
|
||||
// * the old fields are moved to the corresponing new fields and translated as needed
|
||||
// */
|
||||
// private mapOldListFieldsToNewListFields(listItem: ListItem) {
|
||||
|
||||
// const newListDef = this.getListDefinition(listItem.__metadata__ListDefinitionId);
|
||||
// const oldListDef = this.getListDefinition(listItem.__metadata__OriginalValues.__metadata__ListDefinitionId);
|
||||
// for (const newColRef of newListDef.columnReferences) {
|
||||
// // find the old columnReference
|
||||
// const oldColRef = oldListDef.columnReferences.find(cr => cr.columnDefinitionId === newColRef.columnDefinitionId);
|
||||
// const newFieldName = utils.ParseSPField(newColRef.name).id;
|
||||
// const oldFieldName = utils.ParseSPField(oldColRef.name).id;
|
||||
// switch (newColRef.fieldDefinition.TypeAsString) {
|
||||
// case "User":
|
||||
// // should male a local copy befor i start messing with these.// fieldd names may overlap on old and new
|
||||
// // const name = listItem.__metadata__OriginalValues[oldFieldName].Name;// the user login name
|
||||
// const name = listItem[oldFieldName].Name;// the user login name
|
||||
// const siteUsersOnNewSite = this.props.siteUsers.find(su => su.siteUrl === newListDef.siteUrl);
|
||||
// const newUser = siteUsersOnNewSite.siteUser.find(user => user.loginName === name);
|
||||
// listItem[newFieldName].Id = newUser.id;
|
||||
// listItem[newFieldName].Name = newUser.loginName;
|
||||
// listItem[newFieldName].Title = newUser.value;
|
||||
// break;
|
||||
|
||||
// default:
|
||||
// listItem[newFieldName] = listItem[oldFieldName];
|
||||
// }
|
||||
|
||||
// }
|
||||
// }
|
||||
// /**
|
||||
// * This method gets called when react cells in the gid get updated.
|
||||
// * Office UI Fabric does not use events. It just calls this method with the new value.
|
||||
// * It reformats the data to fit the format we recievbed from SP in the first place ,
|
||||
// * and dispatches an action to save the data in the store.
|
||||
// *
|
||||
// * Also, it saves the original version of the record, so we can undo later.
|
||||
// */
|
||||
// private handleCellUpdated(value) {
|
||||
|
||||
// const {entityid, columnid} = this.state.editing;
|
||||
// const entity: ListItem = this.props.listItems.find((temp) => temp.GUID === entityid);
|
||||
// const listDef = this.getListDefinition(entity.__metadata__ListDefinitionId);
|
||||
// const titlecolumnid = this.props.columns.find(c => { return c.type === "__LISTDEFINITIONTITLE__" }).guid
|
||||
// if (columnid === titlecolumnid) { // user just changed the listDef,
|
||||
|
||||
// if (entity.__metadata__GridRowStatus === GridRowStatus.pristine) {
|
||||
// if (!entity.__metadata__OriginalValues) { //SAVE orgininal values so we can undo;
|
||||
// entity.__metadata__OriginalValues = _.cloneDeep(entity); // need deep if we have lookup values
|
||||
// }
|
||||
// }
|
||||
// entity.__metadata__ListDefinitionId = value.key; // value is a DropDDownOptions
|
||||
// if (entity.__metadata__GridRowStatus !== GridRowStatus.new) {
|
||||
// const listDef = this.getListDefinition(value.key);
|
||||
// this.props.getSiteUsersAction(listDef.siteUrl).then(r => {
|
||||
// this.mapOldListFieldsToNewListFields(entity);
|
||||
// this.props.saveListItem(entity);
|
||||
// });
|
||||
// } else {
|
||||
// this.props.saveListItem(entity);
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
// const columnReference = listDef.columnReferences.find(cr => cr.columnDefinitionId === columnid);
|
||||
// const internalName = utils.ParseSPField(columnReference.name).id;
|
||||
// if (!entity.__metadata__OriginalValues) { //SAVE orgininal values so we can undo;
|
||||
// entity.__metadata__OriginalValues = _.cloneDeep(entity); // need deep if we have lookup values
|
||||
// }
|
||||
// if (entity.__metadata__GridRowStatus === GridRowStatus.pristine) {
|
||||
// entity.__metadata__GridRowStatus = GridRowStatus.modified;
|
||||
// }
|
||||
// switch (columnReference.fieldDefinition.TypeAsString) {
|
||||
// case "User":
|
||||
// if (!entity[internalName]) {// if value was not previously set , then this is undefined//
|
||||
// entity[internalName] = {};// set new value to an empty objecte
|
||||
// }
|
||||
// entity[internalName].Id = value.key;//and then fill in the values
|
||||
// entity[internalName].Title = value.text;
|
||||
// break;
|
||||
// case "DateTime":
|
||||
// const year = value.getFullYear().toString();
|
||||
|
||||
// entity[internalName] = (value.getFullYear().toString()) + "-" + (value.getMonth() + 1).toString() + "-" + value.getDate().toString() + "T00:00:00Z";
|
||||
// break;
|
||||
// case "Lookup":
|
||||
// if (!entity[internalName]) {// if value was not previously set , then this is undefined//
|
||||
// entity[internalName] = {};// set new value to an empty objecte
|
||||
// }
|
||||
// entity[internalName]["Id"] = value.key;//and then fill in the values
|
||||
// entity[internalName][columnReference.fieldDefinition.LookupField] = value.text;
|
||||
// break;
|
||||
// default:
|
||||
// entity[internalName] = value;
|
||||
// }
|
||||
// this.props.saveListItem(entity);
|
||||
// }
|
||||
// /**
|
||||
// * If the the options for a lookup list are not in the cache, fire an event to get them
|
||||
// * This method is called when a lookup column receives focus.
|
||||
// */
|
||||
// public ensureSiteUsers(siteUrl: string): SiteUsers {
|
||||
// // see if the options are in the store, if so, return them, otherwoise dispatch an action to get them
|
||||
// const siteUsers = this.props.siteUsers.find(x => {
|
||||
// return (x.siteUrl === siteUrl);
|
||||
// });
|
||||
// if (siteUsers === undefined) {
|
||||
// this.props.getSiteUsersAction(siteUrl);
|
||||
// }
|
||||
// return siteUsers;
|
||||
// }
|
||||
// /**
|
||||
// * Gets the options to display for a lookupField
|
||||
// * This method is called when a lookup column gets rendered... we fire the event to get the data when its focused,
|
||||
// * then we use the data when it gets renderd
|
||||
// */
|
||||
// public getSiteUsers(siteUrl: string): SiteUsers {
|
||||
// // see if the options are in the store, if so, return them, otherwoise dispatch an action to get them
|
||||
// const siteUsers = this.props.siteUsers.find(x => {
|
||||
// return (x.siteUrl === siteUrl);
|
||||
// });
|
||||
// return siteUsers;
|
||||
// }
|
||||
// /**
|
||||
// * If the the options for a lookup list are not in the cache, fire an event to get them
|
||||
// * This method is called when a lookup column receives focus.
|
||||
// */
|
||||
// public ensureLookupOptions(lookupSite: string, lookupWebId: string, lookupListId: string, lookupField: string): LookupOptions {
|
||||
// // see if the options are in the store, if so, return them, otherwoise dispatch an action to get them
|
||||
// const lookupoptions = this.props.lookupOptions.find(x => {
|
||||
// return (x.lookupField === lookupField) &&
|
||||
// (x.lookupListId === lookupListId) &&
|
||||
// (x.lookupSite === lookupSite) &&
|
||||
// (x.lookupWebId === lookupWebId);
|
||||
// });
|
||||
// if (lookupoptions === undefined) {
|
||||
// this.props.getLookupOptionAction(lookupSite, lookupWebId, lookupListId, lookupField);
|
||||
// }
|
||||
// return lookupoptions;
|
||||
// }
|
||||
// /**
|
||||
// * Gets the options to display for a lookupField
|
||||
// * This method is called when a lookup column gets rendered... we fire the event to get the data when its focused,
|
||||
// * then we use the data when it gets renderd
|
||||
// */
|
||||
// public getLookupOptions(lookupSite: string, lookupWebId: string, lookupListId: string, lookupField: string): LookupOptions {
|
||||
// // see if the options are in the store, if so, return them, otherwoise dispatch an action to get them
|
||||
// let lookupoptions = this.props.lookupOptions.find(x => {
|
||||
// return (x.lookupField === lookupField) &&
|
||||
// (x.lookupListId === lookupListId) &&
|
||||
// (x.lookupSite === lookupSite) &&
|
||||
// (x.lookupWebId === lookupWebId);
|
||||
// });
|
||||
// return lookupoptions;
|
||||
// }
|
||||
// /**
|
||||
// * Returns the ListDefinition for the given ListDefinionId
|
||||
// *
|
||||
// */
|
||||
// public getListDefinition(
|
||||
// /** The id of the list definition to be retrieved */
|
||||
// listdefid: string
|
||||
// ): ListDefinition {
|
||||
// return this.props.listDefinitions.find(ld => ld.guid === listdefid);
|
||||
// }
|
||||
// /**
|
||||
// * This method renders the contents of an individual cell in an editable format.
|
||||
// */
|
||||
// public CellContentsEditable(props: { entity: ListItem, column: SPColumn, cellUpdated: (newValue) => void, cellUpdatedEvent: (event: React.SyntheticEvent) => void; }): JSX.Element {
|
||||
|
||||
// const {entity, column, cellUpdated, cellUpdatedEvent} = props;
|
||||
|
||||
// if (column.type === "__LISTDEFINITIONTITLE__") {
|
||||
// entity.__metadata__ListDefinitionId
|
||||
// const opts: Array<IDropdownOption> = this.props.listDefinitions.map(ld => {
|
||||
// return { key: ld.guid, text: ld.title };
|
||||
// });
|
||||
// // if (!entity.__metadata__ListDefinitionId) {
|
||||
// // opts.unshift({ key: null, text: "Select one" });
|
||||
// // }
|
||||
// // should I have a different handler for this?
|
||||
// return (
|
||||
// <Dropdown options={opts} selectedKey={entity.__metadata__ListDefinitionId} label=""
|
||||
// onChanged={(selection: IDropdownOption) => { cellUpdated(selection); } } />
|
||||
// );
|
||||
// }
|
||||
// const listDef = this.getListDefinition(entity.__metadata__ListDefinitionId);
|
||||
// const colref = listDef.columnReferences.find(cr => cr.columnDefinitionId === column.key);
|
||||
// const internalName = utils.ParseSPField(colref.name).id;
|
||||
// const columnValue = entity[internalName];
|
||||
// switch (colref.fieldDefinition.TypeAsString) {
|
||||
// case "User":
|
||||
// let siteUrl = listDef.siteUrl;
|
||||
// let siteUsers = this.getSiteUsers(siteUrl);
|
||||
// if (siteUsers) {
|
||||
// switch (siteUsers.status) {
|
||||
// case SiteUsersStatus.fetched:
|
||||
// let options: IDropdownOption[] = siteUsers.siteUser.map((opt, index, options) => {
|
||||
// return { key: opt.id, text: opt.value };
|
||||
// });
|
||||
// const selectedKey = columnValue ? columnValue.Id : null;
|
||||
// return (
|
||||
// <Dropdown label="" options={options} selectedKey={selectedKey} onChanged={(selection: IDropdownOption) => { cellUpdated(selection); } } >
|
||||
// </Dropdown >
|
||||
// );
|
||||
// case SiteUsersStatus.fetching:
|
||||
// return (
|
||||
// <Spinner type={SpinnerType.normal} />
|
||||
// );
|
||||
// case SiteUsersStatus.error:
|
||||
// return (
|
||||
// <Spinner label="Error" type={SpinnerType.normal} />
|
||||
// );
|
||||
// default:
|
||||
// return (
|
||||
// <Spinner type={SpinnerType.normal} />
|
||||
// );
|
||||
// }
|
||||
// } else {
|
||||
// return (
|
||||
// <Spinner type={SpinnerType.normal} />
|
||||
// );
|
||||
// }
|
||||
// case "Lookup":
|
||||
|
||||
// let lookupField = colref.fieldDefinition.LookupField;
|
||||
// let lookupListId = colref.fieldDefinition.LookupList;
|
||||
// let lookupWebId = colref.fieldDefinition.LookupWebId;
|
||||
// /**
|
||||
// * We are assuming here that the lookup listy is in the same web.
|
||||
// *
|
||||
// */
|
||||
// lookupWebId = utils.ParseSPField(listDef.webLookup).id; // temp fix. Need to use graph to get the web by id in the site
|
||||
// let lookupSite = listDef.siteUrl;
|
||||
// let lookupOptions = this.getLookupOptions(lookupSite, lookupWebId, lookupListId, lookupField);
|
||||
|
||||
|
||||
// if (lookupOptions) {
|
||||
// switch (lookupOptions.status) {
|
||||
// case LookupOptionStatus.fetched:
|
||||
// let options: IDropdownOption[] = lookupOptions.lookupOption.map((opt, index, options) => {
|
||||
// return { key: opt.id, text: opt.value };
|
||||
// });
|
||||
// return (
|
||||
// <Dropdown label="" options={options} selectedKey={(columnValue ? columnValue.Id : null)} onChanged={(selection: IDropdownOption) => { cellUpdated(selection); } } >
|
||||
// </Dropdown >
|
||||
// );
|
||||
// case LookupOptionStatus.fetching:
|
||||
// return (
|
||||
// <Spinner type={SpinnerType.normal} />
|
||||
// );
|
||||
// case LookupOptionStatus.error:
|
||||
// return (
|
||||
// <Spinner label="Error" type={SpinnerType.normal} />
|
||||
// );
|
||||
// default:
|
||||
// return (
|
||||
// <Spinner type={SpinnerType.normal} />
|
||||
// );
|
||||
// }
|
||||
// } else {
|
||||
// return (
|
||||
// <Spinner type={SpinnerType.normal} />
|
||||
// );
|
||||
// }
|
||||
// case "Choice":
|
||||
// const choices = colref.fieldDefinition.Choices.map((c, i) => {
|
||||
|
||||
// let opt: IDropdownOption = {
|
||||
// index: i,
|
||||
// key: i,
|
||||
// text: c,
|
||||
// isSelected: (c === columnValue)
|
||||
// };
|
||||
// return opt;
|
||||
// });
|
||||
// return (
|
||||
// <Dropdown label="" selectedKey={entity[columnValue]} options={choices} onChanged={(selection: IDropdownOption) => cellUpdated(selection)} >
|
||||
// </Dropdown >
|
||||
// );
|
||||
// case "Text":
|
||||
// return (
|
||||
// <input autoFocus type="text"
|
||||
// value={columnValue}
|
||||
// onChange={cellUpdatedEvent} />);
|
||||
// case "Note":
|
||||
// return (
|
||||
// <TextField autoFocus
|
||||
// value={columnValue}
|
||||
// onChanged={cellUpdated} />);
|
||||
|
||||
// case "DateTime":
|
||||
// const datpickerStrings: IDatePickerStrings = {
|
||||
// "months": [""],
|
||||
// "shortMonths": [""],
|
||||
// "days": [""],
|
||||
// "shortDays": [""],
|
||||
// goToToday: "yes"
|
||||
// };
|
||||
|
||||
// const year = parseInt(columnValue.substring(0, 34));
|
||||
// const month = parseInt(columnValue.substring(5, 7)) - 1;
|
||||
// const day = parseInt(columnValue.substring(8, 10));
|
||||
// const date = new Date(year, month, day);
|
||||
|
||||
// return (
|
||||
// <DatePicker strings={datpickerStrings} onSelectDate={cellUpdated} value={date}
|
||||
// allowTextInput={true} isRequired={colref.fieldDefinition.Required}
|
||||
// />);
|
||||
// default:
|
||||
// return (
|
||||
// <input autoFocus type="text"
|
||||
// value={columnValue}
|
||||
// onChange={cellUpdatedEvent} />);
|
||||
// }
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * This method renders the contents of an individual cell in a non-editable format.
|
||||
// */
|
||||
// public CellContents(props: { entity: ListItem, column: SPColumn }): JSX.Element {
|
||||
// const {entity, column} = props;
|
||||
// if (!entity.__metadata__ListDefinitionId) { // item is new and list not yet selected
|
||||
// }
|
||||
// const listDef = this.getListDefinition(entity.__metadata__ListDefinitionId);
|
||||
// if (column.type === "__LISTDEFINITIONTITLE__") {// this type is sued to show the listdefinition name
|
||||
// if (listDef != null) {//listdef has been selected
|
||||
// return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
// {listDef.title}
|
||||
// </a>);
|
||||
// }
|
||||
// else {//listdef not yet selected
|
||||
// return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
// Select a list
|
||||
// </a>);
|
||||
// }
|
||||
// }
|
||||
// if (!listDef) { // cant edit columns til we select a listdef, not NO onFocus={this.toggleEditing}
|
||||
// return (<a href="#" style={{ textDecoration: "none" }} >
|
||||
// select a list first
|
||||
// </a>
|
||||
// );
|
||||
// }
|
||||
// const colref = listDef.columnReferences.find(cr => cr.columnDefinitionId === column.key);
|
||||
// if (colref === undefined) { //Column has not been configured for this list
|
||||
// return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
// 'Column Not Defined'
|
||||
// </a>
|
||||
// );
|
||||
// }
|
||||
// const internalName = utils.ParseSPField(colref.name).id;
|
||||
|
||||
// switch (colref.fieldDefinition.TypeAsString) {
|
||||
// case "User":
|
||||
|
||||
// if (entity[internalName] === undefined) { // value not set
|
||||
// return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
|
||||
// </a>
|
||||
// );
|
||||
// } else {
|
||||
// return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
// {entity[internalName]["Title"]}
|
||||
// </a>
|
||||
// );
|
||||
// }
|
||||
// case "Lookup":
|
||||
|
||||
// if (entity[internalName] === undefined) { // value not set
|
||||
// return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
|
||||
// </a>
|
||||
// );
|
||||
// } else {
|
||||
// return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
// {entity[internalName][colref.fieldDefinition.LookupField]}
|
||||
// </a>
|
||||
// );
|
||||
// }
|
||||
// case "Text":
|
||||
// return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
// {entity[internalName]}
|
||||
// </a>
|
||||
// );
|
||||
// case "Note":
|
||||
// return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} dangerouslySetInnerHTML={{ __html: entity[internalName] }} >
|
||||
// </a>
|
||||
// );
|
||||
|
||||
// case "DateTime":
|
||||
// let value: string;
|
||||
// if (entity[internalName] === null) {
|
||||
// return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
|
||||
// </a>);
|
||||
// }
|
||||
// if (colref.fieldDefinition.EntityPropertyName === "DateOnly") {
|
||||
// value = entity[internalName].split("T")[0];
|
||||
// }
|
||||
// else {
|
||||
// value = entity[internalName];
|
||||
// }
|
||||
// return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
// {value}
|
||||
// </a>
|
||||
// );
|
||||
// default:
|
||||
// return (<a href="#" onFocus={this.toggleEditing} style={{ textDecoration: "none" }} >
|
||||
// {entity[internalName]}
|
||||
// </a>
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// /**
|
||||
// * This method renders the A TD for an individual Cell. The TD contains the listItemID and the ColumnID as attributes.
|
||||
// * It calls CellContentsEditable or CellContents based on whether the cell is being edited.
|
||||
// * It determines if the cell is being edited by looking at this,props.editing(which got set by ToggleEditing).
|
||||
// */
|
||||
// public TableDetail(props: { entity: ListItem, column: SPColumn, cellUpdated: (newValue) => void, cellUpdatedEvent: (event: React.SyntheticEvent) => void; }): JSX.Element {
|
||||
|
||||
// const {entity, column, cellUpdated, cellUpdatedEvent} = props;
|
||||
// if (this.state && this.state.editing && this.state.editing.entityid === entity.GUID && this.state.editing.columnid === column.key) {
|
||||
// return (<div width={column.minWidth} className="spCell" key={entity.GUID + column.key} data-entityid={entity.GUID} data-columnid={column.key} style={{ border: "2px solid black", padding: "0px" }}>
|
||||
// <this.CellContentsEditable entity={entity} column={column} cellUpdated={this.handleCellUpdated} cellUpdatedEvent={this.handleCellUpdatedEvent} />
|
||||
// </div>
|
||||
// );
|
||||
// } else {
|
||||
// return (<div width={column.minWidth} className="spCell" key={entity.GUID + column.key} data-entityid={entity.GUID} data-columnid={column.key} style={{ border: "1px solid black", padding: "0px" }} onClick={this.toggleEditing} >
|
||||
// <this.CellContents entity={entity} column={column} />
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// public onRenderItemColumn(item: any, index: number, column: SPColumn): any {
|
||||
|
||||
// const listDef = this.getListDefinition(item.__metadata__ListDefinitionId);
|
||||
// const colRef = listDef.columnReferences.find(cr => cr.columnDefinitionId === column.key);
|
||||
// const internalName = utils.ParseSPField(colRef.name).id;
|
||||
// return (
|
||||
// <FocusZone>
|
||||
// <this.TableDetail entity={item} column={column} cellUpdated={this.handleCellUpdated} cellUpdatedEvent={this.handleCellUpdatedEvent} />
|
||||
// </FocusZone>
|
||||
// );
|
||||
|
||||
|
||||
// }
|
||||
|
||||
// public render() {
|
||||
// const { listItems } = this.props;
|
||||
// Log.info("ListItemContainer", "In Render");
|
||||
|
||||
// const uColumns: SPColumn[] = this.props.columns.map((c, i, a) => {
|
||||
// return {
|
||||
// key: c.guid,
|
||||
// name: c.name,
|
||||
// fieldName: c.name,
|
||||
// minWidth: 80,
|
||||
// maxWidth: 80,
|
||||
|
||||
// width: 80,
|
||||
|
||||
// type: c.type,
|
||||
// editable: c.editable,
|
||||
|
||||
// };
|
||||
// });
|
||||
|
||||
// return (
|
||||
|
||||
// <Container testid="columns" size={2} center>
|
||||
// <DetailsList columns={uColumns} items={listItems} onRenderItemColumn={this.onRenderItemColumn}>
|
||||
// </DetailsList>
|
||||
|
||||
// </Container>
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// export default connect(
|
||||
// mapStateToProps,
|
||||
// mapDispatchToProps
|
||||
// )(ListItemContainerUIF);
|
@ -0,0 +1,56 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
Button,
|
||||
MessageBar,
|
||||
MessageBarType
|
||||
} from "office-ui-fabric-react";
|
||||
const connect = require("react-redux").connect;
|
||||
import SystemStatus from "../model/SystemStatus";
|
||||
const Link = require("react-router").Link;
|
||||
import Content from "../components/content";
|
||||
interface IAppProps extends React.Props<any> {
|
||||
systemStatus: SystemStatus;
|
||||
}
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
systemStatus: state.systemStatus,
|
||||
};
|
||||
}
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
};
|
||||
}
|
||||
class App extends React.Component<IAppProps, void> {
|
||||
private messageBar(error: string): JSX.Element {
|
||||
if (error === "") {
|
||||
return (<div />);
|
||||
}
|
||||
else {
|
||||
return (
|
||||
<MessageBar messageBarType={MessageBarType.error}>{error} </MessageBar>
|
||||
);
|
||||
}
|
||||
}
|
||||
public render() {
|
||||
const { children} = this.props;
|
||||
return (
|
||||
<div>
|
||||
<Button> <Link to="/lists">List Definitions</Link></Button>
|
||||
<Button> <Link to="/columns">Column Definitions</Link></Button>
|
||||
<Button> <Link to="/">List Items</Link></Button>
|
||||
<div>
|
||||
{this.messageBar(this.props.systemStatus.fetchStatus)}
|
||||
<div>{this.props.systemStatus.currentAction}
|
||||
</div>
|
||||
</div>
|
||||
<Content isVisible={true}>
|
||||
{children}
|
||||
</Content>
|
||||
</div >
|
||||
);
|
||||
};
|
||||
}
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(App);
|
7
samples/react-spfx-multilist-grid/src/webparts/spfxReactGrid/loc/en-us.js
vendored
Normal file
7
samples/react-spfx-multilist-grid/src/webparts/spfxReactGrid/loc/en-us.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
define([], function() {
|
||||
return {
|
||||
"PropertyPaneDescription": "Description",
|
||||
"BasicGroupName": "Group Name",
|
||||
"DescriptionFieldLabel": "Description Field"
|
||||
}
|
||||
});
|
10
samples/react-spfx-multilist-grid/src/webparts/spfxReactGrid/loc/mystrings.d.ts
vendored
Normal file
10
samples/react-spfx-multilist-grid/src/webparts/spfxReactGrid/loc/mystrings.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
declare interface ISpfxReactGridStrings {
|
||||
PropertyPaneDescription: string;
|
||||
BasicGroupName: string;
|
||||
DescriptionFieldLabel: string;
|
||||
}
|
||||
|
||||
declare module 'spfxReactGridStrings' {
|
||||
const strings: ISpfxReactGridStrings;
|
||||
export = strings;
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
export default class ColumnDefinition {
|
||||
public constructor(
|
||||
public guid: string,
|
||||
public name: string,
|
||||
public width: number,
|
||||
public editable: boolean = true,
|
||||
public type: string = "Text",
|
||||
)
|
||||
{ }
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
// for eac of the columns to be displayed, which field in this list should we use
|
||||
import { Guid } from '@microsoft/sp-client-base';
|
||||
|
||||
export class FieldDefinition {
|
||||
/** The type of field to dispay */
|
||||
public TypeAsString: string;
|
||||
/** The Internal Name of the firld */
|
||||
public InternalName: string;
|
||||
/** for Lookup Fields, the field iin the foreign list to be displayed*/
|
||||
public LookupField: string;
|
||||
/** for Lookup Fields, the Id of the web containing the foreign list*/
|
||||
public LookupWebId: string;
|
||||
/** for Lookup Fields, the Id of the foreign list*/
|
||||
public LookupList: string;
|
||||
/** for Lookup Fields, the Id of the foreign list*/
|
||||
public Choices: Array<string>;
|
||||
/** for Lookup Fields, the Id of the foreign list*/
|
||||
public Required: boolean;
|
||||
/** for Date Fiels. Determines if it is Date Only EntityPropertyName === "DateOnly" */
|
||||
public EntityPropertyName: string;
|
||||
}
|
||||
export class ColumnReference {
|
||||
public constructor(
|
||||
/** Tghe ID of this ColmnReference */
|
||||
public columnDefinitionId: string,
|
||||
/** The field in the Sharepoint list. Stored as 'internalname#;displayname')*/
|
||||
public name: string,
|
||||
/** The FULL field Definistion from sharepoint.... need to shave tos donw a bit
|
||||
* the Definition of the field iin sharepoint.... Should narrrow trhis down later I need EntityPropertyName and TypeAsString. Required,lookup info. etc...*/
|
||||
public fieldDefinition: FieldDefinition
|
||||
|
||||
) { }
|
||||
|
||||
}
|
||||
export default class ListDefinition {
|
||||
/** The columns in the Sharepoint list we ewant to edit*/
|
||||
public columnReferences: Array<ColumnReference>;
|
||||
/** The Guid of this list Definition. The id field is the id of the list in sharepoint. The guid is the ID of this listdefinition */
|
||||
public guid: string;
|
||||
public constructor(
|
||||
/** the id of the list we are pointing to in Sharepoint. Stored as id#;name */
|
||||
public id: string,
|
||||
/** the web the list is contained in. Stored as webUrl#;Title */
|
||||
public webLookup: string,
|
||||
/** the list to be disoplayed. Stored as listid#;Title */
|
||||
public listLookup: string,
|
||||
/** the url of the site holding the list. (only used during setup) */
|
||||
public siteUrl: string,
|
||||
/** the url of the list. (not used. to be deleted) */
|
||||
public url: string,
|
||||
/** A name for the listDefinition. When users add a new item, they must select the list nby this name */
|
||||
public listDefTitle: string) {
|
||||
this.columnReferences = new Array<ColumnReference>();
|
||||
this.guid = Guid.newGuid().toString();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
|
||||
export enum LookupOptionStatus {
|
||||
fetching,
|
||||
fetched,
|
||||
error
|
||||
}
|
||||
export class LookupOption {
|
||||
constructor(public id: number, public value: string) { }
|
||||
}
|
||||
export class LookupOptions {
|
||||
public status: LookupOptionStatus;
|
||||
public lookupOption:Array<LookupOption>;
|
||||
constructor(
|
||||
/** Th eurl opf the site that contains the lookup list */
|
||||
public lookupSite: string,
|
||||
/** The id of the web that contains the lookup list NOTY WORKINMG: Cannot get web by id */
|
||||
public lookupWebId: string,
|
||||
/** The id of the Liist that contains the lookup info */
|
||||
public lookupListId: string,
|
||||
/** The Internal name of the field that is being looked up */
|
||||
public lookupField: string) {
|
||||
this.status = LookupOptionStatus.fetching;
|
||||
this.lookupOption= new Array<LookupOption>();
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
//Webs is only needed when we ara ading a list, dont pupulate it until then
|
||||
|
||||
export class WebListField {
|
||||
public constructor(public id: string,
|
||||
/** the name of the field in the list stored as internalName#;name */
|
||||
public name: string,
|
||||
/** the Definition of the field iin sharepoint.... Should narrrow trhis down later I need EntityPropertyName and TypeAsString. lookup info. etc...*/
|
||||
public fieldDefinition:any,
|
||||
) {
|
||||
}
|
||||
}
|
||||
export class WebList {
|
||||
/** An array of fieldss that are contained in the list */
|
||||
public fields: Array<WebListField>;
|
||||
/** Indicates if fieldss have been fetched for this list */
|
||||
public fieldsFetched;
|
||||
public constructor(
|
||||
public id: string,
|
||||
public title: string,
|
||||
public url: string) {
|
||||
this.fieldsFetched = false;
|
||||
this.fields = new Array<WebListField>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class Web {
|
||||
/** An array of lists that are contained in the web */
|
||||
public lists: Array<WebList>;
|
||||
/** Indicates if lists have been fetched for this web */
|
||||
public listsFetched: boolean;
|
||||
public constructor(
|
||||
/** The ID of the SPWebObject as stored in Sharepoint. PRObably can be deleted */
|
||||
public id: string,
|
||||
/** The Title of the SPWebObject as stored in Sharepoint. for display puroses */
|
||||
public title: string,
|
||||
/** The Url the SPWeb*/
|
||||
public url: string) {
|
||||
this.listsFetched = false;
|
||||
this.lists = new Array<WebList>();
|
||||
}
|
||||
}
|
||||
export class Site {
|
||||
/** An array of webs, contains currently contains only webs under the rootweb. Need to change pnp to get allwebs */
|
||||
public webs: Array<Web>;
|
||||
public constructor(
|
||||
/** The url of a SiteCOllection we want to get data from */
|
||||
public url: string) {
|
||||
this.webs = new Array<Web>();
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
|
||||
export enum SiteUsersStatus {
|
||||
fetching,
|
||||
fetched,
|
||||
error
|
||||
}
|
||||
export class SiteUser {
|
||||
/** The integer id for the user within a site */
|
||||
public id: number;
|
||||
/** The display name for the user */
|
||||
public value: string;
|
||||
/** The loginID for a user, userd when moving items from one site to annother*/
|
||||
public loginName: string;
|
||||
constructor(id: number, value: string,loginName:string) {
|
||||
this.id=id;
|
||||
this.value=value;
|
||||
this.loginName=loginName;
|
||||
}
|
||||
}
|
||||
export class SiteUsers {
|
||||
public status: SiteUsersStatus;
|
||||
public siteUser: Array<SiteUser>;
|
||||
constructor(
|
||||
/** Th eurl opf the site that contains the lookup list */
|
||||
public siteUrl: string,
|
||||
|
||||
) {
|
||||
this.status = SiteUsersStatus.fetching;
|
||||
this.siteUser = new Array<SiteUser>();
|
||||
}
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
export default class {
|
||||
public currentAction:string;
|
||||
public fetchStatus:string;
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
/** if status is null row is fresh from server */
|
||||
enum GridRowStatus{
|
||||
new,
|
||||
pristine,
|
||||
modified,
|
||||
toBeDeleted
|
||||
|
||||
}
|
||||
/**Status of row )mew */
|
||||
export default GridRowStatus;
|
@ -0,0 +1,22 @@
|
||||
import GridRowStatus from "./GridRowStatus";
|
||||
import { Guid } from '@microsoft/sp-client-base';
|
||||
export default class ListItem {
|
||||
/** The listDefinition this item came from. Need this to get to columnMappings */
|
||||
public __metadata__ListDefinitionId;
|
||||
/** The Status of this . Need this to get to columnMappings */
|
||||
public __metadata__GridRowStatus: GridRowStatus;
|
||||
/** The Original Values of this item . Need this to revert changes */
|
||||
public __metadata__OriginalValues: ListItem;
|
||||
/** the internal ID for tthe listitem */
|
||||
public GUID: string;
|
||||
public ID: number;
|
||||
/**
|
||||
* When a new Item is added, its status is set to new and its given a Guid.
|
||||
* wjen we save it to sharepoint we need to refresh and get the actual goid assigned by sharepoint.
|
||||
*/
|
||||
public constructor(
|
||||
) {
|
||||
this.__metadata__GridRowStatus = GridRowStatus.new;
|
||||
this.GUID = Guid.newGuid().toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
import ColumnDefinition from "../Model/ColumnDefinition";
|
||||
import * as _ from "lodash";
|
||||
import {
|
||||
ADD_COLUMN,
|
||||
ADD_COLUMNS,
|
||||
REMOVE_COLUMN,
|
||||
SAVE_COLUMN, REMOVE_ALLCOLUMNS,
|
||||
MOVE_COLUMN_UP,
|
||||
MOVE_COLUMN_DOWN
|
||||
} from "../constants";
|
||||
|
||||
function moveColumnUp(state: Array<ColumnDefinition>, action) {
|
||||
let newstate = _.clone(state);
|
||||
|
||||
const index = _.findIndex<ColumnDefinition>(newstate, c => c.guid === action.payload.column.guid);
|
||||
newstate[index] = newstate.splice(index - 1, 1, newstate[index])[0];
|
||||
return newstate;
|
||||
}
|
||||
function moveColumnDown(state: Array<ColumnDefinition>, action) {
|
||||
let newstate = _.clone(state);
|
||||
|
||||
let index = _.findIndex<ColumnDefinition>(newstate, c => c.guid === action.payload.column.guid);
|
||||
newstate[index] = newstate.splice(index+1, 1, newstate[index])[0];
|
||||
return newstate;
|
||||
}
|
||||
const INITIAL_STATE = new Array<ColumnDefinition>();
|
||||
function listItemReducer(state = INITIAL_STATE, action: any = { type: "" }) {
|
||||
|
||||
switch (action.type) {
|
||||
case MOVE_COLUMN_UP:
|
||||
return moveColumnUp(state, action);
|
||||
case MOVE_COLUMN_DOWN:
|
||||
return moveColumnDown(state, action);
|
||||
case ADD_COLUMN:
|
||||
let newarray = _.clone(state);
|
||||
newarray.push(action.payload.column);
|
||||
return newarray;
|
||||
case SAVE_COLUMN:
|
||||
|
||||
let newarray2 = _.clone(state);
|
||||
let item = newarray2.find(item => item.guid === action.payload.column.guid);
|
||||
item = action.payload.column;
|
||||
return newarray2;
|
||||
case REMOVE_COLUMN:
|
||||
let newArr = _.filter(state, (o) => { return o.guid !== action.payload.column.guid; });
|
||||
return newArr;
|
||||
case REMOVE_ALLCOLUMNS:
|
||||
|
||||
return [];
|
||||
case ADD_COLUMNS:
|
||||
return _.union(state, action.payload.columns);
|
||||
default:
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
export default listItemReducer;
|
@ -0,0 +1,100 @@
|
||||
import ListItem from "../Model/ListItem";
|
||||
import * as _ from "lodash";
|
||||
import {
|
||||
ADD_LISTITEM,
|
||||
REMOVE_LISTITEM_SUCCESS,
|
||||
GOT_LISTITEMS,
|
||||
SAVE_LISTITEM,
|
||||
UNDO_LISTITEMCHANGES,
|
||||
UPDATE_LISTITEM_SUCCESS,
|
||||
ADDED_NEW_ITEM_TO_SHAREPOINT,
|
||||
CLEAR_LISTITEMS
|
||||
} from "../constants";
|
||||
const INITIAL_STATE = [];
|
||||
/**
|
||||
* deletes the originalvalues of a listitem, after itt has been saved to sharepoint,. This in effec disables the undo button,
|
||||
*/
|
||||
function updateListItemSuccess(state: Array<ListItem>, action: { payload: { listItem: ListItem } }) {
|
||||
let newState = _.cloneDeep(state);
|
||||
let index = _.findIndex(newState, { GUID: action.payload.listItem.GUID });
|
||||
// if (newState[index].__metadata__OriginalValues) {
|
||||
// delete newState[index].__metadata__OriginalValues;
|
||||
// }
|
||||
newState[index] = action.payload.listItem;
|
||||
return newState;
|
||||
}
|
||||
/**
|
||||
* reverts a listimes values to thos originally retrived from sharepoint
|
||||
*/
|
||||
function undoListItemChanges(state: Array<ListItem>, action: { payload: { listItem: ListItem } }) {
|
||||
let newarray3 = _.cloneDeep(state);
|
||||
let index = _.findIndex(newarray3, { GUID: action.payload.listItem.GUID });
|
||||
if (newarray3[index].__metadata__OriginalValues) {
|
||||
newarray3[index] = newarray3[index].__metadata__OriginalValues;
|
||||
}
|
||||
return newarray3;
|
||||
}
|
||||
/**
|
||||
* Adds a new listitem to the store
|
||||
*/
|
||||
function addListItem(state: Array<ListItem>, action: { payload: { listItem: ListItem } }) {
|
||||
let newarray = _.cloneDeep(state);
|
||||
newarray.unshift(action.payload.listItem);
|
||||
return newarray;
|
||||
}
|
||||
/**
|
||||
* removes a listitem from the store
|
||||
*/
|
||||
function removeListItem(state: Array<ListItem>, action: { payload: { listItem: ListItem } }) {
|
||||
// REMOVES ITEM FROM STORE. Called after item is deleted from sharepoint
|
||||
let newArr = _.filter(state, (o) => { return o.GUID !== action.payload.listItem.GUID; });
|
||||
return newArr;
|
||||
|
||||
}
|
||||
/**
|
||||
* After adding a new item to the store, updatiing it, then sending to SP ,
|
||||
* we need to replace the local copy with the values we fot back from sharepoint
|
||||
*/
|
||||
function relpaceItemInStore(state: Array<ListItem>, action: { payload: { listItem: ListItem, localCopy: ListItem } }) {
|
||||
let newState = _.cloneDeep(state);
|
||||
const idx = _.findIndex(newState, { GUID: action.payload.localCopy.GUID });
|
||||
newState[idx] = action.payload.listItem;
|
||||
return newState;
|
||||
}
|
||||
/**
|
||||
* updates a Listitem in the store
|
||||
*/
|
||||
function saveListItem(state: Array<ListItem>, action: { payload: { listItem: ListItem } }) {
|
||||
let newarray2 = _.cloneDeep(state);
|
||||
let item = newarray2.find(i => i.GUID === action.payload.listItem.GUID);
|
||||
item = action.payload.listItem;
|
||||
|
||||
if (!item.__metadata__OriginalValues) {
|
||||
item.__metadata__OriginalValues = state.find(i => i.GUID === action.payload.listItem.GUID);
|
||||
}
|
||||
return newarray2;
|
||||
}
|
||||
|
||||
function listItemReducer(state = INITIAL_STATE, action: any = { type: "" }) {
|
||||
switch (action.type) {
|
||||
case ADD_LISTITEM:
|
||||
return addListItem(state, action);
|
||||
case REMOVE_LISTITEM_SUCCESS:
|
||||
return removeListItem(state, action);
|
||||
case SAVE_LISTITEM:
|
||||
return saveListItem(state, action);
|
||||
case UPDATE_LISTITEM_SUCCESS:
|
||||
return updateListItemSuccess(state, action);
|
||||
case ADDED_NEW_ITEM_TO_SHAREPOINT:
|
||||
return relpaceItemInStore(state, action);
|
||||
case UNDO_LISTITEMCHANGES:
|
||||
return undoListItemChanges(state, action);
|
||||
case GOT_LISTITEMS:
|
||||
return _.union(state, action.payload.items);
|
||||
case CLEAR_LISTITEMS:
|
||||
return [];
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
export default listItemReducer;
|
@ -0,0 +1,49 @@
|
||||
import {
|
||||
ADD_LIST,
|
||||
REMOVE_LIST,
|
||||
REMOVE_ALLLISTS,
|
||||
ADD_LISTS,
|
||||
SAVE_LIST,
|
||||
REMOVE_COLUMN // remove the dolumn from all lists
|
||||
|
||||
|
||||
} from "../constants";
|
||||
import * as _ from "lodash";
|
||||
import ListDefinition from "../model/ListDefinition";
|
||||
const INITIAL_STATE = [];
|
||||
function listReducer(state: Array<ListDefinition> = INITIAL_STATE, action: any = { type: "" }): Array<ListDefinition> {
|
||||
switch (action.type) {
|
||||
case ADD_LIST:
|
||||
//https://spin.atomicobject.com/2016/09/27/typed-redux-reducers-typescript-2-0/
|
||||
let newarray = _.clone(state);
|
||||
newarray.push(action.payload.list);
|
||||
return newarray;
|
||||
case SAVE_LIST:
|
||||
let newarray2 = _.clone(state);
|
||||
let item = newarray2.find(item => item.guid === action.payload.list.guid);
|
||||
item = action.payload.list;
|
||||
return newarray2;
|
||||
case REMOVE_LIST:
|
||||
let newArr = _.filter(state, (o) => { return o.guid !== action.payload.list.guid; });
|
||||
return newArr;
|
||||
case REMOVE_ALLLISTS:
|
||||
return [];
|
||||
|
||||
case ADD_LISTS:
|
||||
return _.union(state, action.payload.lists);
|
||||
case REMOVE_COLUMN:
|
||||
|
||||
let listrefs = _.clone(state);
|
||||
for (const listref of listrefs) {
|
||||
for (let i = listref.columnReferences.length - 1; i >= 0; i--) {
|
||||
if (listref.columnReferences[i].columnDefinitionId === action.payload.column.guid) {
|
||||
listref.columnReferences.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return listrefs;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
export default listReducer;
|
@ -0,0 +1,54 @@
|
||||
import { LookupOptions } from "../Model/LookupOptions";
|
||||
import { Log } from "@microsoft/sp-client-base";
|
||||
import * as _ from "lodash";
|
||||
import {
|
||||
GET_LOOKUPOPTIONS,
|
||||
GET_LOOKUPOPTIONS_SUCCESS,
|
||||
GET_LOOKUPOPTIONS_ERROR
|
||||
} from "../constants";
|
||||
|
||||
function getLookupOptions(state: Array<LookupOptions>, action) {
|
||||
|
||||
let newstate = _.clone(state);
|
||||
newstate.push(action.payload.lookupOptions);
|
||||
Log.info("getLookupOptions", "Added Header Record");
|
||||
return newstate;
|
||||
}
|
||||
function updateLookupOption(state: Array<LookupOptions>, action: { payload: { lookupOptions: LookupOptions } }) {
|
||||
|
||||
let newstate = _.clone(state);
|
||||
let index = _.findIndex<LookupOptions>(newstate, x =>
|
||||
(x.lookupField === action.payload.lookupOptions.lookupField) &&
|
||||
(x.lookupListId === action.payload.lookupOptions.lookupListId) &&
|
||||
(x.lookupSite === action.payload.lookupOptions.lookupSite) &&
|
||||
(x.lookupWebId === action.payload.lookupOptions.lookupWebId));
|
||||
if (index !== -1) {
|
||||
newstate[index] = action.payload.lookupOptions;
|
||||
}
|
||||
else {
|
||||
newstate.push(action.payload.lookupOptions);
|
||||
}
|
||||
Log.info("getLookupOptions", "Updated Header Record");
|
||||
return newstate;
|
||||
}
|
||||
const INITIAL_STATE = [];
|
||||
|
||||
function lookupOptionReducer(state = INITIAL_STATE, action: any = { type: "" }) {
|
||||
|
||||
switch (action.type) {
|
||||
case GET_LOOKUPOPTIONS:
|
||||
Log.verbose("getLookupOptions", "In getLookupOptions GET_LOOKUPOPTIONS listItemReducer ActionType is " + action.type);
|
||||
return getLookupOptions(state, action);
|
||||
case GET_LOOKUPOPTIONS_SUCCESS:
|
||||
Log.verbose("getLookupOptions", "In getLookupOptions GET_LOOKUPOPTIONS_SUCCESSof listItemReducer ActionType is " + action.type);
|
||||
return updateLookupOption(state, action);
|
||||
case GET_LOOKUPOPTIONS_ERROR:
|
||||
/** The ActionCreator has set the state to error , so i just update the item */
|
||||
Log.verbose("getLookupOptions", "In getLookupOptions GET_LOOKUPOPTIONS_ERRORof listItemReducer ActionType is " + action.type);
|
||||
return updateLookupOption(state, action);
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
export default lookupOptionReducer;
|
@ -0,0 +1,12 @@
|
||||
import {
|
||||
ADD_PAGECONTEXT
|
||||
} from "../constants";
|
||||
export default function PageContextReducer(state = {}, action: any = { type: "" }) {
|
||||
switch (action.type) {
|
||||
case ADD_PAGECONTEXT:
|
||||
return action.payload.pageContext;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
import { combineReducers } from "redux";
|
||||
import ListReducer from "./ListReducer";
|
||||
import listItemReducer from "./listItemReducer";
|
||||
import ColumnReducer from "./ColumnReducer";
|
||||
import PageContextReducer from "./PageContextReducer";
|
||||
import LookupOptionsReducer from "./LookupOptionsReducer";
|
||||
import SiteReducer from "./SiteReducer";
|
||||
import SiteUserReducer from "./SiteUsersReducer";
|
||||
import SystemStatus from "./SystemStatus";
|
||||
const { routerReducer } = require("react-router-redux");
|
||||
export function RootReducer(state, action) {
|
||||
const combinedReducers = combineReducers(
|
||||
{
|
||||
items: listItemReducer,
|
||||
lists: ListReducer,
|
||||
columns: ColumnReducer,
|
||||
sites: SiteReducer,
|
||||
pageContext: PageContextReducer,
|
||||
routing: routerReducer,
|
||||
systemStatus:SystemStatus,
|
||||
lookupOptions:LookupOptionsReducer,
|
||||
siteUsers:SiteUserReducer
|
||||
}
|
||||
);
|
||||
return combinedReducers(state, action);
|
||||
}
|
||||
|
@ -0,0 +1,56 @@
|
||||
import {
|
||||
GOT_WEBS,
|
||||
GET_LISTSFORWEB_SUCCESS,
|
||||
GET_FIELDSFORLIST_SUCCESS
|
||||
|
||||
} from "../constants";
|
||||
import * as _ from "lodash";
|
||||
import { Site } from "../model/Site";
|
||||
const INITIAL_STATE: Array<Site> = [];
|
||||
function gotWebs(state: Array<Site> = INITIAL_STATE, action: any = { type: "" }): Array<Site> {
|
||||
let site: Site = new Site(action.payload.siteUrl);
|
||||
site.webs = action.payload.webs;
|
||||
let result: Array<Site> = _.union(state, new Array<Site>(site));
|
||||
return result;
|
||||
}
|
||||
function siteReducer(state: Array<Site> = INITIAL_STATE, action: any = { type: "" }): Array<Site> {
|
||||
|
||||
switch (action.type) {
|
||||
case GOT_WEBS:
|
||||
|
||||
return gotWebs(state, action);
|
||||
case GET_LISTSFORWEB_SUCCESS:
|
||||
|
||||
let newState = _.clone(state);
|
||||
//find the site and add the lists to it
|
||||
for (const site of newState) {
|
||||
for (const web of site.webs) {
|
||||
if (web.url === action.payload.webUrl) {
|
||||
web.lists = action.payload.lists;
|
||||
web.listsFetched = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return newState;
|
||||
case GET_FIELDSFORLIST_SUCCESS:
|
||||
let newState2 = _.clone(state);
|
||||
//find the site and add the lists to it
|
||||
for (const site of newState2) {
|
||||
for (const web of site.webs) {
|
||||
if (web.url === action.payload.webUrl) {
|
||||
for (const list of web.lists) {
|
||||
if (list.id === action.payload.listId) {
|
||||
list.fields = action.payload.fields;
|
||||
list.fieldsFetched = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return newState2;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
export default siteReducer;
|
||||
|
@ -0,0 +1,51 @@
|
||||
import { SiteUsers } from "../Model/SiteUsers";
|
||||
import { Log } from "@microsoft/sp-client-base";
|
||||
import * as _ from "lodash";
|
||||
import {
|
||||
GET_SITE_USERS,
|
||||
GET_SITE_USERS_SUCCESS,
|
||||
GET_SITE_USERS_ERROR
|
||||
} from "../constants";
|
||||
|
||||
function getSiteUsers(state: Array<SiteUsers>, action) {
|
||||
|
||||
let newstate = _.clone(state);
|
||||
newstate.push(action.payload.lookupOptions);
|
||||
Log.info("getLookupOptions", "Added Header Record");
|
||||
return newstate;
|
||||
}
|
||||
function updateSiteUser(state: Array<SiteUsers>, action: { payload: { siteUsers: SiteUsers } }) {
|
||||
|
||||
let newstate = _.clone(state);
|
||||
let index = _.findIndex<SiteUsers>(newstate, x =>
|
||||
(x.siteUrl === action.payload.siteUsers.siteUrl) );
|
||||
if (index !== -1) {
|
||||
newstate[index] = action.payload.siteUsers;
|
||||
}
|
||||
else {
|
||||
newstate.push(action.payload.siteUsers);
|
||||
}
|
||||
Log.info("GetSiteYsers", "Updated Header Record");
|
||||
return newstate;
|
||||
}
|
||||
const INITIAL_STATE = [];
|
||||
|
||||
function siteUsersReducer (state = INITIAL_STATE, action: any = { type: "" }) {
|
||||
|
||||
switch (action.type) {
|
||||
case GET_SITE_USERS:
|
||||
Log.verbose("getLookupOptions", "In getLookupOptions GET_SITE_USERS listItemReducer ActionType is " + action.type);
|
||||
return getSiteUsers(state, action);
|
||||
case GET_SITE_USERS_SUCCESS:
|
||||
Log.verbose("getLookupOptions", "In getLookupOptions GET_SITE_USERS_SUCCESS listItemReducer ActionType is " + action.type);
|
||||
return updateSiteUser(state, action);
|
||||
case GET_SITE_USERS_ERROR:
|
||||
/** The ActionCreator has set the state to error , so i just update the item */
|
||||
Log.verbose("getLookupOptions", "In getLookupOptions GET_SITE_USERS_ERROR listItemReducer ActionType is " + action.type);
|
||||
return updateSiteUser(state, action);
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
export default siteUsersReducer;
|
@ -0,0 +1,31 @@
|
||||
|
||||
import SystemStatus from "../Model/SystemStatus";
|
||||
const defaultStatus: SystemStatus = {
|
||||
currentAction: "",
|
||||
fetchStatus: ""
|
||||
};
|
||||
import { Log } from "@microsoft/sp-client-base";
|
||||
export default function SystemStatusReducer(state: SystemStatus = defaultStatus, action: any = { type: "" }) {
|
||||
/**
|
||||
*
|
||||
*
|
||||
* DO NOT UNCOMMENTS
|
||||
* CAUSING INFINITE LOOP
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
const newstate = _.clone(state);
|
||||
if (action.type.startsWith("App/")) {
|
||||
|
||||
newstate.currentAction = action.type;
|
||||
}
|
||||
if (action.type.endsWith("_ERROR")) {
|
||||
Log.info("SystemStatusReducer", "canged sfetch Status to action.payload.error.message");
|
||||
newstate.fetchStatus = action.payload.error.message;
|
||||
}
|
||||
return newstate;
|
||||
//return state;
|
||||
}
|
||||
|
@ -0,0 +1,71 @@
|
||||
import {
|
||||
createStore,
|
||||
applyMiddleware,
|
||||
compose,
|
||||
Middleware
|
||||
} from "redux";
|
||||
import { fromJS } from "immutable";
|
||||
import { createMemoryHistory } from "react-router";
|
||||
import { routerMiddleware } from "react-router-redux";
|
||||
import thunk from "redux-thunk";
|
||||
|
||||
import promiseMiddleware from "redux-promise-middleware";
|
||||
import logger from "./logger";
|
||||
import { RootReducer } from "../reducers/rootReducer";
|
||||
const __DEV__: boolean = true; // from webpack
|
||||
function configureStore(initialState) {
|
||||
const store = createStore(
|
||||
RootReducer,
|
||||
initialState,
|
||||
compose(
|
||||
applyMiddleware(..._getMiddleware()),
|
||||
///// persistState("session", _getStorageConfig()),
|
||||
__DEV__ && environment.devToolsExtension ?
|
||||
environment.devToolsExtension() :
|
||||
f => f));
|
||||
// _enableHotLoader(store);
|
||||
return store;
|
||||
}
|
||||
|
||||
function _getMiddleware(): Middleware[] {
|
||||
const history = createMemoryHistory();
|
||||
let middleware = [
|
||||
routerMiddleware(history),
|
||||
promiseMiddleware(),
|
||||
thunk,
|
||||
];
|
||||
if (__DEV__) {
|
||||
middleware = [...middleware, logger];
|
||||
}
|
||||
return middleware;
|
||||
}
|
||||
const environment: any = window || this;
|
||||
|
||||
// function _enableHotLoader(store) {
|
||||
// if (!__DEV__) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// const { hot } = module as any;
|
||||
// if (hot) {
|
||||
// hot.accept("../reducers", () => {
|
||||
// const nextRootReducer = require("../reducers");
|
||||
// store.replaceReducer(nextRootReducer);
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
function _getStorageConfig() {
|
||||
return {
|
||||
key: "typescript-react-redux-seed",
|
||||
serialize: (store) => {
|
||||
return store && store.session ?
|
||||
JSON.stringify(store.session.toJS()) : store;
|
||||
},
|
||||
deserialize: (state) => ({
|
||||
session: state ? fromJS(JSON.parse(state)) : fromJS({}),
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
export default configureStore;
|
@ -0,0 +1,19 @@
|
||||
const createLogger = require('redux-logger');
|
||||
import immutableToJS from '../utils/immutable-to-js';
|
||||
|
||||
|
||||
const logger = createLogger({
|
||||
collapsed: true,
|
||||
stateTransformer: (state) => {
|
||||
return immutableToJS(state);
|
||||
},
|
||||
predicate: (getState, { type }) => {
|
||||
return type !== 'redux-form/BLUR' &&
|
||||
type !== 'redux-form/CHANGE' &&
|
||||
type !== 'redux-form/FOCUS' &&
|
||||
type !== 'redux-form/TOUCH';
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
export default logger;
|
@ -0,0 +1,16 @@
|
||||
import * as React from "react";
|
||||
const { IndexRoute, Route } = require("react-router");
|
||||
import App from "../containers/app";
|
||||
import ListDefinitionContainer from "../containers/ListDefinitionContainer";
|
||||
import ColumnDefinitionContainer from "../containers/ColumnDefinitionContainer";
|
||||
import ListItemContainer from "../containers/ListItemContainer";
|
||||
export default (
|
||||
<Route path="/" component={App}>
|
||||
<IndexRoute component={ListItemContainer} />
|
||||
<Route path="/lists" component={ListDefinitionContainer}>
|
||||
</Route>
|
||||
<Route path="/columns" component={ColumnDefinitionContainer}>
|
||||
</Route>
|
||||
|
||||
</Route>
|
||||
);
|
@ -0,0 +1,18 @@
|
||||
import { Iterable } from 'immutable';
|
||||
|
||||
/**
|
||||
* [immutableToJS
|
||||
* converts properties of the provided [state] object from immutable
|
||||
* data structures to regular JavaScript data structures - used with
|
||||
* redux-logger
|
||||
*
|
||||
* @param {object} state [state reference]
|
||||
* @return {object} [transformed state]
|
||||
*/
|
||||
export default function immutableToJS(state) {
|
||||
return Object.keys(state).reduce((newState, key) => {
|
||||
const val = state[key];
|
||||
newState[key] = Iterable.isIterable(val) ? val.toJS() : val;
|
||||
return newState;
|
||||
}, {});
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { Log } from "@microsoft/sp-client-base";
|
||||
export class ParsedSPField {
|
||||
constructor(public id: string, public value: string
|
||||
) { }
|
||||
public toString(): string {
|
||||
return this.id + "#;" + this.value;
|
||||
|
||||
}
|
||||
}
|
||||
/** Parses a string that is deleimetted with '#;'. Returns a ParsedSPField where the id is the part befor the '#;' and the value is the part after the '#;'.
|
||||
* if thi input parameter is null, the id and the string of the returned ParsedSPField object will be null.
|
||||
*/
|
||||
export function ParseSPField(fieldValue: string): ParsedSPField {
|
||||
if (fieldValue === null) {
|
||||
return new ParsedSPField(null, null);
|
||||
}
|
||||
|
||||
if (fieldValue.indexOf("#;") === -1) {
|
||||
Log.info("ParseSPField", "Parse SP field called with a field value that has no '#;' delimeter. field valud is " + fieldValue);
|
||||
return new ParsedSPField(null, null);
|
||||
}
|
||||
const parts = fieldValue.split("#;");
|
||||
return new ParsedSPField(parts[0], parts[1]);
|
||||
|
||||
}
|
12
samples/react-spfx-multilist-grid/tsconfig.json
Normal file
12
samples/react-spfx-multilist-grid/tsconfig.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "commonjs",
|
||||
"jsx": "react",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
|
||||
"experimentalDecorators": true
|
||||
|
||||
}
|
||||
}
|
15
samples/react-spfx-multilist-grid/typings.json
Normal file
15
samples/react-spfx-multilist-grid/typings.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"globalDependencies": {
|
||||
"react-data-grid": "registry:dt/react-data-grid#1.0.4+20161116100048",
|
||||
"redux": "registry:dt/redux#3.5.2+20160703092728",
|
||||
"redux-promise-middleware": "registry:dt/redux-promise-middleware#0.0.0+20160108032528"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-router": "registry:npm/react-router#2.4.0+20160628165748",
|
||||
"react-router-redux": "registry:npm/react-router-redux#4.0.0+20160602212457",
|
||||
"redux-thunk": "registry:npm/redux-thunk#2.0.0+20160525185520"
|
||||
},
|
||||
"devDependencies": {
|
||||
"react-redux": "registry:npm/react-redux#4.4.0+20160614222153"
|
||||
}
|
||||
}
|
13
samples/react-spfx-multilist-grid/typings/@ms/odsp-webpack.d.ts
vendored
Normal file
13
samples/react-spfx-multilist-grid/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-spfx-multilist-grid/typings/@ms/odsp.d.ts
vendored
Normal file
10
samples/react-spfx-multilist-grid/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-spfx-multilist-grid/typings/assertion-error/assertion-error.d.ts
vendored
Normal file
15
samples/react-spfx-multilist-grid/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;
|
||||
}
|
388
samples/react-spfx-multilist-grid/typings/chai/chai.d.ts
vendored
Normal file
388
samples/react-spfx-multilist-grid/typings/chai/chai.d.ts
vendored
Normal file
@ -0,0 +1,388 @@
|
||||
// Type definitions for chai 3.2.0
|
||||
// Project: http://chaijs.com/
|
||||
// Definitions by: Jed Mao <https://github.com/jedmao/>,
|
||||
// Bart van der Schoor <https://github.com/Bartvds>,
|
||||
// Andrew Brown <https://github.com/AGBrown>,
|
||||
// Olivier Chevet <https://github.com/olivr70>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
// <reference path="../assertion-error/assertion-error.d.ts"/>
|
||||
|
||||
declare module Chai {
|
||||
|
||||
interface ChaiStatic {
|
||||
expect: ExpectStatic;
|
||||
should(): Should;
|
||||
/**
|
||||
* Provides a way to extend the internals of Chai
|
||||
*/
|
||||
use(fn: (chai: any, utils: any) => void): any;
|
||||
assert: AssertStatic;
|
||||
config: Config;
|
||||
AssertionError: AssertionError;
|
||||
}
|
||||
|
||||
export interface ExpectStatic extends AssertionStatic {
|
||||
fail(actual?: any, expected?: any, message?: string, operator?: string): void;
|
||||
}
|
||||
|
||||
export interface AssertStatic extends Assert {
|
||||
}
|
||||
|
||||
export interface AssertionStatic {
|
||||
(target: any, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface ShouldAssertion {
|
||||
equal(value1: any, value2: any, message?: string): void;
|
||||
Throw: ShouldThrow;
|
||||
throw: ShouldThrow;
|
||||
exist(value: any, message?: string): void;
|
||||
}
|
||||
|
||||
interface Should extends ShouldAssertion {
|
||||
not: ShouldAssertion;
|
||||
fail(actual: any, expected: any, message?: string, operator?: string): void;
|
||||
}
|
||||
|
||||
interface ShouldThrow {
|
||||
(actual: Function): void;
|
||||
(actual: Function, expected: string|RegExp, message?: string): void;
|
||||
(actual: Function, constructor: Error|Function, expected?: string|RegExp, message?: string): void;
|
||||
}
|
||||
|
||||
interface Assertion extends LanguageChains, NumericComparison, TypeComparison {
|
||||
not: Assertion;
|
||||
deep: Deep;
|
||||
any: KeyFilter;
|
||||
all: KeyFilter;
|
||||
a: TypeComparison;
|
||||
an: TypeComparison;
|
||||
include: Include;
|
||||
includes: Include;
|
||||
contain: Include;
|
||||
contains: Include;
|
||||
ok: Assertion;
|
||||
true: Assertion;
|
||||
false: Assertion;
|
||||
null: Assertion;
|
||||
undefined: Assertion;
|
||||
NaN: Assertion;
|
||||
exist: Assertion;
|
||||
empty: Assertion;
|
||||
arguments: Assertion;
|
||||
Arguments: Assertion;
|
||||
equal: Equal;
|
||||
equals: Equal;
|
||||
eq: Equal;
|
||||
eql: Equal;
|
||||
eqls: Equal;
|
||||
property: Property;
|
||||
ownProperty: OwnProperty;
|
||||
haveOwnProperty: OwnProperty;
|
||||
ownPropertyDescriptor: OwnPropertyDescriptor;
|
||||
haveOwnPropertyDescriptor: OwnPropertyDescriptor;
|
||||
length: Length;
|
||||
lengthOf: Length;
|
||||
match: Match;
|
||||
matches: Match;
|
||||
string(string: string, message?: string): Assertion;
|
||||
keys: Keys;
|
||||
key(string: string): Assertion;
|
||||
throw: Throw;
|
||||
throws: Throw;
|
||||
Throw: Throw;
|
||||
respondTo: RespondTo;
|
||||
respondsTo: RespondTo;
|
||||
itself: Assertion;
|
||||
satisfy: Satisfy;
|
||||
satisfies: Satisfy;
|
||||
closeTo(expected: number, delta: number, message?: string): Assertion;
|
||||
members: Members;
|
||||
increase: PropertyChange;
|
||||
increases: PropertyChange;
|
||||
decrease: PropertyChange;
|
||||
decreases: PropertyChange;
|
||||
change: PropertyChange;
|
||||
changes: PropertyChange;
|
||||
extensible: Assertion;
|
||||
sealed: Assertion;
|
||||
frozen: Assertion;
|
||||
|
||||
}
|
||||
|
||||
interface LanguageChains {
|
||||
to: Assertion;
|
||||
be: Assertion;
|
||||
been: Assertion;
|
||||
is: Assertion;
|
||||
that: Assertion;
|
||||
which: Assertion;
|
||||
and: Assertion;
|
||||
has: Assertion;
|
||||
have: Assertion;
|
||||
with: Assertion;
|
||||
at: Assertion;
|
||||
of: Assertion;
|
||||
same: Assertion;
|
||||
}
|
||||
|
||||
interface NumericComparison {
|
||||
above: NumberComparer;
|
||||
gt: NumberComparer;
|
||||
greaterThan: NumberComparer;
|
||||
least: NumberComparer;
|
||||
gte: NumberComparer;
|
||||
below: NumberComparer;
|
||||
lt: NumberComparer;
|
||||
lessThan: NumberComparer;
|
||||
most: NumberComparer;
|
||||
lte: NumberComparer;
|
||||
within(start: number, finish: number, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface NumberComparer {
|
||||
(value: number, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface TypeComparison {
|
||||
(type: string, message?: string): Assertion;
|
||||
instanceof: InstanceOf;
|
||||
instanceOf: InstanceOf;
|
||||
}
|
||||
|
||||
interface InstanceOf {
|
||||
(constructor: Object, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface Deep {
|
||||
equal: Equal;
|
||||
include: Include;
|
||||
property: Property;
|
||||
members: Members;
|
||||
}
|
||||
|
||||
interface KeyFilter {
|
||||
keys: Keys;
|
||||
}
|
||||
|
||||
interface Equal {
|
||||
(value: any, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface Property {
|
||||
(name: string, value?: any, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface OwnProperty {
|
||||
(name: string, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface OwnPropertyDescriptor {
|
||||
(name: string, descriptor: PropertyDescriptor, message?: string): Assertion;
|
||||
(name: string, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface Length extends LanguageChains, NumericComparison {
|
||||
(length: number, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface Include {
|
||||
(value: Object, message?: string): Assertion;
|
||||
(value: string, message?: string): Assertion;
|
||||
(value: number, message?: string): Assertion;
|
||||
keys: Keys;
|
||||
members: Members;
|
||||
any: KeyFilter;
|
||||
all: KeyFilter;
|
||||
}
|
||||
|
||||
interface Match {
|
||||
(regexp: RegExp|string, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface Keys {
|
||||
(...keys: string[]): Assertion;
|
||||
(keys: any[]): Assertion;
|
||||
(keys: Object): Assertion;
|
||||
}
|
||||
|
||||
interface Throw {
|
||||
(): Assertion;
|
||||
(expected: string, message?: string): Assertion;
|
||||
(expected: RegExp, message?: string): Assertion;
|
||||
(constructor: Error, expected?: string, message?: string): Assertion;
|
||||
(constructor: Error, expected?: RegExp, message?: string): Assertion;
|
||||
(constructor: Function, expected?: string, message?: string): Assertion;
|
||||
(constructor: Function, expected?: RegExp, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface RespondTo {
|
||||
(method: string, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface Satisfy {
|
||||
(matcher: Function, message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface Members {
|
||||
(set: any[], message?: string): Assertion;
|
||||
}
|
||||
|
||||
interface PropertyChange {
|
||||
(object: Object, prop: string, msg?: string): Assertion;
|
||||
}
|
||||
|
||||
export interface Assert {
|
||||
/**
|
||||
* @param expression Expression to test for truthiness.
|
||||
* @param message Message to display on error.
|
||||
*/
|
||||
(expression: any, message?: string): void;
|
||||
|
||||
fail(actual?: any, expected?: any, msg?: string, operator?: string): void;
|
||||
|
||||
ok(val: any, msg?: string): void;
|
||||
isOk(val: any, msg?: string): void;
|
||||
notOk(val: any, msg?: string): void;
|
||||
isNotOk(val: any, msg?: string): void;
|
||||
|
||||
equal(act: any, exp: any, msg?: string): void;
|
||||
notEqual(act: any, exp: any, msg?: string): void;
|
||||
|
||||
strictEqual(act: any, exp: any, msg?: string): void;
|
||||
notStrictEqual(act: any, exp: any, msg?: string): void;
|
||||
|
||||
deepEqual(act: any, exp: any, msg?: string): void;
|
||||
notDeepEqual(act: any, exp: any, msg?: string): void;
|
||||
|
||||
isTrue(val: any, msg?: string): void;
|
||||
isFalse(val: any, msg?: string): void;
|
||||
|
||||
isNull(val: any, msg?: string): void;
|
||||
isNotNull(val: any, msg?: string): void;
|
||||
|
||||
isUndefined(val: any, msg?: string): void;
|
||||
isDefined(val: any, msg?: string): void;
|
||||
|
||||
isNaN(val: any, msg?: string): void;
|
||||
isNotNaN(val: any, msg?: string): void;
|
||||
|
||||
isAbove(val: number, abv: number, msg?: string): void;
|
||||
isBelow(val: number, blw: number, msg?: string): void;
|
||||
|
||||
isFunction(val: any, msg?: string): void;
|
||||
isNotFunction(val: any, msg?: string): void;
|
||||
|
||||
isObject(val: any, msg?: string): void;
|
||||
isNotObject(val: any, msg?: string): void;
|
||||
|
||||
isArray(val: any, msg?: string): void;
|
||||
isNotArray(val: any, msg?: string): void;
|
||||
|
||||
isString(val: any, msg?: string): void;
|
||||
isNotString(val: any, msg?: string): void;
|
||||
|
||||
isNumber(val: any, msg?: string): void;
|
||||
isNotNumber(val: any, msg?: string): void;
|
||||
|
||||
isBoolean(val: any, msg?: string): void;
|
||||
isNotBoolean(val: any, msg?: string): void;
|
||||
|
||||
typeOf(val: any, type: string, msg?: string): void;
|
||||
notTypeOf(val: any, type: string, msg?: string): void;
|
||||
|
||||
instanceOf(val: any, type: Function, msg?: string): void;
|
||||
notInstanceOf(val: any, type: Function, msg?: string): void;
|
||||
|
||||
include(exp: string, inc: any, msg?: string): void;
|
||||
include(exp: any[], inc: any, msg?: string): void;
|
||||
|
||||
notInclude(exp: string, inc: any, msg?: string): void;
|
||||
notInclude(exp: any[], inc: any, msg?: string): void;
|
||||
|
||||
match(exp: any, re: RegExp, msg?: string): void;
|
||||
notMatch(exp: any, re: RegExp, msg?: string): void;
|
||||
|
||||
property(obj: Object, prop: string, msg?: string): void;
|
||||
notProperty(obj: Object, prop: string, msg?: string): void;
|
||||
deepProperty(obj: Object, prop: string, msg?: string): void;
|
||||
notDeepProperty(obj: Object, prop: string, msg?: string): void;
|
||||
|
||||
propertyVal(obj: Object, prop: string, val: any, msg?: string): void;
|
||||
propertyNotVal(obj: Object, prop: string, val: any, msg?: string): void;
|
||||
|
||||
deepPropertyVal(obj: Object, prop: string, val: any, msg?: string): void;
|
||||
deepPropertyNotVal(obj: Object, prop: string, val: any, msg?: string): void;
|
||||
|
||||
lengthOf(exp: any, len: number, msg?: string): void;
|
||||
//alias frenzy
|
||||
throw(fn: Function, msg?: string): void;
|
||||
throw(fn: Function, regExp: RegExp): void;
|
||||
throw(fn: Function, errType: Function, msg?: string): void;
|
||||
throw(fn: Function, errType: Function, regExp: RegExp): void;
|
||||
|
||||
throws(fn: Function, msg?: string): void;
|
||||
throws(fn: Function, regExp: RegExp): void;
|
||||
throws(fn: Function, errType: Function, msg?: string): void;
|
||||
throws(fn: Function, errType: Function, regExp: RegExp): void;
|
||||
|
||||
Throw(fn: Function, msg?: string): void;
|
||||
Throw(fn: Function, regExp: RegExp): void;
|
||||
Throw(fn: Function, errType: Function, msg?: string): void;
|
||||
Throw(fn: Function, errType: Function, regExp: RegExp): void;
|
||||
|
||||
doesNotThrow(fn: Function, msg?: string): void;
|
||||
doesNotThrow(fn: Function, regExp: RegExp): void;
|
||||
doesNotThrow(fn: Function, errType: Function, msg?: string): void;
|
||||
doesNotThrow(fn: Function, errType: Function, regExp: RegExp): void;
|
||||
|
||||
operator(val: any, operator: string, val2: any, msg?: string): void;
|
||||
closeTo(act: number, exp: number, delta: number, msg?: string): void;
|
||||
|
||||
sameMembers(set1: any[], set2: any[], msg?: string): void;
|
||||
sameDeepMembers(set1: any[], set2: any[], msg?: string): void;
|
||||
includeMembers(superset: any[], subset: any[], msg?: string): void;
|
||||
|
||||
ifError(val: any, msg?: string): void;
|
||||
|
||||
isExtensible(obj: {}, msg?: string): void;
|
||||
extensible(obj: {}, msg?: string): void;
|
||||
isNotExtensible(obj: {}, msg?: string): void;
|
||||
notExtensible(obj: {}, msg?: string): void;
|
||||
|
||||
isSealed(obj: {}, msg?: string): void;
|
||||
sealed(obj: {}, msg?: string): void;
|
||||
isNotSealed(obj: {}, msg?: string): void;
|
||||
notSealed(obj: {}, msg?: string): void;
|
||||
|
||||
isFrozen(obj: Object, msg?: string): void;
|
||||
frozen(obj: Object, msg?: string): void;
|
||||
isNotFrozen(obj: Object, msg?: string): void;
|
||||
notFrozen(obj: Object, msg?: string): void;
|
||||
|
||||
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
includeStack: boolean;
|
||||
}
|
||||
|
||||
export class AssertionError {
|
||||
constructor(message: string, _props?: any, ssf?: Function);
|
||||
name: string;
|
||||
message: string;
|
||||
showDiff: boolean;
|
||||
stack: string;
|
||||
}
|
||||
}
|
||||
|
||||
declare var chai: Chai.ChaiStatic;
|
||||
|
||||
declare module "chai" {
|
||||
export = chai;
|
||||
}
|
||||
|
||||
interface Object {
|
||||
should: Chai.Assertion;
|
||||
}
|
107
samples/react-spfx-multilist-grid/typings/combokeys/combokeys.d.ts
vendored
Normal file
107
samples/react-spfx-multilist-grid/typings/combokeys/combokeys.d.ts
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
// Type definitions for Combokeys v2.4.6
|
||||
// Project: https://github.com/PolicyStat/combokeys
|
||||
// Definitions by: Ian Clanton-Thuon <https://github.com/iclanton>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
|
||||
declare namespace Combokeys {
|
||||
interface CombokeysStatic {
|
||||
new (element: Element): Combokeys;
|
||||
|
||||
/**
|
||||
* all instances of Combokeys
|
||||
*/
|
||||
instances: Combokeys[];
|
||||
|
||||
/**
|
||||
* reset all instances
|
||||
*/
|
||||
reset(): void;
|
||||
}
|
||||
|
||||
interface Combokeys {
|
||||
element: Element;
|
||||
|
||||
/**
|
||||
* binds an event to Combokeys
|
||||
*
|
||||
* can be a single key, a combination of keys separated with +,
|
||||
* an array of keys, or a sequence of keys separated by spaces
|
||||
*
|
||||
* be sure to list the modifier keys first to make sure that the
|
||||
* correct key ends up getting bound (the last key in the pattern)
|
||||
*
|
||||
* @param {keys} key combination or combinations
|
||||
* @param {callback} callback function
|
||||
* @param {handler} optional - one of "keypress", "keydown", or "keyup"
|
||||
* @returns void
|
||||
*/
|
||||
bind(keys: string | string[], callback: () => void, action?: string): void;
|
||||
|
||||
|
||||
/**
|
||||
* binds multiple combinations to the same callback
|
||||
*
|
||||
* @param {keys} key combinations
|
||||
* @param {callback} callback function
|
||||
* @param {handler} optional - one of "keypress", "keydown", or "keyup"
|
||||
* @returns void
|
||||
*/
|
||||
bindMultiple(keys: string[], callback: () => void, action?: string): void;
|
||||
|
||||
/**
|
||||
* unbinds an event to Combokeys
|
||||
*
|
||||
* the unbinding sets the callback function of the specified key combo
|
||||
* to an empty function and deletes the corresponding key in the
|
||||
* directMap dict.
|
||||
*
|
||||
* the keycombo+action has to be exactly the same as
|
||||
* it was defined in the bind method
|
||||
*
|
||||
* @param {keys} key combination or combinations
|
||||
* @param {action} optional - one of "keypress", "keydown", or "keyup"
|
||||
* @returns void
|
||||
*/
|
||||
unbind(keys: string | string[], action?: string): void;
|
||||
|
||||
/**
|
||||
* triggers an event that has already been bound
|
||||
*
|
||||
* @param {keys} key combination
|
||||
* @param {action} optional - one of "keypress", "keydown", or "keyup"
|
||||
* @returns void
|
||||
*/
|
||||
trigger(keys: string, action?: string): void;
|
||||
|
||||
/**
|
||||
* resets the library back to its initial state. This is useful
|
||||
* if you want to clear out the current keyboard shortcuts and bind
|
||||
* new ones - for example if you switch to another page
|
||||
*
|
||||
* @returns void
|
||||
*/
|
||||
reset(): void;
|
||||
|
||||
/**
|
||||
* should we stop this event before firing off callbacks
|
||||
*
|
||||
* @param {e} event
|
||||
* @param {element} bound element
|
||||
* @return {boolean}
|
||||
*/
|
||||
stopCallback(e: Event, element: Element): boolean;
|
||||
|
||||
/**
|
||||
* detach all listners from the bound element
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
detach(): void;
|
||||
}
|
||||
}
|
||||
|
||||
declare var combokeys: Combokeys.CombokeysStatic;
|
||||
|
||||
declare module "combokeys" {
|
||||
export = combokeys;
|
||||
}
|
113
samples/react-spfx-multilist-grid/typings/es6-collections/es6-collections.d.ts
vendored
Normal file
113
samples/react-spfx-multilist-grid/typings/es6-collections/es6-collections.d.ts
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
// Type definitions for es6-collections v0.5.1
|
||||
// Project: https://github.com/WebReflection/es6-collections/
|
||||
// Definitions by: Ron Buckton <http://github.com/rbuckton>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
/* *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
interface IteratorResult<T> {
|
||||
done: boolean;
|
||||
value?: T;
|
||||
}
|
||||
|
||||
interface Iterator<T> {
|
||||
next(value?: any): IteratorResult<T>;
|
||||
return?(value?: any): IteratorResult<T>;
|
||||
throw?(e?: any): IteratorResult<T>;
|
||||
}
|
||||
|
||||
interface ForEachable<T> {
|
||||
forEach(callbackfn: (value: T) => void): void;
|
||||
}
|
||||
|
||||
interface Map<K, V> {
|
||||
clear(): void;
|
||||
delete(key: K): boolean;
|
||||
forEach(callbackfn: (value: V, index: K, map: Map<K, V>) => void, thisArg?: any): void;
|
||||
get(key: K): V;
|
||||
has(key: K): boolean;
|
||||
set(key: K, value?: V): Map<K, V>;
|
||||
entries(): Iterator<[K, V]>;
|
||||
keys(): Iterator<K>;
|
||||
values(): Iterator<V>;
|
||||
size: number;
|
||||
}
|
||||
|
||||
interface MapConstructor {
|
||||
new <K, V>(): Map<K, V>;
|
||||
new <K, V>(iterable: ForEachable<[K, V]>): Map<K, V>;
|
||||
prototype: Map<any, any>;
|
||||
}
|
||||
|
||||
declare var Map: MapConstructor;
|
||||
|
||||
interface Set<T> {
|
||||
add(value: T): Set<T>;
|
||||
clear(): void;
|
||||
delete(value: T): boolean;
|
||||
forEach(callbackfn: (value: T, index: T, set: Set<T>) => void, thisArg?: any): void;
|
||||
has(value: T): boolean;
|
||||
entries(): Iterator<[T, T]>;
|
||||
keys(): Iterator<T>;
|
||||
values(): Iterator<T>;
|
||||
size: number;
|
||||
}
|
||||
|
||||
interface SetConstructor {
|
||||
new <T>(): Set<T>;
|
||||
new <T>(iterable: ForEachable<T>): Set<T>;
|
||||
prototype: Set<any>;
|
||||
}
|
||||
|
||||
declare var Set: SetConstructor;
|
||||
|
||||
interface WeakMap<K, V> {
|
||||
delete(key: K): boolean;
|
||||
clear(): void;
|
||||
get(key: K): V;
|
||||
has(key: K): boolean;
|
||||
set(key: K, value?: V): WeakMap<K, V>;
|
||||
}
|
||||
|
||||
interface WeakMapConstructor {
|
||||
new <K, V>(): WeakMap<K, V>;
|
||||
new <K, V>(iterable: ForEachable<[K, V]>): WeakMap<K, V>;
|
||||
prototype: WeakMap<any, any>;
|
||||
}
|
||||
|
||||
declare var WeakMap: WeakMapConstructor;
|
||||
|
||||
interface WeakSet<T> {
|
||||
delete(value: T): boolean;
|
||||
clear(): void;
|
||||
add(value: T): WeakSet<T>;
|
||||
has(value: T): boolean;
|
||||
}
|
||||
|
||||
interface WeakSetConstructor {
|
||||
new <T>(): WeakSet<T>;
|
||||
new <T>(iterable: ForEachable<T>): WeakSet<T>;
|
||||
prototype: WeakSet<any>;
|
||||
}
|
||||
|
||||
declare var WeakSet: WeakSetConstructor;
|
||||
|
||||
declare module "es6-collections" {
|
||||
var Map: MapConstructor;
|
||||
var Set: SetConstructor;
|
||||
var WeakMap: WeakMapConstructor;
|
||||
var WeakSet: WeakSetConstructor;
|
||||
}
|
74
samples/react-spfx-multilist-grid/typings/es6-promise/es6-promise.d.ts
vendored
Normal file
74
samples/react-spfx-multilist-grid/typings/es6-promise/es6-promise.d.ts
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
// Type definitions for es6-promise
|
||||
// Project: https://github.com/jakearchibald/ES6-Promise
|
||||
// Definitions by: François de Campredon <https://github.com/fdecampredon/>, vvakame <https://github.com/vvakame>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
interface Thenable<R> {
|
||||
then<U>(onFulfilled?: (value: R) => U | Thenable<U>, onRejected?: (error: any) => U | Thenable<U>): Thenable<U>;
|
||||
then<U>(onFulfilled?: (value: R) => U | Thenable<U>, onRejected?: (error: any) => void): Thenable<U>;
|
||||
catch<U>(onRejected?: (error: any) => U | Thenable<U>): Thenable<U>;
|
||||
}
|
||||
|
||||
declare class Promise<R> implements Thenable<R> {
|
||||
/**
|
||||
* If you call resolve in the body of the callback passed to the constructor,
|
||||
* your promise is fulfilled with result object passed to resolve.
|
||||
* If you call reject your promise is rejected with the object passed to reject.
|
||||
* For consistency and debugging (eg stack traces), obj should be an instanceof Error.
|
||||
* Any errors thrown in the constructor callback will be implicitly passed to reject().
|
||||
*/
|
||||
constructor(callback: (resolve : (value?: R | Thenable<R>) => void, reject: (error?: any) => void) => void);
|
||||
|
||||
/**
|
||||
* onFulfilled is called when/if "promise" resolves. onRejected is called when/if "promise" rejects.
|
||||
* Both are optional, if either/both are omitted the next onFulfilled/onRejected in the chain is called.
|
||||
* Both callbacks have a single parameter , the fulfillment value or rejection reason.
|
||||
* "then" returns a new promise equivalent to the value you return from onFulfilled/onRejected after being passed through Promise.resolve.
|
||||
* If an error is thrown in the callback, the returned promise rejects with that error.
|
||||
*
|
||||
* @param onFulfilled called when/if "promise" resolves
|
||||
* @param onRejected called when/if "promise" rejects
|
||||
*/
|
||||
then<U>(onFulfilled?: (value: R) => U | Thenable<U>, onRejected?: (error: any) => U | Thenable<U>): Promise<U>;
|
||||
then<U>(onFulfilled?: (value: R) => U | Thenable<U>, onRejected?: (error: any) => void): Promise<U>;
|
||||
|
||||
/**
|
||||
* Sugar for promise.then(undefined, onRejected)
|
||||
*
|
||||
* @param onRejected called when/if "promise" rejects
|
||||
*/
|
||||
catch<U>(onRejected?: (error: any) => U | Thenable<U>): Promise<U>;
|
||||
}
|
||||
|
||||
declare module Promise {
|
||||
/**
|
||||
* Make a new promise from the thenable.
|
||||
* A thenable is promise-like in as far as it has a "then" method.
|
||||
*/
|
||||
function resolve<R>(value?: R | Thenable<R>): Promise<R>;
|
||||
|
||||
/**
|
||||
* Make a promise that rejects to obj. For consistency and debugging (eg stack traces), obj should be an instanceof Error
|
||||
*/
|
||||
function reject(error: any): Promise<any>;
|
||||
|
||||
/**
|
||||
* Make a promise that fulfills when every item in the array fulfills, and rejects if (and when) any item rejects.
|
||||
* the array passed to all can be a mixture of promise-like objects and other objects.
|
||||
* The fulfillment value is an array (in order) of fulfillment values. The rejection value is the first rejection value.
|
||||
*/
|
||||
function all<R>(promises: (R | Thenable<R>)[]): Promise<R[]>;
|
||||
|
||||
/**
|
||||
* Make a Promise that fulfills when any item fulfills, and rejects if any item rejects.
|
||||
*/
|
||||
function race<R>(promises: (R | Thenable<R>)[]): Promise<R>;
|
||||
}
|
||||
|
||||
declare module 'es6-promise' {
|
||||
var foo: typeof Promise; // Temp variable to reference Promise in local context
|
||||
module rsvp {
|
||||
export var Promise: typeof foo;
|
||||
}
|
||||
export = rsvp;
|
||||
}
|
498
samples/react-spfx-multilist-grid/typings/globals/react-data-grid/index.d.ts
vendored
Normal file
498
samples/react-spfx-multilist-grid/typings/globals/react-data-grid/index.d.ts
vendored
Normal file
@ -0,0 +1,498 @@
|
||||
// Generated by typings
|
||||
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/896d675b6d9dae75656e499a80ae733d904350bb/react-data-grid/react-data-grid.d.ts
|
||||
declare namespace AdazzleReactDataGrid {
|
||||
import React = __React;
|
||||
|
||||
interface SelectionParams {
|
||||
rowIdx: number,
|
||||
row: any
|
||||
}
|
||||
|
||||
interface GridProps {
|
||||
/**
|
||||
* Gets the data to render in each row. Required.
|
||||
* Can be an array or a function that takes an index and returns an object.
|
||||
*/
|
||||
rowGetter: Array<Object> | ((rowIdx: number) => Object)
|
||||
/**
|
||||
* The total number of rows to render. Required.
|
||||
*/
|
||||
rowsCount: number
|
||||
/**
|
||||
* The columns to render.
|
||||
*/
|
||||
columns?: Array<Column>
|
||||
|
||||
/**
|
||||
* Invoked when the user changes the value of a single cell.
|
||||
* Should update that cell's value.
|
||||
* @param e Information about the event
|
||||
*/
|
||||
onRowUpdated?: (e: RowUpdateEvent) => void
|
||||
/**
|
||||
* Invoked when the user pulls down the drag handle of an editable cell.
|
||||
* Should update the values of the selected cells.
|
||||
* @param e Information about the event
|
||||
*/
|
||||
onCellsDragged?: (e: CellDragEvent) => void
|
||||
/**
|
||||
* Invoked when the user double clicks on the drag handle of an editable cell.
|
||||
* Should update the values of the cells beneath the selected cell.
|
||||
* @param e Information about the event
|
||||
*/
|
||||
onDragHandleDoubleClick?: (e: DragHandleDoubleClickEvent) => void
|
||||
/**
|
||||
* Invoked when the user copies a value from one cell and pastes it into another (in the same column).
|
||||
* Should update the value of the cell in row e.toRow.
|
||||
* @param e Information about the event
|
||||
*/
|
||||
onCellCopyPaste?: (e: CellCopyPasteEvent) => void
|
||||
/**
|
||||
* Invoked after the user updates the grid rows in any way.
|
||||
* @param e Information about the event
|
||||
*/
|
||||
onGridRowsUpdated?: (e: GridRowsUpdatedEvent) => void
|
||||
|
||||
/**
|
||||
* A toolbar to display above the grid.
|
||||
* Consider using the toolbar included in "react-data-grid/addons".
|
||||
*/
|
||||
toolbar?: React.ReactElement<any>
|
||||
/**
|
||||
* A context menu to disiplay when the user right-clicks a cell.
|
||||
* Consider using "react-contextmenu", included in "react-data-grid/addons".
|
||||
*/
|
||||
contextMenu?: React.ReactElement<any>
|
||||
/**
|
||||
* A react component to customize how rows are rendered.
|
||||
* If you want to define your own, consider extending ReactDataGrid.Row.
|
||||
*/
|
||||
rowRenderer?: React.ReactElement<any> | React.ComponentClass<any> | React.StatelessComponent<any>
|
||||
/**
|
||||
* A component to display when there are no rows to render.
|
||||
*/
|
||||
emptyRowsView?: React.ComponentClass<any> | React.StatelessComponent<any>
|
||||
|
||||
/**
|
||||
* The minimum width of the entire grid in pixels.
|
||||
*/
|
||||
minWidth?: number
|
||||
/**
|
||||
* The minimum height of the entire grid in pixels.
|
||||
* @default 350
|
||||
*/
|
||||
minHeight?: number
|
||||
/**
|
||||
* The height of each individual row in pixels.
|
||||
* @default 35
|
||||
*/
|
||||
rowHeight?: number
|
||||
/**
|
||||
* The height of the header row in pixels.
|
||||
* @default rowHeight
|
||||
*/
|
||||
headerRowHeight?: number
|
||||
/**
|
||||
* The minimum width of each column in pixels.
|
||||
* @default 80
|
||||
*/
|
||||
minColumnWidth?: number
|
||||
/**
|
||||
* Invoked when a column has been resized.
|
||||
* @param index The index of the column
|
||||
* @param width The new width of the column
|
||||
*/
|
||||
onColumnResize?: (index: number, width: number) => void
|
||||
|
||||
/**
|
||||
* Controls what happens when the user navigates beyond the first or last cells.
|
||||
* 'loopOverRow' will navigate to the beginning/end of the current row.
|
||||
* 'changeRow' will navigate to the beginning of the next row or the end of the last.
|
||||
* 'none' will do nothing.
|
||||
* @default none
|
||||
*/
|
||||
cellNavigationMode?: 'none' | 'loopOverRow' | 'changeRow'
|
||||
|
||||
/**
|
||||
* Called when the user sorts the grid by some column.
|
||||
* Should update the order of the rows returned by rowGetter.
|
||||
* @param sortColumn The name of the column being sorted by
|
||||
* @param sortDirection The direction to sort ('ASC'/'DESC'/'NONE')
|
||||
*/
|
||||
onGridSort?: (sortColumn: string, sortDirection: 'ASC' | 'DESC' | 'NONE') => void
|
||||
/**
|
||||
* Called when the user filters a column by some value.
|
||||
* Should restrict the rows in rowGetter to only things that match the filter.
|
||||
* @param filter The filter being added
|
||||
*/
|
||||
onAddFilter?: (filter: Filter) => void
|
||||
/**
|
||||
* Called when the user clears all filters.
|
||||
* Should restore the rows in rowGetter to their original state.
|
||||
*/
|
||||
onClearFilters?: () => void
|
||||
|
||||
/**
|
||||
* When set to true or 'multi', enables multiple row select.
|
||||
* When set to 'single', enables single row select.
|
||||
* When set to false or not set, disables row select.
|
||||
* @default false
|
||||
*/
|
||||
enableRowSelect?: boolean | 'single' | 'multi'
|
||||
/**
|
||||
* Called when a row is selected.
|
||||
* @param rows The (complete) current selection of rows.
|
||||
*/
|
||||
onRowSelect?: (rows: Array<Object>) => void
|
||||
/**
|
||||
* A property that's unique to every row.
|
||||
* This property is required to enable row selection.
|
||||
* @default 'id'
|
||||
*/
|
||||
rowKey?: string
|
||||
|
||||
/**
|
||||
* Enables cells to be selected when clicked.
|
||||
* @default false
|
||||
*/
|
||||
enableCellSelect?: boolean
|
||||
/**
|
||||
* Called when a cell is selected.
|
||||
* @param coordinates The row and column indices of the selected cell.
|
||||
*/
|
||||
onCellSelected?: (coordinates: {rowIdx: number, idx: number}) => void
|
||||
/**
|
||||
* Called when a cell is deselected.
|
||||
* @param coordinates The row and column indices of the deselected cell.
|
||||
*/
|
||||
onCellDeSelected?: (coordinates: {rowIdx: number, idx: number}) => void
|
||||
|
||||
/**
|
||||
* How long to wait before rendering a new row while scrolling in milliseconds.
|
||||
* @default 0
|
||||
*/
|
||||
rowScrollTimeout?: number
|
||||
/**
|
||||
* Options object for selecting rows
|
||||
*/
|
||||
rowSelection?: {
|
||||
showCheckbox?: boolean
|
||||
enableShiftSelect?: boolean
|
||||
onRowsSelected?: (rows: Array<SelectionParams>) => void,
|
||||
onRowsDeselected?: (rows: Array<SelectionParams>) => void,
|
||||
selectBy?: {
|
||||
indexes?: Array<number>;
|
||||
keys?: { rowKey: string, values: Array<any> };
|
||||
isSelectedKey?: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about a specific column to be rendered.
|
||||
*/
|
||||
interface Column {
|
||||
/**
|
||||
* A unique key for this column. Required.
|
||||
* Each row should have a property with this name, which contains this column's value.
|
||||
*/
|
||||
key: string
|
||||
/**
|
||||
* This column's display name. Required.
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* A custom width for this specific column.
|
||||
* @default minColumnWidth from the ReactDataGrid
|
||||
*/
|
||||
width?: number
|
||||
/**
|
||||
* Whether this column can be resized by the user.
|
||||
* @default false
|
||||
*/
|
||||
resizable?: boolean
|
||||
/**
|
||||
* Whether this column should stay fixed on the left as the user scrolls horizontally.
|
||||
* @default false
|
||||
*/
|
||||
locked?: boolean
|
||||
/**
|
||||
* Whether this column can be edited.
|
||||
* @default false
|
||||
*/
|
||||
editable?: boolean
|
||||
/**
|
||||
* Whether the rows in the grid can be sorted by this column.
|
||||
* @default false
|
||||
*/
|
||||
sortable?: boolean
|
||||
/**
|
||||
* Whether the rows in the grid can be filtered by this column.
|
||||
* @default false
|
||||
*/
|
||||
filterable?: boolean
|
||||
/**
|
||||
* The editor for this column. Several editors are available in "react-data-grid/addons".
|
||||
* @default A simple text editor
|
||||
*/
|
||||
editor?: React.ReactElement<any>
|
||||
/**
|
||||
* A custom read-only formatter for this column. An image formatter is available in "react-data-grid/addons".
|
||||
*/
|
||||
formatter?: React.ReactElement<any> | React.ComponentClass<any> | React.StatelessComponent<any>
|
||||
/**
|
||||
* A custom formatter for this column's header.
|
||||
*/
|
||||
headerRenderer?: React.ReactElement<any> | React.ComponentClass<any> | React.StatelessComponent<any>
|
||||
/**
|
||||
* Events to be bound to the cells in this specific column.
|
||||
* Each event must respect this standard in order to work correctly:
|
||||
* @example
|
||||
* function onXxx(ev :SyntheticEvent, (rowIdx, idx, name): args)
|
||||
*/
|
||||
events?: {
|
||||
[name: string]: ColumnEventCallback
|
||||
}
|
||||
}
|
||||
|
||||
interface ColumnEventCallback {
|
||||
/**
|
||||
* A callback for a native react event on a specific cell.
|
||||
* @param ev The react event
|
||||
* @param args The row and column coordinates of the cell, and the name of the event.
|
||||
*/
|
||||
(ev: React.SyntheticEvent, args: {rowIdx: number, idx: number, name: string}): void
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about a row update
|
||||
*/
|
||||
interface RowUpdateEvent {
|
||||
/**
|
||||
* The index of the updated row.
|
||||
*/
|
||||
rowIdx: number
|
||||
/**
|
||||
* The columns that were updated and their values.
|
||||
*/
|
||||
updated: Object
|
||||
/**
|
||||
* The name of the column that was updated.
|
||||
*/
|
||||
cellKey: string
|
||||
/**
|
||||
* The name of the key pressed to trigger the event ('Tab', 'Enter', etc.).
|
||||
*/
|
||||
key: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about a cell drag
|
||||
*/
|
||||
interface CellDragEvent {
|
||||
/**
|
||||
* The name of the column that was dragged.
|
||||
*/
|
||||
cellKey: string
|
||||
/**
|
||||
* The row where the drag began.
|
||||
*/
|
||||
fromRow: number
|
||||
/**
|
||||
* The row where the drag ended.
|
||||
*/
|
||||
toRow: number
|
||||
/**
|
||||
* The value of the cell that was dragged.
|
||||
*/
|
||||
value: any
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about a drag handle double click
|
||||
*/
|
||||
interface DragHandleDoubleClickEvent {
|
||||
/**
|
||||
* The row where the double click occurred.
|
||||
*/
|
||||
rowIdx: number
|
||||
/**
|
||||
* The column where the double click occurred.
|
||||
*/
|
||||
idx: number
|
||||
/**
|
||||
* The values of the row.
|
||||
*/
|
||||
rowData: Object
|
||||
/**
|
||||
* The double click event.
|
||||
*/
|
||||
e: React.SyntheticEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about a copy paste
|
||||
*/
|
||||
interface CellCopyPasteEvent {
|
||||
/**
|
||||
* The row that was pasted to.
|
||||
*/
|
||||
rowIdx: number
|
||||
/**
|
||||
* The value that was pasted.
|
||||
*/
|
||||
value: any
|
||||
/**
|
||||
* The row that was copied from.
|
||||
*/
|
||||
fromRow: number
|
||||
/**
|
||||
* The row that was pasted to.
|
||||
*/
|
||||
toRow: number
|
||||
/**
|
||||
* The key of the column where the copy paste occurred.
|
||||
*/
|
||||
cellKey: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about some update to the grid's contents
|
||||
*/
|
||||
interface GridRowsUpdatedEvent {
|
||||
/**
|
||||
* The key of the column where the event occurred.
|
||||
*/
|
||||
cellKey: string
|
||||
/**
|
||||
* The top row affected by the event.
|
||||
*/
|
||||
fromRow: number
|
||||
/**
|
||||
* The bottom row affected by the event.
|
||||
*/
|
||||
toRow: number
|
||||
/**
|
||||
* The columns that were updated and their values.
|
||||
*/
|
||||
updated: Object
|
||||
/**
|
||||
* The action that occurred to trigger this event.
|
||||
* One of 'cellUpdate', 'cellDrag', 'columnFill', or 'copyPaste'.
|
||||
*/
|
||||
action: 'cellUpdate' | 'cellDrag' | 'columnFill' | 'copyPaste'
|
||||
}
|
||||
|
||||
/**
|
||||
* Some filter to be applied to the grid's contents
|
||||
*/
|
||||
interface Filter {
|
||||
/**
|
||||
* The key of the column being filtered.
|
||||
*/
|
||||
columnKey: string
|
||||
/**
|
||||
* The term to filter by.
|
||||
*/
|
||||
filterTerm: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Excel-like grid component built with React, with editors, keyboard navigation, copy & paste, and the like
|
||||
* http://adazzle.github.io/react-data-grid/
|
||||
*/
|
||||
export class ReactDataGrid extends React.Component<GridProps, {}> { }
|
||||
export namespace ReactDataGrid {
|
||||
// Useful types
|
||||
export import Column = AdazzleReactDataGrid.Column;
|
||||
export import Filter = AdazzleReactDataGrid.Filter;
|
||||
|
||||
// Various events
|
||||
export import RowUpdateEvent = AdazzleReactDataGrid.RowUpdateEvent;
|
||||
export import SelectionParams = AdazzleReactDataGrid.SelectionParams;
|
||||
export import CellDragEvent = AdazzleReactDataGrid.CellDragEvent;
|
||||
export import DragHandleDoubleClickEvent = AdazzleReactDataGrid.DragHandleDoubleClickEvent;
|
||||
export import CellCopyPasteEvent = AdazzleReactDataGrid.CellCopyPasteEvent;
|
||||
export import GridRowsUpdatedEvent = AdazzleReactDataGrid.GridRowsUpdatedEvent;
|
||||
|
||||
// Actual classes exposed on module.exports
|
||||
/**
|
||||
* A react component that renders a row of the grid
|
||||
*/
|
||||
export class Row extends React.Component<any, any> { }
|
||||
/**
|
||||
* A react coponent that renders a cell of the grid
|
||||
*/
|
||||
export class Cell extends React.Component<any, any> { }
|
||||
}
|
||||
}
|
||||
|
||||
declare namespace AdazzleReactDataGridPlugins {
|
||||
import React = __React;
|
||||
|
||||
// TODO: refine types for these addons
|
||||
export namespace Editors {
|
||||
export class AutoComplete extends React.Component<any, {}> { }
|
||||
export class DropDownEditor extends React.Component<any, {}> { }
|
||||
export class SimpleTextEditor extends React.Component<any, {}> { }
|
||||
export class CheckboxEditor extends React.Component<any, {}> { }
|
||||
}
|
||||
export namespace Formatters {
|
||||
export class ImageFormatter extends React.Component<any, {}> { }
|
||||
export class DropDownFormatter extends React.Component<any, {}> { }
|
||||
}
|
||||
export class Toolbar extends React.Component<any, any> {}
|
||||
// TODO: re-export the react-contextmenu typings once those exist
|
||||
// https://github.com/vkbansal/react-contextmenu/issues/10
|
||||
export namespace Menu {
|
||||
export class ContextMenu extends React.Component<any, {}> { }
|
||||
export class MenuHeader extends React.Component<any, {}> { }
|
||||
export class MenuItem extends React.Component<any, {}> { }
|
||||
export class SubMenu extends React.Component<any, {}> { }
|
||||
export const monitor: {
|
||||
getItem(): any
|
||||
getPosition(): any
|
||||
hideMenu(): void
|
||||
};
|
||||
export function connect(Menu: any): any;
|
||||
export function ContextMenuLayer(
|
||||
identifier: any,
|
||||
configure?: (props: any) => any
|
||||
): (Component: any) => any
|
||||
}
|
||||
}
|
||||
|
||||
declare module "react-data-grid" {
|
||||
import ReactDataGrid = AdazzleReactDataGrid.ReactDataGrid;
|
||||
|
||||
// commonjs export
|
||||
export = ReactDataGrid;
|
||||
}
|
||||
|
||||
declare module "react-data-grid/addons" {
|
||||
import Plugins = AdazzleReactDataGridPlugins;
|
||||
import Editors = Plugins.Editors;
|
||||
import Formatters = Plugins.Formatters;
|
||||
import Toolbar = Plugins.Toolbar;
|
||||
import Menu = Plugins.Menu;
|
||||
|
||||
// ES6 named exports
|
||||
export {
|
||||
Editors,
|
||||
Formatters,
|
||||
Toolbar,
|
||||
Menu
|
||||
}
|
||||
|
||||
// attach to window
|
||||
global {
|
||||
interface Window {
|
||||
ReactDataGridPlugins: {
|
||||
Editors: typeof Editors
|
||||
Formatters: typeof Formatters
|
||||
Toolbar: typeof Toolbar
|
||||
Menu: typeof Menu
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"resolution": "main",
|
||||
"tree": {
|
||||
"src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/896d675b6d9dae75656e499a80ae733d904350bb/react-data-grid/react-data-grid.d.ts",
|
||||
"raw": "registry:dt/react-data-grid#1.0.4+20161116100048",
|
||||
"typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/896d675b6d9dae75656e499a80ae733d904350bb/react-data-grid/react-data-grid.d.ts"
|
||||
}
|
||||
}
|
7
samples/react-spfx-multilist-grid/typings/globals/redux-promise-middleware/index.d.ts
vendored
Normal file
7
samples/react-spfx-multilist-grid/typings/globals/redux-promise-middleware/index.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
// Generated by typings
|
||||
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/e7df72296ea2a55f57ece35e28bb930ae93b19b5/redux-promise-middleware/redux-promise-middleware.d.ts
|
||||
declare module "redux-promise-middleware" {
|
||||
function promiseMiddleware(config?: { promiseTypeSuffixes: string[] }): Redux.Middleware;
|
||||
|
||||
export default promiseMiddleware;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"resolution": "main",
|
||||
"tree": {
|
||||
"src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/e7df72296ea2a55f57ece35e28bb930ae93b19b5/redux-promise-middleware/redux-promise-middleware.d.ts",
|
||||
"raw": "registry:dt/redux-promise-middleware#0.0.0+20160108032528",
|
||||
"typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/e7df72296ea2a55f57ece35e28bb930ae93b19b5/redux-promise-middleware/redux-promise-middleware.d.ts"
|
||||
}
|
||||
}
|
401
samples/react-spfx-multilist-grid/typings/globals/redux/index.d.ts
vendored
Normal file
401
samples/react-spfx-multilist-grid/typings/globals/redux/index.d.ts
vendored
Normal file
@ -0,0 +1,401 @@
|
||||
// Generated by typings
|
||||
// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/15ddcf312782faf9e7fdfe724a3a29382a5825d7/redux/redux.d.ts
|
||||
declare namespace Redux {
|
||||
/**
|
||||
* An *action* is a plain object that represents an intention to change the
|
||||
* state. Actions are the only way to get data into the store. Any data,
|
||||
* whether from UI events, network callbacks, or other sources such as
|
||||
* WebSockets needs to eventually be dispatched as actions.
|
||||
*
|
||||
* Actions must have a `type` field that indicates the type of action being
|
||||
* performed. Types can be defined as constants and imported from another
|
||||
* module. It’s better to use strings for `type` than Symbols because strings
|
||||
* are serializable.
|
||||
*
|
||||
* Other than `type`, the structure of an action object is really up to you.
|
||||
* If you’re interested, check out Flux Standard Action for recommendations on
|
||||
* how actions should be constructed.
|
||||
*/
|
||||
interface Action {
|
||||
type: any;
|
||||
}
|
||||
|
||||
|
||||
/* reducers */
|
||||
|
||||
/**
|
||||
* A *reducer* (also called a *reducing function*) is a function that accepts
|
||||
* an accumulation and a value and returns a new accumulation. They are used
|
||||
* to reduce a collection of values down to a single value
|
||||
*
|
||||
* Reducers are not unique to Redux—they are a fundamental concept in
|
||||
* functional programming. Even most non-functional languages, like
|
||||
* JavaScript, have a built-in API for reducing. In JavaScript, it's
|
||||
* `Array.prototype.reduce()`.
|
||||
*
|
||||
* In Redux, the accumulated value is the state object, and the values being
|
||||
* accumulated are actions. Reducers calculate a new state given the previous
|
||||
* state and an action. They must be *pure functions*—functions that return
|
||||
* the exact same output for given inputs. They should also be free of
|
||||
* side-effects. This is what enables exciting features like hot reloading and
|
||||
* time travel.
|
||||
*
|
||||
* Reducers are the most important concept in Redux.
|
||||
*
|
||||
* *Do not put API calls into reducers.*
|
||||
*
|
||||
* @template S State object type.
|
||||
*/
|
||||
type Reducer<S> = <A extends Action>(state: S, action: A) => S;
|
||||
|
||||
/**
|
||||
* Object whose values correspond to different reducer functions.
|
||||
*/
|
||||
interface ReducersMapObject {
|
||||
[key: string]: Reducer<any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns an object whose values are different reducer functions, into a single
|
||||
* reducer function. It will call every child reducer, and gather their results
|
||||
* into a single state object, whose keys correspond to the keys of the passed
|
||||
* reducer functions.
|
||||
*
|
||||
* @template S Combined state object type.
|
||||
*
|
||||
* @param reducers An object whose values correspond to different reducer
|
||||
* functions that need to be combined into one. One handy way to obtain it
|
||||
* is to use ES6 `import * as reducers` syntax. The reducers may never
|
||||
* return undefined for any action. Instead, they should return their
|
||||
* initial state if the state passed to them was undefined, and the current
|
||||
* state for any unrecognized action.
|
||||
*
|
||||
* @returns A reducer function that invokes every reducer inside the passed
|
||||
* object, and builds a state object with the same shape.
|
||||
*/
|
||||
function combineReducers<S>(reducers: ReducersMapObject): Reducer<S>;
|
||||
|
||||
|
||||
/* store */
|
||||
|
||||
/**
|
||||
* A *dispatching function* (or simply *dispatch function*) is a function that
|
||||
* accepts an action or an async action; it then may or may not dispatch one
|
||||
* or more actions to the store.
|
||||
*
|
||||
* We must distinguish between dispatching functions in general and the base
|
||||
* `dispatch` function provided by the store instance without any middleware.
|
||||
*
|
||||
* The base dispatch function *always* synchronously sends an action to the
|
||||
* store’s reducer, along with the previous state returned by the store, to
|
||||
* calculate a new state. It expects actions to be plain objects ready to be
|
||||
* consumed by the reducer.
|
||||
*
|
||||
* Middleware wraps the base dispatch function. It allows the dispatch
|
||||
* function to handle async actions in addition to actions. Middleware may
|
||||
* transform, delay, ignore, or otherwise interpret actions or async actions
|
||||
* before passing them to the next middleware.
|
||||
*/
|
||||
interface Dispatch<S> {
|
||||
<A extends Action>(action: A): A;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to remove listener added by `Store.subscribe()`.
|
||||
*/
|
||||
interface Unsubscribe {
|
||||
(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* A store is an object that holds the application’s state tree.
|
||||
* There should only be a single store in a Redux app, as the composition
|
||||
* happens on the reducer level.
|
||||
*
|
||||
* @template S State object type.
|
||||
*/
|
||||
interface Store<S> {
|
||||
/**
|
||||
* Dispatches an action. It is the only way to trigger a state change.
|
||||
*
|
||||
* The `reducer` function, used to create the store, will be called with the
|
||||
* current state tree and the given `action`. Its return value will be
|
||||
* considered the **next** state of the tree, and the change listeners will
|
||||
* be notified.
|
||||
*
|
||||
* The base implementation only supports plain object actions. If you want
|
||||
* to dispatch a Promise, an Observable, a thunk, or something else, you
|
||||
* need to wrap your store creating function into the corresponding
|
||||
* middleware. For example, see the documentation for the `redux-thunk`
|
||||
* package. Even the middleware will eventually dispatch plain object
|
||||
* actions using this method.
|
||||
*
|
||||
* @param action A plain object representing “what changed”. It is a good
|
||||
* idea to keep actions serializable so you can record and replay user
|
||||
* sessions, or use the time travelling `redux-devtools`. An action must
|
||||
* have a `type` property which may not be `undefined`. It is a good idea
|
||||
* to use string constants for action types.
|
||||
*
|
||||
* @returns For convenience, the same action object you dispatched.
|
||||
*
|
||||
* Note that, if you use a custom middleware, it may wrap `dispatch()` to
|
||||
* return something else (for example, a Promise you can await).
|
||||
*/
|
||||
dispatch: Dispatch<S>;
|
||||
|
||||
/**
|
||||
* Reads the state tree managed by the store.
|
||||
*
|
||||
* @returns The current state tree of your application.
|
||||
*/
|
||||
getState(): S;
|
||||
|
||||
/**
|
||||
* Adds a change listener. It will be called any time an action is
|
||||
* dispatched, and some part of the state tree may potentially have changed.
|
||||
* You may then call `getState()` to read the current state tree inside the
|
||||
* callback.
|
||||
*
|
||||
* You may call `dispatch()` from a change listener, with the following
|
||||
* caveats:
|
||||
*
|
||||
* 1. The subscriptions are snapshotted just before every `dispatch()` call.
|
||||
* If you subscribe or unsubscribe while the listeners are being invoked,
|
||||
* this will not have any effect on the `dispatch()` that is currently in
|
||||
* progress. However, the next `dispatch()` call, whether nested or not,
|
||||
* will use a more recent snapshot of the subscription list.
|
||||
*
|
||||
* 2. The listener should not expect to see all states changes, as the state
|
||||
* might have been updated multiple times during a nested `dispatch()` before
|
||||
* the listener is called. It is, however, guaranteed that all subscribers
|
||||
* registered before the `dispatch()` started will be called with the latest
|
||||
* state by the time it exits.
|
||||
*
|
||||
* @param listener A callback to be invoked on every dispatch.
|
||||
* @returns A function to remove this change listener.
|
||||
*/
|
||||
subscribe(listener: () => void): Unsubscribe;
|
||||
|
||||
/**
|
||||
* Replaces the reducer currently used by the store to calculate the state.
|
||||
*
|
||||
* You might need this if your app implements code splitting and you want to
|
||||
* load some of the reducers dynamically. You might also need this if you
|
||||
* implement a hot reloading mechanism for Redux.
|
||||
*
|
||||
* @param nextReducer The reducer for the store to use instead.
|
||||
*/
|
||||
replaceReducer(nextReducer: Reducer<S>): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* A store creator is a function that creates a Redux store. Like with
|
||||
* dispatching function, we must distinguish the base store creator,
|
||||
* `createStore(reducer, preloadedState)` exported from the Redux package, from
|
||||
* store creators that are returned from the store enhancers.
|
||||
*
|
||||
* @template S State object type.
|
||||
*/
|
||||
interface StoreCreator {
|
||||
<S>(reducer: Reducer<S>, enhancer?: StoreEnhancer<S>): Store<S>;
|
||||
<S>(reducer: Reducer<S>, preloadedState: S, enhancer?: StoreEnhancer<S>): Store<S>;
|
||||
}
|
||||
|
||||
/**
|
||||
* A store enhancer is a higher-order function that composes a store creator
|
||||
* to return a new, enhanced store creator. This is similar to middleware in
|
||||
* that it allows you to alter the store interface in a composable way.
|
||||
*
|
||||
* Store enhancers are much the same concept as higher-order components in
|
||||
* React, which are also occasionally called “component enhancers”.
|
||||
*
|
||||
* Because a store is not an instance, but rather a plain-object collection of
|
||||
* functions, copies can be easily created and modified without mutating the
|
||||
* original store. There is an example in `compose` documentation
|
||||
* demonstrating that.
|
||||
*
|
||||
* Most likely you’ll never write a store enhancer, but you may use the one
|
||||
* provided by the developer tools. It is what makes time travel possible
|
||||
* without the app being aware it is happening. Amusingly, the Redux
|
||||
* middleware implementation is itself a store enhancer.
|
||||
*/
|
||||
type StoreEnhancer<S> = (next: StoreEnhancerStoreCreator<S>) => StoreEnhancerStoreCreator<S>;
|
||||
type GenericStoreEnhancer = <S>(next: StoreEnhancerStoreCreator<S>) => StoreEnhancerStoreCreator<S>;
|
||||
type StoreEnhancerStoreCreator<S> = (reducer: Reducer<S>, preloadedState?: S) => Store<S>;
|
||||
|
||||
/**
|
||||
* Creates a Redux store that holds the state tree.
|
||||
* The only way to change the data in the store is to call `dispatch()` on it.
|
||||
*
|
||||
* There should only be a single store in your app. To specify how different
|
||||
* parts of the state tree respond to actions, you may combine several
|
||||
* reducers
|
||||
* into a single reducer function by using `combineReducers`.
|
||||
*
|
||||
* @template S State object type.
|
||||
*
|
||||
* @param reducer A function that returns the next state tree, given the
|
||||
* current state tree and the action to handle.
|
||||
*
|
||||
* @param [preloadedState] The initial state. You may optionally specify it to
|
||||
* hydrate the state from the server in universal apps, or to restore a
|
||||
* previously serialized user session. If you use `combineReducers` to
|
||||
* produce the root reducer function, this must be an object with the same
|
||||
* shape as `combineReducers` keys.
|
||||
*
|
||||
* @param [enhancer] The store enhancer. You may optionally specify it to
|
||||
* enhance the store with third-party capabilities such as middleware, time
|
||||
* travel, persistence, etc. The only store enhancer that ships with Redux
|
||||
* is `applyMiddleware()`.
|
||||
*
|
||||
* @returns A Redux store that lets you read the state, dispatch actions and
|
||||
* subscribe to changes.
|
||||
*/
|
||||
const createStore: StoreCreator;
|
||||
|
||||
|
||||
/* middleware */
|
||||
|
||||
interface MiddlewareAPI<S> {
|
||||
dispatch: Dispatch<S>;
|
||||
getState(): S;
|
||||
}
|
||||
|
||||
/**
|
||||
* A middleware is a higher-order function that composes a dispatch function
|
||||
* to return a new dispatch function. It often turns async actions into
|
||||
* actions.
|
||||
*
|
||||
* Middleware is composable using function composition. It is useful for
|
||||
* logging actions, performing side effects like routing, or turning an
|
||||
* asynchronous API call into a series of synchronous actions.
|
||||
*/
|
||||
interface Middleware {
|
||||
<S>(api: MiddlewareAPI<S>): (next: Dispatch<S>) => Dispatch<S>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a store enhancer that applies middleware to the dispatch method
|
||||
* of the Redux store. This is handy for a variety of tasks, such as
|
||||
* expressing asynchronous actions in a concise manner, or logging every
|
||||
* action payload.
|
||||
*
|
||||
* See `redux-thunk` package as an example of the Redux middleware.
|
||||
*
|
||||
* Because middleware is potentially asynchronous, this should be the first
|
||||
* store enhancer in the composition chain.
|
||||
*
|
||||
* Note that each middleware will be given the `dispatch` and `getState`
|
||||
* functions as named arguments.
|
||||
*
|
||||
* @param middlewares The middleware chain to be applied.
|
||||
* @returns A store enhancer applying the middleware.
|
||||
*/
|
||||
function applyMiddleware(...middlewares: Middleware[]): GenericStoreEnhancer;
|
||||
|
||||
|
||||
/* action creators */
|
||||
|
||||
/**
|
||||
* An *action creator* is, quite simply, a function that creates an action. Do
|
||||
* not confuse the two terms—again, an action is a payload of information, and
|
||||
* an action creator is a factory that creates an action.
|
||||
*
|
||||
* Calling an action creator only produces an action, but does not dispatch
|
||||
* it. You need to call the store’s `dispatch` function to actually cause the
|
||||
* mutation. Sometimes we say *bound action creators* to mean functions that
|
||||
* call an action creator and immediately dispatch its result to a specific
|
||||
* store instance.
|
||||
*
|
||||
* If an action creator needs to read the current state, perform an API call,
|
||||
* or cause a side effect, like a routing transition, it should return an
|
||||
* async action instead of an action.
|
||||
*
|
||||
* @template A Returned action type.
|
||||
*/
|
||||
interface ActionCreator<A> {
|
||||
(...args: any[]): A;
|
||||
}
|
||||
|
||||
/**
|
||||
* Object whose values are action creator functions.
|
||||
*/
|
||||
interface ActionCreatorsMapObject {
|
||||
[key: string]: ActionCreator<any>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns an object whose values are action creators, into an object with the
|
||||
* same keys, but with every function wrapped into a `dispatch` call so they
|
||||
* may be invoked directly. This is just a convenience method, as you can call
|
||||
* `store.dispatch(MyActionCreators.doSomething())` yourself just fine.
|
||||
*
|
||||
* For convenience, you can also pass a single function as the first argument,
|
||||
* and get a function in return.
|
||||
*
|
||||
* @param actionCreator An object whose values are action creator functions.
|
||||
* One handy way to obtain it is to use ES6 `import * as` syntax. You may
|
||||
* also pass a single function.
|
||||
*
|
||||
* @param dispatch The `dispatch` function available on your Redux store.
|
||||
*
|
||||
* @returns The object mimicking the original object, but with every action
|
||||
* creator wrapped into the `dispatch` call. If you passed a function as
|
||||
* `actionCreator`, the return value will also be a single function.
|
||||
*/
|
||||
function bindActionCreators<A extends ActionCreator<any>>(actionCreator: A, dispatch: Dispatch<any>): A;
|
||||
|
||||
function bindActionCreators<
|
||||
A extends ActionCreator<any>,
|
||||
B extends ActionCreator<any>
|
||||
>(actionCreator: A, dispatch: Dispatch<any>): B;
|
||||
|
||||
function bindActionCreators<M extends ActionCreatorsMapObject>(actionCreators: M, dispatch: Dispatch<any>): M;
|
||||
|
||||
function bindActionCreators<
|
||||
M extends ActionCreatorsMapObject,
|
||||
N extends ActionCreatorsMapObject
|
||||
>(actionCreators: M, dispatch: Dispatch<any>): N;
|
||||
|
||||
|
||||
/* compose */
|
||||
|
||||
/**
|
||||
* Composes single-argument functions from right to left. The rightmost
|
||||
* function can take multiple arguments as it provides the signature for the
|
||||
* resulting composite function.
|
||||
*
|
||||
* @param funcs The functions to compose.
|
||||
* @returns R function obtained by composing the argument functions from right
|
||||
* to left. For example, `compose(f, g, h)` is identical to doing
|
||||
* `(...args) => f(g(h(...args)))`.
|
||||
*/
|
||||
function compose(): <R>(a: R, ...args: any[]) => R;
|
||||
|
||||
function compose<A, R>(
|
||||
f1: (b: A) => R,
|
||||
f2: (...args: any[]) => A
|
||||
): (...args: any[]) => R;
|
||||
|
||||
function compose<A, B, R>(
|
||||
f1: (b: B) => R,
|
||||
f2: (a: A) => B,
|
||||
f3: (...args: any[]) => A
|
||||
): (...args: any[]) => R;
|
||||
|
||||
function compose<A, B, C, R>(
|
||||
f1: (b: C) => R,
|
||||
f2: (a: B) => C,
|
||||
f3: (a: A) => B,
|
||||
f4: (...args: any[]) => A
|
||||
): (...args: any[]) => R;
|
||||
|
||||
function compose<R>(
|
||||
f1: (a: any) => R,
|
||||
...funcs: Function[]
|
||||
): (...args: any[]) => R;
|
||||
}
|
||||
|
||||
declare module "redux" {
|
||||
export = Redux;
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"resolution": "main",
|
||||
"tree": {
|
||||
"src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/15ddcf312782faf9e7fdfe724a3a29382a5825d7/redux/redux.d.ts",
|
||||
"raw": "registry:dt/redux#3.5.2+20160703092728",
|
||||
"typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/15ddcf312782faf9e7fdfe724a3a29382a5825d7/redux/redux.d.ts"
|
||||
}
|
||||
}
|
8
samples/react-spfx-multilist-grid/typings/index.d.ts
vendored
Normal file
8
samples/react-spfx-multilist-grid/typings/index.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
/// <reference path="globals/react-data-grid/index.d.ts" />
|
||||
/// <reference path="globals/redux-promise-middleware/index.d.ts" />
|
||||
/// <reference path="globals/redux/index.d.ts" />
|
||||
/// <reference path="modules/react-redux/index.d.ts" />
|
||||
/// <reference path="modules/react-router-redux/index.d.ts" />
|
||||
/// <reference path="modules/react-router/index.d.ts" />
|
||||
/// <reference path="modules/react-select/index.d.ts" />
|
||||
/// <reference path="modules/redux-thunk/index.d.ts" />
|
631
samples/react-spfx-multilist-grid/typings/knockout/knockout.d.ts
vendored
Normal file
631
samples/react-spfx-multilist-grid/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;
|
||||
}
|
20808
samples/react-spfx-multilist-grid/typings/lodash/lodash.d.ts
vendored
Normal file
20808
samples/react-spfx-multilist-grid/typings/lodash/lodash.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
214
samples/react-spfx-multilist-grid/typings/mocha/mocha.d.ts
vendored
Normal file
214
samples/react-spfx-multilist-grid/typings/mocha/mocha.d.ts
vendored
Normal file
@ -0,0 +1,214 @@
|
||||
// Type definitions for mocha 2.2.5
|
||||
// Project: http://mochajs.org/
|
||||
// Definitions by: Kazi Manzur Rashid <https://github.com/kazimanzurrashid/>, otiai10 <https://github.com/otiai10>, jt000 <https://github.com/jt000>, Vadim Macagon <https://github.com/enlight>
|
||||
// Definitions: https://github.com/borisyankov/DefinitelyTyped
|
||||
|
||||
interface MochaSetupOptions {
|
||||
//milliseconds to wait before considering a test slow
|
||||
slow?: number;
|
||||
|
||||
// timeout in milliseconds
|
||||
timeout?: number;
|
||||
|
||||
// ui name "bdd", "tdd", "exports" etc
|
||||
ui?: string;
|
||||
|
||||
//array of accepted globals
|
||||
globals?: any[];
|
||||
|
||||
// reporter instance (function or string), defaults to `mocha.reporters.Spec`
|
||||
reporter?: any;
|
||||
|
||||
// bail on the first test failure
|
||||
bail?: boolean;
|
||||
|
||||
// ignore global leaks
|
||||
ignoreLeaks?: boolean;
|
||||
|
||||
// grep string or regexp to filter tests with
|
||||
grep?: any;
|
||||
}
|
||||
|
||||
interface MochaDone {
|
||||
(error?: Error): void;
|
||||
}
|
||||
|
||||
declare var mocha: Mocha;
|
||||
declare var describe: Mocha.IContextDefinition;
|
||||
declare var xdescribe: Mocha.IContextDefinition;
|
||||
// alias for `describe`
|
||||
declare var context: Mocha.IContextDefinition;
|
||||
// alias for `describe`
|
||||
declare var suite: Mocha.IContextDefinition;
|
||||
declare var it: Mocha.ITestDefinition;
|
||||
declare var xit: Mocha.ITestDefinition;
|
||||
// alias for `it`
|
||||
declare var test: Mocha.ITestDefinition;
|
||||
|
||||
declare function before(action: () => void): void;
|
||||
|
||||
declare function before(action: (done: MochaDone) => void): void;
|
||||
|
||||
declare function setup(action: () => void): void;
|
||||
|
||||
declare function setup(action: (done: MochaDone) => void): void;
|
||||
|
||||
declare function after(action: () => void): void;
|
||||
|
||||
declare function after(action: (done: MochaDone) => void): void;
|
||||
|
||||
declare function teardown(action: () => void): void;
|
||||
|
||||
declare function teardown(action: (done: MochaDone) => void): void;
|
||||
|
||||
declare function beforeEach(action: () => void): void;
|
||||
|
||||
declare function beforeEach(action: (done: MochaDone) => void): void;
|
||||
|
||||
declare function suiteSetup(action: () => void): void;
|
||||
|
||||
declare function suiteSetup(action: (done: MochaDone) => void): void;
|
||||
|
||||
declare function afterEach(action: () => void): void;
|
||||
|
||||
declare function afterEach(action: (done: MochaDone) => void): void;
|
||||
|
||||
declare function suiteTeardown(action: () => void): void;
|
||||
|
||||
declare function suiteTeardown(action: (done: MochaDone) => void): void;
|
||||
|
||||
declare class Mocha {
|
||||
constructor(options?: {
|
||||
grep?: RegExp;
|
||||
ui?: string;
|
||||
reporter?: string;
|
||||
timeout?: number;
|
||||
bail?: boolean;
|
||||
});
|
||||
|
||||
/** Setup mocha with the given options. */
|
||||
setup(options: MochaSetupOptions): Mocha;
|
||||
bail(value?: boolean): Mocha;
|
||||
addFile(file: string): Mocha;
|
||||
/** Sets reporter by name, defaults to "spec". */
|
||||
reporter(name: string): Mocha;
|
||||
/** Sets reporter constructor, defaults to mocha.reporters.Spec. */
|
||||
reporter(reporter: (runner: Mocha.IRunner, options: any) => any): Mocha;
|
||||
ui(value: string): Mocha;
|
||||
grep(value: string): Mocha;
|
||||
grep(value: RegExp): Mocha;
|
||||
invert(): Mocha;
|
||||
ignoreLeaks(value: boolean): Mocha;
|
||||
checkLeaks(): Mocha;
|
||||
/** Enables growl support. */
|
||||
growl(): Mocha;
|
||||
globals(value: string): Mocha;
|
||||
globals(values: string[]): Mocha;
|
||||
useColors(value: boolean): Mocha;
|
||||
useInlineDiffs(value: boolean): Mocha;
|
||||
timeout(value: number): Mocha;
|
||||
slow(value: number): Mocha;
|
||||
enableTimeouts(value: boolean): Mocha;
|
||||
asyncOnly(value: boolean): Mocha;
|
||||
noHighlighting(value: boolean): Mocha;
|
||||
/** Runs tests and invokes `onComplete()` when finished. */
|
||||
run(onComplete?: (failures: number) => void): Mocha.IRunner;
|
||||
}
|
||||
|
||||
// merge the Mocha class declaration with a module
|
||||
declare module Mocha {
|
||||
/** Partial interface for Mocha's `Runnable` class. */
|
||||
interface IRunnable {
|
||||
title: string;
|
||||
fn: Function;
|
||||
async: boolean;
|
||||
sync: boolean;
|
||||
timedOut: boolean;
|
||||
}
|
||||
|
||||
/** Partial interface for Mocha's `Suite` class. */
|
||||
interface ISuite {
|
||||
parent: ISuite;
|
||||
title: string;
|
||||
|
||||
fullTitle(): string;
|
||||
}
|
||||
|
||||
/** Partial interface for Mocha's `Test` class. */
|
||||
interface ITest extends IRunnable {
|
||||
parent: ISuite;
|
||||
pending: boolean;
|
||||
|
||||
fullTitle(): string;
|
||||
}
|
||||
|
||||
/** Partial interface for Mocha's `Runner` class. */
|
||||
interface IRunner {}
|
||||
|
||||
interface IContextDefinition {
|
||||
(description: string, spec: () => void): ISuite;
|
||||
only(description: string, spec: () => void): ISuite;
|
||||
skip(description: string, spec: () => void): void;
|
||||
timeout(ms: number): void;
|
||||
}
|
||||
|
||||
interface ITestDefinition {
|
||||
(expectation: string, assertion?: () => void): ITest;
|
||||
(expectation: string, assertion?: (done: MochaDone) => void): ITest;
|
||||
only(expectation: string, assertion?: () => void): ITest;
|
||||
only(expectation: string, assertion?: (done: MochaDone) => void): ITest;
|
||||
skip(expectation: string, assertion?: () => void): void;
|
||||
skip(expectation: string, assertion?: (done: MochaDone) => void): void;
|
||||
timeout(ms: number): void;
|
||||
}
|
||||
|
||||
export module reporters {
|
||||
export class Base {
|
||||
stats: {
|
||||
suites: number;
|
||||
tests: number;
|
||||
passes: number;
|
||||
pending: number;
|
||||
failures: number;
|
||||
};
|
||||
|
||||
constructor(runner: IRunner);
|
||||
}
|
||||
|
||||
export class Doc extends Base {}
|
||||
export class Dot extends Base {}
|
||||
export class HTML extends Base {}
|
||||
export class HTMLCov extends Base {}
|
||||
export class JSON extends Base {}
|
||||
export class JSONCov extends Base {}
|
||||
export class JSONStream extends Base {}
|
||||
export class Landing extends Base {}
|
||||
export class List extends Base {}
|
||||
export class Markdown extends Base {}
|
||||
export class Min extends Base {}
|
||||
export class Nyan extends Base {}
|
||||
export class Progress extends Base {
|
||||
/**
|
||||
* @param options.open String used to indicate the start of the progress bar.
|
||||
* @param options.complete String used to indicate a complete test on the progress bar.
|
||||
* @param options.incomplete String used to indicate an incomplete test on the progress bar.
|
||||
* @param options.close String used to indicate the end of the progress bar.
|
||||
*/
|
||||
constructor(runner: IRunner, options?: {
|
||||
open?: string;
|
||||
complete?: string;
|
||||
incomplete?: string;
|
||||
close?: string;
|
||||
});
|
||||
}
|
||||
export class Spec extends Base {}
|
||||
export class TAP extends Base {}
|
||||
export class XUnit extends Base {
|
||||
constructor(runner: IRunner, options?: any);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare module "mocha" {
|
||||
export = Mocha;
|
||||
}
|
107
samples/react-spfx-multilist-grid/typings/modules/react-redux/index.d.ts
vendored
Normal file
107
samples/react-spfx-multilist-grid/typings/modules/react-redux/index.d.ts
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
// Generated by typings
|
||||
// Source: https://raw.githubusercontent.com/andrew-w-ross/typings-redux/master/redux.d.ts
|
||||
declare module '~react-redux~redux' {
|
||||
module redux {
|
||||
//This should be extended
|
||||
export interface IAction {
|
||||
type: string | number;
|
||||
}
|
||||
|
||||
export interface IActionGeneric<TPayload> extends IAction {
|
||||
payload?: TPayload;
|
||||
error?: Error;
|
||||
meta?: any;
|
||||
}
|
||||
|
||||
export interface IReducer<TState> {
|
||||
(state: TState, action: IAction): TState;
|
||||
}
|
||||
|
||||
export interface IReducerMap {
|
||||
[key: string]: IReducerMap | IReducer<any>
|
||||
}
|
||||
|
||||
export interface IDispatch {
|
||||
(action: IAction): IAction;
|
||||
}
|
||||
|
||||
export interface IMiddlewareStore<TState> {
|
||||
getState(): TState;
|
||||
|
||||
dispatch: IDispatch;
|
||||
}
|
||||
|
||||
export interface IStore<TState> extends IMiddlewareStore<TState> {
|
||||
subscribe(listener: (state: TState) => any): () => void;
|
||||
|
||||
replaceReducer(nextReducer: IReducer<TState>): void;
|
||||
}
|
||||
|
||||
export interface IMiddleware<State> {
|
||||
(middlewareStore: IMiddlewareStore<State>): (next: IDispatch) => IDispatch;
|
||||
}
|
||||
|
||||
export interface ICreateStoreGeneric<TState> {
|
||||
(reducer: IReducer<TState>, initialState?: TState): IStore<TState>;
|
||||
}
|
||||
|
||||
export interface IStoreEnhancerGeneric<TState> {
|
||||
(createStore: ICreateStoreGeneric<TState>): ICreateStoreGeneric<TState>;
|
||||
}
|
||||
|
||||
export function createStore<TState>(reducer: IReducer<TState>, initialState?: TState): IStore<TState>;
|
||||
|
||||
export function combineReducers(reducers: IReducerMap): IReducer<any>;
|
||||
export function combineReducers<TState>(reducers: IReducerMap): IReducer<TState>;
|
||||
|
||||
export function applyMiddleware<TState>(...middlewares: IMiddleware<TState>[]): IStoreEnhancerGeneric<TState>;
|
||||
|
||||
export function bindActionCreators<TActionCreator extends Function | { [key: string]: Function }>(actionCreators: TActionCreator, dispatch: IDispatch): TActionCreator;
|
||||
|
||||
export function compose<TArg>(...functions: { (arg: TArg): TArg }[]): (arg: TArg) => TArg;
|
||||
export function compose(...functions: { (arg: any): any }[]): (arg: any) => any;
|
||||
}
|
||||
|
||||
export = redux;
|
||||
}
|
||||
|
||||
// Generated by typings
|
||||
// Source: https://raw.githubusercontent.com/andrew-w-ross/typings-react-redux/21202533f75a73d4fa4c50e0357aaf23739fcabb/react-redux.d.ts
|
||||
declare module 'react-redux' {
|
||||
|
||||
import * as React from 'react';
|
||||
import {IStore, IDispatch} from '~react-redux~redux';
|
||||
|
||||
module ReactRedux {
|
||||
|
||||
export class Provider extends React.Component<{store:IStore<any>},{}>{}
|
||||
|
||||
export interface IMapStateToProps {
|
||||
(state: any, ownProps?: any): Object;
|
||||
}
|
||||
|
||||
export interface IMapDispatchToProps {
|
||||
(dispatch: IDispatch, ownProps?: any): Object;
|
||||
}
|
||||
|
||||
export interface IConnectOptions {
|
||||
pure?: boolean;
|
||||
withRef?: boolean;
|
||||
}
|
||||
|
||||
type ComponentConstructor<P> = React.ComponentClass<P> | React.StatelessComponent<P>
|
||||
|
||||
function wrapWithConnect<T extends ComponentConstructor<any>>(
|
||||
component: T
|
||||
): T
|
||||
|
||||
export function connect(
|
||||
mapStateToProps?: IMapStateToProps,
|
||||
mapDispatchToProps?: IMapDispatchToProps | Object,
|
||||
mergeProps?: (stateProps: Object, dispatchProps: Object, ownProps: Object) => Object,
|
||||
options?: IConnectOptions
|
||||
): typeof wrapWithConnect;
|
||||
}
|
||||
|
||||
export = ReactRedux;
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"resolution": "main",
|
||||
"tree": {
|
||||
"src": "https://raw.githubusercontent.com/andrew-w-ross/typings-react-redux/21202533f75a73d4fa4c50e0357aaf23739fcabb/typings.json",
|
||||
"raw": "registry:npm/react-redux#4.4.0+20160614222153",
|
||||
"main": "react-redux.d.ts",
|
||||
"dependencies": {
|
||||
"redux": {
|
||||
"src": "https://raw.githubusercontent.com/andrew-w-ross/typings-redux/master/typings.json",
|
||||
"raw": "github:andrew-w-ross/typings-redux",
|
||||
"main": "redux.d.ts",
|
||||
"name": "redux",
|
||||
"type": "typings"
|
||||
}
|
||||
},
|
||||
"name": "react-redux",
|
||||
"type": "typings"
|
||||
}
|
||||
}
|
334
samples/react-spfx-multilist-grid/typings/modules/react-router-redux/index.d.ts
vendored
Normal file
334
samples/react-spfx-multilist-grid/typings/modules/react-router-redux/index.d.ts
vendored
Normal file
@ -0,0 +1,334 @@
|
||||
// Generated by typings
|
||||
// Source: https://raw.githubusercontent.com/andrew-w-ross/typings-history/master/history.d.ts
|
||||
declare module '~react-router-redux~history' {
|
||||
module otherHistory {
|
||||
type Action = 'PUSH' | 'REPLACE' | 'POP';
|
||||
|
||||
type BeforeUnloadHook = () => string | void;
|
||||
|
||||
type CreateLocation = (path: string, locationObj: Object) => Location;
|
||||
|
||||
type CreateHistoryDefault = CreateHistory<HistoryOptions, History>;
|
||||
|
||||
type CreateHistory<TOptions extends HistoryOptions, TResult extends History> = (options?: TOptions) => TResult;
|
||||
|
||||
type Hash = string;
|
||||
|
||||
interface History {
|
||||
listenBefore(hook: TransitionHook): Function;
|
||||
listen(listener: LocationListener): Function;
|
||||
transitionTo(location: Location): void;
|
||||
push(location: LocationDescriptor): void;
|
||||
replace(location: LocationDescriptor): void;
|
||||
go(n: number): void;
|
||||
goBack(): void;
|
||||
goForward(): void;
|
||||
createKey(): LocationKey;
|
||||
createLocation: CreateLocation;
|
||||
createPath(location: LocationDescriptor): Path;
|
||||
createHref(location: LocationDescriptor): Href;
|
||||
}
|
||||
|
||||
interface HistoryOptions {
|
||||
getUserConfirmation?(message: string, callback: (confirmed: boolean) => void): void;
|
||||
queryKey?: boolean | string;
|
||||
}
|
||||
|
||||
interface BeforeUnload {
|
||||
listenBeforeUnload?(callBack: () => string | boolean | void): void;
|
||||
}
|
||||
|
||||
interface QueryOptions {
|
||||
parseQueryString?(queryString: string): any;
|
||||
stringifyQuery?(query: Object): string;
|
||||
}
|
||||
|
||||
interface BasenameOptions {
|
||||
basename?: string;
|
||||
}
|
||||
|
||||
type Href = string;
|
||||
|
||||
interface Location {
|
||||
pathname?: Pathname;
|
||||
search?: Search;
|
||||
query?: Query;
|
||||
state?: LocationState;
|
||||
action?: Action;
|
||||
key?: LocationKey;
|
||||
}
|
||||
|
||||
interface LocationDescriptorObject {
|
||||
pathname?: Pathname;
|
||||
search?: Search;
|
||||
query?: Query;
|
||||
state?: LocationState;
|
||||
}
|
||||
|
||||
type LocationDescriptor = LocationDescriptorObject | Path;
|
||||
|
||||
type LocationKey = string;
|
||||
|
||||
type LocationListener = (location: Location) => void;
|
||||
|
||||
type LocationState = Object;
|
||||
|
||||
type Path = string;
|
||||
|
||||
type Pathname = string;
|
||||
|
||||
type Query = Object;
|
||||
|
||||
type Search = string;
|
||||
|
||||
type TransitionHook = (location: Location, callback?: Function) => any;
|
||||
|
||||
export const createLocation: CreateLocation;
|
||||
|
||||
export const createHistory: CreateHistoryDefault;
|
||||
|
||||
export const createHashHistory: CreateHistoryDefault;
|
||||
|
||||
export const createMemoryHistory: CreateHistoryDefault;
|
||||
|
||||
export function useBeforeUnload<TArguments, TResult extends History>(createHistory: CreateHistory<TArguments, TResult>): CreateHistory<TArguments, TResult & BeforeUnload>;
|
||||
|
||||
export function useQueries<TArguments, TResult extends History>(createHistory: CreateHistory<TArguments, TResult>): CreateHistory<TArguments & QueryOptions, TResult>;
|
||||
|
||||
export function useBasename<TArguments, TResult extends History>(createHistory: CreateHistory<TArguments, TResult>): CreateHistory<TArguments & BasenameOptions, TResult>;
|
||||
}
|
||||
|
||||
export = otherHistory;
|
||||
}
|
||||
|
||||
// Generated by typings
|
||||
// Source: https://raw.githubusercontent.com/andrew-w-ross/typings-redux/master/redux.d.ts
|
||||
declare module '~react-router-redux~redux' {
|
||||
module redux {
|
||||
//This should be extended
|
||||
export interface IAction {
|
||||
type: string | number;
|
||||
}
|
||||
|
||||
export interface IActionGeneric<TPayload> extends IAction {
|
||||
payload?: TPayload;
|
||||
error?: Error;
|
||||
meta?: any;
|
||||
}
|
||||
|
||||
export interface IReducer<TState> {
|
||||
(state: TState, action: IAction): TState;
|
||||
}
|
||||
|
||||
export interface IReducerMap {
|
||||
[key: string]: IReducerMap | IReducer<any>
|
||||
}
|
||||
|
||||
export interface IDispatch {
|
||||
(action: IAction): IAction;
|
||||
}
|
||||
|
||||
export interface IMiddlewareStore<TState> {
|
||||
getState(): TState;
|
||||
|
||||
dispatch: IDispatch;
|
||||
}
|
||||
|
||||
export interface IStore<TState> extends IMiddlewareStore<TState> {
|
||||
subscribe(listener: (state: TState) => any): () => void;
|
||||
|
||||
replaceReducer(nextReducer: IReducer<TState>): void;
|
||||
}
|
||||
|
||||
export interface IMiddleware<State> {
|
||||
(middlewareStore: IMiddlewareStore<State>): (next: IDispatch) => IDispatch;
|
||||
}
|
||||
|
||||
export interface ICreateStoreGeneric<TState> {
|
||||
(reducer: IReducer<TState>, initialState?: TState): IStore<TState>;
|
||||
}
|
||||
|
||||
export interface IStoreEnhancerGeneric<TState> {
|
||||
(createStore: ICreateStoreGeneric<TState>): ICreateStoreGeneric<TState>;
|
||||
}
|
||||
|
||||
export function createStore<TState>(reducer: IReducer<TState>, initialState?: TState): IStore<TState>;
|
||||
|
||||
export function combineReducers(reducers: IReducerMap): IReducer<any>;
|
||||
export function combineReducers<TState>(reducers: IReducerMap): IReducer<TState>;
|
||||
|
||||
export function applyMiddleware<TState>(...middlewares: IMiddleware<TState>[]): IStoreEnhancerGeneric<TState>;
|
||||
|
||||
export function bindActionCreators<TActionCreator extends Function | { [key: string]: Function }>(actionCreators: TActionCreator, dispatch: IDispatch): TActionCreator;
|
||||
|
||||
export function compose<TArg>(...functions: { (arg: TArg): TArg }[]): (arg: TArg) => TArg;
|
||||
export function compose(...functions: { (arg: any): any }[]): (arg: any) => any;
|
||||
}
|
||||
|
||||
export = redux;
|
||||
}
|
||||
|
||||
// Generated by typings
|
||||
// Source: https://raw.githubusercontent.com/andrew-w-ross/typings-react-router-redux/caf792cb79efbf54ce328366809dc52821192a73/react-router-redux.d.ts
|
||||
declare module 'react-router-redux' {
|
||||
|
||||
import {History, Location, LocationDescriptor} from '~react-router-redux~history';
|
||||
import {IMiddleware, IStore, IAction, IReducer} from '~react-router-redux~redux';
|
||||
|
||||
module reactRouterRedux {
|
||||
/**
|
||||
* An action type that you can listen for in your reducers to be notified of route updates. Fires after any changes to history.
|
||||
*/
|
||||
export const LOCATION_CHANGE: string;
|
||||
|
||||
/**
|
||||
* Router action
|
||||
*/
|
||||
export interface RouterAction extends IAction {
|
||||
/**
|
||||
* New location
|
||||
*/
|
||||
payload: Location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redux router internal state. Useful if you're overriding own reducer
|
||||
*/
|
||||
export interface IRouterState {
|
||||
locationBeforeTransitions: Location;
|
||||
}
|
||||
|
||||
/**
|
||||
* History syncing options
|
||||
*/
|
||||
interface ISyncHistoryOptions<TState> {
|
||||
/**
|
||||
* When false, the URL will not be kept in sync during time travel.
|
||||
* This is useful when using persistState from Redux DevTools and not wanting to maintain the URL state when restoring state.
|
||||
* @default true
|
||||
*/
|
||||
adjustUrlOnReplay?: boolean;
|
||||
/**
|
||||
* A selector function to obtain the history state from your store.
|
||||
* Useful when not using the provided routerReducer to store history state. Allows you to use wrappers, such as Immutable.js.
|
||||
* @default state => state.routing
|
||||
*/
|
||||
selectLocationState?: (state: TState) => IRouterState;
|
||||
}
|
||||
|
||||
/**
|
||||
* @export
|
||||
* @template TState
|
||||
* @param {History} history History singleton from react-router
|
||||
* @param {IStore<TState>} store Application store
|
||||
* @param {ISyncHistoryOptions<TState>} options Syncing options
|
||||
*/
|
||||
export function syncHistoryWithStore<TState>(history: History, store: IStore<TState>, options?: ISyncHistoryOptions<TState>): History;
|
||||
|
||||
/**
|
||||
* A reducer function that keeps track of the router state. You must add this reducer to your app reducers when creating the store.
|
||||
* It will return a location property in state. If you use combineReducers, it will be nested under wherever property you add it to (state.routing in the example above).
|
||||
* Warning: It is a bad pattern to use react-redux's connect decorator to map the state from this reducer to props on your Route components. This can lead to infinite loops and performance problems. react-router already provides this for you via this.props.location.
|
||||
*
|
||||
* @export
|
||||
* @param {Location} state (description)
|
||||
* @param {IAction} action (description)
|
||||
* @returns {Location} (description)
|
||||
*/
|
||||
export function routerReducer(state: IRouterState, action: RouterAction): IRouterState;
|
||||
|
||||
|
||||
/**
|
||||
* A middleware you can apply to your Redux store to capture dispatched actions created by the action creators.
|
||||
* It will redirect those actions to the provided history instance.
|
||||
*/
|
||||
export function routerMiddleware<TState>(history: History): IMiddleware<TState>;
|
||||
|
||||
// Action types interfaces. These are deprecated
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
interface IRoutePushAction {
|
||||
(nextLocation: LocationDescriptor): IAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
interface IRouteReplaceAction {
|
||||
(nextLocation: LocationDescriptor): IAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
interface IRouteGoAction {
|
||||
(n: number): IAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
interface IRouteGoForwardAction {
|
||||
(): IAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
interface IRouteGoBackAction {
|
||||
(): IAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
export interface IRouteActions {
|
||||
push: IRoutePushAction;
|
||||
replace: IRouteReplaceAction;
|
||||
go: IRouteGoAction;
|
||||
goForward: IRouteGoForwardAction;
|
||||
goBack: IRouteGoBackAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* An object that contains all the actions creators you can use to manipulate history:
|
||||
* @deprecated
|
||||
* @export
|
||||
*/
|
||||
export const routerActions: IRouteActions;
|
||||
|
||||
/**
|
||||
* This action type will be dispatched by the history actions below.
|
||||
* If you're writing a middleware to watch for navigation events, be sure to
|
||||
* look for actions of this type.
|
||||
* @export
|
||||
*/
|
||||
export const CALL_HISTORY_METHOD: string;
|
||||
|
||||
// separate actions
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
export const push: IRoutePushAction;
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
export const replace: IRouteReplaceAction;
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
export const go: IRouteGoAction;
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
export const goForward: IRouteGoForwardAction;
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
export const goBack: IRouteGoBackAction;
|
||||
|
||||
}
|
||||
|
||||
export = reactRouterRedux;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
{
|
||||
"resolution": "main",
|
||||
"tree": {
|
||||
"src": "https://raw.githubusercontent.com/andrew-w-ross/typings-react-router-redux/caf792cb79efbf54ce328366809dc52821192a73/typings.json",
|
||||
"raw": "registry:npm/react-router-redux#4.0.0+20160602212457",
|
||||
"main": "react-router-redux.d.ts",
|
||||
"dependencies": {
|
||||
"history": {
|
||||
"src": "https://raw.githubusercontent.com/andrew-w-ross/typings-history/master/typings.json",
|
||||
"raw": "github:andrew-w-ross/typings-history",
|
||||
"main": "history.d.ts",
|
||||
"name": "history",
|
||||
"type": "typings"
|
||||
},
|
||||
"redux": {
|
||||
"src": "https://raw.githubusercontent.com/andrew-w-ross/typings-redux/master/typings.json",
|
||||
"raw": "github:andrew-w-ross/typings-redux",
|
||||
"main": "redux.d.ts",
|
||||
"name": "redux",
|
||||
"type": "typings"
|
||||
}
|
||||
},
|
||||
"name": "react-router-redux",
|
||||
"type": "typings"
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user