Added a way to search for artists with a given role (composer, conductor, etC.)

This commit is contained in:
emeric
2023-09-15 22:40:15 +02:00
parent 5a1d18d26e
commit 7da171b639
8 changed files with 88 additions and 51 deletions
+8 -1
View File
@@ -16,7 +16,14 @@
</ul> </ul>
<div class="tab-content" id="myTabContent"> <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 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="artists" role="tabpanel" aria-labelledby="artists-tab">
<div class="row mb-3">
<div class="col-lg-3">
${link-type class="form-select"}
</div>
</div>
${artists}
</div>
<div class="tab-pane" id="tracks" role="tabpanel" aria-labelledby="tracks-tab">${tracks}</div> <div class="tab-pane" id="tracks" role="tabpanel" aria-labelledby="tracks-tab">${tracks}</div>
</div> </div>
</message> </message>
+1
View File
@@ -78,6 +78,7 @@ namespace UserInterface
Artist::FindParameters params; Artist::FindParameters params;
params.setClusters(getFilters().getClusterIds()); params.setClusters(getFilters().getClusterIds());
params.setKeywords(getSearchKeywords()); params.setKeywords(getSearchKeywords());
params.setLinkType(_linkType);
params.setSortMethod(ArtistSortMethod::BySortName); params.setSortMethod(ArtistSortMethod::BySortName);
params.setRange(range); params.setRange(range);
+42
View File
@@ -21,6 +21,10 @@
#include <Wt/WAnchor.h> #include <Wt/WAnchor.h>
#include "services/database/Artist.hpp" #include "services/database/Artist.hpp"
#include "services/database/Session.hpp"
#include "services/database/TrackArtistLink.hpp"
#include "utils/EnumSet.hpp"
#include "LmsApplication.hpp"
#include "Utils.hpp" #include "Utils.hpp"
namespace UserInterface::ArtistListHelpers namespace UserInterface::ArtistListHelpers
@@ -33,5 +37,43 @@ namespace UserInterface::ArtistListHelpers
return res; return res;
} }
std::unique_ptr<ArtistLinkTypesModel>
createArtistLinkTypesModel()
{
using namespace Database;
std::unique_ptr<ArtistLinkTypesModel> linkTypesModel {std::make_unique<ArtistLinkTypesModel>()};
EnumSet<TrackArtistLinkType> usedLinkTypes;
{
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
usedLinkTypes = TrackArtistLink::findUsedTypes(LmsApp->getDbSession());
}
auto addTypeIfUsed {[&](TrackArtistLinkType linkType, std::string_view stringKey)
{
if (!usedLinkTypes.contains(linkType))
return;
linkTypesModel->add(Wt::WString::trn(std::string {stringKey}, 2), linkType);
}};
// add default one first (none)
linkTypesModel->add(Wt::WString::tr("Lms.Explore.Artists.linktype-all"), std::nullopt);
// TODO: sort by translated strings
addTypeIfUsed(TrackArtistLinkType::Artist, "Lms.Explore.Artists.linktype-artist");
addTypeIfUsed(TrackArtistLinkType::ReleaseArtist, "Lms.Explore.Artists.linktype-releaseartist");
addTypeIfUsed(TrackArtistLinkType::Composer, "Lms.Explore.Artists.linktype-composer");
addTypeIfUsed(TrackArtistLinkType::Conductor, "Lms.Explore.Artists.linktype-conductor");
addTypeIfUsed(TrackArtistLinkType::Lyricist, "Lms.Explore.Artists.linktype-lyricist");
addTypeIfUsed(TrackArtistLinkType::Mixer, "Lms.Explore.Artists.linktype-mixer");
addTypeIfUsed(TrackArtistLinkType::Performer, "Lms.Explore.Artists.linktype-performer");
addTypeIfUsed(TrackArtistLinkType::Producer, "Lms.Explore.Artists.linktype-producer");
addTypeIfUsed(TrackArtistLinkType::Remixer, "Lms.Explore.Artists.linktype-remixer");
return linkTypesModel;
}
} }
+10 -2
View File
@@ -23,15 +23,23 @@
#include <Wt/WTemplate.h> #include <Wt/WTemplate.h>
#include "common/ValueStringModel.hpp"
#include "services/database/Object.hpp" #include "services/database/Object.hpp"
#include "services/database/Types.hpp"
namespace Database namespace Database
{ {
class Artist; class Artist;
} }
namespace UserInterface::ArtistListHelpers namespace UserInterface
{ {
std::unique_ptr<Wt::WTemplate> createEntry(const Database::ObjectPtr<Database::Artist>& artist); using ArtistLinkTypesModel = ValueStringModel<std::optional<Database::TrackArtistLinkType>>;
namespace ArtistListHelpers
{
std::unique_ptr<Wt::WTemplate> createEntry(const Database::ObjectPtr<Database::Artist>& artist);
std::unique_ptr<ArtistLinkTypesModel> createArtistLinkTypesModel();
}
} }
+3 -44
View File
@@ -24,10 +24,8 @@
#include "services/database/Artist.hpp" #include "services/database/Artist.hpp"
#include "services/database/Session.hpp" #include "services/database/Session.hpp"
#include "services/database/TrackArtistLink.hpp" #include "services/database/TrackArtistLink.hpp"
#include "utils/EnumSet.hpp"
#include "utils/Logger.hpp" #include "utils/Logger.hpp"
#include "common/ValueStringModel.hpp"
#include "common/InfiniteScrollingContainer.hpp" #include "common/InfiniteScrollingContainer.hpp"
#include "ArtistListHelpers.hpp" #include "ArtistListHelpers.hpp"
#include "Filters.hpp" #include "Filters.hpp"
@@ -37,8 +35,6 @@ using namespace Database;
namespace UserInterface { namespace UserInterface {
using ArtistLinkModel = ValueStringModel<std::optional<TrackArtistLinkType>>;
Artists::Artists(Filters& filters) Artists::Artists(Filters& filters)
: Wt::WTemplate {Wt::WString::tr("Lms.Explore.Artists.template")} : Wt::WTemplate {Wt::WString::tr("Lms.Explore.Artists.template")}
, _artistCollector {filters, _defaultMode, _maxCount} , _artistCollector {filters, _defaultMode, _maxCount}
@@ -71,18 +67,17 @@ Artists::Artists(Filters& filters)
bindMenuItem("all", Wt::WString::tr("Lms.Explore.all"), ArtistCollector::Mode::All); bindMenuItem("all", Wt::WString::tr("Lms.Explore.all"), ArtistCollector::Mode::All);
_linkType = bindNew<Wt::WComboBox>("link-type"); _linkType = bindNew<Wt::WComboBox>("link-type");
_linkType->setModel(std::make_shared<ArtistLinkModel>()); _linkType->setModel(ArtistListHelpers::createArtistLinkTypesModel());
_linkType->changed().connect([this] _linkType->changed().connect([this]
{ {
const std::optional<TrackArtistLinkType> linkType {static_cast<ArtistLinkModel*>(_linkType->model().get())->getValue(_linkType->currentIndex())}; const std::optional<TrackArtistLinkType> linkType {static_cast<ArtistLinkTypesModel*>(_linkType->model().get())->getValue(_linkType->currentIndex())};
refreshView(linkType); refreshView(linkType);
}); });
refreshArtistLinkTypes();
LmsApp->getScannerEvents().scanComplete.connect(this, [this](const Scanner::ScanStats& stats) LmsApp->getScannerEvents().scanComplete.connect(this, [this](const Scanner::ScanStats& stats)
{ {
if (stats.nbChanges()) if (stats.nbChanges())
refreshArtistLinkTypes(); _linkType->setModel(ArtistListHelpers::createArtistLinkTypesModel());
}); });
_container = bindNew<InfiniteScrollingContainer>("artists", Wt::WString::tr("Lms.Explore.Artists.template.container")); _container = bindNew<InfiniteScrollingContainer>("artists", Wt::WString::tr("Lms.Explore.Artists.template.container"));
@@ -120,42 +115,6 @@ Artists::refreshView(std::optional<TrackArtistLinkType> linkType)
refreshView(); refreshView();
} }
void
Artists::refreshArtistLinkTypes()
{
std::shared_ptr<ArtistLinkModel> linkTypeModel {std::static_pointer_cast<ArtistLinkModel>(_linkType->model())};
EnumSet<TrackArtistLinkType> usedLinkTypes;
{
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
usedLinkTypes = TrackArtistLink::findUsedTypes(LmsApp->getDbSession());
}
auto addTypeIfUsed {[&](TrackArtistLinkType linkType, std::string_view stringKey)
{
if (!usedLinkTypes.contains(linkType))
return;
linkTypeModel->add(Wt::WString::trn(std::string {stringKey}, 2), linkType);
}};
linkTypeModel->clear();
// add default one first (none)
linkTypeModel->add(Wt::WString::tr("Lms.Explore.Artists.linktype-all"), std::nullopt);
// TODO: sort by translated strings
addTypeIfUsed(TrackArtistLinkType::Artist, "Lms.Explore.Artists.linktype-artist");
addTypeIfUsed(TrackArtistLinkType::ReleaseArtist, "Lms.Explore.Artists.linktype-releaseartist");
addTypeIfUsed(TrackArtistLinkType::Composer, "Lms.Explore.Artists.linktype-composer");
addTypeIfUsed(TrackArtistLinkType::Conductor, "Lms.Explore.Artists.linktype-conductor");
addTypeIfUsed(TrackArtistLinkType::Lyricist, "Lms.Explore.Artists.linktype-lyricist");
addTypeIfUsed(TrackArtistLinkType::Mixer, "Lms.Explore.Artists.linktype-mixer");
addTypeIfUsed(TrackArtistLinkType::Performer, "Lms.Explore.Artists.linktype-performer");
addTypeIfUsed(TrackArtistLinkType::Producer, "Lms.Explore.Artists.linktype-producer");
addTypeIfUsed(TrackArtistLinkType::Remixer, "Lms.Explore.Artists.linktype-remixer");
}
void void
Artists::addSome() Artists::addSome()
{ {
-1
View File
@@ -42,7 +42,6 @@ namespace UserInterface
void refreshView(); void refreshView();
void refreshView(ArtistCollector::Mode mode); void refreshView(ArtistCollector::Mode mode);
void refreshView(std::optional<Database::TrackArtistLinkType> linkType); void refreshView(std::optional<Database::TrackArtistLinkType> linkType);
void refreshArtistLinkTypes();
void addSome(); void addSome();
static constexpr std::size_t _batchSize {30}; static constexpr std::size_t _batchSize {30};
+15
View File
@@ -48,6 +48,14 @@ namespace UserInterface
_artists = bindNew<InfiniteScrollingContainer>("artists", Wt::WString::tr("Lms.Explore.Artists.template.container")); _artists = bindNew<InfiniteScrollingContainer>("artists", Wt::WString::tr("Lms.Explore.Artists.template.container"));
_artists->onRequestElements.connect([this] { addSomeArtists(); }); _artists->onRequestElements.connect([this] { addSomeArtists(); });
_artistLinkType = bindNew<Wt::WComboBox>("link-type");
_artistLinkType->setModel(ArtistListHelpers::createArtistLinkTypesModel());
_artistLinkType->changed().connect([this]
{
const std::optional<TrackArtistLinkType> linkType {static_cast<ArtistLinkTypesModel*>(_artistLinkType->model().get())->getValue(_artistLinkType->currentIndex())};
refreshView(linkType);
});
_releases = bindNew<InfiniteScrollingContainer>("releases", Wt::WString::tr("Lms.Explore.Releases.template.container")); _releases = bindNew<InfiniteScrollingContainer>("releases", Wt::WString::tr("Lms.Explore.Releases.template.container"));
_releases->onRequestElements.connect([this] { addSomeReleases(); }); _releases->onRequestElements.connect([this] { addSomeReleases(); });
@@ -76,6 +84,13 @@ namespace UserInterface
return it->second; return it->second;
} }
void
SearchView::refreshView(std::optional<TrackArtistLinkType> linkType)
{
_artistCollector.setArtistLinkType(linkType);
refreshView();
}
void void
SearchView::refreshView(const Wt::WString& searchText) SearchView::refreshView(const Wt::WString& searchText)
{ {
+9 -3
View File
@@ -19,11 +19,14 @@
#pragma once #pragma once
#include <optional>
#include <unordered_map> #include <unordered_map>
#include <Wt/WComboBox.h>
#include <Wt/WStackedWidget.h> #include <Wt/WStackedWidget.h>
#include <Wt/WTemplate.h> #include <Wt/WTemplate.h>
#include "services/database/Types.hpp"
#include "ArtistCollector.hpp" #include "ArtistCollector.hpp"
#include "ReleaseCollector.hpp" #include "ReleaseCollector.hpp"
#include "TrackCollector.hpp" #include "TrackCollector.hpp"
@@ -67,6 +70,7 @@ namespace UserInterface
std::size_t getMaxCount(Mode mode) const; std::size_t getMaxCount(Mode mode) const;
void refreshView(); void refreshView();
void refreshView(std::optional<Database::TrackArtistLinkType> linkType);
void addSomeArtists(); void addSomeArtists();
void addSomeReleases(); void addSomeReleases();
void addSomeTracks(); void addSomeTracks();
@@ -77,9 +81,11 @@ namespace UserInterface
ReleaseCollector _releaseCollector; ReleaseCollector _releaseCollector;
TrackCollector _trackCollector; TrackCollector _trackCollector;
InfiniteScrollingContainer* _artists; InfiniteScrollingContainer* _artists {};
InfiniteScrollingContainer* _releases; InfiniteScrollingContainer* _releases {};
InfiniteScrollingContainer* _tracks; InfiniteScrollingContainer* _tracks {};
Wt::WComboBox* _artistLinkType {};
std::vector<InfiniteScrollingContainer*> _results; std::vector<InfiniteScrollingContainer*> _results;
}; };