mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2024-11-15 01:05:42 +00:00
Redesign corpus page and add possibility to add followers by username for owner
This commit is contained in:
parent
ec6d0a6477
commit
145b80356d
@ -3,6 +3,7 @@ from flask import (
|
||||
abort,
|
||||
current_app,
|
||||
flash,
|
||||
jsonify,
|
||||
make_response,
|
||||
Markup,
|
||||
redirect,
|
||||
@ -49,22 +50,34 @@ def fake_add():
|
||||
return ''
|
||||
|
||||
|
||||
@bp.route('/<hashid:corpus_id>/is_public/enable', methods=['POST'])
|
||||
@bp.route('/<hashid:corpus_id>/is_public', methods=['POST'])
|
||||
@login_required
|
||||
@owner_or_admin_required()
|
||||
def enable_corpus_is_public(corpus_id):
|
||||
def update_corpus_is_public(corpus_id):
|
||||
is_public = request.json
|
||||
if not isinstance(is_public, bool):
|
||||
response = jsonify('The request body must be a boolean')
|
||||
response.status_code = 400
|
||||
abort(response)
|
||||
corpus = Corpus.query.get_or_404(corpus_id)
|
||||
corpus.is_public = True
|
||||
corpus.is_public = is_public
|
||||
db.session.commit()
|
||||
return '', 204
|
||||
|
||||
|
||||
@bp.route('/<hashid:corpus_id>/is_public/disable', methods=['POST'])
|
||||
@bp.route('/<hashid:corpus_id>/followers/add', methods=['POST'])
|
||||
@login_required
|
||||
@owner_or_admin_required()
|
||||
def disable_corpus_is_public(corpus_id):
|
||||
def add_corpus_followers(corpus_id):
|
||||
usernames = request.json
|
||||
if not (isinstance(usernames, list) or all(isinstance(u, str) for u in usernames)):
|
||||
response = jsonify('The request body must be a list of strings')
|
||||
response.status_code = 400
|
||||
abort(response)
|
||||
corpus = Corpus.query.get_or_404(corpus_id)
|
||||
corpus.is_public = False
|
||||
for username in usernames:
|
||||
user = User.query.filter_by(username=username, is_public=True).first_or_404()
|
||||
user.follow_corpus(corpus)
|
||||
db.session.commit()
|
||||
return '', 204
|
||||
|
||||
@ -169,14 +182,12 @@ def create_corpus():
|
||||
@login_required
|
||||
def corpus(corpus_id):
|
||||
corpus = Corpus.query.get_or_404(corpus_id)
|
||||
exp_date = (datetime.utcnow() + timedelta(days=7)).strftime('%b %d, %Y')
|
||||
roles = [x.name for x in CorpusFollowerRole.query.all()]
|
||||
corpus_follower_roles = CorpusFollowerRole.query.all()
|
||||
if corpus.user == current_user or current_user.is_administrator():
|
||||
return render_template(
|
||||
'corpora/corpus.html.j2',
|
||||
corpus=corpus,
|
||||
exp_date=exp_date,
|
||||
roles=roles,
|
||||
corpus_follower_roles=corpus_follower_roles,
|
||||
title='Corpus'
|
||||
)
|
||||
if current_user.is_following_corpus(corpus) or corpus.is_public:
|
||||
@ -191,6 +202,7 @@ def corpus(corpus_id):
|
||||
)
|
||||
abort(403)
|
||||
|
||||
|
||||
@bp.route('/<hashid:corpus_id>/generate-corpus-share-link', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@corpus_follower_permission_required('GENERATE_SHARE_LINK')
|
||||
|
@ -12,16 +12,6 @@ class CorpusDisplay extends RessourceDisplay {
|
||||
.addEventListener('click', (event) => {
|
||||
Utils.deleteCorpusRequest(this.userId, this.corpusId);
|
||||
});
|
||||
this.displayElement
|
||||
.querySelector('.action-switch[data-action="toggle-is-public"]')
|
||||
.addEventListener('click', (event) => {
|
||||
if (event.target.tagName !== 'INPUT') {return;}
|
||||
if (event.target.checked) {
|
||||
Utils.enableCorpusIsPublicRequest(this.userId, this.corpusId);
|
||||
} else {
|
||||
Utils.disableCorpusIsPublicRequest(this.userId, this.corpusId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
init(user) {
|
||||
@ -31,7 +21,6 @@ class CorpusDisplay extends RessourceDisplay {
|
||||
this.setStatus(corpus.status);
|
||||
this.setTitle(corpus.title);
|
||||
this.setNumTokens(corpus.num_tokens);
|
||||
this.setShareLink();
|
||||
}
|
||||
|
||||
onPatch(patch) {
|
||||
@ -82,7 +71,7 @@ class CorpusDisplay extends RessourceDisplay {
|
||||
}
|
||||
|
||||
setStatus(status) {
|
||||
let elements = this.displayElement.querySelectorAll('.corpus-analyse-trigger')
|
||||
let elements = this.displayElement.querySelectorAll('.action-button[data-action="analyze"]');
|
||||
for (let element of elements) {
|
||||
if (['BUILT', 'STARTING_ANALYSIS_SESSION', 'RUNNING_ANALYSIS_SESSION', 'CANCELING_ANALYSIS_SESSION'].includes(status)) {
|
||||
element.classList.remove('disabled');
|
||||
@ -118,28 +107,4 @@ class CorpusDisplay extends RessourceDisplay {
|
||||
new Date(creationDate).toLocaleString("en-US")
|
||||
);
|
||||
}
|
||||
|
||||
setShareLink() {
|
||||
let generateShareLinkButton = this.displayElement.querySelector('#generate-share-link-button');
|
||||
let copyShareLinkButton = this.displayElement.querySelector('#copy-share-link-button');
|
||||
let shareLinkInput = this.displayElement.querySelector('#share-link-input');
|
||||
let shareLinkContainer = this.displayElement.querySelector('#share-link-container');
|
||||
let roleSelect = this.displayElement.querySelector('#role-select');
|
||||
let expirationDate = this.displayElement.querySelector('#expiration');
|
||||
|
||||
|
||||
generateShareLinkButton.addEventListener('click', () => {
|
||||
Utils.generateCorpusShareLinkRequest(`${this.corpusId}`, roleSelect.value, expirationDate.value)
|
||||
.then((shareLink) => {
|
||||
shareLinkContainer.classList.remove('hide');
|
||||
shareLinkInput.value = shareLink;
|
||||
});
|
||||
});
|
||||
|
||||
copyShareLinkButton.addEventListener('click', () => {
|
||||
shareLinkInput.select();
|
||||
navigator.clipboard.writeText(shareLinkInput.value);
|
||||
app.flash(`Copied!`, 'success');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,36 @@ class Utils {
|
||||
return Utils.mergeObjectsDeep(mergedObject, ...objects.slice(2));
|
||||
}
|
||||
|
||||
static updateCorpusIsPublicRequest(corpusId, isPublic) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let fetchRessource = `/corpora/${corpusId}/is_public`;
|
||||
let fetchOptions = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(isPublic)
|
||||
};
|
||||
fetch(fetchRessource, fetchOptions)
|
||||
.then(
|
||||
(response) => {
|
||||
if (response.ok) {
|
||||
app.flash(`Corpus is now ${isPublic ? 'public' : 'private'}`, 'corpus');
|
||||
resolve(response);
|
||||
} else {
|
||||
app.flash(`${response.statusText}`, 'error');
|
||||
reject(response);
|
||||
}
|
||||
},
|
||||
(response) => {
|
||||
app.flash('Something went wrong', 'error');
|
||||
reject(response);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
static updateCorpusFollowerRole(corpusId, followerId, roleName) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch(`/corpora/${corpusId}/followers/${followerId}/role`, {method: 'POST', headers: {Accept: 'application/json', 'Content-Type': 'application/json'}, body: JSON.stringify({role: roleName})})
|
||||
@ -91,79 +121,27 @@ class Utils {
|
||||
});
|
||||
}
|
||||
|
||||
static enableCorpusIsPublicRequest(userId, corpusId) {
|
||||
static addCorpusFollowersRequest(corpusId, usernames) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let corpus;
|
||||
try {
|
||||
corpus = app.data.users[userId].corpora[corpusId];
|
||||
} catch (error) {
|
||||
corpus = {};
|
||||
}
|
||||
|
||||
let modalElement = Utils.HTMLToElement(
|
||||
`
|
||||
<div class="modal">
|
||||
<div class="modal-content">
|
||||
<h4>Hier könnte eine Warnung stehen</h4>
|
||||
<p></p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<a class="action-button btn modal-close waves-effect waves-light" data-action="cancel">Cancel</a>
|
||||
<a class="action-button btn modal-close red waves-effect waves-light" data-action="confirm">Confirm</a>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
);
|
||||
document.querySelector('#modals').appendChild(modalElement);
|
||||
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) => {
|
||||
let corpusTitle = corpus?.title;
|
||||
fetch(`/corpora/${corpusId}/is_public/enable`, {method: 'POST', headers: {Accept: 'application/json'}})
|
||||
.then(
|
||||
(response) => {
|
||||
if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
|
||||
if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
|
||||
app.flash(`Corpus "${corpusTitle}" is public now`, 'corpus');
|
||||
resolve(response);
|
||||
},
|
||||
(response) => {
|
||||
app.flash('Something went wrong', 'error');
|
||||
reject(response);
|
||||
}
|
||||
);
|
||||
});
|
||||
modal.open();
|
||||
});
|
||||
}
|
||||
|
||||
static disableCorpusIsPublicRequest(userId, corpusId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let corpus;
|
||||
try {
|
||||
corpus = app.data.users[userId].corpora[corpusId];
|
||||
} catch (error) {
|
||||
corpus = {};
|
||||
}
|
||||
|
||||
let corpusTitle = corpus?.title;
|
||||
fetch(`/corpora/${corpusId}/is_public/disable`, {method: 'POST', headers: {Accept: 'application/json'}})
|
||||
let fetchRessource = `/corpora/${corpusId}/followers/add`;
|
||||
let fetchOptions = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(usernames)
|
||||
};
|
||||
fetch(fetchRessource, fetchOptions)
|
||||
.then(
|
||||
(response) => {
|
||||
if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);}
|
||||
if (response.status === 404) {app.flash('Not Found', 'error'); reject(response);}
|
||||
app.flash(`Corpus "${corpusTitle}" is private now`, 'corpus');
|
||||
resolve(response);
|
||||
if (response.ok) {
|
||||
app.flash(`${usernames.length > 1 ? 'Users are' : 'User is'} following now`, 'corpus');
|
||||
resolve(response);
|
||||
} else {
|
||||
app.flash(`${response.statusText}`, 'error');
|
||||
reject(response);
|
||||
}
|
||||
},
|
||||
(response) => {
|
||||
app.flash('Something went wrong', 'error');
|
||||
|
@ -8,13 +8,11 @@
|
||||
<div class="container">
|
||||
<div class="row" data-corpus-id="{{ corpus.hashid }}" data-user-id="{{ corpus.user.hashid }}" id="corpus-display">
|
||||
<div class="col s12">
|
||||
<div class="row">
|
||||
<div class="col s8 m9 l10">
|
||||
<h1 id="title"><span class="corpus-title"></span></h1>
|
||||
</div>
|
||||
<div class="col s4 m3 l2 right-align">
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<h1 id="title"><span class="corpus-title"></span></h1>
|
||||
</div>
|
||||
<div class="col s12 l8">
|
||||
<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">
|
||||
@ -29,11 +27,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</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">
|
||||
<div class="input-field">
|
||||
@ -57,12 +50,35 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<div class="right-align">
|
||||
<a class="btn corpus-analyse-trigger disabled waves-effect waves-light" href="{{ url_for('corpora.analyse_corpus', corpus_id=corpus.id) }}"><i class="material-icons left">search</i>Analyze</a>
|
||||
<a class="action-button btn disabled waves-effect waves-light" data-action="build-request"><i class="nopaque-icons left">K</i>Build</a>
|
||||
<a class="btn disabled export-corpus-trigger waves-effect waves-light" href="{{ url_for('corpora.export_corpus', corpus_id=corpus.id) }}"><i class="material-icons left">import_export</i>Export</a>
|
||||
<a class="action-button btn red waves-effect waves-light" data-action="delete-request"><i class="material-icons left">delete</i>Delete</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col s12 l4">
|
||||
<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.analyse_corpus', 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="action-button btn red waves-effect waves-light" data-action="delete-request" style="width: 100%;"><i class="material-icons left">delete</i>Delete</a>
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
@ -80,73 +96,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col s12">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<span class="card-title">Share your Corpus</span>
|
||||
<br>
|
||||
<p></p>
|
||||
<p><b>Change your Corpus Status to Public</b></p>
|
||||
<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="action-switch switch" data-action="toggle-is-public">
|
||||
<span class="share"></span>
|
||||
<label>
|
||||
<input {% if corpus.is_public %}checked{% endif %} type="checkbox">
|
||||
<span class="lever"></span>
|
||||
public
|
||||
</label>
|
||||
</div>
|
||||
<br>
|
||||
<p></p>
|
||||
<hr style="height:1px;border:none;color:grey;background-color:grey;">
|
||||
<br>
|
||||
<p></p>
|
||||
<p><b>Create a link to share your corpus files with your team</b></p>
|
||||
<p><i>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.</i></p>
|
||||
<br>
|
||||
<div class="row">
|
||||
<div class="col s4">
|
||||
<div class="input-field">
|
||||
<select id="role-select">
|
||||
{% for role in roles%}
|
||||
<option value="{{role}}">{{role}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label>Role</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col s4">
|
||||
<div class="input-field">
|
||||
<input type="text" class="datepicker" value="{{exp_date}}" id="expiration">
|
||||
<label for="expiration-date">Expiration date</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col s12">
|
||||
<a class="action-button btn waves-effect waves-light" id="generate-share-link-button">Generate Share Link</a>
|
||||
</div>
|
||||
<div class="col s12 hide" id="share-link-container">
|
||||
<p></p>
|
||||
<br>
|
||||
<div class="row">
|
||||
<div class="col s1">
|
||||
<a class="action-button btn-small waves-effect waves-light" id="copy-share-link-button">Copy</a>
|
||||
</div>
|
||||
<div class="col s11">
|
||||
<input id="share-link-input" readonly>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col s12"></div>
|
||||
|
||||
<div class="col s12">
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
@ -159,9 +110,215 @@
|
||||
</div>
|
||||
{% endblock page_content %}
|
||||
|
||||
{% block modals %}
|
||||
{{ super() }}
|
||||
<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 no-autoinit" id="invite-user-modal">
|
||||
<div class="modal-content">
|
||||
<h4>Invite a nopaque user by username</h4>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
|
||||
</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>
|
||||
<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 corpus_follower_role in corpus_follower_roles %}
|
||||
<option value="{{ corpus_follower_role.hashid }}">{{ corpus_follower_role.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label>Role</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col s12 l2">
|
||||
<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 l6">
|
||||
<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>
|
||||
{% endblock modals %}
|
||||
|
||||
{% block scripts %}
|
||||
{{ super() }}
|
||||
<script>
|
||||
let corpusId = {{ corpus.hashid|tojson }};
|
||||
let corpusDisplay = new CorpusDisplay(document.querySelector('#corpus-display'));
|
||||
|
||||
// #region publishing_modal_js
|
||||
let publishingModalIsPublicSwitchElement = document.querySelector('#publishing-modal-is-public-switch');
|
||||
publishingModalIsPublicSwitchElement.addEventListener('change', (event) => {
|
||||
let newIsPublic = publishingModalIsPublicSwitchElement.checked;
|
||||
Utils.updateCorpusIsPublicRequest(corpusId, newIsPublic)
|
||||
.catch((response) => {
|
||||
publishingModalIsPublicSwitchElement.checked = !newIsPublic;
|
||||
});
|
||||
});
|
||||
// #endregion publishing_modal_js
|
||||
|
||||
// #region invite_user_modal_js
|
||||
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 inviteUserModalSearch = M.Chips.init(
|
||||
inviteUserModalSearchElement,
|
||||
{
|
||||
autocompleteOptions: {
|
||||
data: {
|
||||
'nopaque': '/users/3V8Aqpg74JvxOd9o/avatar',
|
||||
'pjentsch': '/users/3V8Aqpg74JvxOd9o/avatar',
|
||||
'pjentsch2': '/users/3V8Aqpg74JvxOd9o/avatar'
|
||||
}
|
||||
},
|
||||
limit: 3,
|
||||
onChipAdd: (a, chipElement) => {
|
||||
if (!(chipElement.firstChild.data in inviteUserModalSearch.autocomplete.options.data)) {
|
||||
chipElement.firstElementChild.click();
|
||||
}
|
||||
},
|
||||
placeholder: 'Enter a 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);
|
||||
Utils.addCorpusFollowersRequest(corpusId, usernames);
|
||||
});
|
||||
// #endregion invite_user_modal_js
|
||||
|
||||
// #region share_link_modal_js
|
||||
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) => {
|
||||
Utils.generateCorpusShareLinkRequest(corpusId, shareLinkModalCorpusFollowerRoleSelectElement.value, shareLinkModalExpirationDateDatepickerElement.value)
|
||||
.then((shareLink) => {
|
||||
shareLinkModalOutputContainerElement.classList.remove('hide');
|
||||
shareLinkModalOutputFieldElement.value = shareLink;
|
||||
});
|
||||
});
|
||||
|
||||
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_modal_js
|
||||
</script>
|
||||
{% endblock scripts %}
|
||||
|
Loading…
Reference in New Issue
Block a user