Design pending blogs in organizations (#123)

This commit is contained in:
Phuoc Anh Kha Le 2024-07-23 01:24:43 -05:00 committed by GitHub
parent 66f6212947
commit 44554d7de6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 423 additions and 306 deletions

View file

@ -208,14 +208,9 @@ class PostView(TitleMixin, CommentedDetailView, PageVoteDetailView, BookMarkDeta
orgs = list(self.object.organizations.all()) orgs = list(self.object.organizations.all())
if self.request.profile: if self.request.profile:
if self.request.profile.id in self.object.get_authors(): for org in orgs:
for org in orgs: if self.request.profile.can_edit_organization(org):
if org.is_member(self.request.profile): context["editable_orgs"].append(org)
context["editable_orgs"].append(org)
else:
for org in orgs:
if org.is_admin(self.request.profile):
context["editable_orgs"].append(org)
return context return context

View file

@ -1118,7 +1118,7 @@ class EditOrganizationBlog(
LoginRequiredMixin, LoginRequiredMixin,
TitleMixin, TitleMixin,
OrganizationHomeView, OrganizationHomeView,
MemberOrganizationMixin, AdminOrganizationMixin,
UpdateView, UpdateView,
): ):
template_name = "organization/blog/edit.html" template_name = "organization/blog/edit.html"
@ -1134,19 +1134,20 @@ class EditOrganizationBlog(
self.blog_id = kwargs["blog_pk"] self.blog_id = kwargs["blog_pk"]
self.blog = BlogPost.objects.get(id=self.blog_id) self.blog = BlogPost.objects.get(id=self.blog_id)
if self.organization not in self.blog.organizations.all(): if self.organization not in self.blog.organizations.all():
raise Exception("This blog does not belong to this organization") raise Exception(_("This blog does not belong to this organization"))
if ( if not self.request.profile.can_edit_organization(self.organization):
self.request.profile.id not in self.blog.get_authors() raise Exception(_("Not allowed to edit this blog"))
and not self.can_edit_organization(self.organization) except Exception as e:
):
raise Exception("Not allowed to edit this blog")
except:
return generic_message( return generic_message(
request, request,
_("Permission denied"), _("Permission denied"),
_("Not allowed to edit this blog"), e,
) )
def publish_blog(self, request, *args, **kwargs):
self.blog_id = kwargs["blog_pk"]
BlogPost.objects.filter(pk=self.blog_id).update(visible=True)
def delete_blog(self, request, *args, **kwargs): def delete_blog(self, request, *args, **kwargs):
self.blog_id = kwargs["blog_pk"] self.blog_id = kwargs["blog_pk"]
BlogPost.objects.get(pk=self.blog_id).delete() BlogPost.objects.get(pk=self.blog_id).delete()
@ -1164,6 +1165,22 @@ class EditOrganizationBlog(
if request.POST["action"] == "Delete": if request.POST["action"] == "Delete":
self.create_notification("Delete blog") self.create_notification("Delete blog")
self.delete_blog(request, *args, **kwargs) self.delete_blog(request, *args, **kwargs)
cur_url = reverse(
"organization_home",
args=(self.organization_id, self.organization.slug),
)
return HttpResponseRedirect(cur_url)
elif request.POST["action"] == "Reject":
self.create_notification("Reject blog")
self.delete_blog(request, *args, **kwargs)
cur_url = reverse(
"organization_pending_blogs",
args=(self.organization_id, self.organization.slug),
)
return HttpResponseRedirect(cur_url)
elif request.POST["action"] == "Approve":
self.create_notification("Approve blog")
self.publish_blog(request, *args, **kwargs)
cur_url = reverse( cur_url = reverse(
"organization_pending_blogs", "organization_pending_blogs",
args=(self.organization_id, self.organization.slug), args=(self.organization_id, self.organization.slug),
@ -1185,9 +1202,8 @@ class EditOrganizationBlog(
args=[self.organization.id, self.organization.slug, self.blog_id], args=[self.organization.id, self.organization.slug, self.blog_id],
) )
html = f'<a href="{link}">{blog.title} - {self.organization.name}</a>' html = f'<a href="{link}">{blog.title} - {self.organization.name}</a>'
post_authors = blog.authors.all() to_users = (self.organization.admins.all() | blog.get_authors()).distinct()
posible_users = self.organization.admins.all() | post_authors make_notification(to_users, action, html, self.request.profile)
make_notification(posible_users, action, html, self.request.profile)
def form_valid(self, form): def form_valid(self, form):
with revisions.create_revision(): with revisions.create_revision():
@ -1224,3 +1240,8 @@ class PendingBlogs(
def get_title(self): def get_title(self):
return _("Pending blogs in %s") % self.organization.name return _("Pending blogs in %s") % self.organization.name
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["org"] = self.organization
return context

File diff suppressed because it is too large Load diff

View file

@ -24,9 +24,6 @@ msgstr "Giới thiệu"
msgid "Status" msgid "Status"
msgstr "Máy chấm" msgstr "Máy chấm"
msgid "Courses"
msgstr "Khóa học"
msgid "Suggestions" msgid "Suggestions"
msgstr "Đề xuất ý tưởng" msgstr "Đề xuất ý tưởng"
@ -42,9 +39,6 @@ msgstr "Đăng ký tên"
msgid "Report" msgid "Report"
msgstr "Báo cáo tiêu cực" msgstr "Báo cáo tiêu cực"
msgid "Bug Report"
msgstr "Báo cáo lỗi"
msgid "2sat" msgid "2sat"
msgstr "" msgstr ""
@ -600,6 +594,12 @@ msgstr ""
msgid "z-function" msgid "z-function"
msgstr "" msgstr ""
#~ msgid "Courses"
#~ msgstr "Khóa học"
#~ msgid "Bug Report"
#~ msgstr "Báo cáo lỗi"
#~ msgid "Insert Image" #~ msgid "Insert Image"
#~ msgstr "Chèn hình ảnh" #~ msgstr "Chèn hình ảnh"

View file

@ -795,6 +795,14 @@ noscript #noscript {
background-color: royalblue !important; background-color: royalblue !important;
} }
.background-green {
background-color: #28a745 !important;
}
.background-red {
background-color: #dc3545 !important;
}
.background-footer { .background-footer {
color: #808080; color: #808080;
} }

View file

@ -1769,6 +1769,12 @@ noscript #noscript {
.background-royalblue { .background-royalblue {
background-color: rgb(25, 58, 158) !important; background-color: rgb(25, 58, 158) !important;
} }
.background-green {
background-color: rgb(32, 134, 55) !important;
}
.background-red {
background-color: rgb(165, 29, 42) !important;
}
.background-footer { .background-footer {
color: rgb(152, 143, 129); color: rgb(152, 143, 129);
} }
@ -3828,15 +3834,6 @@ svg line.messageLine1 {
div.mermaid .actor { div.mermaid .actor {
fill: var(--darkreader-neutral-background) !important; fill: var(--darkreader-neutral-background) !important;
} }
.google-material-icons {
font-family: 'Google Material Icons' !important;
}
.google-symbols {
font-family: 'Google Symbols Subset', 'Google Symbols' !important;
}
.material-icons-extended {
font-family: 'Material Icons Extended' !important;
}
mitid-authenticators-code-app > .code-app-container { mitid-authenticators-code-app > .code-app-container {
background-color: white !important; background-color: white !important;
padding-top: 1rem; padding-top: 1rem;
@ -3844,6 +3841,3 @@ mitid-authenticators-code-app > .code-app-container {
iframe#unpaywall[src$="unpaywall.html"] { iframe#unpaywall[src$="unpaywall.html"] {
color-scheme: light !important; color-scheme: light !important;
} }
.oui-icon {
font-family: 'Oui Icons' !important;
}

View file

@ -0,0 +1,48 @@
<script type="text/javascript">
$(document).ready(function () {
function ajax_post(url, data, on_success) {
return $.ajax({
url: url,
type: 'POST',
data: data,
success: function (data, textStatus, jqXHR) {
if (typeof on_success !== 'undefined')
on_success();
},
error: function (data, textStatus, jqXHR) {
alert('Action failed: ' + data.responseText);
}
});
}
function removePost(postId) {
$('#post-' + postId).slideUp('normal', function () {
$(this).remove();
});
}
window.approvePost = function (url, postId, e) {
e.preventDefault();
const csrfToken = '{{ csrf_token }}';
ajax_post(url, {
id: postId,
action: 'Approve',
csrfmiddlewaretoken: csrfToken
}, function () {
removePost(postId);
});
}
window.rejectPost = function (url, postId, e) {
e.preventDefault();
const csrfToken = '{{ csrf_token }}';
ajax_post(url, {
id: postId,
action: 'Reject',
csrfmiddlewaretoken: csrfToken
}, function () {
removePost(postId);
});
}
});
</script>

View file

@ -1,28 +1,71 @@
{% extends "organization/home-base.html" %} {% extends "organization/home-base.html" %}
{% block middle_content %} {% block org_js %}
<table class="table"> {% include "organization/blog/pending-js.html" %}
<thead> {% endblock %}
<tr>
<th> {% block middle_content %}
{{_('Blog')}} {% for post in blogs %}
</th> <section class="{% if post.sticky %}sticky {% endif %} blog-box" id="post-{{post.id}}">
<th> {% if post.is_organization_private and show_organization_private_icon %}
{{_('Author')}} <div style="margin-bottom: 1em; display: flex;">
</th> {% for org in post.organizations.all() %}
<th> {% include "organization/tag.html" %}
{{_('Post time')}} {% endfor %}
</th> </div>
</tr> {% endif %}
</thead> <div style="margin-bottom: 0.5em">
<tbody> <span class="post-content-header time">
{% for blog in blogs %} {% with authors=post.get_authors() %}
<tr> {%- if authors -%}
<td><a href="{{url('edit_organization_blog', organization.id, organization.slug, blog.id)}}">{{blog.title}}</a></td> <span class="user-img" style="width: 1.5em; height: 1.5em">
<td>{{link_users(blog.authors.all())}}</td> <img src="{{gravatar(authors[0])}}" loading="lazy">
<td>{{- blog.publish_on|date(_("N j, Y, g:i a")) -}}</td> </span>
</tr> <span class="post-authors">{{ link_users(authors) }}</span>
{% endfor %} {%- endif -%}
</tbody> {% endwith %}
</table> &#8226;
{{ relative_time(post.publish_on) }}
{%- if post.sticky %} &#8226;
<i title="Sticky" class="fa fa-star fa-fw"></i>{% endif -%}
</span>
</div>
<h2 class="title">
<a href="{{ url('blog_post', post.id, post.slug) }}">{{ post.title }}</a>
</h2>
<div class="blog-description">
<div class="summary content-description">
{% cache 86400 'post_content' post.id %}
{{ post.content|markdown(lazy_load=True)|reference|str|safe }}
{% endcache %}
</div>
<div class="show-more"> {{_("...More")}} </div>
</div>
{% if request.profile.can_edit_organization(org) %}
<div class="actionbar-box">
<div class="actionbar {{'hide_texts_on_mobile' if hide_texts_on_mobile}}">
<span class="actionbar-block">
<a class="actionbar-button white background-green" href="#" onclick="javascript:approvePost('{{ url('edit_organization_blog', org.id , org.slug , post.id) }}', {{ post.id }}, event)">
<i class="fa fa-check" style="font-size: large;"></i>
<span class="actionbar-text">{{_("Approve")}}</span>
</a>
</span>
<span class="actionbar-block">
<a class="actionbar-button black" href="{{ url('edit_organization_blog', org.id , org.slug , post.id) }}">
<i class="fa fa-edit" style="font-size: large;"></i>
<span class="actionbar-text">{{_("Edit")}}</span>
</a>
</span>
<span class="actionbar-block">
<a class="actionbar-button white background-red" href="#" onclick="javascript:rejectPost('{{ url('edit_organization_blog', org.id , org.slug , post.id) }}', {{ post.id }}, event)">
<i class="fa fa-times" style="font-size: large;"></i>
<span class="actionbar-text">{{_("Reject")}}</span>
</a>
</span>
</div>
</div>
{% endif %}
</section>
{% endfor %}
{% include "feed/has_next.html" %}
{% endblock %} {% endblock %}