Update corpus page

This commit is contained in:
Inga Kirschnick 2023-04-27 15:11:18 +02:00
parent 817a13dfff
commit 6c76d27a32
18 changed files with 296 additions and 273 deletions

View File

@ -8,7 +8,7 @@ from . import bp
@bp.route('/<hashid:corpus_id>/files/<hashid:corpus_file_id>', methods=['DELETE'])
@corpus_follower_permission_required('REMOVE_CORPUS_FILE')
@corpus_follower_permission_required('MANAGE_FILES')
@content_negotiation(produces='application/json')
def delete_corpus_file(corpus_id, corpus_file_id):
def _delete_corpus_file(app, corpus_file_id):

View File

@ -25,7 +25,7 @@ def corpus_files(corpus_id):
@bp.route('/<hashid:corpus_id>/files/create', methods=['GET', 'POST'])
@register_breadcrumb(bp, '.entity.files.create', 'Create', endpoint_arguments_constructor=corpus_eac)
@corpus_follower_permission_required('ADD_CORPUS_FILE')
@corpus_follower_permission_required('MANAGE_FILES')
def create_corpus_file(corpus_id):
corpus = Corpus.query.get_or_404(corpus_id)
form = CreateCorpusFileForm()
@ -67,7 +67,7 @@ def create_corpus_file(corpus_id):
@bp.route('/<hashid:corpus_id>/files/<hashid:corpus_file_id>', methods=['GET', 'POST'])
@register_breadcrumb(bp, '.entity.files.entity', '', dynamic_list_constructor=corpus_file_dlc)
@corpus_follower_permission_required('UPDATE_CORPUS_FILE')
@corpus_follower_permission_required('MANAGE_FILES')
def corpus_file(corpus_id, corpus_file_id):
corpus_file = CorpusFile.query.filter_by(corpus_id=corpus_id, id=corpus_file_id).first_or_404()
form = UpdateCorpusFileForm(data=corpus_file.to_json_serializeable())

View File

@ -1,4 +1,5 @@
from flask import abort, request
from flask import abort, flash, jsonify, make_response, request
from flask_login import current_user
from app import db
from app.decorators import content_negotiation
from app.models import (
@ -10,9 +11,8 @@ from app.models import (
from ..decorators import corpus_follower_permission_required
from . import bp
@bp.route('/<hashid:corpus_id>/followers', methods=['POST'])
@corpus_follower_permission_required('ADD_FOLLOWER')
@corpus_follower_permission_required('MANAGE_FOLLOWERS')
@content_negotiation(consumes='application/json', produces='application/json')
def create_corpus_followers(corpus_id):
usernames = request.json
@ -31,7 +31,7 @@ def create_corpus_followers(corpus_id):
@bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>/role', methods=['PUT'])
@corpus_follower_permission_required('UPDATE_FOLLOWER')
@corpus_follower_permission_required('MANAGE_FOLLOWERS')
@content_negotiation(consumes='application/json', produces='application/json')
def update_corpus_follower_role(corpus_id, follower_id):
role_name = request.json
@ -51,17 +51,25 @@ def update_corpus_follower_role(corpus_id, follower_id):
@bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>', methods=['DELETE'])
@corpus_follower_permission_required('REMOVE_FOLLOWER')
@content_negotiation(produces='application/json')
def delete_corpus_follower(corpus_id, follower_id):
cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404()
if not (
current_user.id == follower_id
or current_user == cfa.corpus.user
or CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first().role.has_permission('MANAGE_FOLLOWERS')
or current_user.is_administrator()):
abort(403)
if current_user.id == follower_id:
flash(f'You are no longer following "{cfa.corpus.title}"', 'corpus')
response = make_response()
response.status_code = 204
else:
response_data = {
'message': f'"{cfa.follower.username}" is not following "{cfa.corpus.title}" anymore',
'category': 'corpus'
}
response = jsonify(response_data)
response.status_code = 200
cfa.follower.unfollow_corpus(cfa.corpus)
db.session.commit()
response_data = {
'message': (
f'"{cfa.follower.username}" is not following '
f'"{cfa.corpus.title}" anymore'
),
'category': 'corpus'
}
return response_data, 200
return response

View File

@ -33,7 +33,7 @@ def delete_corpus(corpus_id):
@bp.route('/<hashid:corpus_id>/build', methods=['POST'])
@corpus_owner_or_admin_required
@corpus_follower_permission_required('MANAGE_FILES')
@content_negotiation(produces='application/json')
def build_corpus(corpus_id):
def _build_corpus(app, corpus_id):
@ -58,7 +58,7 @@ def build_corpus(corpus_id):
@bp.route('/<hashid:corpus_id>/generate-share-link', methods=['POST'])
@corpus_follower_permission_required('ADD_FOLLOWER')
@corpus_follower_permission_required('MANAGE_FOLLOWERS')
@content_negotiation(consumes='application/json', produces='application/json')
def generate_corpus_share_link(corpus_id):
data = request.json

View File

@ -50,26 +50,24 @@ def create_corpus():
@register_breadcrumb(bp, '.entity', '', dynamic_list_constructor=corpus_dlc)
def corpus(corpus_id):
corpus = Corpus.query.get_or_404(corpus_id)
corpus_follower_roles = CorpusFollowerRole.query.all()
cfrs = CorpusFollowerRole.query.all()
users = User.query.filter(User.is_public == True, User.id != current_user.id).all()
# TODO: Add URL query option to toggle view
if corpus.user == current_user or current_user.is_administrator():
return render_template(
'corpora/corpus.html.j2',
title=corpus.title,
corpus=corpus,
corpus_follower_roles=corpus_follower_roles,
users = users
)
if current_user.is_following_corpus(corpus) or corpus.is_public:
cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first_or_404()
return render_template(
'corpora/public_corpus.html.j2',
title=corpus.title,
corpus=corpus,
cfa=cfa
)
abort(403)
cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first()
if cfa is None:
if corpus.user == current_user or current_user.is_administrator():
cfr = CorpusFollowerRole.query.filter_by(name='Administrator').first()
else:
cfr = CorpusFollowerRole.query.filter_by(name='Anonymous').first()
else:
cfr = cfa.role
return render_template(
'corpora/corpus.html.j2',
title=corpus.title,
corpus=corpus,
cfrs=cfrs,
cfr=cfr,
users = users
)
@bp.route('/<hashid:corpus_id>/analysis')

View File

@ -113,12 +113,9 @@ class ProfilePrivacySettings(IntEnum):
class CorpusFollowerPermission(IntEnum):
VIEW = 1
ADD_CORPUS_FILE = 2
UPDATE_CORPUS_FILE = 4
REMOVE_CORPUS_FILE = 8
ADD_FOLLOWER = 16
UPDATE_FOLLOWER = 32
REMOVE_FOLLOWER = 64
MANAGE_FILES = 2
MANAGE_FOLLOWERS = 4
MANAGE_CORPUS = 8
@staticmethod
def get(corpus_follower_permission: Union['CorpusFollowerPermission', int, str]) -> 'CorpusFollowerPermission':
@ -434,23 +431,20 @@ class CorpusFollowerRole(HashidMixin, db.Model):
@staticmethod
def insert_defaults():
roles = {
'Anonymous': [],
'Viewer': [
CorpusFollowerPermission.VIEW
],
'Contributor': [
CorpusFollowerPermission.VIEW,
CorpusFollowerPermission.ADD_CORPUS_FILE,
CorpusFollowerPermission.UPDATE_CORPUS_FILE,
CorpusFollowerPermission.REMOVE_CORPUS_FILE
CorpusFollowerPermission.MANAGE_FILES
],
'Administrator': [
CorpusFollowerPermission.VIEW,
CorpusFollowerPermission.ADD_CORPUS_FILE,
CorpusFollowerPermission.UPDATE_CORPUS_FILE,
CorpusFollowerPermission.REMOVE_CORPUS_FILE,
CorpusFollowerPermission.ADD_FOLLOWER,
CorpusFollowerPermission.UPDATE_FOLLOWER,
CorpusFollowerPermission.REMOVE_FOLLOWER
CorpusFollowerPermission.MANAGE_FILES,
CorpusFollowerPermission.MANAGE_FOLLOWERS,
CorpusFollowerPermission.MANAGE_CORPUS
]
}
default_role_name = 'Viewer'

View File

@ -11,6 +11,8 @@ class CorpusFileList extends ResourceList {
this.isInitialized = false;
this.userId = listContainerElement.dataset.userId;
this.corpusId = listContainerElement.dataset.corpusId;
this.hasPermissionView = listContainerElement.dataset?.hasPermissionView == 'true' || false;
this.hasPermissionManageFiles = listContainerElement.dataset?.hasPermissionManageFiles == 'true' || false;
if (this.userId === undefined || this.corpusId === undefined) {return;}
app.subscribeUser(this.userId).then((response) => {
app.socket.on('PATCH', (patch) => {
@ -24,19 +26,21 @@ class CorpusFileList extends ResourceList {
}
get item() {
return `
<tr class="list-item clickable hoverable">
<td><span class="filename"></span></td>
<td><span class="author"></span></td>
<td><span class="title"></span></td>
<td><span class="publishing-year"></span></td>
<td class="right-align">
<a class="list-action-trigger btn-floating red waves-effect waves-light" data-list-action="delete"><i class="material-icons">delete</i></a>
<a class="list-action-trigger btn-floating service-color darken waves-effect waves-light" data-list-action="download" data-service="corpus-analysis"><i class="material-icons">file_download</i></a>
<a class="list-action-trigger btn-floating service-color darken waves-effect waves-light" data-list-action="view" data-service="corpus-analysis"><i class="material-icons">send</i></a>
</td>
</tr>
`.trim();
return (values) => {
return `
<tr class="list-item">
<td><span class="filename"></span></td>
<td><span class="author"></span></td>
<td><span class="title"></span></td>
<td><span class="publishing-year"></span></td>
<td class="right-align">
<a class="list-action-trigger btn-floating red waves-effect waves-light ${this.hasPermissionManageFiles ? '' : 'hide'}" data-list-action="delete"><i class="material-icons">delete</i></a>
<a class="list-action-trigger btn-floating service-color darken waves-effect waves-light ${this.hasPermissionView ? '' : 'hide'}" data-list-action="download" data-service="corpus-analysis"><i class="material-icons">file_download</i></a>
<a class="list-action-trigger btn-floating service-color darken waves-effect waves-light ${this.hasPermissionManageFiles ? '' : 'hide'}" data-list-action="view" data-service="corpus-analysis"><i class="material-icons">send</i></a>
</td>
</tr>
`.trim();
}
}
get valueNames() {

View File

@ -22,7 +22,9 @@ class CorpusFollowerList extends ResourceList {
});
});
app.getUser(this.userId).then((user) => {
this.add(Object.values(user.corpora[this.corpusId].corpus_follower_associations));
let corpusFollowerAssociations = Object.values(user.corpora[this.corpusId].corpus_follower_associations);
let filteredList = corpusFollowerAssociations.filter(association => association.follower.id != currentUserId);
this.add(filteredList);
this.isInitialized = true;
});
}

View File

@ -1,15 +0,0 @@
class PublicCorpusFileList extends CorpusFileList {
get item() {
return `
<tr class="list-item clickable hoverable">
<td><span class="filename"></span></td>
<td><span class="author"></span></td>
<td><span class="title"></span></td>
<td><span class="publishing-year"></span></td>
<td class="right-align">
<a class="list-action-trigger btn-floating service-color darken waves-effect waves-light" data-list-action="view" data-service="corpus-analysis"><i class="material-icons">send</i></a>
</td>
</tr>
`.trim();
}
}

View File

@ -39,7 +39,6 @@
output='gen/ResourceLists.%(version)s.js',
'js/ResourceLists/ResourceList.js',
'js/ResourceLists/CorpusFileList.js',
'js/ResourceLists/PublicCorpusFileList.js',
'js/ResourceLists/CorpusList.js',
'js/ResourceLists/FollowedCorpusList.js',
'js/ResourceLists/PublicCorpusList.js',

View File

@ -0,0 +1,36 @@
{% set owner_admin %}
<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>
{% endset %}
{% set follower %}
{% if cfr.has_permission('MANAGE_FILES') %}
<div class="col s12 l6" style="padding: 0 2.5px;">
{% if corpus.status.name in ['UNPREPARED'] %}
<a class="action-button btn waves-effect waves-light" id="build-button" style="width: 100%;"><i class="nopaque-icons left">K</i>Build</a>
{% else %}
<a class="action-button btn waves-effect waves-light disabled" id="build-button" style="width: 100%;"><i class="nopaque-icons left">K</i>Build</a>
{% endif %}
</div>
{% if corpus.status.name in ['BUILT', 'STARTING_ANALYSIS_SESSION', 'RUNNING_ANALYSIS_SESSION', 'CANCELING_ANALYSIS_SESSION'] %}
<div class="col s12 l6" style="padding: 0 2.5px;">
<a class="btn waves-effect waves-light" href="{{ url_for('corpora.analysis', corpus_id=corpus.id) }}" style="width: 100%;"><i class="material-icons left">search</i>Analyze</a>
</div>
{% endif %}
{% 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 %}
{% endset %}

View File

@ -0,0 +1,72 @@
{% set name = 'Corpus Information' %}
{% set owner %}
<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>
{% endset %}
{% set public %}
<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">
<div class="row">
<div class="col s12">
<p><b>Status:</b> <span class="chip corpus-status-text corpus-status-color white-text" data-status="{{ corpus.status.name }}"></span></p>
<br>
</div>
<div class="col s12">
<p><b>Description:</b> {{ corpus.description }}</p>
<br>
</div>
<div class="col s12">
<p><b>Creation date:</b> {{ corpus.creation_date }}</p>
<br>
</div>
<div class="col s12">
<p><b>Number of tokens used:</b> {{ corpus.num_tokens }}</p>
</div>
</div>
</div>
</div>
</div>
{% endset %}

View File

@ -1,7 +1,7 @@
{% extends "base.html.j2" %}
{% import "materialize/wtf.html.j2" as wtf %}
{% import 'corpora/analysis_extensions/concordance.html.j2' as concordance_extension %}
{% import 'corpora/analysis_extensions/reader.html.j2' as reader_extension %}
{% import 'corpora/_analysis/concordance.html.j2' as concordance_extension %}
{% import 'corpora/_analysis/reader.html.j2' as reader_extension %}
{% set extensions = [concordance_extension, reader_extension] %}
{% block main_attribs %} class="service-scheme" data-service="corpus-analysis" id="corpus-analysis-app-container"{% endblock main_attribs %}

View File

@ -1,5 +1,7 @@
{% extends "base.html.j2" %}
{% import "materialize/wtf.html.j2" as wtf %}
{% import "corpora/_corpus/corpus_information_card.html.j2" as corpus_information_card with context %}
{% import "corpora/_corpus/action_buttons.html.j2" as action_buttons with context %}
{% block main_attribs %} class="service-scheme" data-service="corpus-analysis"{% endblock main_attribs %}
@ -7,69 +9,28 @@
<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 id="title"><span class="corpus-title"></span></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>
<h1>{{ corpus.title }}</h1>
</div>
{% if current_user == corpus.user or current_user.is_administrator() %}
{{ corpus_information_card.owner }}
{% else %}
{{ corpus_information_card.public }}
{% endif %}
{% 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>
{% if current_user == corpus.user or current_user.is_administrator() %}
{{ action_buttons.owner_admin }}
{% else %}
{{ action_buttons.follower }}
{% 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;">
@ -79,24 +40,66 @@
<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 %}
{% if current_user != corpus.user %}
<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) %}
<a class="waves-effect waves-light btn-small">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>
{% 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-user-id="{{ corpus.user.hashid }}" data-corpus-id="{{ corpus.hashid }}"></div>
<div class="corpus-file-list" 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>
<div class="col s12"></div>
{% if cfr.has_permission('MANAGE_FOLLOWERS') %}
<div class="col s12">
<div class="card">
<div class="card-content">
@ -105,12 +108,16 @@
</div>
</div>
</div>
{% endif %}
</div>
</div>
{% endblock page_content %}
{% block modals %}
{{ super() }}
{% if cfr.has_permission('MANAGE_FOLLOWERS') %}
<div class="modal" id="publishing-modal">
<div class="modal-content">
<h4>Change your Corpus publishing status</h4>
@ -129,7 +136,9 @@
<a class="modal-close waves-effect waves-green btn-flat">Close</a>
</div>
</div>
{% endif %}
{% if current_user == corpus.user or current_user.is_administrator() %}
<div class="modal" id="delete-modal">
<div class="modal-content">
<h4>Confirm Corpus deletion</h4>
@ -140,7 +149,9 @@
<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>
@ -174,27 +185,27 @@
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>
<h5>HIER RECHTLICHEN HINWEIS EINFÜGEN</h5>
<h5>Please make sure that the invited users are legally allowed to view the included corpus files.</h5>
<div class="row">
<div class="col s12 l2">
<div class="col s12 l3">
<div class="input-field">
<i class="material-icons prefix">badge</i>
<select id="share-link-modal-corpus-follower-role-select">
{% for corpus_follower_role in corpus_follower_roles %}
<option value="{{ corpus_follower_role.name }}">{{ corpus_follower_role.name }}</option>
{% for cfr in cfrs %}
<option value="{{ cfr.name }}">{{ cfr.name }}</option>
{% endfor %}
</select>
<label>Role</label>
</div>
</div>
<div class="col s12 l2">
<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">
<div class="col s12 l3">
<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>
@ -218,13 +229,44 @@
<a class="modal-close waves-effect waves-green btn-flat">Close</a>
</div>
</div>
{% endif %}
{% endblock modals %}
{% block scripts %}
{{ super() }}
<script>
{% if current_user == corpus.user or current_user.is_administrator() %}
let corpusDisplay = new CorpusDisplay(document.querySelector('#corpus-display'));
{% endif %}
let corpusFileList = new CorpusFileList(document.querySelector('#corpus-file-list'));
corpusFileList.add(
[
{% for corpus_file in corpus.files %}
{{ corpus_file.to_json_serializeable()|tojson }},
{% endfor %}
]
);
{% if current_user.is_following_corpus(corpus) %}
{% if cfr.has_permission('MANAGE_FILES') %}
let buildButton = document.querySelector('#build-button');
buildButton.addEventListener('click', () => {
Requests.corpora.entity.build({{ corpus.hashid|tojson }})
});
{% endif %}
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) => {
@ -245,8 +287,10 @@ deleteModalDeleteButtonElement.addEventListener('click', (event) => {
});
});
// #endregion Delete
{% endif %}
// #region Invite users
{% 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');
@ -289,7 +333,7 @@ inviteUserModalInviteButtonElement.addEventListener('click', (event) => {
let usernames = inviteUserModalSearch.chipsData.map((chipData) => chipData.tag);
Requests.corpora.entity.followers.add({{ corpus.hashid|tojson }}, usernames);
});
// #endregion Invite users
// #endregion Invite user
// #region Share link
let shareLinkModalElement = document.querySelector('#share-link-modal');
@ -351,5 +395,8 @@ shareLinkModalOutputCopyButtonElement.addEventListener('click', (event) => {
});
// #endregion Share link
{% endif %}
</script>
{% endblock scripts %}

View File

@ -1,122 +0,0 @@
{% 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 class="row">
<div class="col s8 m9 l10">
{% if current_user.is_following_corpus(corpus) %}
<a class="action-button btn waves-effect waves-light" data-action="unfollow-request"><i class="material-icons left outlined">close</i>Unfollow Corpus</a>
{% endif %}
{% if corpus.status.name in ['BUILT', 'STARTING_ANALYSIS_SESSION', 'RUNNING_ANALYSIS_SESSION', 'CANCELING_ANALYSIS_SESSION'] and current_user.is_following_corpus(corpus) %}
<a class="btn waves-effect waves-light" href="{{ url_for('corpora.analysis', corpus_id=corpus.id) }}">Analyze</a>
{% endif %}
</div>
</div>
<div class="card service-color-border border-darken" data-service="corpus-analysis" style="border-top: 10px solid">
<div class="card-content">
<div class="row">
<div class="col s12">
<p><b>Status:</b> <span class="chip corpus-status-text corpus-status-color white-text" data-status="{{ corpus.status.name }}"></span></p>
<p></p>
<br>
</div>
<div class="col s12">
<p><b>Description:</b> {{ corpus.description }}</p>
<br>
<p></p>
</div>
<div class="col s6">
<p><b>Creation date:</b> {{ corpus.creation_date }}</p>
</div>
<div class="col s6">
<p><b>Number of tokens used:</b> {{ corpus.num_tokens }}</p>
</div>
</div>
</div>
</div>
<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) %}
<a class="waves-effect waves-light btn-small">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>
{% if cfa.role.has_permission('VIEW') %}
<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"></div>
</div>
</div>
{% endif %}
{% if cfa.role.has_permission('UPDATE_FOLLOWER') %}
<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>
{% endif %}
</div>
</div>
</div>
{% endblock page_content %}
{% block scripts %}
{{ super() }}
<script>
let publicCorpusFileList = new PublicCorpusFileList(document.querySelector('#corpus-file-list'));
publicCorpusFileList.add(
[
{% for corpus_file in corpus.files %}
{{ corpus_file.to_json_serializeable()|tojson }},
{% endfor %}
]
);
let unfollowRequestElement = document.querySelector('.action-button[data-action="unfollow-request"]');
unfollowRequestElement.addEventListener('click', () => {
Requests.corpora.entity.followers.entity.delete({{ corpus.hashid|tojson }}, {{ corpus.user.hashid|tojson }})
.then((response) => {
window.location.href = {{ url_for('main.dashboard')|tojson }};
});
});
</script>
{% endblock scripts %}