From 1f62b1708d077a19f3b0527222ddbfae3b870062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ku=C5=BE=C3=ADlek?= Date: Sat, 21 Mar 2020 19:31:32 +0100 Subject: [PATCH] A load of rubbish - comments, little tweaks regarding user permissions --- ...c5059a5_comment_deletion_and_visibility.py | 31 +++++++ yadc/__init__.py | 2 + yadc/assets/css/base-types.scss | 35 ++++++- yadc/assets/css/default.scss | 24 ----- yadc/assets/js/formswitchers.js | 61 +++++++++---- yadc/bp/manage.py | 69 +++++++++++++- yadc/bp/post.py | 40 ++++++-- yadc/forms.py | 14 ++- yadc/models.py | 20 +++- yadc/static/all.css | 2 +- yadc/static/all.js | 61 +++++++++---- yadc/templates/_includes.html | 91 ------------------- yadc/templates/layout/settings.html | 7 +- yadc/templates/post/post.html | 38 ++++---- yadc/templates/user/profile.html | 8 +- 15 files changed, 316 insertions(+), 187 deletions(-) create mode 100644 migrations/versions/2534cc5059a5_comment_deletion_and_visibility.py diff --git a/migrations/versions/2534cc5059a5_comment_deletion_and_visibility.py b/migrations/versions/2534cc5059a5_comment_deletion_and_visibility.py new file mode 100644 index 0000000..da17afa --- /dev/null +++ b/migrations/versions/2534cc5059a5_comment_deletion_and_visibility.py @@ -0,0 +1,31 @@ +"""comment deletion and visibility + +Revision ID: 2534cc5059a5 +Revises: 4b6c6a23c639 +Create Date: 2020-03-20 23:56:02.150560 + +""" +from alembic import op +import sqlalchemy as sa +import sqlalchemy_utc + + +# revision identifiers, used by Alembic. +revision = '2534cc5059a5' +down_revision = '4b6c6a23c639' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('comment', sa.Column('visible', sa.Boolean(), nullable=True)) + op.drop_column('comment', 'delete_reason') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('comment', sa.Column('delete_reason', sa.VARCHAR(length=512), autoincrement=False, nullable=True)) + op.drop_column('comment', 'visible') + # ### end Alembic commands ### diff --git a/yadc/__init__.py b/yadc/__init__.py index 727e619..6408fb5 100644 --- a/yadc/__init__.py +++ b/yadc/__init__.py @@ -32,6 +32,8 @@ def create_app(): app.config.from_pyfile('config.py') + app.jinja_env.trim_blocks = True + app.jinja_env.lstrip_blocks = True db.init_app(app) migrate.init_app(app, db) diff --git a/yadc/assets/css/base-types.scss b/yadc/assets/css/base-types.scss index c2b2ba2..1e34df4 100644 --- a/yadc/assets/css/base-types.scss +++ b/yadc/assets/css/base-types.scss @@ -90,12 +90,12 @@ h4 { .editingable { &:not(.time-to-edit){ .edit { - display: none; + display: none !important; } } &.time-to-edit { .notedit { - display: none; + display: none !important; } } } @@ -306,6 +306,37 @@ label { } } +.comment-container { + padding: 0 10px; + max-width: 500px; + + article.comment { + overflow: hidden; + // margin-bottom: 1em; + margin: .4em 0; + + p, textarea { + // margin-top: .5em; + margin-top: 0; + // margin-bottom: 1em; + + &.deleted { + color: red; + } + } + + .comment-head { + display: flex; + justify-content: space-between; + + a, label { + cursor: pointer; + } + .controls > * { display: inline-block; } + } + } +} + // form { // margin: 0 auto; // width: 300px; diff --git a/yadc/assets/css/default.scss b/yadc/assets/css/default.scss index f765d98..1fa1195 100644 --- a/yadc/assets/css/default.scss +++ b/yadc/assets/css/default.scss @@ -180,30 +180,6 @@ section.comments { padding: 10px; - > .comment-container { - padding: 0 10px; - max-width: 500px; - - article.comment { - overflow: hidden; - margin-bottom: 1em; - - p, textarea { - // margin-top: .5em; - margin-top: 0; - // margin-bottom: 1em; - - &.deleted { - color: red; - } - } - - .comment-head { - display: flex; - justify-content: space-between; - } - } - } } section.management-table { diff --git a/yadc/assets/js/formswitchers.js b/yadc/assets/js/formswitchers.js index 6b47f76..ad87570 100644 --- a/yadc/assets/js/formswitchers.js +++ b/yadc/assets/js/formswitchers.js @@ -6,26 +6,55 @@ function switchEdit(el) { } } -function commentSwitcher() { - let comments = document.querySelectorAll('section.comments article.comment') - comments.forEach(comment => comment - .querySelectorAll('.comment-head .control-edit') +// function commentSwitcher() { +// let comments = document.querySelectorAll('section.comments article.comment') +// comments.forEach(comment => comment +// .querySelectorAll('.comment-head .control-edit') +// .forEach(el => el +// .addEventListener('click', ev => switchEdit(comment)) +// ) +// ) +// // comment.target.closest('form.editingable') +// } + +// function mgmtSwitcher() { +// let rows = document.querySelectorAll("section.management-table tbody > tr") +// rows.forEach(row => row +// .querySelectorAll('label.to-edit, label.to-close') +// .forEach(el => el +// .addEventListener('click', ev => switchEdit(row)) +// ) +// ) +// } + +// commentSwitcher() +// mgmtSwitcher() + +function toggleSwitcher(rootSelector, triggerSelector) { + let rootelements = document.querySelectorAll(rootSelector) + rootelements.forEach(rootelement => rootelement + .querySelectorAll(triggerSelector) .forEach(el => el - .addEventListener('click', ev => switchEdit(comment.querySelector('.editingable'))) - ) + .addEventListener('click', ev => switchEdit(rootelement)) ) - // comment.target.closest('form.editingable') + ) } -function mgmtSwitcher() { - let rows = document.querySelectorAll("section.management-table tbody > tr") - rows.forEach(row => row - .querySelectorAll('label.to-edit, label.to-close') - .forEach(el => el - .addEventListener('click', ev => switchEdit(row)) +function doubleclickSwitcher(rootSelector, triggerSelector, dblSelector) { + let rootelements = document.querySelectorAll(rootSelector) + rootelements.forEach(rootelement => { + rootelement + .querySelectorAll(triggerSelector) + .forEach(el => el + .addEventListener('click', ev => switchEdit(rootelement)) ) - ) + rootelement + .querySelectorAll(dblSelector) + .forEach(el => el + .addEventListener('dblclick', ev => switchEdit(rootelement)) + ) + }) } -commentSwitcher() -mgmtSwitcher() \ No newline at end of file +toggleSwitcher('section.comments article.comment', '.comment-head .control-edit', '.comment-content') +doubleclickSwitcher('section.management-table tbody > tr', 'label.to-edit, label.to-close', '.notedit') \ No newline at end of file diff --git a/yadc/bp/manage.py b/yadc/bp/manage.py index 70f1916..03af981 100644 --- a/yadc/bp/manage.py +++ b/yadc/bp/manage.py @@ -22,7 +22,8 @@ def manage_users(page): username=user.username, email=user.email, op_level=user.op_level.name, - user_status=user.user_status.name) + user_status=user.user_status.name + ) return render_template('manage/users.html', users=users, elements=users.items, createform=UserForm()) @@ -57,10 +58,27 @@ def manage_tags(page): tag.editform = TagForm( id=tag.id, content=tag.content_deser, - category=tag.category.name) + category=tag.category.name + ) return render_template('manage/tags.html', tags=tags, elements=tags.items, createform=TagForm()) +@bp.route('/comments', defaults={'page': 1}) +@bp.route('/comments/') +@login_required +@moderator_required +def manage_comments(page): + comments = Comment.query.order_by(Comment.updated).paginate(page, current_app.config.get('MANAGE_PER_PAGE')) + + # for comment in comments.items: + # comment.editform = CommentForm( + # id=comment.id, + # content=comment.content, + + # ) + + return render_template('manage/comments.html', tags=comments, elements=comments.items) + # ONLY THROUGH MANAGEMENT @bp.route('/modify_user', methods=['POST']) @@ -198,4 +216,49 @@ def modify_tag(): flasherrors(form) return redirect(url_for('.manage_tags')) - # return redirect(url_for('main.index')) \ No newline at end of file + # return redirect(url_for('main.index')) + +@bp.route('/modify_comment', methods=['POST']) +@login_required +@moderator_required +def modify_comment(): + form = CommentForm(request.form) + # flash(str(request.form)) + if form.validate(): + if form.create.data: + pass + else: + el = Comment.query.get(form.id.data) + + if form.delete.data: + db.session.delete(el) + db.session.commit() + flash('{} deleted.'.format(str(el))) + + elif form.edit.data: + # if form.rating.raw_data and form.rating.data: el.rating = form.rating.data + # if form.status.raw_data and form.status.data: el.status = form.status.data + # if form.source.raw_data: el.source = form.source.data + + # db.session.commit() + flash('Changes to {} have been applied.'.format(str(el))) + + elif form.ban.data: + el.ban_reason = form.ban_reason.data + el.banned = True + + db.session.commit() + flash('Comment {} has been banned.'.format(str(el))) + + elif form.unban.data: + el.ban_reason = None + el.banned = False + + db.session.commit() + flash('Comment {} has been unbanned.'.format(str(el))) + + flasherrors(form) + if form.referer.data == 'post_show': + return redirect(url_for('post.post_show', id=Comment.query.get(form.id.data).post_id)) + + return redirect(url_for('.manage_comments')) \ No newline at end of file diff --git a/yadc/bp/post.py b/yadc/bp/post.py index ca527d2..574fe6b 100644 --- a/yadc/bp/post.py +++ b/yadc/bp/post.py @@ -76,14 +76,16 @@ def post_show(id): # tag.endpoint = query_replace(dict(**session_rating(), tags=tag.content), url_for('.posts')) pass - for comment in post.comments: + comments = db.session.query(Comment).filter_by(post=post).filter_by(visible=True).order_by(Comment.id).all() + + for comment in comments: comment.editform = CommentForm(id=comment.id, content=comment.content) return render_template( 'post/post.html', post=post, tags=post.tags, - comments=post.comments, + comments=comments, editform=PostForm( id=post.id, referer=post_show.__name__, @@ -100,7 +102,7 @@ def post_show(id): @login_required def comment(): form = CommentForm(request.form) - # flash(str(request.form)) + flash(str(request.form)) if form.validate(): if form.create.data: el = Comment(content=form.content.data.strip(), post_id=form.post_id.data, user=current_user) @@ -111,9 +113,12 @@ def comment(): return redirect(url_for('post.post_show', id=form.post_id.data)) else: el = Comment.query.filter_by(id=form.id.data).first() - if not current_user.is_moderator and not (el.user.is_current if el.user is not None else None): - flash("You don't have sufficient rights to do this.") - return redirect(url_for('main.index')) + + # only authors allowed to edit + # if not (el.user and el.user.is_current): + # flash("You don't have sufficient rights to do this.") + # return redirect(url_for('main.index')) + if form.delete.data: db.session.delete(el) db.session.commit() @@ -124,9 +129,30 @@ def comment(): db.session.commit() flash('Changes to {} have been applied.'.format(str(el))) + elif form.ban.data: + if not current_user.is_moderator: + flash("You don't have sufficient rights to do this.") + return redirect(url_for('main.index')) + + el.deleted = True + + db.session.commit() + flash('Comment {} has been banned.'.format(str(el))) + + elif form.unban.data: + if not current_user.is_moderator: + flash("You don't have sufficient rights to do this.") + return redirect(url_for('main.index')) + + el.deleted = False + + db.session.commit() + flash('Comment {} has been unbanned.'.format(str(el))) + return redirect(url_for('post.post_show', id=el.post_id)) - return redirect(url_for('main.posts')) + flasherrors(form) + return redirect(url_for('main.index')) @bp.route('/upload', methods=['GET', 'POST']) @login_required diff --git a/yadc/forms.py b/yadc/forms.py index 0760b4c..97d054b 100644 --- a/yadc/forms.py +++ b/yadc/forms.py @@ -142,7 +142,8 @@ class EditForm(CSRFForm): delete = SubmitField('Delete') def validate_id(form, field): - if (form.edit.data or form.delete.data) and not field.data: + # if (form.edit.data or form.delete.data) and not field.data: + if not form.create.data and not field.data: raise ValidationError('ID must be defined to be able to modify.') def validate_create_required(form, field): @@ -191,4 +192,13 @@ class CommentForm(EditForm): def validate_content(form, field): if (form.create.data or form.edit.data) and not field.data: - raise ValidationError('Please fill out this field.') \ No newline at end of file + raise ValidationError('Please fill out this field.') + + # referer = HiddenField() + ban = SubmitField('Ban') + unban = SubmitField('Unban') + + # def validate_id(form, field): + # if form.ban.data and not field.data: + # raise ValidationError('ID must be defined to be able to ban.') + # super().validate_id(form, field) \ No newline at end of file diff --git a/yadc/models.py b/yadc/models.py index 2ede90b..0940158 100644 --- a/yadc/models.py +++ b/yadc/models.py @@ -127,6 +127,14 @@ class User(UserMixin, TimestampMixin, db.Model): def logout(self): logout_user() + @property + def can_upload(self): + self.user_status is USER_STATUS.active + + @property + def is_author(self): + return len(self.authored_posts) > 0 + @property def is_moderator(self): # return self.op_level in [OP_LEVEL.moderator, OP_LEVEL.admin] @@ -329,10 +337,10 @@ class Tag(TimestampMixin, db.Model): class Comment(TimestampMixin, db.Model): id = db.Column(db.Integer, primary_key=True) content = db.Column(db.String(512), nullable=False) + visible = db.Column(db.Boolean, default=True) # status = db.Column(db.Enum(COMMENT_STATUS), default=COMMENT_STATUS.visible) deleted = db.Column(db.Boolean, default=False) - delete_reason = db.Column(db.String(512)) post_id = db.Column(db.Integer, db.ForeignKey('post.id')) post = db.relationship('Post', backref=db.backref('comments', order_by='Comment.id', lazy=True)) @@ -340,7 +348,11 @@ class Comment(TimestampMixin, db.Model): user = db.relationship('User', backref=db.backref('comments', lazy=True)) @property - def can_edit(self): - author = current_user == self.user + def can_modify(self): + # author = current_user == self.user moderator = current_user.is_moderator - return author or moderator \ No newline at end of file + return self.is_author or moderator + + @property + def is_author(self): + return current_user == self.user \ No newline at end of file diff --git a/yadc/static/all.css b/yadc/static/all.css index 2e4b7cb..8a61cf8 100644 --- a/yadc/static/all.css +++ b/yadc/static/all.css @@ -1 +1 @@ -.flash_msgs{display:flex;flex-flow:column-reverse nowrap;position:fixed;z-index:20;bottom:0;right:0;margin:0;padding:10px;font-size:.9em;pointer-events:none}.flash_msgs>li{width:250px;padding:10px;list-style-type:none;background-color:#000c;overflow:hidden;opacity:0;animation:fade 7s normal}.flash_msgs>li:not(:first-child){margin-bottom:10px}@keyframes fade{0%,100%{opacity:0}20%,80%{opacity:1}}.flash_msgs>li.error{background-color:#500c}h2{margin:0;margin-bottom:.5em}h3{margin:0;margin-bottom:.5em;font-size:1.3em}h4{margin:0;margin-bottom:.8em;margin-top:.4em}.oneline-space{height:1em}.comment-form{margin-left:10px;max-width:500px}.comment-form input:required{box-shadow:none}.editingable:not(.time-to-edit) .edit{display:none}.editingable.time-to-edit .notedit{display:none}input[type=text],input[type=password],textarea{background:#444a;border:1px solid #444;color:inherit;display:block;padding:.5em}input[type=text],input[type=password]{width:100%}textarea{resize:vertical;width:100%}input[type=submit]{background:#444a;border:2px solid #666a;border-radius:4px;color:inherit;padding:.4em 1.8em}input[type=submit]:active{background:#000a;border:2px solid #444a}label{padding:.4em}.baseform input[type=text],.baseform input[type=password],.baseform textarea,.pageform input[type=text],.pageform input[type=password],.pageform textarea{width:100%}.baseform input[type=checkbox],.pageform input[type=checkbox]{margin:.5em}.baseform input[type=submit],.pageform input[type=submit]{margin:.2em}.baseform>input,.baseform>textarea,.baseform>div,.baseform form>input,.baseform form>textarea,.baseform form>div,.pageform>input,.pageform>textarea,.pageform>div,.pageform form>input,.pageform form>textarea,.pageform form>div{margin:.8em 0}.baseform div.row,.pageform div.row{display:flex;align-items:center}.baseform div.row.stretch,.pageform div.row.stretch{justify-content:space-between}.baseform div.row label,.pageform div.row label{padding:0;margin-left:.2em;margin-right:.6em}.baseform ul,.pageform ul{padding:0;margin:0}.baseform ul li,.pageform ul li{list-style-type:none}.pageform{padding:1em;width:300px;margin:0 auto}.tag-input .tag-suggester{width:100%;position:relative}.tag-input .tag-suggester input[type=text]{margin:.3em 0}.tag-input .tag-suggester>.suggest-dropdown{display:flex;align-items:start;width:100%;top:100%;position:absolute;z-index:10;overflow:auto;background-color:#2d2d2de0}.tag-input .tag-suggester>.suggest-dropdown:not(:empty){padding:.2em}.tag-input .tag-suggester>.suggest-dropdown>a.sug-sel{background-color:#242424}.tag-input .tag-container{display:flex;flex-flow:row wrap}.tag-input .tag-container:empty{display:none}.tag-input .tag-container>a{display:flex;justify-content:space-between;overflow:hidden;align-items:baseline;margin:.2em;padding:.35em .6em;border-radius:4px;background-color:#121212ff;cursor:pointer}.tag-input .tag-container>a .content{margin:0 .4em;flex-grow:1;flex-basis:100%;word-break:break-word;overflow-wrap:anywhere}.tag-input .tag-container>a .tag-icon,.tag-input .tag-container>a .tag-right{align-self:center}.tag-input .tag-container>a .count{font-size:.8em;margin-right:.4em}.tag-input .tag-container>a>*{pointer-events:none}.tag-input .tag-container>a:not(:hover) span.close{opacity:0}.tag-input .tag-container>a:not(:hover) span.plus{opacity:0}.tag-input .tag-container>a.tagselected{background-color:#400808ff}.tag-input .tag-container>a.tag_hide{display:none}header{display:flex;align-items:baseline;padding:0 10px;background-color:#222}header>a.logo{font-size:2em;margin:6px}@media(max-width:559px){header{position:relative}}header>nav{flex-grow:1;display:flex}header>nav>._overlay{display:none}@media(max-width:559px){header>nav{display:none}header>nav._drop{display:flex;flex-flow:column nowrap;position:absolute;margin:0;top:100%;left:0;right:0;z-index:10;background-color:#111d}header>nav>a,header>nav a#user-menu,header>nav .user_dropdown>a{padding:12px;padding-left:24px}header>nav>a:hover,header>nav>a:active,header>nav a#user-menu:hover,header>nav a#user-menu:active,header>nav .user_dropdown>a:hover,header>nav .user_dropdown>a:active{background-color:#333}header>nav .user::before{content:"";display:block;border-top:1px solid grey;margin:2px 12px}header>nav .user #user-menu{display:block}header>nav .user .user_dropdown{display:flex;flex-flow:column nowrap}header>nav>._overlay{display:block;position:fixed;width:100%;height:100%;z-index:-1;background-color:#0006}html.oh{overflow:hidden}}@media(min-width:560px){header>nav{margin:0 5px;align-items:center}header>nav>*{margin:0 5px;padding:6px 0}header>nav>.user{padding:0;margin-left:auto;margin-right:0;position:relative}header>nav>.user #user-menu{display:block;padding:6px 10px}header>nav>.user .user_dropdown{display:none}header>nav>.user .user_dropdown a{padding:10px}header>nav>.user .user_dropdown a:hover{background-color:#333}header>nav>.user:hover>.user_dropdown{display:flex;flex-flow:column nowrap;position:absolute;margin:0;top:100%;right:0;z-index:10;background-color:#111d}}header>#nav-menu{display:none}@media(max-width:559px){header>#nav-menu{display:block;margin:5px;margin-left:auto;padding:0 2px;align-self:center;font-size:2em;cursor:pointer}}.main-wrap{margin:0 auto;max-width:1300px;padding:8px;padding-top:0;padding-bottom:0;display:flex}@media(min-width:900px){.main-wrap{flex-flow:row nowrap}}@media(max-width:899px){.main-wrap{flex-flow:column nowrap}}@media(max-width:899px){.main-wrap{overflow:visible}}.main-wrap .important-subwrap{display:flex;flex-flow:column nowrap;flex-grow:1;overflow:visible}@media(max-width:899px){.main-wrap .important-subwrap{display:contents}}.main-wrap>section.sidepanel{flex-shrink:0;padding:10px}@media(min-width:900px){.main-wrap>section.sidepanel{width:18rem}}.main-wrap>section.sidepanel article:not(:last-child){margin-bottom:10px}@media(max-width:899px){.main-wrap>section.sidepanel article.tags .tag-container,.main-wrap>section.sidepanel article.post-edit .tag-container{flex-flow:row wrap}}@media(min-width:900px){.main-wrap>section.sidepanel article.tags .tag-container,.main-wrap>section.sidepanel article.post-edit .tag-container{flex-flow:column nowrap;align-items:start}.main-wrap>section.sidepanel article.tags .suggest-dropdown,.main-wrap>section.sidepanel article.post-edit .suggest-dropdown{flex-flow:row wrap}.main-wrap>section.sidepanel article.tags .suggest-dropdown a,.main-wrap>section.sidepanel article.post-edit .suggest-dropdown a{width:100%}}.main-wrap>section.sidepanel article.rating ul{padding:0}.main-wrap>section.sidepanel article.rating ul li{list-style-type:none}.main-wrap>section.sidepanel article.post-desc{display:flex;flex-flow:column nowrap;font-size:.9em}.main-wrap>section.sidepanel article.post-desc .source>a{word-break:break-all}.main-wrap>section.sidepanel article.post-desc>img{display:block;max-width:128px}.main-wrap>section.sidepanel article.sidenav>a{display:block;padding:.3em 1em}@media(min-width:900px){.main-wrap section:not(.sidepanel){width:100%}}.main-wrap section.post-list{overflow:hidden}@media(max-width:559px){.main-wrap section.post-list{margin-left:-8px;margin-right:-8px}}.main-wrap section.post-list .posts{display:flex;flex-flow:row wrap}@media(max-width:899px){.main-wrap section.post-list .posts{margin-left:-8px;margin-right:-8px}}.main-wrap section.post-list .posts::after{content:"";flex:10000 0 350px}.main-wrap section.post-list .posts>figure{position:relative;margin:8px}.main-wrap section.post-list .posts>figure img{display:block;width:100%;height:100%;transition:.2s ease}.main-wrap section.post-list .posts>figure:hover img{opacity:.7}@media(min-width:900px){.main-wrap section.post-single{padding:8px}}@media(max-width:899px){.main-wrap section.post-single{order:-1;margin-bottom:8px}}@media(max-width:559px){.main-wrap section.post-single{margin-left:-8px;margin-right:-8px}}.main-wrap section.post-single img{display:block;max-width:100%}.main-wrap section.comments{padding:10px}.main-wrap section.comments>.comment-container{padding:0 10px;max-width:500px}.main-wrap section.comments>.comment-container article.comment{overflow:hidden;margin-bottom:1em}.main-wrap section.comments>.comment-container article.comment p,.main-wrap section.comments>.comment-container article.comment textarea{margin-top:0}.main-wrap section.comments>.comment-container article.comment p.deleted,.main-wrap section.comments>.comment-container article.comment textarea.deleted{color:red}.main-wrap section.comments>.comment-container article.comment .comment-head{display:flex;justify-content:space-between}.main-wrap section.management-table{overflow-x:auto}.main-wrap section.management-table table{margin:0 auto}.main-wrap section.management-table tr{background-color:#303030}.main-wrap section.management-table tr th,.main-wrap section.management-table tr td{padding:6px 10px}.main-wrap section.management-table tr th{background-color:#606060}.main-wrap section.management-table tr label>input{display:none}.main-wrap section.management-table tr .fa{padding:4px 4px;align-self:center;font-size:1.5em;cursor:pointer}.main-wrap section.manage-profile>.baseform{margin:0 10px;margin-bottom:15px;max-width:500px}.main-wrap .pagin{margin:10px 0;display:flex;flex-flow:row nowrap;justify-content:center}.main-wrap .pagin>a{display:block;background-color:#0005;padding:8px 12px;margin:0 2px}footer{padding:10px;text-align:center}*{box-sizing:border-box}body{margin:0;font-family:Verdana,Geneva,Tahoma,sans-serif;background-color:#222;color:#fff}a{color:#bbb;text-decoration:none}a:hover{color:#909090;text-decoration:none} \ No newline at end of file +.flash_msgs{display:flex;flex-flow:column-reverse nowrap;position:fixed;z-index:20;bottom:0;right:0;margin:0;padding:10px;font-size:.9em;pointer-events:none}.flash_msgs>li{width:250px;padding:10px;list-style-type:none;background-color:#000c;overflow:hidden;opacity:0;animation:fade 7s normal}.flash_msgs>li:not(:first-child){margin-bottom:10px}@keyframes fade{0%,100%{opacity:0}20%,80%{opacity:1}}.flash_msgs>li.error{background-color:#500c}h2{margin:0;margin-bottom:.5em}h3{margin:0;margin-bottom:.5em;font-size:1.3em}h4{margin:0;margin-bottom:.8em;margin-top:.4em}.oneline-space{height:1em}.comment-form{margin-left:10px;max-width:500px}.comment-form input:required{box-shadow:none}.editingable:not(.time-to-edit) .edit{display:none!important}.editingable.time-to-edit .notedit{display:none!important}input[type=text],input[type=password],textarea{background:#444a;border:1px solid #444;color:inherit;display:block;padding:.5em}input[type=text],input[type=password]{width:100%}textarea{resize:vertical;width:100%}input[type=submit]{background:#444a;border:2px solid #666a;border-radius:4px;color:inherit;padding:.4em 1.8em}input[type=submit]:active{background:#000a;border:2px solid #444a}label{padding:.4em}.baseform input[type=text],.baseform input[type=password],.baseform textarea,.pageform input[type=text],.pageform input[type=password],.pageform textarea{width:100%}.baseform input[type=checkbox],.pageform input[type=checkbox]{margin:.5em}.baseform input[type=submit],.pageform input[type=submit]{margin:.2em}.baseform>input,.baseform>textarea,.baseform>div,.baseform form>input,.baseform form>textarea,.baseform form>div,.pageform>input,.pageform>textarea,.pageform>div,.pageform form>input,.pageform form>textarea,.pageform form>div{margin:.8em 0}.baseform div.row,.pageform div.row{display:flex;align-items:center}.baseform div.row.stretch,.pageform div.row.stretch{justify-content:space-between}.baseform div.row label,.pageform div.row label{padding:0;margin-left:.2em;margin-right:.6em}.baseform ul,.pageform ul{padding:0;margin:0}.baseform ul li,.pageform ul li{list-style-type:none}.pageform{padding:1em;width:300px;margin:0 auto}.tag-input .tag-suggester{width:100%;position:relative}.tag-input .tag-suggester input[type=text]{margin:.3em 0}.tag-input .tag-suggester>.suggest-dropdown{display:flex;align-items:start;width:100%;top:100%;position:absolute;z-index:10;overflow:auto;background-color:#2d2d2de0}.tag-input .tag-suggester>.suggest-dropdown:not(:empty){padding:.2em}.tag-input .tag-suggester>.suggest-dropdown>a.sug-sel{background-color:#242424}.tag-input .tag-container{display:flex;flex-flow:row wrap}.tag-input .tag-container:empty{display:none}.tag-input .tag-container>a{display:flex;justify-content:space-between;overflow:hidden;align-items:baseline;margin:.2em;padding:.35em .6em;border-radius:4px;background-color:#121212ff;cursor:pointer}.tag-input .tag-container>a .content{margin:0 .4em;flex-grow:1;flex-basis:100%;word-break:break-word;overflow-wrap:anywhere}.tag-input .tag-container>a .tag-icon,.tag-input .tag-container>a .tag-right{align-self:center}.tag-input .tag-container>a .count{font-size:.8em;margin-right:.4em}.tag-input .tag-container>a>*{pointer-events:none}.tag-input .tag-container>a:not(:hover) span.close{opacity:0}.tag-input .tag-container>a:not(:hover) span.plus{opacity:0}.tag-input .tag-container>a.tagselected{background-color:#400808ff}.tag-input .tag-container>a.tag_hide{display:none}.comment-container{padding:0 10px;max-width:500px}.comment-container article.comment{overflow:hidden;margin:.4em 0}.comment-container article.comment p,.comment-container article.comment textarea{margin-top:0}.comment-container article.comment p.deleted,.comment-container article.comment textarea.deleted{color:red}.comment-container article.comment .comment-head{display:flex;justify-content:space-between}.comment-container article.comment .comment-head a,.comment-container article.comment .comment-head label{cursor:pointer}.comment-container article.comment .comment-head .controls>*{display:inline-block}header{display:flex;align-items:baseline;padding:0 10px;background-color:#222}header>a.logo{font-size:2em;margin:6px}@media(max-width:559px){header{position:relative}}header>nav{flex-grow:1;display:flex}header>nav>._overlay{display:none}@media(max-width:559px){header>nav{display:none}header>nav._drop{display:flex;flex-flow:column nowrap;position:absolute;margin:0;top:100%;left:0;right:0;z-index:10;background-color:#111d}header>nav>a,header>nav a#user-menu,header>nav .user_dropdown>a{padding:12px;padding-left:24px}header>nav>a:hover,header>nav>a:active,header>nav a#user-menu:hover,header>nav a#user-menu:active,header>nav .user_dropdown>a:hover,header>nav .user_dropdown>a:active{background-color:#333}header>nav .user::before{content:"";display:block;border-top:1px solid grey;margin:2px 12px}header>nav .user #user-menu{display:block}header>nav .user .user_dropdown{display:flex;flex-flow:column nowrap}header>nav>._overlay{display:block;position:fixed;width:100%;height:100%;z-index:-1;background-color:#0006}html.oh{overflow:hidden}}@media(min-width:560px){header>nav{margin:0 5px;align-items:center}header>nav>*{margin:0 5px;padding:6px 0}header>nav>.user{padding:0;margin-left:auto;margin-right:0;position:relative}header>nav>.user #user-menu{display:block;padding:6px 10px}header>nav>.user .user_dropdown{display:none}header>nav>.user .user_dropdown a{padding:10px}header>nav>.user .user_dropdown a:hover{background-color:#333}header>nav>.user:hover>.user_dropdown{display:flex;flex-flow:column nowrap;position:absolute;margin:0;top:100%;right:0;z-index:10;background-color:#111d}}header>#nav-menu{display:none}@media(max-width:559px){header>#nav-menu{display:block;margin:5px;margin-left:auto;padding:0 2px;align-self:center;font-size:2em;cursor:pointer}}.main-wrap{margin:0 auto;max-width:1300px;padding:8px;padding-top:0;padding-bottom:0;display:flex}@media(min-width:900px){.main-wrap{flex-flow:row nowrap}}@media(max-width:899px){.main-wrap{flex-flow:column nowrap}}@media(max-width:899px){.main-wrap{overflow:visible}}.main-wrap .important-subwrap{display:flex;flex-flow:column nowrap;flex-grow:1;overflow:visible}@media(max-width:899px){.main-wrap .important-subwrap{display:contents}}.main-wrap>section.sidepanel{flex-shrink:0;padding:10px}@media(min-width:900px){.main-wrap>section.sidepanel{width:18rem}}.main-wrap>section.sidepanel article:not(:last-child){margin-bottom:10px}@media(max-width:899px){.main-wrap>section.sidepanel article.tags .tag-container,.main-wrap>section.sidepanel article.post-edit .tag-container{flex-flow:row wrap}}@media(min-width:900px){.main-wrap>section.sidepanel article.tags .tag-container,.main-wrap>section.sidepanel article.post-edit .tag-container{flex-flow:column nowrap;align-items:start}.main-wrap>section.sidepanel article.tags .suggest-dropdown,.main-wrap>section.sidepanel article.post-edit .suggest-dropdown{flex-flow:row wrap}.main-wrap>section.sidepanel article.tags .suggest-dropdown a,.main-wrap>section.sidepanel article.post-edit .suggest-dropdown a{width:100%}}.main-wrap>section.sidepanel article.rating ul{padding:0}.main-wrap>section.sidepanel article.rating ul li{list-style-type:none}.main-wrap>section.sidepanel article.post-desc{display:flex;flex-flow:column nowrap;font-size:.9em}.main-wrap>section.sidepanel article.post-desc .source>a{word-break:break-all}.main-wrap>section.sidepanel article.post-desc>img{display:block;max-width:128px}.main-wrap>section.sidepanel article.sidenav>a{display:block;padding:.3em 1em}@media(min-width:900px){.main-wrap section:not(.sidepanel){width:100%}}.main-wrap section.post-list{overflow:hidden}@media(max-width:559px){.main-wrap section.post-list{margin-left:-8px;margin-right:-8px}}.main-wrap section.post-list .posts{display:flex;flex-flow:row wrap}@media(max-width:899px){.main-wrap section.post-list .posts{margin-left:-8px;margin-right:-8px}}.main-wrap section.post-list .posts::after{content:"";flex:10000 0 350px}.main-wrap section.post-list .posts>figure{position:relative;margin:8px}.main-wrap section.post-list .posts>figure img{display:block;width:100%;height:100%;transition:.2s ease}.main-wrap section.post-list .posts>figure:hover img{opacity:.7}@media(min-width:900px){.main-wrap section.post-single{padding:8px}}@media(max-width:899px){.main-wrap section.post-single{order:-1;margin-bottom:8px}}@media(max-width:559px){.main-wrap section.post-single{margin-left:-8px;margin-right:-8px}}.main-wrap section.post-single img{display:block;max-width:100%}.main-wrap section.comments{padding:10px}.main-wrap section.management-table{overflow-x:auto}.main-wrap section.management-table table{margin:0 auto}.main-wrap section.management-table tr{background-color:#303030}.main-wrap section.management-table tr th,.main-wrap section.management-table tr td{padding:6px 10px}.main-wrap section.management-table tr th{background-color:#606060}.main-wrap section.management-table tr label>input{display:none}.main-wrap section.management-table tr .fa{padding:4px 4px;align-self:center;font-size:1.5em;cursor:pointer}.main-wrap section.manage-profile>.baseform{margin:0 10px;margin-bottom:15px;max-width:500px}.main-wrap .pagin{margin:10px 0;display:flex;flex-flow:row nowrap;justify-content:center}.main-wrap .pagin>a{display:block;background-color:#0005;padding:8px 12px;margin:0 2px}footer{padding:10px;text-align:center}*{box-sizing:border-box}body{margin:0;font-family:Verdana,Geneva,Tahoma,sans-serif;background-color:#222;color:#fff}a{color:#bbb;text-decoration:none}a:hover{color:#909090;text-decoration:none} \ No newline at end of file diff --git a/yadc/static/all.js b/yadc/static/all.js index 553f8b4..f13c020 100644 --- a/yadc/static/all.js +++ b/yadc/static/all.js @@ -6,29 +6,58 @@ function switchEdit(el) { } } -function commentSwitcher() { - let comments = document.querySelectorAll('section.comments article.comment') - comments.forEach(comment => comment - .querySelectorAll('.comment-head .control-edit') +// function commentSwitcher() { +// let comments = document.querySelectorAll('section.comments article.comment') +// comments.forEach(comment => comment +// .querySelectorAll('.comment-head .control-edit') +// .forEach(el => el +// .addEventListener('click', ev => switchEdit(comment)) +// ) +// ) +// // comment.target.closest('form.editingable') +// } + +// function mgmtSwitcher() { +// let rows = document.querySelectorAll("section.management-table tbody > tr") +// rows.forEach(row => row +// .querySelectorAll('label.to-edit, label.to-close') +// .forEach(el => el +// .addEventListener('click', ev => switchEdit(row)) +// ) +// ) +// } + +// commentSwitcher() +// mgmtSwitcher() + +function toggleSwitcher(rootSelector, triggerSelector) { + let rootelements = document.querySelectorAll(rootSelector) + rootelements.forEach(rootelement => rootelement + .querySelectorAll(triggerSelector) .forEach(el => el - .addEventListener('click', ev => switchEdit(comment.querySelector('.editingable'))) - ) + .addEventListener('click', ev => switchEdit(rootelement)) ) - // comment.target.closest('form.editingable') + ) } -function mgmtSwitcher() { - let rows = document.querySelectorAll("section.management-table tbody > tr") - rows.forEach(row => row - .querySelectorAll('label.to-edit, label.to-close') - .forEach(el => el - .addEventListener('click', ev => switchEdit(row)) +function doubleclickSwitcher(rootSelector, triggerSelector, dblSelector) { + let rootelements = document.querySelectorAll(rootSelector) + rootelements.forEach(rootelement => { + rootelement + .querySelectorAll(triggerSelector) + .forEach(el => el + .addEventListener('click', ev => switchEdit(rootelement)) ) - ) + rootelement + .querySelectorAll(dblSelector) + .forEach(el => el + .addEventListener('dblclick', ev => switchEdit(rootelement)) + ) + }) } -commentSwitcher() -mgmtSwitcher() +toggleSwitcher('section.comments article.comment', '.comment-head .control-edit', '.comment-content') +doubleclickSwitcher('section.management-table tbody > tr', 'label.to-edit, label.to-close', '.notedit') let nav_menu = document.querySelectorAll("#nav-menu, nav#main-nav > ._overlay") function nav_menu_event(event) { let drop = document.getElementById("main-nav") diff --git a/yadc/templates/_includes.html b/yadc/templates/_includes.html index 0fd3acf..1bee272 100644 --- a/yadc/templates/_includes.html +++ b/yadc/templates/_includes.html @@ -21,13 +21,6 @@ {% endmacro %} - - {% macro render_comments() %}
@@ -52,23 +45,6 @@
{% endmacro %} - -{% macro render_post_edit() %} - -{% endmacro %} - - -{% macro render_sidenav(sidenav_links) %} -
- {% for class, (name, link) in sidenav_links.items() %} - {{ name }} - {% endfor %} -
-{% endmacro %} - {% macro render_tag_input(input_field, param_dict={}) %}
@@ -79,71 +55,4 @@
-{% endmacro %} - - -{#{% from "_formhelpers.html" import errors %}#} -{% macro render_management_table(elements) %} - - - - {% for heading in elements[0][1].keys() %} - - {% endfor %} - - - - - {% for element,fields in elements %} - - - {{ element.editform.csrf_token }} - {{ element.editform.id() }} - - {% for field,formfield in fields.values() %} - {% if not formfield %} - - {% else %} - - {% endif %} - {% endfor %} - - - - - {% endfor %} - - {{ caller() }} - - {##} - -
{{ heading }}Manage
- {{ field }} - - {{ field }} - {{ formfield() }} - {#{{ errors(formfield) }}#} - - - - - -
{% endmacro %} \ No newline at end of file diff --git a/yadc/templates/layout/settings.html b/yadc/templates/layout/settings.html index 5e38e8e..c85a924 100644 --- a/yadc/templates/layout/settings.html +++ b/yadc/templates/layout/settings.html @@ -2,10 +2,15 @@ {% block sidebar %} {% endblock %} diff --git a/yadc/templates/post/post.html b/yadc/templates/post/post.html index f3d10bf..7ebeac6 100644 --- a/yadc/templates/post/post.html +++ b/yadc/templates/post/post.html @@ -76,31 +76,40 @@

Comments

{% for comment in comments %} -
-
+
+ + {{ comment.editform.csrf_token }} + {{ comment.editform.id() }}

{{ comment.user.username or "Deleted account" }}

- {% if comment.can_edit %} - edit - {% endif %} + {% if current_user.is_moderator %} + {% if not comment.deleted %} + + {% else %} + + {% endif %} + {% endif %} + {% if comment.is_author %} + + + {% endif %}
- {{ comment.editform.csrf_token }} - {{ comment.editform.id() }} - - {% if not comment.deleted %} + {% if not comment.deleted or comment.is_author or current_user.is_moderator %}

{{ comment.content }}

- {{ comment.editform.content(class="edit") }} - {% else %} -

{{ comment.delete_reason }}

- {##} + {% endif %} + {% if comment.deleted %} +

[Comment banned]

{% endif %} + {% if comment.is_author %} + {{ comment.editform.content(class="edit") }} {{ comment.editform.edit(class="edit") }} {{ comment.editform.delete(class="edit") }} + {% endif %}
@@ -110,10 +119,8 @@

No comments so far.

{% endif %}
- {##} {% if current_user.is_authenticated %} -

Reply

@@ -126,7 +133,6 @@
{% else %} -

To comment, please log in.

{% endif %} diff --git a/yadc/templates/user/profile.html b/yadc/templates/user/profile.html index 8fb2e64..27b2d3a 100644 --- a/yadc/templates/user/profile.html +++ b/yadc/templates/user/profile.html @@ -1,10 +1,10 @@ -{% extends 'layout/base_sidebar.html' %} +{% extends 'layout/base.html' %} -{% block sidebar %} +{#{% block sidebar %} {{ super()}} -{% endblock %} +{% endblock %}#} -{% block main_content %} +{% block content %}

{{ user.biography }}

{% endblock %} \ No newline at end of file