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

Album covers #397

Merged
merged 17 commits into from
Oct 4, 2024
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
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ RUN apt-get update -qq && \
libsndfile-dev \
memcached \
shared-mime-info \
imagemagick \
libmagickwand-dev \
libjpeg-dev \
&& apt-get clean

# Install Node and Yarn
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ gem "grape-entity"
gem "grape-swagger"
gem "grape-swagger-entity"
gem "htmlentities"
gem "image_processing"
gem "jwt"
gem "highline"
gem "nokogiri"
Expand Down
12 changes: 10 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,15 @@ GEM
httpclient (2.8.3)
i18n (1.14.6)
concurrent-ruby (~> 1.0)
image_processing (1.13.0)
mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3)
io-console (0.7.2)
irb (1.14.1)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
json (2.7.2)
jwt (2.9.1)
jwt (2.9.3)
base64
language_server-protocol (3.17.0.3)
launchy (3.0.1)
Expand All @@ -239,6 +242,7 @@ GEM
net-smtp
marcel (1.0.4)
matrix (0.4.2)
mini_magick (4.13.2)
mini_mime (1.1.5)
minitest (5.25.1)
multi_json (1.15.0)
Expand Down Expand Up @@ -361,7 +365,7 @@ GEM
rspec-expectations (3.13.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.1)
rspec-mocks (3.13.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-rails (7.0.1)
Expand Down Expand Up @@ -415,6 +419,9 @@ GEM
ruby-audio (1.6.1)
ruby-mp3info (0.8.10)
ruby-progressbar (1.13.0)
ruby-vips (2.2.2)
ffi (~> 1.12)
logger
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
rufus-scheduler (3.9.2)
Expand Down Expand Up @@ -532,6 +539,7 @@ DEPENDENCIES
grape-swagger-entity
highline
htmlentities
image_processing
jwt
nokogiri
pg
Expand Down
24 changes: 0 additions & 24 deletions app/api/api_v2/entities/search_results.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,30 +51,6 @@ class ApiV2::Entities::SearchResults < ApiV2::Entities::Base
"detailed venue information. Returns an empty array if no venues match."
}

expose \
:show_tags,
using: ApiV2::Entities::ShowTag,
default: [],
documentation: {
type: "Array[Object]",
desc: \
"Tags applied to shows that match the search term in their notes. " \
"Each show tag object includes the tag name and associated show details. " \
"Returns an empty array if no tags match."
}

expose \
:track_tags,
using: ApiV2::Entities::TrackTag,
default: [],
documentation: {
type: "Array[Object]",
desc: \
"Tags applied to tracks that match the search term in their notes. " \
"Each track tag object includes the tag name and the associated " \
"track and show details. Empty array if no track tags match."
}

expose(
:tracks,
default: [],
Expand Down
16 changes: 16 additions & 0 deletions app/api/api_v2/entities/show.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,22 @@ class ApiV2::Entities::Show < ApiV2::Entities::Base
desc: "Date of the show"
}

expose(
:cover_art_urls,
documentation: {
type: "Object",
desc: "Object containing named URLs for variants of raw cover art images"
}
)

expose(
:album_cover_url,
documentation: {
type: "String",
desc: "URL of album cover image (text overlayed on cover art)"
}
)

expose \
:duration,
documentation: {
Expand Down
16 changes: 16 additions & 0 deletions app/api/api_v2/entities/track.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,22 @@ class ApiV2::Entities::Track < ApiV2::Entities::Base
}
) { _1.show.date }

expose(
:show_cover_art_urls,
documentation: {
type: "Object",
desc: "Object containing named URLs for variants of raw cover art images"
}
) { _1.show.cover_art_urls }

expose(
:show_album_cover_url,
documentation: {
type: "Object",
desc: "URL of album cover image (text overlayed on cover art)"
}
) { _1.show.album_cover_url }

expose(
:venue_slug,
documentation: {
Expand Down
14 changes: 14 additions & 0 deletions app/api/api_v2/search.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,21 @@ class ApiV2::Search < ApiV2::Base
get ":term" do
return error!({ message: "Term too short" }, 400) if params[:term].length < 3
results = fetch_results(params[:term], params[:scope])

# Add Show Tag matches to other_shows
if results[:show_tags].present?
ids = results[:show_tags].map(&:show_id) + results[:other_shows].map(&:id)
results[:other_shows] = Show.where(id: ids)
end

# Add Track Tag matches to tracks
if results[:track_tags].present?
ids = results[:track_tags].map(&:track_id) + results[:tracks].map(&:id)
results[:tracks] = Track.where(id: ids)
end

all_matched_shows = (Array(results[:exact_show]) + Array(results[:other_shows])).compact

present \
results,
with: ApiV2::Entities::SearchResults,
Expand Down
25 changes: 25 additions & 0 deletions app/javascript/components/CoverArt.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from "react";

const CoverArt = ({ coverArtUrls, albumCoverUrl, openAppModal, size }) => {
const handleOpenModal = () => {
if (!openAppModal) return;
const modalContent = (
<div className="large-album-art">
<img src={albumCoverUrl || coverArtUrls?.medium} alt="Cover art" />
</div>
);
openAppModal(modalContent);
};

return (
<span className="cover-art cover-art-modal-trigger" onClick={handleOpenModal}>
<img
src={size === "large" ? coverArtUrls?.medium : coverArtUrls?.small}
alt="Cover art"
className={size === "large" ? "cover-art-large" : "cover-art-small"}
/>
</span>
);
};

export default CoverArt;
2 changes: 1 addition & 1 deletion app/javascript/components/Playlist.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ const Playlist = () => {
{playlist.description || "This playlist has no description"}
<p>
<FontAwesomeIcon icon={faCalendar} className="mr-1 text-gray" />
Last updated: {formatDateLong(playlist.updated_at)}
Updated: {formatDateLong(playlist.updated_at)}
</p>

<div className="display-phone-only">
Expand Down
2 changes: 1 addition & 1 deletion app/javascript/components/Playlists.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const Playlists = ({ playlists, highlight }) => {
</div>
<div className="last-updated">
<FontAwesomeIcon icon={faCalendar} className="mr-1 text-gray" />
Last Updated: {formatDateLong(new Date(playlist.updated_at))}
Updated: {formatDateLong(new Date(playlist.updated_at))}
</div>

<div className="display-phone-only">
Expand Down
2 changes: 1 addition & 1 deletion app/javascript/components/SearchResults.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const SearchResults = ({ results, term }) => {

{otherShows?.length > 0 && (
<>
<h2 className="title">Shows on Day of Year</h2>
<h2 className="title">Matched Shows</h2>
<Shows shows={showMoreOtherShows ? otherShows : otherShows.slice(0, 10)} />
{otherShows.length > 10 && (
<button className="button" onClick={() => setShowMoreOtherShows(!showMoreOtherShows)}>
Expand Down
26 changes: 21 additions & 5 deletions app/javascript/components/Show.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ import LikeButton from "./controls/LikeButton";
import Tracks from "./Tracks";
import TagBadges from "./controls/TagBadges";
import MapView from "./MapView";
import CoverArt from "./CoverArt";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCircleChevronLeft, faCircleChevronRight, faCircleXmark, faInfoCircle, faClock } from "@fortawesome/free-solid-svg-icons";

const Show = ({ trackSlug }) => {
const show = useLoaderData();
const [tracks, setTracks] = useState(show.tracks);
const trackRefs = useRef([]);
const { playTrack, mapboxToken } = useOutletContext();
const { playTrack, mapboxToken, openAppModal } = useOutletContext();
const [matchedTrack, setMatchedTrack] = useState(tracks[0]);
const [showIncompleteNotification, setShowIncompleteNotification] = useState(show.incomplete);
const [showAdminNotesNotification, setShowAdminNotesNotification] = useState(!!show.admin_notes);
Expand Down Expand Up @@ -63,12 +64,27 @@ const Show = ({ trackSlug }) => {

const sidebarContent = (
<div className="sidebar-content">
<p className="sidebar-title">{formatDateMed(show.date)}</p>
<p className="sidebar-info hidden-mobile">
<Link to={`/venues/${show.venue.slug}`}>{show.venue_name}</Link>
<div class="hidden-mobile mb-2">
<CoverArt
coverArtUrls={show.cover_art_urls}
albumCoverUrl={show.album_cover_url}
openAppModal={openAppModal}
size="large"
/>
</div>

<p className="sidebar-title show-cover-title">
<span class="display-mobile-only">
<CoverArt
coverArtUrls={show.cover_art_urls}
albumCoverUrl={show.album_cover_url}
openAppModal={openAppModal}
/>
</span>
{formatDateMed(show.date)}
</p>
<p className="sidebar-info hidden-mobile">
<Link to={`/map?term=${encodeURIComponent(show.venue.location)}`}>{show.venue.location}</Link>
<Link to={`/venues/${show.venue.slug}`}>{show.venue_name}</Link>
</p>
<div className="mr-1 show-duration">
<FontAwesomeIcon icon={faClock} className="mr-1 text-gray" />
Expand Down
2 changes: 2 additions & 0 deletions app/javascript/components/Shows.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { formatDurationShow, formatDate } from "./helpers/utils";
import TagBadges from "./controls/TagBadges";
import LikeButton from "./controls/LikeButton";
import ShowContextMenu from "./controls/ShowContextMenu";
import CoverArt from "./CoverArt";

const Shows = ({ shows, numbering = false, tourHeaders = false }) => {
const { activeTrack } = useOutletContext();
Expand Down Expand Up @@ -45,6 +46,7 @@ const Shows = ({ shows, numbering = false, tourHeaders = false }) => {
<div className="main-row">
{numbering && <span className="leftside-numbering">#{index + 1}</span>}
<span className="leftside-primary">
<CoverArt coverArtUrls={show.cover_art_urls} />
{formatDate(show.date)}
</span>
<span className="leftside-secondary">{show.venue.name}</span>
Expand Down
5 changes: 3 additions & 2 deletions app/javascript/components/Tracks.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import TagBadges from "./controls/TagBadges";
import HighlightedText from "./controls/HighlightedText";
import LikeButton from "./controls/LikeButton";
import TrackContextMenu from "./controls/TrackContextMenu";
import CoverArt from "./CoverArt";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faScissors } from "@fortawesome/free-solid-svg-icons";

Expand Down Expand Up @@ -92,15 +93,15 @@ const Tracks = ({ tracks, viewStyle, numbering = false, omitSecondary = false, h
{
viewStyle !== "show" && (
<>
<CoverArt coverArtUrls={track.show_cover_art_urls} />
<span className="date-link">
<Link
to={`/${track.show_date}/${track.slug}`}
onClick={(e) => e.stopPropagation()}
>
{formatDate(track.show_date)}
</Link>
</span>
<span className="donut-bullet">&#127849;</span>
</span>{" "}
</>
)
}
Expand Down
Loading
Loading