mirror of
https://github.com/jlengrand/bugsink.git
synced 2026-03-10 08:01:17 +00:00
Hide in-progress deletions of Project & Issue from the UI
I've done a full grep on Issue.objects, Project.objects and get_object_or_404
equivelents, and applying some common sense. The goal: avoid having
confusing/half-broken pages in the UI.
On index-usage: I've decided not to update the indexes. The assumption is:
`is_deleted` items will be a tiny minority of items in general, making the
cost/benefit analysis not turn out favorably (just scanning them out as a final
step is more efficient). Also: sqlite is able to use the correct index without
adding a special one, proof:
```
EXPLAIN QUERY PLAN SELECT [..] WHERE ("issues_issue"."project_id" = 1 AND "issues_issue"."is_muted" = (0) AND "issues_issue"."is_resolved" = (0)) ORDER BY "issues_issue"."last_seen" DESC LIMIT 250;
QUERY PLAN
`--SEARCH issues_issue USING INDEX issue_list_open (project_id=? AND is_resolved=? AND is_muted=?)
EXPLAIN QUERY PLAN SELECT [..] WHERE ("issues_issue"."project_id" = 1 AND "issues_issue"."is_muted" = (0) AND "issues_issue"."is_resolved" = (0) AND "issues_issue"."is_deleted" = 0) ORDER BY "issues_issue"."last_seen" DESC LIMIT 250;
QUERY PLAN
`--SEARCH issues_issue USING INDEX issue_list_open (project_id=? AND is_resolved=? AND is_muted=?)
```
See #139 for the 0/1 notation in the above.
(Project-indexes: not an issue, the scale is "below relevance for indexes")
This commit is contained in:
@@ -35,21 +35,24 @@ def project_list(request, ownership_filter=None):
|
||||
my_memberships = ProjectMembership.objects.filter(user=request.user)
|
||||
my_team_memberships = TeamMembership.objects.filter(user=request.user)
|
||||
|
||||
my_projects = Project.objects.filter(projectmembership__in=my_memberships).order_by('name').distinct()
|
||||
my_projects = Project.objects.filter(
|
||||
projectmembership__in=my_memberships, is_deleted=False).order_by('name').distinct()
|
||||
my_teams_projects = \
|
||||
Project.objects \
|
||||
.filter(team__teammembership__in=my_team_memberships) \
|
||||
.filter(team__teammembership__in=my_team_memberships, is_deleted=False) \
|
||||
.exclude(projectmembership__in=my_memberships) \
|
||||
.order_by('name').distinct()
|
||||
|
||||
if request.user.is_superuser:
|
||||
# superusers can see all project, even hidden ones
|
||||
other_projects = Project.objects \
|
||||
.filter(is_deleted=False) \
|
||||
.exclude(projectmembership__in=my_memberships) \
|
||||
.exclude(team__teammembership__in=my_team_memberships) \
|
||||
.order_by('name').distinct()
|
||||
else:
|
||||
other_projects = Project.objects \
|
||||
.filter(is_deleted=False) \
|
||||
.exclude(projectmembership__in=my_memberships) \
|
||||
.exclude(team__teammembership__in=my_team_memberships) \
|
||||
.exclude(visibility=ProjectVisibility.TEAM_MEMBERS) \
|
||||
@@ -158,7 +161,7 @@ def _check_project_admin(project, user):
|
||||
|
||||
@atomic_for_request_method
|
||||
def project_edit(request, project_pk):
|
||||
project = Project.objects.get(id=project_pk)
|
||||
project = Project.objects.get(id=project_pk, is_deleted=False)
|
||||
|
||||
_check_project_admin(project, request.user)
|
||||
|
||||
@@ -195,7 +198,7 @@ def project_edit(request, project_pk):
|
||||
|
||||
@atomic_for_request_method
|
||||
def project_members(request, project_pk):
|
||||
project = Project.objects.get(id=project_pk)
|
||||
project = Project.objects.get(id=project_pk, is_deleted=False)
|
||||
_check_project_admin(project, request.user)
|
||||
|
||||
if request.method == 'POST':
|
||||
@@ -230,7 +233,7 @@ def project_members_invite(request, project_pk):
|
||||
# NOTE: project-member invite is just that: a direct invite to a project. If you want to also/instead invite someone
|
||||
# to a team, you need to just do that instead.
|
||||
|
||||
project = Project.objects.get(id=project_pk)
|
||||
project = Project.objects.get(id=project_pk, is_deleted=False)
|
||||
|
||||
_check_project_admin(project, request.user)
|
||||
|
||||
@@ -292,7 +295,7 @@ def project_member_settings(request, project_pk, user_pk):
|
||||
|
||||
this_is_you = str(user_pk) == str(request.user.id)
|
||||
if not this_is_you:
|
||||
_check_project_admin(Project.objects.get(id=project_pk), request.user)
|
||||
_check_project_admin(Project.objects.get(id=project_pk, is_deleted=False), request.user)
|
||||
|
||||
membership = ProjectMembership.objects.get(project=project_pk, user=user_pk)
|
||||
create_form = lambda data: ProjectMembershipForm(data, instance=membership) # noqa
|
||||
@@ -317,7 +320,7 @@ def project_member_settings(request, project_pk, user_pk):
|
||||
return render(request, 'projects/project_member_settings.html', {
|
||||
'this_is_you': this_is_you,
|
||||
'user': User.objects.get(id=user_pk),
|
||||
'project': Project.objects.get(id=project_pk),
|
||||
'project': Project.objects.get(id=project_pk, is_deleted=False),
|
||||
'form': form,
|
||||
})
|
||||
|
||||
@@ -377,7 +380,7 @@ def project_members_accept(request, project_pk):
|
||||
# invited as user B. Security-wise this is fine, but UX-wise it could be confusing. However, I'm in the assumption
|
||||
# here that normal people (i.e. not me) don't have multiple accounts, so I'm not going to bother with this.
|
||||
|
||||
project = Project.objects.get(id=project_pk)
|
||||
project = Project.objects.get(id=project_pk, is_deleted=False)
|
||||
membership = ProjectMembership.objects.get(project=project, user=request.user)
|
||||
|
||||
if membership.accepted:
|
||||
@@ -402,7 +405,7 @@ def project_members_accept(request, project_pk):
|
||||
|
||||
@atomic_for_request_method
|
||||
def project_sdk_setup(request, project_pk, platform=""):
|
||||
project = Project.objects.get(id=project_pk)
|
||||
project = Project.objects.get(id=project_pk, is_deleted=False)
|
||||
|
||||
if not request.user.is_superuser and not ProjectMembership.objects.filter(project=project, user=request.user,
|
||||
accepted=True).exists():
|
||||
@@ -423,7 +426,7 @@ def project_sdk_setup(request, project_pk, platform=""):
|
||||
|
||||
@atomic_for_request_method
|
||||
def project_alerts_setup(request, project_pk):
|
||||
project = Project.objects.get(id=project_pk)
|
||||
project = Project.objects.get(id=project_pk, is_deleted=False)
|
||||
_check_project_admin(project, request.user)
|
||||
|
||||
if request.method == 'POST':
|
||||
@@ -446,7 +449,7 @@ def project_alerts_setup(request, project_pk):
|
||||
|
||||
@atomic_for_request_method
|
||||
def project_messaging_service_add(request, project_pk):
|
||||
project = Project.objects.get(id=project_pk)
|
||||
project = Project.objects.get(id=project_pk, is_deleted=False)
|
||||
_check_project_admin(project, request.user)
|
||||
|
||||
if request.method == 'POST':
|
||||
@@ -474,7 +477,7 @@ def project_messaging_service_add(request, project_pk):
|
||||
|
||||
@atomic_for_request_method
|
||||
def project_messaging_service_edit(request, project_pk, service_pk):
|
||||
project = Project.objects.get(id=project_pk)
|
||||
project = Project.objects.get(id=project_pk, is_deleted=False)
|
||||
_check_project_admin(project, request.user)
|
||||
|
||||
instance = project.service_configs.get(id=service_pk)
|
||||
|
||||
Reference in New Issue
Block a user