Example #1
0
def tag_list(context, owner, plus_exclude=None):
    # TODO: memcache this

    if plus_exclude is not None:
        add = u','.join(plus_exclude)
        plus_exclude_lower = [x.lower() for x in plus_exclude]
    else:
        add = u''
        plus_exclude_lower = []

    no_plus = u'<a href="/search/?q=%(fulltag)s"%(class)s data-votes="%(votes)s">%(tag)s</a>'
    plus = no_plus + u'<a href="/search/?q=' + add + ',%(tag)s"%(class)s>+</a>'

    user = context['user']
    show_hidden_option = user.is_authenticated() \
            and user.get_profile().show_hidden_tags
    show_hidden = show_hidden_option == UserProfile.HIDDEN_TAGS_SHOW_ALWAYS

    content_type = ContentType.objects.get_for_model(owner)
    if content_type.app_label == 'task' and content_type.model == 'task':
        if show_hidden_option == UserProfile.HIDDEN_TAGS_SHOW_IF_SOLVED:
            # TODO: do not rely on cache_solution
            solution = getattr(owner, 'cache_solution', None)
            show_hidden = solution and solution.is_solved()

    v0 = []     # not hidden
    v1 = []     # hidden
    for tagged_item in get_object_tagged_items(owner):
        name = tagged_item.tag.name
        votes = tagged_item.votes_sum
        attr = {'votes': votes, 'class': '', 'fulltag': name}
        if name[0] != '$':
            attr['tag'] = name
        elif show_hidden:
            attr['tag'] = name[1:]
            attr['class'] = 'tag-hidden'
        else:
            continue

        if votes <= VOTE_WRONG:
            attr['class'] += ' tag-wrong'
        if attr['class']:
            attr['class'] = ' class="{}"'.format(attr['class'].strip())

        if not plus_exclude or name.lower() in plus_exclude_lower:
            fmt = no_plus
        else:
            fmt = plus
        (v0 if name[0] != '$' else v1).append(fmt % attr)

    # Update apps/tags/static/tags.coffee and .scss if changing this!
    return mark_safe(
            u'<div class="tag-list tag-list-tooltip" data-content-type-id="{}" '
            u'data-object-id="{}">{}</div>'.format(
                content_type.id, owner.id, u" ".join(v0 + v1)))
Example #2
0
def get_task_folder_ids(task):
    """
    Returns the list of IDs of all folders containing given task.
    Combines result of many-to-many relation and folder-filters.

    Does not check permissions, and not supposed to do any checks.

    Note that even search results are copied into FolderTask for
    folder-filters, there may still be some of those Folders whose m2m is not
    refreshed (i.e. their .cache_searchcache is None).
    """
    # Implementation of permission check is very complicated, do not implement
    # it here! Use get_visible_folder_tree instead.

    tags = [x.tag for x in get_object_tagged_items(task)]

    # One possible solution is:
    #   Folder.objects.for_user(user, permission)  \
    #       .filter(tasks=task, search_cache_elements__cache=search_cache) \
    #       .distinct()
    # but the complexity of this query is O(count(Folder)).
    # That's why we separately take IDs from FolderTask and IDs from
    # reverse_cache and then select them through their IDs.

    # Folders with many-to-many relation
    m2m_ids = FolderTask.objects.filter(task=task).values_list('folder_id', flat=True)

    # Folders with tag filter
    search_cache = reverse_search([x.name for x in tags])
    if search_cache:
        content_type = ContentType.objects.get_for_model(Folder)
        search_ids = SearchCacheElement.objects.filter(cache=search_cache,
            content_type=content_type).values_list('object_id', flat=True)
    else:
        search_ids = []

    ids = list(m2m_ids) + list(search_ids)

    # Remove duplicates (does not preserve order)
    return list(set(ids))
Example #3
0
 def CHECK(x, y, z = None):
     names = [item.tag.name for item in get_object_tagged_items(x)]
     self.assertEqual(sorted(names), sorted(y), z)