diff --git a/api/graphql/resolvers/photo.go b/api/graphql/resolvers/photo.go index fa492181..b6bc05cf 100644 --- a/api/graphql/resolvers/photo.go +++ b/api/graphql/resolvers/photo.go @@ -152,30 +152,9 @@ func (r *photoResolver) Thumbnail(ctx context.Context, obj *models.Photo) (*mode 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) { - 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) { diff --git a/ui/src/components/header/Header.js b/ui/src/components/header/Header.js index b434e70c..e839b9a6 100644 --- a/ui/src/components/header/Header.js +++ b/ui/src/components/header/Header.js @@ -22,7 +22,7 @@ const Title = styled.h1` const Header = () => ( Photoview - + {localStorage.getItem('token') ? : null} ) diff --git a/ui/src/components/header/Searchbar.js b/ui/src/components/header/Searchbar.js index eb100385..5f714df5 100644 --- a/ui/src/components/header/Searchbar.js +++ b/ui/src/components/header/Searchbar.js @@ -53,6 +53,7 @@ const Results = styled.div` const SEARCH_QUERY = gql` query searchQuery($query: String!) { search(query: $query) { + query albums { id title @@ -68,6 +69,9 @@ const SEARCH_QUERY = gql` thumbnail { url } + album { + id + } } } } @@ -118,6 +122,7 @@ const ResultTitle = styled.h1` const SearchResults = ({ result }) => { const { data, loading } = result + const query = data && data.search.query const photos = (data && data.search.photos) || [] const albums = (data && data.search.albums) || [] @@ -128,11 +133,11 @@ const SearchResults = ({ result }) => { message = 'No results found' const albumElements = albums.map(album => ( - + )) const photoElements = photos.map(photo => ( - + )) return ( @@ -144,24 +149,28 @@ const SearchResults = ({ result }) => { show={data} > {message} - Albums + {albumElements.length > 0 && Albums} {albumElements} - Photos + {photoElements.length > 0 && Photos} {photoElements} ) } +SearchResults.propTypes = { + result: PropTypes.object, +} + const RowLink = styled(NavLink)` display: flex; align-items: center; - border-bottom: 1px solid #eee; color: black; ` const PhotoSearchThumbnail = styled(ProtectedImage)` width: 50px; height: 50px; + margin: 2px 0; object-fit: contain; ` @@ -170,7 +179,7 @@ const AlbumSearchThumbnail = styled(ProtectedImage)` height: 50px; margin: 4px 0; border-radius: 4px; - border: 1px solid #888; + /* border: 1px solid #888; */ object-fit: cover; ` @@ -179,22 +188,48 @@ const RowTitle = styled.span` padding-left: 8px; ` -const PhotoRow = photo => ( - +const PhotoRow = ({ query, photo }) => ( + - {photo.title} + {searchHighlighted(query, photo.title)} ) -const AlbumRow = album => ( +PhotoRow.propTypes = { + query: PropTypes.string.isRequired, + photo: PropTypes.object.isRequired, +} + +const AlbumRow = ({ query, album }) => ( - {album.title} + {searchHighlighted(query, album.title)} ) -SearchResults.propTypes = { - result: PropTypes.object, +AlbumRow.propTypes = { + 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} + {middle} + {end} + + ) } export default SearchBar