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.

171 line
5.4KB

  1. import { h, Component, createRef } from 'preact';
  2. import WBNavbarCommon from 'wb-navbar-common';
  3. import WBArvadosCrumbs from 'wb-arvados-crumbs';
  4. import WBNameAndUuid from 'wb-name-and-uuid';
  5. import WBSelect from 'wb-select';
  6. import WBTable from 'wb-table';
  7. import WBPickObjectDialog from 'wb-pick-object-dialog';
  8. import makeArvadosRequest from 'make-arvados-request';
  9. class WBSharingPage extends Component {
  10. constructor(...args) {
  11. super(...args);
  12. this.state.rows = [];
  13. this.dialogRef = createRef();
  14. }
  15. componentDidMount() {
  16. this.fetchData();
  17. }
  18. fetchData() {
  19. const { app, uuid } = this.props;
  20. const { arvHost, arvToken } = app.state;
  21. let prom = makeArvadosRequest(arvHost, arvToken,
  22. '/arvados/v1/permissions/' + encodeURIComponent(uuid) +
  23. '?limit=100000');
  24. prom = prom.then(xhr => this.setState({
  25. 'entries': xhr.response.items,
  26. 'rows': this.prepareRows(xhr.response.items)
  27. }));
  28. }
  29. deleteEntry(it) {
  30. it._delete = true;
  31. this.setState({ rows: this.prepareRows(this.state.entries) });
  32. }
  33. prepareRows(items) {
  34. const { app } = this.props;
  35. return items.filter(it => (!it._delete)).map(it => [
  36. ( <WBNameAndUuid app={ app } uuid={ it.tail_uuid } /> ),
  37. ( <WBSelect value={ it.name }
  38. options={ ['can_read', 'can_write', 'can_manage'] }
  39. onChange={ e => this.modifyEntry(it, e.target.value) } /> ),
  40. ( <button class="btn btn-outline-danger m-1" title="Delete"
  41. onclick={ () => this.deleteEntry(it) }>
  42. <i class="fas fa-trash"></i>
  43. </button> )
  44. ]);
  45. }
  46. modifyEntry(it, newPermissionName) {
  47. it.name = newPermissionName;
  48. it._dirty = true;
  49. // this.setState({ rows: this.prepareRows(this.state.entries) });
  50. }
  51. addEntry(it, permissionName='can_read') {
  52. // throw Error('Not implemented');
  53. const { uuid } = this.props;
  54. let { entries } = this.state;
  55. if (entries.filter(e => (e.tail_uuid === it.uuid)).length > 0)
  56. return; // already in the list
  57. const e = {
  58. //_dirty: true,
  59. link_class: 'permission',
  60. head_uuid: uuid,
  61. tail_uuid: it.uuid,
  62. name: permissionName
  63. };
  64. entries = entries.concat([e]);
  65. this.setState({
  66. entries,
  67. rows: this.prepareRows(entries)
  68. });
  69. }
  70. disableControls() {
  71. $('input, select, button').attr('disabled', 'disabled');
  72. $('a').each(function() { $(this).data('old_href', $(this).attr('href')); });
  73. $('a').attr('href', null);
  74. }
  75. enableControls() {
  76. $('input, select, button').attr('disabled', null);
  77. $('a').each(function() { $(this).attr('href', $(this).data('old_href')); });
  78. }
  79. save() {
  80. const { entries } = this.state;
  81. const { arvHost, arvToken } = this.props.app.state;
  82. let prom = new Promise(accept => accept());
  83. this.disableControls();
  84. this.setState({ working: true });
  85. for (let i = 0; i < entries.length; i++) {
  86. const e = entries[i];
  87. //if (!e._dirty && !e._delete)
  88. //continue;
  89. if (!e.uuid) {
  90. prom = prom.then(() => makeArvadosRequest(arvHost, arvToken,
  91. '/arvados/v1/links',
  92. { 'method': 'POST',
  93. 'data': JSON.stringify({
  94. 'link_class': 'permission',
  95. 'head_uuid': e.head_uuid,
  96. 'tail_uuid': e.tail_uuid,
  97. 'name': e.name
  98. }) }));
  99. } else if (e._delete) {
  100. prom = prom.then(() => makeArvadosRequest(arvHost, arvToken,
  101. '/arvados/v1/links/' + e.uuid,
  102. { 'method': 'DELETE' }));
  103. } else if (e._dirty) {
  104. prom = prom.then(() => makeArvadosRequest(arvHost, arvToken,
  105. '/arvados/v1/links/' + e.uuid,
  106. { 'method': 'PUT',
  107. 'data': JSON.stringify({
  108. 'name': e.name
  109. }) }));
  110. }
  111. prom = prom.catch(() => {});
  112. }
  113. prom = prom.then(() => {
  114. this.enableControls();
  115. this.fetchData();
  116. this.setState({ working: false });
  117. });
  118. }
  119. render({ app, uuid }, { rows, working }) {
  120. return (
  121. <div>
  122. <WBNavbarCommon app={ app } />
  123. <WBArvadosCrumbs app={ app } uuid={ uuid } />
  124. <div class="container-fluid">
  125. <div class="my-2">
  126. This is the sharing management page for { uuid }
  127. </div>
  128. <WBTable columns={ [ 'Name', 'Permission', '' ] }
  129. headerClasses={ [ null, null, 'w-1' ] }
  130. rows={ rows } />
  131. <WBPickObjectDialog app={ app } ref={ this.dialogRef } />
  132. { working ? (<div class="progress my-2">
  133. <div class={ 'progress-bar progress-bar-striped progress-bar-animated' }
  134. role="progressbar" aria-valuenow="100" aria-valuemin="0"
  135. aria-valuemax="100" style="width: 100%"></div>
  136. </div>) : null }
  137. <button class="btn btn-outline-secondary mr-2"
  138. onclick={ () => this.dialogRef.current.show('Select User', 'user', it => this.addEntry(it)) }>Add User...</button>
  139. <button class="btn btn-outline-secondary mr-2"
  140. onclick={ () => this.dialogRef.current.show('Select Group', 'group', it => this.addEntry(it), [['group_class', '=', 'role']]) }>Add Group...</button>
  141. <button class="btn btn-primary mr-2"
  142. onclick={ () => this.save() }>Save</button>
  143. </div>
  144. </div>
  145. );
  146. }
  147. }
  148. export default WBSharingPage;