add search result info bar
This commit is contained in:
parent
9fe12d1510
commit
fa0f903ba0
|
@ -16,7 +16,7 @@ import {
|
||||||
import { isSharedFile } from 'utils/file';
|
import { isSharedFile } from 'utils/file';
|
||||||
import { isPlaybackPossible } from 'utils/photoFrame';
|
import { isPlaybackPossible } from 'utils/photoFrame';
|
||||||
import { PhotoList } from './PhotoList';
|
import { PhotoList } from './PhotoList';
|
||||||
import { SetFiles, SelectedState, SetSearchStats } from 'types/gallery';
|
import { SetFiles, SelectedState } from 'types/gallery';
|
||||||
import { FILE_TYPE } from 'constants/file';
|
import { FILE_TYPE } from 'constants/file';
|
||||||
import PublicCollectionDownloadManager from 'services/publicCollectionDownloadManager';
|
import PublicCollectionDownloadManager from 'services/publicCollectionDownloadManager';
|
||||||
import { PublicCollectionGalleryContext } from 'utils/publicCollectionGallery';
|
import { PublicCollectionGalleryContext } from 'utils/publicCollectionGallery';
|
||||||
|
@ -57,7 +57,6 @@ interface Props {
|
||||||
openUploader?;
|
openUploader?;
|
||||||
isInSearchMode?: boolean;
|
isInSearchMode?: boolean;
|
||||||
search?: Search;
|
search?: Search;
|
||||||
setSearchStats?: SetSearchStats;
|
|
||||||
deleted?: number[];
|
deleted?: number[];
|
||||||
activeCollection: number;
|
activeCollection: number;
|
||||||
isSharedCollection?: boolean;
|
isSharedCollection?: boolean;
|
||||||
|
@ -81,7 +80,6 @@ const PhotoFrame = ({
|
||||||
openUploader,
|
openUploader,
|
||||||
isInSearchMode,
|
isInSearchMode,
|
||||||
search,
|
search,
|
||||||
setSearchStats,
|
|
||||||
deleted,
|
deleted,
|
||||||
activeCollection,
|
activeCollection,
|
||||||
isSharedCollection,
|
isSharedCollection,
|
||||||
|
@ -90,7 +88,6 @@ const PhotoFrame = ({
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [currentIndex, setCurrentIndex] = useState<number>(0);
|
const [currentIndex, setCurrentIndex] = useState<number>(0);
|
||||||
const [fetching, setFetching] = useState<{ [k: number]: boolean }>({});
|
const [fetching, setFetching] = useState<{ [k: number]: boolean }>({});
|
||||||
const startTime = Date.now();
|
|
||||||
const galleryContext = useContext(GalleryContext);
|
const galleryContext = useContext(GalleryContext);
|
||||||
const appContext = useContext(AppContext);
|
const appContext = useContext(AppContext);
|
||||||
const deduplicateContext = useContext(DeduplicateContext);
|
const deduplicateContext = useContext(DeduplicateContext);
|
||||||
|
@ -136,12 +133,6 @@ const PhotoFrame = ({
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isInSearchMode) {
|
|
||||||
setSearchStats({
|
|
||||||
resultCount: filteredData.length,
|
|
||||||
timeTaken: (Date.now() - startTime) / 1000,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!isNaN(search?.file)) {
|
if (!isNaN(search?.file)) {
|
||||||
const filteredDataIdx = filteredData.findIndex((file) => {
|
const filteredDataIdx = filteredData.findIndex((file) => {
|
||||||
return file.id === search.file;
|
return file.id === search.file;
|
||||||
|
|
32
src/components/Search/SearchResultInfo.tsx
Normal file
32
src/components/Search/SearchResultInfo.tsx
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { CollectionSummary } from 'types/collection';
|
||||||
|
import { CollectionInfo } from 'components/Collections/CollectionInfo';
|
||||||
|
import constants from 'utils/strings/constants';
|
||||||
|
import { Typography } from '@mui/material';
|
||||||
|
import { CollectionSectionWrapper } from 'components/Collections/styledComponents';
|
||||||
|
|
||||||
|
interface Iprops {
|
||||||
|
searchResult: CollectionSummary;
|
||||||
|
}
|
||||||
|
export default function SearchResultInfo({ searchResult }: Iprops) {
|
||||||
|
if (!searchResult) {
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { name, fileCount } = searchResult;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CollectionSectionWrapper>
|
||||||
|
<Typography
|
||||||
|
css={`
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 36px;
|
||||||
|
opacity: 50%;
|
||||||
|
`}>
|
||||||
|
{constants.SEARCH_RESULTS}
|
||||||
|
</Typography>
|
||||||
|
<CollectionInfo name={name} fileCount={fileCount} />
|
||||||
|
</CollectionSectionWrapper>
|
||||||
|
);
|
||||||
|
}
|
|
@ -7,12 +7,14 @@ import { EnteFile } from 'types/file';
|
||||||
import { SearchBarWrapper, SearchButtonWrapper } from './styledComponents';
|
import { SearchBarWrapper, SearchButtonWrapper } from './styledComponents';
|
||||||
import SearchInput from './input';
|
import SearchInput from './input';
|
||||||
import { Search } from 'types/search';
|
import { Search } from 'types/search';
|
||||||
|
import { SetSearchResultInfo } from 'types/gallery';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
isFirstFetch: boolean;
|
isFirstFetch: boolean;
|
||||||
setOpen: (value: boolean) => void;
|
setOpen: (value: boolean) => void;
|
||||||
setSearch: (search: Search) => void;
|
setSearch: (search: Search) => void;
|
||||||
|
setSearchResultInfo: SetSearchResultInfo;
|
||||||
collections: Collection[];
|
collections: Collection[];
|
||||||
setActiveCollection: (id: number) => void;
|
setActiveCollection: (id: number) => void;
|
||||||
files: EnteFile[];
|
files: EnteFile[];
|
||||||
|
|
|
@ -3,17 +3,18 @@ import debounce from 'debounce-promise';
|
||||||
import { AppContext } from 'pages/_app';
|
import { AppContext } from 'pages/_app';
|
||||||
import React, { useContext, useEffect, useState } from 'react';
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
import { getAutoCompleteSuggestions } from 'services/searchService';
|
import { getAutoCompleteSuggestions } from 'services/searchService';
|
||||||
import { Bbox, DateValue, Suggestion, SuggestionType } from 'types/search';
|
import { Bbox, DateValue, SearchOption, SuggestionType } from 'types/search';
|
||||||
import constants from 'utils/strings/constants';
|
import constants from 'utils/strings/constants';
|
||||||
import { ControlWithIcon } from './controlWithIcon';
|
import { ControlWithIcon } from './controlWithIcon';
|
||||||
import { SearchInputWrapper } from './styledComponents';
|
import { SearchInputWrapper } from './styledComponents';
|
||||||
import { SelectStyles } from './styles';
|
import { SelectStyles } from './styles';
|
||||||
import AsyncSelect from 'react-select/async';
|
import AsyncSelect from 'react-select/async';
|
||||||
import CloseIcon from '@mui/icons-material/Close';
|
import CloseIcon from '@mui/icons-material/Close';
|
||||||
import { SetSearch } from 'types/gallery';
|
import { SetSearch, SetSearchResultInfo } from 'types/gallery';
|
||||||
import { EnteFile } from 'types/file';
|
import { EnteFile } from 'types/file';
|
||||||
import { Collection } from 'types/collection';
|
import { Collection } from 'types/collection';
|
||||||
import { OptionWithInfo } from './optionWithInfo';
|
import { OptionWithInfo } from './optionWithInfo';
|
||||||
|
import { CollectionType } from 'constants/collection';
|
||||||
|
|
||||||
interface Iprops {
|
interface Iprops {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
|
@ -22,12 +23,13 @@ interface Iprops {
|
||||||
files: EnteFile[];
|
files: EnteFile[];
|
||||||
collections: Collection[];
|
collections: Collection[];
|
||||||
setActiveCollection: (id: number) => void;
|
setActiveCollection: (id: number) => void;
|
||||||
|
setSearchResultInfo: SetSearchResultInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SearchInput(props: Iprops) {
|
export default function SearchInput(props: Iprops) {
|
||||||
const [value, setValue] = useState<Suggestion>(null);
|
const [value, setValue] = useState<SearchOption>(null);
|
||||||
const appContext = useContext(AppContext);
|
const appContext = useContext(AppContext);
|
||||||
const handleChange = (value: Suggestion) => {
|
const handleChange = (value: SearchOption) => {
|
||||||
setValue(value);
|
setValue(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -50,7 +52,7 @@ export default function SearchInput(props: Iprops) {
|
||||||
250
|
250
|
||||||
);
|
);
|
||||||
|
|
||||||
const search = (selectedOption: Suggestion) => {
|
const search = (selectedOption: SearchOption) => {
|
||||||
if (!selectedOption) {
|
if (!selectedOption) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -77,6 +79,11 @@ export default function SearchInput(props: Iprops) {
|
||||||
setValue(null);
|
setValue(null);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
props.setSearchResultInfo({
|
||||||
|
name: selectedOption.label,
|
||||||
|
fileCount: selectedOption.fileCount,
|
||||||
|
type: CollectionType.system,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -17,6 +17,7 @@ export function GalleryNavbar({
|
||||||
files,
|
files,
|
||||||
setActiveCollection,
|
setActiveCollection,
|
||||||
updateSearch,
|
updateSearch,
|
||||||
|
setSearchResultInfo,
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<NavbarBase>
|
<NavbarBase>
|
||||||
|
@ -39,6 +40,7 @@ export function GalleryNavbar({
|
||||||
files={getNonTrashedUniqueUserFiles(files)}
|
files={getNonTrashedUniqueUserFiles(files)}
|
||||||
setActiveCollection={setActiveCollection}
|
setActiveCollection={setActiveCollection}
|
||||||
setSearch={updateSearch}
|
setSearch={updateSearch}
|
||||||
|
setSearchResultInfo={setSearchResultInfo}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!isInSearchMode && (
|
{!isInSearchMode && (
|
||||||
|
|
|
@ -90,7 +90,11 @@ import DeleteBtn from 'components/DeleteBtn';
|
||||||
import FixCreationTime, {
|
import FixCreationTime, {
|
||||||
FixCreationTimeAttributes,
|
FixCreationTimeAttributes,
|
||||||
} from 'components/FixCreationTime';
|
} from 'components/FixCreationTime';
|
||||||
import { Collection, CollectionSummaries } from 'types/collection';
|
import {
|
||||||
|
Collection,
|
||||||
|
CollectionSummaries,
|
||||||
|
CollectionSummary,
|
||||||
|
} from 'types/collection';
|
||||||
import { EnteFile } from 'types/file';
|
import { EnteFile } from 'types/file';
|
||||||
import {
|
import {
|
||||||
GalleryContextType,
|
GalleryContextType,
|
||||||
|
@ -103,8 +107,8 @@ import { ElectronFile } from 'types/upload';
|
||||||
import importService from 'services/importService';
|
import importService from 'services/importService';
|
||||||
import Collections from 'components/Collections';
|
import Collections from 'components/Collections';
|
||||||
import { GalleryNavbar } from 'components/pages/gallery/Navbar';
|
import { GalleryNavbar } from 'components/pages/gallery/Navbar';
|
||||||
import SearchStatsContainer from 'components/Search/SearchStatsContainer';
|
import { Search } from 'types/search';
|
||||||
import { SearchStats, Search } from 'types/search';
|
import SearchResultInfo from 'components/Search/SearchResultInfo';
|
||||||
|
|
||||||
export const DeadCenter = styled.div`
|
export const DeadCenter = styled.div`
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
@ -175,7 +179,8 @@ export default function Gallery() {
|
||||||
});
|
});
|
||||||
|
|
||||||
const [isInSearchMode, setIsInSearchMode] = useState(false);
|
const [isInSearchMode, setIsInSearchMode] = useState(false);
|
||||||
const [searchStats, setSearchStats] = useState<SearchStats>(null);
|
const [searchResultInfo, setSearchResultInfo] =
|
||||||
|
useState<CollectionSummary>(null);
|
||||||
const syncInProgress = useRef(true);
|
const syncInProgress = useRef(true);
|
||||||
const resync = useRef(false);
|
const resync = useRef(false);
|
||||||
const [deleted, setDeleted] = useState<number[]>([]);
|
const [deleted, setDeleted] = useState<number[]>([]);
|
||||||
|
@ -497,7 +502,6 @@ export default function Gallery() {
|
||||||
const updateSearch = (newSearch: Search) => {
|
const updateSearch = (newSearch: Search) => {
|
||||||
setActiveCollection(ALL_SECTION);
|
setActiveCollection(ALL_SECTION);
|
||||||
setSearch(newSearch);
|
setSearch(newSearch);
|
||||||
setSearchStats(null);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeCollectionSelector = (closeBtnClick?: boolean) => {
|
const closeCollectionSelector = (closeBtnClick?: boolean) => {
|
||||||
|
@ -626,6 +630,7 @@ export default function Gallery() {
|
||||||
files={getNonTrashedUniqueUserFiles(files)}
|
files={getNonTrashedUniqueUserFiles(files)}
|
||||||
setActiveCollection={setActiveCollection}
|
setActiveCollection={setActiveCollection}
|
||||||
updateSearch={updateSearch}
|
updateSearch={updateSearch}
|
||||||
|
setSearchResultInfo={setSearchResultInfo}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Collections
|
<Collections
|
||||||
|
@ -636,10 +641,8 @@ export default function Gallery() {
|
||||||
collectionSummaries={collectionSummaries}
|
collectionSummaries={collectionSummaries}
|
||||||
setCollectionNamerAttributes={setCollectionNamerAttributes}
|
setCollectionNamerAttributes={setCollectionNamerAttributes}
|
||||||
/>
|
/>
|
||||||
{searchStats && (
|
{isInSearchMode && (
|
||||||
<SearchStatsContainer>
|
<SearchResultInfo searchResult={searchResultInfo} />
|
||||||
{constants.SEARCH_STATS(searchStats)}
|
|
||||||
</SearchStatsContainer>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Upload
|
<Upload
|
||||||
|
@ -662,7 +665,7 @@ export default function Gallery() {
|
||||||
setUploadInProgress={setUploadInProgress}
|
setUploadInProgress={setUploadInProgress}
|
||||||
fileRejections={fileRejections}
|
fileRejections={fileRejections}
|
||||||
setFiles={setFiles}
|
setFiles={setFiles}
|
||||||
isFirstUpload={collectionSummaries.size === 0}
|
isFirstUpload={collectionSummaries?.size === 0}
|
||||||
electronFiles={electronFiles}
|
electronFiles={electronFiles}
|
||||||
setElectronFiles={setElectronFiles}
|
setElectronFiles={setElectronFiles}
|
||||||
uploadTypeSelectorView={uploadTypeSelectorView}
|
uploadTypeSelectorView={uploadTypeSelectorView}
|
||||||
|
@ -682,7 +685,6 @@ export default function Gallery() {
|
||||||
openUploader={openUploader}
|
openUploader={openUploader}
|
||||||
isInSearchMode={isInSearchMode}
|
isInSearchMode={isInSearchMode}
|
||||||
search={search}
|
search={search}
|
||||||
setSearchStats={setSearchStats}
|
|
||||||
deleted={deleted}
|
deleted={deleted}
|
||||||
activeCollection={activeCollection}
|
activeCollection={activeCollection}
|
||||||
isSharedCollection={isSharedCollection(
|
isSharedCollection={isSharedCollection(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Collection } from 'types/collection';
|
import { Collection, CollectionSummary } from 'types/collection';
|
||||||
import { EnteFile } from 'types/file';
|
import { EnteFile } from 'types/file';
|
||||||
import { Search, SearchStats } from 'types/search';
|
import { Search } from 'types/search';
|
||||||
|
|
||||||
export type SelectedState = {
|
export type SelectedState = {
|
||||||
[k: number]: boolean;
|
[k: number]: boolean;
|
||||||
|
@ -10,7 +10,9 @@ export type SelectedState = {
|
||||||
export type SetFiles = React.Dispatch<React.SetStateAction<EnteFile[]>>;
|
export type SetFiles = React.Dispatch<React.SetStateAction<EnteFile[]>>;
|
||||||
export type SetCollections = React.Dispatch<React.SetStateAction<Collection[]>>;
|
export type SetCollections = React.Dispatch<React.SetStateAction<Collection[]>>;
|
||||||
export type SetLoading = React.Dispatch<React.SetStateAction<Boolean>>;
|
export type SetLoading = React.Dispatch<React.SetStateAction<Boolean>>;
|
||||||
export type SetSearchStats = React.Dispatch<React.SetStateAction<SearchStats>>;
|
export type SetSearchResultInfo = React.Dispatch<
|
||||||
|
React.SetStateAction<CollectionSummary>
|
||||||
|
>;
|
||||||
export type SetSearch = React.Dispatch<React.SetStateAction<Search>>;
|
export type SetSearch = React.Dispatch<React.SetStateAction<Search>>;
|
||||||
|
|
||||||
export type GalleryContextType = {
|
export type GalleryContextType = {
|
||||||
|
|
|
@ -33,10 +33,6 @@ export type Search = {
|
||||||
collection?: number;
|
collection?: number;
|
||||||
file?: number;
|
file?: number;
|
||||||
};
|
};
|
||||||
export interface SearchStats {
|
|
||||||
resultCount: number;
|
|
||||||
timeTaken: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SearchOption extends Suggestion {
|
export interface SearchOption extends Suggestion {
|
||||||
fileCount: number;
|
fileCount: number;
|
||||||
|
|
|
@ -405,6 +405,7 @@ const englishConstants = {
|
||||||
DOWNLOAD_COLLECTION_FAILED: 'album downloading failed, please try again',
|
DOWNLOAD_COLLECTION_FAILED: 'album downloading failed, please try again',
|
||||||
CREATE_ALBUM_FAILED: 'failed to create album , please try again',
|
CREATE_ALBUM_FAILED: 'failed to create album , please try again',
|
||||||
|
|
||||||
|
SEARCH_RESULTS: 'Search results',
|
||||||
SEARCH_HINT: () => <span>Search for location, dates, themes</span>,
|
SEARCH_HINT: () => <span>Search for location, dates, themes</span>,
|
||||||
SEARCH_TYPE: (type: SuggestionType) => {
|
SEARCH_TYPE: (type: SuggestionType) => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
Loading…
Reference in a new issue