diff --git a/app/src/Dashboard.js b/app/src/Dashboard.js index 110fe44f..fee0f472 100644 --- a/app/src/Dashboard.js +++ b/app/src/Dashboard.js @@ -75,7 +75,7 @@ export function Dashboard() { // Only show dashboard parts if not searching. let body; - if (searchStr || activeTags) { + if (searchStr || (activeTags && activeTags.length > 0)) { body = ; } else { body = <> diff --git a/app/src/Tags.js b/app/src/Tags.js index 50a92d71..301e8ffd 100644 --- a/app/src/Tags.js +++ b/app/src/Tags.js @@ -4,7 +4,7 @@ import { Button as SButton, Confirm, Dimmer, - Divider, + Divider, Dropdown, Form, FormInput, Grid, @@ -356,6 +356,40 @@ const Dashboard = () => { } +export const TagsDropdown = ({value = [], onChange, ...props}) => { + const {tagNames} = React.useContext(TagsContext); + const [activeTags, setActiveTags] = React.useState(value); + + const handleChange = (e, {value}) => { + if (e) { + e.preventDefault(); + } + if (!value) { + setActiveTags([]); + onChange([]); + } else { + setActiveTags(value); + onChange(value); + } + } + + let options = [{key: null, text: '', value: ''}]; + if (tagNames && tagNames.length > 0) { + const tagOptions = tagNames.map(i => { + return {key: i, text: i, value: i} + }) + options = [...options, ...tagOptions]; + } + + return +} + export const TagsDashboard = () => { return diff --git a/app/src/api.js b/app/src/api.js index 7040a635..64a1103f 100644 --- a/app/src/api.js +++ b/app/src/api.js @@ -103,7 +103,7 @@ export async function getChannel(id) { return (await response.json())['channel']; } -export async function searchVideos(offset, limit, channelId, searchStr, order_by, tags) { +export async function searchVideos(offset, limit, channelId, searchStr, order_by, tagNames) { // Build a search query to retrieve a list of videos from the API offset = parseInt(offset || 0); limit = parseInt(limit || DEFAULT_LIMIT); @@ -115,8 +115,8 @@ export async function searchVideos(offset, limit, channelId, searchStr, order_by if (channelId) { body['channel_id'] = parseInt(channelId); } - if (tags) { - body['tag_names'] = tags.split(','); + if (tagNames) { + body['tag_names'] = tagNames; } console.debug('searching videos', body); @@ -350,7 +350,7 @@ export async function deleteArchives(archiveIds) { } } -export async function searchArchives(offset, limit, domain, searchStr, order, tags) { +export async function searchArchives(offset, limit, domain, searchStr, order, tagNames) { // Build a search query to retrieve a list of videos from the API offset = parseInt(offset || 0); limit = parseInt(limit || DEFAULT_LIMIT); @@ -364,8 +364,8 @@ export async function searchArchives(offset, limit, domain, searchStr, order, ta if (order) { body['order_by'] = order; } - if (tags) { - body['tag_names'] = tags.split(','); + if (tagNames) { + body['tag_names'] = tagNames; } console.debug('searching archives', body); @@ -479,7 +479,7 @@ export async function deleteDownload(downloadId) { } } -export async function filesSearch(offset, limit, searchStr, mimetypes, model, tags) { +export async function filesSearch(offset, limit, searchStr, mimetypes, model, tagNames) { const body = {search_str: searchStr, offset: parseInt(offset), limit: parseInt(limit)}; if (mimetypes) { body['mimetypes'] = mimetypes; @@ -487,8 +487,8 @@ export async function filesSearch(offset, limit, searchStr, mimetypes, model, ta if (model) { body['model'] = model; } - if (tags) { - body['tag_names'] = tags.split(','); + if (tagNames) { + body['tag_names'] = tagNames; } console.debug('searching files', body); const response = await apiPost(`${API_URI}/files/search`, body); diff --git a/app/src/components/Files.js b/app/src/components/Files.js index 0dd906f8..f8edefe8 100644 --- a/app/src/components/Files.js +++ b/app/src/components/Files.js @@ -42,7 +42,7 @@ import _ from 'lodash'; import {FileBrowser} from "./FileBrowser"; import {refreshDirectoryFiles, refreshFiles} from "../api"; import {useSubscribeEventName} from "../Events"; -import {TagsContext} from "../Tags"; +import {TagsContext, TagsDropdown, TagsProvider} from "../Tags"; function EbookCard({file}) { const {s} = useContext(ThemeContext); @@ -347,7 +347,9 @@ export function FilesView({ {selectButton} {viewButton} {limitDropdown} - + + + {filterOptions && filtersDropdown} {menuColumns} @@ -360,8 +362,7 @@ export function FilesView({ export function TagsFilesGroupDropdown({onChange}) { // Creates dropdown that the User can use to manipulate the tag query. const {searchParams, updateQuery} = useQuery(); - const activeTag = searchParams.get('tag'); - const {tags} = React.useContext(TagsContext); + const activeTags = searchParams.getAll('tag'); const localOnChange = (name) => { updateQuery({'tag': name}); @@ -370,23 +371,11 @@ export function TagsFilesGroupDropdown({onChange}) { } } - let tagOptions = []; - if (tags && tags.length) { - for (let i = 0; i < tags.length; i++) { - const {name} = tags[i]; - tagOptions = [...tagOptions, {key: name, text: name, value: name}]; - } - - return localOnChange(value)} - style={{marginLeft: '0.3em', marginTop: '0.3em'}} - value={activeTag} - />; - } else { - return - } + return } export function FilesSearchView({ diff --git a/app/src/hooks/customHooks.js b/app/src/hooks/customHooks.js index 409ec5cd..253d25ad 100644 --- a/app/src/hooks/customHooks.js +++ b/app/src/hooks/customHooks.js @@ -153,7 +153,7 @@ export const useSearchArchives = (defaultLimit, domain, order_by) => { const {searchParams, updateQuery} = useQuery(); const searchStr = searchParams.get('q') || ''; const order = searchParams.get('order') || order_by; - const activeTags = searchParams.get('tag'); + const activeTags = searchParams.getAll('tag'); const [archives, setArchives] = useState(null); const [totalPages, setTotalPages] = useState(0); @@ -179,7 +179,7 @@ export const useSearchArchives = (defaultLimit, domain, order_by) => { useEffect(() => { localSearchArchives(); - }, [searchStr, limit, domain, order, activePage, activeTags]); + }, [searchStr, limit, domain, order, activePage, JSON.stringify(activeTags)]); const setSearchStr = (value) => { updateQuery({q: value, o: 0, order: undefined}); @@ -211,7 +211,7 @@ export const useSearchVideos = (defaultLimit, channelId, order_by) => { const {offset, limit, setLimit, activePage, setPage} = usePages(defaultLimit) const searchStr = searchParams.get('q') || ''; const order = searchParams.get('order') || order_by; - const activeTags = searchParams.get('tag'); + const activeTags = searchParams.getAll('tag'); const [videos, setVideos] = useState(); const [totalPages, setTotalPages] = useState(0); @@ -237,7 +237,7 @@ export const useSearchVideos = (defaultLimit, channelId, order_by) => { useEffect(() => { localSearchVideos(); - }, [searchStr, limit, channelId, offset, order_by, activeTags]); + }, [searchStr, limit, channelId, offset, order_by, JSON.stringify(activeTags)]); const setSearchStr = (value) => { updateQuery({q: value, o: 0, order: undefined}); @@ -385,7 +385,7 @@ export const useSearchFiles = (defaultLimit = 48, emptySearch = false, model) => const searchStr = searchParams.get('q'); const filter = searchParams.get('filter'); const model_ = searchParams.get('model'); - const activeTags = searchParams.get('tag'); + const activeTags = searchParams.getAll('tag'); const [searchFiles, setSearchFiles] = useState(null); const [totalPages, setTotalPages] = useState(0); @@ -416,7 +416,7 @@ export const useSearchFiles = (defaultLimit = 48, emptySearch = false, model) => useEffect(() => { localSearchFiles(); - }, [searchStr, limit, offset, activePage, filter, model, model_, activeTags]); + }, [searchStr, limit, offset, activePage, filter, model, model_, JSON.stringify(activeTags)]); const setPage = (i) => { i = parseInt(i);