FilesApp.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * Copyright (C) 2015 - present Instructure, Inc.
  3. *
  4. * This file is part of Canvas.
  5. *
  6. * Canvas is free software: you can redistribute it and/or modify it under
  7. * the terms of the GNU Affero General Public License as published by the Free
  8. * Software Foundation, version 3 of the License.
  9. *
  10. * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
  11. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  13. * details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License along
  16. * with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. import $ from 'jquery'
  19. import React from 'react'
  20. import ReactModal from 'react-modal'
  21. import page from 'page'
  22. import FilesApp from 'compiled/react_files/components/FilesApp'
  23. import filesEnv from 'compiled/react_files/modules/filesEnv'
  24. import I18n from 'i18n!react_files'
  25. import Breadcrumbs from 'jsx/files/Breadcrumbs'
  26. import FolderTree from 'jsx/files/FolderTree'
  27. import FilesUsage from 'jsx/files/FilesUsage'
  28. import Toolbar from 'jsx/files/Toolbar'
  29. const modalOverrides = {
  30. overlay : {
  31. backgroundColor: 'rgba(0,0,0,0.5)'
  32. },
  33. content : {
  34. position: 'static',
  35. top: '0',
  36. left: '0',
  37. right: 'auto',
  38. bottom: 'auto',
  39. borderRadius: '0',
  40. border: 'none',
  41. padding: '0'
  42. }
  43. };
  44. FilesApp.previewItem = function (item) {
  45. this.clearSelectedItems(() => {
  46. this.toggleItemSelected(item, null, () => {
  47. const queryString = $.param(this.getPreviewQuery());
  48. page(`${this.getPreviewRoute()}?${queryString}`);
  49. });
  50. });
  51. };
  52. FilesApp.getPreviewRoute = function () {
  53. if (this.props.query && this.props.query.search_term) {
  54. return '/search';
  55. } else if (this.props.splat) {
  56. return `/folder/${this.props.splat}`;
  57. } else {
  58. return '';
  59. }
  60. };
  61. FilesApp.render = function () {
  62. var contextType;
  63. var contextId;
  64. // when showing a folder
  65. if (this.state.currentFolder) {
  66. contextType = this.state.currentFolder.get('context_type').toLowerCase() + 's';
  67. contextId = this.state.currentFolder.get('context_id');
  68. } else {
  69. // when showing search results
  70. contextType = filesEnv.contextType;
  71. contextId = filesEnv.contextId;
  72. }
  73. var userCanManageFilesForContext = filesEnv.userHasPermission({contextType: contextType, contextId: contextId}, 'manage_files');
  74. var userCanRestrictFilesForContext = userCanManageFilesForContext && contextType != "groups";
  75. var usageRightsRequiredForContext = (filesEnv.contextsDictionary[`${contextType}_${contextId}`]) ?
  76. filesEnv.contextsDictionary[`${contextType}_${contextId}`].usage_rights_required : false;
  77. var externalToolsForContext = (filesEnv.contextFor({contextType: contextType, contextId: contextId})) ?
  78. filesEnv.contextFor({contextType: contextType, contextId: contextId}).file_menu_tools : [];
  79. return (
  80. <div>
  81. {/* For whatever reason, VO in Safari didn't like just the h1 tag.
  82. Sometimes it worked, others it didn't, this makes it work always */}
  83. <header>
  84. <h1 className='screenreader-only'>
  85. {I18n.t('Files')}
  86. </h1>
  87. </header>
  88. <div className='ic-app-nav-toggle-and-crumbs ic-app-nav-toggle-and-crumbs--files no-print'>
  89. <button
  90. className='Button Button--link ic-app-course-nav-toggle'
  91. type='button'
  92. id='courseMenuToggle'
  93. title={I18n.t("Show and hide courses menu")}
  94. aria-hidden={true}
  95. >
  96. <i className='icon-hamburger' aria-hidden='true' />
  97. </button>
  98. <div className='ic-app-crumbs'>
  99. <Breadcrumbs
  100. rootTillCurrentFolder={this.state.rootTillCurrentFolder}
  101. showingSearchResults={this.state.showingSearchResults}
  102. query={this.props.query}
  103. contextAssetString={this.props.contextAssetString}
  104. />
  105. </div>
  106. <div className="TutorialToggleHolder" />
  107. </div>
  108. <Toolbar
  109. currentFolder={this.state.currentFolder}
  110. query={this.props.query}
  111. selectedItems={this.state.selectedItems}
  112. clearSelectedItems={this.clearSelectedItems}
  113. onMove={this.onMove}
  114. contextType={contextType}
  115. contextId={contextId}
  116. userCanManageFilesForContext={userCanManageFilesForContext}
  117. usageRightsRequiredForContext={usageRightsRequiredForContext}
  118. userCanRestrictFilesForContext={userCanRestrictFilesForContext}
  119. getPreviewQuery={this.getPreviewQuery}
  120. getPreviewRoute={this.getPreviewRoute}
  121. modalOptions={{
  122. openModal: this.openModal,
  123. closeModal: this.closeModal
  124. }}
  125. />
  126. <div className='ef-main'>
  127. {filesEnv.newFolderTree && (
  128. <p>New folder tree goes here</p>
  129. )}
  130. {!filesEnv.newFolderTree && (
  131. <aside
  132. className='visible-desktop ef-folder-content'
  133. role='region'
  134. aria-label={I18n.t('Folder Browsing Tree')}
  135. >
  136. <FolderTree
  137. rootTillCurrentFolder={this.state.rootTillCurrentFolder}
  138. rootFoldersToShow={filesEnv.rootFolders}
  139. dndOptions={{
  140. onItemDragEnterOrOver: this.onItemDragEnterOrOver,
  141. onItemDragLeaveOrEnd: this.onItemDragLeaveOrEnd,
  142. onItemDrop: this.onItemDrop
  143. }}
  144. />
  145. </aside>
  146. )}
  147. <div
  148. className='ef-directory'
  149. role='region'
  150. aria-label={I18n.t('File List')}
  151. >
  152. {React.cloneElement(this.props.children, {
  153. key: this.state.key,
  154. pathname: this.props.pathname,
  155. splat: this.props.splat,
  156. query: this.props.query,
  157. params: this.props.params,
  158. onResolvePath: this.onResolvePath,
  159. currentFolder: this.state.currentFolder,
  160. contextType: contextType,
  161. contextId: contextId,
  162. selectedItems: this.state.selectedItems,
  163. toggleItemSelected: this.toggleItemSelected,
  164. toggleAllSelected: this.toggleAllSelected,
  165. areAllItemsSelected: this.areAllItemsSelected,
  166. userCanManageFilesForContext: userCanManageFilesForContext,
  167. userCanRestrictFilesForContext: userCanRestrictFilesForContext,
  168. usageRightsRequiredForContext: usageRightsRequiredForContext,
  169. externalToolsForContext: externalToolsForContext,
  170. previewItem: this.previewItem,
  171. onMove: this.onMove,
  172. modalOptions: {
  173. openModal: this.openModal,
  174. closeModal: this.closeModal
  175. },
  176. dndOptions: {
  177. onItemDragStart: this.onItemDragStart,
  178. onItemDragEnterOrOver: this.onItemDragEnterOrOver,
  179. onItemDragLeaveOrEnd: this.onItemDragLeaveOrEnd,
  180. onItemDrop: this.onItemDrop
  181. },
  182. clearSelectedItems: this.clearSelectedItems
  183. })}
  184. </div>
  185. </div>
  186. <div className='ef-footer grid-row'>
  187. {userCanManageFilesForContext && (
  188. <FilesUsage
  189. className='col-xs-4'
  190. contextType={contextType}
  191. contextId={contextId}
  192. />
  193. )}
  194. {(!filesEnv.showingAllContexts) && (
  195. <div className='col-xs'>
  196. <div>
  197. <a className='pull-right' href='/files'>
  198. {I18n.t('All My Files')}
  199. </a>
  200. </div>
  201. </div>
  202. )}
  203. </div>
  204. {this.state.showingModal && (
  205. <ReactModal
  206. isOpen={this.state.showingModal}
  207. onRequestClose={this.closeModal}
  208. closeTimeoutMS={10}
  209. className='ReactModal__Content--canvas'
  210. overlayClassName='ReactModal__Overlay--canvas'
  211. style={modalOverrides}
  212. >
  213. {this.state.modalContents}
  214. </ReactModal>
  215. )}
  216. </div>
  217. );
  218. };
  219. export default React.createClass(FilesApp)