diff --git a/client/dist/js/bundle.js b/client/dist/js/bundle.js index 1b33a6e52..5fdb540e5 100644 --- a/client/dist/js/bundle.js +++ b/client/dist/js/bundle.js @@ -2,7 +2,7 @@ var o=n[r]={exports:{},id:r,loaded:!1} return e[r].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={} return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict" -n(1),n(277),n(297)},function(e,t,n){(function(t){e.exports=t.InsertMediaModal=n(2)}).call(t,function(){return this}())},function(e,t,n){"use strict" +n(1),n(277),n(297),n(299)},function(e,t,n){(function(t){e.exports=t.InsertMediaModal=n(2)}).call(t,function(){return this}())},function(e,t,n){"use strict" function r(e){if(e&&e.__esModule)return e var t={} if(null!=e)for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n]) @@ -58,7 +58,7 @@ return{loading:n,files:o,folder:r,securityId:e.config.SecurityID}}function u(e){ value:!0}),t.AssetAdmin=void 0 var p=Object.assign||function(e){for(var t=1;t-1}},{key:"itemIsHighlighted",value:function M(e){return this.props.fileId===e}},{key:"handleOpenFolder",value:function H(e,t){ e.preventDefault(),this.props.onOpenFolder(t.id)}},{key:"handleOpenFile",value:function G(e,t){e.preventDefault(),null!==t.created&&this.props.onOpenFile(t.id,t)}},{key:"handleSelect",value:function z(e,t){ @@ -232,10 +232,10 @@ return t===e.props.view?null:(o.push("font-icon-"+r),v["default"].createElement( value:function $(){var e=["btn","btn-secondary","btn--no-text","font-icon-level-up","btn--icon-large","gallery__back"].join(" ") return null!==this.props.folder.parentID?v["default"].createElement("button",{className:e,onClick:this.handleBackClick,ref:"backButton"}):null}},{key:"renderBulkActions",value:function Z(){var e=this,t=function i(t){ var n=t.map(function(e){return e.id}) -e.props.actions.gallery.deleteItems(e.props.deleteApi,n)},n=function s(t){e.props.onOpenFile(t[0].id)},r=L["default"].BULK_ACTIONS.map(function(e){return"delete"!==e.value||e.callback?"edit"!==e.value||e.callback?e:d({},e,{ +e.props.actions.gallery.deleteItems(e.props.deleteApi,n)},n=function s(t){e.props.onOpenFile(t[0].id)},r=U["default"].BULK_ACTIONS.map(function(e){return"delete"!==e.value||e.callback?"edit"!==e.value||e.callback?e:d({},e,{ callback:n}):d({},e,{callback:t})}),o=this.props.selectedFiles.map(function(t){return e.props.files.find(function(e){return t===e.id})}) -return o.length>0&&"admin"===this.props.type?v["default"].createElement(w["default"],{transitionName:"bulk-actions",transitionEnterTimeout:L["default"].CSS_TRANSITION_TIME,transitionLeaveTimeout:L["default"].CSS_TRANSITION_TIME -},v["default"].createElement(I["default"],{actions:r,items:o,key:o.length>0})):null}},{key:"renderNoItemsNotice",value:function Y(){return 0!==this.props.files.length||this.props.loading?null:v["default"].createElement("p",{ +return o.length>0&&"admin"===this.props.type?v["default"].createElement(w["default"],{transitionName:"bulk-actions",transitionEnterTimeout:U["default"].CSS_TRANSITION_TIME,transitionLeaveTimeout:U["default"].CSS_TRANSITION_TIME +},v["default"].createElement(A["default"],{actions:r,items:o,key:o.length>0})):null}},{key:"renderNoItemsNotice",value:function Y(){return 0!==this.props.files.length||this.props.loading?null:v["default"].createElement("p",{ className:"gallery__no-item-notice"},g["default"]._t("AssetAdmin.NOITEMSFOUND"))}},{key:"renderGalleryView",value:function X(){var e=this,t="table"===this.props.view?N["default"]:D["default"],n=this.props.files.map(function(t){ return d({},t,{selected:e.itemIsSelected(t.id),highlighted:e.itemIsHighlighted(t.id)})}),r=this.props.queuedFiles.items.map(function(e){return d({},e,{uploading:!0})}),o=[].concat(i(r),i(n)),s=this.props,l=s.type,a=s.loading,u=s.page,p=s.count,c=s.limit,f=s.sort,h={ selectableItems:"admin"===l,files:o,loading:a,page:u,count:p,limit:c,sort:f,onSort:this.handleSort,onSetPage:this.handleSetPage,onOpenFile:this.handleOpenFile,onOpenFolder:this.handleOpenFolder,onSelect:this.handleSelect, @@ -244,7 +244,7 @@ return v["default"].createElement(t,h)}},{key:"render",value:function J(){if(!th className:"gallery__error-message"},v["default"].createElement("h3",null,this.props.errorMessage&&g["default"]._t("AssetAdmin.DROPZONE_RESPONSE_ERROR","Server responded with an error.")),v["default"].createElement("p",null,this.props.errorMessage))):null -var e={height:L["default"].THUMBNAIL_HEIGHT,width:L["default"].THUMBNAIL_WIDTH},t={url:this.props.createFileApiUrl,method:this.props.createFileApiMethod,paramName:"Upload",clickable:"#upload-button"},n=this.props.securityId,r=this.props.folder.canEdit,o=["panel","panel--padded","panel--scrollable","gallery__main"] +var e={height:U["default"].THUMBNAIL_HEIGHT,width:U["default"].THUMBNAIL_WIDTH},t={url:this.props.createFileApiUrl,method:this.props.createFileApiMethod,paramName:"Upload",clickable:"#upload-button"},n=this.props.securityId,r=this.props.folder.canEdit,o=["panel","panel--padded","panel--scrollable","gallery__main"] return"insert"===this.props.type&&o.push("insert-media-modal__main"),v["default"].createElement("div",{className:"flexbox-area-grow gallery__outer"},this.renderBulkActions(),v["default"].createElement(T["default"],{ @@ -254,7 +254,7 @@ page:0,limit:15,sort:B[0].field+","+B[0].direction},q={loading:y.PropTypes.bool, })})).isRequired,count:y.PropTypes.number,page:y.PropTypes.number,limit:y.PropTypes.number,onOpenFile:y.PropTypes.func.isRequired,onOpenFolder:y.PropTypes.func.isRequired,onSort:y.PropTypes.func.isRequired, onSetPage:y.PropTypes.func.isRequired},Q=d({},z,{selectableItems:!1}),V=d({},q,{selectableItems:y.PropTypes.bool,onSelect:y.PropTypes.func,onCancelUpload:y.PropTypes.func,onRemoveErroredUpload:y.PropTypes.func, renderNoItemsNotice:y.PropTypes.func.isRequired}) -G.defaultProps=d({},z,{type:"admin",view:"tile"}),G.propTypes=d({},q,{type:y.PropTypes.oneOf(["insert","admin"]),view:y.PropTypes.oneOf(["tile","table"]),dialog:y.PropTypes.bool,fileId:y.PropTypes.number, +G.defaultProps=d({},z,{type:"admin",view:"tile"}),G.propTypes=d({},q,{type:y.PropTypes.oneOf(["insert","select","admin"]),view:y.PropTypes.oneOf(["tile","table"]),dialog:y.PropTypes.bool,fileId:y.PropTypes.number, folderId:y.PropTypes.number.isRequired,folder:y.PropTypes.shape({id:y.PropTypes.number,parentID:y.PropTypes.number,canView:y.PropTypes.bool,canEdit:y.PropTypes.bool}),queuedFiles:y.PropTypes.shape({items:y.PropTypes.array.isRequired }),selectedFiles:y.PropTypes.arrayOf(y.PropTypes.number),errorMessage:y.PropTypes.string,actions:y.PropTypes.object.isRequired,securityId:y.PropTypes.string,onViewChange:y.PropTypes.func.isRequired,createFileApiUrl:y.PropTypes.string, createFileApiMethod:y.PropTypes.string,createFolderApi:y.PropTypes.func,readFolderApi:y.PropTypes.func,deleteApi:y.PropTypes.func}),t.Gallery=G,t.sorters=B,t.galleryViewPropTypes=V,t.galleryViewDefaultProps=Q, @@ -316,8 +316,8 @@ return/[.]/.exec(e)?e.replace(/^.+[.]/,""):""}},{key:"loadImage",value:function return new Promise(function(r){e.onload=function(){var t=document.createElement("canvas"),o=t.getContext("2d"),i=2*n.props.preview.width,s=2*n.props.preview.height,l=e.naturalWidth/e.naturalHeight e.naturalWidth=U;p=0<=U?++A:--A)i.append(this._getParamName(p),e[p],this._renameFilename(e[p].name)) +c=d.getAttribute("name"),f=d.getAttribute("type"),"SELECT"===d.tagName&&d.hasAttribute("multiple"))for(R=d.options,P=0,A=R.length;P=L;p=0<=L?++I:--I)i.append(this._getParamName(p),e[p],this._renameFilename(e[p].name)) return this.submitRequest(S,i,e)},t.prototype.submitRequest=function(e,t,n){return e.send(t)},t.prototype._finished=function(e,n,r){var o,i,s for(i=0,s=e.length;i0?y.keys(this.props.results[0]):[],this.props.columns,this.props.childrenColumnName,this.props.columnMetadata,this.props.metadataColumns), this.rowSettings=new g(this.props.rowMetadata,this.props.useCustomTableRowComponent&&this.props.customTableRowComponent?this.props.customTableRowComponent:p,this.props.useCustomTableRowComponent),this.props.initialSort&&this.changeSort(this.props.initialSort), @@ -737,7 +737,7 @@ var e=this.getDataForRender(this.getCurrentResults(),this.columnSettings.getColu S(e,function(e){r._updateSelectedRowIds(e[r.props.uniqueIdentifier],n,t)},this),this.setState({isSelectAllChecked:t,selectedRowIds:n}),this.props.onSelectionChange&&this.props.onSelectionChange(n,t)},_toggleSelectRow:function me(e,t){ var n=this.getDataForRender(this.getCurrentResults(),this.columnSettings.getColumns(),!0),r=JSON.parse(JSON.stringify(this.state.selectedRowIds)) this._updateSelectedRowIds(e[this.props.uniqueIdentifier],r,t) -var o=this._getAreAllRowsChecked(r,I(n,this.props.uniqueIdentifier)) +var o=this._getAreAllRowsChecked(r,A(n,this.props.uniqueIdentifier)) this.setState({isSelectAllChecked:o,selectedRowIds:r}),this.props.onSelectionChange&&this.props.onSelectionChange(r,o)},_updateSelectedRowIds:function ge(e,t,n){var r n?(r=C(t,function(t){return e===t}),void 0===r&&t.push(e)):t.splice(t.indexOf(e),1)},_getIsSelectAllChecked:function ye(){return this.state.isSelectAllChecked},_getAreAllRowsChecked:function ve(e,t){return t.length===w(t,e).length @@ -752,11 +752,11 @@ onClick:this.toggleColumnChooser,style:this.props.useGriddleStyles?{background:" if(this.props.showFilter===!1&&this.props.showSettings===!1)return"" var n=null,r=null,i=null return this.props.useGriddleStyles&&(n=this.getFilterStyles(),r=this.getSettingsStyles(),i=this.getClearFixStyles()),o.createElement("div",{className:"top-section",style:i},o.createElement("div",{className:"griddle-filter", -style:n},e),o.createElement("div",{className:"griddle-settings-toggle",style:r},t))},getPagingSection:function Ie(e,t){if((this.props.showPager&&!this.isInfiniteScrollEnabled()&&!this.shouldUseCustomGridComponent())!==!1)return o.createElement("div",{ +style:n},e),o.createElement("div",{className:"griddle-settings-toggle",style:r},t))},getPagingSection:function Ae(e,t){if((this.props.showPager&&!this.isInfiniteScrollEnabled()&&!this.shouldUseCustomGridComponent())!==!1)return o.createElement("div",{ className:"griddle-footer"},this.props.useCustomPagerComponent?o.createElement(f,{customPagerComponentOptions:this.props.customPagerComponentOptions,next:this.nextPage,previous:this.previousPage,currentPage:e, maxPage:t,setPage:this.setPage,nextText:this.props.nextText,previousText:this.props.previousText,customPagerComponent:this.props.customPagerComponent}):o.createElement(l,{useGriddleStyles:this.props.useGriddleStyles, next:this.nextPage,previous:this.previousPage,nextClassName:this.props.nextClassName,nextIconComponent:this.props.nextIconComponent,previousClassName:this.props.previousClassName,previousIconComponent:this.props.previousIconComponent, -currentPage:e,maxPage:t,setPage:this.setPage,nextText:this.props.nextText,previousText:this.props.previousText}))},getColumnSelectorSection:function Ae(e,t){return this.state.showColumnChooser?o.createElement(a,{ +currentPage:e,maxPage:t,setPage:this.setPage,nextText:this.props.nextText,previousText:this.props.previousText}))},getColumnSelectorSection:function Ie(e,t){return this.state.showColumnChooser?o.createElement(a,{ columns:e,selectedColumns:t,setColumns:this.setColumns,settingsText:this.props.settingsText,settingsIconComponent:this.props.settingsIconComponent,maxRowsText:this.props.maxRowsText,setPageSize:this.setPageSize, showSetPageSize:!this.shouldUseCustomGridComponent(),resultsPerPage:this.state.resultsPerPage,enableToggleCustom:this.props.enableToggleCustom,toggleCustomComponent:this.toggleCustomComponent,useCustomComponent:this.shouldUseCustomRowComponent()||this.shouldUseCustomGridComponent(), useGriddleStyles:this.props.useGriddleStyles,enableCustomFormatText:this.props.enableCustomFormatText,columnMetadata:this.props.columnMetadata}):""},getCustomGridSection:function De(){return o.createElement(this.props.customGridComponent,r({ @@ -771,8 +771,8 @@ parentRowCollapsedClassName:this.props.parentRowCollapsedClassName,parentRowExpa bodyHeight:this.props.bodyHeight,paddingHeight:this.props.paddingHeight,rowHeight:this.props.rowHeight,infiniteScrollLoadTreshold:this.props.infiniteScrollLoadTreshold,externalLoadingComponent:this.props.externalLoadingComponent, externalIsLoading:this.props.externalIsLoading,hasMorePages:s,onRowClick:this.props.onRowClick}))},getContentSection:function Re(e,t,n,r,o,i){return this.shouldUseCustomGridComponent()&&null!==this.props.customGridComponent?this.getCustomGridSection():this.shouldUseCustomRowComponent()?this.getCustomRowSection(e,t,n,r,i):this.getStandardGridSection(e,t,n,r,o) -},getNoDataSection:function Le(){return null!=this.props.customNoDataComponent?o.createElement("div",{className:this.props.noDataClassName},o.createElement(this.props.customNoDataComponent,this.props.customNoDataComponentProps)):o.createElement(u,{ -noDataMessage:this.props.noDataMessage})},shouldShowNoDataSection:function Ue(e){return!this.props.allowEmptyGrid&&(this.props.useExternal===!1&&("undefined"==typeof e||0===e.length)||this.props.useExternal===!0&&this.props.externalIsLoading===!1&&0===e.length) +},getNoDataSection:function Ue(){return null!=this.props.customNoDataComponent?o.createElement("div",{className:this.props.noDataClassName},o.createElement(this.props.customNoDataComponent,this.props.customNoDataComponentProps)):o.createElement(u,{ +noDataMessage:this.props.noDataMessage})},shouldShowNoDataSection:function Le(e){return!this.props.allowEmptyGrid&&(this.props.useExternal===!1&&("undefined"==typeof e||0===e.length)||this.props.useExternal===!0&&this.props.externalIsLoading===!1&&0===e.length) },render:function je(){var e=this,t=this.getCurrentResults(),n=this.props.tableClassName+" table-header",r=this.getFilter(),i=this.getSettings(),s=this.getTopSection(r,i),l=[],a=this.columnSettings.getColumns(),u=this.getDataForRender(t,a,!0),p=this.columnSettings.getMetadataColumns() @@ -783,7 +783,7 @@ var d=this.getCurrentPage(),c=this.getCurrentMaxPage(),f=d+1-1&&e%1==0&&e<=r +I[S]=I[_]=I[w]=I[x]=I[P]=I[F]=I[T]=I[O]=I[A]=!0,I[l]=I[a]=I[C]=I[u]=I[E]=I[p]=I[d]=I[c]=I[f]=I[h]=I[m]=I[g]=I[y]=I[v]=I[b]=!1,e.exports=r},function(e,t){function n(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=r }var r=9007199254740991 e.exports=n},function(e,t){function n(e){return function(t){return e(t)}}e.exports=n},function(e,t,n){(function(e){var r=n(60),o="object"==typeof t&&t&&!t.nodeType&&t,i=o&&"object"==typeof e&&e&&!e.nodeType&&e,s=i&&i.exports===o,l=s&&r.process,a=function(){ @@ -1420,22 +1420,22 @@ var a=!1 t=r(t,function(t){return t=s(t,e),a||(a=t.length>1),t}),l(e,u(e),n),a&&(n=o(n,p|d|c)) for(var f=t.length;f--;)i(n,t[f]) return n}) -e.exports=f},function(e,t,n){function r(e,t,n,F,T,O){var I,k=t&_,N=t&w,L=t&x -if(n&&(I=T?n(e,F,T,O):n(e)),void 0!==I)return I +e.exports=f},function(e,t,n){function r(e,t,n,F,T,O){var A,k=t&_,N=t&w,U=t&x +if(n&&(A=T?n(e,F,T,O):n(e)),void 0!==A)return A if(!E(e))return e -var U=b(e) -if(U){if(I=g(e),!k)return p(e,I)}else{var j=m(e),M=j==A||j==D +var L=b(e) +if(L){if(A=g(e),!k)return p(e,A)}else{var j=m(e),M=j==I||j==D if(C(e))return u(e,k) -if(j==R||j==P||M&&!T){if(I=N||M?{}:v(e),!k)return N?c(e,a(I,e)):d(e,l(I,e))}else{if(!X[j])return T?e:{} -I=y(e,j,r,k)}}O||(O=new o) +if(j==R||j==P||M&&!T){if(A=N||M?{}:v(e),!k)return N?c(e,a(A,e)):d(e,l(A,e))}else{if(!X[j])return T?e:{} +A=y(e,j,r,k)}}O||(O=new o) var H=O.get(e) if(H)return H -O.set(e,I) -var B=L?N?h:f:N?keysIn:S,G=U?void 0:B(e) -return i(G||e,function(o,i){G&&(i=o,o=e[i]),s(I,i,r(o,t,n,i,e,O))}),I}var o=n(39),i=n(210),s=n(185),l=n(240),a=n(241),u=n(242),p=n(243),d=n(244),c=n(247),f=n(250),h=n(252),m=n(116),g=n(253),y=n(254),v=n(265),b=n(102),C=n(103),E=n(63),S=n(96),_=1,w=2,x=4,P="[object Arguments]",F="[object Array]",T="[object Boolean]",O="[object Date]",I="[object Error]",A="[object Function]",D="[object GeneratorFunction]",k="[object Map]",N="[object Number]",R="[object Object]",L="[object RegExp]",U="[object Set]",j="[object String]",M="[object Symbol]",H="[object WeakMap]",B="[object ArrayBuffer]",G="[object DataView]",z="[object Float32Array]",q="[object Float64Array]",Q="[object Int8Array]",V="[object Int16Array]",W="[object Int32Array]",K="[object Uint8Array]",$="[object Uint8ClampedArray]",Z="[object Uint16Array]",Y="[object Uint32Array]",X={} +O.set(e,A) +var B=U?N?h:f:N?keysIn:S,G=L?void 0:B(e) +return i(G||e,function(o,i){G&&(i=o,o=e[i]),s(A,i,r(o,t,n,i,e,O))}),A}var o=n(39),i=n(210),s=n(185),l=n(240),a=n(241),u=n(242),p=n(243),d=n(244),c=n(247),f=n(250),h=n(252),m=n(116),g=n(253),y=n(254),v=n(265),b=n(102),C=n(103),E=n(63),S=n(96),_=1,w=2,x=4,P="[object Arguments]",F="[object Array]",T="[object Boolean]",O="[object Date]",A="[object Error]",I="[object Function]",D="[object GeneratorFunction]",k="[object Map]",N="[object Number]",R="[object Object]",U="[object RegExp]",L="[object Set]",j="[object String]",M="[object Symbol]",H="[object WeakMap]",B="[object ArrayBuffer]",G="[object DataView]",z="[object Float32Array]",q="[object Float64Array]",Q="[object Int8Array]",V="[object Int16Array]",W="[object Int32Array]",K="[object Uint8Array]",$="[object Uint8ClampedArray]",Z="[object Uint16Array]",Y="[object Uint32Array]",X={} -X[P]=X[F]=X[B]=X[G]=X[T]=X[O]=X[z]=X[q]=X[Q]=X[V]=X[W]=X[k]=X[N]=X[R]=X[L]=X[U]=X[j]=X[M]=X[K]=X[$]=X[Z]=X[Y]=!0,X[I]=X[A]=X[H]=!1,e.exports=r},function(e,t,n){function r(e,t){return e&&o(t,i(t),e)}var o=n(187),i=n(96) +X[P]=X[F]=X[B]=X[G]=X[T]=X[O]=X[z]=X[q]=X[Q]=X[V]=X[W]=X[k]=X[N]=X[R]=X[U]=X[L]=X[j]=X[M]=X[K]=X[$]=X[Z]=X[Y]=!0,X[A]=X[I]=X[H]=!1,e.exports=r},function(e,t,n){function r(e,t){return e&&o(t,i(t),e)}var o=n(187),i=n(96) e.exports=r},function(e,t,n){function r(e,t){return e&&o(t,i(t),e)}var o=n(187),i=n(217) @@ -1456,13 +1456,13 @@ return i(e)?r:o(r,n(e))}var o=n(161),i=n(102) e.exports=r},function(e,t,n){function r(e){return o(e,s,i)}var o=n(251),i=n(248),s=n(217) e.exports=r},function(e,t){function n(e){var t=e.length,n=e.constructor(t) return t&&"string"==typeof e[0]&&o.call(e,"index")&&(n.index=e.index,n.input=e.input),n}var r=Object.prototype,o=r.hasOwnProperty -e.exports=n},function(e,t,n){function r(e,t,n,r){var I=e.constructor +e.exports=n},function(e,t,n){function r(e,t,n,r){var A=e.constructor switch(t){case b:return o(e) -case d:case c:return new I((+e)) +case d:case c:return new A((+e)) case C:return i(e,r) case E:case S:case _:case w:case x:case P:case F:case T:case O:return p(e,r) case f:return s(e,r,n) -case h:case y:return new I(e) +case h:case y:return new A(e) case m:return l(e) case g:return a(e,r,n) case v:return u(e)}}var o=n(255),i=n(256),s=n(257),l=n(260),a=n(261),u=n(263),p=n(264),d="[object Boolean]",c="[object Date]",f="[object Map]",h="[object Number]",m="[object RegExp]",g="[object Set]",y="[object String]",v="[object Symbol]",b="[object ArrayBuffer]",C="[object DataView]",E="[object Float32Array]",S="[object Float64Array]",_="[object Int8Array]",w="[object Int16Array]",x="[object Int32Array]",P="[object Uint8Array]",F="[object Uint8ClampedArray]",T="[object Uint16Array]",O="[object Uint32Array]" @@ -1551,9 +1551,9 @@ SUCCEED_UPLOAD:"SUCCEED_UPLOAD",UPDATE_QUEUED_FILE:"UPDATE_QUEUED_FILE"}},functi function r(e){return e&&e.__esModule?e:{"default":e}}var o=n(4),i=n(278),s=r(i),l=n(279),a=r(l),u=n(280),p=r(u),d=n(281),c=r(d),f=n(283),h=r(f),m=n(285),g=r(m),y=n(287),v=r(y),b=n(289),C=r(b),E=n(290),S=r(E),_=n(295),w=r(_) -document.addEventListener("DOMContentLoaded",function(){C["default"].register("UploadField",S["default"]) +document.addEventListener("DOMContentLoaded",function(){C["default"].register("UploadField",S["default"]),C["default"].register("HistoryList",w["default"]) var e=s["default"].getSection("SilverStripe\\AssetAdmin\\Controller\\AssetAdmin") -C["default"].register("HistoryList",w["default"]),a["default"].add({path:e.url,component:g["default"],indexRoute:{onEnter:function t(n,r){var o=[e.url,"show",0].join("/") +a["default"].add({path:e.url,component:g["default"],indexRoute:{onEnter:function t(n,r){var o=[e.url,"show",0].join("/") r(o)}},childRoutes:[{path:"show/:folderId/edit/:fileId",component:g["default"]},{path:"show/:folderId",component:g["default"]}]}),p["default"].add("assetAdmin",(0,o.combineReducers)({gallery:c["default"], queuedFiles:h["default"],uploadField:v["default"]}))})},function(e,t){e.exports=Config},function(e,t){e.exports=ReactRouteRegister},function(e,t){e.exports=ReducerRegister},function(e,t,n){"use strict" @@ -1663,10 +1663,10 @@ e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,wri e.assetAdmin&&e.assetAdmin.uploadField&&e.assetAdmin.uploadField.fields&&e.assetAdmin.uploadField.fields[n]&&(r=e.assetAdmin.uploadField.fields[n].files||[]) var o=e.config.SecurityID -return{files:r,securityId:o}}function u(e){return{actions:{uploadField:(0,y.bindActionCreators)(k,e)}}}Object.defineProperty(t,"__esModule",{value:!0}),t.UploadField=void 0 +return{files:r,securityId:o}}function u(e){return{actions:{uploadField:(0,y.bindActionCreators)(k,e)}}}Object.defineProperty(t,"__esModule",{value:!0}),t.ConnectedUploadField=t.UploadField=void 0 var p=Object.assign||function(e){for(var t=1;t { Injector.register('UploadField', UploadField); + Injector.register('HistoryList', HistoryList); const sectionConfig = Config.getSection('SilverStripe\\AssetAdmin\\Controller\\AssetAdmin'); - injector.register('HistoryList', HistoryList); reactRouteRegister.add({ path: sectionConfig.url, diff --git a/client/src/bundles/bundle.js b/client/src/bundles/bundle.js index 465d8e94e..4a5029953 100644 --- a/client/src/bundles/bundle.js +++ b/client/src/bundles/bundle.js @@ -1,5 +1,6 @@ require('expose?InsertMediaModal!containers/InsertMediaModal/InsertMediaModal'); require('boot'); +require('entwine/UploadField/UploadFieldEntwine.js'); require('styles/bundle.scss'); diff --git a/client/src/components/UploadField/UploadField.js b/client/src/components/UploadField/UploadField.js index 6c2ec7ceb..05bfa49b5 100644 --- a/client/src/components/UploadField/UploadField.js +++ b/client/src/components/UploadField/UploadField.js @@ -231,15 +231,15 @@ class UploadField extends SilverStripeComponent { >
- + {' '} {i18n._t('AssetAdminUploadField.OR', 'or')} {' '} - + ); @@ -326,6 +326,8 @@ function mapDispatchToProps(dispatch) { }; } -export { UploadField }; +const ConnectedUploadField = connect(mapStateToProps, mapDispatchToProps)(UploadField); -export default fieldHolder(connect(mapStateToProps, mapDispatchToProps)(UploadField)); +export { UploadField, ConnectedUploadField }; + +export default fieldHolder(ConnectedUploadField); diff --git a/client/src/components/UploadField/UploadField.scss b/client/src/components/UploadField/UploadField.scss index 19700051d..6e5afc238 100644 --- a/client/src/components/UploadField/UploadField.scss +++ b/client/src/components/UploadField/UploadField.scss @@ -40,10 +40,26 @@ cursor: pointer; } +.uploadfield__upload-button, +.uploadfield__add-button { + border: 0; + margin: 0; + padding: 0; + background: none; + text-decoration: $link-decoration; + color: $link-color; + + &:hover { + color: $link-hover-color; + text-decoration: $link-hover-decoration; + } +} + .uploadfield__droptext { position: absolute; top: 20px; - left: 40%; + left: 50%; + transform: translateX(-50%); display: inline-block; text-align: center; diff --git a/client/src/containers/Gallery/Gallery.js b/client/src/containers/Gallery/Gallery.js index bce4379ad..7682c74cf 100644 --- a/client/src/containers/Gallery/Gallery.js +++ b/client/src/containers/Gallery/Gallery.js @@ -272,8 +272,8 @@ class Gallery extends Component { this.props.actions.queuedFiles.removeQueuedFile(fileXhr._queuedId); this.props.actions.gallery.addFiles(json, this.props.count + 1); - // redirect to open the last uploaded file for 'insert modal' type only - if (this.props.type === 'insert' + // redirect to open the last uploaded file for 'insert/select modal' type only + if (this.props.type !== 'admin' && !this.props.fileId && this.props.queuedFiles.items.length === 0 ) { @@ -736,7 +736,7 @@ Gallery.defaultProps = Object.assign({}, sharedDefaultProps, { }); Gallery.propTypes = Object.assign({}, sharedPropTypes, { - type: PropTypes.oneOf(['insert', 'admin']), + type: PropTypes.oneOf(['insert', 'select', 'admin']), view: PropTypes.oneOf(['tile', 'table']), dialog: PropTypes.bool, fileId: PropTypes.number, diff --git a/client/src/entwine/UploadField/UploadFieldEntwine.js b/client/src/entwine/UploadField/UploadFieldEntwine.js new file mode 100644 index 000000000..16f1a4f2a --- /dev/null +++ b/client/src/entwine/UploadField/UploadFieldEntwine.js @@ -0,0 +1,50 @@ +import jQuery from 'jQuery'; +import React from 'react'; +import ReactDOM from 'react-dom'; +import { Provider } from 'react-redux'; +import { schemaMerge } from 'lib/schemaFieldValues'; +import { ConnectedUploadField } from 'components/UploadField/UploadField'; + +/** + * Shiv for inserting react UploadField into entwine forms + */ +jQuery.entwine('ss', ($) => { + /** + * See boot/index.js for `.react-boot` bootstrap + */ + $('.js-react-boot input.entwine-uploadfield').entwine({ + + onunmatch() { + this._super(); + // solves errors given by ReactDOM "no matched root found" error. + ReactDOM.unmountComponentAtNode(this[0]); + }, + + onmatch() { + this._super(); + this.refresh(); + }, + + refresh() { + const store = window.ss.store; + const props = this.getAttributes(); + ReactDOM.render( + + + , + this.parent()[0] + ); + }, + + /** + * Find the selected node and get attributes associated to attach the data to the form + * + * @returns {Object} + */ + getAttributes() { + const state = $(this).data('state'); + const schema = $(this).data('schema'); + return schemaMerge(schema, state); + }, + }); +}); diff --git a/code/Forms/UploadField.php b/code/Forms/UploadField.php index 879360f5c..e7cedee0f 100644 --- a/code/Forms/UploadField.php +++ b/code/Forms/UploadField.php @@ -145,4 +145,27 @@ public function setIsMultiUpload($multi) $this->multiUpload = $multi; return $this; } + + public function getAttributes() + { + $attributes = array( + 'class' => $this->extraClass(), + 'type' => 'file', + 'multiple' => $this->getIsMultiUpload(), + 'id' => $this->ID(), + 'data-schema' => json_encode($this->getSchemaData()), + 'data-state' => json_encode($this->getSchemaState()), + ); + + $attributes = array_merge($attributes, $this->attributes); + + $this->extend('updateAttributes', $attributes); + + return $attributes; + } + + public function Type() + { + return 'entwine-uploadfield uploadfield'; + } } diff --git a/templates/SilverStripe/AssetAdmin/Forms/UploadField.ss b/templates/SilverStripe/AssetAdmin/Forms/UploadField.ss new file mode 100644 index 000000000..c55f77550 --- /dev/null +++ b/templates/SilverStripe/AssetAdmin/Forms/UploadField.ss @@ -0,0 +1 @@ + /> diff --git a/tests/php/FileFormBuilderTest.php b/tests/php/Forms/FileFormBuilderTest.php similarity index 97% rename from tests/php/FileFormBuilderTest.php rename to tests/php/Forms/FileFormBuilderTest.php index 9150d126f..89c1e1bc1 100644 --- a/tests/php/FileFormBuilderTest.php +++ b/tests/php/Forms/FileFormBuilderTest.php @@ -1,6 +1,6 @@ setFromLocalFile(__DIR__.'/fixtures/testimage.png', 'files/testimage.png'); } + public function tearDown() + { + TestAssetStore::reset(); + parent::tearDown(); + } + public function testEditFileForm() { $this->logInWithPermission('ADMIN'); diff --git a/tests/php/FileFormBuilderTest.yml b/tests/php/Forms/FileFormBuilderTest.yml similarity index 100% rename from tests/php/FileFormBuilderTest.yml rename to tests/php/Forms/FileFormBuilderTest.yml diff --git a/tests/php/Forms/UploadFieldTest.php b/tests/php/Forms/UploadFieldTest.php new file mode 100644 index 000000000..29026db73 --- /dev/null +++ b/tests/php/Forms/UploadFieldTest.php @@ -0,0 +1,107 @@ +objFromFixture(File::class, 'file1'); + $testfile->setFromLocalFile(__DIR__ . '/fixtures/testfile.txt', 'files/testfile.txt'); + $testfile->write(); + + /** @var Image $testimage */ + $testimage = $this->objFromFixture(Image::class, 'image1'); + $testimage->setFromLocalFile(__DIR__ . '/fixtures/testimage.png', 'files/testimage.png'); + } + + public function tearDown() + { + TestAssetStore::reset(); + parent::tearDown(); + } + + public function testGetAttributes() + { + $field = UploadField::create('MyField'); + $field->addExtraClass('myfield'); + $field->setIsMultiUpload(false); + $field->setFolderName('/'); + /** @var Image $image */ + $image = $this->objFromFixture(Image::class, 'image1'); + $field->setItems(new ArrayList([$image])); + Form::create(new Controller(), 'MyForm', FieldList::create($field), FieldList::create()); + $admin = new AssetAdmin(); + + $attributes = $field->getAttributes(); + $schema = [ + 'name' => 'MyField', + 'id' => 'Form_MyForm_MyField', + 'type' => 'Custom', + 'component' => 'UploadField', + 'holderId' => 'Form_MyForm_MyField_Holder', + 'title' => 'My Field', + 'source' => null, + 'extraClass' => 'entwine-uploadfield uploadfield myfield', + 'description' => null, + 'rightTitle' => null, + 'leftTitle' => null, + 'readOnly' => false, + 'disabled' => false, + 'customValidationMessage' => '', + 'validation' => [], + 'attributes' => [], + 'data' => [ + 'createFileEndpoint' => [ + 'url' => 'admin/assets/api/createFile', + 'method' => 'post', + 'payloadFormat' => 'urlencoded', + ], + 'multi' => false, + 'parentid' => 0, + ], + ]; + $state = [ + 'name' => 'MyField', + 'id' => 'Form_MyForm_MyField', + 'value' => [ 'Files' => [$image->ID] ], + 'message' => null, + 'data' => [ + 'files' => [ $admin->getObjectFromData($image) ], + ], + ]; + $this->assertArraySubset( + [ + 'class' => 'entwine-uploadfield uploadfield myfield', + 'type' => 'file', + 'multiple' => false, + 'id' => 'Form_MyForm_MyField' + ], + $attributes + ); + + // Check schema / state are encoded in this field + $this->assertEquals($schema, json_decode($attributes['data-schema'], true)); + $this->assertEquals($state, json_decode($attributes['data-state'], true)); + } +} diff --git a/tests/php/fixtures/testfile.txt b/tests/php/Forms/fixtures/testfile.txt similarity index 100% rename from tests/php/fixtures/testfile.txt rename to tests/php/Forms/fixtures/testfile.txt diff --git a/tests/php/fixtures/testimage.png b/tests/php/Forms/fixtures/testimage.png similarity index 100% rename from tests/php/fixtures/testimage.png rename to tests/php/Forms/fixtures/testimage.png diff --git a/webpack.config.js b/webpack.config.js index d897611e5..6c3cf1bf5 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -40,6 +40,7 @@ module.exports = { 'state/schema/SchemaActions': 'SchemaActions', 'components/FieldHolder/FieldHolder': 'FieldHolder', 'lib/DataFormat': 'DataFormat', + 'lib/schemaFieldValues': 'schemaFieldValues', 'components/FormBuilderModal/FormBuilderModal': 'FormBuilderModal', 'components/FormBuilder/FormBuilder': 'FormBuilder', 'components/Toolbar/Toolbar': 'Toolbar',