mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-03 20:02:47 +00:00 
			
		
		
		
	social-area page and profile page update
This commit is contained in:
		@@ -3,27 +3,24 @@ from flask_login import current_user
 | 
				
			|||||||
from functools import wraps
 | 
					from functools import wraps
 | 
				
			||||||
from app.models import Corpus, CorpusFollowerAssociation
 | 
					from app.models import Corpus, CorpusFollowerAssociation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def corpus_follower_permission_required(permissions):
 | 
					def corpus_follower_permission_required(*permissions):
 | 
				
			||||||
    def decorator(f):
 | 
					    def decorator(f):
 | 
				
			||||||
        @wraps(f)
 | 
					        @wraps(f)
 | 
				
			||||||
        def decorated_function(*args, **kwargs):
 | 
					        def decorated_function(*args, **kwargs):
 | 
				
			||||||
            corpus_id = kwargs.get('corpus_id')
 | 
					            corpus_id = kwargs.get('corpus_id')
 | 
				
			||||||
            corpus = Corpus.query.get_or_404(corpus_id)
 | 
					            corpus = Corpus.query.get_or_404(corpus_id)
 | 
				
			||||||
            if current_user == corpus.user or current_user.is_administrator():
 | 
					            if current_user == corpus.user or current_user.is_administrator():
 | 
				
			||||||
                print('user or admin')
 | 
					 | 
				
			||||||
                return f(*args, **kwargs)
 | 
					                return f(*args, **kwargs)
 | 
				
			||||||
            if not current_user.is_following_corpus(corpus):
 | 
					            if not current_user.is_following_corpus(corpus):
 | 
				
			||||||
                print('not following corpus')
 | 
					 | 
				
			||||||
                abort(403)
 | 
					                abort(403)
 | 
				
			||||||
            corpus_follower_association = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first_or_404()
 | 
					            corpus_follower_association = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=current_user.id).first_or_404()
 | 
				
			||||||
            for permission in permissions:
 | 
					            if not all([corpus_follower_association.role.has_permission(p) for p in permissions]):
 | 
				
			||||||
                if not corpus_follower_association.role.has_permission(permission):
 | 
					                abort(403)
 | 
				
			||||||
                    abort(403)
 | 
					 | 
				
			||||||
            return f(*args, **kwargs)
 | 
					            return f(*args, **kwargs)
 | 
				
			||||||
        return decorated_function
 | 
					        return decorated_function
 | 
				
			||||||
    return decorator
 | 
					    return decorator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def owner_or_admin_required():
 | 
					def corpus_owner_or_admin_required():
 | 
				
			||||||
    def decorator(f):
 | 
					    def decorator(f):
 | 
				
			||||||
        @wraps(f)
 | 
					        @wraps(f)
 | 
				
			||||||
        def decorated_function(*args, **kwargs):
 | 
					        def decorated_function(*args, **kwargs):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,7 +15,7 @@ from flask_login import current_user, login_required
 | 
				
			|||||||
from threading import Thread
 | 
					from threading import Thread
 | 
				
			||||||
import jwt
 | 
					import jwt
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
from .decorators import corpus_follower_permission_required, owner_or_admin_required
 | 
					from .decorators import corpus_follower_permission_required, corpus_owner_or_admin_required
 | 
				
			||||||
from app import db, hashids
 | 
					from app import db, hashids
 | 
				
			||||||
from app.models import (
 | 
					from app.models import (
 | 
				
			||||||
    Corpus,
 | 
					    Corpus,
 | 
				
			||||||
@@ -33,12 +33,6 @@ from .forms import (
 | 
				
			|||||||
    UpdateCorpusFileForm
 | 
					    UpdateCorpusFileForm
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@bp.route('/<hashid:corpus_id>/test')
 | 
					 | 
				
			||||||
@login_required
 | 
					 | 
				
			||||||
@corpus_follower_permission_required(['VIEW', 'ADD_CORPUS_FILE'])
 | 
					 | 
				
			||||||
def test(corpus_id):
 | 
					 | 
				
			||||||
    return 'ok'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@bp.route('/fake-add')
 | 
					@bp.route('/fake-add')
 | 
				
			||||||
@login_required
 | 
					@login_required
 | 
				
			||||||
def fake_add():
 | 
					def fake_add():
 | 
				
			||||||
@@ -51,7 +45,7 @@ def fake_add():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@bp.route('/<hashid:corpus_id>/is_public/enable', methods=['POST'])
 | 
					@bp.route('/<hashid:corpus_id>/is_public/enable', methods=['POST'])
 | 
				
			||||||
@login_required
 | 
					@login_required
 | 
				
			||||||
@owner_or_admin_required()
 | 
					@corpus_owner_or_admin_required()
 | 
				
			||||||
def enable_corpus_is_public(corpus_id):
 | 
					def enable_corpus_is_public(corpus_id):
 | 
				
			||||||
    corpus = Corpus.query.get_or_404(corpus_id)
 | 
					    corpus = Corpus.query.get_or_404(corpus_id)
 | 
				
			||||||
    corpus.is_public = True
 | 
					    corpus.is_public = True
 | 
				
			||||||
@@ -61,7 +55,7 @@ def enable_corpus_is_public(corpus_id):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@bp.route('/<hashid:corpus_id>/is_public/disable', methods=['POST'])
 | 
					@bp.route('/<hashid:corpus_id>/is_public/disable', methods=['POST'])
 | 
				
			||||||
@login_required
 | 
					@login_required
 | 
				
			||||||
@owner_or_admin_required()
 | 
					@corpus_owner_or_admin_required()
 | 
				
			||||||
def disable_corpus_is_public(corpus_id):
 | 
					def disable_corpus_is_public(corpus_id):
 | 
				
			||||||
    corpus = Corpus.query.get_or_404(corpus_id)
 | 
					    corpus = Corpus.query.get_or_404(corpus_id)
 | 
				
			||||||
    corpus.is_public = False
 | 
					    corpus.is_public = False
 | 
				
			||||||
@@ -111,7 +105,7 @@ def current_user_unfollow_corpus(corpus_id):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>/role', methods=['POST'])
 | 
					@bp.route('/<hashid:corpus_id>/followers/<hashid:follower_id>/role', methods=['POST'])
 | 
				
			||||||
@corpus_follower_permission_required(['REMOVE_FOLLOWER', 'UPDATE_FOLLOWER'])
 | 
					@corpus_follower_permission_required('REMOVE_FOLLOWER', 'UPDATE_FOLLOWER')
 | 
				
			||||||
def add_permission(corpus_id, follower_id):
 | 
					def add_permission(corpus_id, follower_id):
 | 
				
			||||||
    corpus_follower_association = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404()
 | 
					    corpus_follower_association = CorpusFollowerAssociation.query.filter_by(corpus_id=corpus_id, follower_id=follower_id).first_or_404()
 | 
				
			||||||
    if not (corpus_follower_association.corpus.user == current_user or current_user.is_administrator()):
 | 
					    if not (corpus_follower_association.corpus.user == current_user or current_user.is_administrator()):
 | 
				
			||||||
@@ -206,6 +200,7 @@ def generate_corpus_share_link(corpus_id):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@bp.route('/<hashid:corpus_id>', methods=['DELETE'])
 | 
					@bp.route('/<hashid:corpus_id>', methods=['DELETE'])
 | 
				
			||||||
@login_required
 | 
					@login_required
 | 
				
			||||||
 | 
					@corpus_owner_or_admin_required()
 | 
				
			||||||
def delete_corpus(corpus_id):
 | 
					def delete_corpus(corpus_id):
 | 
				
			||||||
    def _delete_corpus(app, corpus_id):
 | 
					    def _delete_corpus(app, corpus_id):
 | 
				
			||||||
        with app.app_context():
 | 
					        with app.app_context():
 | 
				
			||||||
@@ -214,8 +209,6 @@ def delete_corpus(corpus_id):
 | 
				
			|||||||
            db.session.commit()
 | 
					            db.session.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    corpus = Corpus.query.get_or_404(corpus_id)
 | 
					    corpus = Corpus.query.get_or_404(corpus_id)
 | 
				
			||||||
    if not (corpus.user == current_user or current_user.is_administrator()):
 | 
					 | 
				
			||||||
        abort(403)
 | 
					 | 
				
			||||||
    thread = Thread(
 | 
					    thread = Thread(
 | 
				
			||||||
        target=_delete_corpus,
 | 
					        target=_delete_corpus,
 | 
				
			||||||
        args=(current_app._get_current_object(), corpus_id)
 | 
					        args=(current_app._get_current_object(), corpus_id)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,20 +27,7 @@ def faq():
 | 
				
			|||||||
@bp.route('/dashboard')
 | 
					@bp.route('/dashboard')
 | 
				
			||||||
@login_required
 | 
					@login_required
 | 
				
			||||||
def dashboard():
 | 
					def dashboard():
 | 
				
			||||||
    # users = [
 | 
					    return render_template('main/dashboard.html.j2', title='Dashboard')
 | 
				
			||||||
    #     u.to_json_serializeable(filter_by_privacy_settings=True) for u
 | 
					 | 
				
			||||||
    #     in User.query.filter(User.is_public == True, User.id != current_user.id).all()
 | 
					 | 
				
			||||||
    # ]
 | 
					 | 
				
			||||||
    # corpora = [
 | 
					 | 
				
			||||||
    #     c.to_json_serializeable() for c
 | 
					 | 
				
			||||||
    #     in Corpus.query.filter(Corpus.is_public == True, Corpus.user != current_user).all()
 | 
					 | 
				
			||||||
    # ]
 | 
					 | 
				
			||||||
    return render_template(
 | 
					 | 
				
			||||||
        'main/dashboard.html.j2',
 | 
					 | 
				
			||||||
        title='Dashboard',
 | 
					 | 
				
			||||||
        # users=users,
 | 
					 | 
				
			||||||
        # corpora=corpora
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@bp.route('/dashboard2')
 | 
					@bp.route('/dashboard2')
 | 
				
			||||||
@@ -67,3 +54,20 @@ def privacy_policy():
 | 
				
			|||||||
@bp.route('/terms_of_use')
 | 
					@bp.route('/terms_of_use')
 | 
				
			||||||
def terms_of_use():
 | 
					def terms_of_use():
 | 
				
			||||||
    return render_template('main/terms_of_use.html.j2', title='Terms of Use')
 | 
					    return render_template('main/terms_of_use.html.j2', title='Terms of Use')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@bp.route('/social-area')
 | 
				
			||||||
 | 
					def social_area():
 | 
				
			||||||
 | 
					    users = [
 | 
				
			||||||
 | 
					        u.to_json_serializeable(relationships=True, filter_by_privacy_settings=True,) for u
 | 
				
			||||||
 | 
					        in User.query.filter(User.is_public == True, User.id != current_user.id).all()
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					    corpora = [
 | 
				
			||||||
 | 
					        c.to_json_serializeable() for c
 | 
				
			||||||
 | 
					        in Corpus.query.filter(Corpus.is_public == True, Corpus.user != current_user).all()
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					    return render_template(
 | 
				
			||||||
 | 
					        'main/social_area.html.j2',
 | 
				
			||||||
 | 
					        users=users,
 | 
				
			||||||
 | 
					        corpora=corpora,
 | 
				
			||||||
 | 
					        title='Social Area'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										14
									
								
								app/static/js/ResourceLists/FollowedCorpusList.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								app/static/js/ResourceLists/FollowedCorpusList.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					class FollowedCorpusList extends CorpusList {
 | 
				
			||||||
 | 
					  get item() {
 | 
				
			||||||
 | 
					    return `
 | 
				
			||||||
 | 
					      <tr class="list-item clickable hoverable">
 | 
				
			||||||
 | 
					        <td><a class="btn-floating disabled"><i class="material-icons service-color darken" data-service="corpus-analysis">book</i></a></td>
 | 
				
			||||||
 | 
					        <td><b class="title"></b><br><i class="description"></i></td>
 | 
				
			||||||
 | 
					        <td><span class="status badge new corpus-status-color corpus-status-text" data-badge-caption=""></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();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -13,14 +13,14 @@ class UserList extends ResourceList {
 | 
				
			|||||||
  get item() {
 | 
					  get item() {
 | 
				
			||||||
    return `
 | 
					    return `
 | 
				
			||||||
      <tr class="list-item clickable hoverable">
 | 
					      <tr class="list-item clickable hoverable">
 | 
				
			||||||
        <td><img alt="user-image" class="circle responsive-img avatar" style="width:50%"></td>
 | 
					        <td><img alt="user-image" class="circle responsive-img avatar" style="width:25%"></td>
 | 
				
			||||||
        <td><b><span class="username"></span><b></td>
 | 
					        <td><b><span class="username"></span><b></td>
 | 
				
			||||||
        <td><span class="full-name"></span></td>
 | 
					        <td><span class="full-name"></span></td>
 | 
				
			||||||
        <td><span class="location"></span></td>
 | 
					        <td><span class="location"></span></td>
 | 
				
			||||||
        <td><span class="organization"></span></td>
 | 
					        <td><span class="organization"></span></td>
 | 
				
			||||||
        <td><span class="corpora-online"></span></td>
 | 
					        <td><span class="corpora-online"></span></td>
 | 
				
			||||||
        <td class="right-align">
 | 
					        <td class="right-align">
 | 
				
			||||||
          <a class="list-action-trigger btn-floating waves-effect waves-light" data-list-action="view"><i class="material-icons">send</i></a>
 | 
					          <a class="list-action-trigger btn-floating waves-effect waves-light" data-list-action="view" style="background-color:#D9A36D"><i class="material-icons">send</i></a>
 | 
				
			||||||
        </td>
 | 
					        </td>
 | 
				
			||||||
      </tr>
 | 
					      </tr>
 | 
				
			||||||
    `.trim();
 | 
					    `.trim();
 | 
				
			||||||
@@ -77,7 +77,7 @@ class UserList extends ResourceList {
 | 
				
			|||||||
      'full-name': user.full_name ? user.full_name : '',
 | 
					      'full-name': user.full_name ? user.full_name : '',
 | 
				
			||||||
      'location': user.location ? user.location : '',
 | 
					      'location': user.location ? user.location : '',
 | 
				
			||||||
      'organization': user.organization ? user.organization : '',
 | 
					      'organization': user.organization ? user.organization : '',
 | 
				
			||||||
      'corpora-online': '-'
 | 
					      'corpora-online': Object.values(user.corpora).filter((corpus) => corpus.is_public).length
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,7 @@
 | 
				
			|||||||
  'js/ResourceLists/CorpusFileList.js',
 | 
					  'js/ResourceLists/CorpusFileList.js',
 | 
				
			||||||
  'js/ResourceLists/PublicCorpusFileList.js',
 | 
					  'js/ResourceLists/PublicCorpusFileList.js',
 | 
				
			||||||
  'js/ResourceLists/CorpusList.js',
 | 
					  'js/ResourceLists/CorpusList.js',
 | 
				
			||||||
 | 
					  'js/ResourceLists/FollowedCorpusList.js',
 | 
				
			||||||
  'js/ResourceLists/PublicCorpusList.js',
 | 
					  'js/ResourceLists/PublicCorpusList.js',
 | 
				
			||||||
  'js/ResourceLists/JobList.js',
 | 
					  'js/ResourceLists/JobList.js',
 | 
				
			||||||
  'js/ResourceLists/JobInputList.js',
 | 
					  'js/ResourceLists/JobInputList.js',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,11 +6,10 @@
 | 
				
			|||||||
        <div class="col s4">
 | 
					        <div class="col s4">
 | 
				
			||||||
            <a href="{{ url_for('users.user', user_id=current_user.id) }}">
 | 
					            <a href="{{ url_for('users.user', user_id=current_user.id) }}">
 | 
				
			||||||
            {% if current_user.avatar %}
 | 
					            {% if current_user.avatar %}
 | 
				
			||||||
            <img src="{{ url_for('users.profile_avatar', user_id=current_user.id) }}" alt="user-image" class="circle responsive-img"  style="height:80%; margin-top: 20px; margin-left:-15px;">
 | 
					            <img src="{{ url_for('users.profile_avatar', user_id=current_user.id) }}" alt="user-image" class="circle responsive-img"  style="height:80%; margin-top: 13px; margin-left:-15px;">
 | 
				
			||||||
            {% else %}
 | 
					            {% else %}
 | 
				
			||||||
            <img src="{{ url_for('static', filename='images/user_avatar.png') }}" alt="user-image" class="circle responsive-img" style="height:80%; margin-top: 20px; margin-left:-15px;">
 | 
					            <img src="{{ url_for('static', filename='images/user_avatar.png') }}" alt="user-image" class="circle responsive-img" style="height:80%; margin-top: 13px; margin-left:-15px;">
 | 
				
			||||||
            {% endif %}
 | 
					            {% endif %}
 | 
				
			||||||
            {# <i class="material-icons" style="color:white; font-size:3em; margin-top: 25px; margin-left:-15px;">account_circle</i></div> #}
 | 
					 | 
				
			||||||
            </a>
 | 
					            </a>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="col s8">
 | 
					        <div class="col s8">
 | 
				
			||||||
@@ -27,6 +26,7 @@
 | 
				
			|||||||
  <li><a href="{{ url_for('main.dashboard', _anchor='corpora') }}" style="padding-left: 47px;"><i class="nopaque-icons">I</i>My Corpora</a></li>
 | 
					  <li><a href="{{ url_for('main.dashboard', _anchor='corpora') }}" style="padding-left: 47px;"><i class="nopaque-icons">I</i>My Corpora</a></li>
 | 
				
			||||||
  <li><a href="{{ url_for('main.dashboard', _anchor='jobs') }}" style="padding-left: 47px;"><i class="nopaque-icons">J</i>My Jobs</a></li>
 | 
					  <li><a href="{{ url_for('main.dashboard', _anchor='jobs') }}" style="padding-left: 47px;"><i class="nopaque-icons">J</i>My Jobs</a></li>
 | 
				
			||||||
  <li><a href="{{ url_for('contributions.contributions') }}"><i class="material-icons">new_label</i>Contribute</a></li>
 | 
					  <li><a href="{{ url_for('contributions.contributions') }}"><i class="material-icons">new_label</i>Contribute</a></li>
 | 
				
			||||||
 | 
					  <li><a href="{{ url_for('main.social_area') }}"><i class="material-icons">group</i>Social Area</a></li>
 | 
				
			||||||
  <li><div class="divider"></div></li>
 | 
					  <li><div class="divider"></div></li>
 | 
				
			||||||
  <li><a class="subheader">Processes & Services</a></li>
 | 
					  <li><a class="subheader">Processes & Services</a></li>
 | 
				
			||||||
  <li class="service-color service-color-border border-darken" data-service="file-setup-pipeline" style="border-left: 10px solid; margin-top: 5px;"><a href="{{ url_for('services.file_setup_pipeline') }}"><i class="nopaque-icons service-icons" data-service="file-setup-pipeline"></i>File setup</a></li>
 | 
					  <li class="service-color service-color-border border-darken" data-service="file-setup-pipeline" style="border-left: 10px solid; margin-top: 5px;"><a href="{{ url_for('services.file_setup_pipeline') }}"><i class="nopaque-icons service-icons" data-service="file-setup-pipeline"></i>File setup</a></li>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										70
									
								
								app/templates/main/social_area.html.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								app/templates/main/social_area.html.j2
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					{% extends "base.html.j2" %}
 | 
				
			||||||
 | 
					{% import "materialize/wtf.html.j2" as wtf %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block main_attribs %} style="background-color:#d8c9ba86" {% endblock main_attribs %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block page_content %}
 | 
				
			||||||
 | 
					<div class="container">
 | 
				
			||||||
 | 
					  <div class="row">
 | 
				
			||||||
 | 
					    <div class="col s12">
 | 
				
			||||||
 | 
					      <h1 id="title">{{ title }}</h1>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="col s12 m3 push-m9">
 | 
				
			||||||
 | 
					      <div class="center-align">
 | 
				
			||||||
 | 
					        <p class="hide-on-small-only"> </p>
 | 
				
			||||||
 | 
					        <p class="hide-on-small-only"> </p>
 | 
				
			||||||
 | 
					        <a class="btn-floating btn-large btn-scale-x2 waves-effect waves-light" style="background-color:#D9A36D">
 | 
				
			||||||
 | 
					          <i class="left material-icons">group</i>
 | 
				
			||||||
 | 
					        </a>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="col s12 m9 pull-m3">
 | 
				
			||||||
 | 
					      <div class="card" style="border-top: 10px solid #D9A36D;">
 | 
				
			||||||
 | 
					        <div class="card-content">
 | 
				
			||||||
 | 
					          <div class="row">
 | 
				
			||||||
 | 
					            <div class="col s12">
 | 
				
			||||||
 | 
					              <div class="card-panel z-depth-0">
 | 
				
			||||||
 | 
					                <span class="card-title"><i class="left material-icons">layers</i>Your social area</span>
 | 
				
			||||||
 | 
					                <p>Here you can network with your team and other users. You can find corpora that are public and request them or just see what other users are working on.</p>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="col s12">
 | 
				
			||||||
 | 
					      <h3>Other Users</h3>
 | 
				
			||||||
 | 
					      <p>Find other users and see what corpora they have made public.</p>
 | 
				
			||||||
 | 
					      <div class="card">
 | 
				
			||||||
 | 
					        <div class="card-content">
 | 
				
			||||||
 | 
					          <div class="user-list no-autoinit"></div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <div class="col s12">
 | 
				
			||||||
 | 
					      <h3>Public Corpora</h3>
 | 
				
			||||||
 | 
					      <p>Find public corpora.</p>
 | 
				
			||||||
 | 
					      <div class="card">
 | 
				
			||||||
 | 
					        <div class="card-content">
 | 
				
			||||||
 | 
					          <span class="card-title">Public Corpora</span>
 | 
				
			||||||
 | 
					          <div class="public-corpus-list no-autoinit"></div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{% endblock page_content %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block scripts %}
 | 
				
			||||||
 | 
					{{ super() }}
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					  let userList = new UserList(document.querySelector('.user-list'));
 | 
				
			||||||
 | 
					  userList.add({{ users|tojson }});
 | 
				
			||||||
 | 
					  let publicCorpusList = new PublicCorpusList(document.querySelector('.public-corpus-list'));
 | 
				
			||||||
 | 
					  publicCorpusList.add({{ corpora|tojson }});
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					{% endblock scripts %}
 | 
				
			||||||
@@ -26,7 +26,7 @@
 | 
				
			|||||||
                  </div>
 | 
					                  </div>
 | 
				
			||||||
                  <div class="col 12">
 | 
					                  <div class="col 12">
 | 
				
			||||||
                    {% if user.show_last_seen %}
 | 
					                    {% if user.show_last_seen %}
 | 
				
			||||||
                    <div class="chip">Last seen: {{ user.last_seen }}</div>
 | 
					                    <div class="chip">Last seen: {{ last_seen }}</div>
 | 
				
			||||||
                    {% endif %}
 | 
					                    {% endif %}
 | 
				
			||||||
                    {% if user.location %}
 | 
					                    {% if user.location %}
 | 
				
			||||||
                    <p><span class="material-icons" style="margin-right:20px; margin-top:20px;">location_on</span><i>{{ user.location }}</i></p>
 | 
					                    <p><span class="material-icons" style="margin-right:20px; margin-top:20px;">location_on</span><i>{{ user.location }}</i></p>
 | 
				
			||||||
@@ -76,7 +76,7 @@
 | 
				
			|||||||
                </table>
 | 
					                </table>
 | 
				
			||||||
                <br>
 | 
					                <br>
 | 
				
			||||||
                {% if user.show_member_since %}
 | 
					                {% if user.show_member_since %}
 | 
				
			||||||
                <p><i>Member since: {{ user.member_since }}</i></p>
 | 
					                <p><i>Member since: {{ member_since }}</i></p>
 | 
				
			||||||
                {% endif %}
 | 
					                {% endif %}
 | 
				
			||||||
                <p></p>
 | 
					                <p></p>
 | 
				
			||||||
                <br>
 | 
					                <br>
 | 
				
			||||||
@@ -93,7 +93,8 @@
 | 
				
			|||||||
      <div class="col s6">
 | 
					      <div class="col s6">
 | 
				
			||||||
        <div class="card">
 | 
					        <div class="card">
 | 
				
			||||||
          <div class="card-content">
 | 
					          <div class="card-content">
 | 
				
			||||||
            <h4>Groups</h4>
 | 
					            <h4>Followed corpora</h4>
 | 
				
			||||||
 | 
					            <div class="followed-corpus-list no-autoinit"></div>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
@@ -101,7 +102,7 @@
 | 
				
			|||||||
        <div class="card">
 | 
					        <div class="card">
 | 
				
			||||||
          <div class="card-content">
 | 
					          <div class="card-content">
 | 
				
			||||||
            <h4>Public corpora</h4>
 | 
					            <h4>Public corpora</h4>
 | 
				
			||||||
              <div class="public-corpora-list" data-user-id="{{ user.hashid }}"></div>
 | 
					            <div class="public-corpus-list no-autoinit"></div>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
@@ -127,6 +128,11 @@ if ("{{ user.id }}" == "{{ current_user.hashid }}") {
 | 
				
			|||||||
} else {
 | 
					} else {
 | 
				
			||||||
  publicInformationBadge.remove();
 | 
					  publicInformationBadge.remove();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let followedCorpusList = new FollowedCorpusList(document.querySelector('.followed-corpus-list'));
 | 
				
			||||||
 | 
					followedCorpusList.add({{ followed_corpora|tojson }});
 | 
				
			||||||
 | 
					let publicCorpusList = new PublicCorpusList(document.querySelector('.public-corpus-list'));
 | 
				
			||||||
 | 
					publicCorpusList.add({{ own_public_corpora|tojson }});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
{% endblock scripts %}
 | 
					{% endblock scripts %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					from datetime import datetime
 | 
				
			||||||
from flask import (
 | 
					from flask import (
 | 
				
			||||||
    abort,
 | 
					    abort,
 | 
				
			||||||
    current_app,
 | 
					    current_app,
 | 
				
			||||||
@@ -12,7 +13,7 @@ from flask_login import current_user, login_required
 | 
				
			|||||||
from threading import Thread
 | 
					from threading import Thread
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
from app import db
 | 
					from app import db
 | 
				
			||||||
from app.models import Avatar, ProfilePrivacySettings, User
 | 
					from app.models import Avatar, Corpus, ProfilePrivacySettings, User
 | 
				
			||||||
from . import bp
 | 
					from . import bp
 | 
				
			||||||
from .forms import (
 | 
					from .forms import (
 | 
				
			||||||
  EditPrivacySettingsForm,
 | 
					  EditPrivacySettingsForm,
 | 
				
			||||||
@@ -29,10 +30,23 @@ def before_request():
 | 
				
			|||||||
@login_required
 | 
					@login_required
 | 
				
			||||||
def user(user_id):
 | 
					def user(user_id):
 | 
				
			||||||
    user = User.query.get_or_404(user_id)
 | 
					    user = User.query.get_or_404(user_id)
 | 
				
			||||||
 | 
					    last_seen = user.last_seen.strftime('%Y-%m-%d %H:%M')
 | 
				
			||||||
 | 
					    member_since = user.member_since.strftime('%Y-%m-%d')
 | 
				
			||||||
 | 
					    followed_corpora = [
 | 
				
			||||||
 | 
					        c.to_json_serializeable() for c in user.followed_corpora
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					    own_public_corpora = [
 | 
				
			||||||
 | 
					        c.to_json_serializeable() for c
 | 
				
			||||||
 | 
					        in Corpus.query.filter_by(is_public = True, user = user).all()
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
    if not user.is_public and user != current_user:
 | 
					    if not user.is_public and user != current_user:
 | 
				
			||||||
        abort(403)
 | 
					        abort(403)
 | 
				
			||||||
    return render_template(
 | 
					    return render_template(
 | 
				
			||||||
        'users/profile.html.j2',
 | 
					        'users/profile.html.j2',
 | 
				
			||||||
 | 
					        followed_corpora=followed_corpora,
 | 
				
			||||||
 | 
					        last_seen=last_seen,
 | 
				
			||||||
 | 
					        member_since=member_since,
 | 
				
			||||||
 | 
					        own_public_corpora=own_public_corpora,
 | 
				
			||||||
        user=user.to_json_serializeable(),
 | 
					        user=user.to_json_serializeable(),
 | 
				
			||||||
        user_id=user_id
 | 
					        user_id=user_id
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
@@ -56,18 +70,6 @@ def delete_user(user_id):
 | 
				
			|||||||
    thread.start()
 | 
					    thread.start()
 | 
				
			||||||
    return {}, 202
 | 
					    return {}, 202
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@bp.route('/<hashid:user_id>')
 | 
					 | 
				
			||||||
def profile(user_id):
 | 
					 | 
				
			||||||
    user = User.query.get_or_404(user_id)
 | 
					 | 
				
			||||||
    if not user.is_public and user != current_user:
 | 
					 | 
				
			||||||
        abort(403)
 | 
					 | 
				
			||||||
    return render_template(
 | 
					 | 
				
			||||||
        'users/profile.html.j2', 
 | 
					 | 
				
			||||||
        user=user.to_json_serializeable(),
 | 
					 | 
				
			||||||
        user_id=user_id
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@bp.route('/<hashid:user_id>/avatar')
 | 
					@bp.route('/<hashid:user_id>/avatar')
 | 
				
			||||||
def profile_avatar(user_id):
 | 
					def profile_avatar(user_id):
 | 
				
			||||||
    user = User.query.get_or_404(user_id)
 | 
					    user = User.query.get_or_404(user_id)
 | 
				
			||||||
@@ -91,7 +93,6 @@ def delete_profile_avatar(user_id):
 | 
				
			|||||||
            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)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user