Skip to content
Snippets Groups Projects
corpus.html.j2 15.16 KiB
{% 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" data-corpus-id="{{ corpus.hashid }}" data-user-id="{{ corpus.user.hashid }}" id="corpus-display">
    <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 corpus-status-color corpus-status-text white-text"></span>
          <div class="active preloader-wrapper small corpus-status-spinner">
            <div class="spinner-layer spinner-blue-only">
              <div class="circle-clipper left">
                <div class="circle"></div>
              </div>
              <div class="gap-patch">
                <div class="circle"></div>
              </div>
              <div class="circle-clipper right">
                <div class="circle"></div>
              </div>
            </div>
          </div>
          <div class="row">
            <div class="col s12">
              <div class="input-field">
                <input class="corpus-description" disabled id="corpus-description" type="text">
                <label for="corpus-description">Description</label>
              </div>
            </div>

            <div class="col s12 m6">
              <div class="input-field">
                <input class="corpus-creation-date validate" disabled id="corpus-creation-date" type="text">
                <label for="corpus-creation-date">Creation date</label>
              </div>
            </div>

            <div class="col s12 m6">
              <div class="input-field">
                <input class="corpus-token-ratio validate" disabled id="corpus-token-ratio" type="text">
                <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>
              </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">
            <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;">
              <a class="action-button btn disabled 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>
            </div>
            <div class="col s12 l6" style="padding: 5px 2.5px 0 2.5px;">
              <a class="btn waves-effect waves-light modal-trigger" href="#publishing-modal" style="width: 100%;"><i class="material-icons left">publish</i>Publishing</a>
            </div>
            <div class="col s12 l6" style="padding: 5px 2.5px 0 2.5px;">
              <a class="btn red waves-effect waves-light modal-trigger" href="#delete-modal" style="width: 100%;"><i class="material-icons left">delete</i>Delete</a>
            </div>
          </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 files</span>
          <div class="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 }}" data-user-id="{{ corpus.user.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="files">Corpus followers</span>
          <div class="corpus-follower-list" data-user-id="{{ corpus.user.hashid }}" data-corpus-id="{{ corpus.hashid }}"></div>
        </div>
      </div>
    </div>
    {% endif %}

  </div>
</div>
{% endblock page_content %}

{% block modals %}
{{ super() }}

{% if current_user == corpus.user or current_user.is_administrator() %}
<div class="modal" id="publishing-modal">
  <div class="modal-content">
    <h4>Change your Corpus publishing status</h4>
    <p><i>Other users can only see the meta data of your corpus. The files of the corpus remain private and can only be viewed via a share link.</i></p>
    <br>
    <div class="switch">
      <label>
        private
        <input {% if corpus.is_public %}checked{% endif %} id="publishing-modal-is-public-switch" type="checkbox">
        <span class="lever"></span>
        public
      </label>
    </div>
  </div>
  <div class="modal-footer">
    <a class="modal-close waves-effect waves-green btn-flat">Close</a>
  </div>
</div>

<div class="modal" id="delete-modal">
  <div class="modal-content">
    <h4>Confirm Corpus deletion</h4>
    <p>Do you really want to delete the Corpus <b>{{ corpus.title }}</b>? 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="btn modal-close red waves-effect waves-light" id="delete-modal-delete-button">Delete</a>
  </div>
</div>
{% endif %}

{% 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 if cfr.name != 'Anonymous' %}
            <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 corpusDisplay = new CorpusDisplay(document.querySelector('#corpus-display'));

{% 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 %}

{% if current_user == corpus.user or current_user.is_administrator() %}
// #region Publishing
let publishingModalIsPublicSwitchElement = document.querySelector('#publishing-modal-is-public-switch');
publishingModalIsPublicSwitchElement.addEventListener('change', (event) => {
  let newIsPublic = publishingModalIsPublicSwitchElement.checked;
  Requests.corpora.entity.isPublic.update({{ corpus.hashid|tojson }}, newIsPublic)
    .catch((response) => {
      publishingModalIsPublicSwitchElement.checked = !newIsPublic;
    });
});
// #endregion Publishing

// #region Delete
let deleteModalDeleteButtonElement = document.querySelector('#delete-modal-delete-button');
deleteModalDeleteButtonElement.addEventListener('click', (event) => {
  Requests.corpora.entity.delete({{ corpus.hashid|tojson }})
    .then((response) => {
      window.location.href = {{ url_for('main.dashboard')|tojson }};
    });
});
// #endregion Delete
{% endif %}

{% 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 %}