Adding usernotes.
This commit is contained in:
parent
957edab4dc
commit
19903cccb5
16 changed files with 484 additions and 10 deletions
|
@ -83,3 +83,157 @@ blockquote {
|
|||
#frontpage .post-title a:visited, .visited {
|
||||
color: #7a7a7a !important;
|
||||
}
|
||||
|
||||
.usernote-link {
|
||||
color: var(--primary);
|
||||
text-decoration: none;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.usernote-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.modal__overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0,0,0,0.6);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index:1033 !important;
|
||||
}
|
||||
|
||||
.modal__container {
|
||||
background-color: #fff;
|
||||
padding: 30px;
|
||||
max-width: 500px;
|
||||
max-height: 100vh;
|
||||
border-radius: 4px;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.modal__header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.modal__title {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
font-weight: 600;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.25;
|
||||
color: #00449e;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.modal__close {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.modal__header .modal__close:before { content: "\2715"; }
|
||||
|
||||
.modal__content {
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
line-height: 1.5;
|
||||
color: rgba(0,0,0,.8);
|
||||
}
|
||||
|
||||
.modal__content > .content__wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
.modal__content > .content__wrapper > .table_content,
|
||||
.modal__content > .content__wrapper > .table_content > .table_note,
|
||||
.modal__content > .content__wrapper > .table_headers {
|
||||
display: flex;
|
||||
}
|
||||
.modal__content > .content__wrapper > .table_content > .table_note {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.modal__content > .content__wrapper > .table_headers > *,
|
||||
.modal__content > .content__wrapper > .table_content > .table_note > * {
|
||||
flex-basis: 20%;
|
||||
}
|
||||
.modal__content > .content__wrapper > .table_headers > *:nth-child(2),
|
||||
.modal__content > .content__wrapper > .table_content > .table_note > *:nth-child(2) {
|
||||
flex-basis: 35%;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.modal__content > .content__wrapper > .table_content .table_note_message {
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.modal__content > .content__wrapper > .table_content > .table_note .table_note_date,
|
||||
.modal__content > .content__wrapper > .table_content > .table_note > .table_note_delete > span {
|
||||
color: var(--primary);
|
||||
border: none !important;
|
||||
text-decoration: none;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
.modal__content > .content__wrapper > .table_content > .table_note .table_note_date:hover,
|
||||
.modal__content > .content__wrapper > .table_content > .table_note > .table_note_delete > span:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.modal__content > form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.modal__content > .content__wrapper > .table_content {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.modal__content textarea {
|
||||
resize: vertical !important;
|
||||
min-height: 50px;
|
||||
margin-top:20px;
|
||||
}
|
||||
|
||||
.modal__content select {
|
||||
display: table-cell;
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
margin-top:5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.modal__btn {
|
||||
font-size: .875rem;
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
padding-top: .5rem;
|
||||
padding-bottom: .5rem;
|
||||
background-color: #e6e6e6;
|
||||
color: rgba(0,0,0,.8);
|
||||
border-radius: .25rem;
|
||||
border-style: none;
|
||||
border-width: 0;
|
||||
cursor: pointer;
|
||||
-webkit-appearance: button;
|
||||
text-transform: none;
|
||||
overflow: visible;
|
||||
line-height: 1.15;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.micromodal-slide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.micromodal-slide.is-open {
|
||||
display: block;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,106 @@ function popclick(author) {
|
|||
; }, 1);
|
||||
}
|
||||
|
||||
function fillnote(user,post,comment) {
|
||||
|
||||
let dialog = document.getElementById("modal-1");
|
||||
let table = "";
|
||||
|
||||
for(let i = 0; i < user.notes.length; ++i){
|
||||
let note_id = "note_" + i;
|
||||
let note = user.notes[i];
|
||||
let date = new Date(parseInt(note.created) * 1000);
|
||||
let date_str = date.toLocaleDateString();
|
||||
let time_str = date.toLocaleTimeString();
|
||||
|
||||
let tag = "None";
|
||||
switch(note.tag){
|
||||
case 0: tag = "Quality"; break;
|
||||
case 1: tag = "Good" ; break;
|
||||
case 2: tag = "Comment"; break;
|
||||
case 3: tag = "Warning"; break;
|
||||
case 4: tag = "Tempban"; break;
|
||||
case 5: tag = "Permban"; break;
|
||||
case 6: tag = "Spam" ; break;
|
||||
case 7: tag = "Bot" ; break;
|
||||
}
|
||||
|
||||
table += "" +
|
||||
"<div class=\"table_note\" id=\"" + note_id + "\" data-id=\"" + note.id + "\">" +
|
||||
"<div class=\"table_note_author\">" +
|
||||
note.author_name + "<br/>" +
|
||||
"<a class=\"table_note_date\" href=\"" + note.reference + "\">" + date_str + ", " + time_str + "</a>" +
|
||||
"</div>" +
|
||||
"<div class=\"table_note_message\">" + note.note + "</div>" +
|
||||
"<div class=\"table_note_tag\">" + tag + "</div>" +
|
||||
"<div class=\"table_note_delete\"><span onclick=\"delete_note('" + note_id + "','" + user.url + "')\">Delete</span></div>" +
|
||||
"</div>\n"
|
||||
}
|
||||
|
||||
dialog.getElementsByClassName('notes_target')[0].innerText = user.username;
|
||||
dialog.getElementsByClassName('table_content')[0].innerHTML = table;
|
||||
|
||||
dialog.dataset.context = JSON.stringify({
|
||||
'url': user.url,
|
||||
'post': post,
|
||||
'comment': comment,
|
||||
'user': user.id,
|
||||
});
|
||||
}
|
||||
|
||||
function delete_note(element,url) {
|
||||
let note = document.getElementById(element);
|
||||
let id = note.dataset.id;
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", url + "/delete_note/" + id);
|
||||
xhr.setRequestHeader('xhr', 'xhr');
|
||||
xhr.responseType = 'json';
|
||||
|
||||
xhr.onload = function() {
|
||||
if(xhr.status === 200) {
|
||||
console.log(xhr.response);
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
var form = new FormData()
|
||||
form.append("formkey", formkey());
|
||||
xhr.send(form);
|
||||
}
|
||||
|
||||
function send_note() {
|
||||
let dialog = document.getElementById("modal-1");
|
||||
let context = JSON.parse(dialog.dataset.context);
|
||||
|
||||
let note = document.querySelector("#modal-1 textarea").value;
|
||||
let tag = document.querySelector("#modal-1 #usernote_tag").value;
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", context.url + "/create_note");
|
||||
xhr.setRequestHeader('xhr', 'xhr');
|
||||
xhr.responseType = 'json';
|
||||
var form = new FormData()
|
||||
|
||||
form.append("formkey", formkey());
|
||||
form.append("data", JSON.stringify({
|
||||
'note': note,
|
||||
'post': context.post,
|
||||
'comment': context.comment,
|
||||
'user': context.user,
|
||||
'tag': tag
|
||||
}));
|
||||
|
||||
xhr.onload = function() {
|
||||
if(xhr.status === 200) {
|
||||
console.log(xhr.response);
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
xhr.send(form);
|
||||
}
|
||||
|
||||
document.addEventListener("click", function(){
|
||||
active = document.activeElement.getAttributeNode("class");
|
||||
if (active && active.nodeValue == "user-name text-decoration-none"){
|
||||
|
|
1
files/assets/js/micromodal.js
Normal file
1
files/assets/js/micromodal.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -6,6 +6,7 @@ from .domains import *
|
|||
from .flags import *
|
||||
from .user import *
|
||||
from .userblock import *
|
||||
from .usernotes import *
|
||||
from .submission import *
|
||||
from .votes import *
|
||||
from .domains import *
|
||||
|
|
|
@ -57,6 +57,7 @@ class Comment(Base):
|
|||
child_comments = relationship("Comment", lazy="dynamic", remote_side=[parent_comment_id], viewonly=True)
|
||||
awards = relationship("AwardRelationship", viewonly=True)
|
||||
reports = relationship("CommentFlag", viewonly=True)
|
||||
notes = relationship("UserNote", back_populates="comment")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if "created_utc" not in kwargs:
|
||||
|
|
|
@ -59,6 +59,7 @@ class Submission(Base):
|
|||
reports = relationship("Flag", viewonly=True)
|
||||
comments = relationship("Comment", primaryjoin="Comment.parent_submission==Submission.id")
|
||||
subr = relationship("Sub", primaryjoin="foreign(Submission.sub)==remote(Sub.name)", viewonly=True)
|
||||
notes = relationship("UserNote", back_populates="post")
|
||||
|
||||
bump_utc = deferred(Column(Integer, server_default=FetchedValue()))
|
||||
|
||||
|
|
|
@ -130,6 +130,7 @@ class User(Base):
|
|||
authorizations = relationship("ClientAuth", viewonly=True)
|
||||
awards = relationship("AwardRelationship", primaryjoin="User.id==AwardRelationship.user_id", viewonly=True)
|
||||
referrals = relationship("User", viewonly=True)
|
||||
notes = relationship("UserNote", foreign_keys='UserNote.reference_user', back_populates="user")
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
|
@ -509,6 +510,7 @@ class User(Base):
|
|||
'post_count': 0 if self.shadowbanned and not (v and (v.shadowbanned or v.admin_level > 2)) else self.post_count,
|
||||
'comment_count': 0 if self.shadowbanned and not (v and (v.shadowbanned or v.admin_level > 2)) else self.comment_count,
|
||||
'badges': [x.path for x in self.badges],
|
||||
'notes': [x.json() for x in self.notes]
|
||||
}
|
||||
|
||||
return data
|
||||
|
|
66
files/classes/usernotes.py
Normal file
66
files/classes/usernotes.py
Normal file
|
@ -0,0 +1,66 @@
|
|||
import time
|
||||
from flask import *
|
||||
from sqlalchemy import *
|
||||
from sqlalchemy.orm import relationship
|
||||
from files.__main__ import Base
|
||||
from files.helpers.const import *
|
||||
from enum import Enum
|
||||
from sqlalchemy import Enum as EnumType
|
||||
|
||||
class UserTag(Enum):
|
||||
Quality = 0
|
||||
Good = 1
|
||||
Comment = 2
|
||||
Warning = 3
|
||||
Tempban = 4
|
||||
Permban = 5
|
||||
Spam = 6
|
||||
Bot = 7
|
||||
|
||||
class UserNote(Base):
|
||||
|
||||
__tablename__ = "usernotes"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
author_id = Column(Integer, ForeignKey("users.id"), nullable=False)
|
||||
created_utc = Column(Integer, nullable=False)
|
||||
reference_user = Column(Integer, ForeignKey("users.id", ondelete='CASCADE'), nullable=False)
|
||||
reference_comment = Column(Integer, ForeignKey("comments.id", ondelete='SET NULL'))
|
||||
reference_post = Column(Integer, ForeignKey("submissions.id", ondelete='SET NULL'))
|
||||
note = Column(String, nullable=False)
|
||||
tag = Column(EnumType(UserTag), nullable=False)
|
||||
|
||||
author = relationship("User", foreign_keys='UserNote.author_id')
|
||||
user = relationship("User", foreign_keys='UserNote.reference_user', back_populates="notes")
|
||||
|
||||
comment = relationship("Comment", back_populates="notes")
|
||||
post = relationship("Submission", back_populates="notes")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if "created_utc" not in kwargs:
|
||||
kwargs["created_utc"] = int(time.time())
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<UserNote(id={self.id})>"
|
||||
|
||||
def json(self):
|
||||
reference = None
|
||||
|
||||
if self.comment:
|
||||
reference = self.comment.permalink
|
||||
elif self.post:
|
||||
reference = self.post.permalink
|
||||
|
||||
data = {'id': self.id,
|
||||
'author_name': self.author.username,
|
||||
'author_id': self.author.id,
|
||||
'user_name': self.user.username,
|
||||
'user_id': self.user.id,
|
||||
'created': self.created_utc,
|
||||
'reference': reference,
|
||||
'note': self.note,
|
||||
'tag': self.tag.value
|
||||
}
|
||||
|
||||
return data
|
|
@ -217,6 +217,56 @@ def distribute(v, comment):
|
|||
g.db.commit()
|
||||
return {"message": f"Each winner has received {coinsperperson} coins!"}
|
||||
|
||||
@app.post("/@<username>/delete_note/<id>")
|
||||
@admin_level_required(3)
|
||||
def delete_note(v,username,id):
|
||||
g.db.query(UserNote).filter_by(id=id).delete()
|
||||
g.db.commit()
|
||||
|
||||
return make_response(jsonify({
|
||||
'success':True, 'message': 'Note deleted', 'note': id
|
||||
}), 200)
|
||||
|
||||
@app.post("/@<username>/create_note")
|
||||
@admin_level_required(3)
|
||||
def create_note(v,username):
|
||||
|
||||
def result(msg,succ,note):
|
||||
return make_response(jsonify({
|
||||
'success':succ, 'message': msg, 'note': note
|
||||
}), 200)
|
||||
|
||||
data = json.loads(request.values.get('data'))
|
||||
user = g.db.query(User).filter_by(username=username).one_or_none()
|
||||
|
||||
if not user:
|
||||
return result('User not found',False,None)
|
||||
|
||||
author_id = v.id
|
||||
reference_user = user.id
|
||||
reference_comment = data.get('comment',None)
|
||||
reference_post = data.get('post',None)
|
||||
note = data['note']
|
||||
tag = UserTag(int(data['tag']))
|
||||
|
||||
if reference_comment:
|
||||
reference_post = None
|
||||
elif reference_post:
|
||||
reference_comment = None
|
||||
|
||||
note = UserNote(
|
||||
author_id=author_id,
|
||||
reference_user=reference_user,
|
||||
reference_comment=reference_comment,
|
||||
reference_post=reference_post,
|
||||
note=note,
|
||||
tag=tag)
|
||||
|
||||
g.db.add(note)
|
||||
g.db.commit()
|
||||
|
||||
return result('Note saved',True,note.json())
|
||||
|
||||
@app.post("/@<username>/revert_actions")
|
||||
@limiter.limit("1/second;30/minute;200/hour;1000/day")
|
||||
@admin_level_required(3)
|
||||
|
|
|
@ -71,16 +71,6 @@ def leaderboard_thread():
|
|||
|
||||
gevent.spawn(leaderboard_thread())
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@app.get("/@<username>/upvoters/<uid>/posts")
|
||||
@auth_required
|
||||
def upvoters_posts(v, username, uid):
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% include 'usernote.html' %}
|
||||
|
||||
{% macro single_comment(c, level=1) %}
|
||||
|
||||
{% set ups=c.upvotes %}
|
||||
|
@ -201,6 +203,12 @@
|
|||
{{c.print()}}
|
||||
{% endif %}
|
||||
<a href="/@{{c.author_name}}" class="user-name text-decoration-none" onclick='popclick({{c.author.json_popover(v) | tojson}})' data-bs-placement="bottom" data-bs-toggle="popover" data-bs-trigger="click" data-content-id="popover" role="button" tabindex="0" style="color:#{{c.author.namecolor}}; font-size:12px; font-weight:bold;"><img loading="lazy" src="{{c.author.profile_url}}" class="profile-pic-25 mr-2"><span {% if c.author.patron and not c.distinguish_level %}class="patron" style="background-color:#{{c.author.namecolor}};"{% elif c.distinguish_level %}class="mod"{% endif %}>{{c.author_name}}</span></a>
|
||||
{% if v and v.admin_level > 2 %}
|
||||
<span
|
||||
class="usernote-link"
|
||||
data-micromodal-trigger="modal-1"
|
||||
onclick='fillnote( {{c.author.json_popover(v) | tojson}}, null, {{c.id}} )'>_U_</span>
|
||||
{% endif %}
|
||||
{% if c.author.customtitle %} <bdi style="color: #{{c.author.titlecolor}}"> {{c.author.customtitle | safe}}</bdi>{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval' ajax.cloudflare.com; connect-src 'self' tls-use1.fpapi.io api.fpjs.io {% if PUSHER_ID != 'blahblahblah' %}{{PUSHER_ID}}.pushnotifications.pusher.com{% endif %}; object-src 'none';">
|
||||
|
||||
<script src="/assets/js/bootstrap.js?v=245"></script>
|
||||
<script src="/assets/js/micromodal.js?v=245"></script>
|
||||
{% if v %}
|
||||
<style>:root{--primary:#{{v.themecolor}}}</style>
|
||||
<link rel="stylesheet" href="/assets/css/main.css?v=250">
|
||||
|
@ -327,6 +328,10 @@
|
|||
|
||||
<script src="/assets/js/lite-youtube.js?v=240"></script>
|
||||
|
||||
<script>
|
||||
MicroModal.init();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
@ -468,6 +468,12 @@
|
|||
{% if p.author.verified %}<i class="fas fa-badge-check align-middle ml-1 {% if p.author.verified=='Glowiefied' %}glow{% endif %}" style="color:{% if p.author.verifiedcolor %}#{{p.author.verifiedcolor}}{% else %}#1DA1F2{% endif %}" data-bs-toggle="tooltip" data-bs-placement="bottom" title="{{p.author.verified}}"></i>
|
||||
{% endif %}
|
||||
<a href="/@{{p.author_name}}" class="user-name text-decoration-none" onclick='popclick({{p.author.json_popover(v) | tojson}})' data-bs-placement="bottom" data-bs-toggle="popover" data-bs-trigger="click" data-content-id="popover" role="button" tabindex="0" style="color: #{{p.author.namecolor}}; font-weight: bold"class="user-name"><img loading="lazy" src="{{p.author.profile_url}}" class="profile-pic-25 mr-2"><span {% if p.author.patron and not p.distinguish_level %}class="patron" style="background-color:#{{p.author.namecolor}};"{% elif p.distinguish_level %}class="mod"{% endif %}>{{p.author_name}}</span></a>{% if p.author.customtitle %} <bdi style="color: #{{p.author.titlecolor}}"> {{p.author.customtitle | safe}}</bdi>{% endif %}
|
||||
{% if v and v.admin_level > 2 %}
|
||||
<span
|
||||
class="usernote-link"
|
||||
data-micromodal-trigger="modal-1"
|
||||
onclick='fillnote( {{p.author.json_popover(v) | tojson}}, {{p.id}}, null )'>_U_</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<span data-bs-toggle="tooltip" data-bs-placement="bottom" id="timestamp" onmouseover="timestamp('timestamp','{{p.created_utc}}')"> {{p.age_string}}</span>
|
||||
({% if p.is_image %}image post{% elif p.is_video %}video post{% elif p.domain %}<a href="/search/posts/?q=domain%3A{{p.domain}}&sort=new&t=all" {% if not v or v.newtabexternal %}target="_blank"{% endif %}>{{p.domain}}</a>{% else %}text post{% endif %})
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<script src="/assets/js/new_comments_count.js?v=242"></script>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<div style="display:none" id="popover">
|
||||
<div class="popover-user-profile" role="tooltip">
|
||||
<img loading="lazy" class="pop-banner w-100 h-64 object-cover">
|
||||
|
@ -42,6 +43,8 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{% include 'usernote.html' %}
|
||||
|
||||
{% for p in listing %}
|
||||
|
||||
{% set ups=p.upvotes %}
|
||||
|
@ -182,6 +185,12 @@
|
|||
{% if p.author.verified %}<i class="fas fa-badge-check align-middle ml-1 {% if p.author.verified=='Glowiefied' %}glow{% endif %}" style="color:{% if p.author.verifiedcolor %}#{{p.author.verifiedcolor}}{% else %}#1DA1F2{% endif %}" data-bs-toggle="tooltip" data-bs-placement="bottom" title="{{p.author.verified}}"></i>
|
||||
{% endif %}
|
||||
<a href="/@{{p.author_name}}" class="user-name text-decoration-none" onclick='popclick({{p.author.json_popover(v) | tojson}})' data-bs-placement="bottom" data-bs-toggle="popover" data-bs-trigger="click" data-content-id="popover" role="button" tabindex="0" style="color: #{{p.author.namecolor}}; font-weight: bold;"><img loading="lazy" src="{{p.author.profile_url}}" class="profile-pic-25 mr-2"><span {% if p.author.patron and not p.distinguish_level %}class="patron" style="background-color:#{{p.author.namecolor}};"{% elif p.distinguish_level %}class="mod"{% endif %}>{{p.author_name}}</span></a>{% if p.author.customtitle %}<bdi style="color: #{{p.author.titlecolor}}"> {{p.author.customtitle | safe}}</bdi>{% endif %}
|
||||
{% if v and v.admin_level > 2 %}
|
||||
<span
|
||||
class="usernote-link"
|
||||
data-micromodal-trigger="modal-1"
|
||||
onclick='fillnote( {{p.author.json_popover(v) | tojson}}, {{p.id}}, null )'>_U_</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<span data-bs-toggle="tooltip" data-bs-placement="bottom" onmouseover="timestamp('timestamp-{{p.id}}','{{p.created_utc}}')" id="timestamp-{{p.id}}"> {{p.age_string}}</span>
|
||||
|
||||
|
|
41
files/templates/usernote.html
Normal file
41
files/templates/usernote.html
Normal file
|
@ -0,0 +1,41 @@
|
|||
<div class="modal micromodal-slide" id="modal-1" aria-hidden="true">
|
||||
<div class="modal__overlay" tabindex="-1" data-micromodal-close>
|
||||
<div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="modal-1-title">
|
||||
<header class="modal__header">
|
||||
<h2 class="modal__title" id="modal-1-title">
|
||||
Notes - <span class="notes_target"></span>
|
||||
</h2>
|
||||
<button class="modal__close" aria-label="Close modal" data-micromodal-close></button>
|
||||
</header>
|
||||
<main class="modal__content" id="modal-1-content">
|
||||
<div class="content__wrapper">
|
||||
<div class="table_headers">
|
||||
<strong>Author</strong>
|
||||
<strong>Note</strong>
|
||||
<strong>Tag</strong>
|
||||
<strong>Actions</strong>
|
||||
</div>
|
||||
<div class="table_content">
|
||||
</div>
|
||||
</div>
|
||||
<form>
|
||||
<textarea></textarea>
|
||||
<select id="usernote_tag">
|
||||
<option class="quality" value="0"> Quality </option>
|
||||
<option class="good" value="1"> Good </option>
|
||||
<option class="comment" value="2"> Comment </option>
|
||||
<option class="warning" value="3"> Warning </option>
|
||||
<option class="tempban" value="4"> Tempban </option>
|
||||
<option class="permban" value="5"> Permban </option>
|
||||
<option class="spam" value="6"> Spam </option>
|
||||
<option class="bot" value="7"> Bot </option>
|
||||
</select>
|
||||
</form>
|
||||
</main>
|
||||
<footer class="modal__footer">
|
||||
<button class="modal__btn modal__btn-primary" onclick="send_note()">Submit</button>
|
||||
<button class="modal__btn" data-micromodal-close aria-label="Close this dialog window">Close</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
39
schema.sql
39
schema.sql
|
@ -248,6 +248,39 @@ CREATE TABLE public.commentflags (
|
|||
created_utc integer NOT NULL
|
||||
);
|
||||
|
||||
--
|
||||
-- Name: usernotes; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.usernotes (
|
||||
id integer NOT NULL,
|
||||
author_id integer NOT NULL,
|
||||
created_utc integer NOT NULL,
|
||||
reference_user integer NOT NULL,
|
||||
reference_comment integer,
|
||||
reference_post integer,
|
||||
note character varying(10000),
|
||||
tag character varying(10)
|
||||
);
|
||||
|
||||
--
|
||||
-- Name: usernotes_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.usernotes_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: usernotes_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.usernotes_id_seq OWNED BY public.usernotes.id;
|
||||
|
||||
--
|
||||
-- Name: comments; Type: TABLE; Schema: public; Owner: -
|
||||
|
@ -691,6 +724,12 @@ ALTER TABLE ONLY public.award_relationships ALTER COLUMN id SET DEFAULT nextval(
|
|||
ALTER TABLE ONLY public.badge_defs ALTER COLUMN id SET DEFAULT nextval('public.badge_defs_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: usernotes id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.usernotes ALTER COLUMN id SET DEFAULT nextval('public.usernotes_id_seq'::regclass);
|
||||
|
||||
--
|
||||
-- Name: comments id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue