Different small improvements to search
- Make photos link to its album - Implement Photo -> Album resolver - Highlight query in search - Hide search bar when not logged in
This commit is contained in:
parent
525edbea07
commit
ec7a7adf43
|
@ -152,30 +152,9 @@ func (r *photoResolver) Thumbnail(ctx context.Context, obj *models.Photo) (*mode
|
||||||
return url, nil
|
return url, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// func processPhoto(db *sql.DB, photo *models.Photo) error {
|
|
||||||
// tx, err := db.Begin()
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// err = scanner.ProcessPhoto(tx, photo)
|
|
||||||
// if err != nil {
|
|
||||||
// tx.Rollback()
|
|
||||||
// log.Printf("ERROR: Could not process photo: %s\n", err)
|
|
||||||
// return errors.New(fmt.Sprintf("Could not process photo: %s\n", err))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// err = tx.Commit()
|
|
||||||
// if err != nil {
|
|
||||||
// log.Printf("ERROR: Could not commit photo after process to db: %s\n", err)
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
func (r *photoResolver) Album(ctx context.Context, obj *models.Photo) (*models.Album, error) {
|
func (r *photoResolver) Album(ctx context.Context, obj *models.Photo) (*models.Album, error) {
|
||||||
panic("not implemented")
|
row := r.Database.QueryRow("SELECT album.* from photo JOIN album ON photo.album_id = album.album_id WHERE photo_id = ?", obj.PhotoID)
|
||||||
|
return models.NewAlbumFromRow(row)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *photoResolver) Exif(ctx context.Context, obj *models.Photo) (*models.PhotoEXIF, error) {
|
func (r *photoResolver) Exif(ctx context.Context, obj *models.Photo) (*models.PhotoEXIF, error) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ const Title = styled.h1`
|
||||||
const Header = () => (
|
const Header = () => (
|
||||||
<Container>
|
<Container>
|
||||||
<Title>Photoview</Title>
|
<Title>Photoview</Title>
|
||||||
<SearchBar />
|
{localStorage.getItem('token') ? <SearchBar /> : null}
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ const Results = styled.div`
|
||||||
const SEARCH_QUERY = gql`
|
const SEARCH_QUERY = gql`
|
||||||
query searchQuery($query: String!) {
|
query searchQuery($query: String!) {
|
||||||
search(query: $query) {
|
search(query: $query) {
|
||||||
|
query
|
||||||
albums {
|
albums {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
|
@ -68,6 +69,9 @@ const SEARCH_QUERY = gql`
|
||||||
thumbnail {
|
thumbnail {
|
||||||
url
|
url
|
||||||
}
|
}
|
||||||
|
album {
|
||||||
|
id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,6 +122,7 @@ const ResultTitle = styled.h1`
|
||||||
|
|
||||||
const SearchResults = ({ result }) => {
|
const SearchResults = ({ result }) => {
|
||||||
const { data, loading } = result
|
const { data, loading } = result
|
||||||
|
const query = data && data.search.query
|
||||||
|
|
||||||
const photos = (data && data.search.photos) || []
|
const photos = (data && data.search.photos) || []
|
||||||
const albums = (data && data.search.albums) || []
|
const albums = (data && data.search.albums) || []
|
||||||
|
@ -128,11 +133,11 @@ const SearchResults = ({ result }) => {
|
||||||
message = 'No results found'
|
message = 'No results found'
|
||||||
|
|
||||||
const albumElements = albums.map(album => (
|
const albumElements = albums.map(album => (
|
||||||
<AlbumRow key={album.id} {...album} />
|
<AlbumRow key={album.id} query={query} album={album} />
|
||||||
))
|
))
|
||||||
|
|
||||||
const photoElements = photos.map(photo => (
|
const photoElements = photos.map(photo => (
|
||||||
<PhotoRow key={photo.id} {...photo} />
|
<PhotoRow key={photo.id} query={query} photo={photo} />
|
||||||
))
|
))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -144,24 +149,28 @@ const SearchResults = ({ result }) => {
|
||||||
show={data}
|
show={data}
|
||||||
>
|
>
|
||||||
{message}
|
{message}
|
||||||
<ResultTitle>Albums</ResultTitle>
|
{albumElements.length > 0 && <ResultTitle>Albums</ResultTitle>}
|
||||||
{albumElements}
|
{albumElements}
|
||||||
<ResultTitle>Photos</ResultTitle>
|
{photoElements.length > 0 && <ResultTitle>Photos</ResultTitle>}
|
||||||
{photoElements}
|
{photoElements}
|
||||||
</Results>
|
</Results>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SearchResults.propTypes = {
|
||||||
|
result: PropTypes.object,
|
||||||
|
}
|
||||||
|
|
||||||
const RowLink = styled(NavLink)`
|
const RowLink = styled(NavLink)`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
color: black;
|
color: black;
|
||||||
`
|
`
|
||||||
|
|
||||||
const PhotoSearchThumbnail = styled(ProtectedImage)`
|
const PhotoSearchThumbnail = styled(ProtectedImage)`
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
|
margin: 2px 0;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -170,7 +179,7 @@ const AlbumSearchThumbnail = styled(ProtectedImage)`
|
||||||
height: 50px;
|
height: 50px;
|
||||||
margin: 4px 0;
|
margin: 4px 0;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 1px solid #888;
|
/* border: 1px solid #888; */
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -179,22 +188,48 @@ const RowTitle = styled.span`
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
`
|
`
|
||||||
|
|
||||||
const PhotoRow = photo => (
|
const PhotoRow = ({ query, photo }) => (
|
||||||
<RowLink to="/">
|
<RowLink to={`/album/${photo.album.id}`}>
|
||||||
<PhotoSearchThumbnail src={photo.thumbnail.url} />
|
<PhotoSearchThumbnail src={photo.thumbnail.url} />
|
||||||
<RowTitle>{photo.title}</RowTitle>
|
<RowTitle>{searchHighlighted(query, photo.title)}</RowTitle>
|
||||||
</RowLink>
|
</RowLink>
|
||||||
)
|
)
|
||||||
|
|
||||||
const AlbumRow = album => (
|
PhotoRow.propTypes = {
|
||||||
|
query: PropTypes.string.isRequired,
|
||||||
|
photo: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
const AlbumRow = ({ query, album }) => (
|
||||||
<RowLink to={`/album/${album.id}`}>
|
<RowLink to={`/album/${album.id}`}>
|
||||||
<AlbumSearchThumbnail src={album.thumbnail.thumbnail.url} />
|
<AlbumSearchThumbnail src={album.thumbnail.thumbnail.url} />
|
||||||
<RowTitle>{album.title}</RowTitle>
|
<RowTitle>{searchHighlighted(query, album.title)}</RowTitle>
|
||||||
</RowLink>
|
</RowLink>
|
||||||
)
|
)
|
||||||
|
|
||||||
SearchResults.propTypes = {
|
AlbumRow.propTypes = {
|
||||||
result: PropTypes.object,
|
query: PropTypes.string.isRequired,
|
||||||
|
album: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchHighlighted = (query, text) => {
|
||||||
|
const i = text.toLowerCase().indexOf(query.toLowerCase())
|
||||||
|
|
||||||
|
if (i == -1) {
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
const start = text.substring(0, i)
|
||||||
|
const middle = text.substring(i, i + query.length)
|
||||||
|
const end = text.substring(i + query.length)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{start}
|
||||||
|
<b>{middle}</b>
|
||||||
|
{end}
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SearchBar
|
export default SearchBar
|
||||||
|
|
Loading…
Reference in New Issue