Skip to content
This repository was archived by the owner on Aug 26, 2024. It is now read-only.

Commit 394880f

Browse files
Merge pull request #315 from sounak98/dev
bugfix
2 parents 8b033de + 8d87796 commit 394880f

24 files changed

+734
-534
lines changed

gsoc/admin.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from .models import (UserProfile, RegLink, UserDetails, Scheduler, PageNotification, AddUserLog,
22
BlogPostDueDate, Builder, Timeline, ArticleReview, Event, SubOrgDetails,
3-
GsocEndDate, Comment, SendEmail)
3+
GsocEndDate, Comment, SendEmail, BlogPostHistory)
44
from .forms import (UserProfileForm, UserDetailsForm, RegLinkForm, BlogPostDueDateForm, EventForm,
55
GsocEndDateForm)
66

@@ -368,6 +368,7 @@ def formfield_for_foreignkey(self, db_field, request, **kwargs):
368368
class RegLinkInline(admin.TabularInline):
369369
model = RegLink
370370
form = RegLinkForm
371+
extra = 1
371372

372373

373374
class AddUserLogAdmin(admin.ModelAdmin):
@@ -544,3 +545,18 @@ def has_change_permission(self, request, obj=None):
544545

545546

546547
admin.site.register(SendEmail, SendEmailAdmin)
548+
549+
550+
class BlogPostHistoryAdmin(admin.ModelAdmin):
551+
list_display = ('article', 'timestamp')
552+
list_filter = ('article', )
553+
fields = ('article', 'content_safe', 'timestamp')
554+
555+
def has_change_permission(self, request, obj=None):
556+
return False
557+
558+
def content_safe(self, obj):
559+
return mark_safe(obj.content)
560+
561+
562+
admin.site.register(BlogPostHistory, BlogPostHistoryAdmin)

gsoc/cms_toolbars.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,34 @@ def add_admin_menu(self):
5353
if user and user.is_superuser:
5454
self._admin_menu.add_sideframe_item(_('Schedulers'),
5555
url=admin_reverse('gsoc_scheduler_changelist'))
56-
self._admin_menu.add_break(ADMINISTRATION_BREAK)
57-
58-
# cms users settings
59-
self._admin_menu.add_sideframe_item(_('User settings'), url=admin_reverse('cms_usersettings_change'))
60-
self._admin_menu.add_break(USER_SETTINGS_BREAK)
61-
if user and user.is_superuser:
56+
self._admin_menu.add_sideframe_item(_('Builders'),
57+
url=admin_reverse('gsoc_builder_changelist'))
58+
self._admin_menu.add_sideframe_item(_('Review Article'),
59+
url=admin_reverse('gsoc_articlereview_changelist'))
60+
self._admin_menu.add_sideframe_item(_('Timeline'),
61+
url=admin_reverse('gsoc_timeline_changelist'))
62+
self._admin_menu.add_sideframe_item(_('Send Email'),
63+
url=admin_reverse('gsoc_sendemail_add'))
64+
self._admin_menu.add_sideframe_item(_('Suborg Applications'),
65+
url=admin_reverse('gsoc_suborgdetails_changelist'))
6266
self._admin_menu.add_modal_item(
6367
name='Add Users',
6468
url=admin_reverse('gsoc_adduserlog_add'),
6569
on_close=None,
6670
)
71+
72+
if user:
73+
self._admin_menu.add_link_item(_('New Suborg Application'),
74+
reverse('suborg:register_suborg'))
75+
self._admin_menu.add_link_item(_('Manage Suborg Application'),
76+
reverse('suborg:application_list'))
77+
78+
self._admin_menu.add_break(ADMINISTRATION_BREAK)
79+
80+
# cms users settings
81+
self._admin_menu.add_sideframe_item(_('User settings'),
82+
url=admin_reverse('cms_usersettings_change'))
83+
self._admin_menu.add_break(USER_SETTINGS_BREAK)
6784
# clipboard
6885
if self.toolbar.edit_mode_active:
6986
# True if the clipboard exists and there's plugins in it.
@@ -226,5 +243,10 @@ def populate(self):
226243
except ArticleReview.DoesNotExist:
227244
pass
228245

246+
if user.is_superuser:
247+
url = (f"{admin_reverse('gsoc_blogposthistory_changelist')}"
248+
f"?article__id__exact={article.id}")
249+
self.toolbar.add_sideframe_item(_('View History'), url=url)
250+
229251

230252
NewsBlogToolbar.populate = populate

gsoc/common/utils/memcached_stats.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import re
2+
import telnetlib
3+
import sys
4+
5+
6+
class MemcachedStats:
7+
8+
_client = None
9+
_key_regex = re.compile(r'ITEM (.*) \[(.*); (.*)\]')
10+
_slab_regex = re.compile(r'STAT items:(.*):number')
11+
_stat_regex = re.compile(r"STAT (.*) (.*)\r")
12+
13+
def __init__(self, host='localhost', port='11211', timeout=None):
14+
self._host = host
15+
self._port = port
16+
self._timeout = timeout
17+
18+
@property
19+
def client(self):
20+
if self._client is None:
21+
self._client = telnetlib.Telnet(self._host, self._port,
22+
self._timeout)
23+
return self._client
24+
25+
def command(self, cmd):
26+
' Write a command to telnet and return the response '
27+
self.client.write(("%s\n" % cmd).encode('ascii'))
28+
return self.client.read_until(b'END').decode('ascii')
29+
30+
def key_details(self, sort=True, limit=100):
31+
' Return a list of tuples containing keys and details '
32+
cmd = 'stats cachedump %s %s'
33+
keys = [key for id in self.slab_ids()
34+
for key in self._key_regex.findall(self.command(cmd % (id, limit)))]
35+
if sort:
36+
return sorted(keys)
37+
else:
38+
return keys
39+
40+
def keys(self, sort=True, limit=100):
41+
' Return a list of keys in use '
42+
return [key[0] for key in self.key_details(sort=sort, limit=limit)]
43+
44+
def slab_ids(self):
45+
' Return a list of slab ids in use '
46+
return self._slab_regex.findall(self.command('stats items'))
47+
48+
def stats(self):
49+
' Return a dict containing memcached stats '
50+
return dict(self._stat_regex.findall(self.command('stats')))

gsoc/common/utils/tools.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,23 +85,30 @@ def is_year(file_name):
8585
return False
8686

8787

88-
def get_files(repo, except_files=['CNAME', 'LICENSE.md', 'README.md']):
88+
def get_files(repo, except_files=['CNAME', 'LICENSE.md', 'README.md', 'favicon.ico', 'robots.txt']):
8989
contents = repo.get_contents('')
9090
files = []
9191
while contents:
9292
file_content = contents.pop(0)
9393
if not (file_content.path in except_files or is_year(file_content.path)):
94-
if file_content.type == "dir":
94+
if file_content.type == 'dir':
9595
contents.extend(repo.get_contents(file_content.path))
9696
else:
9797
files.append(file_content)
9898
return files
9999

100100

101+
def update_robots_file(repo, current_year):
102+
c = repo.get_contents('robots.txt')
103+
new_content = c.decoded_content.strip() + f'\nDisallow: /{current_year}/\n'.encode()
104+
repo.update_file(c.path, 'Update robots.txt', new_content, c.sha)
105+
106+
101107
def archive_current_gsoc_files(current_year):
102108
g = Github(settings.GITHUB_ACCESS_TOKEN)
103109
repo = g.get_repo(settings.STATIC_SITE_REPO)
104110
files = get_files(repo)
111+
update_robots_file(repo, current_year)
105112
for file in files:
106113
try:
107114
repo.create_file(f'{current_year}/{file.path}',
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Generated by Django 2.1.10 on 2019-07-28 09:57
2+
3+
from django.db import migrations, models
4+
import django.db.models.deletion
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('aldryn_newsblog', '0016_auto_20180329_1417'),
11+
('gsoc', '0048_reglink_send_notifications'),
12+
]
13+
14+
operations = [
15+
migrations.CreateModel(
16+
name='BlogPostHistory',
17+
fields=[
18+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19+
('timestamp', models.DateTimeField(auto_now_add=True)),
20+
('content', models.TextField(blank=True, null=True)),
21+
('article', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='aldryn_newsblog.Article')),
22+
],
23+
),
24+
]

gsoc/models.py

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,15 @@ def gen_uuid_str():
4848
NewsBlogConfig.__str__ = lambda self: self.app_title
4949

5050

51+
def current_year_profile(self):
52+
gsoc_year = GsocYear.objects.first()
53+
profile = self.userprofile_set.filter(gsoc_year=gsoc_year, role__in=[1, 2, 3])
54+
return profile.first() if len(profile) > 0 else None
55+
56+
57+
auth.models.User.add_to_class('current_year_profile', current_year_profile)
58+
59+
5160
def has_proposal(self):
5261
try:
5362
proposal = self.student_profile().accepted_proposal_pdf
@@ -112,34 +121,6 @@ def get_root_comments(self):
112121
Article.add_to_class('get_root_comments', get_root_comments)
113122

114123

115-
def is_unclean(self):
116-
unclean_texts = (
117-
'<pre>',
118-
'</pre>',
119-
'&lt;',
120-
'&gt;',
121-
)
122-
for _ in unclean_texts:
123-
if _ in self.lead_in:
124-
return True
125-
return False
126-
127-
128-
Article.add_to_class('is_unclean', is_unclean)
129-
130-
131-
def clean_article_html(self):
132-
self.lead_in = re.sub(r'<pre>', '<code>', self.lead_in)
133-
self.lead_in = re.sub(r'<\/pre>', '</code>', self.lead_in)
134-
self.lead_in = re.sub(r'&lt;', '<', self.lead_in)
135-
self.lead_in = re.sub(r'&gt;', '>', self.lead_in)
136-
self.lead_in = mark_safe(self.lead_in)
137-
self.save()
138-
139-
140-
Article.add_to_class('clean_article_html', clean_article_html)
141-
142-
143124
# Models
144125

145126
class SubOrg(models.Model):
@@ -488,6 +469,12 @@ def save(self, *args, **kwargs):
488469
super().save(*args, **kwargs)
489470

490471

472+
class BlogPostHistory(models.Model):
473+
article = models.ForeignKey(Article, on_delete=models.CASCADE)
474+
timestamp = models.DateTimeField(auto_now_add=True)
475+
content = models.TextField(null=True, blank=True)
476+
477+
491478
class BlogPostDueDate(models.Model):
492479
categories = (
493480
(0, 'Weekly Check-In'),
@@ -1098,11 +1085,17 @@ def decrease_blog_counter(sender, instance, **kwargs):
10981085
up.save()
10991086

11001087

1101-
# Clean lead_in HTML when new Article is created
1102-
# @receiver(models.signals.post_save, sender=Article)
1103-
# def clean_html(sender, instance, **kwargs):
1104-
# if instance.is_unclean():
1105-
# instance.clean_article_html()
1088+
# Add ArticleReveiw object when new Article is created
1089+
@receiver(models.signals.post_save, sender=Article)
1090+
def add_review(sender, instance, **kwargs):
1091+
ar = ArticleReview.objects.filter(article=instance).all()
1092+
if not ar:
1093+
ArticleReview.objects.create(article=instance)
1094+
1095+
if ar:
1096+
ar = ar.first()
1097+
ar.is_reviewed = False
1098+
ar.save()
11061099

11071100

11081101
# Add ArticleReveiw object when new Article is created
@@ -1116,3 +1109,9 @@ def add_review(sender, instance, **kwargs):
11161109
ar = ar.first()
11171110
ar.is_reviewed = False
11181111
ar.save()
1112+
1113+
1114+
# Add BlogPostHistory object when new Article is created
1115+
@receiver(models.signals.post_save, sender=Article)
1116+
def add_history(sender, instance, **kwargs):
1117+
BlogPostHistory.objects.create(article=instance, content=instance.lead_in)

gsoc/static/css/article.css

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,65 @@ article > heading {
111111
text-decoration: none;
112112
color: white;
113113
}
114+
115+
.aldryn-newsblog-comments {
116+
margin: 16px 0;
117+
padding: 16px 24px;
118+
}
119+
120+
.aldryn-newsblog-comments form {
121+
display: none;
122+
}
123+
124+
.aldryn-newsblog-comments #form-root {
125+
display: block;
126+
}
127+
128+
.aldryn-newsblog-subcomments {
129+
padding-left: 24px;
130+
border-left: 0.1px solid #eee;
131+
}
132+
133+
.comment {
134+
padding: 5px 10px;
135+
margin: 5px 0px;
136+
background: #eee;
137+
}
138+
139+
.comment.selected {
140+
background: #ccc;
141+
}
142+
143+
.comment-container .c-username {
144+
color: #489EBA;
145+
font-size: 12px;
146+
font-weight: bold;
147+
}
148+
149+
.comment-container .c-actions {
150+
font-size: 12px;
151+
}
152+
153+
.comment-container .c-actions span {
154+
margin-right: 10px;
155+
}
156+
157+
.comment-container .c-actions .reply {
158+
cursor: pointer;
159+
}
160+
161+
.comment-container .c-actions .share {
162+
cursor: pointer;
163+
}
164+
165+
.comment-container .c-actions .delete {
166+
cursor: pointer;
167+
}
168+
169+
.comment-container .c-content {
170+
font-size: 14px;
171+
}
172+
173+
form textarea {
174+
border-radius: 0 0 4px 4px !important;
175+
}

0 commit comments

Comments
 (0)