ItSpiderman has uploaded a new change for review. https://gerrit.wikimedia.org/r/311676
Change subject: Added FileRepo Grid - extended filelist, added page_link, file_link fields to BSApiFileBackendStore ...................................................................... Added FileRepo Grid - extended filelist, added page_link, file_link fields to BSApiFileBackendStore Change-Id: I36bfbc5897562a035f5c2dac4c0d4340760b5722 --- M extension.json A i18n/filerepo/en.json A i18n/filerepo/qqq.json A includes/JsonLicenses.php M includes/api/BSApiFileBackendStore.php A includes/api/BSApiUploadLicenseStore.php M resources/Resources.php A resources/bluespice.extjs/BS/grid/FileRepo.js M resources/bluespice.extjs/BS/model/File.js A resources/bluespice.extjs/BS/panel/Upload.js A resources/bluespice.extjs/BS/panel/UploadPanel.js 11 files changed, 1,087 insertions(+), 6 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/BlueSpiceFoundation refs/changes/76/311676/1 diff --git a/extension.json b/extension.json old mode 100644 new mode 100755 index e0a8151..9b698f6 --- a/extension.json +++ b/extension.json @@ -1,6 +1,6 @@ { "name": "BlueSpice", - "version": "2.27.0-beta", + "version": "2.27.0", "author": [ "[http://www.hallowelt.com Hallo Welt! GmbH]" ], @@ -24,7 +24,8 @@ "bs-wikipage-store": "BSApiWikiPageStore", "bs-wikisubpage-treestore": "BSApiWikiSubPageTreeStore", "bs-titlequery-store": "BSApiTitleQueryStore", - "bs-ping-tasks": "BSApiPingTasks" + "bs-ping-tasks": "BSApiPingTasks", + "bs-upload-license-store": "BSApiUploadLicenseStore" }, "MessagesDirs": { "BlueSpice": [ @@ -53,6 +54,12 @@ ], "BlueSpice.API": [ "i18n/api" + ], + "BlueSpice.Upload": [ + "i18n/upload" + ], + "BlueSpice.FileRepo": [ + "i18n/filerepo" ] }, "ExtensionMessagesFiles": { @@ -80,8 +87,8 @@ "config": { "BlueSpiceExtInfo": { "name": "BlueSpice", - "version": "2.27.0-beta", - "status": "beta", + "version": "2.27.0", + "status": "alpha", "package": "BlueSpice Free", "url": "http://bluespice.com", "desc": "Makes MediaWiki enterprise ready.", @@ -153,6 +160,8 @@ "BSApiAdminUserStore": "includes/api/BSApiAdminUserStore.php", "BSApiGroupStore": "includes/api/BSApiGroupStore.php", "BSApiInterwikiStore": "includes/api/BSApiInterwikiStore.php", + "JsonLicenses": "includes/JsonLicenses.php", + "BSApiUploadLicenseStore": "includes/api/BSApiUploadLicenseStore.php", "BSApiWikiPageTasks": "includes/api/BSApiWikiPageTasks.php", "BSApiWikiPageStore": "includes/api/BSApiWikiPageStore.php", "BSApiWikiSubPageTreeStore": "includes/api/BSApiWikiSubPageTreeStore.php", diff --git a/i18n/filerepo/en.json b/i18n/filerepo/en.json new file mode 100644 index 0000000..22b8b6e --- /dev/null +++ b/i18n/filerepo/en.json @@ -0,0 +1,38 @@ +{ + "@metadata": { + "authors": [ + "Dejan Savuljesku" + ] + }, + "bs-filerepo-desc": "Extended filelist description - TODO", + "bs-filerepo-headerfilename": "Filename", + "bs-filerepo-headerfilesize": "File size", + "bs-filerepo-labelupload": "Upload", + "bs-filerepo-labelfilter": "Filter", + "bs-filerepo-uploaddialogtitle": "Upload file", + "bs-filerepo-headerpageid": "Page ID", + "bs-filerepo-headerpagetitle": "Page title", + "bs-filerepo-headerpagelatest": "Page latest change", + "bs-filerepo-headerpagenamespace": "Page namespace", + "bs-filerepo-headerpageisredirect": "Is page redirect?", + "bs-filerepo-headerpageisnew": "Is page new?", + "bs-filerepo-headerpagetouched": "Page touched", + "bs-filerepo-headerpagelink": "Page link", + "bs-filerepo-headerpagecategories": "Page categories", + "bs-filerepo-headerfileurl": "File URL", + "bs-filerepo-headerfilebits": "File bits", + "bs-filerepo-headerfileuser": "User ID", + "bs-filerepo-headerfilewidth": "File width", + "bs-filerepo-headerfileheight": "File height", + "bs-filerepo-headerfilemimetype": "File mimetype", + "bs-filerepo-headerfileusertext": "User", + "bs-filerepo-headerfileextension": "File extension", + "bs-filerepo-headerfiletimestamp": "Uploaded", + "bs-filerepo-headerfilemediatype": "File media type", + "bs-filerepo-headerfiledescription": "Description", + "bs-filerepo-headerfiledisplaytext": "Display text", + "bs-filerepo-headerfilethumbnail": "Preview", + "bs-filerepo-yes": "Yes", + "bs-filerepo-no": "No", + "bs-filerepo-headerfilelink": "File link" +} \ No newline at end of file diff --git a/i18n/filerepo/qqq.json b/i18n/filerepo/qqq.json new file mode 100644 index 0000000..22b8b6e --- /dev/null +++ b/i18n/filerepo/qqq.json @@ -0,0 +1,38 @@ +{ + "@metadata": { + "authors": [ + "Dejan Savuljesku" + ] + }, + "bs-filerepo-desc": "Extended filelist description - TODO", + "bs-filerepo-headerfilename": "Filename", + "bs-filerepo-headerfilesize": "File size", + "bs-filerepo-labelupload": "Upload", + "bs-filerepo-labelfilter": "Filter", + "bs-filerepo-uploaddialogtitle": "Upload file", + "bs-filerepo-headerpageid": "Page ID", + "bs-filerepo-headerpagetitle": "Page title", + "bs-filerepo-headerpagelatest": "Page latest change", + "bs-filerepo-headerpagenamespace": "Page namespace", + "bs-filerepo-headerpageisredirect": "Is page redirect?", + "bs-filerepo-headerpageisnew": "Is page new?", + "bs-filerepo-headerpagetouched": "Page touched", + "bs-filerepo-headerpagelink": "Page link", + "bs-filerepo-headerpagecategories": "Page categories", + "bs-filerepo-headerfileurl": "File URL", + "bs-filerepo-headerfilebits": "File bits", + "bs-filerepo-headerfileuser": "User ID", + "bs-filerepo-headerfilewidth": "File width", + "bs-filerepo-headerfileheight": "File height", + "bs-filerepo-headerfilemimetype": "File mimetype", + "bs-filerepo-headerfileusertext": "User", + "bs-filerepo-headerfileextension": "File extension", + "bs-filerepo-headerfiletimestamp": "Uploaded", + "bs-filerepo-headerfilemediatype": "File media type", + "bs-filerepo-headerfiledescription": "Description", + "bs-filerepo-headerfiledisplaytext": "Display text", + "bs-filerepo-headerfilethumbnail": "Preview", + "bs-filerepo-yes": "Yes", + "bs-filerepo-no": "No", + "bs-filerepo-headerfilelink": "File link" +} \ No newline at end of file diff --git a/includes/JsonLicenses.php b/includes/JsonLicenses.php new file mode 100755 index 0000000..197e37e --- /dev/null +++ b/includes/JsonLicenses.php @@ -0,0 +1,44 @@ +<?php + +/** + * JsonLicenses + * + * Extends the mediawiki licenses class to put the available licenses out in a json format for ExtJS combobox. + * + * @author Sebastian Ulbricht + */ +class JsonLicenses extends Licenses { + + protected $json; + + public function __construct() { + parent::__construct( array( 'fieldname' => 'JsonLicenses' ) ); + } + + public function getJsonOutput() { + $this->json[] = $this->outputJsonOption( wfMessage( 'nolicense' )->text(), '' ); + $this->makeJson( $this->getLicenses() ); + return json_encode(array('items' => $this->json)); + } + + protected function outputJsonOption( $text, $value, $depth = 0 ) { + return array( + 'text' => $text, + 'value' => "\n\n==". wfMessage( 'license-header' )->inContentLanguage()->text()."==\n{{".$value."}}", + 'indent'=> $depth + ); + } + + protected function makeJson( $tagset, $depth = 0 ) { + foreach ( $tagset as $key => $val ) { + if ( is_array( $val ) ) { + $this->json[] = $this->outputJsonOption( $key, '', $depth ); + $this->makeJson( $val, $depth + 1 ); + } + else { + $this->json[] = $this->outputJsonOption( $val->text, $val->template, $depth ); + } + } + } + +} \ No newline at end of file diff --git a/includes/api/BSApiFileBackendStore.php b/includes/api/BSApiFileBackendStore.php index 58cc951..b2b5cd9 100644 --- a/includes/api/BSApiFileBackendStore.php +++ b/includes/api/BSApiFileBackendStore.php @@ -69,9 +69,17 @@ $sThumb = html_entity_decode( SecureFileStore::secureStuff( $sThumb, true ) ); $sUrl = html_entity_decode( SecureFileStore::secureStuff( $sUrl, true ) ); } + $oFileLink = Html::element('a', array( + 'href' => $sUrl, + 'title' => $oImg->getName(), + 'data-bs-title' => $oImg->getName(), + ), $oImg->getName()); + + $oFileName = Title::makeTitle( NS_FILE , $oImg->getName()); $aReturn[ $oRow->page_id ] = (object) array( 'file_url' => $sUrl, + 'file_link' => $oFileLink, 'file_name' => $oImg->getName(), 'file_size' => $oImg->getSize(), 'file_bits' => $oImg->getBitDepth(), @@ -86,6 +94,7 @@ 'file_description' => $oImg->getDescription(), 'file_display_text' => $oImg->getName(), 'file_thumbnail_url' => $sThumb, + 'page_link' => Linker::link($oFileName, $oImg->getName()), 'page_id' => $oTitle->getArticleID(), 'page_title' => $oTitle->getText(), 'page_latest' => $oTitle->getLatestRevID(), diff --git a/includes/api/BSApiUploadLicenseStore.php b/includes/api/BSApiUploadLicenseStore.php new file mode 100755 index 0000000..6e78922 --- /dev/null +++ b/includes/api/BSApiUploadLicenseStore.php @@ -0,0 +1,47 @@ +<?php +/** + * This class serves as a backend for the license store of the InsertFile + * extension + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * This file is part of BlueSpice for MediaWiki + * For further information visit http://www.blue-spice.org + * + * @author Patric Wirth <wi...@hallowelt.com> + * @package Bluespice_Extensions + * @copyright Copyright (C) 2016 Hallo Welt! GmbH, All rights reserved. + * @license http://www.gnu.org/copyleft/gpl.html GNU Public License v2 or later + * + * Example request parameters of an ExtJS store + */ +class BSApiUploadLicenseStore extends BSApiExtJSStoreBase { + /** + * @param string $sQuery Potential query provided by ExtJS component. + * This is some kind of preliminary filtering. Subclass has to decide if + * and how to process it + * @return array - Full list of of data objects. Filters, paging, sorting + * will be done by the base class + */ + protected function makeData( $sQuery = '' ) { + //There is an api action "licences" in mw 2.24, but it is described as + //"Get media license dropdown HTML." + $oLicenses = new JsonLicenses(); + $aData = FormatJson::decode( + $oLicenses->getJsonOutput() + ); + return $aData->items; + } +} \ No newline at end of file diff --git a/resources/Resources.php b/resources/Resources.php old mode 100644 new mode 100755 index 97f7fd4..da25508 --- a/resources/Resources.php +++ b/resources/Resources.php @@ -41,10 +41,56 @@ 'bs-two-units-ago', 'bs-one-unit-ago', 'bs-now', - 'blanknamespace', //MediaWiki + 'blanknamespace', + 'bs-upload-uploadfilefieldlabel', + 'bs-upload-uploadbuttontext', + 'bs-upload-uploadfileemptytext', + 'bs-upload-uploaddestfilelabel', + 'bs-upload-descfilelabel', + 'bs-upload-license', + 'bs-upload-uploadwatchthislabel', + 'bs-upload-uploadignorewarningslabel', + 'bs-upload-categories', + 'bs-upload-upload-waitmessage', + 'bs-upload-error', + 'bs-upload-error-long', + 'bs-upload-filetypenotsupported', + 'bs-filerepo-headerfilename', + 'bs-filerepo-headerfilesize', + 'bs-filerepo-labelfilter', + 'bs-filerepo-labelupload', + 'bs-filerepo-uploaddialogtitle', + 'bs-filerepo-headerpageid', + 'bs-filerepo-headerpagetitle', + 'bs-filerepo-headerpagelatest', + 'bs-filerepo-headerpagenamespace', + 'bs-filerepo-headerpageisredirect', + 'bs-filerepo-headerpageisnew', + 'bs-filerepo-headerpagetouched', + 'bs-filerepo-headerpagelink', + 'bs-filerepo-headerpagecategories', + 'bs-filerepo-headerfileurl', + 'bs-filerepo-headerfilebits', + 'bs-filerepo-headerfileuser', + 'bs-filerepo-headerfilewidth', + 'bs-filerepo-headerfileheight', + 'bs-filerepo-headerfilemimetype', + 'bs-filerepo-headerfileusertext', + 'bs-filerepo-headerfileextension', + 'bs-filerepo-headerfiletimestamp', + 'bs-filerepo-headerfilemediatype', + 'bs-filerepo-headerfiledescription', + 'bs-filerepo-headerfiledisplaytext', + 'bs-filerepo-headerfilethumbnail', + 'bs-filerepo-yes', + 'bs-filerepo-no', + 'bs-filerepo-headerfilelink' + ) ) + $aResourceModuleTemplate; + + $wgResourceModules['ext.bluespice.styles'] = array( 'styles' => array( 'bluespice/bluespice.css', diff --git a/resources/bluespice.extjs/BS/grid/FileRepo.js b/resources/bluespice.extjs/BS/grid/FileRepo.js new file mode 100755 index 0000000..5b983a9 --- /dev/null +++ b/resources/bluespice.extjs/BS/grid/FileRepo.js @@ -0,0 +1,357 @@ +Ext.define( 'BS.grid.FileRepo', { + extend: 'Ext.grid.Panel', + requires: ['BS.store.BSApi', 'Ext.ux.form.SearchField', 'BS.model.File', + 'Ext.Button', 'BS.panel.Upload'], + id: 'bs-filerepo-panel', + features: [], + initComponent: function() { + var pageSize = 10; + + this.store = new BS.store.BSApi({ + apiAction: 'bs-filebackend-store', + model: 'BS.model.File', + proxy:{ + extraParams: { + limit: pageSize + } + }, + pageSize: pageSize + }); + + + this.colFileThumb = Ext.create( 'Ext.grid.column.Column', { + id: 'filethumb', + sortable: false, + filterable: false, + dataIndex: 'file_thumbnail_url', + renderer: this.renderThumb, + width: 64, + header: mw.message('bs-filerepo-headerfilethumbnail').plain() + }); + + this.colPageId = Ext.create( 'Ext.grid.column.Column', { + id: 'pageid', + sortable: true, + filterable: true, + dataIndex: 'page_id', + hidden: true, + header: mw.message('bs-filerepo-headerpageid').plain() + }); + + this.colPageTitle = Ext.create( 'Ext.grid.column.Column', { + id: 'pagetitle', + sortable: true, + filterable: true, + dataIndex: 'page_title', + hidden: true, + header: mw.message('bs-filerepo-headerpagetitle').plain() + }); + + this.colPageLatest = Ext.create( 'Ext.grid.column.Column', { + id: 'pagelatest', + sortable: true, + filterable: true, + dataIndex: 'page_latest', + hidden: true, + header: mw.message('bs-filerepo-headerpagelatest').plain() + }); + + this.colPageNamespace = Ext.create( 'Ext.grid.column.Column', { + id: 'pagenamespace', + sortable: true, + filterable: true, + dataIndex: 'page_namespace', + hidden: true, + header: mw.message('bs-filerepo-headerpagenamespace').plain() + }); + + this.colPageIsRedirect = Ext.create( 'Ext.grid.column.Column', { + id: 'pageidredirect', + sortable: true, + filterable: true, + dataIndex: 'page_is_redirect', + hidden: true, + renderer: this.renderBool, + header: mw.message('bs-filerepo-headerpageisredirect').plain() + }); + + this.colPageIsNew = Ext.create( 'Ext.grid.column.Column', { + id: 'pageisnew', + sortable: true, + filterable: true, + dataIndex: 'page_is_new', + hidden: true, + renderer: this.renderBool, + header: mw.message('bs-filerepo-headerpageisnew').plain() + }); + + this.colPageTouched = Ext.create( 'Ext.grid.column.Column', { + id: 'pagetouched', + sortable: true, + filterable: true, + dataIndex: 'page_touched', + hidden: true, + header: mw.message('bs-filerepo-headerpagetouched').plain() + }); + + this.colPageLink = Ext.create( 'Ext.grid.column.Column', { + id: 'pagelink', + sortable: true, + filterable: true, + dataIndex: 'page_link', + flex:1, + header: mw.message('bs-filerepo-headerfilename').plain() + }); + + this.colFileLink = Ext.create( 'Ext.grid.column.Column', { + id: 'filelink', + sortable: true, + filterable: true, + dataIndex: 'file_link', + hidden: true, + header: mw.message('bs-filerepo-headerfilelink').plain() + }); + + this.colPageCategories = Ext.create( 'Ext.grid.column.Column', { + id: 'pagecategories', + sortable: true, + filterable: true, + dataIndex: 'page_categories', + hidden: true, + header: mw.message('bs-filerepo-headerpagecategories').plain() + }); + + this.colFileUrl = Ext.create( 'Ext.grid.column.Column', { + id: 'fileurl', + sortable: true, + filterable: true, + dataIndex: 'file_url', + hidden: true, + header: mw.message('bs-filerepo-headerfileurl').plain() + }); + + this.colFileBits = Ext.create( 'Ext.grid.column.Column', { + id: 'filebits', + sortable: true, + filterable: true, + dataIndex: 'file_bits', + hidden: true, + header: mw.message('bs-filerepo-headerfilebits').plain() + }); + + this.colFileUser = Ext.create( 'Ext.grid.column.Column', { + id: 'fileuser', + sortable: true, + filterable: true, + dataIndex: 'file_user', + header: mw.message('bs-filerepo-headerfileuser').plain(), + hidden: true + }); + + this.colFileWidth = Ext.create( 'Ext.grid.column.Column', { + id: 'filewidth', + sortable: true, + filterable: true, + dataIndex: 'file_width', + hidden: true, + header: mw.message('bs-filerepo-headerfilewidth').plain() + }); + + this.colFileHeight = Ext.create( 'Ext.grid.column.Column', { + id: 'fileheight', + sortable: true, + filterable: true, + dataIndex: 'file_height', + hidden: true, + header: mw.message('bs-filerepo-headerfileheight').plain() + }); + + this.colFileMimetype = Ext.create( 'Ext.grid.column.Column', { + id: 'filemimetype', + sortable: true, + filterable: true, + dataIndex: 'file_mimetype', + hidden: true, + header: mw.message('bs-filerepo-headerfilemimetype').plain() + }); + + this.colFileUserText = Ext.create( 'Ext.grid.column.Column', { + id: 'fileusertext', + sortable: true, + filterable: true, + dataIndex: 'file_user_text', + header: mw.message('bs-filerepo-headerfileusertext').plain() + }); + + this.colFileExtension = Ext.create( 'Ext.grid.column.Column', { + id: 'fileextension', + sortable: true, + filterable: true, + dataIndex: 'file_extension', + hidden: true, + header: mw.message('bs-filerepo-headerfileextension').plain() + }); + + this.colFileTimestamp = Ext.create( 'Ext.grid.column.Date', { + id: 'filetimestamp', + sortable: true, + filterable: true, + dateFormat: 'Y-m-d H:i:s', + dataIndex: 'file_timestamp', + width:100, + header: mw.message('bs-filerepo-headerfiletimestamp').plain() + }); + + this.colFileMediaType = Ext.create( 'Ext.grid.column.Column', { + id: 'filemediatype', + sortable: true, + filterable: true, + dataIndex: 'file_mediatype', + hidden: true, + header: mw.message('bs-filerepo-headerfilemediatype').plain() + }); + + this.colFileDescription = Ext.create( 'Ext.grid.column.Column', { + id: 'filedescription', + sortable: true, + filterable: true, + dataIndex: 'file_description', + hidden: true, + header: mw.message('bs-filerepo-headerfiledescription').plain() + }); + + this.colFileDisplayText = Ext.create( 'Ext.grid.column.Column', { + id: 'filedisplaytext', + sortable: true, + filterable: true, + dataIndex: 'file_display_text', + hidden: true, + header: mw.message('bs-filerepo-headerfiledisplaytext').plain() + }); + + this.colFilename = Ext.create( 'Ext.grid.column.Column', { + id: 'filename', + header: mw.message('bs-filerepo-headerfilename').plain(), + sortable: true, + dataIndex: 'page_link', + flex:1, + hidden: true, + filterable: true + }); + + this.colFilesize = Ext.create( 'Ext.grid.column.Column', { + id: 'filesize', + header: mw.message('bs-filerepo-headerfilesize').plain(), + sortable: true, + dataIndex: 'file_size', + renderer: this.renderFilesize, + width: 100, + filterable: true + }); + + this.columns = [ + this.colFileThumb, + this.colPageLink, + this.colFilename, + this.colFilesize, + this.colPageId, + this.colPageTitle, + this.colPageLatest, + this.colPageNamespace, + this.colPageIsRedirect, + this.colPageIsNew, + this.colPageTouched, + this.colPageCategories, + this.colFileUrl, + this.colFileBits, + this.colFileUser, + this.colFileWidth, + this.colFileHeight, + this.colFileMimetype, + this.colFileUserText, + this.colFileExtension, + this.colFileTimestamp, + this.colFileMediaType, + this.colFileDescription, + this.colFileDisplayText, + this.colFileLink + ]; + + this.bbar = new Ext.PagingToolbar({ + store: this.store, + displayInfo: true + }); + + this.sfFilter = Ext.create( 'Ext.ux.form.SearchField', { + fieldLabel: mw.message('bs-filerepo-labelfilter').plain(), + width:500, + labelWidth:40, + store: this.store, + listeners: { + change: function ( field, newValue, oldValue, eOpts ) { + field.onTrigger2Click(); + return true; + } + } + }); + + this.btnUpload = Ext.create( 'Ext.Button', { + text: mw.message('bs-filerepo-labelupload').plain() + }); + + this.btnUpload.on('click', this.btnUploadClick, this); + + var allowedFileExtensions = mw.config.get('bsFileExtensions').concat(mw.config.get('bsImageExtensions')); + + this.dlgUpload = Ext.create( 'BS.panel.Upload', { + title: mw.message('bs-filerepo-uploaddialogtitle'), + allowedFileExtensions: allowedFileExtensions + }); + + this.dlgUpload.on ('ok', this.onUploadComplete, this); + + var toolBarItems = [ + this.sfFilter + ]; + + if (mw.config.get('bsEnableUploads')){ + toolBarItems.push( '->' ); + toolBarItems.push(this.btnUpload); + }; + + this.tbGridTools = Ext.create('Ext.toolbar.Toolbar', { + dock: 'top', + items: toolBarItems + }); + + this.dockedItems = [this.tbGridTools]; + + this.callParent(arguments); + }, + + renderFilesize: function( val ){ + return Ext.util.Format.fileSize( val ); + }, + + renderThumb: function( url, meta, record ) { + var attr = { + style: 'background-image:url('+url+'); height: 48px; width:48px;background-position: center center; background-repeat: no-repeat;' + }; + return mw.html.element( 'div', attr); + }, + renderBool: function(value){ + if(value===true){ + return mw.message('bs-filerepo-yes').plain(); + } else { + return mw.message('bs-filerepo-no').plain(); + } + }, + + btnUploadClick: function(sender, event) { + this.dlgUpload.show(); + }, + + onUploadComplete: function(sender, event){ + this.store.reload(); + } +}); \ No newline at end of file diff --git a/resources/bluespice.extjs/BS/model/File.js b/resources/bluespice.extjs/BS/model/File.js index e1e159a..6625d3b 100644 --- a/resources/bluespice.extjs/BS/model/File.js +++ b/resources/bluespice.extjs/BS/model/File.js @@ -17,7 +17,8 @@ { name: 'page_is_redirect', type: 'bool', defaultValue: false }, { name: 'page_is_new', type: 'bool', defaultValue: true }, { name: 'page_touched', type: 'date', defaultValue: '19700101000000', dateFormat: 'YmdHis' }, - + { name: 'page_link', type: 'string'}, + { name: 'file_link', type: 'string'}, //Here come custom fields that are calculated on the server side { name: 'page_categories', type: 'array', defaultValue: [] }, diff --git a/resources/bluespice.extjs/BS/panel/Upload.js b/resources/bluespice.extjs/BS/panel/Upload.js new file mode 100755 index 0000000..63fe498 --- /dev/null +++ b/resources/bluespice.extjs/BS/panel/Upload.js @@ -0,0 +1,39 @@ +Ext.define( 'BS.panel.Upload', { + extend: 'BS.Window', + requires: [ + 'Ext.Button' + ], + minHeight: 50, + padding:null, + title: null, + layout: 'fit', + + afterInitComponent: function(){ + this.upMain = Ext.create( 'BS.panel.UploadPanel', { + id: this.getId()+'-upload-panel', + allowedFileExtensions: this.allowedFileExtensions + }); + this.upMain.on ('upload-complete', this.onUpMainUploadComplete, this); + + this.items = [ + this.upMain + ]; + + this.callParent(arguments); + }, + + onBtnOKClick: function() { + this.upMain.uploadFile(); + }, + + onUpMainUploadComplete: function( panel, upload ){ + this.fireEvent( 'ok', this, upload ); + + this.close(); + }, + + resetData: function(){ + this.upMain.getForm().reset(); + this.callParent(arguments); + } +}); \ No newline at end of file diff --git a/resources/bluespice.extjs/BS/panel/UploadPanel.js b/resources/bluespice.extjs/BS/panel/UploadPanel.js new file mode 100755 index 0000000..8e6c98d --- /dev/null +++ b/resources/bluespice.extjs/BS/panel/UploadPanel.js @@ -0,0 +1,453 @@ +Ext.define ( 'BS.panel.UploadPanel', { + extend: 'Ext.form.Panel', + require: [ + 'BS.form.action.MediaWikiApiCall' + ], + fileUpload: true, + layout: { + type: 'vbox', + align: 'stretch' + }, + + initComponent: function(){ + + this.fuFile = Ext.create('Ext.form.field.File', { + fieldLabel: mw.message('bs-upload-uploadfilefieldlabel').plain(), + buttonText: mw.message('bs-upload-uploadbuttontext').plain(), + id: this.getId()+'-file', + name: 'file', + emptyText: mw.message('bs-upload-uploadfileemptytext').plain(), + validator: this.validateFile, + validateOnChange: true, + clearOnSubmit: false, + msgTarget: 'under' + + }); + + + this.fuFile.on( 'change', this.fuFileChange, this); + + this.tfFileName = Ext.create('Ext.form.TextField', { + fieldLabel: mw.message('bs-upload-uploaddestfilelabel').plain(), + id: this.getId()+'-filename', + maskRe: new RegExp(/[^\/\?\*\"\#\<\>\|\\]/), + name: 'filename' + }); + + this.tfFileName.on( 'change', this.tfFileNameChange, this); + + this.taDescription = Ext.create('Ext.form.field.TextArea', { + fieldLabel: mw.message('bs-upload-descfilelabel').plain(), + id: this.getId()+'-description', + value: '', + submitValue: false + }); + + //This hidden field will store the combined data of this.storeLicenses, + //this.taDescription and this.bsCategories on submit + this.hfText = Ext.create('Ext.form.field.Hidden', { + id: this.getId()+'-text', + value: '', + name: 'text' + }); + + this.storeLicenses = Ext.create( 'BS.store.BSApi', { + apiAction: 'bs-upload-license-store', + fields: ['text', 'value', 'indent'], + submitValue: false + }); + + this.cbLicenses = Ext.create('Ext.form.ComboBox',{ + fieldLabel: mw.message('bs-upload-license').plain(), + //autoSelect: true, + //forceSelection: true, + //typeAhead: true, + //triggerAction: 'all', + //lazyRender: true, + mode: 'local', + store: this.storeLicenses, + valueField: 'value', + displayField: 'text', + tpl: new Ext.XTemplate( + '<ul class="x-list-plain">', + '<tpl for=".">', + '<tpl if="this.hasValue(value) == false">', + '<li role="option" class="x-boundlist-item no-value">{text}</li>', + '</tpl>', + '<tpl if="this.hasValue(value)">', + '<li role="option" class="x-boundlist-item indent-{indent}">{text}</li>', + '</tpl>', + '</tpl>', + '</ul>', + { + compiled: true, + disableFormats: true, + // member functions: + hasValue: function(value) { + return value !== ''; + } + } + ) + }); + + this.cbxWatch = Ext.create('Ext.form.field.Checkbox', { + boxLabel: mw.message('bs-upload-uploadwatchthislabel').plain(), + id: this.getId()+'watch_page', + name: 'watchlist', + inputValue: 'watch' + }); + + this.cbxWarnings = Ext.create('Ext.form.field.Checkbox', { + boxLabel: mw.message('bs-upload-uploadignorewarningslabel').plain(), + id: this.getId()+'ignorewarnings', + name: 'ignorewarnings' + }); + + this.bsCategories = Ext.create( 'BS.form.CategoryBoxSelect', { + id: this.getId()+'categories', + fieldLabel: mw.message('bs-upload-categories').plain(), + submitValue: false + }); + + this.fsDetails = Ext.create( 'Ext.form.FieldSet', { + title: 'Details', + collapsed: true, + collapsible: true, + anchor: '98%', + defaults: { + anchor: '100%', + labelWidth: 90, + labelAlign: 'right' + } + }); + + this.panelItems = [ + this.fuFile, + this.tfFileName, + this.fsDetails + ]; + + var detailsItems = [ + this.hfText, + this.bsCategories, + this.taDescription, + this.cbLicenses, + this.cbxWarnings, + this.cbxWatch + ]; + + $(document).trigger( 'BSUploadPanelInitComponent', [ this, this.panelItems, detailsItems ] ); + + this.fsDetails.add( detailsItems ); + + this.items = this.panelItems; + + this.addEvents( 'uploadcomplete' ); + + this.callParent(arguments); + + }, + + + fuFileChange: function(field, value, eOpts){ + //Remove path info + value = value.replace(/^.*?([^\\\/:]*?\.[a-z0-9]+)$/img, "$1"); + value = value.replace(/\s/g, "_"); + if( mw.config.get('bsIsWindows') ) { + value = value.replace(/[^\u0000-\u007F]/gmi, ''); //Replace Non-ASCII + } + //apply value without 'C:\fakepath\' to file filed as well + field.setRawValue(value); + + this.tfFileName.setValue(value); + this.tfFileName.fireEvent('change', this.tfFileName, value); + + }, + + + + tfFileNameChange: function(sender, newValue, oldValue, eOpts){ + var Api = new mw.Api(); + var me = this; + Api.get({ + action: 'query', + format: 'json', + titles: 'File:' + newValue, + prop: 'imageinfo', + iiprop: 'uploadwarning', + indexpageids: '' + }).done( function ( response ) { + //file does not exist + if( response.query.pageids[0] === "-1" ) { + return null; + } + //replacement warning, notify user and if user ignores, set ignore warnings automatically + bs.util.alert( + me.getId()+'-existswarning', + { + titleMsg: 'bs-extjs-title-warning', + text: response.query.pages[response.query.pageids[0]] + .imageinfo[0] + .html + }, + { + ok: function() { + + me.cbxWarnings.setValue(true); + }, + scope: me + } + ); + }); + }, + + checkFileSize: function( ExtCmpId ) { + //No FileAPI? No love. + if(typeof window.FileReader === 'undefined') return true; + + var allowedSize = mw.config.get('bsMaxUploadSize'); + if( allowedSize === null ) return true; + + var filesize = this.fuFile.fileInputEl.dom.files[0].size; + if( filesize > allowedSize.php || filesize > allowedSize.mediawiki) { + return false; + } + return true; + }, + + //PW(12.03.2015) TODO: Make a second ajax request to edit file description + //(text), cause mediawiki api for action upload does not allow to change an + //existing text while uploading. + uploadFile: function( sessionKeyForReupload ) { + var desc = this.taDescription.getValue(); + var license = this.cbLicenses.getValue(); + if( license ) { + desc += license + "\n"; + } + + var categories = this.bsCategories.getValue(); + var formattedNamespaces = mw.config.get('wgFormattedNamespaces'); + for( var i = 0; i < categories.length; i++ ) { + var categoryLink = new bs.wikiText.Link({ + title: categories[i].ucFirst(), + nsText: formattedNamespaces[bs.ns.NS_CATEGORY], + link: false //TDOD: fix this in "bs.wikiText.Link" + }); + desc += "\n" + categoryLink.toString(); + } + this.hfText.setValue(desc); + + this.cbLicenses.disable(); //To prevent the form from submitting a generated name + + var params = { + action: 'upload', + token: mw.user.tokens.get('editToken'), + //IE9 has an issue with this API call returnug a application/json + //content-type. Therefore we let the server return a "text/xml" + //content-type header + //HINT: http://stackoverflow.com/questions/18571719/extjs-file-uploading-error-on-ie8-ie9 + format: 'xml' + }; + + if( sessionKeyForReupload ) { + params.sessionkey = sessionKeyForReupload; + } + + this.getForm().doAction( Ext.create('BS.form.action.MediaWikiApiCall', { + form: this.getForm(), //Required + url: mw.util.wikiScript('api'), + params: params, + success: this.onUploadSuccess, + failure: this.onUploadFailure, + scope: this + })); + + //We mask only the FormPanel, because masking the whole document using + // "waitMsg" param on MediaWikiApiCall does no automatic unmasking. + //This is because MediaWikiApiCall overrides the onSuccess/onFailure + //methods of action "Submit" + this.getEl().mask( + mw.message('bs-upload-upload-waitmessage').plain(), + Ext.baseCSSPrefix + 'mask-loading' + ); + }, + + onUploadSuccess: function( response, action ) { + this.getEl().unmask(); + this.cbLicenses.enable(); + + var errorTag = response.responseXML + .documentElement.getElementsByTagName('error').item(0); + + if( errorTag !== null ) { + //Mw API only renders un-localized windows-nonascii-filename + if( errorTag.getAttribute('invalidparameter') === "filename" ) { + if( errorTag.getAttribute('info').indexOf('windows-nonascii-filename') >= 0 ) { + bs.util.alert( + this.getId()+'-error', { + title: mw.message('bs-upload-error').plain(), + text: mw.message('windows-nonascii-filename').plain() + } + ); + return; + } + } + bs.util.alert( + this.getId()+'-error', + { + title: mw.message('bs-upload-error').plain(), + text: errorTag.getAttribute('info') + } + ); + + return; + } + + //As we process XML instead of JSON (see reason above) we have to + //create a suitable JS object from the XML response to be compatible + var uploadTag = response.responseXML + .documentElement.getElementsByTagName('upload').item(0); + + var imageinfoTag = uploadTag.getElementsByTagName('imageinfo').item(0); + + var warningsTag = uploadTag.getElementsByTagName('warnings').item(0); + if( warningsTag !== null && imageinfoTag === null ) { + var duplicate = warningsTag.getElementsByTagName('duplicate'); + if( duplicate !== null && duplicate.length > 0 ) { + var dupUrls = []; + $.each(duplicate, function() { + dupUrls.push( "File:"+this.textContent ); + }); + this.duplicateWarning({ + titles: dupUrls + }); + return; + } + // Unknown warnings + bs.util.alert( + this.getId()+'-warning', + { + title: mw.message('bs-upload-error').plain(), + text: $(warningsTag).html() + } + ); + + return; + } + + var imageinfo = {}; + if( imageinfoTag.attributes ) { + for( var i = 0; i < imageinfoTag.attributes.length; i++ ) { + var attribute = imageinfoTag.attributes.item(i); + imageinfo[attribute.nodeName] = attribute.nodeValue; + } + } + var upload = { + result: uploadTag.getAttribute('result'), + filename: uploadTag.getAttribute('filename'), + imageinfo: imageinfo + }; + + this.fireEvent( 'upload-complete', this, upload ); + //walkaround for reseting fuFile Field + this.fuFile.setRawValue(''); + this.getForm().reset(); + }, + + onUploadFailure: function( response, action ) { + //This would only happen when a server error occurred but not when the + //MediaWiki API returns an JSON encoded error + + this.getEl().unmask(); + this.getForm().reset(); + this.cbLicenses.enable(); + //walkaround for reseting fuFile Field + this.fuFile.setRawValue(''); + bs.util.alert( + this.getId()+'-error', + { + title: mw.message('bs-upload-error').plain(), + text: mw.message('bs-upload-error-long').plain() + } + ); + + }, + + //scope: "this" == fuFile + validateFile: function( value ) { + if( value === "" ) return true; + var me = this.up('form'); + + + var nameParts = value.split('.'); + + var fileExtension = nameParts[nameParts.length-1].toLowerCase(); + var extensionFound = false; + + for (i = 0; i<me.allowedFileExtensions.length; i++){ + + if (me.allowedFileExtensions[i].toLowerCase() === fileExtension.toLowerCase()){ + + extensionFound = true; + + break; + } + } + if(!extensionFound){ + return mw.message('bs-upload-filetypenotsupported').plain(); + } + + if( me.checkFileSize() === false ) { + return mw.message( 'largefileserver' ).plain(); + } + + return true; + + }, + + duplicateWarning: function( params ) { + var Api = new mw.Api(); + var me = this; + params = $.extend({ + action: 'query', + format: 'json', + titles: [], + prop: 'imageinfo', + iiprop: 'url|uploadwarning', + iiurlwidth: 64, + indexpageids: '' + }, params); + params.titles = params.titles.join('|'); + + Api.get(params).done( function ( response ) { + var text = ''; + var count = 0; + for( var i in response.query.pages ) { + if( i < 0 ) { + continue; + } + count ++; + var href = response.query.pages[i].imageinfo[0].descriptionurl; + var src = response.query.pages[i].imageinfo[0].thumburl; + var title = response.query.pages[i].title; + text += "<div class='thumbinner' style='width:62px; float:left'><a target='_blank' class='image' href="+href+" title="+title+"><img src='"+src+"' /></a></div>"; + } + + bs.util.alert( + me.getId()+'-existswarning', + { + titleMsg: 'bs-extjs-title-warning', + text: mw.message('file-exists-duplicate',count).text() + '<br /><div style="clear:both">' + text + '</div>' + }, + { + ok: function() { + //User is noticed. Now let's set the + //ignore warnings flag automatically + me.cbxWarnings.setValue(true); + }, + scope: me + } + ); + }); + } +}); \ No newline at end of file -- To view, visit https://gerrit.wikimedia.org/r/311676 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I36bfbc5897562a035f5c2dac4c0d4340760b5722 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/BlueSpiceFoundation Gerrit-Branch: master Gerrit-Owner: ItSpiderman <d.savulje...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits