/* * Copyright 2007-2017 Charles du Jeu - Abstrium SAS * This file is part of Pydio. * * Pydio is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Pydio 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Pydio. If not, see . * * The latest code can be found at . */ 'use strict'; exports.__esModule = true; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _pydio = require('pydio'); var _pydio2 = _interopRequireDefault(_pydio); var _reactDom = require('react-dom'); var _reactDom2 = _interopRequireDefault(_reactDom); var _FilePreview = require('./FilePreview'); var _FilePreview2 = _interopRequireDefault(_FilePreview); var _materialUi = require('material-ui'); var _Pydio$requireLib = _pydio2['default'].requireLib('components'); var SimpleList = _Pydio$requireLib.SimpleList; var ComponentConfigsParser = (function () { function ComponentConfigsParser() { _classCallCheck(this, ComponentConfigsParser); } ComponentConfigsParser.prototype.getDefaultListColumns = function getDefaultListColumns() { return { text: { label: 'File Name', message: '1', width: '50%', renderCell: MainFilesList.tableEntryRenderCell, sortType: 'string', remoteSortAttribute: 'ajxp_label' }, filesize: { label: 'File Size', message: '2', sortType: 'number', sortAttribute: 'bytesize', remoteSortAttribute: 'filesize' }, mimestring: { label: 'File Type', message: '3', sortType: 'string' }, ajxp_modiftime: { label: 'Mofidied on', message: '4', sortType: 'number' } }; }; ComponentConfigsParser.prototype.loadConfigs = function loadConfigs(componentName) { var configs = new Map(); var columnsNodes = XMLUtils.XPathSelectNodes(global.pydio.getXmlRegistry(), 'client_configs/component_config[@component="FilesList"]/columns/column|client_configs/component_config[@component="FilesList"]/columns/additional_column'); var columns = {}; var messages = global.pydio.MessageHash; columnsNodes.forEach(function (colNode) { var name = colNode.getAttribute('attributeName'); columns[name] = { message: colNode.getAttribute('messageId'), label: colNode.getAttribute('messageString') ? colNode.getAttribute('messageString') : messages[colNode.getAttribute('messageId')], sortType: messages[colNode.getAttribute('sortType')] }; if (name === 'ajxp_label') { columns[name].renderCell = MainFilesList.tableEntryRenderCell; } if (colNode.getAttribute('reactModifier')) { (function () { var reactModifier = colNode.getAttribute('reactModifier'); ResourcesManager.detectModuleToLoadAndApply(reactModifier, function () { columns[name].renderComponent = columns[name].renderCell = FuncUtils.getFunctionByName(reactModifier, global); }, true); })(); } columns[name]['sortType'] = 'string'; }); configs.set('columns', columns); return configs; }; ComponentConfigsParser.loadDefaultDisplayOptions = function loadDefaultDisplayOptions(props) { var pydio = props.pydio; var displayMode = props.displayMode; var repoType = undefined; var res = { displayMode: displayMode || 'list', defaultSortingInfo: { sortType: 'file-natural', attribute: '', direction: 'asc' } }; try { repoType = pydio.user.getRepositoriesList().get(pydio.user.getActiveRepository()).getAccessType(); } catch (e) { return res; } var data = pydio.getPluginConfigs("access." + repoType); if (!displayMode && data.get('UX_DISPLAY_DEFAULT_MODE')) { res.displayMode = data.get('UX_DISPLAY_DEFAULT_MODE'); } if (data.get('UX_SORTING_DEFAULT_COLUMN')) { var sort = data.get('UX_SORTING_DEFAULT_COLUMN'); var dir = data.get('UX_SORTING_DEFAULT_DIRECTION') || 'asc'; switch (sort) { case 'natural': res.defaultSortingInfo = { sortType: 'file-natural', attribute: '', direction: dir }; break; case 'filename': res.defaultSortingInfo = { sortType: 'string', attribute: 'text', direction: dir }; break; case 'ajxp_modiftime': res.defaultSortingInfo = { sortType: 'string', attribute: 'ajxp_modiftime', direction: dir }; break; case 'bytesize': res.defaultSortingInfo = { sortType: 'number', attribute: 'bytesize', direction: dir }; break; default: break; } } return res; }; return ComponentConfigsParser; })(); var MainFilesList = _react2['default'].createClass({ displayName: 'MainFilesList', propTypes: { pydio: _react2['default'].PropTypes.instanceOf(_pydio2['default']), horizontalRibbon: _react2['default'].PropTypes.bool }, statics: { tableEntryRenderCell: function tableEntryRenderCell(node) { return _react2['default'].createElement( 'span', null, _react2['default'].createElement(_FilePreview2['default'], { rounded: true, loadThumbnail: false, node: node, style: { backgroundColor: 'transparent' } }), ' ', node.getLabel() ); } }, getInitialState: function getInitialState() { var configParser = new ComponentConfigsParser(); var columns = configParser.loadConfigs('FilesList').get('columns'); var uxProps = ComponentConfigsParser.loadDefaultDisplayOptions(this.props); return _extends({ contextNode: this.props.pydio.getContextHolder().getContextNode(), thumbNearest: 200, thumbSize: 200, elementsPerLine: 5, columns: columns ? columns : configParser.getDefaultListColumns(), parentIsScrolling: this.props.parentIsScrolling, repositoryId: this.props.pydio.repositoryId }, uxProps); }, componentDidMount: function componentDidMount() { // Hook to the central datamodel this._contextObserver = (function () { this.setState({ contextNode: this.props.pydio.getContextHolder().getContextNode() }); }).bind(this); this.props.pydio.getContextHolder().observe("context_changed", this._contextObserver); this.props.pydio.getController().updateGuiActions(this.getPydioActions()); this.recomputeThumbnailsDimension(); if (window.addEventListener) { window.addEventListener('resize', this.recomputeThumbnailsDimension); } else { window.attachEvent('onresize', this.recomputeThumbnailsDimension); } }, componentWillUnmount: function componentWillUnmount() { this.props.pydio.getContextHolder().stopObserving("context_changed", this._contextObserver); this.getPydioActions(true).map((function (key) { this.props.pydio.getController().deleteFromGuiActions(key); }).bind(this)); if (window.addEventListener) { window.removeEventListener('resize', this.recomputeThumbnailsDimension); } else { window.detachEvent('onresize', this.recomputeThumbnailsDimension); } }, shouldComponentUpdate: function shouldComponentUpdate(nextProps, nextState) { return !this.state || this.state.repositoryId !== nextProps.pydio.repositoryId || nextState !== this.state; }, componentWillReceiveProps: function componentWillReceiveProps(nextProps) { if (this.state && this.state.repositoryId !== this.props.pydio.repositoryId) { this.props.pydio.getController().updateGuiActions(this.getPydioActions()); var configParser = new ComponentConfigsParser(); var columns = configParser.loadConfigs('FilesList').get('columns'); var uxProps = ComponentConfigsParser.loadDefaultDisplayOptions(nextProps); this.setState(_extends({}, uxProps, { columns: columns ? columns : configParser.getDefaultListColumns(), repositoryId: this.props.pydio.repositoryId })); } }, resize: function resize() { this.recomputeThumbnailsDimension(); }, recomputeThumbnailsDimension: function recomputeThumbnailsDimension(nearest) { if (!nearest || nearest instanceof Event) { nearest = this.state.thumbNearest; } var MAIN_CONTAINER_FULL_PADDING = 2; var THUMBNAIL_MARGIN = 1; var containerWidth = undefined; try { containerWidth = _reactDom2['default'].findDOMNode(this.refs['list'].refs['infinite']).clientWidth - MAIN_CONTAINER_FULL_PADDING; } catch (e) { containerWidth = 200; } // Find nearest dim var blockNumber = Math.floor(containerWidth / nearest); var width = Math.floor(containerWidth / blockNumber) - THUMBNAIL_MARGIN * 2; if (this.props.horizontalRibbon) { blockNumber = this.state.contextNode.getChildren().size; if (this.state.displayMode === 'grid-160') width = 160;else if (this.state.displayMode === 'grid-320') width = 320;else if (this.state.displayMode === 'grid-80') width = 80;else width = 200; } // Recompute columns widths var columns = this.state.columns; var columnKeys = Object.keys(columns); var defaultFirstWidthPercent = 10; var defaultFirstMinWidthPx = 250; var firstColWidth = Math.max(250, containerWidth * defaultFirstWidthPercent / 100); var otherColWidth = (containerWidth - firstColWidth) / (Object.keys(this.state.columns).length - 1); columnKeys.map(function (columnKey) { columns[columnKey]['width'] = otherColWidth; }); this.setState({ columns: columns, elementsPerLine: blockNumber, thumbSize: width, thumbNearest: nearest }); }, entryRenderIcon: function entryRenderIcon(node) { var _this = this; var entryProps = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; if (entryProps && entryProps.parent) { return _react2['default'].createElement(_FilePreview2['default'], { loadThumbnail: false, node: node, mimeClassName: 'mimefont mdi mdi-chevron-left', onTouchTap: function () { _this.entryHandleClicks(node, SimpleList.CLICK_TYPE_DOUBLE); }, style: { cursor: 'pointer' } }); } else { return _react2['default'].createElement(_FilePreview2['default'], { loadThumbnail: !entryProps['parentIsScrolling'], node: node }); } }, entryRenderActions: function entryRenderActions(node) { var _this2 = this; var content = null; var mobile = this.props.pydio.UI.MOBILE_EXTENSIONS; var dm = this.props.pydio.getContextHolder(); if (mobile) { var _ret2 = (function () { var ContextMenuModel = require('pydio/model/context-menu'); return { v: _react2['default'].createElement(_materialUi.IconButton, { iconClassName: 'mdi mdi-dots-vertical', tooltip: 'Info', onClick: function (event) { _this2.props.pydio.observeOnce('actions_refreshed', function () { ContextMenuModel.getInstance().openNodeAtPosition(node, event.clientX, event.clientY); }); event.stopPropagation(); dm.setSelectedNodes([node]); ContextMenuModel.getInstance().openNodeAtPosition(node, event.clientX, event.clientY); } }) }; })(); if (typeof _ret2 === 'object') return _ret2.v; } else if (node.getMetadata().get('overlay_class')) { var elements = node.getMetadata().get('overlay_class').split(',').map(function (c) { return _react2['default'].createElement('span', { key: c, className: c + ' overlay-class-span' }); }); content = _react2['default'].createElement( 'div', { className: 'overlay_icon_div' }, elements ); } return content; }, entryHandleClicks: function entryHandleClicks(node, clickType, event) { var dm = this.props.pydio.getContextHolder(); var mobile = this.props.pydio.UI.MOBILE_EXTENSIONS || this.props.horizontalRibbon; if (dm.getContextNode().getParent() === node && clickType === SimpleList.CLICK_TYPE_SIMPLE) { return; } if (!mobile && (!clickType || clickType === SimpleList.CLICK_TYPE_SIMPLE)) { var crtSelection = dm.getSelectedNodes(); if (event && event.shiftKey && crtSelection.length) { var newSelection = this.refs.list.computeSelectionFromCurrentPlusTargetNode(crtSelection, node); dm.setSelectedNodes(newSelection); } else if (event && (event.ctrlKey || event.metaKey) && crtSelection.length) { if (crtSelection.indexOf(node) === -1) { dm.setSelectedNodes([].concat(crtSelection, [node])); } else { var otherSelection = crtSelection.filter(function (obj) { return obj !== node; }); dm.setSelectedNodes(otherSelection); } } else { dm.setSelectedNodes([node]); } } else if (mobile || clickType === SimpleList.CLICK_TYPE_DOUBLE) { if (!node.isBrowsable()) { dm.setSelectedNodes([node]); this.props.pydio.Controller.fireAction("open_with_unique"); } else { dm.requireContextChange(node); } } }, entryRenderSecondLine: function entryRenderSecondLine(node) { var metaData = node.getMetadata(); var pieces = []; if (metaData.get("ajxp_description")) { pieces.push(_react2['default'].createElement( 'span', { key: 'ajxp_description', className: 'metadata_chunk metadata_chunk_description' }, metaData.get('ajxp_description') )); } var first = false; var attKeys = Object.keys(this.state.columns); for (var i = 0; i < attKeys.length; i++) { var s = attKeys[i]; var columnDef = this.state.columns[s]; var label = undefined; if (s === 'ajxp_label' || s === 'text') { continue; } else if (s == "ajxp_modiftime") { var date = new Date(); date.setTime(parseInt(metaData.get(s)) * 1000); label = PathUtils.formatModifDate(date); } else if (s == "ajxp_dirname" && metaData.get("filename")) { var dirName = PathUtils.getDirname(metaData.get("filename")); label = dirName ? dirName : "/"; } else if (s == "filesize" && metaData.get(s) == "-") { continue; } else if (columnDef.renderComponent) { columnDef['name'] = s; label = columnDef.renderComponent(node, columnDef); } else { var metaValue = metaData.get(s) || ""; if (!metaValue) continue; label = metaValue; } var sep = undefined; if (!first) { sep = _react2['default'].createElement('span', { className: 'icon-angle-right' }); } var cellClass = 'metadata_chunk metadata_chunk_standard metadata_chunk_' + s; pieces.push(_react2['default'].createElement( 'span', { key: s, className: cellClass }, sep, _react2['default'].createElement( 'span', { className: 'text_label' }, label ) )); } return pieces; }, switchDisplayMode: function switchDisplayMode(displayMode) { this.setState({ displayMode: displayMode }); if (displayMode.indexOf('grid-') === 0) { var near = parseInt(displayMode.split('-')[1]); this.recomputeThumbnailsDimension(near); } else if (displayMode === 'detail') { this.recomputeThumbnailsDimension(); } }, getPydioActions: function getPydioActions() { var keysOnly = arguments.length <= 0 || arguments[0] === undefined ? false : arguments[0]; if (keysOnly) { return ['switch_display_mode']; } var multiAction = new Action({ name: 'switch_display_mode', icon_class: 'mdi mdi-view-list', text_id: 150, title_id: 151, text: MessageHash[150], title: MessageHash[151], hasAccessKey: false, subMenu: true, subMenuUpdateImage: true }, { selection: false, dir: true, actionBar: true, actionBarGroup: 'display_toolbar', contextMenu: false, infoPanel: false }, {}, {}, { staticItems: [{ name: 'List', title: 227, icon_class: 'mdi mdi-view-list', callback: (function () { this.switchDisplayMode('list'); }).bind(this), hasAccessKey: true, accessKey: 'list_access_key' }, { name: 'Detail', title: 461, icon_class: 'mdi mdi-view-headline', callback: (function () { this.switchDisplayMode('detail'); }).bind(this), hasAccessKey: true, accessKey: 'detail_access_key' }, { name: 'Thumbs', title: 229, icon_class: 'mdi mdi-view-grid', callback: (function () { this.switchDisplayMode('grid-160'); }).bind(this), hasAccessKey: true, accessKey: 'thumbs_access_key' }, { name: 'Thumbs large', title: 229, icon_class: 'mdi mdi-view-agenda', callback: (function () { this.switchDisplayMode('grid-320'); }).bind(this), hasAccessKey: false }, { name: 'Thumbs small', title: 229, icon_class: 'mdi mdi-view-module', callback: (function () { this.switchDisplayMode('grid-80'); }).bind(this), hasAccessKey: false }] }); var buttons = new Map(); buttons.set('switch_display_mode', multiAction); return buttons; }, render: function render() { var tableKeys = undefined, sortKeys = undefined, elementStyle = undefined, className = 'files-list layout-fill main-files-list'; var elementHeight = undefined, entryRenderSecondLine = undefined, elementsPerLine = 1, near = undefined; var dMode = this.state.displayMode; if (dMode.indexOf('grid-') === 0) { near = parseInt(dMode.split('-')[1]); dMode = 'grid'; } var infiniteSliceCount = 50; if (dMode === 'detail') { elementHeight = SimpleList.HEIGHT_ONE_LINE; tableKeys = this.state.columns; } else if (dMode === 'grid') { sortKeys = this.state.columns; className += ' material-list-grid grid-size-' + near; elementHeight = Math.ceil(this.state.thumbSize / this.state.elementsPerLine); if (!elementHeight || this.props.horizontalRibbon) { elementHeight = 1; } elementsPerLine = this.state.elementsPerLine; elementStyle = { width: this.state.thumbSize, height: this.state.thumbSize }; if (this.props.horizontalRibbon) { className += ' horizontal-ribbon'; } // Todo: compute a more real number of elements visible per page. if (near === 320) infiniteSliceCount = 25;else if (near === 160) infiniteSliceCount = 80;else if (near === 80) infiniteSliceCount = 200; } else if (dMode === 'list') { sortKeys = this.state.columns; elementHeight = SimpleList.HEIGHT_TWO_LINES; entryRenderSecondLine = this.entryRenderSecondLine; } var pydio = this.props.pydio; var contextNode = this.state.contextNode; var messages = pydio.MessageHash; var canUpload = pydio.user && pydio.user.write && pydio.Controller.getActionByName('upload') && contextNode.getMetadata().get('ajxp_readonly') !== 'true'; var secondary = messages[canUpload ? '565' : '566']; var iconClassName = canUpload ? 'mdi mdi-cloud-upload' : 'mdi mdi-folder-outline'; var emptyStateProps = { style: { backgroundColor: 'transparent' }, iconClassName: iconClassName, primaryTextId: messages['562'], secondaryTextId: secondary }; if (contextNode.isRoot()) { (function () { var recyclePath = contextNode.getMetadata().get('repo_has_recycle'); emptyStateProps = { style: { backgroundColor: 'transparent' }, iconClassName: iconClassName, primaryTextId: messages['563'], secondaryTextId: secondary }; if (recyclePath) { emptyStateProps = _extends({}, emptyStateProps, { checkEmptyState: function checkEmptyState(node) { return node.isLoaded() && node.getChildren().size === 1 && node.getChildren().get(recyclePath); }, actionLabelId: messages['567'], actionIconClassName: 'mdi mdi-delete', actionCallback: function actionCallback(e) { pydio.goTo(recyclePath); } }); } })(); } else { var recycle = pydio.getContextHolder().getRootNode().getMetadata().get('repo_has_recycle'); if (contextNode.getPath() === recycle) { emptyStateProps = _extends({}, emptyStateProps, { iconClassName: 'mdi mdi-delete-empty', primaryTextId: messages['564'], secondaryTextId: null }); } } return _react2['default'].createElement(SimpleList, { ref: 'list', tableKeys: tableKeys, sortKeys: sortKeys, node: this.state.contextNode, dataModel: pydio.getContextHolder(), className: className, actionBarGroups: ["change_main"], infiniteSliceCount: infiniteSliceCount, skipInternalDataModel: true, elementsPerLine: elementsPerLine, elementHeight: elementHeight, elementStyle: elementStyle, passScrollingStateToChildren: true, entryRenderIcon: this.entryRenderIcon, entryRenderParentIcon: this.entryRenderIcon, entryRenderSecondLine: entryRenderSecondLine, entryRenderActions: this.entryRenderActions, entryHandleClicks: this.entryHandleClicks, horizontalRibbon: this.props.horizontalRibbon, emptyStateProps: emptyStateProps, defaultSortingInfo: this.state.defaultSortingInfo }); } }); exports['default'] = MainFilesList; module.exports = exports['default'];