IF YOU WOULD LIKE TO GET AN ACCOUNT, please write an email to s dot adaszewski at gmail dot com. User accounts are meant only to report issues and/or generate pull requests. This is a purpose-specific Git hosting for ADARED projects. Thank you for your understanding!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

249 lines
9.1KB

  1. import { h, Component, createRef } from 'preact';
  2. import { route } from 'preact-router';
  3. import WBNavbarCommon from 'wb-navbar-common';
  4. import WBProjectListing from 'wb-project-listing';
  5. import WBInlineSearch from 'wb-inline-search';
  6. import WBArvadosCrumbs from 'wb-arvados-crumbs';
  7. import WBTabs from 'wb-tabs';
  8. import WBProcessListing from 'wb-process-listing';
  9. import WBCollectionListing from 'wb-collection-listing';
  10. import WBWorkflowListing from 'wb-workflow-listing';
  11. import WBRenameDialog from 'wb-rename-dialog';
  12. import WBDeleteDialog from 'wb-delete-dialog';
  13. import WBNewProjectDialog from 'wb-new-project-dialog';
  14. import WBEditDescriptionDialog from 'wb-edit-description-dialog';
  15. import wbMoveObject from 'wb-move-object';
  16. import wbCopyCollection from 'wb-copy-collection';
  17. import arvadosTypeName from 'arvados-type-name';
  18. class WBBrowseProjectTabs extends Component {
  19. render({ ownerUuid, selected, newProjectDialogRef, projectListingRef,
  20. moveHere, copyHere }) {
  21. return (
  22. <WBTabs tabs={ [
  23. { 'name': 'Projects', 'isActive': true },
  24. ownerUuid ? { 'name': ( <span><i class="fas fa-plus-square text-success"></i> New Project</span> ),
  25. 'onClick': () => newProjectDialogRef.current.show(ownerUuid,
  26. () => projectListingRef.current.fetchItems() ) } : null,
  27. ( ownerUuid && Object.keys(selected).length > 0 ) ?
  28. { 'name': ( <span><i class="fas fa-compress-arrows-alt text-warning"></i> Move Here</span> ),
  29. 'onClick': moveHere } : null,
  30. ( ownerUuid && (uuids => uuids.length > 0 && uuids.length ===
  31. uuids.map(arvadosTypeName).filter(a => (a === 'collection')).length )(Object.keys(selected)) ) ?
  32. { 'name': ( <span><i class="fas fa-file-import text-warning"></i> Copy Here</span> ),
  33. 'onClick': copyHere } : null
  34. ] } />
  35. );
  36. }
  37. }
  38. class WBBrowse extends Component {
  39. constructor(...args) {
  40. super(...args);
  41. this.renameDialogRef = createRef();
  42. this.deleteDialogRef = createRef();
  43. this.newProjectDialogRef = createRef();
  44. this.projectListingRef = createRef();
  45. this.projectTabsRef = createRef();
  46. this.editDescriptionDialogRef = createRef();
  47. this.state.selected = {};
  48. }
  49. getUrl(params) {
  50. const mode = ('mode' in params ? params.mode : this.props.mode);
  51. if (mode === 'shared-with-me')
  52. return '/shared-with-me/' +
  53. ('activePage' in params ? params.activePage : (this.props.activePage || '')) + '/' +
  54. ('textSearch' in params ? params.textSearch : (this.props.textSearch || ''));
  55. let res = '/browse/' +
  56. ('ownerUuid' in params ? params.ownerUuid : (this.props.ownerUuid || '')) + '/' +
  57. ('activePage' in params ? params.activePage : (this.props.activePage || '')) + '/' +
  58. ('objTypeTab' in params ? params.objTypeTab : (this.props.objTypeTab || '')) + '/' +
  59. ('collectionPage' in params ? params.collectionPage : (this.props.collectionPage || '')) + '/' +
  60. ('processPage' in params ? params.processPage : (this.props.processPage || '')) + '/' +
  61. ('workflowPage' in params ? params.workflowPage : (this.props.workflowPage || '')) + '/' +
  62. encodeURIComponent('textSearch' in params ? params.textSearch : (this.props.textSearch || ''));
  63. return res;
  64. }
  65. route(params) {
  66. route(this.getUrl(params));
  67. }
  68. renameDialog(item, callback) {
  69. // throw Error('Not implemented');
  70. this.renameDialogRef.current.show(item, callback);
  71. }
  72. renderRenameLink(item, callback) {
  73. return (
  74. <a href="#" title="Rename" onclick={ e => { e.preventDefault(); this.renameDialog(item, callback); } }>
  75. <i class="fas fa-edit text-secondary"></i>
  76. </a>
  77. );
  78. }
  79. renderEditDescription(item, callback) {
  80. return (
  81. <a href="#" title="Edit description" onclick={ e => { e.preventDefault();
  82. this.editDescriptionDialogRef.current.show(item, callback); } }>
  83. <i class="fas fa-edit text-secondary"></i>
  84. </a>
  85. );
  86. }
  87. renderDeleteButton(item, callback) {
  88. return (
  89. <button class="btn btn-outline-danger m-1" title="Delete"
  90. onclick={ () => this.deleteDialogRef.current.show(item, callback) }>
  91. <i class="fas fa-trash"></i>
  92. </button>
  93. );
  94. }
  95. renderSelectionCell(item) {
  96. const { selected } = this.state;
  97. const { uuid } = item;
  98. return (
  99. <div>
  100. <input type="checkbox" checked={ (uuid in selected) }
  101. onChange={ e => {
  102. if (e.target.checked)
  103. selected[uuid] = true;
  104. else
  105. delete selected[uuid];
  106. this.projectTabsRef.current.setState({});
  107. } } /> { '\u00A0' }
  108. </div>
  109. );
  110. }
  111. renderSharingButton(item) {
  112. return (
  113. <a class="btn btn-outline-success m-1" title="Share"
  114. href={ '/sharing/' + item.uuid }>
  115. <i class="fas fa-share-alt"></i>
  116. </a>
  117. );
  118. }
  119. moveOrCopyOp(op) {
  120. const { ownerUuid, app } = this.props;
  121. const { selected } = this.state;
  122. const { arvHost, arvToken } = app.state;
  123. let prom = new Promise(accept => accept());
  124. const uuids = Object.keys(selected);
  125. for (let i = 0; i < uuids.length; i++) {
  126. prom = prom.then(() => op(arvHost, arvToken, uuids[i], ownerUuid));
  127. prom = prom.then(() => ( delete selected[uuids[i]] ));
  128. prom = prom.catch(() => {});
  129. }
  130. prom = prom.then(() => this.setState({}));
  131. }
  132. moveHere() {
  133. this.moveOrCopyOp(wbMoveObject);
  134. }
  135. copyHere() {
  136. this.moveOrCopyOp(wbCopyCollection);
  137. }
  138. render({ mode, ownerUuid, activePage, app,
  139. objTypeTab, collectionPage, processPage, workflowPage,
  140. textSearch }, { selected }) {
  141. const commonProps = {
  142. renderRenameLink: (it, cb) => this.renderRenameLink(it, cb),
  143. renderEditDescription: (it, cb) => this.renderEditDescription(it, cb),
  144. renderDeleteButton: (it, cb) => this.renderDeleteButton(it, cb),
  145. renderSelectionCell: it => this.renderSelectionCell(it),
  146. renderSharingButton: it => this.renderSharingButton(it),
  147. textSearch,
  148. app,
  149. appState: app.state,
  150. arvHost: app.state.arvHost,
  151. arvToken: app.state.arvToken,
  152. ownerUuid
  153. };
  154. const { currentUser } = app.state;
  155. const atHome = (ownerUuid === currentUser.uuid);
  156. return (
  157. <div>
  158. <WBRenameDialog app={ app } ref={ this.renameDialogRef } />
  159. <WBDeleteDialog app={ app } ref={ this.deleteDialogRef } />
  160. <WBNewProjectDialog app={ app } ref={ this.newProjectDialogRef } />
  161. <WBEditDescriptionDialog app={ app } ref={ this.editDescriptionDialogRef } />
  162. <WBNavbarCommon app={ app }
  163. activeItem={ mode === 'shared-with-me' ? 'shared-with-me' :
  164. (!ownerUuid) ? 'all-projects' :
  165. (ownerUuid === app.state.currentUser.uuid) ? 'home' : null }
  166. textSearch={ textSearch }
  167. textSearchNavigate={ textSearch => route(this.getUrl({ textSearch,
  168. activePage: 0, collectionPage: 0, processPage: 0, workflowPage: 0 })) } />
  169. <WBArvadosCrumbs mode={ mode } uuid={ ownerUuid } app={ app } />
  170. <WBBrowseProjectTabs ref={ this.projectTabsRef } ownerUuid={ ownerUuid }
  171. selected={ selected } newProjectDialogRef={ this.newProjectDialogRef }
  172. projectListingRef={ this.projectListingRef } moveHere={ () => this.moveHere() }
  173. copyHere={ () => this.copyHere() } />
  174. <WBProjectListing ref={ this.projectListingRef }
  175. mode={ mode }
  176. itemsPerPage="5"
  177. activePage={ Number(activePage || 0) }
  178. getPageUrl={ i => this.getUrl({ 'activePage': i }) }
  179. { ...commonProps } />
  180. { (mode !== 'browse') ? null : (
  181. <WBTabs tabs={ [
  182. { 'id': 'collection', 'name': 'Collections', 'isActive': ((!objTypeTab && !atHome) || objTypeTab === 'collection') },
  183. { 'id': 'process', 'name': 'Processes', 'isActive': (objTypeTab === 'process') },
  184. { 'id': 'workflow', 'name': 'Workflows', 'isActive': (objTypeTab === 'workflow') } ] }
  185. onTabChanged={ tab => this.route({ 'objTypeTab': tab['id'] }) } />
  186. ) }
  187. {
  188. (mode !== 'browse') ? null :
  189. ((!objTypeTab && !atHome) || objTypeTab === 'collection') ? (
  190. <WBCollectionListing
  191. itemsPerPage="20"
  192. activePage={ Number(collectionPage || 0) }
  193. getPageUrl={ i => this.getUrl({ 'collectionPage': i }) }
  194. { ...commonProps } />
  195. ) : (objTypeTab === 'process') ? (
  196. <WBProcessListing
  197. itemsPerPage="20"
  198. activePage={ Number(processPage || 0) }
  199. onPageChanged={ i => this.route({ 'processPage': i }) }
  200. { ...commonProps } />
  201. ) : (objTypeTab === 'workflow') ? (
  202. <WBWorkflowListing
  203. itemsPerPage="20"
  204. page={ Number(workflowPage || 0) }
  205. getPageUrl={ i => this.getUrl({ 'workflowPage': i }) }
  206. { ...commonProps } />
  207. ) : null
  208. }
  209. </div>
  210. );
  211. }
  212. }
  213. export default WBBrowse;