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.

232 line
8.2KB

  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 )
  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' ]
  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. }
  42. navigateBack() {
  43. if (this.state.history.length === 0)
  44. return;
  45. const url = this.state.history.pop();
  46. this.navigate(url, false);
  47. }
  48. navigate(url, useHistory=true) {
  49. if (typeof(url) === 'object') {
  50. url = ['', 'browse-dialog',
  51. 'mode' in url ? url.mode : this.state.mode,
  52. 'uuid' in url ? url.uuid : this.state.uuid,
  53. 'topPage' in url ? url.topPage : this.state.topPage,
  54. 'bottomPage' in url ? url.bottomPage : this.state.bottomPage,
  55. 'textSearch' in url ? url.textSearch : this.state.textSearch
  56. ].join('/');
  57. }
  58. url = url.substr(url.indexOf('/browse-dialog/'));
  59. if (useHistory)
  60. this.state.history.push(this.state.currentUrl);
  61. let [ _1, _2, mode, uuid, topPage, bottomPage, textSearch ] = url.split('/');
  62. topPage = parseInt(topPage, 10) || 0;
  63. bottomPage = parseInt(bottomPage, 10) || 0;
  64. this.setState({
  65. 'currentUrl': url,
  66. mode, uuid, topPage, bottomPage, textSearch
  67. });
  68. }
  69. select(uuid) {
  70. let { selected, selectedOrder } = this.state;
  71. if (uuid in selected) {
  72. const n = selectedOrder.indexOf(uuid);
  73. selectedOrder = selected.splice(n, n + 1);
  74. }
  75. selected[uuid] = true;
  76. selectedOrder.push(uuid);
  77. this.setState({
  78. selected, selectedOrder
  79. });
  80. }
  81. deselect(uuid) {
  82. let { selected, selectedOrder } = this.state;
  83. if (!(uuid in selected))
  84. return;
  85. const n = selectedOrder.indexOf(uuid);
  86. selectedOrder = selected.splice(n, n + 1);
  87. delete selected[uuid];
  88. this.setState({
  89. selected, selectedOrder
  90. });
  91. }
  92. resetSelection() {
  93. this.setState({
  94. 'selected': {},
  95. 'selectedOrder': []
  96. });
  97. }
  98. makeSelectionCell(uuid) {
  99. const { selectMany, id, accept } = this.props;
  100. const { selected } = this.state;
  101. return selectMany ? (
  102. <div>
  103. <input type="checkbox" checked={ (uuid in selected) }
  104. onChange={ e => {
  105. if (e.target.value === 'on')
  106. this.select(uuid);
  107. else
  108. this.deselect(uuid);
  109. } } /> { '\u00A0' }
  110. </div>
  111. ) : (
  112. <button class="btn btn-outline-primary" title="Use"
  113. onclick={ () => {
  114. $('#' + id).modal('hide');
  115. accept(uuid);
  116. } }>
  117. <i class="fas fa-hand-pointer"></i>
  118. </button>
  119. );
  120. }
  121. render({ app, id, selectMany, selectWhat }, { history, currentUrl, mode, uuid, topPage, bottomPage, textSearch }) {
  122. return (
  123. <div class="modal" id={ id } tabindex="-1" role="dialog">
  124. <div class="modal-dialog modal-lg" role="document">
  125. <div class="modal-content">
  126. <div class="modal-header">
  127. { false ? <h5 class="modal-title">Browse</h5> : null }
  128. <div>{ currentUrl }</div>
  129. <button type="button" class="close" data-dismiss="modal" aria-label="Close">
  130. <span aria-hidden="true">&times;</span>
  131. </button>
  132. </div>
  133. <div class="modal-body">
  134. <div class="mb-3">
  135. <a href="#" class={ 'btn btn-outline-secondary mr-2' +
  136. (history.length === 0 ? ' disabled': '') }
  137. onclick={ e => { e.preventDefault();
  138. this.navigateBack(); } }>Back</a>
  139. <a href="#" class="btn btn-outline-primary mr-2"
  140. onclick={ e => { e.preventDefault();
  141. this.navigate('/browse-dialog/browse/' + app.state.currentUser.uuid); } }>Home</a>
  142. <a href="#" class="btn btn-outline-primary mr-2"
  143. onclick={ e => { e.preventDefault();
  144. this.navigate('/browse-dialog/browse'); } }>All Projects</a>
  145. <a href="#" class="btn btn-outline-primary mr-2"
  146. onclick={ e => { e.preventDefault();
  147. this.navigate('/browse-dialog/users'); } }>All Users</a>
  148. <a href="#" class="btn btn-outline-primary mr-2"
  149. onclick={ e => { e.preventDefault();
  150. this.navigate('/browse-dialog/shared-with-me'); } }>Shared with Me</a>
  151. </div>
  152. <div class="input-group mb-3">
  153. <input type="text" class="form-control" placeholder="Search"
  154. aria-label="Search" value={ textSearch }
  155. onChange={ e => this.navigate({
  156. 'textSearch': e.target.value,
  157. 'topPage': 0,
  158. 'bottomPage': 0}) } />
  159. <div class="input-group-append">
  160. <button class="btn btn-outline-primary" type="button">Search</button>
  161. </div>
  162. </div>
  163. { (mode === 'browse' || mode === 'shared-with-me') ? (
  164. <div>
  165. <h5>Projects</h5>
  166. <WBBrowseDialogProjectList app={ app }
  167. navigate={ url => this.navigate(url) }
  168. mode={ mode } ownerUuid={ uuid }
  169. page={ topPage } textSearch={ textSearch }
  170. selectWhat={ selectWhat }
  171. makeSelectionCell={ uuid => this.makeSelectionCell(uuid) } />
  172. </div>
  173. ) : null }
  174. { (mode === 'users') ? (
  175. <WBBrowseDialogUserList app={ app }
  176. navigate={ url => this.navigate(url) }
  177. page={ topPage } textSearch={ textSearch }/>
  178. ) : null }
  179. { (mode === 'content') ? (
  180. <div>
  181. <h5>Content</h5>
  182. <WBBrowseDialogCollectionContent app={ app } parent={ this }
  183. selectMany={ selectMany } selectWhat={ selectWhat }/>
  184. </div>
  185. ) : (selectWhat !== 'owner' && mode === 'browse') ? (
  186. <div>
  187. <h5>Collections</h5>
  188. <WBBrowseDialogCollectionList app={ app }
  189. page={ bottomPage } textSearch={ textSearch }
  190. navigate={ url => this.navigate(url) }
  191. ownerUuid={ uuid } selectWhat={ selectWhat }
  192. makeSelectionCell={ uuid => this.makeSelectionCell(uuid) } />
  193. </div>
  194. ) : null }
  195. </div>
  196. <div class="modal-footer">
  197. <button type="button" class="btn btn-primary">Accept</button>
  198. <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
  199. </div>
  200. </div>
  201. </div>
  202. </div>
  203. );
  204. }
  205. }
  206. WBBrowseDialog.defaultProps = {
  207. 'accept': () => {}
  208. };
  209. export default WBBrowseDialog;