123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- /*
- * Copyright (C) 2015 - present Instructure, Inc.
- *
- * This file is part of Canvas.
- *
- * Canvas 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, version 3 of the License.
- *
- * Canvas 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 this program. If not, see <http://www.gnu.org/licenses/>.
- */
- import I18n from 'i18n!react_files'
- import React from 'react'
- import PropTypes from 'prop-types'
- import ReactDOM from 'react-dom'
- import preventDefault from 'compiled/fn/preventDefault'
- import customPropTypes from 'compiled/react_files/modules/customPropTypes'
- import filesEnv from 'compiled/react_files/modules/filesEnv'
- import File from 'compiled/models/File'
- import Folder from 'compiled/models/Folder'
- import UsageRightsDialog from 'jsx/files/UsageRightsDialog'
- import RestrictedDialogForm from 'jsx/files/RestrictedDialogForm'
- import openMoveDialog from 'jsx/files/utils/openMoveDialog'
- import downloadStuffAsAZip from 'compiled/react_files/utils/downloadStuffAsAZip'
- import deleteStuff from 'compiled/react_files/utils/deleteStuff'
- import $ from 'jquery'
- var ItemCog = React.createClass({
- displayName: 'ItemCog',
- propTypes: {
- model: customPropTypes.filesystemObject,
- modalOptions: PropTypes.object.isRequired,
- externalToolsForContext: PropTypes.arrayOf(PropTypes.object),
- userCanManageFilesForContext: PropTypes.bool,
- userCanRestrictFilesForContext: PropTypes.bool.isRequired,
- usageRightsRequiredForContext: PropTypes.bool
- },
- isMasterCourseRestricted () {
- return this.props.model.get('is_master_course_child_content') &&
- this.props.model.get('restricted_by_master_course')
- },
- downloadFile (file, args) {
- window.location = file[0].get('url');
- $(args.returnFocusTo).focus();
- },
- downloadZip (folder, args) {
- downloadStuffAsAZip(folder, args);
- $(args.returnFocusTo).focus();
- },
- deleteItem (item, args) {
- // Unfortunately, ars.returnFocusTo isn't really the one we want to focus,
- // because we want the previous one or the +Folder button
- // Also unfortunately, our state management in this app is a bit terrible
- // so we'll just handle all that via jQuery right here for now.
- // TODO: Make this less terrible when we have sane state management
- const allTriggers = $('.al-trigger').toArray();
- const hasMoreTriggers = allTriggers.length - 1 > 0;
- const toFocus = (hasMoreTriggers) ?
- allTriggers[allTriggers.indexOf(args.returnFocusTo) - 1] :
- $('.ef-name-col a').first();
- args.returnFocusTo = toFocus;
- deleteStuff(item, args);
- },
- openUsageRightsDialog (event) {
- var contents = (
- <UsageRightsDialog
- closeModal={this.props.modalOptions.closeModal}
- itemsToManage={[this.props.model]}
- userCanRestrictFilesForContext={this.props.userCanRestrictFilesForContext}
- />
- );
- this.props.modalOptions.openModal(contents, () => {
- ReactDOM.findDOMNode(this.refs.settingsCogBtn).focus();
- });
- },
- render () {
- var externalToolMenuItems;
- if (this.props.model instanceof File) {
- externalToolMenuItems = this.props.externalToolsForContext.map((tool) => {
- if (this.props.model.externalToolEnabled(tool)) {
- return (
- <li key={tool.title} role='presentation'>
- <a href={`${tool.base_url}&files[]=${this.props.model.id}`} role='menuitem' tabIndex='-1'>
- {tool.title}
- </a>
- </li>
- );
- } else {
- return (<li key={tool.title} role='presentation'><a href='#' className='disabled' role='menuitem' tabIndex='-1' aria-disabled='true'>{tool.title}</a></li>);
- }
- });
- } else {
- externalToolMenuItems = [];
- }
- var wrap = (fn, params = {}) => {
- return preventDefault((event) => {
- var singularContextType = (this.props.model.collection && this.props.model.collection.parentFolder) ?
- this.props.model.collection.parentFolder.get('context_type').toLowerCase() : null;
- var pluralContextType = (singularContextType) ? singularContextType + 's' : null
- var contextType = pluralContextType || filesEnv.contextType;
- var contextId = (this.props.model.collection && this.props.model.collection.parentFolder) ?
- this.props.model.collection.parentFolder.get('context_id') : filesEnv.contextId;
- var args = {
- contextType,
- contextId,
- returnFocusTo: ReactDOM.findDOMNode(this.refs.settingsCogBtn)
- };
- args = $.extend(args, params);
- return fn([this.props.model], args);
- });
- };
- var menuItems = [];
- // Download Link
- if (this.props.model instanceof Folder) {
- menuItems.push(<li key='folderDownload' role='presentation'><a href='#' onClick={wrap(this.downloadZip)} ref='download' role='menuitem' tabIndex='-1'>{I18n.t('Download')}</a></li>);
- } else {
- menuItems.push(<li key='download' role='presentation'><a onClick={wrap(this.downloadFile)} href={this.props.model.get('url')} ref='download' role='menuitem' tabIndex='-1'>{I18n.t('Download')}</a></li>);
- }
- if (this.props.userCanManageFilesForContext && !this.isMasterCourseRestricted()) {
- // Rename Link
- menuItems.push(<li key='rename' role='presentation'><a href='#' onClick={preventDefault(this.props.startEditingName)} ref='editName' role='menuitem' tabIndex='-1'>{I18n.t('Rename')}</a></li>);
- // Move Link
- menuItems.push(<li key='move' role='presentation'><a href='#' onClick={wrap(openMoveDialog, {clearSelectedItems: this.props.clearSelectedItems, onMove: this.props.onMove})} ref='move' role='menuitem' tabIndex='-1'>{I18n.t('Move')}</a></li>);
- if (this.props.usageRightsRequiredForContext) {
- // Manage Usage Rights Link
- menuItems.push(<li key='manageUsageRights' className='ItemCog__OpenUsageRights' role='presentation'><a href='#' onClick={preventDefault(this.openUsageRightsDialog)} ref='usageRights' role='menuitem' tabIndex='-1'>{I18n.t('Manage Usage Rights')}</a></li>);
- }
- // Delete Link
- menuItems.push(<li key='delete' role='presentation'><a href='#' onClick={wrap(this.deleteItem)} ref='deleteLink' role='menuitem' tabIndex='-1'>{I18n.t('Delete')}</a></li>);
- }
- return (
- // without the stopPropagation(), using the cog menu causes the file's invisible selection checkbox to be toggled as well
- <div className='al-dropdown__container' style={{minWidth: '45px', display: 'inline-block'}} onClick={(e) => e.stopPropagation()}>
- <button
- type='button'
- ref='settingsCogBtn'
- className='al-trigger al-trigger-gray btn btn-link'
- aria-label={I18n.t('Actions')}
- data-popup-within='#application'
- data-append-to-body={true}
- >
- <i className='icon-settings' />
- <i className='icon-mini-arrow-down' />
- </button>
- <ul className='al-options' role='menu' aria-hidden='true' aria-expanded='false' tabIndex='0'>
- {menuItems.concat(externalToolMenuItems)}
- </ul>
- </div>
- );
- }
- });
- export default ItemCog
|