-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
signal handlers for syncing of project views and tasks #1218
Conversation
d708437
to
9065876
Compare
rdmo/projects/handlers/utils.py
Outdated
@@ -0,0 +1,10 @@ | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think those methods should exist, this should be inline in the handlers (and without the getattr
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could make it more explicit but it would require a lot more boilerplate code.
The signal handlers for View
and Task
are basically duplicates, so there would be 18 branches instead of the 9 if action == ...
in total in the different functions for .catalogs
, .sites
and .groups
.
But we already agreed about this in the meeting right?
Or would there be an extra use case that would require an update on the Issues as well, when project.tasks are handled?
Example for an explicit function
# Identify the catalogs affected by this change
catalogs = model.objects.filter(pk__in=pk_set)
# Determine the projects to be modified
if action == 'post_add':
projects = Project.objects.filter_catalogs(catalogs).exclude(views=instance)
for project in projects:
project.views.add(instance)
elif action == 'post_remove':
projects = Project.objects.filter_catalogs(catalogs).filter(views=instance)
for project in projects:
project.views.remove(instance)
elif action == 'post_clear':
projects = Project.objects.filter(views=instance)
for project in projects:
project.views.remove(instance)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No I mean just remove_instance_from_projects
and add_instance_to_projects
should be inlined to the generic handlers.
rdmo/tasks/managers.py
Outdated
@@ -15,6 +15,16 @@ class TaskQuestionSet(CurrentSiteQuerySetMixin, GroupsQuerySetMixin, Availabilit | |||
def filter_catalog(self, catalog): | |||
return self.filter(models.Q(catalogs=None) | models.Q(catalogs=catalog)) | |||
|
|||
def filter_available_views_for_project(self, project): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that a Project
should be able to find the views
that are available for itself. Do you agree and would this query be correct for that?
I've changed the filter_group
a little bit to handle a list of users
as well as a single user
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to check after the meeting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this kind of method is also needed for an endpoint (for project.views) in the new Project Detail in React I think
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed in the meeting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change filter to filter_for_project_site
and filter_project_owners_groups
and add project.groups: set()
if 'cancel' in self.data: | ||
return self.instance | ||
|
||
# if the catalog is the same, do nothing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to prevent calling the save
method if nothing was changed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure, but shouldn't this be handled by the UpdateView
... maybe because we use only parts of the model here.
return | ||
|
||
# Defer synchronization of views | ||
setattr(instance, DEFERRED_SYNC_TASKS_KEY, True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I needed a pre_save
to check if the catalog
was changed or not. And afterwards it passes this boolean (with a "deferred" attribute name) to the post_save
.
It seems complicated for just a project.save()
but could not find another way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove setattr and just use, eg. instance._catalog_has_changed_sync_task
for catalog in view.catalogs.all(): | ||
catalog_views_mapping[catalog.id].append({ | ||
'id': view.id, | ||
'sites': list(view.sites.values_list('id', flat=True)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to explicitly test this filter filter_available_views_for_project
with this mapping but have not implemented that test yet.
55905ba
to
e19be64
Compare
rdmo/core/managers.py
Outdated
def filter_group(self, user): | ||
groups = user.groups.all() | ||
def filter_group(self, users): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove newline.
if 'cancel' in self.data: | ||
return self.instance | ||
|
||
# if the catalog is the same, do nothing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure, but shouldn't this be handled by the UpdateView
... maybe because we use only parts of the model here.
rdmo/projects/forms.py
Outdated
@@ -180,6 +190,22 @@ class Meta: | |||
'tasks': forms.CheckboxSelectMultiple() | |||
} | |||
|
|||
def save(self, commit=True, *args, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this is just about not saving the instance when nothing changed, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, but it might be just an optional optimization, think I'll remove it again for now.
rdmo/projects/handlers/utils.py
Outdated
@@ -0,0 +1,10 @@ | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No I mean just remove_instance_from_projects
and add_instance_to_projects
should be inlined to the generic handlers.
@@ -21,7 +21,7 @@ <h2>{% trans 'Tasks' %}</h2> | |||
<th style="width: 15%">{% trans 'Time frame' %}</th> | |||
<th style="width: 15%">{% trans 'Status' %}</th> | |||
<th style="width: 10%" class="text-right"> | |||
{% if can_change_project %} | |||
{% if can_change_project and not settings.PROJECT_TASKS_SYNC %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But only for tasks it seems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, its for both, but there is another error: A view/task without catalog should be available to all projects. Also the update-task/view-for-project forms should be disabled when the setting is True
. Check /projects/1/update/views/
and /projects/1/update/tasks/
. Maybe 404?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, I am adding now a filter to the managers that is used for all cases where a project needs its available views/tasks.
There is no request.user in the loop anymore. Is that a problem? The filter is determined by the project's properties (like project.site
, .catalogs
and the new .groups
)
def filter_available_views_for_project(self, project):
site_filter = Q(sites=project.site) | Q(sites__isnull=True)
catalogs_filter = Q(catalogs=project.catalog) | Q(catalogs__isnull=True)
groups_filter = Q(groups__in=project.groups) | Q(groups__isnull=True)
availability_filter = Q(available=True)
return self.filter(site_filter & catalogs_filter & groups_filter & availability_filter)
rdmo/tasks/managers.py
Outdated
@@ -15,6 +15,16 @@ class TaskQuestionSet(CurrentSiteQuerySetMixin, GroupsQuerySetMixin, Availabilit | |||
def filter_catalog(self, catalog): | |||
return self.filter(models.Q(catalogs=None) | models.Q(catalogs=catalog)) | |||
|
|||
def filter_available_views_for_project(self, project): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to check after the meeting.
rdmo/core/settings.py
Outdated
@@ -332,7 +334,8 @@ | |||
|
|||
PROJECT_SEND_INVITE = True | |||
|
|||
PROJECT_REMOVE_VIEWS = True | |||
PROJECT_VIEWS_SYNC = True | |||
PROJECT_TASKS_SYNC = True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should these actually be enabled by default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think not.
Signed-off-by: David Wallace <[email protected]>
# Conflicts: # rdmo/projects/handlers.py
…hange in catalog Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
…bled Signed-off-by: David Wallace <[email protected]> # Conflicts: # rdmo/core/settings.py
… handlers Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
…ps to Project Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
4860e95
to
50f25dd
Compare
rebased to 2.3.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main issue is about the new managers and availability. An reviewer/editor/admin should be able to assign a non available Task/View to a project to test it.
rdmo/core/settings.py
Outdated
@@ -332,7 +334,8 @@ | |||
|
|||
PROJECT_SEND_INVITE = True | |||
|
|||
PROJECT_REMOVE_VIEWS = True | |||
PROJECT_VIEWS_SYNC = True | |||
PROJECT_TASKS_SYNC = True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think not.
rdmo/views/managers.py
Outdated
catalogs_filter = Q(catalogs=project.catalog) | Q(catalogs__isnull=True) | ||
groups_filter = Q(groups__in=project.groups) | Q(groups__isnull=True) | ||
availability_filter = Q(available=True) | ||
return self.filter(site_filter & catalogs_filter & groups_filter & availability_filter) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am sorry but there is a newline in rdmo.tasks.managers
right here 🙃
testing/config/settings/base.py
Outdated
@@ -69,7 +69,8 @@ | |||
|
|||
PROJECT_SEND_INVITE = True | |||
|
|||
PROJECT_REMOVE_VIEWS = True | |||
PROJECT_VIEWS_SYNC = True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depending on the default settings and the tests, maybe this should be False (or removed from this file).
rdmo/tasks/managers.py
Outdated
site_filter = Q(sites=project.site) | Q(sites__isnull=True) | ||
catalogs_filter = Q(catalogs=project.catalog) | Q(catalogs__isnull=True) | ||
groups_filter = Q(groups__in=project.groups) | Q(groups__isnull=True) | ||
availability_filter = Q(available=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you removed the check for the managers and admins here, this was done by .filter_availability(self.request.user)
and needs the user. This comes from AvailabilityQuerySetMixin
. I think you also reimplemented the other thinks in core/managers.py
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the availability part should stay in AvailabilityQuerySetMixin
and we need only filter_for_project
and use it like this
tasks = Task.objects.filter_for_project(project).filter_availability(self.request.user)
alternatively 3 methods
tasks = Task.objects.filter_for_project_site(project) \
.filter_for_project_catalog(project) \
.filter_for_project_group(project) \
.filter_availability(self.request.user)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, Ive added it now like this in the code where it is already several times indented.
What do you think about this type of notation? ;)
tasks = (
Task.objects
.filter_for_project(project)
.filter_availability(self.request.user)
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like "my" style better, but I think this is fine (at least no \
). I would indent the two '.filter...' lines by 4.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've used one-liner queries when there is only a single filter and it fits on one line, for multiple filters I've used this multi-line parentheses notation with the extra indent. So basically best of both worlds ;)
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
Signed-off-by: David Wallace <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks!
Description
For the settings this PR removes:
PROJECT_REMOVE_VIEWS = True
and adds:
The
projects/handlers.py
are refactored into aproject/handlers
package with aproject/handlers/generic_handlers.py
module that contains the logic for signal receivers.It handles the signals for changes in
View.catalogs
,View.sites
,View.groups
as well asTask.catalogs
,Task.sites
,Task.groups
and updates theproject.views
orprojects.tasks
.Tests, that only use db
view.catalog.add(...)
methods and not the client, are included.Related issues: #966, #1198, #345,
Related PRs: #431, #1200
Motivation and Context
ToBeDone:
How has this been tested?
Screenshots (if appropriate)