Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
AE UTBM
Sith
Commits
1ca6bf7c
Commit
1ca6bf7c
authored
Dec 23, 2016
by
Skia
🤘
Browse files
Add news system, still miss nices templates and moderation tools
parent
f79ffbee
Pipeline
#605
passed with stage
in 2 minutes and 28 seconds
Changes
9
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
com/admin.py
View file @
1ca6bf7c
...
...
@@ -3,6 +3,7 @@ from django.contrib import admin
from
com.models
import
*
admin
.
site
.
register
(
Sith
)
admin
.
site
.
register
(
News
)
com/migrations/0002_news_newsdate.py
0 → 100644
View file @
1ca6bf7c
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
from
django.conf
import
settings
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
migrations
.
swappable_dependency
(
settings
.
AUTH_USER_MODEL
),
(
'club'
,
'0005_auto_20161120_1149'
),
(
'com'
,
'0001_initial'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'News'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
serialize
=
False
,
auto_created
=
True
,
primary_key
=
True
,
verbose_name
=
'ID'
)),
(
'title'
,
models
.
CharField
(
max_length
=
64
,
verbose_name
=
'title'
)),
(
'summary'
,
models
.
TextField
(
verbose_name
=
'summary'
)),
(
'content'
,
models
.
TextField
(
verbose_name
=
'content'
)),
(
'type'
,
models
.
CharField
(
max_length
=
16
,
choices
=
[(
'NOTICE'
,
'Notice'
),
(
'EVENT'
,
'Event'
),
(
'WEEKLY'
,
'Weekly'
),
(
'CALL'
,
'Call'
)],
default
=
'EVENT'
,
verbose_name
=
'type'
)),
(
'is_moderated'
,
models
.
BooleanField
(
default
=
False
,
verbose_name
=
'is moderated'
)),
(
'club'
,
models
.
ForeignKey
(
to
=
'club.Club'
,
verbose_name
=
'club'
,
related_name
=
'news'
)),
(
'moderator'
,
models
.
ForeignKey
(
verbose_name
=
'owner'
,
to
=
settings
.
AUTH_USER_MODEL
,
related_name
=
'moderated_news'
,
null
=
True
)),
(
'owner'
,
models
.
ForeignKey
(
to
=
settings
.
AUTH_USER_MODEL
,
verbose_name
=
'owner'
,
related_name
=
'owned_news'
)),
],
),
migrations
.
CreateModel
(
name
=
'NewsDate'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
serialize
=
False
,
auto_created
=
True
,
primary_key
=
True
,
verbose_name
=
'ID'
)),
(
'start_date'
,
models
.
DateTimeField
(
null
=
True
,
blank
=
True
,
verbose_name
=
'start_date'
)),
(
'end_date'
,
models
.
DateTimeField
(
null
=
True
,
blank
=
True
,
verbose_name
=
'end_date'
)),
(
'news'
,
models
.
ForeignKey
(
to
=
'com.News'
,
verbose_name
=
'news_date'
,
related_name
=
'dates'
)),
],
),
]
com/models.py
View file @
1ca6bf7c
from
django.db
import
models
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.core.urlresolvers
import
reverse_lazy
,
reverse
from
django.conf
import
settings
from
core.models
import
User
from
club.models
import
Club
class
Sith
(
models
.
Model
):
"""A one instance class storing all the modifiable infos"""
alert_msg
=
models
.
TextField
(
_
(
"alert message"
),
default
=
""
,
blank
=
True
)
info_msg
=
models
.
TextField
(
_
(
"info message"
),
default
=
""
,
blank
=
True
)
index_page
=
models
.
TextField
(
_
(
"index page"
),
default
=
""
,
blank
=
True
)
...
...
@@ -13,3 +18,40 @@ class Sith(models.Model):
def
__str__
(
self
):
return
"⛩ Sith ⛩"
NEWS_TYPES
=
[
(
'NOTICE'
,
_
(
'Notice'
)),
(
'EVENT'
,
_
(
'Event'
)),
(
'WEEKLY'
,
_
(
'Weekly'
)),
(
'CALL'
,
_
(
'Call'
)),
]
class
News
(
models
.
Model
):
"""The news class"""
title
=
models
.
CharField
(
_
(
"title"
),
max_length
=
64
)
summary
=
models
.
TextField
(
_
(
"summary"
))
content
=
models
.
TextField
(
_
(
"content"
))
type
=
models
.
CharField
(
_
(
"type"
),
max_length
=
16
,
choices
=
NEWS_TYPES
,
default
=
"EVENT"
)
club
=
models
.
ForeignKey
(
Club
,
related_name
=
"news"
,
verbose_name
=
_
(
"club"
))
owner
=
models
.
ForeignKey
(
User
,
related_name
=
"owned_news"
,
verbose_name
=
_
(
"owner"
))
is_moderated
=
models
.
BooleanField
(
_
(
"is moderated"
),
default
=
False
)
moderator
=
models
.
ForeignKey
(
User
,
related_name
=
"moderated_news"
,
verbose_name
=
_
(
"owner"
),
null
=
True
)
def
get_absolute_url
(
self
):
return
reverse
(
'com:news_detail'
,
kwargs
=
{
'news_id'
:
self
.
id
})
def
__str__
(
self
):
return
"%s: %s"
%
(
self
.
type
,
self
.
title
)
class
NewsDate
(
models
.
Model
):
"""
A date class, useful for weekly events, or for events that just have no date
This class allows more flexibilty managing the dates related to a news, particularly when this news is weekly, since
we don't have to make copies
"""
news
=
models
.
ForeignKey
(
News
,
related_name
=
"dates"
,
verbose_name
=
_
(
"news_date"
))
start_date
=
models
.
DateTimeField
(
_
(
'start_date'
),
null
=
True
,
blank
=
True
)
end_date
=
models
.
DateTimeField
(
_
(
'end_date'
),
null
=
True
,
blank
=
True
)
def
__str__
(
self
):
return
"%s: %s - %s"
%
(
self
.
news
.
title
,
self
.
start_date
,
self
.
end_date
)
com/templates/com/news_admin_list.jinja
0 → 100644
View file @
1ca6bf7c
{%
extends
"core/base.jinja"
%}
{%
block
title
%}
{%
trans
%}
News admin
{%
endtrans
%}
{%
endblock
%}
{%
block
content
%}
<h3>
{%
trans
%}
News
{%
endtrans
%}
</h3>
<ul>
{%
for
news
in
object_list
%}
<li>
<p>
{{
news.get_type_display
()
}}
-
{{
news.title
}}
:
<span>
{{
news.dates.first
()
.
start_date
|
localtime
|
date
(
DATETIME_FORMAT
)
}}
{{
news.dates.first
()
.
start_date
|
localtime
|
time
(
DATETIME_FORMAT
)
}}
</span>
-
<span>
{{
news.dates.first
()
.
end_date
|
localtime
|
date
(
DATETIME_FORMAT
)
}}
{{
news.dates.first
()
.
end_date
|
localtime
|
time
(
DATETIME_FORMAT
)
}}
</span>
-
<a
href=
"
{{
url
(
'com:news_edit'
,
news_id
=
news.id
)
}}
"
>
{%
trans
%}
Edit
{%
endtrans
%}
</a>
</p>
</li>
{%
endfor
%}
</ul>
{%
endblock
%}
com/templates/com/news_detail.jinja
0 → 100644
View file @
1ca6bf7c
{%
extends
"core/base.jinja"
%}
{%
block
title
%}
{%
trans
%}
News
{%
endtrans
%}
-
{{
object.title
}}
{%
endblock
%}
{%
block
content
%}
<h3>
{%
trans
%}
News
{%
endtrans
%}
</h3>
{{
object
}}
{{
object.dates.all
()
}}
{%
endblock
%}
com/templates/com/news_edit.jinja
0 → 100644
View file @
1ca6bf7c
{%
extends
"core/base.jinja"
%}
{%
block
title
%}
{%
if
object
%}
{%
trans
%}
Edit news
{%
endtrans
%}
{%
else
%}
{%
trans
%}
Create news
{%
endtrans
%}
{%
endif
%}
{%
endblock
%}
{%
block
content
%}
{%
if
object
%}
<h2>
{%
trans
%}
Edit news
{%
endtrans
%}
</h2>
{%
else
%}
<h2>
{%
trans
%}
Create news
{%
endtrans
%}
</h2>
{%
endif
%}
<form
action=
""
method=
"post"
>
{%
csrf_token
%}
{{
form.non_field_errors
()
}}
{{
form.owner
}}
<p>
{{
form.type.errors
}}
<label
for=
"
{{
form.type.name
}}
"
>
{{
form.type.label
}}
</label>
{{
form.type
}}
</p>
<p
class=
"date"
>
{{
form.start_date.errors
}}
<label
for=
"
{{
form.start_date.name
}}
"
>
{{
form.start_date.label
}}
</label>
{{
form.start_date
}}
</p>
<p
class=
"date"
>
{{
form.end_date.errors
}}
<label
for=
"
{{
form.end_date.name
}}
"
>
{{
form.end_date.label
}}
</label>
{{
form.end_date
}}
</p>
<p
class=
"until"
>
{{
form.until.errors
}}
<label
for=
"
{{
form.until.name
}}
"
>
{{
form.until.label
}}
</label>
{{
form.until
}}
</p>
<p>
{{
form.title.errors
}}
<label
for=
"
{{
form.title.name
}}
"
>
{{
form.title.label
}}
</label>
{{
form.title
}}
</p>
<p>
{{
form.club.errors
}}
<label
for=
"
{{
form.club.name
}}
"
>
{{
form.club.label
}}
</label>
{{
form.club
}}
</p>
<p>
{{
form.summary.errors
}}
<label
for=
"
{{
form.summary.name
}}
"
>
{{
form.summary.label
}}
</label>
{{
form.summary
}}
</p>
<p>
{{
form.content.errors
}}
<label
for=
"
{{
form.content.name
}}
"
>
{{
form.content.label
}}
</label>
{{
form.content
}}
</p>
<p><input
type=
"submit"
value=
"
{%
trans
%}
Save
{%
endtrans
%}
"
/></p>
</form>
{%
endblock
%}
{%
block
script
%}
{{
super
()
}}
<script>
$
(
function
()
{
var
type
=
$
(
'
input[name=type]
'
);
var
dates
=
$
(
'
.date
'
);
var
until
=
$
(
'
.until
'
);
function
update_targets
()
{
type_checked
=
$
(
'
input[name=type]:checked
'
);
if
(
type_checked
.
val
()
==
"
EVENT
"
||
type_checked
.
val
()
==
"
CALL
"
)
{
dates
.
show
();
until
.
hide
();
}
else
if
(
type_checked
.
val
()
==
"
WEEKLY
"
)
{
dates
.
show
();
until
.
show
();
}
else
{
dates
.
hide
();
until
.
hide
();
}
}
update_targets
();
type
.
change
(
update_targets
);
}
);
</script>
{%
endblock
%}
com/templates/com/news_list.jinja
0 → 100644
View file @
1ca6bf7c
{%
extends
"core/base.jinja"
%}
{%
block
title
%}
{%
trans
%}
News
{%
endtrans
%}
{%
endblock
%}
{%
block
head
%}
{{
super
()
}}
<style
type=
"text/css"
media=
"all"
>
section
{
padding
:
5px
;
}
section
.news_call
{
background
:
lightgrey
;
}
section
.news_event
:nth-child
(
even
)
{
background
:
lightblue
;
}
.date
{
font-size
:
small
;
color
:
grey
;
}
</style>
{%
endblock
%}
{%
block
content
%}
<h3>
{%
trans
%}
News
{%
endtrans
%}
</h3>
<hr>
<h4>
Notice
</h4>
{%
for
news
in
object_list.
filter
(
type
=
"NOTICE"
)
%}
<section
class=
"news_notice"
>
<h4>
{{
news.title
}}
</h4>
<p>
{{
news.summary
}}
</p>
</section>
{%
endfor
%}
<hr>
<h4>
Calls
</h4>
{%
for
news
in
object_list.
filter
(
dates__start_date__lte
=
timezone.now
(),
dates__end_date__gte
=
timezone.now
(),
type
=
"CALL"
)
%}
<section
class=
"news_call"
>
<h4>
{{
news.title
}}
</h4>
<p
class=
"date"
>
<span>
{{
news.dates.first
()
.
start_date
|
localtime
|
date
(
DATETIME_FORMAT
)
}}
{{
news.dates.first
()
.
start_date
|
localtime
|
time
(
DATETIME_FORMAT
)
}}
</span>
-
<span>
{{
news.dates.first
()
.
end_date
|
localtime
|
date
(
DATETIME_FORMAT
)
}}
{{
news.dates.first
()
.
end_date
|
localtime
|
time
(
DATETIME_FORMAT
)
}}
</span>
</p>
<p>
{{
news.summary
}}
</p>
</section>
{%
endfor
%}
<hr>
<h4>
Events
</h4>
{%
for
news
in
object_list.
filter
(
dates__end_date__gte
=
timezone.now
(),
type
=
"EVENT"
)
%}
<section
class=
"news_event"
>
<h4>
{{
news.title
}}
</h4>
<p
class=
"date"
>
<span>
{{
news.dates.first
()
.
start_date
|
localtime
|
date
(
DATETIME_FORMAT
)
}}
{{
news.dates.first
()
.
start_date
|
localtime
|
time
(
DATETIME_FORMAT
)
}}
</span>
-
<span>
{{
news.dates.first
()
.
end_date
|
localtime
|
date
(
DATETIME_FORMAT
)
}}
{{
news.dates.first
()
.
end_date
|
localtime
|
time
(
DATETIME_FORMAT
)
}}
</span>
</p>
<p><a
href=
"
{{
news.club.get_absolute_url
()
}}
"
>
{{
news.club
}}
</a></p>
<p>
{{
news.summary
|
markdown
}}
</p>
</section>
{%
endfor
%}
<hr>
<h4>
Weekly
</h4>
{%
for
news
in
object_list.
filter
(
dates__end_date__gte
=
timezone.now
(),
type
=
"WEEKLY"
)
.
distinct
()
%}
<!-- buggy when more than one news, anyway, we won't use it this way -->
{%
for
d
in
news.dates.all
()
%}
<section
class=
"news_weekly"
>
<h4>
{{
news.title
}}
</h4>
<p
class=
"date"
>
<span>
{{
d.start_date
|
localtime
|
date
(
DATETIME_FORMAT
)
}}
{{
d.start_date
|
localtime
|
time
(
DATETIME_FORMAT
)
}}
</span>
-
<span>
{{
d.end_date
|
localtime
|
date
(
DATETIME_FORMAT
)
}}
{{
d.end_date
|
localtime
|
time
(
DATETIME_FORMAT
)
}}
</span>
</p>
<p><a
href=
"
{{
news.club.get_absolute_url
()
}}
"
>
{{
news.club
}}
</a></p>
<p>
{{
news.summary
|
markdown
}}
</p>
</section>
{%
endfor
%}
{%
endfor
%}
{%
endblock
%}
com/urls.py
View file @
1ca6bf7c
...
...
@@ -3,8 +3,13 @@ from django.conf.urls import url, include
from
com.views
import
*
urlpatterns
=
[
url
(
r
'^edit/alert$'
,
AlertMsgEditView
.
as_view
(),
name
=
'alert_edit'
),
url
(
r
'^edit/info$'
,
InfoMsgEditView
.
as_view
(),
name
=
'info_edit'
),
url
(
r
'^edit/index$'
,
IndexEditView
.
as_view
(),
name
=
'index_edit'
),
url
(
r
'^sith/edit/alert$'
,
AlertMsgEditView
.
as_view
(),
name
=
'alert_edit'
),
url
(
r
'^sith/edit/info$'
,
InfoMsgEditView
.
as_view
(),
name
=
'info_edit'
),
url
(
r
'^sith/edit/index$'
,
IndexEditView
.
as_view
(),
name
=
'index_edit'
),
url
(
r
'^news$'
,
NewsListView
.
as_view
(),
name
=
'news_list'
),
url
(
r
'^news/admin$'
,
NewsAdminListView
.
as_view
(),
name
=
'news_admin_list'
),
url
(
r
'^news/create$'
,
NewsCreateView
.
as_view
(),
name
=
'news_new'
),
url
(
r
'^news/(?P<news_id>[0-9]+)/edit$'
,
NewsEditView
.
as_view
(),
name
=
'news_edit'
),
url
(
r
'^news/(?P<news_id>[0-9]+)$'
,
NewsDetailView
.
as_view
(),
name
=
'news_detail'
),
]
com/views.py
View file @
1ca6bf7c
from
django.shortcuts
import
render
from
django.views.generic.edit
import
UpdateView
from
django.views.generic
import
ListView
,
DetailView
,
RedirectView
from
django.views.generic.edit
import
UpdateView
,
CreateView
from
django.utils.translation
import
ugettext
as
_
from
django.core.urlresolvers
import
reverse
,
reverse_lazy
from
django.core.exceptions
import
ValidationError
from
django.utils
import
timezone
from
django
import
forms
from
com.models
import
Sith
from
datetime
import
timedelta
from
com.models
import
Sith
,
News
,
NewsDate
from
core.views
import
CanViewMixin
,
CanEditMixin
,
CanEditPropMixin
,
TabedViewMixin
from
core.views.forms
import
SelectDateTime
from
club.models
import
Club
# Sith object
sith
=
Sith
.
objects
.
first
...
...
@@ -53,3 +63,87 @@ class IndexEditView(ComEditView):
fields
=
[
'index_page'
]
current_tab
=
"index"
success_url
=
reverse_lazy
(
'com:index_edit'
)
# News
class
NewsForm
(
forms
.
ModelForm
):
class
Meta
:
model
=
News
fields
=
[
'type'
,
'title'
,
'club'
,
'summary'
,
'content'
,
'owner'
]
widgets
=
{
'owner'
:
forms
.
HiddenInput
,
'type'
:
forms
.
RadioSelect
,
}
start_date
=
forms
.
DateTimeField
([
'%Y-%m-%d %H:%M:%S'
],
label
=
_
(
"Start date"
),
widget
=
SelectDateTime
,
required
=
False
)
end_date
=
forms
.
DateTimeField
([
'%Y-%m-%d %H:%M:%S'
],
label
=
_
(
"End date"
),
widget
=
SelectDateTime
,
required
=
False
)
until
=
forms
.
DateTimeField
([
'%Y-%m-%d %H:%M:%S'
],
label
=
_
(
"Until"
),
widget
=
SelectDateTime
,
required
=
False
)
def
clean
(
self
):
self
.
cleaned_data
=
super
(
NewsForm
,
self
).
clean
()
if
self
.
cleaned_data
[
'type'
]
!=
"NOTICE"
:
if
not
self
.
cleaned_data
[
'start_date'
]:
self
.
add_error
(
'start_date'
,
ValidationError
(
_
(
"This field is required."
)))
if
not
self
.
cleaned_data
[
'end_date'
]:
self
.
add_error
(
'end_date'
,
ValidationError
(
_
(
"This field is required."
)))
if
self
.
cleaned_data
[
'type'
]
==
"WEEKLY"
and
not
self
.
cleaned_data
[
'until'
]:
self
.
add_error
(
'until'
,
ValidationError
(
_
(
"This field is required."
)))
return
self
.
cleaned_data
def
save
(
self
):
ret
=
super
(
NewsForm
,
self
).
save
()
self
.
instance
.
dates
.
all
().
delete
()
if
self
.
instance
.
type
==
"EVENT"
or
self
.
instance
.
type
==
"CALL"
:
NewsDate
(
start_date
=
self
.
cleaned_data
[
'start_date'
],
end_date
=
self
.
cleaned_data
[
'end_date'
],
news
=
self
.
instance
).
save
()
elif
self
.
instance
.
type
==
"WEEKLY"
:
start_date
=
self
.
cleaned_data
[
'start_date'
]
end_date
=
self
.
cleaned_data
[
'end_date'
]
while
start_date
<=
self
.
cleaned_data
[
'until'
]:
NewsDate
(
start_date
=
start_date
,
end_date
=
end_date
,
news
=
self
.
instance
).
save
()
start_date
+=
timedelta
(
days
=
7
)
end_date
+=
timedelta
(
days
=
7
)
return
ret
class
NewsEditView
(
UpdateView
):
model
=
News
form_class
=
NewsForm
template_name
=
'com/news_edit.jinja'
pk_url_kwarg
=
'news_id'
def
get_initial
(
self
):
init
=
{}
try
:
init
[
'start_date'
]
=
self
.
object
.
dates
.
order_by
(
'id'
).
first
().
start_date
.
strftime
(
'%Y-%m-%d %H:%M:%S'
)
except
:
pass
try
:
init
[
'end_date'
]
=
self
.
object
.
dates
.
order_by
(
'id'
).
first
().
end_date
.
strftime
(
'%Y-%m-%d %H:%M:%S'
)
except
:
pass
return
init
class
NewsCreateView
(
CreateView
):
model
=
News
form_class
=
NewsForm
template_name
=
'com/news_edit.jinja'
def
get_initial
(
self
):
init
=
{
'owner'
:
self
.
request
.
user
}
try
:
init
[
'club'
]
=
Club
.
objects
.
filter
(
id
=
self
.
request
.
GET
[
'club'
]).
first
()
except
:
pass
return
init
class
NewsAdminListView
(
ListView
):
model
=
News
template_name
=
'com/news_admin_list.jinja'
class
NewsListView
(
ListView
):
model
=
News
template_name
=
'com/news_list.jinja'
class
NewsDetailView
(
DetailView
):
model
=
News
template_name
=
'com/news_detail.jinja'
pk_url_kwarg
=
'news_id'
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment