Still converting to bootstrap 5. Restored search
This commit is contained in:
+1
-1
@@ -34,7 +34,7 @@
|
|||||||
</message>
|
</message>
|
||||||
|
|
||||||
<message id="Lms.Explore.Artists.template.entry">
|
<message id="Lms.Explore.Artists.template.entry">
|
||||||
${name class="text-decoration-none text-reset"}
|
${name class="text-decoration-none link-secondary"}
|
||||||
</message>
|
</message>
|
||||||
|
|
||||||
</messages>
|
</messages>
|
||||||
|
|||||||
+2
-2
@@ -14,7 +14,7 @@
|
|||||||
<div class="col">
|
<div class="col">
|
||||||
<h3>${name}</h3>
|
<h3>${name}</h3>
|
||||||
${<if-has-release-artists>}${artists}${</if-has-release-artists>}
|
${<if-has-release-artists>}${artists}${</if-has-release-artists>}
|
||||||
${<if-has-various-release-artists>}${tr:Lms.Explore.various-artists}${</if-has-various-release-artists>}
|
${<if-has-various-release-artists>}<div class="text-secondary">${tr:Lms.Explore.various-artists}</div>${</if-has-various-release-artists>}
|
||||||
<div class="small text-muted">${<if-has-year>}${year}${<if-has-orig-year>} (${orig-year})${</if-has-orig-year>} · ${</if-has-year>}${duration}</div>
|
<div class="small text-muted">${<if-has-year>}${year}${<if-has-orig-year>} (${orig-year})${</if-has-orig-year>} · ${</if-has-year>}${duration}</div>
|
||||||
${clusters class="mb-2"}
|
${clusters class="mb-2"}
|
||||||
</div>
|
</div>
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
</message>
|
</message>
|
||||||
|
|
||||||
<message id="Lms.Explore.Release.template.entry-release-artist">
|
<message id="Lms.Explore.Release.template.entry-release-artist">
|
||||||
${artist}
|
${artist class="text-decoration-none link-success"}
|
||||||
</message>
|
</message>
|
||||||
|
|
||||||
<message id="Lms.Explore.Release.template.entry-disc">
|
<message id="Lms.Explore.Release.template.entry-disc">
|
||||||
|
|||||||
@@ -41,10 +41,10 @@
|
|||||||
<message id="Lms.Explore.Releases.template.entry-grid">
|
<message id="Lms.Explore.Releases.template.entry-grid">
|
||||||
<div class="card border-0 bg-transparent">
|
<div class="card border-0 bg-transparent">
|
||||||
${cover class="shadow-sm"}
|
${cover class="shadow-sm"}
|
||||||
${release-name class="text-truncate text-nowrap"}
|
${release-name class="text-truncate text-nowrap text-decoration-none link-success"}
|
||||||
${<if-has-year>}${year}${</if-has-year>}
|
${<if-has-artist>}${artist-name class=" text-truncate text-nowrap text-decoration-none link-secondary"}${</if-has-artist>}
|
||||||
${<if-has-artist>}${artist-name class=" text-truncate text-nowrap"}${</if-has-artist>}
|
${<if-has-various-artists>}<div class="text-truncate text-nowrap text-success">${tr:Lms.Explore.various-artists}</div>${</if-has-various-artists>}
|
||||||
${<if-has-various-artists>}${tr:Lms.Explore.various-artists}${</if-has-various-artists>}
|
${<if-has-year>}<div class="small text-muted">${year}</div>${</if-has-year>}
|
||||||
</div>
|
</div>
|
||||||
</message>
|
</message>
|
||||||
|
|
||||||
|
|||||||
+16
-2
@@ -3,8 +3,22 @@
|
|||||||
<!--FORMS message blocks-->
|
<!--FORMS message blocks-->
|
||||||
|
|
||||||
<message id="Lms.Explore.Search.template">
|
<message id="Lms.Explore.Search.template">
|
||||||
${mode class="nav nav-pills mb-3"}
|
<ul class="nav nav-pills mb-3" id="myTab" role="tablist">
|
||||||
${stack}
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link active" id="releases-tab" data-bs-toggle="tab" data-bs-target="#releases" type="button" role="tab" aria-controls="releases" aria-selected="true">${tr:Lms.Explore.releases}</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link" id="artists-tab" data-bs-toggle="tab" data-bs-target="#artists" type="button" role="tab" aria-controls="artists" aria-selected="false">${tr:Lms.Explore.artists}</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link" id="tracks-tab" data-bs-toggle="tab" data-bs-target="#tracks" type="button" role="tab" aria-controls="tracks" aria-selected="false">${tr:Lms.Explore.tracks}</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="tab-content" id="myTabContent">
|
||||||
|
<div class="tab-pane show active" id="releases" role="tabpanel" aria-labelledby="releases-tab">${releases}</div>
|
||||||
|
<div class="tab-pane" id="artists" role="tabpanel" aria-labelledby="artists-tab">${artists}</div>
|
||||||
|
<div class="tab-pane" id="tracks" role="tabpanel" aria-labelledby="tracks-tab">${tracks}</div>
|
||||||
|
</div>
|
||||||
</message>
|
</message>
|
||||||
|
|
||||||
</messages>
|
</messages>
|
||||||
|
|||||||
@@ -268,7 +268,9 @@ Release::refreshView()
|
|||||||
{
|
{
|
||||||
if (!firstArtist)
|
if (!firstArtist)
|
||||||
artistsContainer->addNew<Wt::WText>(" · ");
|
artistsContainer->addNew<Wt::WText>(" · ");
|
||||||
artistsContainer->addWidget(LmsApplication::createArtistAnchor(artist));
|
auto anchor {LmsApplication::createArtistAnchor(artist)};
|
||||||
|
anchor->addStyleClass("link-success text-decoration-none"); // hack
|
||||||
|
artistsContainer->addWidget(std::move(anchor));
|
||||||
firstArtist = false;
|
firstArtist = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,19 +19,12 @@
|
|||||||
|
|
||||||
#include "SearchView.hpp"
|
#include "SearchView.hpp"
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include <Wt/WAnchor.h>
|
|
||||||
#include <Wt/WImage.h>
|
|
||||||
#include <Wt/WStackedWidget.h>
|
|
||||||
|
|
||||||
#include "services/database/Artist.hpp"
|
#include "services/database/Artist.hpp"
|
||||||
#include "services/database/Release.hpp"
|
#include "services/database/Release.hpp"
|
||||||
#include "services/database/Session.hpp"
|
#include "services/database/Session.hpp"
|
||||||
#include "services/database/Track.hpp"
|
#include "services/database/Track.hpp"
|
||||||
|
|
||||||
#include "common/InfiniteScrollingContainer.hpp"
|
#include "common/InfiniteScrollingContainer.hpp"
|
||||||
#include "common/LoadingIndicator.hpp"
|
|
||||||
#include "ArtistListHelpers.hpp"
|
#include "ArtistListHelpers.hpp"
|
||||||
#include "Filters.hpp"
|
#include "Filters.hpp"
|
||||||
#include "LmsApplication.hpp"
|
#include "LmsApplication.hpp"
|
||||||
@@ -45,30 +38,20 @@ namespace UserInterface
|
|||||||
SearchView::SearchView(Filters* filters)
|
SearchView::SearchView(Filters* filters)
|
||||||
: Wt::WTemplate {Wt::WString::tr("Lms.Explore.Search.template")}
|
: Wt::WTemplate {Wt::WString::tr("Lms.Explore.Search.template")}
|
||||||
, _filters {filters}
|
, _filters {filters}
|
||||||
, _releaseCollector {*filters, ReleaseCollector::Mode::Search, getMaxCount(Mode::Release)}
|
|
||||||
, _artistCollector {*filters, ArtistCollector::Mode::Search, getMaxCount(Mode::Artist)}
|
, _artistCollector {*filters, ArtistCollector::Mode::Search, getMaxCount(Mode::Artist)}
|
||||||
|
, _releaseCollector {*filters, ReleaseCollector::Mode::Search, getMaxCount(Mode::Release)}
|
||||||
, _trackCollector {*filters, TrackCollector::Mode::Search, getMaxCount(Mode::Track)}
|
, _trackCollector {*filters, TrackCollector::Mode::Search, getMaxCount(Mode::Track)}
|
||||||
{
|
{
|
||||||
addFunction("tr", &Wt::WTemplate::Functions::tr);
|
addFunction("tr", &Wt::WTemplate::Functions::tr);
|
||||||
|
|
||||||
Wt::WStackedWidget* stack {bindNew<Wt::WStackedWidget>("stack")};
|
_artists = bindNew<InfiniteScrollingContainer>("artists", Wt::WString::tr("Lms.infinite-scrolling-container"));
|
||||||
_menu = bindNew<Wt::WMenu>("mode", stack);
|
_artists->onRequestElements.connect([this] { addSomeArtists(); });
|
||||||
|
|
||||||
auto addItem = [=](const Wt::WString& str, [[maybe_unused]] Mode mode, const Wt::WString& templateStr, std::function<void()> onRequestElementsFunc)
|
_releases = bindNew<InfiniteScrollingContainer>("releases", Wt::WString::tr("Lms.Explore.Releases.template.container"));
|
||||||
{
|
_releases->onRequestElements.connect([this] { addSomeReleases(); });
|
||||||
assert(modeToIndex(mode) == _results.size());
|
|
||||||
|
|
||||||
auto results {std::make_unique<InfiniteScrollingContainer>(templateStr)};
|
_tracks = bindNew<InfiniteScrollingContainer>("tracks", Wt::WString::tr("Lms.infinite-scrolling-container"));
|
||||||
results->onRequestElements.connect(std::move(onRequestElementsFunc));
|
_tracks->onRequestElements.connect([this] { addSomeTracks(); });
|
||||||
|
|
||||||
_results.push_back(results.get());
|
|
||||||
_menu->addItem(str, std::move(results));
|
|
||||||
};
|
|
||||||
|
|
||||||
// same order as Mode!
|
|
||||||
addItem(Wt::WString::tr("Lms.Explore.releases"), Mode::Release, Wt::WString::tr("Lms.Explore.Releases.template.container"), [this]{ addSomeReleases(); });
|
|
||||||
addItem(Wt::WString::tr("Lms.Explore.artists"), Mode::Artist, Wt::WString::tr("Lms.infinite-scrolling-container"), [this]{ addSomeArtists(); });
|
|
||||||
addItem(Wt::WString::tr("Lms.Explore.tracks"), Mode::Track, Wt::WString::tr("Lms.infinite-scrolling-container"), [this]{ addSomeTracks(); });
|
|
||||||
|
|
||||||
_filters->updated().connect([=]
|
_filters->updated().connect([=]
|
||||||
{
|
{
|
||||||
@@ -76,24 +59,6 @@ namespace UserInterface
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t
|
|
||||||
SearchView::modeToIndex(Mode mode) const
|
|
||||||
{
|
|
||||||
return static_cast<std::size_t>(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
Wt::WMenuItem&
|
|
||||||
SearchView::getItemMenu(Mode mode) const
|
|
||||||
{
|
|
||||||
return *_menu->itemAt(modeToIndex(mode));
|
|
||||||
}
|
|
||||||
|
|
||||||
InfiniteScrollingContainer&
|
|
||||||
SearchView::getResultContainer(Mode mode) const
|
|
||||||
{
|
|
||||||
return *_results[modeToIndex(mode)];
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t
|
std::size_t
|
||||||
SearchView::getBatchSize(Mode mode) const
|
SearchView::getBatchSize(Mode mode) const
|
||||||
{
|
{
|
||||||
@@ -122,23 +87,21 @@ namespace UserInterface
|
|||||||
void
|
void
|
||||||
SearchView::refreshView()
|
SearchView::refreshView()
|
||||||
{
|
{
|
||||||
for (InfiniteScrollingContainer* results : _results)
|
_artists->clear();
|
||||||
results->clear();
|
_releases->clear();
|
||||||
|
_tracks->clear();
|
||||||
|
|
||||||
addSomeReleases();
|
|
||||||
addSomeArtists();
|
addSomeArtists();
|
||||||
|
addSomeReleases();
|
||||||
addSomeTracks();
|
addSomeTracks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SearchView::addSomeArtists()
|
SearchView::addSomeArtists()
|
||||||
{
|
|
||||||
InfiniteScrollingContainer& results {getResultContainer(Mode::Artist)};
|
|
||||||
|
|
||||||
{
|
{
|
||||||
using namespace Database;
|
using namespace Database;
|
||||||
|
|
||||||
const Range range {results.getCount(), getBatchSize(Mode::Artist)};
|
const Range range {_artists->getCount(), getBatchSize(Mode::Artist)};
|
||||||
const RangeResults<ArtistId> artistIds {_artistCollector.get(range)};
|
const RangeResults<ArtistId> artistIds {_artistCollector.get(range)};
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -147,25 +110,19 @@ namespace UserInterface
|
|||||||
for (const ArtistId artistId : artistIds.results)
|
for (const ArtistId artistId : artistIds.results)
|
||||||
{
|
{
|
||||||
const Artist::pointer artist {Artist::find(LmsApp->getDbSession(), artistId)};
|
const Artist::pointer artist {Artist::find(LmsApp->getDbSession(), artistId)};
|
||||||
results.add(ArtistListHelpers::createEntry(artist));
|
_artists->add(ArtistListHelpers::createEntry(artist));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
results.setHasMore(artistIds.moreResults);
|
_artists->setHasMore(artistIds.moreResults);
|
||||||
}
|
|
||||||
|
|
||||||
getItemMenu(Mode::Artist).setDisabled(results.getCount() == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SearchView::addSomeReleases()
|
SearchView::addSomeReleases()
|
||||||
{
|
|
||||||
InfiniteScrollingContainer& results {getResultContainer(Mode::Release)};
|
|
||||||
|
|
||||||
{
|
{
|
||||||
using namespace Database;
|
using namespace Database;
|
||||||
|
|
||||||
const Range range {results.getCount(), getBatchSize(Mode::Release)};
|
const Range range {_releases->getCount(), getBatchSize(Mode::Release)};
|
||||||
const RangeResults<ReleaseId> releaseIds {_releaseCollector.get(range)};
|
const RangeResults<ReleaseId> releaseIds {_releaseCollector.get(range)};
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -174,24 +131,19 @@ namespace UserInterface
|
|||||||
for (const ReleaseId releaseId : releaseIds.results)
|
for (const ReleaseId releaseId : releaseIds.results)
|
||||||
{
|
{
|
||||||
const Release::pointer release {Release::find(LmsApp->getDbSession(), releaseId)};
|
const Release::pointer release {Release::find(LmsApp->getDbSession(), releaseId)};
|
||||||
results.add(ReleaseListHelpers::createEntry(release));
|
_releases->add(ReleaseListHelpers::createEntry(release));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
results.setHasMore(releaseIds.moreResults);
|
_releases->setHasMore(releaseIds.moreResults);
|
||||||
}
|
|
||||||
|
|
||||||
getItemMenu(Mode::Release).setDisabled(results.getCount() == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SearchView::addSomeTracks()
|
SearchView::addSomeTracks()
|
||||||
{
|
|
||||||
InfiniteScrollingContainer& results {getResultContainer(Mode::Track)};
|
|
||||||
{
|
{
|
||||||
using namespace Database;
|
using namespace Database;
|
||||||
|
|
||||||
const Range range {results.getCount(), getBatchSize(Mode::Track)};
|
const Range range {_tracks->getCount(), getBatchSize(Mode::Track)};
|
||||||
const RangeResults<TrackId> trackIds {_trackCollector.get(range)};
|
const RangeResults<TrackId> trackIds {_trackCollector.get(range)};
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -200,14 +152,11 @@ namespace UserInterface
|
|||||||
for (const TrackId trackId : trackIds.results)
|
for (const TrackId trackId : trackIds.results)
|
||||||
{
|
{
|
||||||
const Track::pointer track {Track::find(LmsApp->getDbSession(), trackId)};
|
const Track::pointer track {Track::find(LmsApp->getDbSession(), trackId)};
|
||||||
results.add(TrackListHelpers::createEntry(track, tracksAction));
|
_tracks->add(TrackListHelpers::createEntry(track, tracksAction));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
results.setHasMore(trackIds.moreResults);
|
_tracks->setHasMore(trackIds.moreResults);
|
||||||
}
|
|
||||||
|
|
||||||
getItemMenu(Mode::Track).setDisabled(results.getCount() == 0);
|
|
||||||
}
|
}
|
||||||
} // namespace UserInterface
|
} // namespace UserInterface
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,7 @@
|
|||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <Wt/WContainerWidget.h>
|
#include <Wt/WStackedWidget.h>
|
||||||
#include <Wt/WMenu.h>
|
|
||||||
#include <Wt/WTemplate.h>
|
#include <Wt/WTemplate.h>
|
||||||
|
|
||||||
#include "ArtistCollector.hpp"
|
#include "ArtistCollector.hpp"
|
||||||
@@ -49,15 +48,11 @@ namespace UserInterface
|
|||||||
// same order as in the menu
|
// same order as in the menu
|
||||||
enum class Mode
|
enum class Mode
|
||||||
{
|
{
|
||||||
Release,
|
|
||||||
Artist,
|
Artist,
|
||||||
|
Release,
|
||||||
Track,
|
Track,
|
||||||
};
|
};
|
||||||
|
|
||||||
std::size_t modeToIndex(Mode mode) const;
|
|
||||||
Wt::WMenuItem& getItemMenu(Mode mode) const;
|
|
||||||
InfiniteScrollingContainer& getResultContainer(Mode mode) const;
|
|
||||||
|
|
||||||
static constexpr Mode _defaultMode {Mode::Release};
|
static constexpr Mode _defaultMode {Mode::Release};
|
||||||
static inline std::unordered_map<Mode, std::size_t> _batchSizes
|
static inline std::unordered_map<Mode, std::size_t> _batchSizes
|
||||||
{
|
{
|
||||||
@@ -75,16 +70,19 @@ namespace UserInterface
|
|||||||
std::size_t getMaxCount(Mode mode) const;
|
std::size_t getMaxCount(Mode mode) const;
|
||||||
|
|
||||||
void refreshView();
|
void refreshView();
|
||||||
void addSomeReleases();
|
|
||||||
void addSomeArtists();
|
void addSomeArtists();
|
||||||
|
void addSomeReleases();
|
||||||
void addSomeTracks();
|
void addSomeTracks();
|
||||||
|
|
||||||
Filters* _filters {};
|
Filters* _filters {};
|
||||||
Wt::WMenu* _menu {};
|
|
||||||
ReleaseCollector _releaseCollector;
|
|
||||||
ArtistCollector _artistCollector;
|
ArtistCollector _artistCollector;
|
||||||
|
ReleaseCollector _releaseCollector;
|
||||||
TrackCollector _trackCollector;
|
TrackCollector _trackCollector;
|
||||||
|
|
||||||
|
InfiniteScrollingContainer* _artists;
|
||||||
|
InfiniteScrollingContainer* _releases;
|
||||||
|
InfiniteScrollingContainer* _tracks;
|
||||||
|
|
||||||
std::vector<InfiniteScrollingContainer*> _results;
|
std::vector<InfiniteScrollingContainer*> _results;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user