UNPKG

@bigfishtv/cockpit

Version:

488 lines (439 loc) 17.5 kB
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; }; var _class, _class2, _temp2, _class3, _temp3; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } import React, { Component } from 'react'; import { Fieldset } from '@bigfishtv/react-forms'; import deepEqual from 'deep-equal'; import classnames from 'classnames'; import _get from 'lodash/get'; import _truncate from 'lodash/truncate'; import * as xhrUtils from '../../api/xhrUtils'; import { showDeletePrompt } from '../../utils/promptUtils'; import { titleCase } from '../../utils/stringUtils'; import { modalHandler } from '../modal/ModalHost'; import { flatten, getParentByChildId, sortByKey, pruneTree, appendChildToParent, replaceChild } from '../../utils/treeUtils'; import modalFormValueContext from '../../decorators/modalFormValueContext'; import { AutoTableIndexContainer, AutoTableIndexBase } from './AutoTableIndex'; import MainContent from '../container/MainContent'; import Bulkhead from '../page/Bulkhead'; import Panel from '../container/panel/Panel'; import Tree from '../tree/Tree'; import Field from '../form/Field'; import Modal from '../modal/Modal'; import TreeSelectModal from '../modal/TreeSelectModal'; import Button from '../button/Button'; import DropdownItem from '../button/dropdown/DropdownItem'; import DropdownItemDivider from '../button/dropdown/DropdownItemDivider'; import DropdownButton from '../button/dropdown/DropdownButton'; import Icon from '../Icon'; import TreeModal from '../modal/TreeModal'; var DefaultBulkheadToolbar = function DefaultBulkheadToolbar(_ref) { var modelLabel = _ref.modelLabel, model = _ref.model, addUrl = _ref.addUrl; return React.createElement(Button, { text: 'New ' + titleCase(modelLabel || model), onClick: function onClick() { return window.location.href = addUrl; }, style: 'primary', size: 'large' }); }; // used in sidebar var DefaultTreeCell = function DefaultTreeCell(props) { var id = props.id, title = props.title, locked = props.locked, isCollapsed = props.isCollapsed, showIndicator = props.showIndicator, onIndicatorClick = props.onIndicatorClick, onIndicatorDoubleClick = props.onIndicatorDoubleClick, isOver = props.isOver, position = props.position, onClick = props.onClick, onDoubleClick = props.onDoubleClick, selected = props.selected, data = props.data; var items = id === null ? data : data.filter(function (_ref2) { var folder_id = _ref2.folder_id; return id === '_unsorted' ? folder_id === null : folder_id === id; }); return React.createElement( 'div', { className: classnames('tree-item', isOver && 'drag-' + position) }, React.createElement( 'div', { className: classnames('tree-cell tree-cell-small', { selected: selected }), onClick: onClick, onDoubleClick: onDoubleClick }, showIndicator ? React.createElement( 'div', { className: classnames('tree-cell-icon', isCollapsed && 'collapsed'), onClick: onIndicatorClick, onDoubleClick: onIndicatorDoubleClick }, React.createElement(Icon, { name: 'chevron-' + (isCollapsed ? 'right' : 'down'), size: 18 }) ) : React.createElement('div', { className: 'tree-cell-icon' }), locked && React.createElement( 'div', { className: 'tree-cell-icon' }, React.createElement(Icon, { name: 'lock', size: 12 }) ), React.createElement( 'div', { className: 'tree-cell-title' }, _truncate(title, { length: 45 }), ' (', items.length, ')' ) ) ); }; // used in sidebar var DefaultTray = function DefaultTray(props) { var onFolderAdd = props.onFolderAdd, onFolderDelete = props.onFolderDelete, onEdit = props.onEdit, currentFolderId = props.currentFolderId; return React.createElement( 'div', { className: 'finder-menu-footer' }, React.createElement(Button, { size: 'small', text: 'Add Folder', onClick: onFolderAdd }), React.createElement(Button, { size: 'small', text: 'Delete', onClick: onFolderDelete }), React.createElement(Button, { size: 'small', text: 'Edit', onClick: onEdit, disabled: currentFolderId === null }) ); }; export var DefaultFolderSidebarToolbar = function DefaultFolderSidebarToolbar(props) { return React.createElement( DropdownButton, { style: 'icon', caret: false, pullRight: true, text: React.createElement(Icon, { name: 'hamburger' }) }, React.createElement(DropdownItem, { text: 'New Folder', icon: 'folder-new', onClick: props.handleFolderAdd }), React.createElement(DropdownItem, { text: 'Edit', icon: 'edit', onClick: props.handleFolderEdit, disabled: !props.currentFolderId }), React.createElement(DropdownItemDivider, null), React.createElement(DropdownItem, { text: 'Remove', icon: 'remove', onClick: props.handleFolderDelete, disabled: !props.currentFolderId }) ); }; export var DefaultFolderEditModal = modalFormValueContext(_class = (_temp2 = _class2 = function (_Component) { _inherits(DefaultFolderEditModal, _Component); function DefaultFolderEditModal() { var _temp, _this, _ret; _classCallCheck(this, DefaultFolderEditModal); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = _possibleConstructorReturn(this, _Component.call.apply(_Component, [this].concat(args))), _this), _this.handleSave = function () { _this.props.onSave(_this.props.formValue, _this.props.isNew); }, _this.handleClose = function () { var didSave = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; _this.props.onClose(_this.props.formValue, didSave, _this.props.isNew); }, _temp), _possibleConstructorReturn(_this, _ret); } DefaultFolderEditModal.prototype.render = function render() { var foldersUrl = this.props.foldersUrl; var title = this.props.formValue.value.title; return React.createElement( Modal, _extends({}, this.props, { title: title || 'New Folder', size: 'small', onClose: this.handleClose, onSave: this.handleSave }), React.createElement( Fieldset, { formValue: this.props.formValue }, React.createElement(Field, { select: 'title', label: 'Title', placeholder: 'Title', autoFocus: true }), React.createElement( Field, { select: 'parent', label: 'Parent Folder' }, React.createElement(TreeSelectModal, { buttonText: 'Select Folder', modalProps: { url: foldersUrl, title: 'Select Parent Folder', primaryActionText: 'Select Parent Folder', filterData: function filterData(data, user) { return sortByKey(data, 'title'); } } }) ) ) ); }; return DefaultFolderEditModal; }(Component), _class2.defaultProps = { isNew: false }, _temp2)) || _class; var AutoFolderTableIndex = (_temp3 = _class3 = function (_Component2) { _inherits(AutoFolderTableIndex, _Component2); function AutoFolderTableIndex(props) { _classCallCheck(this, AutoFolderTableIndex); var _this2 = _possibleConstructorReturn(this, _Component2.call(this, props)); _this2.handleFolderSelection = function (ids, handleFilterChange) { var currentFolderId = ids[0]; _this2.setState({ currentFolderId: currentFolderId }, function () { return handleFilterChange && handleFilterChange('folder_id', currentFolderId == '_unsorted' ? function (val) { return val === null; } : currentFolderId); }); }; _this2.handleFolderCollapse = function (collapsedIds) { _this2.setState({ collapsedIds: collapsedIds }); }; _this2.handleFolderAdd = function () { console.log('opening folder add modal'); modalHandler.add({ Component: _this2.props.FolderEditModal, props: { isNew: true, defaultValue: _this2.props.newFolderDefaultValue, foldersUrl: _this2.props.foldersUrl, onSave: _this2.handleFolderEditSave.bind(_this2, {}), onClose: _this2.handleFolderEditClose.bind(_this2, {}) } }); }; _this2.handleFolderEdit = function () { var _this2$state = _this2.state, foldersData = _this2$state.foldersData, currentFolderId = _this2$state.currentFolderId; if (!currentFolderId) return; // because folder data is threaded we gotta flatten it to find current selection and set its parent var folder = flatten(foldersData).filter(function (item) { return item.id === currentFolderId; })[0]; folder.parent = getParentByChildId(currentFolderId, foldersData); modalHandler.add({ Component: _this2.props.FolderEditModal, props: { defaultValue: folder, foldersUrl: _this2.props.foldersUrl, onSave: _this2.handleFolderEditSave.bind(_this2, folder), onClose: _this2.handleFolderEditClose.bind(_this2, folder) } }); }; _this2.handleFolderEditSave = function (oldRowValue, newRowValue, isNew) { newRowValue = newRowValue.value; if (!deepEqual(oldRowValue, newRowValue)) { var postUrl = _this2.props.getFolderSubmitUrl({ id: isNew ? false : newRowValue.id }); var hasNewParent = _get(newRowValue, 'parent.id', null) != _get(oldRowValue, 'parent.id'); if (hasNewParent) newRowValue.parent_id = _get(newRowValue, 'parent.id', null); xhrUtils.post({ url: postUrl, data: newRowValue, callback: function callback(folder) { var foldersData = _this2.state.foldersData; if (isNew) { foldersData = appendChildToParent(foldersData, folder.parent_id, folder); foldersData = sortByKey(foldersData, 'title'); } else { if (hasNewParent) { foldersData = pruneTree(foldersData, 'id', folder.id); foldersData = appendChildToParent(foldersData, folder.parent_id, folder); foldersData = sortByKey(foldersData, 'title'); } else { foldersData = replaceChild(_this2.state.foldersData, folder); } } _this2.setState({ foldersData: foldersData }); _this2.handleFolderSelection([folder.id]); } }); } else { console.log('Nothing edited, not saving.'); } }; _this2.handleFolderEditClose = function (oldRowValue, newFormValue, isNew) { console.log('MODAL CLOSED, W/E'); }; _this2.handleFolderDelete = function () { var _this2$state2 = _this2.state, foldersData = _this2$state2.foldersData, currentFolderId = _this2$state2.currentFolderId; showDeletePrompt({ subject: 'email template folder', queryUrl: _this2.props.folderDeleteUrl, style: 'error', selectedIds: [currentFolderId], data: flatten(foldersData).filter(function (item) { return item.id === currentFolderId; }), callback: function callback(response) { _this2.setState({ foldersData: pruneTree(foldersData, 'id', [currentFolderId]), currentFolderId: null }); } }); }; _this2.handleMove = function (selectedItems, updateCallback) { modalHandler.add({ Component: TreeModal, props: { title: 'Select Folder', primaryActionText: 'Confirm', url: _this2.props.foldersUrl, onClose: function onClose() {}, onSave: function onSave(folder) { if (folder) { var selectedIds = selectedItems.map(function (_ref3) { var id = _ref3.id; return id; }); xhrUtils.post({ url: _this2.props.moveUrl + '?folder_id=' + folder.id, data: { id: selectedIds }, successMessage: selectedItems.length + ' item' + (selectedItems.length > 1 ? 's' : '') + ' moved to ' + folder.title, failureMessage: 'There was an error moving items', callback: function callback() { var updateDataFunc = function updateDataFunc(data) { return data.map(function (item) { return ~selectedIds.indexOf(item.id) ? _extends({}, item, { folder_id: folder.id }) : item; }); }; updateCallback(updateDataFunc); } }); } } } }); }; _this2.state = { foldersData: props.folders || [], currentFolderId: null, collapsedFolderIds: [] }; return _this2; } AutoFolderTableIndex.prototype.render = function render() { var _this3 = this; var _props = this.props, SidebarToolbar = _props.SidebarToolbar, BulkheadToolbar = _props.BulkheadToolbar, _TreeCell = _props.TreeCell, sidebarTitle = _props.sidebarTitle; var _state = this.state, collapsedFolderIds = _state.collapsedFolderIds, currentFolderId = _state.currentFolderId, foldersData = _state.foldersData; var sidebarProps = { currentFolderId: currentFolderId, handleFolderAdd: this.handleFolderAdd, handleFolderEdit: this.handleFolderEdit, handleFolderDelete: this.handleFolderDelete }; var _foldersData = [{ id: null, title: '[All]' }, { id: '_unsorted', title: '[Unsorted]' }].concat(foldersData); return React.createElement( AutoTableIndexContainer, _extends({}, this.props, { defaultValue: this.props.data, movable: !!this.props.moveUrl, onMove: this.handleMove }), function (props) { var model = props.model, panelProps = props.panelProps, handleFilterChange = props.handleFilterChange, originalData = props.originalData; return React.createElement( MainContent, null, React.createElement(Bulkhead, { title: titleCase(model), Toolbar: function Toolbar() { return React.createElement(BulkheadToolbar, _extends({}, props, panelProps)); } }), React.createElement( 'div', { className: 'finder' }, React.createElement( 'div', { className: 'finder-menu' }, React.createElement( Panel, { title: sidebarTitle || 'Folders', PanelToolbar: function PanelToolbar() { return React.createElement(SidebarToolbar, sidebarProps); } }, React.createElement(Tree, { value: _foldersData, TreeCell: function TreeCell(props) { return React.createElement(_TreeCell, _extends({}, props, { data: originalData })); }, dropTargetType: 'TANK_FOLDER', treeItemTarget: treeItemTarget(_this3), treeItemSource: treeItemSource(_this3), onSelectItem: _this3.handleFolderEdit, selectedIds: [currentFolderId], collapsedIds: collapsedFolderIds, onSelectionChange: function onSelectionChange(ids) { return _this3.handleFolderSelection(ids, handleFilterChange); }, onCollapseChange: _this3.handleFolderCollapse, onCombinationChange: function onCombinationChange() { return console.log('HANDLE COMBINATION CHANGE'); } }) ) ), React.createElement( 'div', { className: 'finder-content', ref: 'finderContent' }, React.createElement(AutoTableIndexBase, props) ) ) ); } ); }; return AutoFolderTableIndex; }(Component), _class3.defaultProps = { Tray: DefaultTray, TreeCell: DefaultTreeCell, BulkheadToolbar: DefaultBulkheadToolbar, SidebarToolbar: DefaultFolderSidebarToolbar, FolderEditModal: DefaultFolderEditModal, foldersUrl: '/tank/folders.json', folderDeleteUrl: '/tank/folders/delete.json', getFolderSubmitUrl: function getFolderSubmitUrl(data) { return '/tank/folders/' + (data.id ? 'edit/' + data.id : 'add') + '.json'; }, componentResolver: function componentResolver() {}, attributeModified: function attributeModified() {}, newFolderDefaultValue: {} }, _temp3); // drag source & target configs for allowing projects to be dropped into sector folders export { AutoFolderTableIndex as default }; var treeItemSource = function treeItemSource(parent) { return { beginDrag: function beginDrag(props, monitor, component) { return { id: props.id }; } }; }; var treeItemTarget = function treeItemTarget(parent) { return { drop: function drop(props, monitor, component) { if (monitor.isOver({ shallow: true })) { if (!props.selected) { var sectorId = monitor.getItem().id; var parentId = props.id; parent.onMoveSector(parentId, sectorId); } else { console.log('no need to move asset into already opened folder'); } } }, hover: function hover(props, monitor, component) { if (monitor.isOver({ shallow: true })) { var ownId = props.id; var draggedId = monitor.getItem().id; if (draggedId === ownId) return; component.setState({ position: 'into' }); } } }; };