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
10 changes: 9 additions & 1 deletion kolibri/core/content/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,15 @@ def has_all_labels(self, field_name, labels):
annotations = {}
for bitmask_fieldname, bits in bits.items():
annotation_fieldname = "{}_{}".format(bitmask_fieldname, "masked")
filters[annotation_fieldname + "__gt"] = 0
# To get the correct result, i.e. an AND that all the labels are present,
# we need to check that the aggregated value is euqal to the bits.
# If we wanted an OR (which would check for any being present),
# we would have to use GREATER THAN 0 here.
filters[annotation_fieldname] = bits
# This ensures that the annotated value is the result of the AND operation
# so if all the values are present, the result will be the same as the bits
# but if any are missing, it will not be equal to the bits, but will only be
# 0 if none of the bits are present.
annotations[annotation_fieldname] = F(bitmask_fieldname).bitand(bits)

return self.annotate(**annotations).filter(**filters)
Expand Down
28 changes: 28 additions & 0 deletions kolibri/core/content/test/test_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,34 @@ def test_bitmasks(self, field, label):
"{} {}".format(field, label),
)

def test_bitmasks_and_not_or(self):
for field in metadata_lookup.keys():
node = ContentNode.objects.create(
content_id=uuid4().hex,
channel_id=uuid4().hex,
description="Blah blah blah",
id=uuid4().hex,
license_name="GNU",
license_owner="",
license_description=None,
lang_id=None,
author="",
title="Test{}".format(field),
parent_id=None,
kind=content_kinds.VIDEO,
coach_content=False,
available=False,
**{field: ",".join(metadata_lookup[field])}
)
annotate_label_bitmasks(ContentNode.objects.filter(id=node.id))
self.assertEqual(
1,
ContentNode.objects.has_all_labels(
field, metadata_lookup[field]
).count(),
"{}".format(field),
)


class RandomMetadataLabelsTestCase(TestCase):
@classmethod
Expand Down
2 changes: 1 addition & 1 deletion kolibri/plugins/learn/assets/src/app.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import router from 'kolibri.coreVue.router';
import KolibriApp from 'kolibri_app';
import RootVue from './views/LearnIndex';
import routes from './routes';
import { prepareLearnApp } from './composables/useCoreLearn';
import pluginModule from './modules/pluginModule';
import { PageNames } from './constants';
import KolibriApp from 'kolibri_app';

class LearnModule extends KolibriApp {
get stateSetters() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ const MOCK_DEFAULTS = {
searchMore: jest.fn(),
removeFilterTag: jest.fn(),
clearSearch: jest.fn(),
setCategory: jest.fn(),
currentRoute: jest.fn(() => {
// return a $route-flavored object to avoid undefined errors
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -471,22 +471,4 @@ describe(`useSearch`, () => {
});
});
});
describe('setCategory method', () => {
it('should remove all other category filters and add the new one', () => {
const { setCategory, router } = prep({
categories: 'test1,test2',
channels: 'channel1',
keywords: 'this',
});
setCategory('newcategory');
expect(router.push).toHaveBeenCalledWith({
name,
query: {
categories: 'newcategory',
channels: 'channel1',
keywords: 'this',
},
});
});
});
});
2 changes: 1 addition & 1 deletion kolibri/plugins/learn/assets/src/composables/useDevices.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { computed, getCurrentInstance, ref } from 'kolibri.lib.vueCompositionApi
import { NetworkLocationResource, RemoteChannelResource } from 'kolibri.resources';
import { get, set } from '@vueuse/core';
import useMinimumKolibriVersion from 'kolibri.coreVue.composables.useMinimumKolibriVersion';
import plugin_data from 'plugin_data';
import { KolibriStudioId } from '../constants';
import { learnStrings } from '../views/commonLearnStrings';
import plugin_data from 'plugin_data';

// The refs are defined in the outer scope so they can be used as a shared store
const currentDevice = ref(null);
Expand Down
7 changes: 1 addition & 6 deletions kolibri/plugins/learn/assets/src/composables/useSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import {
NoCategories,
ResourcesNeededTypes,
} from 'kolibri.coreVue.vuex.constants';
import plugin_data from 'plugin_data';
import { deduplicateResources } from '../utils/contentNode';
import useContentNodeProgress from './useContentNodeProgress';
import useDevices from './useDevices';
import plugin_data from 'plugin_data';

export const logging = logger.getLogger(__filename);

Expand Down Expand Up @@ -323,10 +323,6 @@ export default function useSearch(descendant, store, router) {
set(searchTerms, {});
}

function setCategory(category) {
set(searchTerms, { ...get(searchTerms), categories: { [category]: true } });
}

watch(searchTerms, search);

if (descendant) {
Expand Down Expand Up @@ -441,7 +437,6 @@ export default function useSearch(descendant, store, router) {
searchMore,
removeFilterTag,
clearSearch,
setCategory,
};
}

Expand Down
3 changes: 1 addition & 2 deletions kolibri/plugins/learn/assets/src/modules/pluginModule.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// import { LastPages } from './../constants/lastPagesConstants';
import plugin_data from 'plugin_data';
import mutations from './coreLearn/mutations';
import * as getters from './coreLearn/getters';
import * as actions from './coreLearn/actions';
Expand All @@ -9,8 +10,6 @@ import examViewer from './examViewer';
import lessonPlaylist from './lessonPlaylist';
import topicsTree from './topicsTree';

import plugin_data from 'plugin_data';

export default {
state() {
return {
Expand Down
2 changes: 1 addition & 1 deletion kolibri/plugins/learn/assets/src/my_downloads/app.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import PageRoot from 'kolibri.coreVue.components.PageRoot';
import KolibriApp from 'kolibri_app';
import routes from './routes';
import pluginModule from './modules/pluginModule';
import KolibriApp from 'kolibri_app';

class MyDownloadsModule extends KolibriApp {
get routes() {
Expand Down
2 changes: 1 addition & 1 deletion kolibri/plugins/learn/assets/src/views/LearnIndex.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@

import { mapGetters, mapState } from 'vuex';
import NotificationsRoot from 'kolibri.coreVue.components.NotificationsRoot';
import { PageNames } from '../constants';
import plugin_data from 'plugin_data';
import { PageNames } from '../constants';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this just from linting?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, for reasons I couldn't discern, linting changed its mind while I was making this PR and decided to move things around.


export default {
name: 'LearnIndex',
Expand Down
176 changes: 0 additions & 176 deletions kolibri/plugins/learn/assets/src/views/LibraryPage/SidePanel.vue

This file was deleted.

16 changes: 7 additions & 9 deletions kolibri/plugins/learn/assets/src/views/LibraryPage/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -189,15 +189,13 @@
</main>

<!-- Side Panels for filtering and searching -->
<SidePanel
v-if="!isLocalLibraryEmpty || deviceId"
<SearchFiltersPanel
v-if="(!isLocalLibraryEmpty || deviceId) && (windowIsLarge || mobileSidePanelIsOpen)"
ref="sidePanel"
v-model="searchTerms"
data-test="side-panel"
:searchTerms="searchTerms"
:mobileSidePanelIsOpen="mobileSidePanelIsOpen"
@toggleMobileSidePanel="toggleSidePanelVisibility"
@setSearchTerms="newTerms => searchTerms = newTerms"
@setCategory="category => setCategory(category)"
:width="`${sidePanelWidth}px`"
@close="toggleSidePanelVisibility"
/>

<!-- Side Panel for metadata -->
Expand Down Expand Up @@ -253,6 +251,7 @@
import useKResponsiveWindow from 'kolibri.coreVue.composables.useKResponsiveWindow';
import { currentLanguage } from 'kolibri.utils.i18n';
import SidePanelModal from '../SidePanelModal';
import SearchFiltersPanel from '../SearchFiltersPanel';
import { KolibriStudioId } from '../../constants';
import useCardViewStyle from '../../composables/useCardViewStyle';
import useContentLink from '../../composables/useContentLink';
Expand All @@ -270,7 +269,6 @@
import ResumableContentGrid from './ResumableContentGrid';
import PinnedNetworkResources from './PinnedNetworkResources';
import MoreNetworkDevices from './MoreNetworkDevices';
import SidePanel from './SidePanel';

export default {
name: 'LibraryPage',
Expand All @@ -286,7 +284,7 @@
LearningActivityChip,
ResumableContentGrid,
SearchResultsGrid,
SidePanel,
SearchFiltersPanel,
LearnAppBarPage,
PinnedNetworkResources,
MoreNetworkDevices,
Expand Down
Loading