Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
nk20
Manage
Activity
Members
Labels
Plan
Issues
32
Issue boards
Milestones
Wiki
Code
Merge requests
6
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
BDE
nk20
Commits
70e1a611
Commit
70e1a611
authored
4 years ago
by
ynerant
Browse files
Options
Downloads
Patches
Plain Diff
Export activites as an ICS Calendar
parent
5c7fe716
No related branches found
No related tags found
1 merge request
!107
Beta
Pipeline
#8625
failed with stages
in 55 seconds
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
apps/activity/urls.py
+1
-0
1 addition, 0 deletions
apps/activity/urls.py
apps/activity/views.py
+344
-283
344 additions, 283 deletions
apps/activity/views.py
apps/logs/signals.py
+1
-4
1 addition, 4 deletions
apps/logs/signals.py
with
346 additions
and
287 deletions
apps/activity/urls.py
+
1
−
0
View file @
70e1a611
...
...
@@ -14,4 +14,5 @@ urlpatterns = [
path
(
'
<int:pk>/entry/
'
,
views
.
ActivityEntryView
.
as_view
(),
name
=
'
activity_entry
'
),
path
(
'
<int:pk>/update/
'
,
views
.
ActivityUpdateView
.
as_view
(),
name
=
'
activity_update
'
),
path
(
'
new/
'
,
views
.
ActivityCreateView
.
as_view
(),
name
=
'
activity_create
'
),
path
(
'
calendar.ics
'
,
views
.
CalendarView
.
as_view
(),
name
=
'
calendar_ics
'
),
]
This diff is collapsed.
Click to expand it.
apps/activity/views.py
+
344
−
283
View file @
70e1a611
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from
django.conf
import
settings
from
django.contrib.auth.mixins
import
LoginRequiredMixin
from
django.contrib.contenttypes.models
import
ContentType
from
django.core.exceptions
import
PermissionDenied
from
django.db.models
import
F
,
Q
from
django.urls
import
reverse_lazy
from
django.utils
import
timezone
from
django.utils.translation
import
gettext_lazy
as
_
from
django.views.generic
import
DetailView
,
TemplateView
,
UpdateView
from
django_tables2.views
import
SingleTableView
from
note.models
import
Alias
,
NoteSpecial
,
NoteUser
from
permission.backends
import
PermissionBackend
from
permission.views
import
ProtectQuerysetMixin
,
ProtectedCreateView
from
.forms
import
ActivityForm
,
GuestForm
from
.models
import
Activity
,
Entry
,
Guest
from
.tables
import
ActivityTable
,
EntryTable
,
GuestTable
class
ActivityCreateView
(
ProtectQuerysetMixin
,
ProtectedCreateView
):
"""
View to create a new Activity
"""
model
=
Activity
form_class
=
ActivityForm
extra_context
=
{
"
title
"
:
_
(
"
Create new activity
"
)}
def
get_sample_object
(
self
):
return
Activity
(
name
=
""
,
description
=
""
,
creater
=
self
.
request
.
user
,
activity_type_id
=
1
,
organizer_id
=
1
,
attendees_club_id
=
1
,
date_start
=
timezone
.
now
(),
date_end
=
timezone
.
now
(),
)
def
form_valid
(
self
,
form
):
form
.
instance
.
creater
=
self
.
request
.
user
return
super
().
form_valid
(
form
)
def
get_success_url
(
self
,
**
kwargs
):
self
.
object
.
refresh_from_db
()
return
reverse_lazy
(
'
activity:activity_detail
'
,
kwargs
=
{
"
pk
"
:
self
.
object
.
pk
})
class
ActivityListView
(
ProtectQuerysetMixin
,
LoginRequiredMixin
,
SingleTableView
):
"""
Displays all Activities, and classify if they are on-going or upcoming ones.
"""
model
=
Activity
table_class
=
ActivityTable
ordering
=
(
'
-date_start
'
,)
extra_context
=
{
"
title
"
:
_
(
"
Activities
"
)}
def
get_queryset
(
self
):
return
super
().
get_queryset
().
distinct
()
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
().
get_context_data
(
**
kwargs
)
upcoming_activities
=
Activity
.
objects
.
filter
(
date_end__gt
=
timezone
.
now
())
context
[
'
upcoming
'
]
=
ActivityTable
(
data
=
upcoming_activities
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Activity
,
"
view
"
)),
prefix
=
'
upcoming-
'
,
)
started_activities
=
Activity
.
objects
\
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Activity
,
"
view
"
))
\
.
filter
(
open
=
True
,
valid
=
True
).
all
()
context
[
"
started_activities
"
]
=
started_activities
return
context
class
ActivityDetailView
(
ProtectQuerysetMixin
,
LoginRequiredMixin
,
DetailView
):
"""
Shows details about one activity. Add guest to context
"""
model
=
Activity
context_object_name
=
"
activity
"
extra_context
=
{
"
title
"
:
_
(
"
Activity detail
"
)}
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
().
get_context_data
()
table
=
GuestTable
(
data
=
Guest
.
objects
.
filter
(
activity
=
self
.
object
)
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Guest
,
"
view
"
)))
context
[
"
guests
"
]
=
table
context
[
"
activity_started
"
]
=
timezone
.
now
()
>
timezone
.
localtime
(
self
.
object
.
date_start
)
return
context
class
ActivityUpdateView
(
ProtectQuerysetMixin
,
LoginRequiredMixin
,
UpdateView
):
"""
Updates one Activity
"""
model
=
Activity
form_class
=
ActivityForm
extra_context
=
{
"
title
"
:
_
(
"
Update activity
"
)}
def
get_success_url
(
self
,
**
kwargs
):
return
reverse_lazy
(
'
activity:activity_detail
'
,
kwargs
=
{
"
pk
"
:
self
.
kwargs
[
"
pk
"
]})
class
ActivityInviteView
(
ProtectQuerysetMixin
,
ProtectedCreateView
):
"""
Invite a Guest, The rules to invites someone are defined in `forms:activity.GuestForm`
"""
model
=
Guest
form_class
=
GuestForm
template_name
=
"
activity/activity_form.html
"
def
get_sample_object
(
self
):
"""
Creates a standart Guest binds to the Activity
"""
activity
=
Activity
.
objects
.
get
(
pk
=
self
.
kwargs
[
"
pk
"
])
return
Guest
(
activity
=
activity
,
first_name
=
""
,
last_name
=
""
,
inviter
=
self
.
request
.
user
.
note
,
)
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
().
get_context_data
(
**
kwargs
)
activity
=
context
[
"
form
"
].
activity
context
[
"
title
"
]
=
_
(
'
Invite guest to the activity
"
{}
"'
).
format
(
activity
.
name
)
return
context
def
get_form
(
self
,
form_class
=
None
):
form
=
super
().
get_form
(
form_class
)
form
.
activity
=
Activity
.
objects
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Activity
,
"
view
"
))
\
.
get
(
pk
=
self
.
kwargs
[
"
pk
"
])
form
.
fields
[
"
inviter
"
].
initial
=
self
.
request
.
user
.
note
return
form
def
form_valid
(
self
,
form
):
form
.
instance
.
activity
=
Activity
.
objects
\
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Activity
,
"
view
"
)).
get
(
pk
=
self
.
kwargs
[
"
pk
"
])
return
super
().
form_valid
(
form
)
def
get_success_url
(
self
,
**
kwargs
):
return
reverse_lazy
(
'
activity:activity_detail
'
,
kwargs
=
{
"
pk
"
:
self
.
kwargs
[
"
pk
"
]})
class
ActivityEntryView
(
LoginRequiredMixin
,
TemplateView
):
"""
Manages entry to an activity
"""
template_name
=
"
activity/activity_entry.html
"
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
"""
Don
'
t display the entry interface if the user has no right to see it (no right to add an entry for itself),
it is closed or doesn
'
t manage entries.
"""
activity
=
Activity
.
objects
.
get
(
pk
=
self
.
kwargs
[
"
pk
"
])
sample_entry
=
Entry
(
activity
=
activity
,
note
=
self
.
request
.
user
.
note
)
if
not
PermissionBackend
.
check_perm
(
self
.
request
.
user
,
"
activity.add_entry
"
,
sample_entry
):
raise
PermissionDenied
(
_
(
"
You are not allowed to display the entry interface for this activity.
"
))
if
not
activity
.
activity_type
.
manage_entries
:
raise
PermissionDenied
(
_
(
"
This activity does not support activity entries.
"
))
if
not
activity
.
open
:
raise
PermissionDenied
(
_
(
"
This activity is closed.
"
))
return
super
().
dispatch
(
request
,
*
args
,
**
kwargs
)
def
get_invited_guest
(
self
,
activity
):
"""
Retrieves all Guests to the activity
"""
guest_qs
=
Guest
.
objects
\
.
annotate
(
balance
=
F
(
"
inviter__balance
"
),
note_name
=
F
(
"
inviter__user__username
"
))
\
.
filter
(
activity
=
activity
)
\
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Guest
,
"
view
"
))
\
.
order_by
(
'
last_name
'
,
'
first_name
'
).
distinct
()
if
"
search
"
in
self
.
request
.
GET
and
self
.
request
.
GET
[
"
search
"
]:
pattern
=
self
.
request
.
GET
[
"
search
"
]
if
pattern
[
0
]
!=
"
^
"
:
pattern
=
"
^
"
+
pattern
guest_qs
=
guest_qs
.
filter
(
Q
(
first_name__regex
=
pattern
)
|
Q
(
last_name__regex
=
pattern
)
|
Q
(
inviter__alias__name__regex
=
pattern
)
|
Q
(
inviter__alias__normalized_name__regex
=
Alias
.
normalize
(
pattern
))
)
else
:
guest_qs
=
guest_qs
.
none
()
return
guest_qs
def
get_invited_note
(
self
,
activity
):
"""
Retrieves all Note that can attend the activity,
they need to have an up-to-date membership in the attendees_club.
"""
note_qs
=
Alias
.
objects
.
annotate
(
last_name
=
F
(
"
note__noteuser__user__last_name
"
),
first_name
=
F
(
"
note__noteuser__user__first_name
"
),
username
=
F
(
"
note__noteuser__user__username
"
),
note_name
=
F
(
"
name
"
),
balance
=
F
(
"
note__balance
"
))
# Keep only users that have a note
note_qs
=
note_qs
.
filter
(
note__noteuser__isnull
=
False
)
# Keep only members
note_qs
=
note_qs
.
filter
(
note__noteuser__user__memberships__club
=
activity
.
attendees_club
,
note__noteuser__user__memberships__date_start__lte
=
timezone
.
now
(),
note__noteuser__user__memberships__date_end__gte
=
timezone
.
now
(),
)
# Filter with permission backend
note_qs
=
note_qs
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Alias
,
"
view
"
))
if
"
search
"
in
self
.
request
.
GET
and
self
.
request
.
GET
[
"
search
"
]:
pattern
=
self
.
request
.
GET
[
"
search
"
]
note_qs
=
note_qs
.
filter
(
Q
(
note__noteuser__user__first_name__regex
=
pattern
)
|
Q
(
note__noteuser__user__last_name__regex
=
pattern
)
|
Q
(
name__regex
=
pattern
)
|
Q
(
normalized_name__regex
=
Alias
.
normalize
(
pattern
))
)
else
:
note_qs
=
note_qs
.
none
()
if
settings
.
DATABASES
[
note_qs
.
db
][
"
ENGINE
"
]
==
'
django.db.backends.postgresql
'
:
note_qs
=
note_qs
.
distinct
(
'
note__pk
'
)[:
20
]
else
:
# SQLite doesn't support distinct fields. For compatibility reason (in dev mode), the note list will only
# have distinct aliases rather than distinct notes with a SQLite DB, but it can fill the result page.
# In production mode, please use PostgreSQL.
note_qs
=
note_qs
.
distinct
()[:
20
]
return
note_qs
def
get_context_data
(
self
,
**
kwargs
):
"""
Query the list of Guest and Note to the activity and add information to makes entry with JS.
"""
context
=
super
().
get_context_data
(
**
kwargs
)
activity
=
Activity
.
objects
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Activity
,
"
view
"
))
\
.
distinct
().
get
(
pk
=
self
.
kwargs
[
"
pk
"
])
context
[
"
activity
"
]
=
activity
matched
=
[]
for
guest
in
self
.
get_invited_guest
(
activity
):
guest
.
type
=
"
Invité
"
matched
.
append
(
guest
)
for
note
in
self
.
get_invited_note
(
activity
):
note
.
type
=
"
Adhérent
"
note
.
activity
=
activity
matched
.
append
(
note
)
table
=
EntryTable
(
data
=
matched
)
context
[
"
table
"
]
=
table
context
[
"
entries
"
]
=
Entry
.
objects
.
filter
(
activity
=
activity
)
context
[
"
title
"
]
=
_
(
'
Entry for activity
"
{}
"'
).
format
(
activity
.
name
)
context
[
"
noteuser_ctype
"
]
=
ContentType
.
objects
.
get_for_model
(
NoteUser
).
pk
context
[
"
notespecial_ctype
"
]
=
ContentType
.
objects
.
get_for_model
(
NoteSpecial
).
pk
activities_open
=
Activity
.
objects
.
filter
(
open
=
True
).
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Activity
,
"
view
"
)).
distinct
().
all
()
context
[
"
activities_open
"
]
=
[
a
for
a
in
activities_open
if
PermissionBackend
.
check_perm
(
self
.
request
.
user
,
"
activity.add_entry
"
,
Entry
(
activity
=
a
,
note
=
self
.
request
.
user
.
note
,))]
return
context
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from
hashlib
import
md5
from
django.conf
import
settings
from
django.contrib.auth.mixins
import
LoginRequiredMixin
from
django.contrib.contenttypes.models
import
ContentType
from
django.core.exceptions
import
PermissionDenied
from
django.db.models
import
F
,
Q
from
django.http
import
HttpResponse
from
django.urls
import
reverse_lazy
from
django.utils
import
timezone
from
django.utils.translation
import
gettext_lazy
as
_
from
django.views
import
View
from
django.views.generic
import
DetailView
,
TemplateView
,
UpdateView
from
django_tables2.views
import
SingleTableView
from
note.models
import
Alias
,
NoteSpecial
,
NoteUser
from
permission.backends
import
PermissionBackend
from
permission.views
import
ProtectQuerysetMixin
,
ProtectedCreateView
from
.forms
import
ActivityForm
,
GuestForm
from
.models
import
Activity
,
Entry
,
Guest
from
.tables
import
ActivityTable
,
EntryTable
,
GuestTable
class
ActivityCreateView
(
ProtectQuerysetMixin
,
ProtectedCreateView
):
"""
View to create a new Activity
"""
model
=
Activity
form_class
=
ActivityForm
extra_context
=
{
"
title
"
:
_
(
"
Create new activity
"
)}
def
get_sample_object
(
self
):
return
Activity
(
name
=
""
,
description
=
""
,
creater
=
self
.
request
.
user
,
activity_type_id
=
1
,
organizer_id
=
1
,
attendees_club_id
=
1
,
date_start
=
timezone
.
now
(),
date_end
=
timezone
.
now
(),
)
def
form_valid
(
self
,
form
):
form
.
instance
.
creater
=
self
.
request
.
user
return
super
().
form_valid
(
form
)
def
get_success_url
(
self
,
**
kwargs
):
self
.
object
.
refresh_from_db
()
return
reverse_lazy
(
'
activity:activity_detail
'
,
kwargs
=
{
"
pk
"
:
self
.
object
.
pk
})
class
ActivityListView
(
ProtectQuerysetMixin
,
LoginRequiredMixin
,
SingleTableView
):
"""
Displays all Activities, and classify if they are on-going or upcoming ones.
"""
model
=
Activity
table_class
=
ActivityTable
ordering
=
(
'
-date_start
'
,)
extra_context
=
{
"
title
"
:
_
(
"
Activities
"
)}
def
get_queryset
(
self
):
return
super
().
get_queryset
().
distinct
()
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
().
get_context_data
(
**
kwargs
)
upcoming_activities
=
Activity
.
objects
.
filter
(
date_end__gt
=
timezone
.
now
())
context
[
'
upcoming
'
]
=
ActivityTable
(
data
=
upcoming_activities
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Activity
,
"
view
"
)),
prefix
=
'
upcoming-
'
,
)
started_activities
=
Activity
.
objects
\
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Activity
,
"
view
"
))
\
.
filter
(
open
=
True
,
valid
=
True
).
all
()
context
[
"
started_activities
"
]
=
started_activities
return
context
class
ActivityDetailView
(
ProtectQuerysetMixin
,
LoginRequiredMixin
,
DetailView
):
"""
Shows details about one activity. Add guest to context
"""
model
=
Activity
context_object_name
=
"
activity
"
extra_context
=
{
"
title
"
:
_
(
"
Activity detail
"
)}
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
().
get_context_data
()
table
=
GuestTable
(
data
=
Guest
.
objects
.
filter
(
activity
=
self
.
object
)
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Guest
,
"
view
"
)))
context
[
"
guests
"
]
=
table
context
[
"
activity_started
"
]
=
timezone
.
now
()
>
timezone
.
localtime
(
self
.
object
.
date_start
)
return
context
class
ActivityUpdateView
(
ProtectQuerysetMixin
,
LoginRequiredMixin
,
UpdateView
):
"""
Updates one Activity
"""
model
=
Activity
form_class
=
ActivityForm
extra_context
=
{
"
title
"
:
_
(
"
Update activity
"
)}
def
get_success_url
(
self
,
**
kwargs
):
return
reverse_lazy
(
'
activity:activity_detail
'
,
kwargs
=
{
"
pk
"
:
self
.
kwargs
[
"
pk
"
]})
class
ActivityInviteView
(
ProtectQuerysetMixin
,
ProtectedCreateView
):
"""
Invite a Guest, The rules to invites someone are defined in `forms:activity.GuestForm`
"""
model
=
Guest
form_class
=
GuestForm
template_name
=
"
activity/activity_form.html
"
def
get_sample_object
(
self
):
"""
Creates a standart Guest binds to the Activity
"""
activity
=
Activity
.
objects
.
get
(
pk
=
self
.
kwargs
[
"
pk
"
])
return
Guest
(
activity
=
activity
,
first_name
=
""
,
last_name
=
""
,
inviter
=
self
.
request
.
user
.
note
,
)
def
get_context_data
(
self
,
**
kwargs
):
context
=
super
().
get_context_data
(
**
kwargs
)
activity
=
context
[
"
form
"
].
activity
context
[
"
title
"
]
=
_
(
'
Invite guest to the activity
"
{}
"'
).
format
(
activity
.
name
)
return
context
def
get_form
(
self
,
form_class
=
None
):
form
=
super
().
get_form
(
form_class
)
form
.
activity
=
Activity
.
objects
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Activity
,
"
view
"
))
\
.
get
(
pk
=
self
.
kwargs
[
"
pk
"
])
form
.
fields
[
"
inviter
"
].
initial
=
self
.
request
.
user
.
note
return
form
def
form_valid
(
self
,
form
):
form
.
instance
.
activity
=
Activity
.
objects
\
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Activity
,
"
view
"
)).
get
(
pk
=
self
.
kwargs
[
"
pk
"
])
return
super
().
form_valid
(
form
)
def
get_success_url
(
self
,
**
kwargs
):
return
reverse_lazy
(
'
activity:activity_detail
'
,
kwargs
=
{
"
pk
"
:
self
.
kwargs
[
"
pk
"
]})
class
ActivityEntryView
(
LoginRequiredMixin
,
TemplateView
):
"""
Manages entry to an activity
"""
template_name
=
"
activity/activity_entry.html
"
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
"""
Don
'
t display the entry interface if the user has no right to see it (no right to add an entry for itself),
it is closed or doesn
'
t manage entries.
"""
activity
=
Activity
.
objects
.
get
(
pk
=
self
.
kwargs
[
"
pk
"
])
sample_entry
=
Entry
(
activity
=
activity
,
note
=
self
.
request
.
user
.
note
)
if
not
PermissionBackend
.
check_perm
(
self
.
request
.
user
,
"
activity.add_entry
"
,
sample_entry
):
raise
PermissionDenied
(
_
(
"
You are not allowed to display the entry interface for this activity.
"
))
if
not
activity
.
activity_type
.
manage_entries
:
raise
PermissionDenied
(
_
(
"
This activity does not support activity entries.
"
))
if
not
activity
.
open
:
raise
PermissionDenied
(
_
(
"
This activity is closed.
"
))
return
super
().
dispatch
(
request
,
*
args
,
**
kwargs
)
def
get_invited_guest
(
self
,
activity
):
"""
Retrieves all Guests to the activity
"""
guest_qs
=
Guest
.
objects
\
.
annotate
(
balance
=
F
(
"
inviter__balance
"
),
note_name
=
F
(
"
inviter__user__username
"
))
\
.
filter
(
activity
=
activity
)
\
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Guest
,
"
view
"
))
\
.
order_by
(
'
last_name
'
,
'
first_name
'
).
distinct
()
if
"
search
"
in
self
.
request
.
GET
and
self
.
request
.
GET
[
"
search
"
]:
pattern
=
self
.
request
.
GET
[
"
search
"
]
if
pattern
[
0
]
!=
"
^
"
:
pattern
=
"
^
"
+
pattern
guest_qs
=
guest_qs
.
filter
(
Q
(
first_name__regex
=
pattern
)
|
Q
(
last_name__regex
=
pattern
)
|
Q
(
inviter__alias__name__regex
=
pattern
)
|
Q
(
inviter__alias__normalized_name__regex
=
Alias
.
normalize
(
pattern
))
)
else
:
guest_qs
=
guest_qs
.
none
()
return
guest_qs
def
get_invited_note
(
self
,
activity
):
"""
Retrieves all Note that can attend the activity,
they need to have an up-to-date membership in the attendees_club.
"""
note_qs
=
Alias
.
objects
.
annotate
(
last_name
=
F
(
"
note__noteuser__user__last_name
"
),
first_name
=
F
(
"
note__noteuser__user__first_name
"
),
username
=
F
(
"
note__noteuser__user__username
"
),
note_name
=
F
(
"
name
"
),
balance
=
F
(
"
note__balance
"
))
# Keep only users that have a note
note_qs
=
note_qs
.
filter
(
note__noteuser__isnull
=
False
)
# Keep only members
note_qs
=
note_qs
.
filter
(
note__noteuser__user__memberships__club
=
activity
.
attendees_club
,
note__noteuser__user__memberships__date_start__lte
=
timezone
.
now
(),
note__noteuser__user__memberships__date_end__gte
=
timezone
.
now
(),
)
# Filter with permission backend
note_qs
=
note_qs
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Alias
,
"
view
"
))
if
"
search
"
in
self
.
request
.
GET
and
self
.
request
.
GET
[
"
search
"
]:
pattern
=
self
.
request
.
GET
[
"
search
"
]
note_qs
=
note_qs
.
filter
(
Q
(
note__noteuser__user__first_name__regex
=
pattern
)
|
Q
(
note__noteuser__user__last_name__regex
=
pattern
)
|
Q
(
name__regex
=
pattern
)
|
Q
(
normalized_name__regex
=
Alias
.
normalize
(
pattern
))
)
else
:
note_qs
=
note_qs
.
none
()
if
settings
.
DATABASES
[
note_qs
.
db
][
"
ENGINE
"
]
==
'
django.db.backends.postgresql
'
:
note_qs
=
note_qs
.
distinct
(
'
note__pk
'
)[:
20
]
else
:
# SQLite doesn't support distinct fields. For compatibility reason (in dev mode), the note list will only
# have distinct aliases rather than distinct notes with a SQLite DB, but it can fill the result page.
# In production mode, please use PostgreSQL.
note_qs
=
note_qs
.
distinct
()[:
20
]
return
note_qs
def
get_context_data
(
self
,
**
kwargs
):
"""
Query the list of Guest and Note to the activity and add information to makes entry with JS.
"""
context
=
super
().
get_context_data
(
**
kwargs
)
activity
=
Activity
.
objects
.
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Activity
,
"
view
"
))
\
.
distinct
().
get
(
pk
=
self
.
kwargs
[
"
pk
"
])
context
[
"
activity
"
]
=
activity
matched
=
[]
for
guest
in
self
.
get_invited_guest
(
activity
):
guest
.
type
=
"
Invité
"
matched
.
append
(
guest
)
for
note
in
self
.
get_invited_note
(
activity
):
note
.
type
=
"
Adhérent
"
note
.
activity
=
activity
matched
.
append
(
note
)
table
=
EntryTable
(
data
=
matched
)
context
[
"
table
"
]
=
table
context
[
"
entries
"
]
=
Entry
.
objects
.
filter
(
activity
=
activity
)
context
[
"
title
"
]
=
_
(
'
Entry for activity
"
{}
"'
).
format
(
activity
.
name
)
context
[
"
noteuser_ctype
"
]
=
ContentType
.
objects
.
get_for_model
(
NoteUser
).
pk
context
[
"
notespecial_ctype
"
]
=
ContentType
.
objects
.
get_for_model
(
NoteSpecial
).
pk
activities_open
=
Activity
.
objects
.
filter
(
open
=
True
).
filter
(
PermissionBackend
.
filter_queryset
(
self
.
request
.
user
,
Activity
,
"
view
"
)).
distinct
().
all
()
context
[
"
activities_open
"
]
=
[
a
for
a
in
activities_open
if
PermissionBackend
.
check_perm
(
self
.
request
.
user
,
"
activity.add_entry
"
,
Entry
(
activity
=
a
,
note
=
self
.
request
.
user
.
note
,))]
return
context
class
CalendarView
(
View
):
"""
Render an ICS calendar with all valid activities.
"""
def
multilines
(
self
,
string
,
maxlength
,
offset
=
0
):
newstring
=
string
[:
maxlength
-
offset
]
string
=
string
[
maxlength
-
offset
:]
while
string
:
newstring
+=
"
\r\n
"
newstring
+=
string
[:
maxlength
-
1
]
string
=
string
[
maxlength
-
1
:]
return
newstring
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
ics
=
"""
BEGIN:VCALENDAR
VERSION: 2.0
PRODID:Note Kfet 2020
X-WR-CALNAME:Kfet Calendar
NAME:Kfet Calendar
CALSCALE:GREGORIAN
BEGIN:VTIMEZONE
TZID:Europe/Berlin
TZURL:http://tzurl.org/zoneinfo-outlook/Europe/Berlin
X-LIC-LOCATION:Europe/Berlin
BEGIN:DAYLIGHT
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
TZNAME:CEST
DTSTART:19700329T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
TZNAME:CET
DTSTART:19701025T030000
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
END:STANDARD
END:VTIMEZONE
"""
for
activity
in
Activity
.
objects
.
filter
(
valid
=
True
).
order_by
(
"
-date_start
"
).
all
():
ics
+=
f
"""
BEGIN:VEVENT
DTSTAMP:
{
"
{:
%
Y
%
m
%
dT
%
H
%
M
%
S
}
"
.format(activity.date_start)
}
Z
UID:
{
activity
.
id
}
SUMMARY;CHARSET=UTF-8:
{
self
.
multilines
(
activity
.
name
,
75
,
22
)
}
DTSTART;TZID=Europe/Berlin:
{
"
{:
%
Y
%
m
%
dT
%
H
%
M
%
S
}
"
.format(activity.date_start)
}
DTEND;TZID=Europe/Berlin:
{
"
{:
%
Y
%
m
%
dT
%
H
%
M
%
S
}
"
.format(activity.date_end)
}
LOCATION:
{
self
.
multilines
(
activity
.
location
,
75
,
9
)
if
activity
.
location
else
"
Kfet
"
}
DESCRIPTION;CHARSET=UTF-8:
{
self
.
multilines
(
activity
.
description
,
75
,
26
)
}
--
{
activity
.
organizer
.
name
}
END:VEVENT
"""
ics
+=
"
END:VCALENDAR
"
ics
=
ics
.
replace
(
"
\r
"
,
""
).
replace
(
"
\n
"
,
"
\r\n
"
)
return
HttpResponse
(
ics
,
content_type
=
"
text/calendar; charset=UTF-8
"
)
This diff is collapsed.
Click to expand it.
apps/logs/signals.py
+
1
−
4
View file @
70e1a611
...
...
@@ -117,10 +117,7 @@ def delete_object(sender, instance, **kwargs):
Each time a model is deleted, an entry in the table `Changelog` is added in the database
"""
# noinspection PyProtectedMember
if
instance
.
_meta
.
label_lower
in
EXCLUDED
:
return
if
hasattr
(
instance
,
"
_no_log
"
):
if
instance
.
_meta
.
label_lower
in
EXCLUDED
or
hasattr
(
instance
,
"
_no_log
"
):
return
# Si un utilisateur est connecté, on récupère l'utilisateur courant ainsi que son adresse IP
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment