Added a way to search for artists with a given role (composer, conductor, etC.)
This commit is contained in:
+8
-1
@@ -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>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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};
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user