mirror of
https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
synced 2025-01-13 11:40:35 +00:00
Compare commits
3 Commits
c046fbfb1e
...
f4d3415c11
Author | SHA1 | Date | |
---|---|---|---|
|
f4d3415c11 | ||
|
965f2854b2 | ||
|
f101a742a9 |
@ -12,65 +12,65 @@ from ..decorators import corpus_follower_permission_required
|
|||||||
from . import bp
|
from . import bp
|
||||||
|
|
||||||
|
|
||||||
# @bp.route('/<hashid:corpus_id>/followers', methods=['POST'])
|
@bp.route('/<hashid:corpus_id>/followers', methods=['POST'])
|
||||||
# @corpus_follower_permission_required('MANAGE_FOLLOWERS')
|
@corpus_follower_permission_required('MANAGE_FOLLOWERS')
|
||||||
# @content_negotiation(consumes='application/json', produces='application/json')
|
@content_negotiation(consumes='application/json', produces='application/json')
|
||||||
# def create_corpus_followers(corpus_id):
|
def create_corpus_followers(corpus_id):
|
||||||
# usernames = request.json
|
usernames = request.json
|
||||||
# if not (isinstance(usernames, list) or all(isinstance(u, str) for u in usernames)):
|
if not (isinstance(usernames, list) or all(isinstance(u, str) for u in usernames)):
|
||||||
# abort(400)
|
abort(400)
|
||||||
# corpus = Corpus.query.get_or_404(corpus_id)
|
corpus = Corpus.query.get_or_404(corpus_id)
|
||||||
# for username in usernames:
|
for username in usernames:
|
||||||
# user = User.query.filter_by(username=username, is_public=True).first_or_404()
|
user = User.query.filter_by(username=username, is_public=True).first_or_404()
|
||||||
# user.follow_corpus(corpus)
|
user.follow_corpus(corpus)
|
||||||
# db.session.commit()
|
db.session.commit()
|
||||||
# response_data = {
|
response_data = {
|
||||||
# 'message': f'Users are now following "{corpus.title}"',
|
'message': f'Users are now following "{corpus.title}"',
|
||||||
# 'category': 'corpus'
|
'category': 'corpus'
|
||||||
# }
|
}
|
||||||
# return response_data, 200
|
return response_data, 200
|
||||||
|
|
||||||
|
|
||||||
# @bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>/role', methods=['PUT'])
|
@bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>/role', methods=['PUT'])
|
||||||
# @corpus_follower_permission_required('MANAGE_FOLLOWERS')
|
@corpus_follower_permission_required('MANAGE_FOLLOWERS')
|
||||||
# @content_negotiation(consumes='application/json', produces='application/json')
|
@content_negotiation(consumes='application/json', produces='application/json')
|
||||||
# def update_corpus_follower_role(corpus_id, follower_id):
|
def update_corpus_follower_role(corpus_id, follower_id):
|
||||||
# role_name = request.json
|
role_name = request.json
|
||||||
# if not isinstance(role_name, str):
|
if not isinstance(role_name, str):
|
||||||
# abort(400)
|
abort(400)
|
||||||
# cfr = CorpusFollowerRole.query.filter_by(name=role_name).first()
|
cfr = CorpusFollowerRole.query.filter_by(name=role_name).first()
|
||||||
# if cfr is None:
|
if cfr is None:
|
||||||
# abort(400)
|
abort(400)
|
||||||
# cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404()
|
cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404()
|
||||||
# cfa.role = cfr
|
cfa.role = cfr
|
||||||
# db.session.commit()
|
db.session.commit()
|
||||||
# response_data = {
|
response_data = {
|
||||||
# 'message': f'User "{cfa.follower.username}" is now {cfa.role.name}',
|
'message': f'User "{cfa.follower.username}" is now {cfa.role.name}',
|
||||||
# 'category': 'corpus'
|
'category': 'corpus'
|
||||||
# }
|
}
|
||||||
# return response_data, 200
|
return response_data, 200
|
||||||
|
|
||||||
|
|
||||||
# @bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>', methods=['DELETE'])
|
@bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>', methods=['DELETE'])
|
||||||
# def delete_corpus_follower(corpus_id, follower_id):
|
def delete_corpus_follower(corpus_id, follower_id):
|
||||||
# cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404()
|
cfa = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404()
|
||||||
# if not (
|
if not (
|
||||||
# current_user.id == follower_id
|
current_user.id == follower_id
|
||||||
# or current_user == cfa.corpus.user
|
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 CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first().role.has_permission('MANAGE_FOLLOWERS')
|
||||||
# or current_user.is_administrator()):
|
or current_user.is_administrator()):
|
||||||
# abort(403)
|
abort(403)
|
||||||
# if current_user.id == follower_id:
|
if current_user.id == follower_id:
|
||||||
# flash(f'You are no longer following "{cfa.corpus.title}"', 'corpus')
|
flash(f'You are no longer following "{cfa.corpus.title}"', 'corpus')
|
||||||
# response = make_response()
|
response = make_response()
|
||||||
# response.status_code = 204
|
response.status_code = 204
|
||||||
# else:
|
else:
|
||||||
# response_data = {
|
response_data = {
|
||||||
# 'message': f'"{cfa.follower.username}" is not following "{cfa.corpus.title}" anymore',
|
'message': f'"{cfa.follower.username}" is not following "{cfa.corpus.title}" anymore',
|
||||||
# 'category': 'corpus'
|
'category': 'corpus'
|
||||||
# }
|
}
|
||||||
# response = jsonify(response_data)
|
response = jsonify(response_data)
|
||||||
# response.status_code = 200
|
response.status_code = 200
|
||||||
# cfa.follower.unfollow_corpus(cfa.corpus)
|
cfa.follower.unfollow_corpus(cfa.corpus)
|
||||||
# db.session.commit()
|
db.session.commit()
|
||||||
# return response
|
return response
|
||||||
|
@ -78,15 +78,15 @@ def terms_of_use():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# @bp.route('/social-area')
|
@bp.route('/social-area')
|
||||||
# @register_breadcrumb(bp, '.social_area', '<i class="material-icons left">group</i>Social Area')
|
@register_breadcrumb(bp, '.social_area', '<i class="material-icons left">group</i>Social Area')
|
||||||
# @login_required
|
@login_required
|
||||||
# def social_area():
|
def social_area():
|
||||||
# corpora = Corpus.query.filter(Corpus.is_public == True, Corpus.user != current_user).all()
|
corpora = Corpus.query.filter(Corpus.is_public == True, Corpus.user != current_user).all()
|
||||||
# users = User.query.filter(User.is_public == True, User.id != current_user.id).all()
|
users = User.query.filter(User.is_public == True, User.id != current_user.id).all()
|
||||||
# return render_template(
|
return render_template(
|
||||||
# 'main/social_area.html.j2',
|
'main/social_area.html.j2',
|
||||||
# title='Social Area',
|
title='Social Area',
|
||||||
# corpora=corpora,
|
corpora=corpora,
|
||||||
# users=users
|
users=users
|
||||||
# )
|
)
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
// IDEA: Split the App logic into seperate units
|
||||||
|
// - App.Data
|
||||||
|
// - App.IO (name is WIP)
|
||||||
|
// - App.UI
|
||||||
|
|
||||||
App.App = class App {
|
App.App = class App {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.data = {
|
this.data = {
|
||||||
@ -101,4 +106,94 @@ App.App = class App {
|
|||||||
// Apply Patch
|
// Apply Patch
|
||||||
jsonpatch.applyPatch(this.data, filteredPatch);
|
jsonpatch.applyPatch(this.data, filteredPatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.initUi();
|
||||||
|
}
|
||||||
|
|
||||||
|
initUi() {
|
||||||
|
/* Pre-Initialization fixes */
|
||||||
|
// #region
|
||||||
|
|
||||||
|
// Flask-WTF sets the standard HTML maxlength Attribute on input/textarea
|
||||||
|
// elements to specify their maximum length (in characters). Unfortunatly
|
||||||
|
// Materialize won't recognize the maxlength Attribute, instead it uses
|
||||||
|
// the data-length Attribute. It's conversion time :)
|
||||||
|
for (let elem of document.querySelectorAll('input[maxlength], textarea[maxlength]')) {
|
||||||
|
elem.dataset.length = elem.getAttribute('maxlength');
|
||||||
|
elem.removeAttribute('maxlength');
|
||||||
|
}
|
||||||
|
|
||||||
|
// To work around some limitations with the Form setup of Flask-WTF.
|
||||||
|
// HTML option elements with an empty value are considered as placeholder
|
||||||
|
// elements. The user should not be able to actively select these options.
|
||||||
|
// So they get the disabled attribute.
|
||||||
|
for (let optionElement of document.querySelectorAll('option[value=""]')) {
|
||||||
|
optionElement.disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Check why we are doing this.
|
||||||
|
for (let optgroupElement of document.querySelectorAll('optgroup[label=""]')) {
|
||||||
|
for (let c of optgroupElement.children) {
|
||||||
|
optgroupElement.parentElement.insertAdjacentElement('afterbegin', c);
|
||||||
|
}
|
||||||
|
optgroupElement.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
/* Initialize Materialize Components */
|
||||||
|
// #region
|
||||||
|
|
||||||
|
// Automatically initialize Materialize Components that do not require
|
||||||
|
// additional configuration.
|
||||||
|
M.AutoInit();
|
||||||
|
|
||||||
|
// CharacterCounters
|
||||||
|
// Materialize didn't include the CharacterCounter plugin within the
|
||||||
|
// AutoInit method (maybe they forgot it?). Anyway... We do it here. :)
|
||||||
|
M.CharacterCounter.init(document.querySelectorAll('input[data-length]:not(.no-autoinit), textarea[data-length]:not(.no-autoinit)'));
|
||||||
|
|
||||||
|
// Header navigation "more" Dropdown.
|
||||||
|
M.Dropdown.init(
|
||||||
|
document.querySelector('#nav-more-dropdown-trigger'),
|
||||||
|
{
|
||||||
|
alignment: 'right',
|
||||||
|
constrainWidth: false,
|
||||||
|
coverTrigger: false
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Manual modal
|
||||||
|
M.Modal.init(
|
||||||
|
document.querySelector('#manual-modal'),
|
||||||
|
{
|
||||||
|
onOpenStart: (modalElement, modalTriggerElement) => {
|
||||||
|
if ('manualModalChapter' in modalTriggerElement.dataset) {
|
||||||
|
let manualModalTocElement = document.querySelector('#manual-modal-toc');
|
||||||
|
let manualModalToc = M.Tabs.getInstance(manualModalTocElement);
|
||||||
|
manualModalToc.select(modalTriggerElement.dataset.manualModalChapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Terms of use modal
|
||||||
|
M.Modal.init(
|
||||||
|
document.querySelector('#terms-of-use-modal'),
|
||||||
|
{
|
||||||
|
dismissible: false,
|
||||||
|
onCloseEnd: (modalElement) => {
|
||||||
|
Requests.users.entity.acceptTermsOfUse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region Nopaque Components
|
||||||
|
ResourceDisplays.AutoInit();
|
||||||
|
ResourceLists.AutoInit();
|
||||||
|
Forms.AutoInit();
|
||||||
|
// #endregion Nopaque Components
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
var Forms = {};
|
var Forms = {};
|
||||||
|
|
||||||
Forms.autoInit = () => {
|
Forms.AutoInit = () => {
|
||||||
for (let propertyName in Forms) {
|
for (let propertyName in Forms) {
|
||||||
let property = Forms[propertyName];
|
let property = Forms[propertyName];
|
||||||
// Call autoInit of all properties that are subclasses of Forms.BaseForm.
|
// Call autoInit of all properties that are subclasses of Forms.BaseForm.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
var ResourceDisplays = {};
|
var ResourceDisplays = {};
|
||||||
|
|
||||||
ResourceDisplays.autoInit = () => {
|
ResourceDisplays.AutoInit = () => {
|
||||||
for (let propertyName in ResourceDisplays) {
|
for (let propertyName in ResourceDisplays) {
|
||||||
let property = ResourceDisplays[propertyName];
|
let property = ResourceDisplays[propertyName];
|
||||||
// Call autoInit of all properties that are subclasses of `ResourceDisplays.ResourceDisplay`.
|
// Call autoInit of all properties that are subclasses of `ResourceDisplays.ResourceDisplay`.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
var ResourceLists = {};
|
var ResourceLists = {};
|
||||||
|
|
||||||
ResourceLists.autoInit = () => {
|
ResourceLists.AutoInit = () => {
|
||||||
for (let propertyName in ResourceLists) {
|
for (let propertyName in ResourceLists) {
|
||||||
let property = ResourceLists[propertyName];
|
let property = ResourceLists[propertyName];
|
||||||
// Call autoInit of all properties that are subclasses of `ResourceLists.ResourceList`.
|
// Call autoInit of all properties that are subclasses of `ResourceLists.ResourceList`.
|
||||||
|
@ -119,76 +119,29 @@
|
|||||||
<script>
|
<script>
|
||||||
// TODO: Implement an app.run method and use this for all of the following
|
// TODO: Implement an app.run method and use this for all of the following
|
||||||
const app = new App.App();
|
const app = new App.App();
|
||||||
|
app.init();
|
||||||
|
|
||||||
|
// Check if the current user is authenticated
|
||||||
{%- if current_user.is_authenticated %}
|
{%- if current_user.is_authenticated %}
|
||||||
|
// TODO: Set this as a property of the app object
|
||||||
const currentUserId = {{ current_user.hashid|tojson }};
|
const currentUserId = {{ current_user.hashid|tojson }};
|
||||||
|
|
||||||
// Initialize components for current user
|
// Subscribe to the current user's data events
|
||||||
app.subscribeUser(currentUserId)
|
app.subscribeUser(currentUserId)
|
||||||
.catch((error) => {throw JSON.stringify(error);});
|
.catch((error) => {throw JSON.stringify(error);});
|
||||||
|
|
||||||
|
// Get the current user's data
|
||||||
app.getUser(currentUserId, true, true)
|
app.getUser(currentUserId, true, true)
|
||||||
.catch((error) => {throw JSON.stringify(error);});
|
.catch((error) => {throw JSON.stringify(error);});
|
||||||
|
|
||||||
|
// Check if the current user hasn't accepted the terms of use yet
|
||||||
|
{%- if not current_user.terms_of_use_accepted %}
|
||||||
|
M.Modal.getInstance(document.querySelector('#terms-of-use-modal')).open();
|
||||||
|
{%- endif %}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
// Disable all option elements with no value
|
|
||||||
for (let optionElement of document.querySelectorAll('option[value=""]')) {
|
|
||||||
optionElement.disabled = true;
|
|
||||||
}
|
|
||||||
for (let optgroupElement of document.querySelectorAll('optgroup[label=""]')) {
|
|
||||||
for (let c of optgroupElement.children) {
|
|
||||||
optgroupElement.parentElement.insertAdjacentElement('afterbegin', c);
|
|
||||||
}
|
|
||||||
optgroupElement.remove();
|
|
||||||
|
|
||||||
}
|
|
||||||
// Set the data-length attribute on textareas/inputs with the maxlength attribute
|
|
||||||
for (let inputElement of document.querySelectorAll('textarea[maxlength], input[maxlength]')) {
|
|
||||||
inputElement.dataset.length = inputElement.getAttribute('maxlength');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize components
|
|
||||||
M.AutoInit();
|
|
||||||
M.CharacterCounter.init(document.querySelectorAll('input[data-length], textarea[data-length]'));
|
|
||||||
M.Dropdown.init(
|
|
||||||
document.querySelectorAll('#nav-more-dropdown-trigger'),
|
|
||||||
{alignment: 'right', constrainWidth: false, coverTrigger: false}
|
|
||||||
);
|
|
||||||
ResourceDisplays.autoInit();
|
|
||||||
ResourceLists.autoInit();
|
|
||||||
Forms.autoInit();
|
|
||||||
|
|
||||||
// Display flashed messages
|
// Display flashed messages
|
||||||
for (let [category, message] of {{ get_flashed_messages(with_categories=True)|tojson }}) {
|
for (let [category, message] of {{ get_flashed_messages(with_categories=True)|tojson }}) {
|
||||||
app.flash(message, message);
|
app.flash(message, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize manual modal
|
|
||||||
let manualModalTableOfContentsElement = document.querySelector('#manual-modal-table-of-contents');
|
|
||||||
let manualModalTableOfContents = M.Tabs.init(manualModalTableOfContentsElement);
|
|
||||||
let manualModalElement = document.querySelector('#manual-modal');
|
|
||||||
let manualModal = M.Modal.init(
|
|
||||||
manualModalElement,
|
|
||||||
{
|
|
||||||
onOpenStart: (manualModalElement, modalTriggerElement) => {
|
|
||||||
if ('manualModalChapter' in modalTriggerElement.dataset) {
|
|
||||||
manualModalTableOfContents.select(modalTriggerElement.dataset.manualModalChapter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Initialize terms of use modal
|
|
||||||
const termsOfUseModal = document.getElementById('terms-of-use-modal');
|
|
||||||
M.Modal.init(
|
|
||||||
termsOfUseModal,
|
|
||||||
{
|
|
||||||
dismissible: false,
|
|
||||||
onCloseEnd: () => {
|
|
||||||
requests.users.entity.acceptTermsOfUse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
{% if current_user.is_authenticated and not current_user.terms_of_use_accepted %}
|
|
||||||
termsOfUseModal.M_Modal.open();
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -3,13 +3,12 @@
|
|||||||
<div class="user-view" style="padding-top: 1px; padding-left: 20px !important; padding-right: 20px !important; height: 112px;">
|
<div class="user-view" style="padding-top: 1px; padding-left: 20px !important; padding-right: 20px !important; height: 112px;">
|
||||||
<div class="background primary-color"></div>
|
<div class="background primary-color"></div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{# <div class="col s5">
|
<div class="col s5">
|
||||||
<a href="{{ url_for('users.user', user_id=current_user.id) }}">
|
<a href="{{ url_for('users.user', user_id=current_user.id) }}">
|
||||||
<img src="{{ url_for('users.user_avatar', user_id=current_user.id) }}" alt="user-image" class="circle responsive-img" style="height:80%; margin-top: 22px;">
|
<img src="{{ url_for('users.user_avatar', user_id=current_user.id) }}" alt="user-image" class="circle responsive-img" style="height:80%; margin-top: 22px;">
|
||||||
</a>
|
</a>
|
||||||
</div> #}
|
</div>
|
||||||
{# Change col s12 to col s5 to show user image #}
|
<div class="col s5" style="word-wrap: break-word; margin-left:-10px;">
|
||||||
<div class="col s12" style="word-wrap: break-word; margin-left:-10px;">
|
|
||||||
<span class="white-text name">
|
<span class="white-text name">
|
||||||
{% if current_user.username|length > 18 %}
|
{% if current_user.username|length > 18 %}
|
||||||
{{ current_user.username[:15] + '...' }}
|
{{ current_user.username[:15] + '...' }}
|
||||||
@ -71,7 +70,7 @@
|
|||||||
<li class="service-color service-color-border border-darken" data-service="corpus-analysis" style="border-left: 10px solid; margin-top: 5px;">
|
<li class="service-color service-color-border border-darken" data-service="corpus-analysis" style="border-left: 10px solid; margin-top: 5px;">
|
||||||
<a class="waves-effect" href="{{ url_for('services.corpus_analysis') }}"><i class="nopaque-icons service-icons" data-service="corpus-analysis"></i>Corpus Analysis</a>
|
<a class="waves-effect" href="{{ url_for('services.corpus_analysis') }}"><i class="nopaque-icons service-icons" data-service="corpus-analysis"></i>Corpus Analysis</a>
|
||||||
</li>
|
</li>
|
||||||
{# <li><div class="divider"></div></li>
|
<li><div class="divider"></div></li>
|
||||||
<li>
|
<li>
|
||||||
<a class="waves-effect" class="waves-effect" href="{{ url_for('main.social_area') }}"><i class="material-icons">rocket_launch</i>Social Area</a>
|
<a class="waves-effect" class="waves-effect" href="{{ url_for('main.social_area') }}"><i class="material-icons">rocket_launch</i>Social Area</a>
|
||||||
<ul>
|
<ul>
|
||||||
@ -82,7 +81,7 @@
|
|||||||
<a class="waves-effect" href="{{ url_for('main.social_area', _anchor='public-corpora') }}" style="padding-left: 47px;"><i class="nopaque-icons">I</i>Public Corpora</a>
|
<a class="waves-effect" href="{{ url_for('main.social_area', _anchor='public-corpora') }}" style="padding-left: 47px;"><i class="nopaque-icons">I</i>Public Corpora</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li> #}
|
</li>
|
||||||
<li class="hide-on-large-only"><div class="divider"></div></li>
|
<li class="hide-on-large-only"><div class="divider"></div></li>
|
||||||
<li class="hide-on-large-only"><a class="subheader">Account</a></li>
|
<li class="hide-on-large-only"><a class="subheader">Account</a></li>
|
||||||
<li class="hide-on-large-only">
|
<li class="hide-on-large-only">
|
||||||
|
@ -65,14 +65,14 @@
|
|||||||
<div class="col s12 l6" style="padding: 0 2.5px;">
|
<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>
|
<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>
|
||||||
{# <div class="col s12 l6" style="padding: 5px 2.5px 0 2.5px;">
|
<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>
|
<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>
|
||||||
<div class="col s12 l6" style="padding: 5px 2.5px 0 2.5px;">
|
<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>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
{# {% if cfr.has_permission('MANAGE_FOLLOWERS') %}
|
{% if cfr.has_permission('MANAGE_FOLLOWERS') %}
|
||||||
<span class="card-title">Social</span>
|
<span class="card-title">Social</span>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col s12 l6" style="padding: 0 2.5px;">
|
<div class="col s12 l6" style="padding: 0 2.5px;">
|
||||||
@ -82,7 +82,7 @@
|
|||||||
<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>
|
<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>
|
||||||
{% endif %} #}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -102,7 +102,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# {% if cfr.has_permission('MANAGE_FOLLOWERS') %}
|
{% if cfr.has_permission('MANAGE_FOLLOWERS') %}
|
||||||
<div class="col s12">
|
<div class="col s12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
@ -111,7 +111,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %} #}
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -121,7 +121,7 @@
|
|||||||
{{ super() }}
|
{{ super() }}
|
||||||
|
|
||||||
{% if current_user == corpus.user or current_user.is_administrator() %}
|
{% if current_user == corpus.user or current_user.is_administrator() %}
|
||||||
{# <div class="modal" id="publishing-modal">
|
<div class="modal" id="publishing-modal">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<h4>Change your Corpus publishing status</h4>
|
<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>
|
<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>
|
||||||
@ -138,7 +138,7 @@
|
|||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<a class="modal-close waves-effect waves-green btn-flat">Close</a>
|
<a class="modal-close waves-effect waves-green btn-flat">Close</a>
|
||||||
</div>
|
</div>
|
||||||
</div> #}
|
</div>
|
||||||
|
|
||||||
<div class="modal" id="delete-modal">
|
<div class="modal" id="delete-modal">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
@ -152,7 +152,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# {% if cfr.has_permission('MANAGE_FOLLOWERS') %}
|
{% if cfr.has_permission('MANAGE_FOLLOWERS') %}
|
||||||
<div class="modal no-autoinit" id="invite-user-modal">
|
<div class="modal no-autoinit" id="invite-user-modal">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<h4>Invite a nopaque user by username</h4>
|
<h4>Invite a nopaque user by username</h4>
|
||||||
@ -230,14 +230,14 @@
|
|||||||
<a class="modal-close waves-effect waves-green btn-flat">Close</a>
|
<a class="modal-close waves-effect waves-green btn-flat">Close</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %} #}
|
{% endif %}
|
||||||
|
|
||||||
{% endblock modals %}
|
{% endblock modals %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
<script>
|
<script>
|
||||||
{# {% if current_user.is_following_corpus(corpus) %}
|
{% if current_user.is_following_corpus(corpus) %}
|
||||||
let unfollowRequestElement = document.querySelector('.action-button[data-action="unfollow-request"]');
|
let unfollowRequestElement = document.querySelector('.action-button[data-action="unfollow-request"]');
|
||||||
unfollowRequestElement.addEventListener('click', () => {
|
unfollowRequestElement.addEventListener('click', () => {
|
||||||
requests.corpora.entity.followers.entity.delete({{ corpus.hashid|tojson }}, {{ current_user.hashid|tojson }})
|
requests.corpora.entity.followers.entity.delete({{ corpus.hashid|tojson }}, {{ current_user.hashid|tojson }})
|
||||||
@ -245,18 +245,18 @@
|
|||||||
window.location.reload();
|
window.location.reload();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
{% endif %} #}
|
{% endif %}
|
||||||
|
|
||||||
{% if current_user == corpus.user or current_user.is_administrator() %}
|
{% if current_user == corpus.user or current_user.is_administrator() %}
|
||||||
// #region Publishing
|
// #region Publishing
|
||||||
{# let publishingModalIsPublicSwitchElement = document.querySelector('#publishing-modal-is-public-switch');
|
let publishingModalIsPublicSwitchElement = document.querySelector('#publishing-modal-is-public-switch');
|
||||||
publishingModalIsPublicSwitchElement.addEventListener('change', (event) => {
|
publishingModalIsPublicSwitchElement.addEventListener('change', (event) => {
|
||||||
let newIsPublic = publishingModalIsPublicSwitchElement.checked;
|
let newIsPublic = publishingModalIsPublicSwitchElement.checked;
|
||||||
requests.corpora.entity.isPublic.update({{ corpus.hashid|tojson }}, newIsPublic)
|
requests.corpora.entity.isPublic.update({{ corpus.hashid|tojson }}, newIsPublic)
|
||||||
.catch((response) => {
|
.catch((response) => {
|
||||||
publishingModalIsPublicSwitchElement.checked = !newIsPublic;
|
publishingModalIsPublicSwitchElement.checked = !newIsPublic;
|
||||||
});
|
});
|
||||||
}); #}
|
});
|
||||||
// #endregion Publishing
|
// #endregion Publishing
|
||||||
|
|
||||||
// #region Delete
|
// #region Delete
|
||||||
@ -272,7 +272,7 @@ deleteModalDeleteButtonElement.addEventListener('click', (event) => {
|
|||||||
|
|
||||||
{% if cfr.has_permission('MANAGE_FOLLOWERS') %}
|
{% if cfr.has_permission('MANAGE_FOLLOWERS') %}
|
||||||
// #region Invite user
|
// #region Invite user
|
||||||
{# let inviteUserModalElement = document.querySelector('#invite-user-modal');
|
let inviteUserModalElement = document.querySelector('#invite-user-modal');
|
||||||
let inviteUserModalSearchElement = document.querySelector('#invite-user-modal-search');
|
let inviteUserModalSearchElement = document.querySelector('#invite-user-modal-search');
|
||||||
let inviteUserModalInviteButtonElement = document.querySelector('#invite-user-modal-invite-button');
|
let inviteUserModalInviteButtonElement = document.querySelector('#invite-user-modal-invite-button');
|
||||||
let users = {
|
let users = {
|
||||||
@ -374,7 +374,7 @@ shareLinkModalOutputCopyButtonElement.addEventListener('click', (event) => {
|
|||||||
() => {app.flash('Could not copy to clipboard. Please copy manually.', 'error');}
|
() => {app.flash('Could not copy to clipboard. Please copy manually.', 'error');}
|
||||||
);
|
);
|
||||||
|
|
||||||
}); #}
|
});
|
||||||
// #endregion Share link
|
// #endregion Share link
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<div id="manual-modal" class="modal no-autoinit">
|
<div id="manual-modal" class="modal no-autoinit">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<h2>Manual</h2>
|
<h2>Manual</h2>
|
||||||
<ul class="tabs no-autoinit" id="manual-modal-table-of-contents">
|
<ul class="tabs" id="manual-modal-toc">
|
||||||
<li class="tab"><a href="#manual-modal-introduction">Introduction</a></li>
|
<li class="tab"><a href="#manual-modal-introduction">Introduction</a></li>
|
||||||
<li class="tab"><a href="#manual-modal-registration-and-log-in">Registration and Log in</a></li>
|
<li class="tab"><a href="#manual-modal-registration-and-log-in">Registration and Log in</a></li>
|
||||||
<li class="tab"><a href="#manual-modal-dashboard">Dashboard</a></li>
|
<li class="tab"><a href="#manual-modal-dashboard">Dashboard</a></li>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<h1 id="title">{{ title }}</h1>
|
<h1 id="title">{{ title }}</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# <div class="col s12 l4">
|
<div class="col s12 l4">
|
||||||
<h4>Profile Settings</h4>
|
<h4>Profile Settings</h4>
|
||||||
<p>You can edit your public profile here and share it with other nopaque users.
|
<p>You can edit your public profile here and share it with other nopaque users.
|
||||||
Tell others about your (scientific) background so they can relate and network with you.
|
Tell others about your (scientific) background so they can relate and network with you.
|
||||||
@ -112,7 +112,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col s12"></div> #}
|
<div class="col s12"></div>
|
||||||
|
|
||||||
<div class="col s12 l4">
|
<div class="col s12 l4">
|
||||||
<h4>General Settings</h4>
|
<h4>General Settings</h4>
|
||||||
@ -181,7 +181,7 @@
|
|||||||
|
|
||||||
{% block modals %}
|
{% block modals %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
{# <div class="modal" id="delete-avatar-modal">
|
<div class="modal" id="delete-avatar-modal">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<h4>Confirm Avatar deletion</h4>
|
<h4>Confirm Avatar deletion</h4>
|
||||||
<p>Do you really want to delete <b>{{ user.username }}</b>’s avatar?</p>
|
<p>Do you really want to delete <b>{{ user.username }}</b>’s avatar?</p>
|
||||||
@ -190,7 +190,7 @@
|
|||||||
<a class="btn modal-close waves-effect waves-light">Cancel</a>
|
<a class="btn modal-close waves-effect waves-light">Cancel</a>
|
||||||
<a class="btn modal-close red waves-effect waves-light" id="delete-avatar">Delete</a>
|
<a class="btn modal-close red waves-effect waves-light" id="delete-avatar">Delete</a>
|
||||||
</div>
|
</div>
|
||||||
</div> #}
|
</div>
|
||||||
|
|
||||||
<div class="modal" id="delete-user-modal">
|
<div class="modal" id="delete-user-modal">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
@ -212,7 +212,7 @@
|
|||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
<script>
|
<script>
|
||||||
{# let avatarPreviewElement = document.querySelector('#update-avatar-form-avatar-preview');
|
let avatarPreviewElement = document.querySelector('#update-avatar-form-avatar-preview');
|
||||||
let avatarUploadElement = document.querySelector('#update-avatar-form-avatar');
|
let avatarUploadElement = document.querySelector('#update-avatar-form-avatar');
|
||||||
|
|
||||||
avatarUploadElement.addEventListener('change', () => {
|
avatarUploadElement.addEventListener('change', () => {
|
||||||
@ -221,16 +221,16 @@ avatarUploadElement.addEventListener('change', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
document.querySelector('#delete-avatar').addEventListener('click', () => {
|
document.querySelector('#delete-avatar').addEventListener('click', () => {
|
||||||
requests.users.entity.avatar.delete({{ user.hashid|tojson }})
|
Requests.users.entity.avatar.delete({{ user.hashid|tojson }})
|
||||||
.then(
|
.then(
|
||||||
(response) => {
|
(response) => {
|
||||||
avatarPreviewElement.src = {{ url_for('static', filename='images/user_avatar.png')|tojson }};
|
avatarPreviewElement.src = {{ url_for('static', filename='images/user_avatar.png')|tojson }};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}); #}
|
});
|
||||||
|
|
||||||
document.querySelector('#delete-user').addEventListener('click', (event) => {
|
document.querySelector('#delete-user').addEventListener('click', (event) => {
|
||||||
requests.users.entity.delete({{ user.hashid|tojson }})
|
Requests.users.entity.delete({{ user.hashid|tojson }})
|
||||||
.then((response) => {window.location.href = '/';});
|
.then((response) => {window.location.href = '/';});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -251,11 +251,11 @@ for (let collapsibleElement of document.querySelectorAll('.collapsible.no-autoin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// #region Profile Privacy settings
|
// #region Profile Privacy settings
|
||||||
{# let profileIsPublicSwitchElement = document.querySelector('#profile-is-public-switch');
|
let profileIsPublicSwitchElement = document.querySelector('#profile-is-public-switch');
|
||||||
let profilePrivacySettingCheckboxElements = document.querySelectorAll('.profile-privacy-setting-checkbox');
|
let profilePrivacySettingCheckboxElements = document.querySelectorAll('.profile-privacy-setting-checkbox');
|
||||||
profileIsPublicSwitchElement.addEventListener('change', (event) => {
|
profileIsPublicSwitchElement.addEventListener('change', (event) => {
|
||||||
let newEnabled = profileIsPublicSwitchElement.checked;
|
let newEnabled = profileIsPublicSwitchElement.checked;
|
||||||
requests.users.entity.settings.profilePrivacy.update({{ user.hashid|tojson }}, 'is-public', newEnabled)
|
Requests.users.entity.settings.profilePrivacy.update({{ user.hashid|tojson }}, 'is-public', newEnabled)
|
||||||
.then(
|
.then(
|
||||||
(response) => {
|
(response) => {
|
||||||
for (let profilePrivacySettingCheckboxElement of document.querySelectorAll('.profile-privacy-setting-checkbox')) {
|
for (let profilePrivacySettingCheckboxElement of document.querySelectorAll('.profile-privacy-setting-checkbox')) {
|
||||||
@ -271,12 +271,12 @@ for (let profilePrivacySettingCheckboxElement of profilePrivacySettingCheckboxEl
|
|||||||
profilePrivacySettingCheckboxElement.addEventListener('change', (event) => {
|
profilePrivacySettingCheckboxElement.addEventListener('change', (event) => {
|
||||||
let newEnabled = profilePrivacySettingCheckboxElement.checked;
|
let newEnabled = profilePrivacySettingCheckboxElement.checked;
|
||||||
let valueName = profilePrivacySettingCheckboxElement.dataset.profilePrivacySettingName;
|
let valueName = profilePrivacySettingCheckboxElement.dataset.profilePrivacySettingName;
|
||||||
requests.users.entity.settings.profilePrivacy.update({{ user.hashid|tojson }}, valueName, newEnabled)
|
Requests.users.entity.settings.profilePrivacy.update({{ user.hashid|tojson }}, valueName, newEnabled)
|
||||||
.catch((response) => {
|
.catch((response) => {
|
||||||
profilePrivacySettingCheckboxElement.checked = !newEnabled;
|
profilePrivacySettingCheckboxElement.checked = !newEnabled;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} #}
|
}
|
||||||
// #endregion Profile Privacy settings
|
// #endregion Profile Privacy settings
|
||||||
</script>
|
</script>
|
||||||
{% endblock scripts %}
|
{% endblock scripts %}
|
||||||
|
@ -32,29 +32,29 @@ def delete_user(user_id):
|
|||||||
return response_data, 202
|
return response_data, 202
|
||||||
|
|
||||||
|
|
||||||
# @bp.route('/<hashid:user_id>/avatar', methods=['DELETE'])
|
@bp.route('/<hashid:user_id>/avatar', methods=['DELETE'])
|
||||||
# @content_negotiation(produces='application/json')
|
@content_negotiation(produces='application/json')
|
||||||
# def delete_user_avatar(user_id):
|
def delete_user_avatar(user_id):
|
||||||
# def _delete_avatar(app, avatar_id):
|
def _delete_avatar(app, avatar_id):
|
||||||
# with app.app_context():
|
with app.app_context():
|
||||||
# avatar = Avatar.query.get(avatar_id)
|
avatar = Avatar.query.get(avatar_id)
|
||||||
# avatar.delete()
|
avatar.delete()
|
||||||
# db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
# user = User.query.get_or_404(user_id)
|
user = User.query.get_or_404(user_id)
|
||||||
# if user.avatar is None:
|
if user.avatar is None:
|
||||||
# abort(404)
|
abort(404)
|
||||||
# if not (user == current_user or current_user.is_administrator()):
|
if not (user == current_user or current_user.is_administrator()):
|
||||||
# abort(403)
|
abort(403)
|
||||||
# thread = Thread(
|
thread = Thread(
|
||||||
# target=_delete_avatar,
|
target=_delete_avatar,
|
||||||
# args=(current_app._get_current_object(), user.avatar.id)
|
args=(current_app._get_current_object(), user.avatar.id)
|
||||||
# )
|
)
|
||||||
# thread.start()
|
thread.start()
|
||||||
# response_data = {
|
response_data = {
|
||||||
# 'message': f'Avatar marked for deletion'
|
'message': f'Avatar marked for deletion'
|
||||||
# }
|
}
|
||||||
# return response_data, 202
|
return response_data, 202
|
||||||
|
|
||||||
@bp.route('/accept-terms-of-use', methods=['POST'])
|
@bp.route('/accept-terms-of-use', methods=['POST'])
|
||||||
@content_negotiation(produces='application/json')
|
@content_negotiation(produces='application/json')
|
||||||
|
@ -13,36 +13,36 @@ from . import bp
|
|||||||
from .utils import user_dynamic_list_constructor as user_dlc
|
from .utils import user_dynamic_list_constructor as user_dlc
|
||||||
|
|
||||||
|
|
||||||
# @bp.route('')
|
@bp.route('')
|
||||||
# @register_breadcrumb(bp, '.', '<i class="material-icons left">group</i>Users')
|
@register_breadcrumb(bp, '.', '<i class="material-icons left">group</i>Users')
|
||||||
# def users():
|
def users():
|
||||||
# return redirect(url_for('main.social_area', _anchor='users'))
|
return redirect(url_for('main.social_area', _anchor='users'))
|
||||||
|
|
||||||
|
|
||||||
# @bp.route('/<hashid:user_id>')
|
@bp.route('/<hashid:user_id>')
|
||||||
# @register_breadcrumb(bp, '.entity', '', dynamic_list_constructor=user_dlc)
|
@register_breadcrumb(bp, '.entity', '', dynamic_list_constructor=user_dlc)
|
||||||
# def user(user_id):
|
def user(user_id):
|
||||||
# user = User.query.get_or_404(user_id)
|
user = User.query.get_or_404(user_id)
|
||||||
# if not (user.is_public or user == current_user or current_user.is_administrator()):
|
if not (user.is_public or user == current_user or current_user.is_administrator()):
|
||||||
# abort(403)
|
abort(403)
|
||||||
# return render_template(
|
return render_template(
|
||||||
# 'users/user.html.j2',
|
'users/user.html.j2',
|
||||||
# title=user.username,
|
title=user.username,
|
||||||
# user=user
|
user=user
|
||||||
# )
|
)
|
||||||
|
|
||||||
|
|
||||||
# @bp.route('/<hashid:user_id>/avatar')
|
@bp.route('/<hashid:user_id>/avatar')
|
||||||
# def user_avatar(user_id):
|
def user_avatar(user_id):
|
||||||
# user = User.query.get_or_404(user_id)
|
user = User.query.get_or_404(user_id)
|
||||||
# if not (user.is_public or user == current_user or current_user.is_administrator()):
|
if not (user.is_public or user == current_user or current_user.is_administrator()):
|
||||||
# abort(403)
|
abort(403)
|
||||||
# if user.avatar is None:
|
if user.avatar is None:
|
||||||
# return redirect(url_for('static', filename='images/user_avatar.png'))
|
return redirect(url_for('static', filename='images/user_avatar.png'))
|
||||||
# return send_from_directory(
|
return send_from_directory(
|
||||||
# os.path.dirname(user.avatar.path),
|
os.path.dirname(user.avatar.path),
|
||||||
# os.path.basename(user.avatar.path),
|
os.path.basename(user.avatar.path),
|
||||||
# as_attachment=True,
|
as_attachment=True,
|
||||||
# attachment_filename=user.avatar.filename,
|
attachment_filename=user.avatar.filename,
|
||||||
# mimetype=user.avatar.mimetype
|
mimetype=user.avatar.mimetype
|
||||||
# )
|
)
|
||||||
|
@ -5,7 +5,7 @@ docker
|
|||||||
eventlet
|
eventlet
|
||||||
Flask==2.1.3
|
Flask==2.1.3
|
||||||
Flask-APScheduler
|
Flask-APScheduler
|
||||||
Flask-Assets
|
Flask-Assets==2.0
|
||||||
Flask-Breadcrumbs
|
Flask-Breadcrumbs
|
||||||
Flask-Hashids>=1.0.1
|
Flask-Hashids>=1.0.1
|
||||||
Flask-HTTPAuth
|
Flask-HTTPAuth
|
||||||
|
Loading…
x
Reference in New Issue
Block a user