Design pending blogs in organizations (#123)
This commit is contained in:
parent
66f6212947
commit
44554d7de6
8 changed files with 423 additions and 306 deletions
|
@ -208,14 +208,9 @@ class PostView(TitleMixin, CommentedDetailView, PageVoteDetailView, BookMarkDeta
|
|||
orgs = list(self.object.organizations.all())
|
||||
|
||||
if self.request.profile:
|
||||
if self.request.profile.id in self.object.get_authors():
|
||||
for org in orgs:
|
||||
if org.is_member(self.request.profile):
|
||||
context["editable_orgs"].append(org)
|
||||
else:
|
||||
for org in orgs:
|
||||
if org.is_admin(self.request.profile):
|
||||
context["editable_orgs"].append(org)
|
||||
for org in orgs:
|
||||
if self.request.profile.can_edit_organization(org):
|
||||
context["editable_orgs"].append(org)
|
||||
|
||||
return context
|
||||
|
||||
|
|
|
@ -1118,7 +1118,7 @@ class EditOrganizationBlog(
|
|||
LoginRequiredMixin,
|
||||
TitleMixin,
|
||||
OrganizationHomeView,
|
||||
MemberOrganizationMixin,
|
||||
AdminOrganizationMixin,
|
||||
UpdateView,
|
||||
):
|
||||
template_name = "organization/blog/edit.html"
|
||||
|
@ -1134,19 +1134,20 @@ class EditOrganizationBlog(
|
|||
self.blog_id = kwargs["blog_pk"]
|
||||
self.blog = BlogPost.objects.get(id=self.blog_id)
|
||||
if self.organization not in self.blog.organizations.all():
|
||||
raise Exception("This blog does not belong to this organization")
|
||||
if (
|
||||
self.request.profile.id not in self.blog.get_authors()
|
||||
and not self.can_edit_organization(self.organization)
|
||||
):
|
||||
raise Exception("Not allowed to edit this blog")
|
||||
except:
|
||||
raise Exception(_("This blog does not belong to this organization"))
|
||||
if not self.request.profile.can_edit_organization(self.organization):
|
||||
raise Exception(_("Not allowed to edit this blog"))
|
||||
except Exception as e:
|
||||
return generic_message(
|
||||
request,
|
||||
_("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):
|
||||
self.blog_id = kwargs["blog_pk"]
|
||||
BlogPost.objects.get(pk=self.blog_id).delete()
|
||||
|
@ -1164,6 +1165,22 @@ class EditOrganizationBlog(
|
|||
if request.POST["action"] == "Delete":
|
||||
self.create_notification("Delete blog")
|
||||
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(
|
||||
"organization_pending_blogs",
|
||||
args=(self.organization_id, self.organization.slug),
|
||||
|
@ -1185,9 +1202,8 @@ class EditOrganizationBlog(
|
|||
args=[self.organization.id, self.organization.slug, self.blog_id],
|
||||
)
|
||||
html = f'<a href="{link}">{blog.title} - {self.organization.name}</a>'
|
||||
post_authors = blog.authors.all()
|
||||
posible_users = self.organization.admins.all() | post_authors
|
||||
make_notification(posible_users, action, html, self.request.profile)
|
||||
to_users = (self.organization.admins.all() | blog.get_authors()).distinct()
|
||||
make_notification(to_users, action, html, self.request.profile)
|
||||
|
||||
def form_valid(self, form):
|
||||
with revisions.create_revision():
|
||||
|
@ -1224,3 +1240,8 @@ class PendingBlogs(
|
|||
|
||||
def get_title(self):
|
||||
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
|
@ -24,9 +24,6 @@ msgstr "Giới thiệu"
|
|||
msgid "Status"
|
||||
msgstr "Máy chấm"
|
||||
|
||||
msgid "Courses"
|
||||
msgstr "Khóa học"
|
||||
|
||||
msgid "Suggestions"
|
||||
msgstr "Đề xuất ý tưởng"
|
||||
|
||||
|
@ -42,9 +39,6 @@ msgstr "Đăng ký tên"
|
|||
msgid "Report"
|
||||
msgstr "Báo cáo tiêu cực"
|
||||
|
||||
msgid "Bug Report"
|
||||
msgstr "Báo cáo lỗi"
|
||||
|
||||
msgid "2sat"
|
||||
msgstr ""
|
||||
|
||||
|
@ -600,6 +594,12 @@ msgstr ""
|
|||
msgid "z-function"
|
||||
msgstr ""
|
||||
|
||||
#~ msgid "Courses"
|
||||
#~ msgstr "Khóa học"
|
||||
|
||||
#~ msgid "Bug Report"
|
||||
#~ msgstr "Báo cáo lỗi"
|
||||
|
||||
#~ msgid "Insert Image"
|
||||
#~ msgstr "Chèn hình ảnh"
|
||||
|
||||
|
|
|
@ -795,6 +795,14 @@ noscript #noscript {
|
|||
background-color: royalblue !important;
|
||||
}
|
||||
|
||||
.background-green {
|
||||
background-color: #28a745 !important;
|
||||
}
|
||||
|
||||
.background-red {
|
||||
background-color: #dc3545 !important;
|
||||
}
|
||||
|
||||
.background-footer {
|
||||
color: #808080;
|
||||
}
|
||||
|
|
|
@ -1769,6 +1769,12 @@ noscript #noscript {
|
|||
.background-royalblue {
|
||||
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 {
|
||||
color: rgb(152, 143, 129);
|
||||
}
|
||||
|
@ -3828,15 +3834,6 @@ svg line.messageLine1 {
|
|||
div.mermaid .actor {
|
||||
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 {
|
||||
background-color: white !important;
|
||||
padding-top: 1rem;
|
||||
|
@ -3844,6 +3841,3 @@ mitid-authenticators-code-app > .code-app-container {
|
|||
iframe#unpaywall[src$="unpaywall.html"] {
|
||||
color-scheme: light !important;
|
||||
}
|
||||
.oui-icon {
|
||||
font-family: 'Oui Icons' !important;
|
||||
}
|
||||
|
|
48
templates/organization/blog/pending-js.html
Normal file
48
templates/organization/blog/pending-js.html
Normal 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>
|
|
@ -1,28 +1,71 @@
|
|||
{% extends "organization/home-base.html" %}
|
||||
|
||||
{% block middle_content %}
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
{{_('Blog')}}
|
||||
</th>
|
||||
<th>
|
||||
{{_('Author')}}
|
||||
</th>
|
||||
<th>
|
||||
{{_('Post time')}}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for blog in blogs %}
|
||||
<tr>
|
||||
<td><a href="{{url('edit_organization_blog', organization.id, organization.slug, blog.id)}}">{{blog.title}}</a></td>
|
||||
<td>{{link_users(blog.authors.all())}}</td>
|
||||
<td>{{- blog.publish_on|date(_("N j, Y, g:i a")) -}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% block org_js %}
|
||||
{% include "organization/blog/pending-js.html" %}
|
||||
{% endblock %}
|
||||
|
||||
{% block middle_content %}
|
||||
{% for post in blogs %}
|
||||
<section class="{% if post.sticky %}sticky {% endif %} blog-box" id="post-{{post.id}}">
|
||||
{% if post.is_organization_private and show_organization_private_icon %}
|
||||
<div style="margin-bottom: 1em; display: flex;">
|
||||
{% for org in post.organizations.all() %}
|
||||
{% include "organization/tag.html" %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div style="margin-bottom: 0.5em">
|
||||
<span class="post-content-header time">
|
||||
{% with authors=post.get_authors() %}
|
||||
{%- if authors -%}
|
||||
<span class="user-img" style="width: 1.5em; height: 1.5em">
|
||||
<img src="{{gravatar(authors[0])}}" loading="lazy">
|
||||
</span>
|
||||
<span class="post-authors">{{ link_users(authors) }}</span>
|
||||
{%- endif -%}
|
||||
{% endwith %}
|
||||
•
|
||||
{{ relative_time(post.publish_on) }}
|
||||
{%- if post.sticky %} •
|
||||
<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 %}
|
Loading…
Reference in a new issue