Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FW-4672 FE media search hookup #171

Merged
merged 7 commits into from
Oct 26, 2023
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
1 change: 1 addition & 0 deletions src/common/constants/misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const DISPLAYABLE_PROPS_MEDIA = [
'title',
'mimeType',
'acknowledgement',
'description',
]
export const ABOUT_LINK =
'https://firstvoices.atlassian.net/wiki/spaces/FIR1/pages/1704813/About+FirstVoices'
Expand Down
4 changes: 4 additions & 0 deletions src/common/constants/searchParams.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export const TYPE_STORY = 'story'
export const TYPE_WORD = 'word'
export const TYPE_ENTRY = 'word,phrase,song,story'
export const TYPE_DICTIONARY = 'word,phrase'
export const TYPE_MEDIA = 'audio,image,video'
export const TYPE_AUDIO = 'audio'
export const TYPE_IMAGE = 'image'
export const TYPE_VIDEO = 'video'

/* Param Keys Frontend ONLY */
export const CHAR = 'char'
1 change: 1 addition & 0 deletions src/common/dataAdaptors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './widgetAdaptors'
export * from './storyAdaptors'
export * from './songAdaptors'
export * from './pageAdaptors'
export * from './mediaAdaptors'
16 changes: 15 additions & 1 deletion src/common/dataHooks/useSearchLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,15 @@ import {
TYPE_SONG,
TYPE_STORY,
TYPE_WORD,
TYPE_AUDIO,
TYPE_IMAGE,
TYPE_VIDEO,
} from 'common/constants'
import { storySummaryAdaptor, songSummaryAdaptor } from 'common/dataAdaptors'
import {
storySummaryAdaptor,
songSummaryAdaptor,
mediaAdaptor,
} from 'common/dataAdaptors'

/**
* Calls search API and provides search results and infinite scroll info.
Expand Down Expand Up @@ -64,6 +71,13 @@ function useSearchLoader({ searchParams }) {
...storySummaryAdaptor({ item: result?.entry }),
...baseObject,
}
case TYPE_AUDIO:
case TYPE_IMAGE:
case TYPE_VIDEO:
return {
...mediaAdaptor({ type: result?.type, data: result?.entry }),
...baseObject,
}
default:
return {
...baseObject,
Expand Down
36 changes: 36 additions & 0 deletions src/common/utils/stringHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import {
TYPE_WORD,
TYPE_STORY,
TYPE_SONG,
TYPE_MEDIA,
TYPE_AUDIO,
TYPE_IMAGE,
TYPE_VIDEO,
UUID_REGEX,
} from 'common/constants'

Expand Down Expand Up @@ -235,6 +239,38 @@ export const getPresentationPropertiesForType = (type) => {
slug: 'dictionary',
color: 'word',
}
case TYPE_MEDIA:
return {
uppercase: 'MEDIA',
singular: 'media',
plural: 'media',
slug: 'search',
color: 'primary',
}
case TYPE_AUDIO:
return {
uppercase: 'AUDIO',
singular: 'audio',
plural: 'audio',
slug: 'audio',
color: 'primary',
}
case TYPE_IMAGE:
return {
uppercase: 'IMAGE',
singular: 'image',
plural: 'images',
slug: 'image',
color: 'primary',
}
case TYPE_VIDEO:
return {
uppercase: 'VIDEO',
singular: 'video',
plural: 'videos',
slug: 'video',
color: 'primary',
}
case TYPE_ENTRY:
default:
return {
Expand Down
17 changes: 10 additions & 7 deletions src/components/DashboardMedia/DashboardMediaData.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,39 @@ import { useSearchParams } from 'react-router-dom'

// FPCC
import { useSiteStore } from 'context/SiteContext'
import { getFriendlyDocType } from 'common/utils/stringHelpers'
import {
TYPE_AUDIO,
TYPE_IMAGE,
TYPE_VIDEO,
TYPES,
} from 'common/constants/searchParams'

function DashboardMediaData() {
const { site } = useSiteStore()
const [searchParams] = useSearchParams()

const docType = searchParams.get('type')
? getFriendlyDocType({ docType: searchParams.get('type') })
: null
const docType = searchParams.get(`${TYPES}`) || null

const tileContent = [
{
icon: 'Microphone',
name: 'Audio',
description: 'Manage your audio files',
href: 'browser?type=audio',
href: `browser?${TYPES}=${TYPE_AUDIO}`,
iconColor: 'songText',
},
{
icon: 'Images',
name: 'Images',
description: 'Manage your images',
href: 'browser?type=images',
href: `browser?${TYPES}=${TYPE_IMAGE}`,
iconColor: 'wordText',
},
{
icon: 'Video',
name: 'Videos',
description: 'Manage your videos',
href: 'browser?type=videos',
href: `browser?${TYPES}=${TYPE_VIDEO}`,
iconColor: 'storyText',
},
]
Expand Down
7 changes: 3 additions & 4 deletions src/components/MediaBrowser/MediaBrowserContainerNonModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function MediaBrowserContainerNonModal({ docType }) {
isLoadingEntries,
loadRef,
loadLabel,
friendlyDocTypeLabel,
docTypePlural,
} = MediaBrowserData({ docType })

const hasResults = !!(
Expand All @@ -36,7 +36,7 @@ function MediaBrowserContainerNonModal({ docType }) {
return (
<SearchSelector.Presentation
searchQuery={searchValue}
searchPromptText={`Search all ${friendlyDocTypeLabel}`}
searchPromptText={`Search all ${docTypePlural}`}
setSearchQuery={handleTextFieldChange}
search={handleSearchSubmit}
headerSection=""
Expand All @@ -48,11 +48,10 @@ function MediaBrowserContainerNonModal({ docType }) {
id="results-header"
className="capitalize flex text-2xl font-bold text-fv-charcoal mb-4"
>
{friendlyDocTypeLabel}
{docTypePlural}
</h1>
<BrowserComponent
data={media}
docType={docType}
infiniteScroll={infiniteScroll}
currentFile={currentFile}
setCurrentFile={setCurrentFile}
Expand Down
85 changes: 29 additions & 56 deletions src/components/MediaBrowser/MediaBrowserData.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
import { useEffect, useRef, useState } from 'react'
import { useNavigate, useLocation, useParams } from 'react-router-dom'
import { useInfiniteQuery } from '@tanstack/react-query'
import { useEffect, useState } from 'react'
import { useNavigate, useParams, useSearchParams } from 'react-router-dom'
import PropTypes from 'prop-types'

// FPCC
import { useSiteStore } from 'context/SiteContext'
import api from 'services/api'
import useSearchLoader from 'common/dataHooks/useSearchLoader'
import useIntersectionObserver from 'common/hooks/useIntersectionObserver'
import { AUDIO, IMAGE, VIDEO, TYPES, TYPE_MEDIA } from 'common/constants'
import useSearchBoxNavigation from 'common/hooks/useSearchBoxNavigation'
import { getFriendlyDocType } from 'common/utils/stringHelpers'
import { mediaAdaptor } from 'common/dataAdaptors/mediaAdaptors'
import { AUDIO, IMAGE, VIDEO } from 'common/constants'

function MediaBrowserData({ docType }) {
const { site } = useSiteStore()
const { search } = useLocation()
const { sitename } = useParams()
const navigate = useNavigate()
const { sitename } = useParams()
const [searchParams] = useSearchParams()

const docTypePlural = getFriendlyDocType({ docType, plural: true })

// Extract search term from URL search params
const searchParamsQuery = new URLSearchParams(search).get('q')
? new URLSearchParams(search).get('q')
: ''
// Friendly Doc Type Label to use in document search
const friendlyDocTypeLabel = getFriendlyDocType({
docType,
plural: true,
const urlSearchType = searchParams.get(TYPES) || TYPE_MEDIA

const { searchType } = useSearchBoxNavigation({
initialSearchType: urlSearchType,
})

const loadRef = useRef(null)
const searchParamsQuery = searchParams.get('q') || ''
const [currentFile, setCurrentFile] = useState() // Used for the sidebar to display the current selected file
const [searchTerm, setSearchTerm] = useState(searchParamsQuery)
const [searchInputValue, setSearchInputValue] = useState(searchParamsQuery)

// Add search Term
const _searchParams = new URLSearchParams({
q: searchTerm,
[TYPES]: searchType,
})

const { data, infiniteScroll, loadRef, isInitialLoading, isError } =
useSearchLoader({ searchParams: _searchParams })

const handleTextFieldChange = (event) => {
event.preventDefault()
setSearchInputValue(event.target.value)
Expand All @@ -42,55 +46,24 @@ function MediaBrowserData({ docType }) {
setSearchTerm(searchInputValue)
if (searchInputValue) {
navigate(
`/${sitename}/dashboard/media/browser?type=${friendlyDocTypeLabel}&q=${searchInputValue}`,
`/${sitename}/dashboard/media/browser?types=${docType}&q=${searchInputValue}`,
)
} else {
navigate(
`/${sitename}/dashboard/media/browser?type=${friendlyDocTypeLabel}`,
)
navigate(`/${sitename}/dashboard/media/browser?types=${docType}`)
}
}

// Data fetch
const {
data,
fetchNextPage,
hasNextPage,
isError,
isFetchingNextPage,
isInitialLoading,
} = useInfiniteQuery(
[`${docType}-search`, searchTerm],
({ pageParam = 1 }) =>
api.media.get({
sitename: site?.sitename,
docType: friendlyDocTypeLabel,
pageParam,
}),
{
// The query will not execute until the siteId exists
enabled: !!site?.id,
getNextPageParam: (lastPage) => lastPage.nextPage,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
},
)

useEffect(() => {
if (!currentFile && data?.pages?.[0]?.results) {
const firstFile = mediaAdaptor({
type: docType,
data: data?.pages?.[0]?.results?.[0],
})
const firstFile = data?.pages?.[0]?.results?.[0]
setCurrentFile(firstFile)
}
}, [currentFile, data, docType])

const infiniteScroll = { fetchNextPage, hasNextPage, isFetchingNextPage }
useIntersectionObserver({
target: loadRef,
onIntersect: fetchNextPage,
enabled: hasNextPage,
onIntersect: infiniteScroll?.fetchNextPage,
enabled: infiniteScroll?.hasNextPage,
})

const getLoadLabel = () => {
Expand All @@ -115,7 +88,7 @@ function MediaBrowserData({ docType }) {
currentFile,
setCurrentFile,
loadLabel: getLoadLabel(),
friendlyDocTypeLabel,
docTypePlural,
}
}

Expand Down
Loading
Loading