mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-04 12:22:47 +00:00 
			
		
		
		
	Merge branch 'public-corpus' of gitlab.ub.uni-bielefeld.de:sfb1288inf/nopaque into public-corpus
This commit is contained in:
		@@ -54,6 +54,7 @@ def corpus(corpus_id):
 | 
				
			|||||||
    # TODO: Better solution for filtering admin
 | 
					    # TODO: Better solution for filtering admin
 | 
				
			||||||
    users = User.query.filter(User.is_public == True, User.id != current_user.id, User.id != corpus.user.id, User.role_id < 4).all()
 | 
					    users = User.query.filter(User.is_public == True, User.id != current_user.id, User.id != corpus.user.id, User.role_id < 4).all()
 | 
				
			||||||
    cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first()
 | 
					    cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first()
 | 
				
			||||||
 | 
					    cfas = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id).all()
 | 
				
			||||||
    if cfa is None:
 | 
					    if cfa is None:
 | 
				
			||||||
        if corpus.user == current_user or current_user.is_administrator():
 | 
					        if corpus.user == current_user or current_user.is_administrator():
 | 
				
			||||||
            cfr = CorpusFollowerRole.query.filter_by(name='Administrator').first()
 | 
					            cfr = CorpusFollowerRole.query.filter_by(name='Administrator').first()
 | 
				
			||||||
@@ -61,14 +62,29 @@ def corpus(corpus_id):
 | 
				
			|||||||
            cfr = CorpusFollowerRole.query.filter_by(name='Anonymous').first()
 | 
					            cfr = CorpusFollowerRole.query.filter_by(name='Anonymous').first()
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        cfr = cfa.role
 | 
					        cfr = cfa.role
 | 
				
			||||||
    return render_template(
 | 
					    if corpus.user == current_user or current_user.is_administrator():
 | 
				
			||||||
        'corpora/corpus.html.j2',
 | 
					        return render_template(
 | 
				
			||||||
        title=corpus.title,
 | 
					            'corpora/corpus.html.j2',
 | 
				
			||||||
        corpus=corpus,
 | 
					            title=corpus.title,
 | 
				
			||||||
        cfrs=cfrs,
 | 
					            corpus=corpus,
 | 
				
			||||||
        cfr=cfr,
 | 
					            cfr=cfr,
 | 
				
			||||||
        users = users
 | 
					            cfrs=cfrs,
 | 
				
			||||||
    )
 | 
					            users = users
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    if (current_user.is_following_corpus(corpus) or corpus.is_public):
 | 
				
			||||||
 | 
					        cfas = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id).all()
 | 
				
			||||||
 | 
					        return render_template(
 | 
				
			||||||
 | 
					            'corpora/public_corpus.html.j2',
 | 
				
			||||||
 | 
					            title=corpus.title,
 | 
				
			||||||
 | 
					            corpus=corpus,
 | 
				
			||||||
 | 
					            cfrs=cfrs,
 | 
				
			||||||
 | 
					            cfr=cfr,
 | 
				
			||||||
 | 
					            cfas=cfas,
 | 
				
			||||||
 | 
					            cfa=cfa,
 | 
				
			||||||
 | 
					            users = users
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    abort(403)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@bp.route('/<hashid:corpus_id>/analysis')
 | 
					@bp.route('/<hashid:corpus_id>/analysis')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,11 @@ class CorpusFileList extends ResourceList {
 | 
				
			|||||||
  constructor(listContainerElement, options = {}) {
 | 
					  constructor(listContainerElement, options = {}) {
 | 
				
			||||||
    super(listContainerElement, options);
 | 
					    super(listContainerElement, options);
 | 
				
			||||||
    this.listjs.list.addEventListener('click', (event) => {this.onClick(event)});
 | 
					    this.listjs.list.addEventListener('click', (event) => {this.onClick(event)});
 | 
				
			||||||
 | 
					    document.querySelectorAll('.selection-action-trigger[data-selection-action]').forEach((element) => {
 | 
				
			||||||
 | 
					      element.addEventListener('click', (event) => {this.onSelectionAction(event)});
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
    this.isInitialized = false;
 | 
					    this.isInitialized = false;
 | 
				
			||||||
 | 
					    this.selectedItemIds = [];
 | 
				
			||||||
    this.userId = listContainerElement.dataset.userId;
 | 
					    this.userId = listContainerElement.dataset.userId;
 | 
				
			||||||
    this.corpusId = listContainerElement.dataset.corpusId;
 | 
					    this.corpusId = listContainerElement.dataset.corpusId;
 | 
				
			||||||
    this.hasPermissionView =  listContainerElement.dataset?.hasPermissionView == 'true' || false;
 | 
					    this.hasPermissionView =  listContainerElement.dataset?.hasPermissionView == 'true' || false;
 | 
				
			||||||
@@ -29,6 +33,12 @@ class CorpusFileList extends ResourceList {
 | 
				
			|||||||
    return (values) => {
 | 
					    return (values) => {
 | 
				
			||||||
      return `
 | 
					      return `
 | 
				
			||||||
        <tr class="list-item">
 | 
					        <tr class="list-item">
 | 
				
			||||||
 | 
					          <td>
 | 
				
			||||||
 | 
					            <label class="list-action-trigger ${this.hasPermissionView ? '' : 'hide'}" data-list-action="select">
 | 
				
			||||||
 | 
					              <input type="checkbox">
 | 
				
			||||||
 | 
					              <span class="disable-on-click"></span>
 | 
				
			||||||
 | 
					            </label>
 | 
				
			||||||
 | 
					          </td>
 | 
				
			||||||
          <td><span class="filename"></span></td>
 | 
					          <td><span class="filename"></span></td>
 | 
				
			||||||
          <td><span class="author"></span></td>
 | 
					          <td><span class="author"></span></td>
 | 
				
			||||||
          <td><span class="title"></span></td>
 | 
					          <td><span class="title"></span></td>
 | 
				
			||||||
@@ -68,11 +78,20 @@ class CorpusFileList extends ResourceList {
 | 
				
			|||||||
      <table>
 | 
					      <table>
 | 
				
			||||||
        <thead>
 | 
					        <thead>
 | 
				
			||||||
          <tr>
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <th>
 | 
				
			||||||
 | 
					              <label class="selection-action-trigger ${this.listContainerElement.dataset?.hasPermissionView == 'true' ? '' : 'hide'}" data-selection-action="select-all">
 | 
				
			||||||
 | 
					                <input type="checkbox">
 | 
				
			||||||
 | 
					                <span></span>
 | 
				
			||||||
 | 
					              </label>
 | 
				
			||||||
 | 
					            </th>
 | 
				
			||||||
            <th>Filename</th>
 | 
					            <th>Filename</th>
 | 
				
			||||||
            <th>Author</th>
 | 
					            <th>Author</th>
 | 
				
			||||||
            <th>Title</th>
 | 
					            <th>Title</th>
 | 
				
			||||||
            <th>Publishing year</th>
 | 
					            <th>Publishing year</th>
 | 
				
			||||||
            <th></th>
 | 
					            <th class="right-align">
 | 
				
			||||||
 | 
					            <a class="selection-action-trigger btn-floating red waves-effect waves-light hide" data-selection-action="delete"><i class="material-icons">delete</i></a>
 | 
				
			||||||
 | 
					            <a class="selection-action-trigger btn-floating service-color darken waves-effect waves-light hide" data-selection-action="download" data-service="corpus-analysis"><i class="material-icons">file_download</i></a>
 | 
				
			||||||
 | 
					            </th>
 | 
				
			||||||
          </tr>
 | 
					          </tr>
 | 
				
			||||||
        </thead>
 | 
					        </thead>
 | 
				
			||||||
        <tbody class="list"></tbody>
 | 
					        <tbody class="list"></tbody>
 | 
				
			||||||
@@ -97,11 +116,12 @@ class CorpusFileList extends ResourceList {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  onClick(event) {
 | 
					  onClick(event) {
 | 
				
			||||||
 | 
					    if (event.target.closest('.disable-on-click') !== null) {return;}
 | 
				
			||||||
    let listItemElement = event.target.closest('.list-item[data-id]');
 | 
					    let listItemElement = event.target.closest('.list-item[data-id]');
 | 
				
			||||||
    if (listItemElement === null) {return;}
 | 
					    if (listItemElement === null) {return;}
 | 
				
			||||||
    let itemId = listItemElement.dataset.id;
 | 
					    let itemId = listItemElement.dataset.id;
 | 
				
			||||||
    let listActionElement = event.target.closest('.list-action-trigger[data-list-action]');
 | 
					    let listActionElement = event.target.closest('.list-action-trigger[data-list-action]');
 | 
				
			||||||
    let listAction = listActionElement === null ? 'view' : listActionElement.dataset.listAction;
 | 
					    let listAction = listActionElement === null ? '' : listActionElement.dataset.listAction;
 | 
				
			||||||
    switch (listAction) {
 | 
					    switch (listAction) {
 | 
				
			||||||
      case 'delete': {
 | 
					      case 'delete': {
 | 
				
			||||||
        let values = this.listjs.get('id', itemId)[0].values();
 | 
					        let values = this.listjs.get('id', itemId)[0].values();
 | 
				
			||||||
@@ -145,12 +165,156 @@ class CorpusFileList extends ResourceList {
 | 
				
			|||||||
        window.location.href = `/corpora/${this.corpusId}/files/${itemId}`;
 | 
					        window.location.href = `/corpora/${this.corpusId}/files/${itemId}`;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					      case 'select': {
 | 
				
			||||||
 | 
					        if (event.target.checked) {
 | 
				
			||||||
 | 
					          this.selectedItemIds.push(itemId);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          let index = this.selectedItemIds.indexOf(itemId);
 | 
				
			||||||
 | 
					          if (index > -1) {
 | 
				
			||||||
 | 
					            this.selectedItemIds.splice(index, 1);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.renderingItemSelection();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      default: {
 | 
					      default: {
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onSelectionAction(event) {
 | 
				
			||||||
 | 
					    let selectionActionElement = event.target.closest('.selection-action-trigger[data-selection-action]');
 | 
				
			||||||
 | 
					    let selectionAction = selectionActionElement.dataset.selectionAction;
 | 
				
			||||||
 | 
					    let items = this.listjs.items;
 | 
				
			||||||
 | 
					    let selectableItems = Array.from(items)
 | 
				
			||||||
 | 
					      .filter(item => item.elm)
 | 
				
			||||||
 | 
					      .map(item => item.elm.querySelector('input[type="checkbox"]'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (selectionAction) {
 | 
				
			||||||
 | 
					      case 'select-all': {
 | 
				
			||||||
 | 
					        let selectedIds = Array.from(items)
 | 
				
			||||||
 | 
					          .map(item => item.values().id);
 | 
				
			||||||
 | 
					        if (event.target.checked) {
 | 
				
			||||||
 | 
					          selectableItems.forEach(selectableItem => selectableItem.checked = true);
 | 
				
			||||||
 | 
					          this.selectedItemIds = selectedIds;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          selectableItems.forEach(checkbox => checkbox.checked = false);
 | 
				
			||||||
 | 
					          this.selectedItemIds = this.selectedItemIds.filter(id => !selectedIds.includes(id));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.renderingItemSelection();
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      case 'delete': {
 | 
				
			||||||
 | 
					        let modalElement = Utils.HTMLToElement(
 | 
				
			||||||
 | 
					          `
 | 
				
			||||||
 | 
					            <div class="modal">
 | 
				
			||||||
 | 
					              <div class="modal-content">
 | 
				
			||||||
 | 
					                <h4>Confirm Corpus File deletion</h4>
 | 
				
			||||||
 | 
					                <p>Do you really want to delete the Corpus Files?</p>
 | 
				
			||||||
 | 
					                  <ul id="selected-items-list"></ul>
 | 
				
			||||||
 | 
					                <p>All files will be permanently deleted!</p>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					              <div class="modal-footer">
 | 
				
			||||||
 | 
					                <a class="btn modal-close waves-effect waves-light">Cancel</a>
 | 
				
			||||||
 | 
					                <a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Delete</a>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          `
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        document.querySelector('#modals').appendChild(modalElement);
 | 
				
			||||||
 | 
					        let itemList = document.querySelector('#selected-items-list');
 | 
				
			||||||
 | 
					        this.selectedItemIds.forEach(selectedItemId => {
 | 
				
			||||||
 | 
					          let listItem = this.listjs.get('id', selectedItemId)[0].elm;
 | 
				
			||||||
 | 
					          let values = this.listjs.get('id', listItem.dataset.id)[0].values();
 | 
				
			||||||
 | 
					          let itemElement = Utils.HTMLToElement(`<li> - ${values.title}</li>`);
 | 
				
			||||||
 | 
					          itemList.appendChild(itemElement);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        let modal = M.Modal.init(
 | 
				
			||||||
 | 
					          modalElement,
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            dismissible: false,
 | 
				
			||||||
 | 
					            onCloseEnd: () => {
 | 
				
			||||||
 | 
					              modal.destroy();
 | 
				
			||||||
 | 
					              modalElement.remove();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]');
 | 
				
			||||||
 | 
					        confirmElement.addEventListener('click', (event) => {
 | 
				
			||||||
 | 
					          this.selectedItemIds.forEach(selectedItemId => {
 | 
				
			||||||
 | 
					            Requests.corpora.entity.files.ent.delete(this.corpusId, selectedItemId);
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					          this.selectedItemIds = [];
 | 
				
			||||||
 | 
					          this.renderingItemSelection();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        modal.open();
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      case 'download': {
 | 
				
			||||||
 | 
					        this.selectedItemIds.forEach(selectedItemId => {
 | 
				
			||||||
 | 
					          let downloadLink = document.createElement('a');
 | 
				
			||||||
 | 
					          downloadLink.href = `/corpora/${this.corpusId}/files/${selectedItemId}/download`;
 | 
				
			||||||
 | 
					          downloadLink.download = '';
 | 
				
			||||||
 | 
					          downloadLink.click();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        selectableItems.forEach(checkbox => checkbox.checked = false);
 | 
				
			||||||
 | 
					        this.selectedItemIds = [];
 | 
				
			||||||
 | 
					        this.renderingItemSelection();
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }  
 | 
				
			||||||
 | 
					      default: {
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  renderingItemSelection() {
 | 
				
			||||||
 | 
					    let selectionActionButtons;
 | 
				
			||||||
 | 
					    if (this.hasPermissionManageFiles) {
 | 
				
			||||||
 | 
					      selectionActionButtons = document.querySelectorAll('.selection-action-trigger:not([data-selection-action="select-all"])');
 | 
				
			||||||
 | 
					    } else if (this.hasPermissionView) {
 | 
				
			||||||
 | 
					      selectionActionButtons = document.querySelectorAll('.selection-action-trigger:not([data-selection-action="select-all"]):not([data-selection-action="delete"])');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    let selectableItems = this.listjs.items;
 | 
				
			||||||
 | 
					    let actionButtons = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Object.values(selectableItems).forEach(selectableItem => {
 | 
				
			||||||
 | 
					      if (selectableItem.elm) {
 | 
				
			||||||
 | 
					        let checkbox = selectableItem.elm.querySelector('input[type="checkbox"]');
 | 
				
			||||||
 | 
					        if (checkbox.checked) {
 | 
				
			||||||
 | 
					          selectableItem.elm.classList.add('grey', 'lighten-3');
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          selectableItem.elm.classList.remove('grey', 'lighten-3');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        let itemActionButtons = [];
 | 
				
			||||||
 | 
					        if (this.hasPermissionManageFiles) {
 | 
				
			||||||
 | 
					          itemActionButtons = selectableItem.elm.querySelectorAll('.list-action-trigger:not([data-list-action="select"])');
 | 
				
			||||||
 | 
					        } else if (this.hasPermissionView) {
 | 
				
			||||||
 | 
					          itemActionButtons = selectableItem.elm.querySelectorAll('.list-action-trigger:not([data-list-action="select"]):not([data-list-action="delete"]):not([data-list-action="view"])');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        itemActionButtons.forEach(itemActionButton => {
 | 
				
			||||||
 | 
					          actionButtons.push(itemActionButton);
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    // Hide item action buttons if > 0 item is selected and show selection action buttons
 | 
				
			||||||
 | 
					    if (this.selectedItemIds.length > 0) {
 | 
				
			||||||
 | 
					      selectionActionButtons.forEach(selectionActionButton => {
 | 
				
			||||||
 | 
					        selectionActionButton.classList.remove('hide');
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      actionButtons.forEach(actionButton => {
 | 
				
			||||||
 | 
					        actionButton.classList.add('hide');
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      selectionActionButtons.forEach(selectionActionButton => {
 | 
				
			||||||
 | 
					        selectionActionButton.classList.add('hide');
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      actionButtons.forEach(actionButton => {
 | 
				
			||||||
 | 
					        actionButton.classList.remove('hide');
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  onPatch(patch) {
 | 
					  onPatch(patch) {
 | 
				
			||||||
    let re = new RegExp(`^/users/${this.userId}/corpora/${this.corpusId}/files/([A-Za-z0-9]*)`);
 | 
					    let re = new RegExp(`^/users/${this.userId}/corpora/${this.corpusId}/files/([A-Za-z0-9]*)`);
 | 
				
			||||||
    let filteredPatch = patch.filter(operation => re.test(operation.path));
 | 
					    let filteredPatch = patch.filter(operation => re.test(operation.path));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,7 +40,6 @@
 | 
				
			|||||||
  'js/ResourceLists/ResourceList.js',
 | 
					  'js/ResourceLists/ResourceList.js',
 | 
				
			||||||
  'js/ResourceLists/CorpusFileList.js',
 | 
					  'js/ResourceLists/CorpusFileList.js',
 | 
				
			||||||
  'js/ResourceLists/CorpusList.js',
 | 
					  'js/ResourceLists/CorpusList.js',
 | 
				
			||||||
  'js/ResourceLists/FollowedCorpusList.js',
 | 
					 | 
				
			||||||
  'js/ResourceLists/PublicCorpusList.js',
 | 
					  'js/ResourceLists/PublicCorpusList.js',
 | 
				
			||||||
  'js/ResourceLists/JobList.js',
 | 
					  'js/ResourceLists/JobList.js',
 | 
				
			||||||
  'js/ResourceLists/JobInputList.js',
 | 
					  'js/ResourceLists/JobInputList.js',
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										379
									
								
								app/templates/corpora/public_corpus.html.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										379
									
								
								app/templates/corpora/public_corpus.html.j2
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,379 @@
 | 
				
			|||||||
 | 
					{% extends "base.html.j2" %}
 | 
				
			||||||
 | 
					{% import "materialize/wtf.html.j2" as wtf %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block main_attribs %} class="service-scheme" data-service="corpus-analysis"{% endblock main_attribs %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block page_content %}
 | 
				
			||||||
 | 
					<div class="container">
 | 
				
			||||||
 | 
					  <div class="row">
 | 
				
			||||||
 | 
					    <div class="col s12">
 | 
				
			||||||
 | 
					      <h1>{{ corpus.title }}</h1>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div class="col s12 l7">
 | 
				
			||||||
 | 
					      <div class="card service-color-border border-darken" data-service="corpus-analysis" style="border-top: 10px solid">
 | 
				
			||||||
 | 
					        <div class="card-content">
 | 
				
			||||||
 | 
					          <span class="chip corpus-status-text corpus-status-color white-text" data-status="{{ corpus.status.name }}"></span></p>
 | 
				
			||||||
 | 
					          <div class="row">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="col s12">
 | 
				
			||||||
 | 
					              <div class="input-field">
 | 
				
			||||||
 | 
					                <label>Description</label>
 | 
				
			||||||
 | 
					                <input disabled type="text" value="{{ corpus.description }}">
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="col s12 m6">
 | 
				
			||||||
 | 
					              <div class="input-field">
 | 
				
			||||||
 | 
					                <label for="corpus-creation-date">Creation date</label>
 | 
				
			||||||
 | 
					                <input disabled type="text" value="{{ corpus.creation_date }}">
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="col s12 m6">
 | 
				
			||||||
 | 
					              <div class="input-field">
 | 
				
			||||||
 | 
					                <label for="corpus-token-ratio">Nr. of tokens used <sup><i class="material-icons tooltipped tiny" data-position="bottom" data-tooltip="Current number of tokens in this corpus. Updates after every analyze session.">help</i></sup></label>
 | 
				
			||||||
 | 
					                <input disabled type="text" value="{{ corpus.num_tokens }}">
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% if cfr.has_permission('VIEW') %}
 | 
				
			||||||
 | 
					    <div class="col s12 l5">
 | 
				
			||||||
 | 
					      <div class="card">
 | 
				
			||||||
 | 
					        <div class="card-content">
 | 
				
			||||||
 | 
					          <span class="card-title">Actions</span>
 | 
				
			||||||
 | 
					          <div class="row">
 | 
				
			||||||
 | 
					            {% if cfr.has_permission('MANAGE_FILES') %}
 | 
				
			||||||
 | 
					            <div class="col s12 l6" style="padding: 0 2.5px;">
 | 
				
			||||||
 | 
					              <a class="action-button btn disabled waves-effect waves-light" data-action="build-request" style="width: 100%;"><i class="nopaque-icons left">K</i>Build</a>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="col s12 l6" style="padding: 0 2.5px;">
 | 
				
			||||||
 | 
					              {% if corpus.status.name in ['BUILT', 'STARTING_ANALYSIS_SESSION', 'RUNNING_ANALYSIS_SESSION', 'CANCELING_ANALYSIS_SESSION'] and current_user.is_following_corpus(corpus) %}
 | 
				
			||||||
 | 
					              <a class="action-button btn waves-effect waves-light" data-action="analyze" href="{{ url_for('corpora.analysis', corpus_id=corpus.id) }}" style="width: 100%;"><i class="material-icons left">search</i>Analyze</a>
 | 
				
			||||||
 | 
					              {% else %}
 | 
				
			||||||
 | 
					              <a class="action-button btn disabled waves-effect waves-light" data-action="analyze" style="width: 100%;"><i class="material-icons left">search</i>Analyze</a>
 | 
				
			||||||
 | 
					              {% endif %}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            {% endif %}
 | 
				
			||||||
 | 
					            {% if current_user.is_following_corpus(corpus) %}
 | 
				
			||||||
 | 
					            <div class="col s12 l6" style="padding: 5px 2.5px 0 2.5px;">
 | 
				
			||||||
 | 
					              <a class="action-button btn red waves-effect waves-light" data-action="unfollow-request" style="width: 100%;"><i class="material-icons left outlined">close</i>Unfollow Corpus</a>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            {% endif %}
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					          {% if cfr.has_permission('MANAGE_FOLLOWERS') %}
 | 
				
			||||||
 | 
					          <span class="card-title">Social</span>
 | 
				
			||||||
 | 
					          <div class="row">
 | 
				
			||||||
 | 
					            <div class="col s12 l6" style="padding: 0 2.5px;">
 | 
				
			||||||
 | 
					              <a class="btn waves-effect waves-light modal-trigger" href="#invite-user-modal" style="width: 100%;"><i class="material-icons left">person_add</i>invite user</a>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="col s12 l6" style="padding: 0 2.5px;">
 | 
				
			||||||
 | 
					              <a class="btn waves-effect waves-light modal-trigger" href="#share-link-modal" style="width: 100%;"><i class="material-icons left">link</i>Share link</a>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					          {% endif %}
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    {% endif %} 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="col s12">
 | 
				
			||||||
 | 
					      <div class="card">
 | 
				
			||||||
 | 
					        <div class="card-content">
 | 
				
			||||||
 | 
					          <span class="card-title" id="files">Corpus Owner</span>
 | 
				
			||||||
 | 
					          <div class="row">
 | 
				
			||||||
 | 
					            <div class="col s12">
 | 
				
			||||||
 | 
					              <table>
 | 
				
			||||||
 | 
					                <tr>
 | 
				
			||||||
 | 
					                  <td style="width:10%; margin-top:25px;">
 | 
				
			||||||
 | 
					                    <img src="{{ url_for('users.user_avatar', user_id=corpus.user.id) }}" alt="user-image" class="circle responsive-img">
 | 
				
			||||||
 | 
					                  </td>
 | 
				
			||||||
 | 
					                  <td></td>
 | 
				
			||||||
 | 
					                  <td>
 | 
				
			||||||
 | 
					                    <ul>
 | 
				
			||||||
 | 
					                      <li><b>{{ corpus.user.username }}</b></li>
 | 
				
			||||||
 | 
					                      {% if corpus.user.full_name %}
 | 
				
			||||||
 | 
					                      <li>{{ corpus.user.full_name }}</li>
 | 
				
			||||||
 | 
					                      {% endif %}
 | 
				
			||||||
 | 
					                      {% if corpus.user.show_email %}
 | 
				
			||||||
 | 
					                      <li></li><a href="mailto:{{ corpus.user.email }}">{{ corpus.user.email }}</a></li>
 | 
				
			||||||
 | 
					                      {% endif %}
 | 
				
			||||||
 | 
					                    </ul>
 | 
				
			||||||
 | 
					                  </td>
 | 
				
			||||||
 | 
					                </tr>
 | 
				
			||||||
 | 
					              </table>
 | 
				
			||||||
 | 
					              <br>
 | 
				
			||||||
 | 
					              <p></p>
 | 
				
			||||||
 | 
					              {% if not current_user.is_following_corpus(corpus) and corpus.user.has_profile_privacy_setting('SHOW_EMAIL') %}
 | 
				
			||||||
 | 
					              <a class="waves-effect waves-light btn-small" href="mailto:{{ corpus.user.email }}">Request Corpus</a>
 | 
				
			||||||
 | 
					              {% endif %}
 | 
				
			||||||
 | 
					              <a class="waves-effect waves-light btn-small" href="{{ url_for('users.user', user_id=corpus.user.id) }}">View profile</a>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="col s12">
 | 
				
			||||||
 | 
					      <div class="card">
 | 
				
			||||||
 | 
					        <div class="card-content">
 | 
				
			||||||
 | 
					          <span class="card-title" id="corpus-files">Corpus files</span>
 | 
				
			||||||
 | 
					          <div class="corpus-file-list no-autoinit" id="corpus-file-list" data-has-permission-view="{{ cfr.has_permission('VIEW')|tojson }}" data-has-permission-manage-files="{{ cfr.has_permission('MANAGE_FILES')|tojson }}" data-corpus-id="{{ corpus.hashid }}"></div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        {% if cfr.has_permission('MANAGE_FILES') %}
 | 
				
			||||||
 | 
					        <div class="card-action right-align">
 | 
				
			||||||
 | 
					          <a href="{{ url_for('corpora.create_corpus_file', corpus_id=corpus.id) }}" class="btn waves-effect waves-light"><i class="material-icons left">add</i>Add corpus file</a>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        {% endif %}
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% if cfr.has_permission('MANAGE_FOLLOWERS') %}
 | 
				
			||||||
 | 
					    <div class="col s12">
 | 
				
			||||||
 | 
					      <div class="card">
 | 
				
			||||||
 | 
					        <div class="card-content">
 | 
				
			||||||
 | 
					          <span class="card-title" id="corpus-followers">Corpus followers</span>
 | 
				
			||||||
 | 
					          <div class="corpus-follower-list no-autoinit"></div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    {% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{% endblock page_content %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block modals %}
 | 
				
			||||||
 | 
					{{ super() }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% if cfr.has_permission('MANAGE_FOLLOWERS') %}
 | 
				
			||||||
 | 
					<div class="modal no-autoinit" id="invite-user-modal">
 | 
				
			||||||
 | 
					  <div class="modal-content">
 | 
				
			||||||
 | 
					    <h4>Invite a nopaque user by username</h4>
 | 
				
			||||||
 | 
					    <p>
 | 
				
			||||||
 | 
					      Add other nopaque users as followers to your corpus. You can also add multiple 
 | 
				
			||||||
 | 
					      users at the same time. Added users get the role of "viewer" 
 | 
				
			||||||
 | 
					      by default, so they are only allowed to analyze files within nopaque, but not 
 | 
				
			||||||
 | 
					      to download or edit them. You can customize the roles later below.
 | 
				
			||||||
 | 
					    </p>
 | 
				
			||||||
 | 
					    <p><b>Please make sure that the invited users are legally allowed to view the included corpus files.</b></p>
 | 
				
			||||||
 | 
					    <div class="row">
 | 
				
			||||||
 | 
					      <div class="col s10">
 | 
				
			||||||
 | 
					        <div class="chips no-autoinit" id="invite-user-modal-search"></div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <div class="col s2">
 | 
				
			||||||
 | 
					        <br class="hide-on-med-and-down">
 | 
				
			||||||
 | 
					        <a class="btn modal-close waves-effect waves-light" id="invite-user-modal-invite-button">Invite<i class="material-icons right">send</i></a>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					  <div class="modal-footer">
 | 
				
			||||||
 | 
					    <a class="modal-close waves-effect waves-green btn-flat">Close</a>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div class="modal no-autoinit" id="share-link-modal">
 | 
				
			||||||
 | 
					  <div class="modal-content">
 | 
				
			||||||
 | 
					    <h4>Create a link to share your corpus</h4>
 | 
				
			||||||
 | 
					    <p>
 | 
				
			||||||
 | 
					      With the link other users follow your corpus directly, if it has not expired. 
 | 
				
			||||||
 | 
					      You can set different roles via the link, you can also edit them later in the menu below. 
 | 
				
			||||||
 | 
					      It is recommended not to set the expiration date of the link too far.
 | 
				
			||||||
 | 
					    </p>
 | 
				
			||||||
 | 
					    <p><b>Please make sure that the invited users are legally allowed to view the included corpus files.</b></p>
 | 
				
			||||||
 | 
					    <div class="row">
 | 
				
			||||||
 | 
					      <div class="col s12 l2">
 | 
				
			||||||
 | 
					        <div class="input-field">
 | 
				
			||||||
 | 
					          <i class="material-icons prefix">badge</i>
 | 
				
			||||||
 | 
					          <select id="share-link-modal-corpus-follower-role-select">
 | 
				
			||||||
 | 
					            {% for cfr in cfrs %}
 | 
				
			||||||
 | 
					            <option value="{{ cfr.name }}">{{ cfr.name }}</option>
 | 
				
			||||||
 | 
					            {% endfor %}
 | 
				
			||||||
 | 
					          </select>
 | 
				
			||||||
 | 
					          <label>Role</label>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <div class="col s12 l3">
 | 
				
			||||||
 | 
					        <div class="input-field">
 | 
				
			||||||
 | 
					          <i class="material-icons prefix">calendar_month</i>
 | 
				
			||||||
 | 
					          <input type="text" class="datepicker no-autoinit" id="share-link-modal-expiration-date-datepicker">
 | 
				
			||||||
 | 
					          <label for="expiration-date">Expiration date</label>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <div class="col s12 l2">
 | 
				
			||||||
 | 
					        <br class="hide-on-med-and-down">
 | 
				
			||||||
 | 
					        <a class="btn waves-effect waves-light" id="share-link-modal-create-button">Create<i class="material-icons right">send</i></a>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <div class="col s12 l5">
 | 
				
			||||||
 | 
					        <div class="row hide" id="share-link-modal-output-container">
 | 
				
			||||||
 | 
					          <div class="col s9">
 | 
				
			||||||
 | 
					            <div class="input-field">
 | 
				
			||||||
 | 
					              <input disabled id="share-link-modal-output-field" readonly type="text">
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					          <div class="col s3">
 | 
				
			||||||
 | 
					            <br class="hide-on-med-and-down">
 | 
				
			||||||
 | 
					            <a class="btn-small waves-effect waves-light" id="share-link-modal-output-copy-button"><i class="material-icons left">content_copy</i>Copy</a>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					  <div class="modal-footer">
 | 
				
			||||||
 | 
					    <a class="modal-close waves-effect waves-green btn-flat">Close</a>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% endblock modals %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block scripts %}
 | 
				
			||||||
 | 
					{{ super() }}
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let publicCorpusFileList = new CorpusFileList(document.querySelector('#corpus-file-list'));
 | 
				
			||||||
 | 
					publicCorpusFileList.add(
 | 
				
			||||||
 | 
					  [
 | 
				
			||||||
 | 
					    {% for corpus_file in corpus.files %}
 | 
				
			||||||
 | 
					    {{ corpus_file.to_json_serializeable()|tojson }},
 | 
				
			||||||
 | 
					    {% endfor %}
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% if cfr.has_permission('MANAGE_FOLLOWERS') %}
 | 
				
			||||||
 | 
					let publicCorpusFollowerList = new CorpusFollowerList(document.querySelector('.corpus-follower-list'));
 | 
				
			||||||
 | 
					publicCorpusFollowerList.add(
 | 
				
			||||||
 | 
					  [
 | 
				
			||||||
 | 
					    {% for cfa in cfas %}
 | 
				
			||||||
 | 
					    {{ cfa.to_json_serializeable()|tojson }},
 | 
				
			||||||
 | 
					    {% endfor %}
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// #region Corpus Unfollow Request
 | 
				
			||||||
 | 
					{% if current_user.is_following_corpus(corpus) %}
 | 
				
			||||||
 | 
					  let unfollowRequestElement = document.querySelector('.action-button[data-action="unfollow-request"]');
 | 
				
			||||||
 | 
					  unfollowRequestElement.addEventListener('click', () => {
 | 
				
			||||||
 | 
					    Requests.corpora.entity.followers.entity.delete({{ corpus.hashid|tojson }}, {{ current_user.hashid|tojson }})
 | 
				
			||||||
 | 
					      .then((response) => {
 | 
				
			||||||
 | 
					        window.location.reload();
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					// #endregion Corpus Unfollow Request
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% if cfr.has_permission('MANAGE_FOLLOWERS') %}
 | 
				
			||||||
 | 
					// #region Invite user
 | 
				
			||||||
 | 
					let inviteUserModalElement = document.querySelector('#invite-user-modal');
 | 
				
			||||||
 | 
					let inviteUserModalSearchElement = document.querySelector('#invite-user-modal-search');
 | 
				
			||||||
 | 
					let inviteUserModalInviteButtonElement = document.querySelector('#invite-user-modal-invite-button');
 | 
				
			||||||
 | 
					let users = {
 | 
				
			||||||
 | 
					  {% for user in users %}
 | 
				
			||||||
 | 
					    {{ user.username|tojson }}: {{ url_for('users.user_avatar', user_id=user.id)|tojson }}
 | 
				
			||||||
 | 
					    {% if not loop.last %},{% endif %}
 | 
				
			||||||
 | 
					  {% endfor %}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let inviteUserModalSearch = M.Chips.init(
 | 
				
			||||||
 | 
					  inviteUserModalSearchElement,
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    autocompleteOptions: {
 | 
				
			||||||
 | 
					      data: users
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    limit: 3,
 | 
				
			||||||
 | 
					    onChipAdd: (a, chipElement) => {
 | 
				
			||||||
 | 
					      if (!(chipElement.firstChild.data in inviteUserModalSearch.autocomplete.options.data)) {
 | 
				
			||||||
 | 
					        chipElement.firstElementChild.click();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    placeholder: 'Enter username',
 | 
				
			||||||
 | 
					    secondaryPlaceholder: 'Add more users'
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					M.Modal.init(
 | 
				
			||||||
 | 
					  inviteUserModalElement,
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    onOpenStart: (modalElement, modalTriggerElement) => {
 | 
				
			||||||
 | 
					      while (inviteUserModalSearch.chipsData.length > 0) {
 | 
				
			||||||
 | 
					        inviteUserModalSearch.deleteChip(0);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inviteUserModalInviteButtonElement.addEventListener('click', (event) => {
 | 
				
			||||||
 | 
					  let usernames = inviteUserModalSearch.chipsData.map((chipData) => chipData.tag);
 | 
				
			||||||
 | 
					  Requests.corpora.entity.followers.add({{ corpus.hashid|tojson }}, usernames);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					// #endregion Invite user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// #region Share link
 | 
				
			||||||
 | 
					let shareLinkModalElement = document.querySelector('#share-link-modal');
 | 
				
			||||||
 | 
					let shareLinkModalCorpusFollowerRoleSelectElement = document.querySelector('#share-link-modal-corpus-follower-role-select');
 | 
				
			||||||
 | 
					let shareLinkModalExpirationDateDatepickerElement = document.querySelector('#share-link-modal-expiration-date-datepicker');
 | 
				
			||||||
 | 
					let shareLinkModalCreateButtonElement = document.querySelector('#share-link-modal-create-button');
 | 
				
			||||||
 | 
					let shareLinkModalOutputContainerElement = document.querySelector('#share-link-modal-output-container');
 | 
				
			||||||
 | 
					let shareLinkModalOutputFieldElement = document.querySelector('#share-link-modal-output-field');
 | 
				
			||||||
 | 
					let shareLinkModalOutputCopyButtonElement = document.querySelector('#share-link-modal-output-copy-button');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let today = new Date();
 | 
				
			||||||
 | 
					let tomorrow = new Date();
 | 
				
			||||||
 | 
					tomorrow.setDate(today.getDate() + 1);
 | 
				
			||||||
 | 
					let oneWeekLater = new Date();
 | 
				
			||||||
 | 
					oneWeekLater.setDate(today.getDate() + 7);
 | 
				
			||||||
 | 
					let fourWeeksLater = new Date();
 | 
				
			||||||
 | 
					fourWeeksLater.setDate(today.getDate() + 28);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					M.Datepicker.init(
 | 
				
			||||||
 | 
					  shareLinkModalExpirationDateDatepickerElement,
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    container: document.querySelector('main'),
 | 
				
			||||||
 | 
					    defaultDate: oneWeekLater,
 | 
				
			||||||
 | 
					    setDefaultDate: true,
 | 
				
			||||||
 | 
					    minDate: tomorrow,
 | 
				
			||||||
 | 
					    maxDate: fourWeeksLater
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					M.Modal.init(
 | 
				
			||||||
 | 
					  shareLinkModalElement,
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    onOpenStart: (modalElement, modalTriggerElement) => {
 | 
				
			||||||
 | 
					      shareLinkModalOutputFieldElement.value = '';
 | 
				
			||||||
 | 
					      shareLinkModalOutputContainerElement.classList.add('hide');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shareLinkModalCreateButtonElement.addEventListener('click', (event) => {
 | 
				
			||||||
 | 
					  let role = shareLinkModalCorpusFollowerRoleSelectElement.value;
 | 
				
			||||||
 | 
					  let expiration = shareLinkModalExpirationDateDatepickerElement.value
 | 
				
			||||||
 | 
					  Requests.corpora.entity.generateShareLink({{ corpus.hashid|tojson }}, role, expiration)
 | 
				
			||||||
 | 
					    .then((response) => {
 | 
				
			||||||
 | 
					      response.json()
 | 
				
			||||||
 | 
					        .then((json) => {
 | 
				
			||||||
 | 
					          shareLinkModalOutputContainerElement.classList.remove('hide');
 | 
				
			||||||
 | 
					          shareLinkModalOutputFieldElement.value = json.corpusShareLink;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					shareLinkModalOutputCopyButtonElement.addEventListener('click', (event) => {
 | 
				
			||||||
 | 
					  navigator.clipboard.writeText(shareLinkModalOutputFieldElement.value)
 | 
				
			||||||
 | 
					    .then(
 | 
				
			||||||
 | 
					      () => {app.flash('Copied!');},
 | 
				
			||||||
 | 
					      () => {app.flash('Could not copy to clipboard. Please copy manually.', 'error');}
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					// #endregion Share link
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					{% endblock scripts %}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user