1
1
Fork 0

User profile BS

dev
Jan Kužílek 5 years ago
parent ae1e616d06
commit 1913c6aa68

@ -13,7 +13,6 @@ login = LoginManager()
assets = AssetsEnvironment() assets = AssetsEnvironment()
def create_app(): def create_app():
app = Flask(__name__, instance_relative_config=True) app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(POST_UPLOADS=os.path.join(app.instance_path, 'post'), SQLALCHEMY_TRACK_MODIFICATIONS=False) app.config.from_mapping(POST_UPLOADS=os.path.join(app.instance_path, 'post'), SQLALCHEMY_TRACK_MODIFICATIONS=False)
@ -76,14 +75,9 @@ def create_app():
from yadc import models as m from yadc import models as m
app = create_app() app = create_app()
@app.shell_context_processor @app.shell_context_processor
def make_shell_context(): def make_shell_context():
ctxt = {'db': db} return dict(db=db, **{mdl.__name__:mdl for mdl in (
m.User, m.Post, m.Tag, m.Comment
for mdl in [m.User, m.Post, m.Tag, m.Comment]: )})
ctxt[mdl.__name__] = mdl
return ctxt
# return {'db': db, 'User': models.User, 'Post': models.Post, 'Tag': models.Tag, 'Comment': models.Comment}

@ -53,7 +53,7 @@ h2 {
// font-size: 1.3em; // font-size: 1.3em;
} }
h3 { h3 {
margin: 0; // margin: 0;
margin-bottom: .5em; margin-bottom: .5em;
font-size: 1.3em; font-size: 1.3em;

@ -1,7 +1,7 @@
.main-wrap { .main-wrap {
margin: 0 auto; margin: 0 auto;
max-width: 1300px; max-width: $max-content-width;
padding: $main-wrap-padding; padding: $main-wrap-padding;
padding-top: 0; padding-top: 0;
@ -213,6 +213,17 @@
} }
} }
} }
.user-main, .user-comments {
flex-grow: 1;
flex-basis: 0;
padding: 10px;
// border: 1px solid red;
.comment-container {
// border: 1px solid white;
}
}
section.manage-profile { section.manage-profile {
// @include media($bp-desktop) { // @include media($bp-desktop) {

@ -18,6 +18,8 @@ $main-wrap-padding: 8px;
// $sidepanel-width: 14rem; // $sidepanel-width: 14rem;
$sidepanel-width: 18rem; $sidepanel-width: 18rem;
$max-content-width: 1300px;
@import "base-types"; @import "base-types";
@import "header"; @import "header";
@import "default"; @import "default";

@ -1,15 +1,3 @@
// // https://stackoverflow.com/questions/8486099/how-do-i-parse-a-url-query-parameters-in-javascript
// function getJsonFromUrl(url) {
// if(!url) url = location.search;
// var query = url.substr(1);
// var result = {};
// query.split("&").forEach(function(part) {
// var item = part.split("=");
// result[item[0]] = decodeURIComponent(item[1]);
// });
// return result;
// }
function create_selection_tag(tagname) { // CLEAR function create_selection_tag(tagname) { // CLEAR
let tag = document.createElement("a") let tag = document.createElement("a")
tag.classList.add("tagselected") tag.classList.add("tagselected")

@ -63,21 +63,21 @@ def manage_tags(page):
return render_template('manage/tags.html', tags=tags, elements=tags.items, createform=TagForm()) return render_template('manage/tags.html', tags=tags, elements=tags.items, createform=TagForm())
@bp.route('/comments', defaults={'page': 1}) # @bp.route('/comments', defaults={'page': 1})
@bp.route('/comments/<int:page>') # @bp.route('/comments/<int:page>')
@login_required # @login_required
@moderator_required # @moderator_required
def manage_comments(page): # def manage_comments(page):
comments = Comment.query.order_by(Comment.updated).paginate(page, current_app.config.get('MANAGE_PER_PAGE')) # comments = Comment.query.order_by(Comment.updated).paginate(page, current_app.config.get('MANAGE_PER_PAGE'))
# for comment in comments.items: # # for comment in comments.items:
# comment.editform = CommentForm( # # comment.editform = CommentForm(
# id=comment.id, # # id=comment.id,
# content=comment.content, # # content=comment.content,
# ) # # )
return render_template('manage/comments.html', tags=comments, elements=comments.items) # return render_template('manage/comments.html', tags=comments, elements=comments.items)
# ONLY THROUGH MANAGEMENT # ONLY THROUGH MANAGEMENT

@ -18,13 +18,8 @@ bp = Blueprint('post', __name__)
@bp.route('/<int:page>') @bp.route('/<int:page>')
def posts(page): def posts(page):
def tags_prepare(posts): def tags_prepare(posts):
tags = db.session.query(Tag, func.array_agg(Post.id)).join(Tag.posts).filter(Post.id.in_([p.id for p in posts])).group_by(Tag.id).all() tags = db.session.query(Tag, func.count(Post.id), func.array_agg(Post.id)).join(Tag.posts).filter(Post.id.in_([p.id for p in posts])).group_by(Tag.id).all()
tags = [tag for tag, tag.count, tag.post_ids in tags]
for tag,p_ids in tags:
tag.count = len(p_ids)
tag.post_ids = p_ids
tags = [t[0] for t in tags]
tags.sort(key=lambda x: (x.category.value, x.content) ) tags.sort(key=lambda x: (x.category.value, x.content) )
return tags return tags
@ -35,7 +30,6 @@ def posts(page):
f_rating = {r.name : r for r in RATING}.get(request.args.get('rating')) f_rating = {r.name : r for r in RATING}.get(request.args.get('rating'))
session['enforced_rating'] = f_rating.name if f_rating else None session['enforced_rating'] = f_rating.name if f_rating else None
# flash(f_rating.name if f_rating else None)
if current_user.is_authenticated and current_user.rating is RATING.explicit and f_rating is RATING.explicit: if current_user.is_authenticated and current_user.rating is RATING.explicit and f_rating is RATING.explicit:
return redirect(url_for('.posts')) # Fookin hack to fix the state after user's switch to RATING.explicit return redirect(url_for('.posts')) # Fookin hack to fix the state after user's switch to RATING.explicit
@ -45,8 +39,6 @@ def posts(page):
m_ratings = f_rating.matched if f_rating else RATING.safe.matched m_ratings = f_rating.matched if f_rating else RATING.safe.matched
# filter user's blacklist # filter user's blacklist
# if current_user.is_authenticated:
# f_tags = list(t for t in f_tags if t not in [tb.content for tb in current_user.tag_blacklist])
blacklist_tags = [tb.content for tb in current_user.tag_blacklist] if current_user.is_authenticated else None blacklist_tags = [tb.content for tb in current_user.tag_blacklist] if current_user.is_authenticated else None
posts_query = Post.query posts_query = Post.query
@ -72,9 +64,10 @@ def post_show(id):
# return redirect(url_for('.posts')) # return redirect(url_for('.posts'))
tags_count = db.session.query(Tag, func.count(Post.id)).join(Tag.posts).filter(Post.id==id).join(aliased(Post), Tag.posts).group_by(Tag).all() tags_count = db.session.query(Tag, func.count(Post.id)).join(Tag.posts).filter(Post.id==id).join(aliased(Post), Tag.posts).group_by(Tag).all()
for tag,tag.count in tags_count: # for tag,tag.count in tags_count:
# tag.endpoint = query_replace(dict(**session_rating(), tags=tag.content), url_for('.posts')) # # tag.endpoint = query_replace(dict(**session_rating(), tags=tag.content), url_for('.posts'))
pass # pass
tags = [tag for tag,tag.count in tags_count]
comments = db.session.query(Comment).filter_by(post=post).filter_by(visible=True).order_by(Comment.id).all() comments = db.session.query(Comment).filter_by(post=post).filter_by(visible=True).order_by(Comment.id).all()
@ -84,14 +77,14 @@ def post_show(id):
return render_template( return render_template(
'post/post.html', 'post/post.html',
post=post, post=post,
tags=post.tags, tags=tags,
comments=comments, comments=comments,
editform=PostForm( editform=PostForm(
id=post.id, id=post.id,
referer=post_show.__name__, referer=post_show.__name__,
source=post.source, source=post.source,
parent=post.parent_id, parent=post.parent_id,
tags=' '.join(t.content for t in post.tags), tags=' '.join(t.content for t in tags),
rating=post.rating, rating=post.rating,
status=post.status status=post.status
), ),

@ -1,7 +1,7 @@
from flask import (Blueprint, abort, current_app, flash, redirect, from flask import (Blueprint, abort, current_app, flash, redirect,
render_template, request, send_from_directory, url_for) render_template, request, send_from_directory, url_for)
from flask_login import current_user, login_required from flask_login import current_user, login_required
from yadc.forms import ChangeUserInfoForm, ChangePassForm, ChangeMailForm, ChangeUserRatingForm, ChangeTagBlacklistForm, DeleteUserDataForm from yadc.forms import ChangeUserInfoForm, ChangePassForm, ChangeMailForm, ChangeUserRatingForm, ChangeTagBlacklistForm, DeleteUserDataForm, CommentForm
from yadc import db from yadc import db
from yadc.models import User, Post, Comment, Tag from yadc.models import User, Post, Comment, Tag
@ -12,7 +12,19 @@ bp = Blueprint('user', __name__)
@bp.route('/@<username>') @bp.route('/@<username>')
def profile(username): def profile(username):
user = User.query.filter_by(username=username).first_or_404() user = User.query.filter_by(username=username).first_or_404()
return render_template('user/profile.html', user=user) last_comments = Comment.query.filter_by(user=user).order_by(Comment.id).limit(5).all()
for comment in last_comments:
comment.editform = CommentForm(id=comment.id, content=comment.content)
return render_template(
'user/profile.html',
user=user,
comments=last_comments,
post_count=Post.query.filter_by(author=user).count(),
comment_count=Comment.query.filter_by(user=user).count(),
approved_count=Post.query.filter_by(approver=user).count()
)
@bp.route('/settings') @bp.route('/settings')
@login_required @login_required

@ -87,7 +87,6 @@ class UploadForm(CSRFForm):
raise ValidationError('Image is corrupted.') raise ValidationError('Image is corrupted.')
fileinfo = Post.fileinfo(file) fileinfo = Post.fileinfo(file)
post = Post.query.filter_by(md5=fileinfo['md5']).first() post = Post.query.filter_by(md5=fileinfo['md5']).first()
if post is not None: if post is not None:
raise ValidationError('Image with same hash already exists. Reposting is not allowed.') raise ValidationError('Image with same hash already exists. Reposting is not allowed.')

@ -16,13 +16,13 @@ from yadc import db, login, utils
class OP_LEVEL(enum.Enum): class OP_LEVEL(enum.Enum):
user = 0 user = 0
creator = 1 creator = 1 # IS HE CREATOR OR NOT?
moderator = 5 moderator = 5
admin = 9 admin = 9
class USER_STATUS(enum.Enum): class USER_STATUS(enum.Enum):
active = 0 active = 0
inactive = 1 # inactive = 1
banned = 5 banned = 5
class FILETYPE(enum.Enum): class FILETYPE(enum.Enum):
@ -114,8 +114,6 @@ class User(UserMixin, TimestampMixin, db.Model):
self.pass_hash = generate_password_hash(password, salt_length=16) self.pass_hash = generate_password_hash(password, salt_length=16)
def check_password(self, password): def check_password(self, password):
# if self.pass_hash is None:
# return True
if self.pass_hash is None: if self.pass_hash is None:
return False return False
return check_password_hash(self.pass_hash, password) return check_password_hash(self.pass_hash, password)
@ -132,7 +130,7 @@ class User(UserMixin, TimestampMixin, db.Model):
self.user_status is USER_STATUS.active self.user_status is USER_STATUS.active
@property @property
def is_author(self): def is_uploader(self):
return len(self.authored_posts) > 0 return len(self.authored_posts) > 0
@property @property
@ -343,7 +341,7 @@ class Comment(TimestampMixin, db.Model):
deleted = db.Column(db.Boolean, default=False) deleted = db.Column(db.Boolean, default=False)
post_id = db.Column(db.Integer, db.ForeignKey('post.id')) post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
post = db.relationship('Post', backref=db.backref('comments', order_by='Comment.id', lazy=True)) post = db.relationship('Post', backref=db.backref('comments', lazy=True))
user_id = db.Column(db.Integer, db.ForeignKey('user.id')) user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
user = db.relationship('User', backref=db.backref('comments', lazy=True)) user = db.relationship('User', backref=db.backref('comments', lazy=True))

File diff suppressed because one or more lines are too long

@ -86,18 +86,6 @@ document.getElementById("user-menu").addEventListener('click', (ev) => {
drop.classList.remove("_drop") drop.classList.remove("_drop")
} }
}) })
// // https://stackoverflow.com/questions/8486099/how-do-i-parse-a-url-query-parameters-in-javascript
// function getJsonFromUrl(url) {
// if(!url) url = location.search;
// var query = url.substr(1);
// var result = {};
// query.split("&").forEach(function(part) {
// var item = part.split("=");
// result[item[0]] = decodeURIComponent(item[1]);
// });
// return result;
// }
function create_selection_tag(tagname) { // CLEAR function create_selection_tag(tagname) { // CLEAR
let tag = document.createElement("a") let tag = document.createElement("a")
tag.classList.add("tagselected") tag.classList.add("tagselected")

@ -21,37 +21,13 @@
</div> </div>
{% endmacro %} {% endmacro %}
<!-- DEPRECATED! -->
{% macro render_comments() %}
<div class="comment_container">
{% for comment in comments %}
<article>
<div class="head">
<h4>{{ comment.user.username }}</h4>
{% if comment.can_edit %}
<span class="controls">edit</span>
{% endif %}
</div>
{% if not comment.deleted %}
<p>{{ comment.content }}</p>
{% else %}
<p class="deleted">{{ comment.delete_reason }}</p>
{% endif %}
</article>
{% endfor %}
{% if not comments %}
<p>No comments so far.</p>
{% endif %}
</div>
{% endmacro %}
{% macro render_comment(comment, editform) %} {% macro render_comment(comment, editform) %}
<article class="comment editingable"> <article id="comment-{{ comment.id }}" class="comment editingable">
<form action="{{ url_for('post.comment') }}" method="post"> <form action="{{ url_for('post.comment') }}" method="post">
{{ editform.csrf_token }} {{ editform.csrf_token }}
{{ editform.id() }} {{ editform.id() }}
<div class="comment-head"> <div class="comment-head">
<h4>{{ comment.user.username or "Deleted account" }}</h4> <a href="{{ url_for('user.profile', username=comment.user.username).replace('%40', '@') }}"><h4>{{ comment.user.username or "Deleted account" }}</h4></a>
<span class="controls"> <span class="controls">
{% if current_user.is_moderator %} {% if current_user.is_moderator %}
{% if not comment.deleted %} {% if not comment.deleted %}

@ -3,7 +3,7 @@
{% block sidebar %} {% block sidebar %}
<article class="sidenav"> <article class="sidenav">
<a href="{{ url_for('user.settings') }}">Profile settings</a> <a href="{{ url_for('user.settings') }}">Profile settings</a>
{% if current_user.is_author or current_user.is_moderator -%} {% if current_user.is_uploader or current_user.is_moderator -%}
<a href="{{ url_for('manage.manage_posts') }}">Post management</a> <a href="{{ url_for('manage.manage_posts') }}">Post management</a>
{%- endif %} {%- endif %}
{% if current_user.is_moderator -%} {% if current_user.is_moderator -%}

@ -1,4 +1,5 @@
{% extends 'layout/base.html' %} {% extends 'layout/base.html' %}
{% from '_includes.html' import render_comment with context %}
{#{% block sidebar %} {#{% block sidebar %}
{{ super()}} {{ super()}}
@ -6,12 +7,23 @@
{% endblock %}#} {% endblock %}#}
{% block content %} {% block content %}
<section class="user-profile"> <div class="user-main">
<h1 class="username">{{ user.username }}</h1> <h1 class="username">{{ user.username }}</h1>
{% if user.biography %}
<p class="bio">{{ user.biography }}</p>
{% endif %}
<div class="joindate">Joined: {{ user.created.date() }}</div> <div class="joindate">Joined: {{ user.created.date() }}</div>
<div class="status">User level: {{ user.op_level.name.capitalize() }}</div> <div class="status">User level: {{ user.op_level.name.capitalize() }}</div>
<p class="bio">{{ user.biography }}</p> <div class="statistics">
<h3>Statistics</h3>
<div class="posts">Uploaded posts: {{ post_count }}</div>
<div class="comments">Posted comments: {{ comment_count }}</div>
{% if user.is_moderator %}<div class="approves">Approved comments: {{ approved_count }}</div>{% endif %}
</div>
{% if user.tag_blacklist %}
<div class="tag-blacklist">
<h3>Tag blacklist</h3>
<div class="blacklist"> <div class="blacklist">
<div class="tag-container"> <div class="tag-container">
{% for tag in user.tag_blacklist %} {% for tag in user.tag_blacklist %}
@ -29,6 +41,19 @@
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
</div>
{% endif %}
</div>
<div class="user-comments">
<h3>Last comments</h3>
<div class="comment-container">
{% for comment in comments %}
{{ render_comment(comment, comment.editform) }}
{% endfor %}
</section> {% if not comments %}
<p>No comments so far.</p>
{% endif %}
</div>
</div>
{% endblock %} {% endblock %}
Loading…
Cancel
Save