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
16 changes: 9 additions & 7 deletions samples/musicfestival-frontend-react/src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useEffect, useState } from 'react';
import authService from '../authService';
import LoginButton from './LoginButton';
import LogoutButton from './LogoutButton';
Expand All @@ -7,12 +7,14 @@ function Header() {
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [username, setUsername] = useState("");

authService.getUser().then((user) => {
if (user && !user.expired) {
setIsLoggedIn(true);
setUsername(user.profile.name || "");
}
});
useEffect(() => {
authService.getUser().then((user) => {
if (user && !user.expired) {
setIsLoggedIn(true);
setUsername(user.profile.name || "");
}
});
}, [])

return (
<nav className="Page-container LoginBar">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { QueryClient } from "@tanstack/react-query";
import { Locales, StartQuery } from "../generated";
import { ArtistSearchQuery, Locales, StartQuery } from "../generated";
import { ContentSavedMessage } from "../models/ContentSavedMessage";
import { extractParams, isEditOrPreviewMode } from "./urlHelper";

Expand All @@ -21,10 +21,29 @@ const generateGQLSearchQueryVars = (token: string, pathname: string, searchParam
if (isEditOrPreviewMode() && token) {
variables = { locales: locales as Locales, searchParam, sortOption };
}

return variables
}

const updateSearchQueryCache = (queryClient: QueryClient, data: StartQuery | undefined, variables: any, message: ContentSavedMessage) => {
const hasComplexProperty = message.properties.find(p => !isSimpleProperty(p.value)) !== undefined
if (hasComplexProperty) {
queryClient.invalidateQueries(['ArtistSearch', variables]);
return;
}

const newContent = updateSearchQueryData({ ...data }, message);
queryClient.setQueryData(['ArtistSearch', variables], newContent);
}

function updateSearchQueryData(data: ArtistSearchQuery, message: ContentSavedMessage) {
if (!data.ArtistDetailsPage?.items || !data.ArtistDetailsPage?.items || data.ArtistDetailsPage?.items?.length === 0) { return; }
const content = data.ArtistDetailsPage?.items[0];
message.properties.forEach((prop) => updateContentProperty(content, prop.name, prop.value));

return data;
}

const updateStartQueryCache = (queryClient: QueryClient, data: StartQuery | undefined, variables: any, message: ContentSavedMessage) => {
const hasComplexProperty = message.properties.find(p => !isSimpleProperty(p.value)) !== undefined
if (hasComplexProperty) {
Expand Down Expand Up @@ -67,4 +86,4 @@ function isSimpleProperty(propValue: any) {
}


export { generateGQLQueryVars, updateStartQueryCache, generateGQLSearchQueryVars }
export { generateGQLQueryVars, updateStartQueryCache, generateGQLSearchQueryVars, updateSearchQueryCache }
127 changes: 83 additions & 44 deletions samples/musicfestival-frontend-react/src/pages/SearchPage.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import { useState } from "react";
import { memo, useCallback, useEffect, useState } from "react";
import { useSearchParams } from "react-router-dom";
import Footer from "../components/Footer";
import Header from "../components/Header";
import SearchButton from "../components/SearchButton";
import { ArtistAutocompleteQuery, ArtistSearchQuery, OtherContentSearchQuery, useArtistAutocompleteQuery, useArtistSearchQuery, useOtherContentSearchQuery } from "../generated";
import { generateGQLSearchQueryVars } from "../helpers/queryCacheHelper";
import { generateGQLSearchQueryVars, updateSearchQueryCache } from "../helpers/queryCacheHelper";
import { getImageUrl, isEditOrPreviewMode } from "../helpers/urlHelper";
import ReactPaginate from 'react-paginate';
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { ContentSavedMessage } from "../models/ContentSavedMessage";
import authService from "../authService";
import { subcribeContentSavedEvent } from "../helpers/contentSavedEvent";

let previousSavedMessage: any = null;
const singleKeyUrl = process.env.REACT_APP_CONTENT_GRAPH_GATEWAY_URL as string
const hmacKeyUrl = process.env.REACT_APP_CG_PROXY_URL as string

function SearchPage() {
const singleKeyUrl = process.env.REACT_APP_CONTENT_GRAPH_GATEWAY_URL as string
console.log("Start")
const queryClient = useQueryClient()
const ARTIST = "Artist"
const OTHERCONTENT = "OtherContent"
const options: string[] = ["ASC", "DESC"]
const itemsPerPageOptions: number[] = [10, 15]
const filterByOption: {value: string; key: string}[] = [
{value: "Artists", key: ARTIST},
{value: "Other Content", key: OTHERCONTENT}
]

const [token, setToken] = useState("")
const [itemOffset, setItemOffset] = useState(0)
Expand All @@ -26,6 +29,9 @@ function SearchPage() {
const [otherItemsPerPage, setOtherItemsPerPage] = useState(10)
const [orderBy, setOrderBy] = useState("ASC")
const [searchParams] = useSearchParams()
const endOffset = itemOffset + itemsPerPage
const endOffsetOther = otherItemOffset + otherItemsPerPage
const modeEdit = isEditOrPreviewMode()
let queryString = searchParams.get("q") ?? ""
let filterQueryString = searchParams.get("f") ?? ""
const [filterBy, setFilterBy] = useState(filterQueryString ?? ARTIST)
Expand All @@ -35,57 +41,90 @@ function SearchPage() {
let autocompleteData : ArtistAutocompleteQuery | undefined = undefined
let resultNumber : number
let otherResultNumber : number
let variables: any
let options: string[] = ["ASC", "DESC"]
let itemsPerPageOptions: number[] = [10, 15]
let filterByOption: {value: string; key: string}[] = [
{value: "Artists", key: "Artist"},
{value: "Other Content", key: "OtherContent"}
]

let modeEdit = isEditOrPreviewMode()
let variables = generateGQLSearchQueryVars(token, window.location.pathname, queryString, orderBy);
let endOffset = itemOffset + itemsPerPage
let endOffsetOther = otherItemOffset + otherItemsPerPage
let headers = {}
let url = singleKeyUrl

const { data : searchQueryData } = useArtistSearchQuery({ endpoint: singleKeyUrl }, variables, { staleTime: 2000, enabled: !modeEdit || !!token });
const { mutate } = useMutation((obj: any) => obj, {
onSuccess: (message: ContentSavedMessage) => {
if (previousSavedMessage !== message) {
previousSavedMessage = message;
updateSearchQueryCache(queryClient, artistData, variables, message)
}
}
})

useEffect(() => {
authService.getAccessToken().then((_token) => {
_token && setToken(_token)
modeEdit && !_token && !artistData && authService.login()
})
}, [])

if (modeEdit) {
if (token) {
headers = { 'Authorization': 'Bearer ' + token }
}
url = hmacKeyUrl
subcribeContentSavedEvent((message: any) => mutate(message))
}

variables = generateGQLSearchQueryVars(token, window.location.pathname, queryString, orderBy)

const { data : searchQueryData } = useArtistSearchQuery({ endpoint: url, fetchParams: { headers: headers } }, variables, { staleTime: 2000, enabled: !modeEdit || !!token })
artistData = searchQueryData
resultNumber = artistData?.ArtistDetailsPage?.items?.length ?? 0
const currentItems = artistData?.ArtistDetailsPage?.items?.slice(itemOffset, endOffset);
const pageCount = Math.ceil(resultNumber / itemsPerPage);
const currentItems = artistData?.ArtistDetailsPage?.items?.slice(itemOffset, endOffset)
const pageCount = Math.ceil(resultNumber / itemsPerPage)

const { data : otherContentSearchQueryData } = useOtherContentSearchQuery({ endpoint: singleKeyUrl }, variables, { staleTime: 2000, enabled: !modeEdit || !!token });
const { data : otherContentSearchQueryData } = useOtherContentSearchQuery({ endpoint: url, fetchParams: { headers: headers } }, variables, { staleTime: 2000, enabled: !modeEdit || !!token })
otherData = otherContentSearchQueryData
otherResultNumber = otherData?.Content?.items?.length ?? 0
const currentOtherItems = otherData?.Content?.items?.slice(otherItemOffset, endOffsetOther);
const pageOtherCount = Math.ceil(otherResultNumber / itemsPerPage);
const currentOtherItems = otherData?.Content?.items?.slice(otherItemOffset, endOffsetOther)
const pageOtherCount = Math.ceil(otherResultNumber / itemsPerPage)

const { data : artistAutocompleteData } = useArtistAutocompleteQuery({ endpoint: singleKeyUrl }, variables, { staleTime: 2000, enabled: !modeEdit || !!token })
const { data : artistAutocompleteData } = useArtistAutocompleteQuery({ endpoint: url, fetchParams: { headers: headers } }, variables, { staleTime: 2000, enabled: !modeEdit || !!token })
autocompleteData = artistAutocompleteData

const handlePageClick = (event: any) => {
const newOffset = (event.selected * itemsPerPage) % resultNumber;
setItemOffset(newOffset);
};
const newOffset = (event.selected * itemsPerPage) % resultNumber
setItemOffset(newOffset)
}

const handleItemsChange = (event: any) => {
setItemsPerPage(event.target.value);
};
setItemsPerPage(event.target.value)
}

const handleOtherPageClick = (event: any) => {
const newOffset = (event.selected * itemsPerPage) % otherResultNumber;
setOtherItemOffset(newOffset);
};
const newOffset = (event.selected * itemsPerPage) % otherResultNumber
setOtherItemOffset(newOffset)
}

const handleOtherItemsChange = (event: any) => {
setOtherItemsPerPage(event.target.value);
};

const handleFilterByChange = (event : any) => {
setFilterBy(event.target.value)
};
setOtherItemsPerPage(event.target.value)
}

const handleChange = (event: any) => {
setOrderBy(event.target.value);
setOrderBy(event.target.value)
}

const handleFacetClick = (event: any) => {
window.location.href = `${window.location.origin}/search?q=${event.target.innerText}&f=${filterBy}`
}

const handleFilterByChange = (event : any) => {
setFilterBy(event.target.value)
//setOtherItemsPerPage(event.target.value)
}


return (
<div>
<Header />
Expand Down Expand Up @@ -136,7 +175,7 @@ function SearchPage() {
artistData?.ArtistDetailsPage?.facets?.StageName?.map((artist, idx) => {
return (
<div key={idx} className="facet-item">
<a key={artist?.name} onClick={(event) => handleFacetClick(event)}>
<a onClick={(event) => handleFacetClick(event)}>
<span>{artist?.name}</span>
</a>
<b>{artist?.count}</b>
Expand All @@ -151,7 +190,7 @@ function SearchPage() {
otherData?.Content?.facets?.Name?.map((content, idx) => {
return (
<div key={idx} className="facet-item">
<a key={content?.name} onClick={(event) => handleFacetClick(event)}>
<a onClick={(event) => handleFacetClick(event)}>
<span>{content?.name}</span>
</a>
<b>{content?.count}</b>
Expand Down Expand Up @@ -208,21 +247,21 @@ function SearchPage() {
<h6>People also search for: </h6>
<br></br>
{
autocompleteData?.ArtistDetailsPage?.autocomplete?.ArtistName?.map((name) => {
autocompleteData?.ArtistDetailsPage?.autocomplete?.ArtistName?.map((name, idx) => {
return (
<div>
<a key={name} onClick={(event) => handleFacetClick(event)}>
<div key={idx}>
<a onClick={(event) => handleFacetClick(event)}>
<i>{name}</i>
</a>
</div>
)
})
}
{
autocompleteData?.ArtistDetailsPage?.autocomplete?.StageName?.map((name) => {
autocompleteData?.ArtistDetailsPage?.autocomplete?.StageName?.map((name, idx) => {
return (
<div>
<a key={name} onClick={(event) => handleFacetClick(event)}>
<div key={idx}>
<a onClick={(event) => handleFacetClick(event)}>
<i>{name}</i>
</a>
</div>
Expand Down Expand Up @@ -326,4 +365,4 @@ function SearchPage() {
);
}

export default SearchPage;
export default memo(SearchPage);