|
1 | 1 | <template> |
2 | 2 |
|
3 | | - <div> |
| 3 | + <div class="catalog-filters-wrapper"> |
4 | 4 | <KButton |
5 | | - v-if="$vuetify.breakpoint.xsOnly" |
6 | | - class="drawer-btn" |
7 | | - :text="$tr('searchText')" |
8 | | - :primary="true" |
9 | | - appearance="flat-button" |
10 | | - @click.stop="drawer = true" |
| 5 | + v-if="windowIsSmall" |
| 6 | + class="filter-button" |
| 7 | + :text="$tr('filterLabel')" |
| 8 | + appearance="raised-button" |
| 9 | + icon="filter" |
| 10 | + @click="openSidePanel" |
11 | 11 | /> |
12 | | - <CatalogFilterBar /> |
13 | | - <VNavigationDrawer |
14 | | - v-model="drawer" |
15 | | - :permanent="$vuetify.breakpoint.smAndUp" |
16 | | - app |
17 | | - disable-route-watcher |
18 | | - :clipped="$vuetify.breakpoint.smAndUp" |
19 | | - :right="isRTL" |
| 12 | + <div |
| 13 | + v-if="!windowIsSmall" |
| 14 | + class="filter-panel" |
| 15 | + :style="asideStyles" |
20 | 16 | > |
21 | | - <VContainer class="filters pa-3"> |
22 | | - <VToolbar |
23 | | - v-if="$vuetify.breakpoint.xsOnly" |
24 | | - color="transparent" |
25 | | - flat |
26 | | - dense |
27 | | - > |
28 | | - <VSpacer /> |
29 | | - <VBtn |
30 | | - icon |
31 | | - flat |
32 | | - style="text-align: right" |
33 | | - @click="drawer = false" |
34 | | - > |
35 | | - <Icon icon="clear" /> |
36 | | - </VBtn> |
37 | | - </VToolbar> |
38 | | - |
39 | | - <!-- Keyword search --> |
40 | | - <VTextField |
41 | | - v-model="keywordInput" |
42 | | - color="primary" |
43 | | - :label="$tr('searchLabel')" |
44 | | - box |
45 | | - clearable |
46 | | - data-test="keywords" |
47 | | - autofocus |
48 | | - @input="setKeywords" |
49 | | - /> |
50 | | - |
51 | | - <!-- Language --> |
52 | | - <LanguageFilter |
53 | | - v-model="languages" |
54 | | - :menu-props="menuProps" |
55 | | - /> |
56 | | - |
57 | | - <!-- License (attach to self to keep in notranslate class) --> |
58 | | - <MultiSelect |
59 | | - v-if="!libraryMode" |
60 | | - v-model="licenses" |
61 | | - :items="licenseOptions" |
62 | | - :label="$tr('licenseLabel')" |
63 | | - /> |
64 | | - |
65 | | - <!-- Formats (attach to self to keep in notranslate class) --> |
66 | | - <MultiSelect |
67 | | - v-model="kinds" |
68 | | - :items="kindOptions" |
69 | | - :label="$tr('formatLabel')" |
70 | | - /> |
71 | | - |
72 | | - <!-- Starred --> |
73 | | - <Checkbox |
74 | | - v-if="loggedIn" |
75 | | - v-model="bookmark" |
76 | | - :label="$tr('starredLabel')" |
77 | | - /> |
78 | | - |
79 | | - <!-- Includes --> |
80 | | - <div class="subheading"> |
81 | | - {{ $tr('includesLabel') }} |
82 | | - </div> |
83 | | - |
84 | | - <div :style="{ display: 'flex', alignItems: 'center' }"> |
85 | | - <Checkbox |
86 | | - v-model="coach" |
87 | | - aria-describedby="tooltip-coach" |
88 | | - :label="$tr('coachLabel')" |
89 | | - /> |
90 | | - <HelpTooltip |
91 | | - :text="$tr('coachDescription')" |
92 | | - maxWidth="250px" |
93 | | - tooltipId="tooltip-coach" |
94 | | - /> |
95 | | - </div> |
96 | | - |
97 | | - <Checkbox |
98 | | - v-model="subtitles" |
99 | | - :label="$tr('subtitlesLabel')" |
100 | | - /> |
101 | | - <KRouterLink |
102 | | - class="qa-link" |
103 | | - :to="faqLink" |
104 | | - :text="$tr('frequentlyAskedQuestionsLink')" |
105 | | - appearance="basic-link" |
106 | | - iconAfter="openNewTab" |
107 | | - target="_blank" |
108 | | - /> |
109 | | - </VContainer> |
110 | | - <VFooter |
111 | | - class="pb-3 pt-2 px-4" |
112 | | - color="transparent" |
113 | | - height="100" |
114 | | - > |
115 | | - <div> |
116 | | - <VImg |
117 | | - height="60" |
118 | | - width="90" |
119 | | - class="mb-1 mr-2" |
120 | | - contain |
121 | | - :src="require('shared/images/le-logo.svg')" |
122 | | - /> |
123 | | - <KExternalLink |
124 | | - href="https://learningequality.org/" |
125 | | - :text="$tr('copyright', { year: new Date().getFullYear() })" |
126 | | - openInNewTab |
127 | | - /> |
128 | | - </div> |
129 | | - </VFooter> |
130 | | - </VNavigationDrawer> |
| 17 | + <CatalogFilterPanelContent /> |
| 18 | + </div> |
| 19 | + <SidePanelModal |
| 20 | + v-if="windowIsSmall && showCatalogFiltersSidePanel" |
| 21 | + alignment="left" |
| 22 | + @closePanel="closeSidePanel" |
| 23 | + > |
| 24 | + <CatalogFilterPanelContent /> |
| 25 | + </SidePanelModal> |
131 | 26 | </div> |
132 | 27 |
|
133 | 28 | </template> |
134 | 29 |
|
135 | 30 |
|
136 | 31 | <script> |
137 | 32 |
|
138 | | - import { mapGetters } from 'vuex'; |
139 | | - import debounce from 'lodash/debounce'; |
140 | | - import { RouteNames } from '../../constants'; |
141 | | - import CatalogFilterBar from './CatalogFilterBar'; |
142 | | - import { catalogFilterMixin } from './mixins'; |
143 | | - import LanguageFilter from './components/LanguageFilter'; |
144 | | - import MultiSelect from 'shared/views/form/MultiSelect'; |
145 | | - import { constantsTranslationMixin } from 'shared/mixins'; |
146 | | - import Checkbox from 'shared/views/form/Checkbox'; |
147 | | - import HelpTooltip from 'shared/views/HelpTooltip'; |
148 | | - import { ContentKindsNames } from 'shared/leUtils/ContentKinds'; |
| 33 | + import { ref, computed, defineComponent } from 'vue'; |
| 34 | + import { themeTokens } from 'kolibri-design-system/lib/styles/theme'; |
| 35 | + import useKResponsiveWindow from 'kolibri-design-system/lib/composables/useKResponsiveWindow'; |
| 36 | + import CatalogFilterPanelContent from './components/CatalogFilterPanelContent.vue'; |
| 37 | + import SidePanelModal from 'shared/views/SidePanelModal'; |
149 | 38 |
|
150 | | - const excludedKinds = new Set([ContentKindsNames.TOPIC, ContentKindsNames.H5P]); |
151 | | -
|
152 | | - export default { |
| 39 | + export default defineComponent({ |
153 | 40 | name: 'CatalogFilters', |
154 | 41 | components: { |
155 | | - LanguageFilter, |
156 | | - Checkbox, |
157 | | - HelpTooltip, |
158 | | - MultiSelect, |
159 | | - CatalogFilterBar, |
| 42 | + CatalogFilterPanelContent, |
| 43 | + SidePanelModal, |
160 | 44 | }, |
161 | | - mixins: [constantsTranslationMixin, catalogFilterMixin], |
162 | | - data() { |
| 45 | + setup() { |
| 46 | + const { windowIsSmall } = useKResponsiveWindow(); |
| 47 | + const tokensTheme = themeTokens(); |
| 48 | +
|
| 49 | + const showCatalogFiltersSidePanel = ref(false); |
| 50 | +
|
| 51 | + const asideStyles = computed(() => ({ |
| 52 | + backgroundColor: tokensTheme.surface, |
| 53 | + borderRight: `2px solid ${tokensTheme.fineLine}`, |
| 54 | + })); |
| 55 | +
|
| 56 | + const openSidePanel = () => { |
| 57 | + showCatalogFiltersSidePanel.value = true; |
| 58 | + }; |
| 59 | +
|
| 60 | + const closeSidePanel = () => { |
| 61 | + showCatalogFiltersSidePanel.value = false; |
| 62 | + }; |
| 63 | +
|
163 | 64 | return { |
164 | | - drawer: false, |
165 | | - keywordInput: '', |
| 65 | + windowIsSmall, |
| 66 | + showCatalogFiltersSidePanel, |
| 67 | + asideStyles, |
| 68 | + openSidePanel, |
| 69 | + closeSidePanel, |
166 | 70 | }; |
167 | 71 | }, |
168 | | - computed: { |
169 | | - ...mapGetters(['loggedIn']), |
170 | | - isRTL() { |
171 | | - return window.isRTL; |
172 | | - }, |
173 | | - libraryMode() { |
174 | | - return window.libraryMode; |
175 | | - }, |
176 | | - faqLink() { |
177 | | - return { name: RouteNames.CATALOG_FAQ }; |
178 | | - }, |
179 | | - menuProps() { |
180 | | - return { offsetY: true, maxHeight: 270 }; |
181 | | - }, |
182 | | - kindOptions() { |
183 | | - return (window.publicKinds || []) |
184 | | - .map(kind => { |
185 | | - if (!excludedKinds.has(kind)) { |
186 | | - return { |
187 | | - value: kind, |
188 | | - text: this.translateConstant(kind), |
189 | | - }; |
190 | | - } |
191 | | - }) |
192 | | - .filter(Boolean); |
193 | | - }, |
194 | | - licenseOptions() { |
195 | | - return (window.publicLicenses || []).map(id => { |
196 | | - return { |
197 | | - value: Number(id), |
198 | | - text: this.translateLicense(Number(id)), |
199 | | - }; |
200 | | - }); |
201 | | - }, |
202 | | - setKeywords() { |
203 | | - return debounce(this.updateKeywords, 500); |
204 | | - }, |
205 | | - }, |
206 | | - watch: { |
207 | | - keywords() { |
208 | | - this.keywordInput = this.keywords; |
209 | | - }, |
210 | | - }, |
211 | | - beforeMount() { |
212 | | - this.keywordInput = this.$route.query.keywords; |
213 | | - }, |
214 | | - methods: { |
215 | | - updateKeywords() { |
216 | | - this.keywords = this.keywordInput; |
217 | | - }, |
218 | | - }, |
219 | 72 | $trs: { |
220 | | - searchLabel: 'Keywords', |
221 | | - coachLabel: 'Resources for coaches', |
222 | | - subtitlesLabel: 'Captions or subtitles', |
223 | | - starredLabel: 'Starred', |
224 | | - licenseLabel: 'Licenses', |
225 | | - formatLabel: 'Formats', |
226 | | - includesLabel: 'Display only channels with', |
227 | | - searchText: 'Search', |
228 | | - coachDescription: 'Resources for coaches are only visible to coaches in Kolibri', |
229 | | - frequentlyAskedQuestionsLink: 'Frequently asked questions', |
230 | | - copyright: '© {year} Learning Equality', |
| 73 | + filterLabel: 'Filter', |
231 | 74 | }, |
232 | | - }; |
| 75 | + }); |
233 | 76 |
|
234 | 77 | </script> |
235 | 78 |
|
236 | 79 |
|
237 | 80 | <style lang="scss" scoped> |
238 | 81 |
|
239 | | - .v-input--checkbox { |
240 | | - margin: 0; |
241 | | - } |
242 | | -
|
243 | | - ::v-deep .v-messages { |
244 | | - display: none; |
245 | | - } |
246 | | -
|
247 | | - .subheading { |
248 | | - margin-top: 20px; |
249 | | - margin-bottom: 5px; |
250 | | - font-weight: bold; |
251 | | - color: gray; |
252 | | - } |
253 | | -
|
254 | | - .filters { |
| 82 | + .catalog-filters-wrapper { |
255 | 83 | width: 100%; |
256 | | - height: calc(100% - 100px); |
257 | | - overflow: auto; |
| 84 | + height: 100%; |
258 | 85 | } |
259 | 86 |
|
260 | | - .qa-link { |
261 | | - margin-top: 24px; |
| 87 | + .filter-button { |
| 88 | + margin: 16px; |
262 | 89 | } |
263 | 90 |
|
264 | | - .drawer-btn { |
265 | | - margin-top: 10px; |
| 91 | + .filter-panel { |
| 92 | + width: 100%; |
| 93 | + height: 100%; |
266 | 94 | } |
267 | 95 |
|
268 | 96 | </style> |
0 commit comments