diff --git a/.gitignore b/.gitignore index 95c67bea7..79e05a2a0 100644 --- a/.gitignore +++ b/.gitignore @@ -9,8 +9,8 @@ node_modules # Build generated files dist lib -solution temp +solution/debug # Coverage directory used by tools like istanbul coverage diff --git a/config/write-manifests.json b/config/write-manifests.json index 661b6410d..540f4d140 100644 --- a/config/write-manifests.json +++ b/config/write-manifests.json @@ -1,3 +1,3 @@ { - "cdnBasePath": "https://publiccdn.sharepointonline.com/spptechnologies.sharepoint.com/110700492eeea162ee5bad0f35b1f0061ded8bf436ce0199efe2a4d24109e1c0df1ec594/react-content-query" + "cdnBasePath": "https://publiccdn.sharepointonline.com/spptechnologies.sharepoint.com/110700492eeea162ee5bad0f35b1f0061ded8bf436ce0199efe2a4d24109e1c0df1ec594/react-content-query-1.0.0" } \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index ee7bd4d46..82f8f4ca7 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -6,12 +6,23 @@ const build = require('@microsoft/sp-build-web'); /******************************************************************************************** * Adds an alias for handlebars in order to avoid errors while gulping the project * https://github.com/wycats/handlebars.js/issues/1174 + * Adds a loader and a node setting for webpacking the handlebars-helpers correctly + * https://github.com/helpers/handlebars-helpers/issues/263 ********************************************************************************************/ -build.configureWebpack.mergeConfig({ - additionalConfiguration: (generatedConfiguration) => { - generatedConfiguration.resolve.alias = { handlebars: 'handlebars/dist/handlebars.min.js' }; - return generatedConfiguration; - } +build.configureWebpack.mergeConfig({ + additionalConfiguration: (generatedConfiguration) => { + generatedConfiguration.resolve.alias = { handlebars: 'handlebars/dist/handlebars.min.js' }; + + generatedConfiguration.module.loaders.push({ + test: /\.js$/, loader: 'unlazy' + }); + + generatedConfiguration.node = { + fs: 'empty' + } + + return generatedConfiguration; + } }); -build.initialize(gulp); +build.initialize(gulp); \ No newline at end of file diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 84f61a330..7107085c6 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "react-content-query", - "version": "0.0.1", + "version": "1.0.0", "dependencies": { "@microsoft/api-extractor": { "version": "1.1.15", @@ -737,14 +737,12 @@ "ansi-regex": { "version": "2.1.1", "from": "ansi-regex@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" }, "ansi-styles": { "version": "2.2.1", "from": "ansi-styles@>=2.2.1 <3.0.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz" }, "anymatch": { "version": "1.3.0", @@ -779,14 +777,24 @@ "arr-diff": { "version": "2.0.0", "from": "arr-diff@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz" + }, + "arr-filter": { + "version": "1.1.2", + "from": "arr-filter@>=1.1.1 <2.0.0", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "dependencies": { + "make-iterator": { + "version": "1.0.0", + "from": "make-iterator@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz" + } + } }, "arr-flatten": { "version": "1.0.1", "from": "arr-flatten@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.1.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.1.tgz" }, "array-differ": { "version": "1.0.0", @@ -812,6 +820,18 @@ "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", "dev": true }, + "array-sort": { + "version": "0.1.2", + "from": "array-sort@>=0.1.2 <0.2.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-0.1.2.tgz", + "dependencies": { + "kind-of": { + "version": "2.0.1", + "from": "kind-of@>=2.0.0 <3.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz" + } + } + }, "array-union": { "version": "1.0.2", "from": "array-union@>=1.0.1 <2.0.0", @@ -827,8 +847,7 @@ "array-unique": { "version": "0.2.1", "from": "array-unique@>=0.2.1 <0.3.0", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz" }, "arraybuffer.slice": { "version": "0.0.6", @@ -897,6 +916,11 @@ "from": "asynckit@>=0.4.0 <0.5.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" }, + "autolinker": { + "version": "0.15.3", + "from": "autolinker@>=0.15.0 <0.16.0", + "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-0.15.3.tgz" + }, "autoprefixer": { "version": "6.3.7", "from": "autoprefixer@6.3.7", @@ -1185,8 +1209,7 @@ "braces": { "version": "1.8.5", "from": "braces@>=1.8.2 <2.0.0", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz" }, "browserify-mime": { "version": "1.2.9", @@ -1311,8 +1334,7 @@ "chalk": { "version": "1.1.3", "from": "chalk@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz" }, "charenc": { "version": "0.0.2", @@ -1703,6 +1725,23 @@ "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", "dev": true }, + "create-frame": { + "version": "1.0.0", + "from": "create-frame@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/create-frame/-/create-frame-1.0.0.tgz", + "dependencies": { + "isobject": { + "version": "3.0.0", + "from": "isobject@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.0.tgz" + }, + "lazy-cache": { + "version": "2.0.2", + "from": "lazy-cache@^2.0.2", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz" + } + } + }, "cross-spawn": { "version": "3.0.1", "from": "cross-spawn@>=3.0.0 <4.0.0", @@ -1866,6 +1905,18 @@ "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", "dev": true }, + "date.js": { + "version": "0.3.1", + "from": "date.js@>=0.3.1 <0.4.0", + "resolved": "https://registry.npmjs.org/date.js/-/date.js-0.3.1.tgz", + "dependencies": { + "debug": { + "version": "0.7.4", + "from": "debug@>=0.7.2 <0.8.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" + } + } + }, "dateformat": { "version": "2.0.0", "from": "dateformat@>=2.0.0 <3.0.0", @@ -1941,6 +1992,11 @@ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", "dev": true }, + "define-property": { + "version": "0.2.5", + "from": "define-property@>=0.2.5 <0.3.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz" + }, "defined": { "version": "1.0.0", "from": "defined@>=1.0.0 <2.0.0", @@ -2182,8 +2238,7 @@ "ent": { "version": "2.2.0", "from": "ent@>=2.2.0 <2.3.0", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz" }, "envify": { "version": "3.4.1", @@ -2234,8 +2289,7 @@ "escape-string-regexp": { "version": "1.0.5", "from": "escape-string-regexp@>=1.0.2 <2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" }, "escodegen": { "version": "1.8.1", @@ -2320,14 +2374,12 @@ "expand-brackets": { "version": "0.1.5", "from": "expand-brackets@>=0.1.4 <0.2.0", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz" }, "expand-range": { "version": "1.8.2", "from": "expand-range@>=1.8.1 <2.0.0", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz" }, "expand-tilde": { "version": "1.2.2", @@ -2413,14 +2465,12 @@ "extend-shallow": { "version": "2.0.1", "from": "extend-shallow@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" }, "extglob": { "version": "0.3.2", "from": "extglob@>=0.3.1 <0.4.0", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz" }, "extract-zip": { "version": "1.5.0", @@ -2503,14 +2553,12 @@ "filename-regex": { "version": "2.0.0", "from": "filename-regex@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.0.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.0.tgz" }, "fill-range": { "version": "2.2.3", "from": "fill-range@>=2.1.0 <3.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz" }, "filled-array": { "version": "1.1.0", @@ -2577,14 +2625,12 @@ "for-in": { "version": "1.0.2", "from": "for-in@>=1.0.1 <2.0.0", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" }, "for-own": { "version": "0.1.5", "from": "for-own@>=0.1.4 <0.2.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz" }, "forever-agent": { "version": "0.6.1", @@ -2629,8 +2675,7 @@ "fs-exists-sync": { "version": "0.1.0", "from": "fs-exists-sync@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz" }, "fs-extra": { "version": "0.26.7", @@ -2692,12 +2737,29 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", "dev": true }, + "get-object": { + "version": "0.2.0", + "from": "get-object@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/get-object/-/get-object-0.2.0.tgz", + "dependencies": { + "isobject": { + "version": "0.2.0", + "from": "isobject@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-0.2.0.tgz" + } + } + }, "get-stdin": { "version": "4.0.1", "from": "get-stdin@>=4.0.1 <5.0.0", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "dev": true }, + "get-value": { + "version": "2.0.6", + "from": "get-value@>=2.0.6 <3.0.0", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz" + }, "getpass": { "version": "0.1.6", "from": "getpass@>=0.1.1 <0.2.0", @@ -2719,8 +2781,7 @@ "glob-base": { "version": "0.3.0", "from": "glob-base@>=0.3.0 <0.4.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz" }, "glob-escape": { "version": "0.0.2", @@ -2731,8 +2792,7 @@ "glob-parent": { "version": "2.0.0", "from": "glob-parent@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz" }, "glob-stream": { "version": "3.1.18", @@ -3657,6 +3717,38 @@ } } }, + "handlebars-helpers": { + "version": "0.8.2", + "from": "handlebars-helpers@latest", + "resolved": "https://registry.npmjs.org/handlebars-helpers/-/handlebars-helpers-0.8.2.tgz", + "dependencies": { + "for-in": { + "version": "0.1.8", + "from": "for-in@>=0.1.6 <0.2.0", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz" + }, + "is-extglob": { + "version": "2.1.1", + "from": "is-extglob@>=2.1.0 <3.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + }, + "is-glob": { + "version": "3.1.0", + "from": "is-glob@>=3.1.0 <4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz" + }, + "is-number": { + "version": "3.0.0", + "from": "is-number@>=3.0.0 <4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz" + }, + "lazy-cache": { + "version": "2.0.2", + "from": "lazy-cache@>=2.0.2 <3.0.0", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz" + } + } + }, "har-schema": { "version": "1.0.5", "from": "har-schema@>=1.0.5 <2.0.0", @@ -3676,8 +3768,7 @@ "has-ansi": { "version": "2.0.0", "from": "has-ansi@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz" }, "has-binary": { "version": "0.1.7", @@ -3726,6 +3817,21 @@ "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", "dev": true }, + "helper-date": { + "version": "0.2.3", + "from": "helper-date@>=0.2.3 <0.3.0", + "resolved": "https://registry.npmjs.org/helper-date/-/helper-date-0.2.3.tgz" + }, + "helper-markdown": { + "version": "0.2.1", + "from": "helper-markdown@>=0.2.1 <0.3.0", + "resolved": "https://registry.npmjs.org/helper-markdown/-/helper-markdown-0.2.1.tgz" + }, + "helper-md": { + "version": "0.2.2", + "from": "helper-md@>=0.2.2 <0.3.0", + "resolved": "https://registry.npmjs.org/helper-md/-/helper-md-0.2.2.tgz" + }, "hoek": { "version": "2.16.3", "from": "hoek@>=2.0.0 <3.0.0", @@ -3783,6 +3889,18 @@ } } }, + "html-tag": { + "version": "1.0.0", + "from": "html-tag@>=1.0.0 <2.0.0", + "resolved": "https://registry.npmjs.org/html-tag/-/html-tag-1.0.0.tgz", + "dependencies": { + "isobject": { + "version": "3.0.0", + "from": "isobject@^3.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.0.tgz" + } + } + }, "http-browserify": { "version": "1.7.0", "from": "http-browserify@>=1.3.2 <2.0.0", @@ -3847,6 +3965,11 @@ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "dev": true }, + "index-of": { + "version": "0.2.0", + "from": "index-of@>=0.2.0 <0.3.0", + "resolved": "https://registry.npmjs.org/index-of/-/index-of-0.2.0.tgz" + }, "indexes-of": { "version": "1.0.1", "from": "indexes-of@>=1.0.1 <2.0.0", @@ -3919,6 +4042,11 @@ "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", "dev": true }, + "is-accessor-descriptor": { + "version": "0.1.6", + "from": "is-accessor-descriptor@>=0.1.6 <0.2.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz" + }, "is-arrayish": { "version": "0.2.1", "from": "is-arrayish@>=0.2.1 <0.3.0", @@ -3942,29 +4070,54 @@ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "dev": true }, + "is-data-descriptor": { + "version": "0.1.4", + "from": "is-data-descriptor@>=0.1.4 <0.2.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz" + }, + "is-descriptor": { + "version": "0.1.5", + "from": "is-descriptor@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.5.tgz", + "dependencies": { + "lazy-cache": { + "version": "2.0.2", + "from": "lazy-cache@^2.0.2", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz" + } + } + }, "is-dotfile": { "version": "1.0.2", "from": "is-dotfile@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.2.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.2.tgz" }, "is-equal-shallow": { "version": "0.1.3", "from": "is-equal-shallow@>=0.1.3 <0.2.0", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz" + }, + "is-even": { + "version": "0.1.1", + "from": "is-even@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/is-even/-/is-even-0.1.1.tgz", + "dependencies": { + "is-number": { + "version": "1.1.2", + "from": "is-number@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-1.1.2.tgz" + } + } }, "is-extendable": { "version": "0.1.1", "from": "is-extendable@>=0.1.1 <0.2.0", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" }, "is-extglob": { "version": "1.0.0", "from": "is-extglob@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz" }, "is-finite": { "version": "1.0.2", @@ -3981,8 +4134,7 @@ "is-glob": { "version": "2.0.1", "from": "is-glob@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz" }, "is-my-json-valid": { "version": "2.16.0", @@ -3999,8 +4151,7 @@ "is-number": { "version": "2.1.0", "from": "is-number@>=2.1.0 <3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz" }, "is-obj": { "version": "1.0.1", @@ -4008,6 +4159,18 @@ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "dev": true }, + "is-odd": { + "version": "0.1.1", + "from": "is-odd@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-0.1.1.tgz", + "dependencies": { + "is-number": { + "version": "1.1.2", + "from": "is-number@>=1.1.0 <2.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-1.1.2.tgz" + } + } + }, "is-path-cwd": { "version": "1.0.0", "from": "is-path-cwd@>=1.0.0 <2.0.0", @@ -4035,14 +4198,12 @@ "is-posix-bracket": { "version": "0.1.1", "from": "is-posix-bracket@>=0.1.0 <0.2.0", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz" }, "is-primitive": { "version": "2.0.0", "from": "is-primitive@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz" }, "is-property": { "version": "1.0.2", @@ -4130,13 +4291,11 @@ "version": "2.1.0", "from": "isobject@>=2.0.0 <3.0.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "dev": true, "dependencies": { "isarray": { "version": "1.0.0", "from": "isarray@1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" } } }, @@ -4742,11 +4901,31 @@ "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", "dev": true }, + "lodash.filter": { + "version": "4.6.0", + "from": "lodash.filter@>=4.2.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz" + }, + "lodash.findkey": { + "version": "4.6.0", + "from": "lodash.findkey@>=4.2.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.findkey/-/lodash.findkey-4.6.0.tgz" + }, + "lodash.foreach": { + "version": "4.5.0", + "from": "lodash.foreach@>=4.1.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz" + }, "lodash.get": { "version": "4.4.2", "from": "lodash.get@>=4.1.2 <5.0.0", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz" }, + "lodash.includes": { + "version": "4.3.0", + "from": "lodash.includes@>=4.1.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz" + }, "lodash.isarguments": { "version": "3.1.0", "from": "lodash.isarguments@>=3.0.0 <4.0.0", @@ -4762,8 +4941,7 @@ "lodash.isempty": { "version": "4.4.0", "from": "lodash.isempty@>=4.2.1 <5.0.0", - "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz" }, "lodash.isequal": { "version": "4.5.0", @@ -4819,6 +4997,11 @@ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.3.5.tgz", "dev": true }, + "lodash.partition": { + "version": "4.6.0", + "from": "lodash.partition@>=4.2.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.partition/-/lodash.partition-4.6.0.tgz" + }, "lodash.pick": { "version": "4.4.0", "from": "lodash.pick@>=4.2.1 <5.0.0", @@ -4855,6 +5038,11 @@ "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", "dev": true }, + "lodash.trim": { + "version": "4.5.1", + "from": "lodash.trim@>=4.2.0 <5.0.0", + "resolved": "https://registry.npmjs.org/lodash.trim/-/lodash.trim-4.5.1.tgz" + }, "lodash.uniq": { "version": "4.5.0", "from": "lodash.uniq@>=4.3.0 <5.0.0", @@ -4907,6 +5095,11 @@ } } }, + "logging-helpers": { + "version": "0.4.0", + "from": "logging-helpers@>=0.4.0 <0.5.0", + "resolved": "https://registry.npmjs.org/logging-helpers/-/logging-helpers-0.4.0.tgz" + }, "lolex": { "version": "1.4.0", "from": "lolex@>=1.4.0 <1.5.0", @@ -4953,6 +5146,11 @@ "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", "dev": true }, + "make-iterator": { + "version": "0.3.1", + "from": "make-iterator@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-0.3.1.tgz" + }, "map-cache": { "version": "0.2.2", "from": "map-cache@>=0.2.0 <0.3.0", @@ -5076,8 +5274,7 @@ "micromatch": { "version": "2.3.11", "from": "micromatch@>=2.3.7 <3.0.0", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz" }, "mime": { "version": "1.3.4", @@ -5107,6 +5304,11 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "dev": true }, + "mixin-deep": { + "version": "1.2.0", + "from": "mixin-deep@>=1.1.3 <2.0.0", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.2.0.tgz" + }, "mkdirp": { "version": "0.5.1", "from": "mkdirp@>=0.5.0 <0.6.0", @@ -5356,8 +5558,7 @@ "normalize-path": { "version": "2.0.1", "from": "normalize-path@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.0.1.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.0.1.tgz" }, "normalize-range": { "version": "0.1.2", @@ -5414,8 +5615,7 @@ "object.omit": { "version": "2.0.1", "from": "object.omit@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz" }, "object.pick": { "version": "1.2.0", @@ -5578,8 +5778,7 @@ "parse-glob": { "version": "3.0.4", "from": "parse-glob@>=3.0.4 <4.0.0", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz" }, "parse-json": { "version": "2.2.0", @@ -6033,8 +6232,7 @@ "preserve": { "version": "0.2.0", "from": "preserve@>=0.2.0 <0.3.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz" }, "pretty-hrtime": { "version": "1.0.3", @@ -6158,8 +6356,7 @@ "randomatic": { "version": "1.1.6", "from": "randomatic@>=1.1.3 <2.0.0", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.6.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.6.tgz" }, "range-parser": { "version": "1.2.0", @@ -6312,8 +6509,7 @@ "regex-cache": { "version": "0.4.3", "from": "regex-cache@>=0.4.2 <0.5.0", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz" }, "regexpu-core": { "version": "1.0.0", @@ -6351,11 +6547,37 @@ "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", "dev": true }, + "relative": { + "version": "3.0.2", + "from": "relative@>=3.0.2 <4.0.0", + "resolved": "https://registry.npmjs.org/relative/-/relative-3.0.2.tgz" + }, + "remarkable": { + "version": "1.7.1", + "from": "remarkable@>=1.6.0 <2.0.0", + "resolved": "https://registry.npmjs.org/remarkable/-/remarkable-1.7.1.tgz", + "dependencies": { + "argparse": { + "version": "0.1.16", + "from": "argparse@>=0.1.15 <0.2.0", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-0.1.16.tgz" + }, + "underscore": { + "version": "1.7.0", + "from": "underscore@>=1.7.0 <1.8.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz" + }, + "underscore.string": { + "version": "2.4.0", + "from": "underscore.string@>=2.4.0 <2.5.0", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.4.0.tgz" + } + } + }, "repeat-element": { "version": "1.1.2", "from": "repeat-element@>=1.1.2 <2.0.0", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz" }, "repeat-string": { "version": "1.6.1", @@ -6423,6 +6645,12 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "dev": true }, + "requires-regex": { + "version": "0.3.3", + "from": "requires-regex@>=0.3.3 <0.4.0", + "resolved": "https://registry.npmjs.org/requires-regex/-/requires-regex-0.3.3.tgz", + "dev": true + }, "resolve": { "version": "1.3.2", "from": "resolve@>=1.1.7 <2.0.0", @@ -6603,6 +6831,11 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "dev": true }, + "set-getter": { + "version": "0.1.0", + "from": "set-getter@>=0.1.0 <0.2.0", + "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz" + }, "set-immediate-shim": { "version": "1.0.1", "from": "set-immediate-shim@>=1.0.1 <2.0.0", @@ -6904,8 +7137,7 @@ "strip-ansi": { "version": "3.0.1", "from": "strip-ansi@>=3.0.0 <4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" }, "strip-bom": { "version": "1.0.0", @@ -6939,6 +7171,11 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "dev": true }, + "striptags": { + "version": "2.2.1", + "from": "striptags@>=2.1.1 <3.0.0", + "resolved": "https://registry.npmjs.org/striptags/-/striptags-2.2.1.tgz" + }, "sudo": { "version": "1.0.3", "from": "sudo@>=1.0.3 <1.1.0", @@ -6948,8 +7185,7 @@ "supports-color": { "version": "2.0.0", "from": "supports-color@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz" }, "svgo": { "version": "0.7.2", @@ -7163,12 +7399,22 @@ "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", "dev": true }, + "to-gfm-code-block": { + "version": "0.1.1", + "from": "to-gfm-code-block@>=0.1.1 <0.2.0", + "resolved": "https://registry.npmjs.org/to-gfm-code-block/-/to-gfm-code-block-0.1.1.tgz" + }, "to-iso-string": { "version": "0.0.2", "from": "to-iso-string@0.0.2", "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", "dev": true }, + "to-object-path": { + "version": "0.3.0", + "from": "to-object-path@>=0.3.0 <0.4.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" + }, "tough-cookie": { "version": "2.3.2", "from": "tough-cookie@>=2.3.0 <2.4.0", @@ -7374,6 +7620,12 @@ "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", "dev": true }, + "unlazy-loader": { + "version": "0.1.2", + "from": "unlazy-loader@latest", + "resolved": "https://registry.npmjs.org/unlazy-loader/-/unlazy-loader-0.1.2.tgz", + "dev": true + }, "unpipe": { "version": "1.0.0", "from": "unpipe@1.0.0", @@ -7588,8 +7840,7 @@ "void-elements": { "version": "2.0.1", "from": "void-elements@>=2.0.0 <3.0.0", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "dev": true + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz" }, "watchpack": { "version": "0.2.9", diff --git a/package.json b/package.json index d747929c7..690969372 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@types/react-dom": "0.14.18", "@types/webpack-env": ">=1.12.1 <1.14.0", "handlebars": "^4.0.6", + "handlebars-helpers": "^0.8.2", "moment": "^2.18.1", "office-ui-fabric-react": "1.14.3", "react": "15.4.2", @@ -30,7 +31,8 @@ "@types/microsoft-ajax": "0.0.31", "@types/mocha": ">=2.2.33 <2.6.0", "@types/sharepoint": "^2013.1.4", - "gulp": "~3.9.1" + "gulp": "~3.9.1", + "unlazy-loader": "^0.1.2" }, "scripts": { "build": "gulp bundle", diff --git a/sharepoint/solution/react-content-query-webpart.sppkg b/sharepoint/solution/react-content-query-webpart.sppkg new file mode 100644 index 000000000..56f6ed30d Binary files /dev/null and b/sharepoint/solution/react-content-query-webpart.sppkg differ diff --git a/src/common/constants/ContentQueryConstants.ts b/src/common/constants/ContentQueryConstants.ts index 90a00d29a..b6e654dc9 100644 --- a/src/common/constants/ContentQueryConstants.ts +++ b/src/common/constants/ContentQueryConstants.ts @@ -4,13 +4,15 @@ export class ContentQueryConstants { /************************************************************** * WebPart Properties **************************************************************/ - public static readonly propertyWebUrl = "webUrl"; - public static readonly propertyListTitle = "listTitle"; - public static readonly propertyOrderBy = "orderBy"; - public static readonly propertOrderByDirection = "orderByDirection"; - public static readonly propertyLimitEnabled = "limitEnabled"; - public static readonly propertyItemLimit = "itemLimit"; - public static readonly propertyFilters = "filters"; - public static readonly propertyViewFields = "viewFields"; - public static readonly propertyTemplateUrl = "templateUrl"; + public static readonly propertyWebUrl = "webUrl"; + public static readonly propertyListTitle = "listTitle"; + public static readonly propertyOrderBy = "orderBy"; + public static readonly propertOrderByDirection = "orderByDirection"; + public static readonly propertyLimitEnabled = "limitEnabled"; + public static readonly propertyItemLimit = "itemLimit"; + public static readonly propertyFilters = "filters"; + public static readonly propertyViewFields = "viewFields"; + public static readonly propertyTemplateText = "templateText"; + public static readonly propertyTemplateUrl = "templateUrl"; + public static readonly propertyhasDefaultTemplateBeenUpdated = "hasDefaultTemplateBeenUpdated"; } \ No newline at end of file diff --git a/src/common/helpers/CamlQueryHelper.ts b/src/common/helpers/CamlQueryHelper.ts index 3b8b2829c..0facc3c31 100644 --- a/src/common/helpers/CamlQueryHelper.ts +++ b/src/common/helpers/CamlQueryHelper.ts @@ -151,11 +151,11 @@ export class CamlQueryHelper { let filterOutput = ''; let filterUsers = filter.value as IPersonaProps[]; - if(isEmpty(filter.value)) { - return ''; + if(filter.me) { + filterOutput = Text.format("", filter.field.internalName); } - else if(filter.me) { - filterOutput = Text.format("", filter.field.internalName); + else if(isEmpty(filter.value)) { + return ''; } else if (filter.operator == QueryFilterOperator.ContainsAny || filterUsers == null) { diff --git a/src/common/services/ContentQueryService.ts b/src/common/services/ContentQueryService.ts index 72e02162e..c5763e9dc 100644 --- a/src/common/services/ContentQueryService.ts +++ b/src/common/services/ContentQueryService.ts @@ -403,6 +403,51 @@ export class ContentQueryService implements IContentQueryService { } + /************************************************************************************************* + * Generates a default handlebars template based on the view fields selected by the user + * @param viewFields : The view fields that have been selected by the user + *************************************************************************************************/ + public generateDefaultTemplate(viewFields: string[]): string { + let viewFieldsStr = viewFields.map((field) => { return Text.format(" {0} : \{\{{0}.textValue\}\}", field); }).join("\n"); + let template = Text.format(` + +
+

{0}

+
+ {{#each items}} +
+

Result #{{@index}}

+
+{1} +
+
+ {{/each}} +
+
`, strings.DynamicallyGeneratedTemplate ,viewFieldsStr); + + return template; + } + + /*************************************************************************** * Resets the stored 'list title' options ***************************************************************************/ diff --git a/src/common/services/IContentQueryService.ts b/src/common/services/IContentQueryService.ts index be95728af..10e4e6ccf 100644 --- a/src/common/services/IContentQueryService.ts +++ b/src/common/services/IContentQueryService.ts @@ -17,6 +17,7 @@ export interface IContentQueryService { getTaxonomyPickerSuggestions: (webUrl: string, listTitle: string, field: IQueryFilterField, filterText: string, currentTerms: ITag[]) => Promise; ensureFileResolves: (filePath: string) => Promise<{}>; isValidTemplateFile: (filePath: string) => boolean; + generateDefaultTemplate: (viewFields: string[]) => string; clearCachedListTitleOptions: () => void; clearCachedOrderByOptions: () => void; clearCachedFilterFields: () => void; diff --git a/src/controls/PropertyPaneTextDialog/IPropertyPaneTextDialogInternalProps.ts b/src/controls/PropertyPaneTextDialog/IPropertyPaneTextDialogInternalProps.ts new file mode 100644 index 000000000..f47a6b7f2 --- /dev/null +++ b/src/controls/PropertyPaneTextDialog/IPropertyPaneTextDialogInternalProps.ts @@ -0,0 +1,6 @@ +import { IPropertyPaneCustomFieldProps } from '@microsoft/sp-webpart-base'; +import { IPropertyPaneTextDialogProps } from './IPropertyPaneTextDialogProps'; + +export interface IPropertyPaneTextDialogInternalProps extends IPropertyPaneTextDialogProps, IPropertyPaneCustomFieldProps { + +} \ No newline at end of file diff --git a/src/controls/PropertyPaneTextDialog/IPropertyPaneTextDialogProps.ts b/src/controls/PropertyPaneTextDialog/IPropertyPaneTextDialogProps.ts new file mode 100644 index 000000000..29219e19b --- /dev/null +++ b/src/controls/PropertyPaneTextDialog/IPropertyPaneTextDialogProps.ts @@ -0,0 +1,8 @@ +import { ITextDialogStrings } from "./components/TextDialog/ITextDialogStrings"; + +export interface IPropertyPaneTextDialogProps { + dialogTextFieldValue?: string; + onPropertyChange: (propertyPath: string, text: string) => void; + disabled?: boolean; + strings: ITextDialogStrings; +} \ No newline at end of file diff --git a/src/controls/PropertyPaneTextDialog/PropertyPaneTextDialog.ts b/src/controls/PropertyPaneTextDialog/PropertyPaneTextDialog.ts new file mode 100644 index 000000000..c0342ada1 --- /dev/null +++ b/src/controls/PropertyPaneTextDialog/PropertyPaneTextDialog.ts @@ -0,0 +1,74 @@ +import * as React from 'react'; +import * as ReactDom from 'react-dom'; +import { IPropertyPaneField, PropertyPaneFieldType } from '@microsoft/sp-webpart-base'; +import { IPropertyPaneTextDialogProps } from './IPropertyPaneTextDialogProps'; +import { IPropertyPaneTextDialogInternalProps } from './IPropertyPaneTextDialogInternalProps'; +import { TextDialog } from './components/TextDialog/TextDialog'; +import { ITextDialogProps } from './components/TextDialog/ITextDialogProps'; + + +export class PropertyPaneTextDialog implements IPropertyPaneField { + + public type: PropertyPaneFieldType = PropertyPaneFieldType.Custom; + public targetProperty: string; + public properties: IPropertyPaneTextDialogInternalProps; + private elem: HTMLElement; + + + /***************************************************************************************** + * Property pane's contructor + * @param targetProperty + * @param properties + *****************************************************************************************/ + constructor(targetProperty: string, properties: IPropertyPaneTextDialogProps) { + this.targetProperty = targetProperty; + this.properties = { + dialogTextFieldValue: properties.dialogTextFieldValue, + onPropertyChange: properties.onPropertyChange, + disabled: properties.disabled, + strings: properties.strings, + onRender: this.onRender.bind(this), + key: targetProperty + }; + } + + + /***************************************************************************************** + * Renders the QueryFilterPanel property pane + *****************************************************************************************/ + public render(): void { + if (!this.elem) { + return; + } + this.onRender(this.elem); + } + + + /***************************************************************************************** + * Renders the QueryFilterPanel property pane + *****************************************************************************************/ + private onRender(elem: HTMLElement): void { + if (!this.elem) { + this.elem = elem; + } + + const textDialog: React.ReactElement = React.createElement(TextDialog, { + dialogTextFieldValue: this.properties.dialogTextFieldValue, + onChanged: this.onChanged.bind(this), + disabled: this.properties.disabled, + strings: this.properties.strings, + // required to allow the component to be re-rendered by calling this.render() externally + stateKey: new Date().toString() + }); + + ReactDom.render(textDialog, elem); + } + + + /***************************************************************************************** + * Call the property pane's onPropertyChange when the TextDialog changes + *****************************************************************************************/ + private onChanged(text: string): void { + this.properties.onPropertyChange(this.targetProperty, text); + } +} \ No newline at end of file diff --git a/src/controls/PropertyPaneTextDialog/components/TextDialog/ITextDialogProps.ts b/src/controls/PropertyPaneTextDialog/components/TextDialog/ITextDialogProps.ts new file mode 100644 index 000000000..04a406d1d --- /dev/null +++ b/src/controls/PropertyPaneTextDialog/components/TextDialog/ITextDialogProps.ts @@ -0,0 +1,9 @@ +import { ITextDialogStrings } from "./ITextDialogStrings"; + +export interface ITextDialogProps { + dialogTextFieldValue?: string; + onChanged?: (text: string) => void; + disabled?: boolean; + strings: ITextDialogStrings; + stateKey?: string; +} \ No newline at end of file diff --git a/src/controls/PropertyPaneTextDialog/components/TextDialog/ITextDialogState.ts b/src/controls/PropertyPaneTextDialog/components/TextDialog/ITextDialogState.ts new file mode 100644 index 000000000..a92c9e4d7 --- /dev/null +++ b/src/controls/PropertyPaneTextDialog/components/TextDialog/ITextDialogState.ts @@ -0,0 +1,4 @@ +export interface ITextDialogState { + dialogText: string; + showDialog: boolean; +} \ No newline at end of file diff --git a/src/controls/PropertyPaneTextDialog/components/TextDialog/ITextDialogStrings.ts b/src/controls/PropertyPaneTextDialog/components/TextDialog/ITextDialogStrings.ts new file mode 100644 index 000000000..c1e69aa67 --- /dev/null +++ b/src/controls/PropertyPaneTextDialog/components/TextDialog/ITextDialogStrings.ts @@ -0,0 +1,9 @@ +export interface ITextDialogStrings { + dialogTitle: string; + dialogSubText?: string; + dialogButtonLabel?: string; + dialogButtonText: string; + dialogTextBoxPlaceholder?: string; + saveButtonText: string; + cancelButtonText: string; +} \ No newline at end of file diff --git a/src/controls/PropertyPaneTextDialog/components/TextDialog/TextDialog.module.scss b/src/controls/PropertyPaneTextDialog/components/TextDialog/TextDialog.module.scss new file mode 100644 index 000000000..698b84b54 --- /dev/null +++ b/src/controls/PropertyPaneTextDialog/components/TextDialog/TextDialog.module.scss @@ -0,0 +1,3 @@ +.textDialog { + max-width: 100%; +} \ No newline at end of file diff --git a/src/controls/PropertyPaneTextDialog/components/TextDialog/TextDialog.tsx b/src/controls/PropertyPaneTextDialog/components/TextDialog/TextDialog.tsx new file mode 100644 index 000000000..f1cd8bbc9 --- /dev/null +++ b/src/controls/PropertyPaneTextDialog/components/TextDialog/TextDialog.tsx @@ -0,0 +1,100 @@ +import * as React from 'react'; +import { Dialog, DialogType, DialogFooter } from 'office-ui-fabric-react'; +import { Button, ButtonType, Label } from 'office-ui-fabric-react'; +import { TextField } from 'office-ui-fabric-react'; +import { ITextDialogProps } from './ITextDialogProps'; +import { ITextDialogState } from './ITextDialogState'; +import styles from './TextDialog.module.scss'; + +export class TextDialog extends React.Component { + + /************************************************************************************* + * Component's constructor + * @param props + * @param state + *************************************************************************************/ + constructor(props: ITextDialogProps, state: ITextDialogState) { + super(props); + this.state = { dialogText: this.props.dialogTextFieldValue, showDialog: false }; + } + + + /************************************************************************************* + * Shows the dialog + *************************************************************************************/ + private showDialog() { + this.setState({ dialogText: this.state.dialogText, showDialog: true }); + } + + + /************************************************************************************* + * Notifies the parent with the dialog's latest value, then closes the dialog + *************************************************************************************/ + private saveDialog() { + this.setState({ dialogText: this.state.dialogText, showDialog: false }); + + if(this.props.onChanged) { + this.props.onChanged(this.state.dialogText); + } + } + + + /************************************************************************************* + * Closes the dialog without notifying the parent for any changes + *************************************************************************************/ + private cancelDialog() { + this.setState({ dialogText: this.state.dialogText, showDialog: false }); + } + + + /************************************************************************************* + * Updates the dialog's value each time the textfield changes + *************************************************************************************/ + private onDialogTextChanged(newValue: string) { + this.setState({ dialogText: newValue, showDialog: this.state.showDialog }); + } + + + /************************************************************************************* + * Called immediately after updating occurs + *************************************************************************************/ + public componentDidUpdate(prevProps: ITextDialogProps, prevState: ITextDialogState): void { + if (this.props.disabled !== prevProps.disabled || this.props.stateKey !== prevProps.stateKey) { + this.setState({ dialogText: this.props.dialogTextFieldValue, showDialog: this.state.showDialog }); + } + } + + + /************************************************************************************* + * Renders the the TextDialog component + *************************************************************************************/ + public render() { + return ( +
+ + + + + + + + + + + + + +
+ ); + } +} diff --git a/src/webparts/contentQuery/ContentQueryWebPart.manifest.json b/src/webparts/contentQuery/ContentQueryWebPart.manifest.json index 97af5efe7..4c4d7c6f3 100644 --- a/src/webparts/contentQuery/ContentQueryWebPart.manifest.json +++ b/src/webparts/contentQuery/ContentQueryWebPart.manifest.json @@ -9,15 +9,15 @@ "preconfiguredEntries": [{ "groupId": "46edf08f-95c7-4ca7-9146-6471f9f471be", - "group": { "default": "Under Development" }, - "title": { "default": "Content by Query WebPart" }, + "group": { "default": "SPP Technologies" }, + "title": { "default": "React Content Query WebPart" }, "description": { "default": "A react content by query WebPart for querying items within a site and easily displaying them using a simple yet powerfull HandleBars templating engine.", "fr-FR": "Un composante React permettant d'effectuer des requêtes sur les items et de facilement afficher les résultat à l'aide de gabarits HandleBars fournit par l'utilisateur" }, "officeFabricIconFontName": "Page", "properties": { - "description": "Content by Query WebPart" + "description": "React Content Query WebPart" } }] } diff --git a/src/webparts/contentQuery/ContentQueryWebPart.ts b/src/webparts/contentQuery/ContentQueryWebPart.ts index 691d886e4..7d8d9d31a 100644 --- a/src/webparts/contentQuery/ContentQueryWebPart.ts +++ b/src/webparts/contentQuery/ContentQueryWebPart.ts @@ -16,6 +16,7 @@ import { IContentQueryWebPartProps } import { PropertyPaneAsyncDropdown } from '../../controls/PropertyPaneAsyncDropdown/PropertyPaneAsyncDropdown'; import { PropertyPaneQueryFilterPanel } from '../../controls/PropertyPaneQueryFilterPanel/PropertyPaneQueryFilterPanel'; import { PropertyPaneAsyncChecklist } from '../../controls/PropertyPaneAsyncChecklist/PropertyPaneAsyncChecklist'; +import { PropertyPaneTextDialog } from '../../controls/PropertyPaneTextDialog/PropertyPaneTextDialog'; import { IQueryFilter } from '../../controls/PropertyPaneQueryFilterPanel/components/QueryFilter/IQueryFilter'; import { IQueryFilterField } from '../../controls/PropertyPaneQueryFilterPanel/components/QueryFilter/IQueryFilterField'; import { IChecklistItem } from '../../controls/PropertyPaneAsyncChecklist/components/AsyncChecklist/IChecklistItem'; @@ -46,6 +47,7 @@ export default class ContentQueryWebPart extends BaseClientSideWebPart; private filtersPanel: PropertyPaneQueryFilterPanel; private viewFieldsChecklist: PropertyPaneAsyncChecklist; + private templateTextDialog: PropertyPaneTextDialog; private templateUrlTextField: IPropertyPaneField; @@ -88,6 +90,7 @@ export default class ContentQueryWebPart extends BaseClientSideWebPart { return checkedKeys; }); + // Updates the default template text if it hasn't been altered by the user + if(!this.properties.hasDefaultTemplateBeenUpdated) { + let generatedTemplate = this.ContentQueryService.generateDefaultTemplate(checkedKeys); + update(this.properties, ContentQueryConstants.propertyTemplateText, (): any => { return generatedTemplate; }); + this.templateTextDialog.properties.dialogTextFieldValue = generatedTemplate; + this.templateTextDialog.render(); + } + // refresh web part this.onPropertyPaneFieldChanged(propertyPath, oldValue, checkedKeys); } + /*************************************************************************** + * Handles the change of the viewFields property + ***************************************************************************/ + private onTemplateTextChange(propertyPath: string, text: string) { + Log.verbose(this.logSource, "WebPart property 'templateText' has changed, refreshing WebPart...", this.context.serviceScope); + const oldValue = get(this.properties, propertyPath); + + // Stores the new value in web part properties + update(this.properties, propertyPath, (): any => { return text; }); + + // Updates the "hasDefaultTemplateBeenUpdated" to true so the WebPart doesn't override the user template after updating view fields + if(!this.properties.hasDefaultTemplateBeenUpdated) { + update(this.properties, ContentQueryConstants.propertyhasDefaultTemplateBeenUpdated, (): any => { return true; }); + } + + // refresh web part + this.onPropertyPaneFieldChanged(propertyPath, oldValue, text); + } + + /*************************************************************************** * Validates the templateUrl property ***************************************************************************/ @@ -505,4 +555,4 @@ export default class ContentQueryWebPart extends BaseClientSideWebPart('handlebars-helpers')({ + handlebars: Handlebars + }); + this.onGoingAsyncCalls = []; this.state = { loading: true, processedTemplateResult: null, error: null }; - } + } /************************************************************************************* @@ -65,7 +70,7 @@ export default class ContentQuery extends React.Component { // Loads the handlebars template - this.props.onLoadTemplate(this.props.templateUrl).then((templateContent: string) => { + this.loadTemplate().then((templateContent: string) => { // Only process the result of the current async call if it's the last in the ordered queue if(this.isLastExecutedCall(templateContext.callTimeStamp)) { @@ -91,6 +96,26 @@ export default class ContentQuery extends React.Component { + // Resolves the template content if no template url + if(isEmpty(this.props.templateUrl)) { + return Promise.resolve(this.props.templateText); + } + + return new Promise((resolve,reject) => { + this.props.onLoadTemplate(this.props.templateUrl).then((templateContent: string) => { + resolve(templateContent); + }) + .catch((error: string) => { + reject(error); + }); + }); + } + + /************************************************************************************* * Process the specified handlebars template with the given template context * @param templateContent : The handlebars template that needs to be compiled @@ -120,7 +145,7 @@ export default class ContentQuery extends React.Component - Configure the following mandatory properties in order to display results : + { this.props.strings.mandatoryProperties } - + } diff --git a/src/webparts/contentQuery/components/IContentQueryProps.ts b/src/webparts/contentQuery/components/IContentQueryProps.ts index 55efc6d6c..6803ea265 100644 --- a/src/webparts/contentQuery/components/IContentQueryProps.ts +++ b/src/webparts/contentQuery/components/IContentQueryProps.ts @@ -7,7 +7,8 @@ export interface IContentQueryProps { onLoadTemplate: (templateUrl: string) => Promise; onLoadTemplateContext: (querySettings: IQuerySettings, callTimeStamp: number) => Promise; querySettings: IQuerySettings; - templateUrl: string; + templateText?: string; + templateUrl?: string; strings: IContentQueryStrings; stateKey: string; } \ No newline at end of file diff --git a/src/webparts/contentQuery/components/IContentQueryStrings.ts b/src/webparts/contentQuery/components/IContentQueryStrings.ts index 552983e68..ea04c2698 100644 --- a/src/webparts/contentQuery/components/IContentQueryStrings.ts +++ b/src/webparts/contentQuery/components/IContentQueryStrings.ts @@ -1,5 +1,6 @@ export interface IContentQueryStrings { loadingItems: string; + mandatoryProperties: string; errorLoadingQuery: string; errorLoadingTemplate: string; errorProcessingTemplate: string; diff --git a/src/webparts/contentQuery/loc/en-us.js b/src/webparts/contentQuery/loc/en-us.js index 83a84d1f1..980c5dd4e 100644 --- a/src/webparts/contentQuery/loc/en-us.js +++ b/src/webparts/contentQuery/loc/en-us.js @@ -2,10 +2,12 @@ define([], function() { return { SourcePageDescription: "Specify where the WebPart should get the results from.", QueryPageDescription: "If needed, choose the sorting behavior, limit the results, or add filters in order to narrow the query down.", - DisplayPageDescription: "Finally, specify which fields should be available for rendering within the HandleBars template, and specify the URL of the said template.", + DisplayPageDescription: "Specify which fields should be available for rendering within the HandleBars template, and edit your handlebars template.", + ExternalPageDescription: "Optionally, externalize the properties below by specifying valid sharepoint urls.", SourceGroupName: "Source", QueryGroupName: "Query", DisplayGroupName: "Display", + ExternalGroupName: "External Resources", WebUrlFieldLabel: "Web Url", WebUrlFieldPlaceholder: "Select the source web...", WebUrlFieldLoadingLabel: "Loading webs from current site...", @@ -29,6 +31,7 @@ define([], function() { ErrorProcessingTemplate: "An error occured while processing the handlebars template : {0}", ShowItemsAscending: "Show items in ascending order", ShowItemsDescending: "Show items in descending order", + DynamicallyGeneratedTemplate: "Dynamically generated template", queryFilterPanelStrings: { filtersLabel: "Filters", addFilterLabel: "Add filter", @@ -80,8 +83,18 @@ define([], function() { loading: 'Loading fields from specified list...', errorFormat: 'An error occured while loading fields : {0}' }, + templateTextStrings: { + dialogTitle: "Edit template content", + dialogSubText: "Edit your handlebars template in this dialog. Note that the inline template specified within this dialog will be ignored if a template url is specified.", + dialogButtonLabel: "Template", + dialogButtonText: "Edit template content", + dialogTextBoxPlaceholder: "Edit your handlebars template here...", + saveButtonText: 'Save', + cancelButtonText: 'Cancel' + }, contentQueryStrings: { loadingItems: 'Processing query', + mandatoryProperties: 'Configure the following mandatory properties in order to display results :', errorLoadingQuery: 'An error occured while processing the query : {0}', errorLoadingTemplate: 'An error occured while loading the template: {0}', errorProcessingTemplate: 'An error occured while processing the handlebars template : {0}' diff --git a/src/webparts/contentQuery/loc/mystrings.d.ts b/src/webparts/contentQuery/loc/mystrings.d.ts index 6df24ef0c..fa264466d 100644 --- a/src/webparts/contentQuery/loc/mystrings.d.ts +++ b/src/webparts/contentQuery/loc/mystrings.d.ts @@ -2,9 +2,11 @@ declare interface IContentQueryStrings { SourcePageDescription: string; QueryPageDescription: string; DisplayPageDescription: string; + ExternalPageDescription: string; SourceGroupName: string; QueryGroupName: string; DisplayGroupName: string; + ExternalGroupName: string; WebUrlFieldLabel: string; WebUrlFieldPlaceholder: string; WebUrlFieldLoadingLabel: string; @@ -27,8 +29,10 @@ declare interface IContentQueryStrings { ErrorWebNotFound: string; ShowItemsAscending: string; ShowItemsDescending: string; + DynamicallyGeneratedTemplate: string; queryFilterPanelStrings: any; viewFieldsChecklistStrings: any; + templateTextStrings: any; contentQueryStrings: any; }