From 72fcfbf4bc3344a3992a8e99ce9d0d506acac5bc Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Thu, 28 Apr 2016 11:41:40 +1200 Subject: [PATCH] API Campaign preview for images --- admin/client/dist/js/bundle-framework.js | 8 +++---- .../client/src/components/Preview/Preview.js | 22 ++++++++++------- .../containers/CampaignAdmin/CampaignAdmin.js | 14 ----------- .../CampaignAdmin/CampaignAdminList.js | 19 ++++----------- admin/code/CMSPreviewable.php | 14 +++++++++-- admin/code/CampaignAdmin.php | 10 ++------ docs/en/04_Changelogs/4.0.0.md | 1 + filesystem/File.php | 8 ++++--- model/Image.php | 11 +++++++++ model/versioning/ChangeSetItem.php | 24 ++++++++++--------- 10 files changed, 66 insertions(+), 65 deletions(-) diff --git a/admin/client/dist/js/bundle-framework.js b/admin/client/dist/js/bundle-framework.js index 70779b2f7..0c67f4870 100644 --- a/admin/client/dist/js/bundle-framework.js +++ b/admin/client/dist/js/bundle-framework.js @@ -1,5 +1,5 @@ -!function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;oAdd to campaignRemove from campaign"},_react2["default"].createElement("i",{className:"font-icon-dot-3"})))))},Preview}(_SilverStripeComponent2["default"]);exports["default"]=Preview},{"lib/SilverStripeComponent":"lib/SilverStripeComponent",react:"react"}],7:[function(require,module,exports){"use strict";function _interopRequireWildcard(obj){if(obj&&obj.__esModule)return obj;var newObj={};if(null!=obj)for(var key in obj)Object.prototype.hasOwnProperty.call(obj,key)&&(newObj[key]=obj[key]);return newObj["default"]=obj,newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{"default":obj}}function _defaults(obj,defaults){for(var keys=Object.getOwnPropertyNames(defaults),i=0;i=200&&response.status<300))throw error=new Error(response.statusText),error.response=response,error;return ret=response}Object.defineProperty(exports,"__esModule",{value:!0});var _extends=Object.assign||function(target){for(var i=1;i1)for(var i=1;ii;i+=2){var callback=lib$es6$promise$asap$$queue[i],arg=lib$es6$promise$asap$$queue[i+1];callback(arg),lib$es6$promise$asap$$queue[i]=void 0,lib$es6$promise$asap$$queue[i+1]=void 0}lib$es6$promise$asap$$len=0}function lib$es6$promise$asap$$attemptVertx(){try{var r=require,vertx=r("vertx");return lib$es6$promise$asap$$vertxNext=vertx.runOnLoop||vertx.runOnContext,lib$es6$promise$asap$$useVertxTimer()}catch(e){return lib$es6$promise$asap$$useSetTimeout()}}function lib$es6$promise$then$$then(onFulfillment,onRejection){var parent=this,state=parent._state;if(state===lib$es6$promise$$internal$$FULFILLED&&!onFulfillment||state===lib$es6$promise$$internal$$REJECTED&&!onRejection)return this;var child=new this.constructor(lib$es6$promise$$internal$$noop),result=parent._result;if(state){var callback=arguments[state-1];lib$es6$promise$asap$$asap(function(){lib$es6$promise$$internal$$invokeCallback(state,child,callback,result)})}else lib$es6$promise$$internal$$subscribe(parent,child,onFulfillment,onRejection);return child}function lib$es6$promise$promise$resolve$$resolve(object){var Constructor=this;if(object&&"object"==typeof object&&object.constructor===Constructor)return object;var promise=new Constructor(lib$es6$promise$$internal$$noop);return lib$es6$promise$$internal$$resolve(promise,object),promise}function lib$es6$promise$$internal$$noop(){}function lib$es6$promise$$internal$$selfFulfillment(){return new TypeError("You cannot resolve a promise with itself")}function lib$es6$promise$$internal$$cannotReturnOwn(){return new TypeError("A promises callback cannot return that same promise.")}function lib$es6$promise$$internal$$getThen(promise){try{return promise.then}catch(error){return lib$es6$promise$$internal$$GET_THEN_ERROR.error=error,lib$es6$promise$$internal$$GET_THEN_ERROR}}function lib$es6$promise$$internal$$tryThen(then,value,fulfillmentHandler,rejectionHandler){try{then.call(value,fulfillmentHandler,rejectionHandler)}catch(e){return e}}function lib$es6$promise$$internal$$handleForeignThenable(promise,thenable,then){lib$es6$promise$asap$$asap(function(promise){var sealed=!1,error=lib$es6$promise$$internal$$tryThen(then,thenable,function(value){sealed||(sealed=!0,thenable!==value?lib$es6$promise$$internal$$resolve(promise,value):lib$es6$promise$$internal$$fulfill(promise,value))},function(reason){sealed||(sealed=!0,lib$es6$promise$$internal$$reject(promise,reason))},"Settle: "+(promise._label||" unknown promise"));!sealed&&error&&(sealed=!0,lib$es6$promise$$internal$$reject(promise,error))},promise)}function lib$es6$promise$$internal$$handleOwnThenable(promise,thenable){thenable._state===lib$es6$promise$$internal$$FULFILLED?lib$es6$promise$$internal$$fulfill(promise,thenable._result):thenable._state===lib$es6$promise$$internal$$REJECTED?lib$es6$promise$$internal$$reject(promise,thenable._result):lib$es6$promise$$internal$$subscribe(thenable,void 0,function(value){lib$es6$promise$$internal$$resolve(promise,value)},function(reason){lib$es6$promise$$internal$$reject(promise,reason)})}function lib$es6$promise$$internal$$handleMaybeThenable(promise,maybeThenable,then){maybeThenable.constructor===promise.constructor&&then===lib$es6$promise$then$$default&&constructor.resolve===lib$es6$promise$promise$resolve$$default?lib$es6$promise$$internal$$handleOwnThenable(promise,maybeThenable):then===lib$es6$promise$$internal$$GET_THEN_ERROR?lib$es6$promise$$internal$$reject(promise,lib$es6$promise$$internal$$GET_THEN_ERROR.error):void 0===then?lib$es6$promise$$internal$$fulfill(promise,maybeThenable):lib$es6$promise$utils$$isFunction(then)?lib$es6$promise$$internal$$handleForeignThenable(promise,maybeThenable,then):lib$es6$promise$$internal$$fulfill(promise,maybeThenable)}function lib$es6$promise$$internal$$resolve(promise,value){promise===value?lib$es6$promise$$internal$$reject(promise,lib$es6$promise$$internal$$selfFulfillment()):lib$es6$promise$utils$$objectOrFunction(value)?lib$es6$promise$$internal$$handleMaybeThenable(promise,value,lib$es6$promise$$internal$$getThen(value)):lib$es6$promise$$internal$$fulfill(promise,value)}function lib$es6$promise$$internal$$publishRejection(promise){promise._onerror&&promise._onerror(promise._result),lib$es6$promise$$internal$$publish(promise)}function lib$es6$promise$$internal$$fulfill(promise,value){promise._state===lib$es6$promise$$internal$$PENDING&&(promise._result=value,promise._state=lib$es6$promise$$internal$$FULFILLED,0!==promise._subscribers.length&&lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish,promise))}function lib$es6$promise$$internal$$reject(promise,reason){promise._state===lib$es6$promise$$internal$$PENDING&&(promise._state=lib$es6$promise$$internal$$REJECTED,promise._result=reason,lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publishRejection,promise))}function lib$es6$promise$$internal$$subscribe(parent,child,onFulfillment,onRejection){var subscribers=parent._subscribers,length=subscribers.length;parent._onerror=null,subscribers[length]=child,subscribers[length+lib$es6$promise$$internal$$FULFILLED]=onFulfillment,subscribers[length+lib$es6$promise$$internal$$REJECTED]=onRejection,0===length&&parent._state&&lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish,parent)}function lib$es6$promise$$internal$$publish(promise){var subscribers=promise._subscribers,settled=promise._state;if(0!==subscribers.length){for(var child,callback,detail=promise._result,i=0;ii;i++)lib$es6$promise$$internal$$subscribe(Constructor.resolve(entries[i]),void 0,onFulfillment,onRejection);return promise}function lib$es6$promise$promise$reject$$reject(reason){var Constructor=this,promise=new Constructor(lib$es6$promise$$internal$$noop);return lib$es6$promise$$internal$$reject(promise,reason),promise}function lib$es6$promise$promise$$needsResolver(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function lib$es6$promise$promise$$needsNew(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function lib$es6$promise$promise$$Promise(resolver){this._id=lib$es6$promise$promise$$counter++,this._state=void 0,this._result=void 0,this._subscribers=[],lib$es6$promise$$internal$$noop!==resolver&&("function"!=typeof resolver&&lib$es6$promise$promise$$needsResolver(),this instanceof lib$es6$promise$promise$$Promise?lib$es6$promise$$internal$$initializePromise(this,resolver):lib$es6$promise$promise$$needsNew())}function lib$es6$promise$enumerator$$Enumerator(Constructor,input){this._instanceConstructor=Constructor,this.promise=new Constructor(lib$es6$promise$$internal$$noop),Array.isArray(input)?(this._input=input,this.length=input.length,this._remaining=input.length,this._result=new Array(this.length),0===this.length?lib$es6$promise$$internal$$fulfill(this.promise,this._result):(this.length=this.length||0,this._enumerate(),0===this._remaining&&lib$es6$promise$$internal$$fulfill(this.promise,this._result))):lib$es6$promise$$internal$$reject(this.promise,this._validationError())}function lib$es6$promise$polyfill$$polyfill(){var local;if("undefined"!=typeof global)local=global;else if("undefined"!=typeof self)local=self;else try{local=Function("return this")()}catch(e){throw new Error("polyfill failed because global object is unavailable in this environment")}var P=local.Promise;P&&"[object Promise]"===Object.prototype.toString.call(P.resolve())&&!P.cast||(local.Promise=lib$es6$promise$promise$$default)}var lib$es6$promise$utils$$_isArray;lib$es6$promise$utils$$_isArray=Array.isArray?Array.isArray:function(x){return"[object Array]"===Object.prototype.toString.call(x)};var lib$es6$promise$asap$$vertxNext,lib$es6$promise$asap$$customSchedulerFn,lib$es6$promise$asap$$scheduleFlush,lib$es6$promise$utils$$isArray=lib$es6$promise$utils$$_isArray,lib$es6$promise$asap$$len=0,lib$es6$promise$asap$$asap=function(callback,arg){lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len]=callback,lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len+1]=arg,lib$es6$promise$asap$$len+=2,2===lib$es6$promise$asap$$len&&(lib$es6$promise$asap$$customSchedulerFn?lib$es6$promise$asap$$customSchedulerFn(lib$es6$promise$asap$$flush):lib$es6$promise$asap$$scheduleFlush())},lib$es6$promise$asap$$browserWindow="undefined"!=typeof window?window:void 0,lib$es6$promise$asap$$browserGlobal=lib$es6$promise$asap$$browserWindow||{},lib$es6$promise$asap$$BrowserMutationObserver=lib$es6$promise$asap$$browserGlobal.MutationObserver||lib$es6$promise$asap$$browserGlobal.WebKitMutationObserver,lib$es6$promise$asap$$isNode="undefined"!=typeof process&&"[object process]"==={}.toString.call(process),lib$es6$promise$asap$$isWorker="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,lib$es6$promise$asap$$queue=new Array(1e3);lib$es6$promise$asap$$scheduleFlush=lib$es6$promise$asap$$isNode?lib$es6$promise$asap$$useNextTick():lib$es6$promise$asap$$BrowserMutationObserver?lib$es6$promise$asap$$useMutationObserver():lib$es6$promise$asap$$isWorker?lib$es6$promise$asap$$useMessageChannel():void 0===lib$es6$promise$asap$$browserWindow&&"function"==typeof require?lib$es6$promise$asap$$attemptVertx():lib$es6$promise$asap$$useSetTimeout();var lib$es6$promise$then$$default=lib$es6$promise$then$$then,lib$es6$promise$promise$resolve$$default=lib$es6$promise$promise$resolve$$resolve,lib$es6$promise$$internal$$PENDING=void 0,lib$es6$promise$$internal$$FULFILLED=1,lib$es6$promise$$internal$$REJECTED=2,lib$es6$promise$$internal$$GET_THEN_ERROR=new lib$es6$promise$$internal$$ErrorObject,lib$es6$promise$$internal$$TRY_CATCH_ERROR=new lib$es6$promise$$internal$$ErrorObject,lib$es6$promise$promise$all$$default=lib$es6$promise$promise$all$$all,lib$es6$promise$promise$race$$default=lib$es6$promise$promise$race$$race,lib$es6$promise$promise$reject$$default=lib$es6$promise$promise$reject$$reject,lib$es6$promise$promise$$counter=0,lib$es6$promise$promise$$default=lib$es6$promise$promise$$Promise;lib$es6$promise$promise$$Promise.all=lib$es6$promise$promise$all$$default,lib$es6$promise$promise$$Promise.race=lib$es6$promise$promise$race$$default,lib$es6$promise$promise$$Promise.resolve=lib$es6$promise$promise$resolve$$default,lib$es6$promise$promise$$Promise.reject=lib$es6$promise$promise$reject$$default,lib$es6$promise$promise$$Promise._setScheduler=lib$es6$promise$asap$$setScheduler,lib$es6$promise$promise$$Promise._setAsap=lib$es6$promise$asap$$setAsap,lib$es6$promise$promise$$Promise._asap=lib$es6$promise$asap$$asap,lib$es6$promise$promise$$Promise.prototype={constructor:lib$es6$promise$promise$$Promise,then:lib$es6$promise$then$$default,"catch":function(onRejection){return this.then(null,onRejection)}};var lib$es6$promise$enumerator$$default=lib$es6$promise$enumerator$$Enumerator;lib$es6$promise$enumerator$$Enumerator.prototype._validationError=function(){return new Error("Array Methods must be provided an Array")},lib$es6$promise$enumerator$$Enumerator.prototype._enumerate=function(){for(var length=this.length,input=this._input,i=0;this._state===lib$es6$promise$$internal$$PENDING&&length>i;i++)this._eachEntry(input[i],i)},lib$es6$promise$enumerator$$Enumerator.prototype._eachEntry=function(entry,i){var c=this._instanceConstructor,resolve=c.resolve;if(resolve===lib$es6$promise$promise$resolve$$default){var then=lib$es6$promise$$internal$$getThen(entry);if(then===lib$es6$promise$then$$default&&entry._state!==lib$es6$promise$$internal$$PENDING)this._settledAt(entry._state,i,entry._result);else if("function"!=typeof then)this._remaining--,this._result[i]=entry;else if(c===lib$es6$promise$promise$$default){var promise=new c(lib$es6$promise$$internal$$noop);lib$es6$promise$$internal$$handleMaybeThenable(promise,entry,then),this._willSettleAt(promise,i)}else this._willSettleAt(new c(function(resolve){resolve(entry)}),i)}else this._willSettleAt(resolve(entry),i)},lib$es6$promise$enumerator$$Enumerator.prototype._settledAt=function(state,i,value){var promise=this.promise;promise._state===lib$es6$promise$$internal$$PENDING&&(this._remaining--,state===lib$es6$promise$$internal$$REJECTED?lib$es6$promise$$internal$$reject(promise,value):this._result[i]=value),0===this._remaining&&lib$es6$promise$$internal$$fulfill(promise,this._result)},lib$es6$promise$enumerator$$Enumerator.prototype._willSettleAt=function(promise,i){var enumerator=this;lib$es6$promise$$internal$$subscribe(promise,void 0,function(value){enumerator._settledAt(lib$es6$promise$$internal$$FULFILLED,i,value)},function(reason){enumerator._settledAt(lib$es6$promise$$internal$$REJECTED,i,reason)})};var lib$es6$promise$polyfill$$default=lib$es6$promise$polyfill$$polyfill,lib$es6$promise$umd$$ES6Promise={Promise:lib$es6$promise$promise$$default,polyfill:lib$es6$promise$polyfill$$default};"function"==typeof define&&define.amd?define(function(){return lib$es6$promise$umd$$ES6Promise}):"undefined"!=typeof module&&module.exports?module.exports=lib$es6$promise$umd$$ES6Promise:"undefined"!=typeof this&&(this.ES6Promise=lib$es6$promise$umd$$ES6Promise),lib$es6$promise$polyfill$$default()}).call(this)}).call(this,require("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{_process:25}],27:[function(require,module,exports){require("whatwg-fetch"),module.exports=self.fetch.bind(self)},{"whatwg-fetch":28}],28:[function(require,module,exports){!function(self){"use strict";function normalizeName(name){if("string"!=typeof name&&(name=String(name)),/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name))throw new TypeError("Invalid character in header field name");return name.toLowerCase()}function normalizeValue(value){return"string"!=typeof value&&(value=String(value)),value}function Headers(headers){this.map={},headers instanceof Headers?headers.forEach(function(value,name){this.append(name,value)},this):headers&&Object.getOwnPropertyNames(headers).forEach(function(name){this.append(name,headers[name])},this)}function consumed(body){return body.bodyUsed?Promise.reject(new TypeError("Already read")):void(body.bodyUsed=!0)}function fileReaderReady(reader){return new Promise(function(resolve,reject){reader.onload=function(){resolve(reader.result)},reader.onerror=function(){reject(reader.error)}})}function readBlobAsArrayBuffer(blob){var reader=new FileReader;return reader.readAsArrayBuffer(blob),fileReaderReady(reader)}function readBlobAsText(blob){var reader=new FileReader;return reader.readAsText(blob),fileReaderReady(reader)}function Body(){return this.bodyUsed=!1,this._initBody=function(body){if(this._bodyInit=body,"string"==typeof body)this._bodyText=body;else if(support.blob&&Blob.prototype.isPrototypeOf(body))this._bodyBlob=body;else if(support.formData&&FormData.prototype.isPrototypeOf(body))this._bodyFormData=body;else if(body){if(!support.arrayBuffer||!ArrayBuffer.prototype.isPrototypeOf(body))throw new Error("unsupported BodyInit type")}else this._bodyText="";this.headers.get("content-type")||("string"==typeof body?this.headers.set("content-type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type&&this.headers.set("content-type",this._bodyBlob.type))},support.blob?(this.blob=function(){var rejected=consumed(this);if(rejected)return rejected;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){return this.blob().then(readBlobAsArrayBuffer)},this.text=function(){var rejected=consumed(this);if(rejected)return rejected;if(this._bodyBlob)return readBlobAsText(this._bodyBlob);if(this._bodyFormData)throw new Error("could not read FormData body as text");return Promise.resolve(this._bodyText)}):this.text=function(){var rejected=consumed(this);return rejected?rejected:Promise.resolve(this._bodyText)},support.formData&&(this.formData=function(){return this.text().then(decode)}),this.json=function(){return this.text().then(JSON.parse)},this}function normalizeMethod(method){var upcased=method.toUpperCase();return methods.indexOf(upcased)>-1?upcased:method}function Request(input,options){options=options||{};var body=options.body;if(Request.prototype.isPrototypeOf(input)){if(input.bodyUsed)throw new TypeError("Already read");this.url=input.url,this.credentials=input.credentials,options.headers||(this.headers=new Headers(input.headers)),this.method=input.method,this.mode=input.mode,body||(body=input._bodyInit,input.bodyUsed=!0)}else this.url=input;if(this.credentials=options.credentials||this.credentials||"omit",!options.headers&&this.headers||(this.headers=new Headers(options.headers)),this.method=normalizeMethod(options.method||this.method||"GET"),this.mode=options.mode||this.mode||null,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&body)throw new TypeError("Body not allowed for GET or HEAD requests");this._initBody(body)}function decode(body){var form=new FormData;return body.trim().split("&").forEach(function(bytes){if(bytes){var split=bytes.split("="),name=split.shift().replace(/\+/g," "),value=split.join("=").replace(/\+/g," ");form.append(decodeURIComponent(name),decodeURIComponent(value))}}),form}function headers(xhr){var head=new Headers,pairs=xhr.getAllResponseHeaders().trim().split("\n");return pairs.forEach(function(header){var split=header.trim().split(":"),key=split.shift().trim(),value=split.join(":").trim();head.append(key,value)}),head}function Response(bodyInit,options){options||(options={}),this.type="default",this.status=options.status,this.ok=this.status>=200&&this.status<300,this.statusText=options.statusText,this.headers=options.headers instanceof Headers?options.headers:new Headers(options.headers),this.url=options.url||"",this._initBody(bodyInit)}if(!self.fetch){Headers.prototype.append=function(name,value){name=normalizeName(name),value=normalizeValue(value);var list=this.map[name];list||(list=[],this.map[name]=list),list.push(value)},Headers.prototype["delete"]=function(name){delete this.map[normalizeName(name)]},Headers.prototype.get=function(name){var values=this.map[normalizeName(name)];return values?values[0]:null},Headers.prototype.getAll=function(name){return this.map[normalizeName(name)]||[]},Headers.prototype.has=function(name){return this.map.hasOwnProperty(normalizeName(name))},Headers.prototype.set=function(name,value){this.map[normalizeName(name)]=[normalizeValue(value)]},Headers.prototype.forEach=function(callback,thisArg){Object.getOwnPropertyNames(this.map).forEach(function(name){this.map[name].forEach(function(value){callback.call(thisArg,value,name,this)},this)},this)};var support={blob:"FileReader"in self&&"Blob"in self&&function(){try{return new Blob,!0}catch(e){return!1}}(),formData:"FormData"in self,arrayBuffer:"ArrayBuffer"in self},methods=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];Request.prototype.clone=function(){return new Request(this)},Body.call(Request.prototype),Body.call(Response.prototype),Response.prototype.clone=function(){return new Response(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new Headers(this.headers),url:this.url})},Response.error=function(){var response=new Response(null,{status:0,statusText:""});return response.type="error",response};var redirectStatuses=[301,302,303,307,308];Response.redirect=function(url,status){if(-1===redirectStatuses.indexOf(status))throw new RangeError("Invalid status code");return new Response(null,{status:status,headers:{location:url}})},self.Headers=Headers,self.Request=Request,self.Response=Response,self.fetch=function(input,init){return new Promise(function(resolve,reject){function responseURL(){return"responseURL"in xhr?xhr.responseURL:/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())?xhr.getResponseHeader("X-Request-URL"):void 0}var request;request=Request.prototype.isPrototypeOf(input)&&!init?input:new Request(input,init);var xhr=new XMLHttpRequest;xhr.onload=function(){var status=1223===xhr.status?204:xhr.status;if(100>status||status>599)return void reject(new TypeError("Network request failed"));var options={status:status,statusText:xhr.statusText,headers:headers(xhr),url:responseURL()},body="response"in xhr?xhr.response:xhr.responseText;resolve(new Response(body,options))},xhr.onerror=function(){reject(new TypeError("Network request failed"))},xhr.open(request.method,request.url,!0),"include"===request.credentials&&(xhr.withCredentials=!0),"responseType"in xhr&&support.blob&&(xhr.responseType="blob"),request.headers.forEach(function(value,name){xhr.setRequestHeader(name,value)}),xhr.send("undefined"==typeof request._bodyInit?null:request._bodyInit)})},self.fetch.polyfill=!0}}("undefined"!=typeof self?self:this)},{}],29:[function(require,module,exports){!function(isNode){function merge_recursive(base,extend){if("object"!==typeOf(base))return extend;for(var key in extend)"object"===typeOf(base[key])&&"object"===typeOf(extend[key])?base[key]=merge_recursive(base[key],extend[key]):base[key]=extend[key];return base}function merge(clone,recursive,argv){var result=argv[0],size=argv.length;(clone||"object"!==typeOf(result))&&(result={});for(var index=0;size>index;++index){var item=argv[index],type=typeOf(item);if("object"===type)for(var key in item){var sitem=clone?Public.clone(item[key]):item[key];recursive?result[key]=merge_recursive(result[key],sitem):result[key]=sitem}}return result}function typeOf(input){return{}.toString.call(input).slice(8,-1).toLowerCase()}var Public=function(clone){return merge(clone===!0,!1,arguments)},publicName="merge";Public.recursive=function(clone){return merge(clone===!0,!0,arguments)},Public.clone=function(input){var index,size,output=input,type=typeOf(input);if("array"===type)for(output=[],size=input.length,index=0;size>index;++index)output[index]=Public.clone(input[index]);else if("object"===type){output={};for(index in input)output[index]=Public.clone(input[index])}return output},isNode?module.exports=Public:window[publicName]=Public}("object"==typeof module&&module&&"object"==typeof module.exports&&module.exports)},{}],30:[function(require,module,exports){"use strict";var Stringify=require("./stringify"),Parse=require("./parse");module.exports={stringify:Stringify,parse:Parse}},{"./parse":31,"./stringify":32}],31:[function(require,module,exports){"use strict";var Utils=require("./utils"),internals={delimiter:"&",depth:5,arrayLimit:20,parameterLimit:1e3,strictNullHandling:!1,plainObjects:!1,allowPrototypes:!1,allowDots:!1};internals.parseValues=function(str,options){for(var obj={},parts=str.split(options.delimiter,options.parameterLimit===1/0?void 0:options.parameterLimit),i=0;i=0&&options.parseArrays&&index<=options.arrayLimit?(obj=[],obj[index]=internals.parseObject(chain,val,options)):obj[cleanRoot]=internals.parseObject(chain,val,options)}return obj},internals.parseKeys=function(givenKey,val,options){if(givenKey){var key=options.allowDots?givenKey.replace(/\.([^\.\[]+)/g,"[$1]"):givenKey,parent=/^([^\[\]]*)/,child=/(\[[^\[\]]*\])/g,segment=parent.exec(key),keys=[];if(segment[1]){if(!options.plainObjects&&Object.prototype.hasOwnProperty(segment[1])&&!options.allowPrototypes)return;keys.push(segment[1])}for(var i=0;null!==(segment=child.exec(key))&&ii;++i)array[i]="%"+((16>i?"0":"")+i.toString(16)).toUpperCase();return array}();exports.arrayToObject=function(source,options){for(var obj=options.plainObjects?Object.create(null):{},i=0;i=48&&57>=c||c>=65&&90>=c||c>=97&&122>=c?out+=string.charAt(i):128>c?out+=hexTable[c]:2048>c?out+=hexTable[192|c>>6]+hexTable[128|63&c]:55296>c||c>=57344?out+=hexTable[224|c>>12]+hexTable[128|c>>6&63]+hexTable[128|63&c]:(i+=1,c=65536+((1023&c)<<10|1023&string.charCodeAt(i)),out+=hexTable[240|c>>18]+hexTable[128|c>>12&63]+hexTable[128|c>>6&63]+hexTable[128|63&c])}return out},exports.compact=function(obj,references){if("object"!=typeof obj||null===obj)return obj;var refs=references||[],lookup=refs.indexOf(obj);if(-1!==lookup)return refs[lookup];if(refs.push(obj),Array.isArray(obj)){for(var compacted=[],i=0;iAdd to campaignRemove from campaign"},_react2["default"].createElement("i",{className:"font-icon-dot-3"})))))},Preview}(_SilverStripeComponent2["default"]);Preview.propTypes={previewUrl:_react2["default"].PropTypes.string.isRequired,previewType:_react2["default"].PropTypes.string},exports["default"]=Preview},{"lib/SilverStripeComponent":"lib/SilverStripeComponent",react:"react"}],7:[function(require,module,exports){"use strict";function _interopRequireWildcard(obj){if(obj&&obj.__esModule)return obj;var newObj={};if(null!=obj)for(var key in obj)Object.prototype.hasOwnProperty.call(obj,key)&&(newObj[key]=obj[key]);return newObj["default"]=obj,newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{"default":obj}}function _defaults(obj,defaults){for(var keys=Object.getOwnPropertyNames(defaults),i=0;i=200&&response.status<300))throw error=new Error(response.statusText),error.response=response,error;return ret=response}Object.defineProperty(exports,"__esModule",{value:!0});var _extends=Object.assign||function(target){for(var i=1;i1)for(var i=1;ii;i+=2){var callback=lib$es6$promise$asap$$queue[i],arg=lib$es6$promise$asap$$queue[i+1];callback(arg),lib$es6$promise$asap$$queue[i]=void 0,lib$es6$promise$asap$$queue[i+1]=void 0}lib$es6$promise$asap$$len=0}function lib$es6$promise$asap$$attemptVertx(){try{var r=require,vertx=r("vertx");return lib$es6$promise$asap$$vertxNext=vertx.runOnLoop||vertx.runOnContext,lib$es6$promise$asap$$useVertxTimer()}catch(e){return lib$es6$promise$asap$$useSetTimeout()}}function lib$es6$promise$then$$then(onFulfillment,onRejection){var parent=this,state=parent._state;if(state===lib$es6$promise$$internal$$FULFILLED&&!onFulfillment||state===lib$es6$promise$$internal$$REJECTED&&!onRejection)return this;var child=new this.constructor(lib$es6$promise$$internal$$noop),result=parent._result;if(state){var callback=arguments[state-1];lib$es6$promise$asap$$asap(function(){lib$es6$promise$$internal$$invokeCallback(state,child,callback,result)})}else lib$es6$promise$$internal$$subscribe(parent,child,onFulfillment,onRejection);return child}function lib$es6$promise$promise$resolve$$resolve(object){var Constructor=this;if(object&&"object"==typeof object&&object.constructor===Constructor)return object;var promise=new Constructor(lib$es6$promise$$internal$$noop);return lib$es6$promise$$internal$$resolve(promise,object),promise}function lib$es6$promise$$internal$$noop(){}function lib$es6$promise$$internal$$selfFulfillment(){return new TypeError("You cannot resolve a promise with itself")}function lib$es6$promise$$internal$$cannotReturnOwn(){return new TypeError("A promises callback cannot return that same promise.")}function lib$es6$promise$$internal$$getThen(promise){try{return promise.then}catch(error){return lib$es6$promise$$internal$$GET_THEN_ERROR.error=error,lib$es6$promise$$internal$$GET_THEN_ERROR}}function lib$es6$promise$$internal$$tryThen(then,value,fulfillmentHandler,rejectionHandler){try{then.call(value,fulfillmentHandler,rejectionHandler)}catch(e){return e}}function lib$es6$promise$$internal$$handleForeignThenable(promise,thenable,then){lib$es6$promise$asap$$asap(function(promise){var sealed=!1,error=lib$es6$promise$$internal$$tryThen(then,thenable,function(value){sealed||(sealed=!0,thenable!==value?lib$es6$promise$$internal$$resolve(promise,value):lib$es6$promise$$internal$$fulfill(promise,value))},function(reason){sealed||(sealed=!0,lib$es6$promise$$internal$$reject(promise,reason))},"Settle: "+(promise._label||" unknown promise"));!sealed&&error&&(sealed=!0,lib$es6$promise$$internal$$reject(promise,error))},promise)}function lib$es6$promise$$internal$$handleOwnThenable(promise,thenable){thenable._state===lib$es6$promise$$internal$$FULFILLED?lib$es6$promise$$internal$$fulfill(promise,thenable._result):thenable._state===lib$es6$promise$$internal$$REJECTED?lib$es6$promise$$internal$$reject(promise,thenable._result):lib$es6$promise$$internal$$subscribe(thenable,void 0,function(value){lib$es6$promise$$internal$$resolve(promise,value)},function(reason){lib$es6$promise$$internal$$reject(promise,reason)})}function lib$es6$promise$$internal$$handleMaybeThenable(promise,maybeThenable,then){maybeThenable.constructor===promise.constructor&&then===lib$es6$promise$then$$default&&constructor.resolve===lib$es6$promise$promise$resolve$$default?lib$es6$promise$$internal$$handleOwnThenable(promise,maybeThenable):then===lib$es6$promise$$internal$$GET_THEN_ERROR?lib$es6$promise$$internal$$reject(promise,lib$es6$promise$$internal$$GET_THEN_ERROR.error):void 0===then?lib$es6$promise$$internal$$fulfill(promise,maybeThenable):lib$es6$promise$utils$$isFunction(then)?lib$es6$promise$$internal$$handleForeignThenable(promise,maybeThenable,then):lib$es6$promise$$internal$$fulfill(promise,maybeThenable)}function lib$es6$promise$$internal$$resolve(promise,value){promise===value?lib$es6$promise$$internal$$reject(promise,lib$es6$promise$$internal$$selfFulfillment()):lib$es6$promise$utils$$objectOrFunction(value)?lib$es6$promise$$internal$$handleMaybeThenable(promise,value,lib$es6$promise$$internal$$getThen(value)):lib$es6$promise$$internal$$fulfill(promise,value)}function lib$es6$promise$$internal$$publishRejection(promise){promise._onerror&&promise._onerror(promise._result),lib$es6$promise$$internal$$publish(promise)}function lib$es6$promise$$internal$$fulfill(promise,value){promise._state===lib$es6$promise$$internal$$PENDING&&(promise._result=value,promise._state=lib$es6$promise$$internal$$FULFILLED,0!==promise._subscribers.length&&lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish,promise))}function lib$es6$promise$$internal$$reject(promise,reason){promise._state===lib$es6$promise$$internal$$PENDING&&(promise._state=lib$es6$promise$$internal$$REJECTED,promise._result=reason,lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publishRejection,promise))}function lib$es6$promise$$internal$$subscribe(parent,child,onFulfillment,onRejection){var subscribers=parent._subscribers,length=subscribers.length;parent._onerror=null,subscribers[length]=child,subscribers[length+lib$es6$promise$$internal$$FULFILLED]=onFulfillment,subscribers[length+lib$es6$promise$$internal$$REJECTED]=onRejection,0===length&&parent._state&&lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish,parent)}function lib$es6$promise$$internal$$publish(promise){var subscribers=promise._subscribers,settled=promise._state;if(0!==subscribers.length){for(var child,callback,detail=promise._result,i=0;ii;i++)lib$es6$promise$$internal$$subscribe(Constructor.resolve(entries[i]),void 0,onFulfillment,onRejection);return promise}function lib$es6$promise$promise$reject$$reject(reason){var Constructor=this,promise=new Constructor(lib$es6$promise$$internal$$noop);return lib$es6$promise$$internal$$reject(promise,reason),promise}function lib$es6$promise$promise$$needsResolver(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function lib$es6$promise$promise$$needsNew(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function lib$es6$promise$promise$$Promise(resolver){this._id=lib$es6$promise$promise$$counter++,this._state=void 0,this._result=void 0,this._subscribers=[],lib$es6$promise$$internal$$noop!==resolver&&("function"!=typeof resolver&&lib$es6$promise$promise$$needsResolver(),this instanceof lib$es6$promise$promise$$Promise?lib$es6$promise$$internal$$initializePromise(this,resolver):lib$es6$promise$promise$$needsNew())}function lib$es6$promise$enumerator$$Enumerator(Constructor,input){this._instanceConstructor=Constructor,this.promise=new Constructor(lib$es6$promise$$internal$$noop),Array.isArray(input)?(this._input=input,this.length=input.length,this._remaining=input.length,this._result=new Array(this.length),0===this.length?lib$es6$promise$$internal$$fulfill(this.promise,this._result):(this.length=this.length||0,this._enumerate(),0===this._remaining&&lib$es6$promise$$internal$$fulfill(this.promise,this._result))):lib$es6$promise$$internal$$reject(this.promise,this._validationError())}function lib$es6$promise$polyfill$$polyfill(){var local;if("undefined"!=typeof global)local=global;else if("undefined"!=typeof self)local=self;else try{local=Function("return this")()}catch(e){throw new Error("polyfill failed because global object is unavailable in this environment")}var P=local.Promise;P&&"[object Promise]"===Object.prototype.toString.call(P.resolve())&&!P.cast||(local.Promise=lib$es6$promise$promise$$default)}var lib$es6$promise$utils$$_isArray;lib$es6$promise$utils$$_isArray=Array.isArray?Array.isArray:function(x){return"[object Array]"===Object.prototype.toString.call(x)};var lib$es6$promise$asap$$vertxNext,lib$es6$promise$asap$$customSchedulerFn,lib$es6$promise$asap$$scheduleFlush,lib$es6$promise$utils$$isArray=lib$es6$promise$utils$$_isArray,lib$es6$promise$asap$$len=0,lib$es6$promise$asap$$asap=function(callback,arg){lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len]=callback,lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len+1]=arg,lib$es6$promise$asap$$len+=2,2===lib$es6$promise$asap$$len&&(lib$es6$promise$asap$$customSchedulerFn?lib$es6$promise$asap$$customSchedulerFn(lib$es6$promise$asap$$flush):lib$es6$promise$asap$$scheduleFlush())},lib$es6$promise$asap$$browserWindow="undefined"!=typeof window?window:void 0,lib$es6$promise$asap$$browserGlobal=lib$es6$promise$asap$$browserWindow||{},lib$es6$promise$asap$$BrowserMutationObserver=lib$es6$promise$asap$$browserGlobal.MutationObserver||lib$es6$promise$asap$$browserGlobal.WebKitMutationObserver,lib$es6$promise$asap$$isNode="undefined"!=typeof process&&"[object process]"==={}.toString.call(process),lib$es6$promise$asap$$isWorker="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,lib$es6$promise$asap$$queue=new Array(1e3);lib$es6$promise$asap$$scheduleFlush=lib$es6$promise$asap$$isNode?lib$es6$promise$asap$$useNextTick():lib$es6$promise$asap$$BrowserMutationObserver?lib$es6$promise$asap$$useMutationObserver():lib$es6$promise$asap$$isWorker?lib$es6$promise$asap$$useMessageChannel():void 0===lib$es6$promise$asap$$browserWindow&&"function"==typeof require?lib$es6$promise$asap$$attemptVertx():lib$es6$promise$asap$$useSetTimeout();var lib$es6$promise$then$$default=lib$es6$promise$then$$then,lib$es6$promise$promise$resolve$$default=lib$es6$promise$promise$resolve$$resolve,lib$es6$promise$$internal$$PENDING=void 0,lib$es6$promise$$internal$$FULFILLED=1,lib$es6$promise$$internal$$REJECTED=2,lib$es6$promise$$internal$$GET_THEN_ERROR=new lib$es6$promise$$internal$$ErrorObject,lib$es6$promise$$internal$$TRY_CATCH_ERROR=new lib$es6$promise$$internal$$ErrorObject,lib$es6$promise$promise$all$$default=lib$es6$promise$promise$all$$all,lib$es6$promise$promise$race$$default=lib$es6$promise$promise$race$$race,lib$es6$promise$promise$reject$$default=lib$es6$promise$promise$reject$$reject,lib$es6$promise$promise$$counter=0,lib$es6$promise$promise$$default=lib$es6$promise$promise$$Promise;lib$es6$promise$promise$$Promise.all=lib$es6$promise$promise$all$$default,lib$es6$promise$promise$$Promise.race=lib$es6$promise$promise$race$$default,lib$es6$promise$promise$$Promise.resolve=lib$es6$promise$promise$resolve$$default,lib$es6$promise$promise$$Promise.reject=lib$es6$promise$promise$reject$$default,lib$es6$promise$promise$$Promise._setScheduler=lib$es6$promise$asap$$setScheduler,lib$es6$promise$promise$$Promise._setAsap=lib$es6$promise$asap$$setAsap,lib$es6$promise$promise$$Promise._asap=lib$es6$promise$asap$$asap,lib$es6$promise$promise$$Promise.prototype={constructor:lib$es6$promise$promise$$Promise,then:lib$es6$promise$then$$default,"catch":function(onRejection){return this.then(null,onRejection)}};var lib$es6$promise$enumerator$$default=lib$es6$promise$enumerator$$Enumerator;lib$es6$promise$enumerator$$Enumerator.prototype._validationError=function(){return new Error("Array Methods must be provided an Array")},lib$es6$promise$enumerator$$Enumerator.prototype._enumerate=function(){for(var length=this.length,input=this._input,i=0;this._state===lib$es6$promise$$internal$$PENDING&&length>i;i++)this._eachEntry(input[i],i)},lib$es6$promise$enumerator$$Enumerator.prototype._eachEntry=function(entry,i){var c=this._instanceConstructor,resolve=c.resolve;if(resolve===lib$es6$promise$promise$resolve$$default){var then=lib$es6$promise$$internal$$getThen(entry);if(then===lib$es6$promise$then$$default&&entry._state!==lib$es6$promise$$internal$$PENDING)this._settledAt(entry._state,i,entry._result);else if("function"!=typeof then)this._remaining--,this._result[i]=entry;else if(c===lib$es6$promise$promise$$default){var promise=new c(lib$es6$promise$$internal$$noop);lib$es6$promise$$internal$$handleMaybeThenable(promise,entry,then),this._willSettleAt(promise,i)}else this._willSettleAt(new c(function(resolve){resolve(entry)}),i)}else this._willSettleAt(resolve(entry),i)},lib$es6$promise$enumerator$$Enumerator.prototype._settledAt=function(state,i,value){var promise=this.promise;promise._state===lib$es6$promise$$internal$$PENDING&&(this._remaining--,state===lib$es6$promise$$internal$$REJECTED?lib$es6$promise$$internal$$reject(promise,value):this._result[i]=value),0===this._remaining&&lib$es6$promise$$internal$$fulfill(promise,this._result)},lib$es6$promise$enumerator$$Enumerator.prototype._willSettleAt=function(promise,i){var enumerator=this;lib$es6$promise$$internal$$subscribe(promise,void 0,function(value){enumerator._settledAt(lib$es6$promise$$internal$$FULFILLED,i,value)},function(reason){enumerator._settledAt(lib$es6$promise$$internal$$REJECTED,i,reason)})};var lib$es6$promise$polyfill$$default=lib$es6$promise$polyfill$$polyfill,lib$es6$promise$umd$$ES6Promise={Promise:lib$es6$promise$promise$$default,polyfill:lib$es6$promise$polyfill$$default};"function"==typeof define&&define.amd?define(function(){return lib$es6$promise$umd$$ES6Promise}):"undefined"!=typeof module&&module.exports?module.exports=lib$es6$promise$umd$$ES6Promise:"undefined"!=typeof this&&(this.ES6Promise=lib$es6$promise$umd$$ES6Promise),lib$es6$promise$polyfill$$default()}).call(this)}).call(this,require("_process"),"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{_process:25}],27:[function(require,module,exports){require("whatwg-fetch"),module.exports=self.fetch.bind(self)},{"whatwg-fetch":28}],28:[function(require,module,exports){!function(self){"use strict";function normalizeName(name){if("string"!=typeof name&&(name=String(name)),/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name))throw new TypeError("Invalid character in header field name");return name.toLowerCase()}function normalizeValue(value){return"string"!=typeof value&&(value=String(value)),value}function Headers(headers){this.map={},headers instanceof Headers?headers.forEach(function(value,name){this.append(name,value)},this):headers&&Object.getOwnPropertyNames(headers).forEach(function(name){this.append(name,headers[name])},this)}function consumed(body){return body.bodyUsed?Promise.reject(new TypeError("Already read")):void(body.bodyUsed=!0)}function fileReaderReady(reader){return new Promise(function(resolve,reject){reader.onload=function(){resolve(reader.result)},reader.onerror=function(){reject(reader.error)}})}function readBlobAsArrayBuffer(blob){var reader=new FileReader;return reader.readAsArrayBuffer(blob),fileReaderReady(reader)}function readBlobAsText(blob){var reader=new FileReader;return reader.readAsText(blob),fileReaderReady(reader)}function Body(){return this.bodyUsed=!1,this._initBody=function(body){if(this._bodyInit=body,"string"==typeof body)this._bodyText=body;else if(support.blob&&Blob.prototype.isPrototypeOf(body))this._bodyBlob=body;else if(support.formData&&FormData.prototype.isPrototypeOf(body))this._bodyFormData=body;else if(body){if(!support.arrayBuffer||!ArrayBuffer.prototype.isPrototypeOf(body))throw new Error("unsupported BodyInit type")}else this._bodyText="";this.headers.get("content-type")||("string"==typeof body?this.headers.set("content-type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type&&this.headers.set("content-type",this._bodyBlob.type))},support.blob?(this.blob=function(){var rejected=consumed(this);if(rejected)return rejected;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){return this.blob().then(readBlobAsArrayBuffer)},this.text=function(){var rejected=consumed(this);if(rejected)return rejected;if(this._bodyBlob)return readBlobAsText(this._bodyBlob);if(this._bodyFormData)throw new Error("could not read FormData body as text");return Promise.resolve(this._bodyText)}):this.text=function(){var rejected=consumed(this);return rejected?rejected:Promise.resolve(this._bodyText)},support.formData&&(this.formData=function(){return this.text().then(decode)}),this.json=function(){return this.text().then(JSON.parse)},this}function normalizeMethod(method){var upcased=method.toUpperCase();return methods.indexOf(upcased)>-1?upcased:method}function Request(input,options){options=options||{};var body=options.body;if(Request.prototype.isPrototypeOf(input)){if(input.bodyUsed)throw new TypeError("Already read");this.url=input.url,this.credentials=input.credentials,options.headers||(this.headers=new Headers(input.headers)),this.method=input.method,this.mode=input.mode,body||(body=input._bodyInit,input.bodyUsed=!0)}else this.url=input;if(this.credentials=options.credentials||this.credentials||"omit",!options.headers&&this.headers||(this.headers=new Headers(options.headers)),this.method=normalizeMethod(options.method||this.method||"GET"),this.mode=options.mode||this.mode||null,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&body)throw new TypeError("Body not allowed for GET or HEAD requests");this._initBody(body)}function decode(body){var form=new FormData;return body.trim().split("&").forEach(function(bytes){if(bytes){var split=bytes.split("="),name=split.shift().replace(/\+/g," "),value=split.join("=").replace(/\+/g," ");form.append(decodeURIComponent(name),decodeURIComponent(value))}}),form}function headers(xhr){var head=new Headers,pairs=xhr.getAllResponseHeaders().trim().split("\n");return pairs.forEach(function(header){var split=header.trim().split(":"),key=split.shift().trim(),value=split.join(":").trim();head.append(key,value)}),head}function Response(bodyInit,options){options||(options={}),this.type="default",this.status=options.status,this.ok=this.status>=200&&this.status<300,this.statusText=options.statusText,this.headers=options.headers instanceof Headers?options.headers:new Headers(options.headers),this.url=options.url||"",this._initBody(bodyInit)}if(!self.fetch){Headers.prototype.append=function(name,value){name=normalizeName(name),value=normalizeValue(value);var list=this.map[name];list||(list=[],this.map[name]=list),list.push(value)},Headers.prototype["delete"]=function(name){delete this.map[normalizeName(name)]},Headers.prototype.get=function(name){var values=this.map[normalizeName(name)];return values?values[0]:null},Headers.prototype.getAll=function(name){return this.map[normalizeName(name)]||[]},Headers.prototype.has=function(name){return this.map.hasOwnProperty(normalizeName(name))},Headers.prototype.set=function(name,value){this.map[normalizeName(name)]=[normalizeValue(value)]},Headers.prototype.forEach=function(callback,thisArg){Object.getOwnPropertyNames(this.map).forEach(function(name){this.map[name].forEach(function(value){callback.call(thisArg,value,name,this)},this)},this)};var support={blob:"FileReader"in self&&"Blob"in self&&function(){try{return new Blob,!0}catch(e){return!1}}(),formData:"FormData"in self,arrayBuffer:"ArrayBuffer"in self},methods=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];Request.prototype.clone=function(){return new Request(this)},Body.call(Request.prototype),Body.call(Response.prototype),Response.prototype.clone=function(){return new Response(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new Headers(this.headers),url:this.url})},Response.error=function(){var response=new Response(null,{status:0,statusText:""});return response.type="error",response};var redirectStatuses=[301,302,303,307,308];Response.redirect=function(url,status){if(-1===redirectStatuses.indexOf(status))throw new RangeError("Invalid status code");return new Response(null,{status:status,headers:{location:url}})},self.Headers=Headers,self.Request=Request,self.Response=Response,self.fetch=function(input,init){return new Promise(function(resolve,reject){function responseURL(){return"responseURL"in xhr?xhr.responseURL:/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())?xhr.getResponseHeader("X-Request-URL"):void 0}var request;request=Request.prototype.isPrototypeOf(input)&&!init?input:new Request(input,init);var xhr=new XMLHttpRequest;xhr.onload=function(){var status=1223===xhr.status?204:xhr.status;if(100>status||status>599)return void reject(new TypeError("Network request failed"));var options={status:status,statusText:xhr.statusText,headers:headers(xhr),url:responseURL()},body="response"in xhr?xhr.response:xhr.responseText;resolve(new Response(body,options))},xhr.onerror=function(){reject(new TypeError("Network request failed"))},xhr.open(request.method,request.url,!0),"include"===request.credentials&&(xhr.withCredentials=!0),"responseType"in xhr&&support.blob&&(xhr.responseType="blob"),request.headers.forEach(function(value,name){xhr.setRequestHeader(name,value)}),xhr.send("undefined"==typeof request._bodyInit?null:request._bodyInit)})},self.fetch.polyfill=!0}}("undefined"!=typeof self?self:this)},{}],29:[function(require,module,exports){!function(isNode){function merge_recursive(base,extend){if("object"!==typeOf(base))return extend;for(var key in extend)"object"===typeOf(base[key])&&"object"===typeOf(extend[key])?base[key]=merge_recursive(base[key],extend[key]):base[key]=extend[key];return base}function merge(clone,recursive,argv){var result=argv[0],size=argv.length;(clone||"object"!==typeOf(result))&&(result={});for(var index=0;size>index;++index){var item=argv[index],type=typeOf(item);if("object"===type)for(var key in item){var sitem=clone?Public.clone(item[key]):item[key];recursive?result[key]=merge_recursive(result[key],sitem):result[key]=sitem}}return result}function typeOf(input){return{}.toString.call(input).slice(8,-1).toLowerCase()}var Public=function(clone){return merge(clone===!0,!1,arguments)},publicName="merge";Public.recursive=function(clone){return merge(clone===!0,!0,arguments)},Public.clone=function(input){var index,size,output=input,type=typeOf(input);if("array"===type)for(output=[],size=input.length,index=0;size>index;++index)output[index]=Public.clone(input[index]);else if("object"===type){output={};for(index in input)output[index]=Public.clone(input[index])}return output},isNode?module.exports=Public:window[publicName]=Public}("object"==typeof module&&module&&"object"==typeof module.exports&&module.exports)},{}],30:[function(require,module,exports){"use strict";var Stringify=require("./stringify"),Parse=require("./parse");module.exports={stringify:Stringify,parse:Parse}},{"./parse":31,"./stringify":32}],31:[function(require,module,exports){"use strict";var Utils=require("./utils"),internals={delimiter:"&",depth:5,arrayLimit:20,parameterLimit:1e3,strictNullHandling:!1,plainObjects:!1,allowPrototypes:!1,allowDots:!1};internals.parseValues=function(str,options){for(var obj={},parts=str.split(options.delimiter,options.parameterLimit===1/0?void 0:options.parameterLimit),i=0;i=0&&options.parseArrays&&index<=options.arrayLimit?(obj=[],obj[index]=internals.parseObject(chain,val,options)):obj[cleanRoot]=internals.parseObject(chain,val,options)}return obj},internals.parseKeys=function(givenKey,val,options){if(givenKey){var key=options.allowDots?givenKey.replace(/\.([^\.\[]+)/g,"[$1]"):givenKey,parent=/^([^\[\]]*)/,child=/(\[[^\[\]]*\])/g,segment=parent.exec(key),keys=[];if(segment[1]){if(!options.plainObjects&&Object.prototype.hasOwnProperty(segment[1])&&!options.allowPrototypes)return;keys.push(segment[1])}for(var i=0;null!==(segment=child.exec(key))&&ii;++i)array[i]="%"+((16>i?"0":"")+i.toString(16)).toUpperCase();return array}();exports.arrayToObject=function(source,options){for(var obj=options.plainObjects?Object.create(null):{},i=0;i=48&&57>=c||c>=65&&90>=c||c>=97&&122>=c?out+=string.charAt(i):128>c?out+=hexTable[c]:2048>c?out+=hexTable[192|c>>6]+hexTable[128|63&c]:55296>c||c>=57344?out+=hexTable[224|c>>12]+hexTable[128|c>>6&63]+hexTable[128|63&c]:(i+=1,c=65536+((1023&c)<<10|1023&string.charCodeAt(i)),out+=hexTable[240|c>>18]+hexTable[128|c>>12&63]+hexTable[128|c>>6&63]+hexTable[128|63&c])}return out},exports.compact=function(obj,references){if("object"!=typeof obj||null===obj)return obj;var refs=references||[],lookup=refs.indexOf(obj);if(-1!==lookup)return refs[lookup];if(refs.push(obj),Array.isArray(obj)){for(var compacted=[],i=0;i; - } else { + if (!this.props.previewUrl) { body = (

There is no preview available for this item.

); + } else if (this.props.previewType.indexOf('image/') === 0) { + body = ( +
+ {this.props.previewUrl} +
+ ); + } else { + body = ; } return ( - ); } } +Preview.propTypes = { + previewUrl: React.PropTypes.string.isRequired, + previewType: React.PropTypes.string, // Mime type +}; + export default Preview; diff --git a/admin/client/src/containers/CampaignAdmin/CampaignAdmin.js b/admin/client/src/containers/CampaignAdmin/CampaignAdmin.js index 2dab781b8..ff991492c 100644 --- a/admin/client/src/containers/CampaignAdmin/CampaignAdmin.js +++ b/admin/client/src/containers/CampaignAdmin/CampaignAdmin.js @@ -297,20 +297,6 @@ class CampaignAdmin extends SilverStripeComponent { ]; } - /** - * Gets preview URL for itemid - * @param int id - * @returns string - */ - previewURLForItem(id) { - if (!id) { - return ''; - } - - // hard code in baseurl for any itemid preview url - return document.getElementsByTagName('base')[0].href; - } - addCampaign() { const path = this.props.sectionConfig.campaignViewRoute .replace(/:type\?/, 'set') diff --git a/admin/client/src/containers/CampaignAdmin/CampaignAdminList.js b/admin/client/src/containers/CampaignAdmin/CampaignAdminList.js index 676c5816d..78bc105d8 100644 --- a/admin/client/src/containers/CampaignAdmin/CampaignAdminList.js +++ b/admin/client/src/containers/CampaignAdmin/CampaignAdminList.js @@ -41,6 +41,7 @@ class CampaignAdminList extends SilverStripeComponent { render() { let itemID = this.props.campaign.changeSetItemId; let previewUrl = null; + let previewType = null; const campaignId = this.props.campaignId; const campaign = this.props.record; @@ -69,8 +70,10 @@ class CampaignAdminList extends SilverStripeComponent { if (selected && item._links.preview) { if (item._links.preview.Stage) { previewUrl = item._links.preview.Stage.href; + previewType = item._links.preview.Stage.type; } else if (item._links.preview.Live) { previewUrl = item._links.preview.Live.href; + previewType = item._links.preview.Live.type; } } @@ -118,7 +121,7 @@ class CampaignAdminList extends SilverStripeComponent { {this.renderButtonToolbar()} - { previewUrl && } + { previewUrl && } ); } @@ -183,20 +186,6 @@ class CampaignAdminList extends SilverStripeComponent { ); } - /** - * Gets preview URL for itemid - * @param int id - * @returns string - */ - previewURLForItem(id) { - if (!id) { - return ''; - } - - // hard code in baseurl for any itemid preview url - return document.getElementsByTagName('base')[0].href; - } - /** * @return {Array} */ diff --git a/admin/code/CMSPreviewable.php b/admin/code/CMSPreviewable.php index 7eafe9769..847fc414a 100644 --- a/admin/code/CMSPreviewable.php +++ b/admin/code/CMSPreviewable.php @@ -14,14 +14,24 @@ interface CMSPreviewable { /** + * Determine the preview link, if available, for this object. + * If no preview is available for this record, it may return null. + * * @param string $action - * @return string Absolute URL to the end-user view for this record. + * @return string Link to the end-user view for this record. * Example: http://mysite.com/my-record */ public function PreviewLink($action = null); /** - * @return string Absolute URL to the CMS-author view. Should point to a + * To determine preview mechanism (e.g. embedded / iframe) + * + * @return string + */ + public function getMimeType(); + + /** + * @return string Link to the CMS-author view. Should point to a * controller subclassing {@link LeftAndMain}. Example: * http://mysite.com/admin/edit/6 */ diff --git a/admin/code/CampaignAdmin.php b/admin/code/CampaignAdmin.php index 3c81b73be..ee8a74647 100644 --- a/admin/code/CampaignAdmin.php +++ b/admin/code/CampaignAdmin.php @@ -295,15 +295,9 @@ JSON; 'Thumbnail' => $changeSetItem->ThumbnailURL($thumbnailWidth, $thumbnailHeight), ]; // Get preview urls - $previewLinks = []; $previews = $changeSetItem->getPreviewLinks(); - foreach($previews as $name => $link) { - $previewLinks[$name] = [ - 'href' => $link, - ]; - } - if($previewLinks) { - $hal['_links']['preview'] = $previewLinks; + if($previews) { + $hal['_links']['preview'] = $previews; } // Get edit link diff --git a/docs/en/04_Changelogs/4.0.0.md b/docs/en/04_Changelogs/4.0.0.md index 9b1ea7b71..df5e69b15 100644 --- a/docs/en/04_Changelogs/4.0.0.md +++ b/docs/en/04_Changelogs/4.0.0.md @@ -41,6 +41,7 @@ * `CMSBatchAction_DeleteFromLive` is removed. * `CMSMain.enabled_legacy_actions` config is removed. * `DataObject::can` has new method signature with `$context` parameter. + * `SiteTree.alternatePreviewLink` is deprecated. Use `updatePreviewLink` instead. ## New API diff --git a/filesystem/File.php b/filesystem/File.php index 3bd4add83..81da3444f 100644 --- a/filesystem/File.php +++ b/filesystem/File.php @@ -1,5 +1,6 @@ File->exists()) { return $this->File->getURL($grant); - } + } } /** @@ -721,7 +722,7 @@ class File extends DataObject implements ShortcodeHandler, AssetContainer, Thumb public function getSourceURL($grant = true) { if($this->File->exists()) { return $this->File->getSourceURL($grant); - } + } } /** @@ -1170,7 +1171,8 @@ class File extends DataObject implements ShortcodeHandler, AssetContainer, Thumb } public function PreviewLink($action = null) { - $link = $this->Link(); + // No preview for non-images by default + $link = null; $this->extend('updatePreviewLink', $link, $action); return $link; } diff --git a/model/Image.php b/model/Image.php index bebe5beb5..657ca2dfc 100644 --- a/model/Image.php +++ b/model/Image.php @@ -120,4 +120,15 @@ class Image extends File implements ShortcodeHandler { $regenerator = ShortcodeParser::get('regenerator'); return $regenerator->parse($value); } + + public function PreviewLink($action = null) { + // Since AbsoluteLink can whitelist protected assets, + // do permission check first + if(!$this->canView()) { + return false; + } + $link = $this->AbsoluteLink(); + $this->extend('updatePreviewLink', $link, $action); + return $link; + } } diff --git a/model/versioning/ChangeSetItem.php b/model/versioning/ChangeSetItem.php index 6ec41e16d..93dbe8d5b 100644 --- a/model/versioning/ChangeSetItem.php +++ b/model/versioning/ChangeSetItem.php @@ -349,27 +349,29 @@ class ChangeSetItem extends DataObject implements Thumbnail { /** * Gets the list of modes this record can be previewed in. * - * @return array Map of mode names to url + * {@link https://tools.ietf.org/html/draft-kelly-json-hal-07#section-5} + * + * @return array Map of links in acceptable HAL format */ public function getPreviewLinks() { $links = []; // Preview draft $stage = $this->getObjectInStage(Versioned::DRAFT); - if($stage instanceof CMSPreviewable && $stage->canView()) { - $links[Versioned::DRAFT] = Controller::join_links( - $stage->PreviewLink(), - '?stage=' . Versioned::DRAFT - ); + if($stage instanceof CMSPreviewable && $stage->canView() && ($link = $stage->PreviewLink())) { + $links[Versioned::DRAFT] = [ + 'href' => Controller::join_links($link, '?stage=' . Versioned::DRAFT), + 'type' => $stage->getMimeType(), + ]; } // Preview live $live = $this->getObjectInStage(Versioned::LIVE); - if($live instanceof CMSPreviewable && $live->canView()) { - $links[Versioned::LIVE] = Controller::join_links( - $live->PreviewLink(), - '?stage=' . Versioned::LIVE - ); + if($live instanceof CMSPreviewable && $live->canView() && ($link = $live->PreviewLink())) { + $links[Versioned::LIVE] = [ + 'href' => Controller::join_links($link, '?stage=' . Versioned::LIVE), + 'type' => $live->getMimeType(), + ]; } return $links;