-
Notifications
You must be signed in to change notification settings - Fork 49
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
base: 2.3.0
Are you sure you want to change the base?
Conversation
15fd305
to
d708437
Compare
Signed-off-by: David Wallace <[email protected]>
d708437
to
9065876
Compare
@@ -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.
# Conflicts: # rdmo/projects/handlers.py
…ange Fix: remove views from projects if catalog is changed
…hange in catalog Signed-off-by: David Wallace <[email protected]>
@@ -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.
@@ -160,6 +160,16 @@ class Meta: | |||
'catalog': forms.RadioSelect() | |||
} | |||
|
|||
def save(self, commit=True, *args, **kwargs): | |||
if 'cancel' in self.data: |
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 was just still missing 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.
Did "Cancel" save the new instance? The update view was probably just a fuction at one point and cancel was handled there.
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.
need to check again, if this was needed or not (cancel seems to work already)
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.
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]>
55905ba
to
e19be64
Compare
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.
@@ -10,5 +10,7 @@ class ProjectsConfig(AppConfig): | |||
def ready(self): | |||
from . import rules # noqa: F401 | |||
|
|||
if settings.PROJECT_REMOVE_VIEWS: | |||
from . import handlers # noqa: F401 | |||
if settings.PROJECT_VIEWS_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.
I don't think this is correct. from . import handlers
just tells django to "load" the file initially. We do nothing with the imported functions. m2m_changed_views
and project_save_views
do not even exist, maybe this is a leftover that somehow does not cause an error?
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.
It should also be settings.PROJECT_REMOVE_VIEWS or settings.PROJECT_VIEWS_SYNC
since we just want to load the file.
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.
Ah now I get it, you created a handlers
module. Then handlers.py
should be deleted and its content should move to handlers/__init__.py
(or a file in the directory).
@@ -160,6 +160,16 @@ class Meta: | |||
'catalog': forms.RadioSelect() | |||
} | |||
|
|||
def save(self, commit=True, *args, **kwargs): | |||
if 'cancel' in self.data: |
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.
Did "Cancel" save the new instance? The update view was probably just a fuction at one point and cancel was handled there.
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.
@@ -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?
|
||
# Defer synchronization of views | ||
setattr(instance, DEFERRED_SYNC_VIEWS_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.
Add newline.
@@ -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?
.exclude(catalogs=None) | ||
) | ||
|
||
|
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.
@@ -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.
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, #431
Related PRs: #1200
Motivation and Context
ToBeDone:
How has this been tested?
Screenshots (if appropriate)