Add automatic tag collections
This commit is contained in:
+38
-13
@@ -536,7 +536,7 @@ def team_accept_invite(request, token):
|
||||
|
||||
|
||||
def visible_collections(user):
|
||||
qs = Collection.objects.select_related('owner', 'team').prefetch_related('tags', 'sections__item')
|
||||
qs = Collection.objects.select_related('owner', 'team').prefetch_related('filter_tags', 'sections__item')
|
||||
if user.is_authenticated:
|
||||
return qs.filter(Q(owner=user) | Q(team_id__in=user_team_ids(user)) | Q(visibility=Item.Visibility.PUBLIC)).distinct()
|
||||
return qs.filter(visibility=Item.Visibility.PUBLIC)
|
||||
@@ -569,14 +569,25 @@ def collection_item_is_compatible(collection, item):
|
||||
|
||||
|
||||
def collection_target_from_form(form, user):
|
||||
tags = form.cleaned_data.get('tags')
|
||||
tag_names = list(tags.values_list('name', flat=True)) if tags is not None else []
|
||||
membership = TeamMembership.objects.select_related('team').filter(user=user, team__slug__in=tag_names).first()
|
||||
if membership:
|
||||
return Item.Visibility.TEAM, membership.team
|
||||
team = form.cleaned_data.get('team')
|
||||
if team:
|
||||
return Item.Visibility.TEAM, team
|
||||
return form.cleaned_data['visibility'], None
|
||||
|
||||
|
||||
def collection_tag_items(collection):
|
||||
items = Item.objects.filter(kind=Item.Kind.NOTE).select_related('owner', 'team').prefetch_related('tags', 'attachments')
|
||||
if collection.visibility == Item.Visibility.PUBLIC:
|
||||
items = items.filter(visibility=Item.Visibility.PUBLIC)
|
||||
elif collection.visibility == Item.Visibility.TEAM:
|
||||
items = items.filter(Q(visibility=Item.Visibility.PUBLIC) | Q(visibility=Item.Visibility.TEAM, team=collection.team))
|
||||
else:
|
||||
items = items.filter(Q(visibility=Item.Visibility.PUBLIC) | Q(visibility=Item.Visibility.PRIVATE, owner=collection.owner))
|
||||
for tag in collection.filter_tags.all():
|
||||
items = items.filter(tags=tag)
|
||||
return items.distinct().order_by('created_at', 'id')
|
||||
|
||||
|
||||
def item_can_change_for_collection(user, item, collection):
|
||||
if not user_can_edit_item(user, item):
|
||||
return False
|
||||
@@ -659,8 +670,11 @@ def collection_detail_context(request, collection, pending_item=None):
|
||||
|
||||
@login_required
|
||||
def collection_list(request):
|
||||
collections = visible_collections(request.user)
|
||||
return render(request, 'core/collection_list.html', {'collections': collections})
|
||||
entries = []
|
||||
for collection in visible_collections(request.user).prefetch_related('filter_tags'):
|
||||
count = collection_tag_items(collection).count() if collection.mode == Collection.Mode.TAGS else collection.sections.count()
|
||||
entries.append({'collection': collection, 'section_count': count})
|
||||
return render(request, 'core/collection_list.html', {'entries': entries})
|
||||
|
||||
|
||||
@login_required
|
||||
@@ -670,7 +684,7 @@ def collection_create(request):
|
||||
if form.is_valid():
|
||||
visibility, team = collection_target_from_form(form, request.user)
|
||||
if visibility == Item.Visibility.TEAM and not team:
|
||||
form.add_error('visibility', _('Select a team tag for a team collection.'))
|
||||
form.add_error('team', _('Select a team for a team collection.'))
|
||||
else:
|
||||
collection = form.save(commit=False)
|
||||
collection.owner = request.user
|
||||
@@ -678,6 +692,8 @@ def collection_create(request):
|
||||
collection.team = team
|
||||
collection.save()
|
||||
form.save_m2m()
|
||||
if collection.mode == Collection.Mode.MANUAL:
|
||||
collection.filter_tags.clear()
|
||||
messages.success(request, _('Collection created.'))
|
||||
return redirect(collection)
|
||||
else:
|
||||
@@ -694,20 +710,26 @@ def collection_edit(request, pk):
|
||||
form = CollectionForm(request.POST, instance=collection, user=request.user)
|
||||
if form.is_valid():
|
||||
visibility, team = collection_target_from_form(form, request.user)
|
||||
incompatible = any(not collection_scope_allows_item(
|
||||
target_mode = form.cleaned_data['mode']
|
||||
has_manual_sections = collection.mode == Collection.Mode.MANUAL and collection.sections.exists()
|
||||
incompatible = target_mode == Collection.Mode.MANUAL and any(not collection_scope_allows_item(
|
||||
visibility, team.id if team else None, collection.owner_id,
|
||||
section.item.visibility, section.item.team_id, section.item.owner_id,
|
||||
) for section in collection.sections.select_related('item'))
|
||||
if incompatible:
|
||||
if target_mode == Collection.Mode.TAGS and has_manual_sections:
|
||||
form.add_error('mode', _('Remove all manual sections before changing to a tag collection.'))
|
||||
elif incompatible:
|
||||
form.add_error(None, _('The collection visibility cannot change while it contains incompatible notes.'))
|
||||
elif visibility == Item.Visibility.TEAM and not team:
|
||||
form.add_error('visibility', _('Select a team tag for a team collection.'))
|
||||
form.add_error('team', _('Select a team for a team collection.'))
|
||||
else:
|
||||
collection = form.save(commit=False)
|
||||
collection.visibility = visibility
|
||||
collection.team = team
|
||||
collection.save()
|
||||
form.save_m2m()
|
||||
if collection.mode == Collection.Mode.MANUAL:
|
||||
collection.filter_tags.clear()
|
||||
messages.success(request, _('Collection saved.'))
|
||||
return redirect(collection)
|
||||
else:
|
||||
@@ -719,7 +741,8 @@ def collection_detail(request, pk):
|
||||
collection = get_object_or_404(visible_collections(request.user), pk=pk)
|
||||
return render(request, 'core/collection_detail.html', {
|
||||
'collection': collection,
|
||||
'sections': collection.sections.select_related('item').prefetch_related('item__tags', 'item__attachments'),
|
||||
'sections': collection.sections.select_related('item').prefetch_related('item__tags', 'item__attachments') if collection.mode == Collection.Mode.MANUAL else [],
|
||||
'tag_items': collection_tag_items(collection) if collection.mode == Collection.Mode.TAGS else [],
|
||||
'can_edit': user_can_edit_collection(request.user, collection),
|
||||
})
|
||||
|
||||
@@ -729,6 +752,8 @@ def collection_manage(request, pk):
|
||||
collection = get_object_or_404(visible_collections(request.user), pk=pk)
|
||||
if not user_can_edit_collection(request.user, collection):
|
||||
return JsonResponse({'error': 'forbidden'}, status=403)
|
||||
if collection.mode == Collection.Mode.TAGS:
|
||||
return redirect('collection_edit', pk=collection.pk)
|
||||
manage_url = reverse('collection_manage', args=[collection.pk])
|
||||
if request.method == 'POST':
|
||||
action = request.POST.get('action')
|
||||
|
||||
Reference in New Issue
Block a user