') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Filter channelsetlist by user by marcellamaki · Pull Request #2613 · learningequality/studio · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,14 +3,15 @@ import { ChannelSet } from 'shared/data/resources';
import storeFactory from 'shared/vuex/baseStore';

jest.mock('shared/vuex/connectionPlugin');
const userId = 'testId';
const userId = 1;

describe('channelSet actions', () => {
let store;
let id;
const channelSetDatum = {
name: 'test',
channels: { '11111111111111111111111111111111': true },
edit: true,
};
beforeEach(() => {
return ChannelSet.put(channelSetDatum).then(newId => {
Expand All@@ -30,7 +31,7 @@ describe('channelSet actions', () => {
it('should call ChannelSet.where', () => {
const whereSpy = jest.spyOn(ChannelSet, 'where');
return store.dispatch('channelSet/loadChannelSetList').then(() => {
expect(whereSpy).toHaveBeenCalledWith();
expect(whereSpy).toHaveBeenCalledWith({ edit: true });
whereSpy.mockRestore();
});
});
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,7 +3,7 @@ import { ChannelSet } from 'shared/data/resources';

/* CHANNEL SET ACTIONS */
export function loadChannelSetList(context) {
return ChannelSet.where().then(channelSets => {
return ChannelSet.where({ edit: true }).then(channelSets => {
context.commit('SET_CHANNELSET_LIST', channelSets);
return channelSets;
});
Expand Down
4 changes: 3 additions & 1 deletion contentcuration/contentcuration/models.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -993,7 +993,9 @@ class ChannelSet(models.Model):
def filter_edit_queryset(cls, queryset, user):
if user.is_anonymous():
return queryset.none()
return queryset.filter(editors=user)
user_id = not user.is_anonymous() and user.id
edit = Exists(User.channel_sets.through.objects.filter(user_id=user_id, channelset_id=OuterRef("id")))
return queryset.annotate(edit=edit).filter(edit=True)

@classmethod
def filter_view_queryset(cls, queryset, user):
Expand Down
27 changes: 26 additions & 1 deletion contentcuration/contentcuration/viewsets/channelset.py
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
from django.db.models import CharField
from django.db.models import Exists
from django.db.models import OuterRef
from django.db.models import Q
from django_filters.rest_framework import BooleanFilter
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import serializers
from rest_framework.permissions import IsAuthenticated

from contentcuration.models import Channel
from contentcuration.models import ChannelSet
from contentcuration.models import User
from contentcuration.viewsets.base import BulkListSerializer
from contentcuration.viewsets.base import BulkModelSerializer
from contentcuration.viewsets.base import FilterSet
from contentcuration.viewsets.base import ValuesViewset
from contentcuration.viewsets.common import NotNullMapArrayAgg
from contentcuration.viewsets.common import UserFilteredPrimaryKeyRelatedField
Expand DownExpand Up@@ -50,14 +56,33 @@ class Meta:
list_serializer_class = BulkListSerializer


class ChannelSetFilter(FilterSet):
edit = BooleanFilter(method="filter_edit")

def filter_edit(self, queryset, name, value):
return queryset.filter(edit=True)

class Meta:
model = ChannelSet
fields = ("edit",)


class ChannelSetViewSet(ValuesViewset):
queryset = ChannelSet.objects.all()
serializer_class = ChannelSetSerializer
filter_backends = (DjangoFilterBackend,)
filter_class = ChannelSetFilter
permission_classes = [IsAuthenticated]
values = ("id", "name", "description", "channels", "secret_token__token")
values = ("id", "name", "description", "channels", "secret_token__token", "edit")

field_map = {"secret_token": "secret_token__token"}

def get_queryset(self):
queryset = super(ChannelSetViewSet, self).get_queryset()
user_id = not self.request.user.is_anonymous() and self.request.user.id
edit = Exists(User.channel_sets.through.objects.filter(user_id=user_id, channelset_id=OuterRef("id")))
return queryset.annotate(edit=edit)

def annotate_queryset(self, queryset):
return queryset.annotate(
channels=NotNullMapArrayAgg(
Expand Down