Skip to content
Open
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 number Diff line number Diff line change
@@ -1,233 +1,89 @@
<template>

<div>
<div class="catalog-filters-wrapper">
<!-- Mobile: Filter button that opens SidePanelModal -->
<KButton
v-if="$vuetify.breakpoint.xsOnly"
class="drawer-btn"
v-if="isMobile"
class="filter-button-mobile"
:text="$tr('searchText')"
:primary="true"
primary
appearance="flat-button"
@click.stop="drawer = true"
@click="openSidePanel"
/>
<CatalogFilterBar />
<VNavigationDrawer
v-model="drawer"
:permanent="$vuetify.breakpoint.smAndUp"
app
disable-route-watcher
:clipped="$vuetify.breakpoint.smAndUp"
:right="isRTL"
>
<VContainer class="filters pa-3">
<VToolbar
v-if="$vuetify.breakpoint.xsOnly"
color="transparent"
flat
dense
>
<VSpacer />
<VBtn
icon
flat
style="text-align: right"
@click="drawer = false"
>
<Icon icon="clear" />
</VBtn>
</VToolbar>

<!-- Keyword search -->
<VTextField
v-model="keywordInput"
color="primary"
:label="$tr('searchLabel')"
box
clearable
data-test="keywords"
autofocus
@input="setKeywords"
/>

<!-- Language -->
<LanguageFilter
v-model="languages"
:menu-props="menuProps"
/>

<!-- License (attach to self to keep in notranslate class) -->
<MultiSelect
v-if="!libraryMode"
v-model="licenses"
:items="licenseOptions"
:label="$tr('licenseLabel')"
/>

<!-- Formats (attach to self to keep in notranslate class) -->
<MultiSelect
v-model="kinds"
:items="kindOptions"
:label="$tr('formatLabel')"
/>

<!-- Starred -->
<Checkbox
v-if="loggedIn"
v-model="bookmark"
:label="$tr('starredLabel')"
/>

<!-- Includes -->
<div class="subheading">
{{ $tr('includesLabel') }}
</div>

<div :style="{ display: 'flex', alignItems: 'center' }">
<Checkbox
v-model="coach"
aria-describedby="tooltip-coach"
:label="$tr('coachLabel')"
/>
<HelpTooltip
:text="$tr('coachDescription')"
maxWidth="250px"
tooltipId="tooltip-coach"
/>
</div>
<!-- Desktop/Tablet: Permanent side panel as page section -->
<aside
v-if="!isMobile"
class="filter-panel-desktop"
:class="{ 'filter-panel-rtl': isRTL }"
>
<CatalogFilterPanelContent />
</aside>

<Checkbox
v-model="subtitles"
:label="$tr('subtitlesLabel')"
/>
<KRouterLink
class="qa-link"
:to="faqLink"
:text="$tr('frequentlyAskedQuestionsLink')"
appearance="basic-link"
iconAfter="openNewTab"
target="_blank"
/>
</VContainer>
<VFooter
class="pb-3 pt-2 px-4"
color="transparent"
height="100"
>
<div>
<VImg
height="60"
width="90"
class="mb-1 mr-2"
contain
:src="require('shared/images/le-logo.svg')"
/>
<KExternalLink
href="https://learningequality.org/"
:text="$tr('copyright', { year: new Date().getFullYear() })"
openInNewTab
/>
</div>
</VFooter>
</VNavigationDrawer>
<!-- Main content area that includes CatalogFilterBar and the list -->
<div
class="main-content-area"
:class="{ 'with-sidebar': !isMobile }"
>
<CatalogFilterBar />
<slot></slot>
</div>

<!-- Mobile: SidePanelModal for filters (full width) -->
<SidePanelModal
v-if="isMobile && showMobilePanel"
alignment="left"
fullscreen
@closePanel="closeSidePanel"
>
<CatalogFilterPanelContent />
</SidePanelModal>
</div>

</template>


<script>

import { mapGetters } from 'vuex';
import debounce from 'lodash/debounce';
import { RouteNames } from '../../constants';
import useKResponsiveWindow from 'kolibri-design-system/lib/composables/useKResponsiveWindow';
import CatalogFilterBar from './CatalogFilterBar';
import { catalogFilterMixin } from './mixins';
import LanguageFilter from './components/LanguageFilter';
import MultiSelect from 'shared/views/form/MultiSelect';
import { constantsTranslationMixin } from 'shared/mixins';
import Checkbox from 'shared/views/form/Checkbox';
import HelpTooltip from 'shared/views/HelpTooltip';
import { ContentKindsNames } from 'shared/leUtils/ContentKinds';

const excludedKinds = new Set([ContentKindsNames.TOPIC, ContentKindsNames.H5P]);
import CatalogFilterPanelContent from './components/CatalogFilterPanelContent.vue';
import SidePanelModal from 'shared/views/SidePanelModal';

export default {
name: 'CatalogFilters',
components: {
LanguageFilter,
Checkbox,
HelpTooltip,
MultiSelect,
CatalogFilterBar,
CatalogFilterPanelContent,
SidePanelModal,
},
setup() {
const { windowIsSmall } = useKResponsiveWindow();

return {
isMobile: windowIsSmall,
};
},
mixins: [constantsTranslationMixin, catalogFilterMixin],
data() {
return {
drawer: false,
keywordInput: '',
showMobilePanel: false,
};
},
computed: {
...mapGetters(['loggedIn']),
isRTL() {
return window.isRTL;
},
libraryMode() {
return window.libraryMode;
},
faqLink() {
return { name: RouteNames.CATALOG_FAQ };
},
menuProps() {
return { offsetY: true, maxHeight: 270 };
},
kindOptions() {
return (window.publicKinds || [])
.map(kind => {
if (!excludedKinds.has(kind)) {
return {
value: kind,
text: this.translateConstant(kind),
};
}
})
.filter(Boolean);
},
licenseOptions() {
return (window.publicLicenses || []).map(id => {
return {
value: Number(id),
text: this.translateLicense(Number(id)),
};
});
},
setKeywords() {
return debounce(this.updateKeywords, 500);
},
},
watch: {
keywords() {
this.keywordInput = this.keywords;
},
},
beforeMount() {
this.keywordInput = this.$route.query.keywords;
},
methods: {
updateKeywords() {
this.keywords = this.keywordInput;
openSidePanel() {
this.showMobilePanel = true;
},
closeSidePanel() {
this.showMobilePanel = false;
},
},
$trs: {
searchLabel: 'Keywords',
coachLabel: 'Resources for coaches',
subtitlesLabel: 'Captions or subtitles',
starredLabel: 'Starred',
licenseLabel: 'Licenses',
formatLabel: 'Formats',
includesLabel: 'Display only channels with',
searchText: 'Search',
coachDescription: 'Resources for coaches are only visible to coaches in Kolibri',
frequentlyAskedQuestionsLink: 'Frequently asked questions',
copyright: '© {year} Learning Equality',
},
};

Expand All @@ -236,33 +92,49 @@

<style lang="scss" scoped>

.v-input--checkbox {
margin: 0;
.catalog-filters-wrapper {
display: flex;
}

::v-deep .v-messages {
display: none;
.filter-button-mobile {
margin: 16px;
}

.subheading {
margin-top: 20px;
margin-bottom: 5px;
font-weight: bold;
color: gray;
.filter-panel-desktop {
position: fixed;
top: 100px;
left: 0;
width: 335px;
overflow-y: auto;
}

.filters {
.main-content-area {
flex: 1;
width: 100%;
height: calc(100% - 100px);
overflow: auto;
}
min-height: 100vh;

.qa-link {
margin-top: 24px;
&.with-sidebar {
margin-left: 335px;
}
}

.drawer-btn {
margin-top: 10px;
@media (max-width: 600px) {
.catalog-filters-wrapper {
flex-direction: column;
}

.main-content-area.with-sidebar {
margin-right: 0;
margin-left: 0;
}

.filter-panel-desktop {
display: none;
}

.filter-button-mobile {
align-self: flex-start;
width: auto;
}
}

</style>
Loading