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.

258 lines
9.4KB

  1. import { h, Component } from 'preact';
  2. import WBBrowseDialogProjectList from 'wb-browse-dialog-project-list';
  3. import WBBrowseDialogCollectionList from 'wb-browse-dialog-collection-list';
  4. import WBBrowseDialogCollectionContent from 'wb-browse-dialog-collection-content';
  5. import WBBrowseDialogUserList from 'wb-browse-dialog-user-list';
  6. import linkState from 'linkstate';
  7. import { Router } from 'preact-router';
  8. import { createHashHistory } from 'history';
  9. //
  10. // internal URLs look like this
  11. //
  12. // /browse-dialog/browse/( owner-uuid )/( project-page )/( text-search )
  13. // /browse-dialog/users//( users-page )/( text-search )
  14. // /browse-dialog/shared-with-me//( project-page )/( collection-page )/( text-search )
  15. // /browse-dialog/content/( collection-uuid )//( content-page )/( text-search )/( collection-path )
  16. //
  17. // general pattern therefore:
  18. // /browse-dialog/( mode )/( uuid )/( top-page )/( bottom-page )/( text-search )
  19. //
  20. // props:
  21. // selectMany: Boolean
  22. // selectWhat: [ 'file', 'directory', 'owner' ]
  23. //
  24. // state:
  25. // selected: Array of UUID
  26. // textSearch: string
  27. // textSearchInput: string
  28. //
  29. class WBBrowseDialog extends Component {
  30. constructor(...args) {
  31. super(...args);
  32. this.state.history = [];
  33. this.state.selected = {};
  34. this.state.selectedOrder = [];
  35. const { currentUser } = this.props.app.state;
  36. this.state.currentUrl = '/browse-dialog/browse/' + currentUser.uuid;
  37. this.state.uuid = currentUser.uuid;
  38. this.state.mode = 'browse';
  39. this.state.topPage = 0;
  40. this.state.bottomPage = 0;
  41. this.state.collectionPath = '';
  42. this.state.textSearch = '';
  43. this.state.id = ('id' in this.props) ? this.props.id : uuid.v4();
  44. this.state.accept = () => {};
  45. }
  46. navigateBack() {
  47. if (this.state.history.length === 0)
  48. return;
  49. const url = this.state.history.pop();
  50. this.navigate(url, false);
  51. }
  52. navigate(url, useHistory=true, stateUpdate={}) {
  53. if (typeof(url) === 'object') {
  54. url = ['', 'browse-dialog',
  55. 'mode' in url ? url.mode : this.state.mode,
  56. 'uuid' in url ? url.uuid : this.state.uuid,
  57. 'topPage' in url ? url.topPage : this.state.topPage,
  58. 'bottomPage' in url ? url.bottomPage : this.state.bottomPage,
  59. 'textSearch' in url ? url.textSearch : this.state.textSearch,
  60. encodeURIComponent('collectionPath' in url ? url.collectionPath : this.state.collectionPath)
  61. ].join('/');
  62. }
  63. url = url.substr(url.indexOf('/browse-dialog/'));
  64. if (useHistory)
  65. this.state.history.push(this.state.currentUrl);
  66. let [ _1, _2, mode, uuid, topPage, bottomPage, textSearch, collectionPath ] = url.split('/');
  67. topPage = parseInt(topPage, 10) || 0;
  68. bottomPage = parseInt(bottomPage, 10) || 0;
  69. collectionPath = decodeURIComponent(collectionPath || '');
  70. this.setState(Object.assign({
  71. 'currentUrl': url,
  72. mode, uuid, topPage, bottomPage, textSearch, collectionPath
  73. }, stateUpdate));
  74. }
  75. select(uuid) {
  76. let { selected, selectedOrder } = this.state;
  77. if (uuid in selected) {
  78. const n = selectedOrder.indexOf(uuid);
  79. selectedOrder = selected.splice(n, n + 1);
  80. }
  81. selected[uuid] = true;
  82. selectedOrder.push(uuid);
  83. /* this.setState({
  84. selected, selectedOrder
  85. }); */
  86. }
  87. deselect(uuid) {
  88. let { selected, selectedOrder } = this.state;
  89. if (!(uuid in selected))
  90. return;
  91. const n = selectedOrder.indexOf(uuid);
  92. selectedOrder = selected.splice(n, n + 1);
  93. delete selected[uuid];
  94. /* this.setState({
  95. selected, selectedOrder
  96. }); */
  97. }
  98. resetSelection() {
  99. this.setState({
  100. 'selected': {},
  101. 'selectedOrder': []
  102. });
  103. }
  104. makeSelectionCell(uuid) {
  105. const { selected, accept, selectMany, id } = this.state;
  106. return selectMany ? (
  107. <div>
  108. <input type="checkbox" checked={ (uuid in selected) }
  109. onChange={ e => {
  110. if (e.target.checked)
  111. this.select(uuid);
  112. else
  113. this.deselect(uuid);
  114. } } /> { '\u00A0' }
  115. </div>
  116. ) : (
  117. <button class="btn btn-outline-primary" title="Use"
  118. onclick={ () => {
  119. $('#' + id).modal('hide');
  120. accept(uuid);
  121. } }>
  122. <i class="fas fa-hand-pointer"></i>
  123. </button>
  124. );
  125. }
  126. show(selectWhat, selectMany, accept=(() => {})) {
  127. const { app } = this.props;
  128. const { currentUser } = app.state;
  129. this.navigate('/browse-dialog/browse/' + currentUser.uuid, false,
  130. { selectWhat, selectMany, accept, history: [],
  131. selected: {}, selectedOrder: [] });
  132. $('#' + this.state.id).modal();
  133. }
  134. render({ app },
  135. { history, currentUrl, mode, uuid,
  136. topPage, bottomPage, textSearch,
  137. collectionPath, id, accept, selectedOrder,
  138. selectMany, selectWhat }) {
  139. return (
  140. <div class="modal" id={ id } tabindex="-1" role="dialog">
  141. <div class="modal-dialog modal-lg" role="document">
  142. <div class="modal-content">
  143. <div class="modal-header">
  144. { false ? <h5 class="modal-title">Browse</h5> : null }
  145. <div>{ currentUrl }</div>
  146. <button type="button" class="close" data-dismiss="modal" aria-label="Close">
  147. <span aria-hidden="true">&times;</span>
  148. </button>
  149. </div>
  150. <div class="modal-body">
  151. <div class="mb-3">
  152. <a href="#" class={ 'btn btn-outline-secondary mr-2' +
  153. (history.length === 0 ? ' disabled': '') }
  154. onclick={ e => { e.preventDefault();
  155. this.navigateBack(); } }>Back</a>
  156. <a href="#" class="btn btn-outline-primary mr-2"
  157. onclick={ e => { e.preventDefault();
  158. this.navigate('/browse-dialog/browse/' + app.state.currentUser.uuid); } }>Home</a>
  159. <a href="#" class="btn btn-outline-primary mr-2"
  160. onclick={ e => { e.preventDefault();
  161. this.navigate('/browse-dialog/browse'); } }>All Projects</a>
  162. <a href="#" class="btn btn-outline-primary mr-2"
  163. onclick={ e => { e.preventDefault();
  164. this.navigate('/browse-dialog/users'); } }>All Users</a>
  165. <a href="#" class="btn btn-outline-primary mr-2"
  166. onclick={ e => { e.preventDefault();
  167. this.navigate('/browse-dialog/shared-with-me'); } }>Shared with Me</a>
  168. </div>
  169. <div class="input-group mb-3">
  170. <input type="text" class="form-control" placeholder="Search"
  171. aria-label="Search" value={ textSearch }
  172. onChange={ e => this.navigate({
  173. 'textSearch': e.target.value,
  174. 'topPage': 0,
  175. 'bottomPage': 0}) } />
  176. <div class="input-group-append">
  177. <button class="btn btn-outline-primary" type="button">Search</button>
  178. </div>
  179. </div>
  180. { (mode === 'browse' || mode === 'shared-with-me') ? (
  181. <div>
  182. <h5>Projects</h5>
  183. <WBBrowseDialogProjectList app={ app }
  184. navigate={ url => this.navigate(url) }
  185. mode={ mode } ownerUuid={ uuid }
  186. page={ topPage } textSearch={ textSearch }
  187. selectWhat={ selectWhat }
  188. makeSelectionCell={ uuid => this.makeSelectionCell(uuid) } />
  189. </div>
  190. ) : null }
  191. { (mode === 'users') ? (
  192. <WBBrowseDialogUserList app={ app }
  193. navigate={ url => this.navigate(url) }
  194. page={ topPage } textSearch={ textSearch }/>
  195. ) : null }
  196. { (mode === 'content') ? (
  197. <div>
  198. <h5>Content</h5>
  199. <WBBrowseDialogCollectionContent app={ app }
  200. collectionUuid={ uuid } collectionPath={ collectionPath }
  201. page={ bottomPage } selectWhat={ selectWhat }
  202. makeSelectionCell={ uuid => this.makeSelectionCell(uuid) }
  203. navigate={ url => this.navigate(url) }
  204. textSearch={ textSearch } />
  205. </div>
  206. ) : (selectWhat !== 'owner' && mode === 'browse') ? (
  207. <div>
  208. <h5>Collections</h5>
  209. <WBBrowseDialogCollectionList app={ app }
  210. page={ bottomPage } textSearch={ textSearch }
  211. navigate={ url => this.navigate(url) }
  212. ownerUuid={ uuid } selectWhat={ selectWhat }
  213. makeSelectionCell={ uuid => this.makeSelectionCell(uuid) } />
  214. </div>
  215. ) : null }
  216. </div>
  217. <div class="modal-footer">
  218. { selectMany ? (
  219. <button type="button" class="btn btn-primary"
  220. onclick={ e => { e.preventDefault(); accept(selectedOrder); $('#' + id).modal('hide'); } }>Accept</button>
  221. ) : null }
  222. <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
  223. </div>
  224. </div>
  225. </div>
  226. </div>
  227. );
  228. }
  229. }
  230. WBBrowseDialog.defaultProps = {
  231. 'accept': () => {}
  232. };
  233. export default WBBrowseDialog;