Added a way to filter artist by type (album artist, track artist, all artits). Fixes #19

This commit is contained in:
emeric
2020-01-22 21:31:11 +01:00
parent e384cdd021
commit 6950616466
10 changed files with 69 additions and 15 deletions
+11 -4
View File
@@ -6,10 +6,17 @@
<div class="page-header">
<h2>${tr:Lms.Explore.artists}</h2>
</div>
<div class="form-group">
<div class="input-group">
<span class="input-group-addon"><i class="fa fa-search"></i></span>
${search}
<div class="row">
<div class="col-xs-12 col-sm-3">
<div class="Lms-explore-artists-input">
${link-type}
</div>
</div>
<div class="col-xs-12 col-sm-9">
<div class="input-group Lms-explore-artists-input">
<span class="input-group-addon"><i class="fa fa-search"></i></span>
${search}
</div>
</div>
</div>
${artists}
+3
View File
@@ -115,6 +115,9 @@
<message id="Lms.Explore.ArtistInfo.similar-artists">Similar artists</message>
<!--Explore:Artists-->
<message id="Lms.Explore.Artists.linktype-all">All artists</message>
<message id="Lms.Explore.Artists.linktype-artist">Track artists</message>
<message id="Lms.Explore.Artists.linktype-releaseartist">Album artists</message>
<message id="Lms.Explore.ArtistsInfo.recently-added">Recently added</message>
<message id="Lms.Explore.ArtistsInfo.most-played">Top artists</message>
+3
View File
@@ -115,6 +115,9 @@
<message id="Lms.Explore.ArtistInfo.similar-artists">Artistes similaires</message>
<!--Explore:Artists-->
<message id="Lms.Explore.Artists.linktype-all">Tous les artistes</message>
<message id="Lms.Explore.Artists.linktype-artist">Artiste de piste</message>
<message id="Lms.Explore.Artists.linktype-releaseartist">Artiste d'album</message>
<message id="Lms.Explore.ArtistsInfo.recently-added">Ajouts récents</message>
<message id="Lms.Explore.ArtistsInfo.most-played">Artistes populaires</message>
+4
View File
@@ -232,6 +232,10 @@ a:hover {
font-style: normal;
}
.Lms-explore-artists-input {
margin-bottom: 10px;
}
.Lms-explore-artist-entry {
padding-top: 8px;
padding-bottom: 8px;
+1 -1
View File
@@ -1387,7 +1387,7 @@ handleSearchRequestCommon(RequestContext& context, bool id3)
bool more;
{
auto artists {Artist::getByFilter(context.dbSession, {}, keywords, artistOffset, artistCount, more)};
auto artists {Artist::getByFilter(context.dbSession, {}, keywords, {}, artistOffset, artistCount, more)};
for (const Artist::pointer& artist : artists)
searchResult2Node.addArrayChild("artist", artistToResponseNode(user, artist, id3));
}
+17 -9
View File
@@ -108,7 +108,8 @@ static
Wt::Dbo::Query<Artist::pointer>
getQuery(Session& session,
const std::set<IdType>& clusterIds,
const std::vector<std::string>& keywords)
const std::vector<std::string>& keywords,
std::optional<TrackArtistLink::Type> linkType)
{
session.checkSharedLocked();
@@ -120,16 +121,22 @@ getQuery(Session& session,
for (auto keyword : keywords)
where.And(WhereClause("a.name LIKE ?")).bind("%%" + keyword + "%%");
if (!clusterIds.empty())
if (!clusterIds.empty() || linkType)
{
oss << " INNER JOIN track t ON t.id = t_a_l.track_id INNER JOIN track_artist_link t_a_l ON t_a_l.artist_id = a.id INNER JOIN cluster c ON c.id = t_c.cluster_id INNER JOIN track_cluster t_c ON t_c.track_id = t.id";
oss << " INNER JOIN track t ON t.id = t_a_l.track_id INNER JOIN track_artist_link t_a_l ON t_a_l.artist_id = a.id";
WhereClause clusterClause;
if (!clusterIds.empty())
{
oss << " INNER JOIN cluster c ON c.id = t_c.cluster_id INNER JOIN track_cluster t_c ON t_c.track_id = t.id";
WhereClause clusterClause;
for (auto id : clusterIds)
clusterClause.Or(WhereClause("c.id = ?")).bind(std::to_string(id));
for (auto id : clusterIds)
clusterClause.Or(WhereClause("c.id = ?")).bind(std::to_string(id));
where.And(clusterClause);
where.And(clusterClause);
}
if (linkType)
where.And(WhereClause {"t_a_l.type = ?"}.bind(std::to_string(static_cast<int>(*linkType))));
}
oss << " " << where.get();
@@ -155,19 +162,20 @@ Artist::getByClusters(Session& session, const std::set<IdType>& clusters)
session.checkSharedLocked();
bool more;
return getByFilter(session, clusters, {}, {}, {}, more);
return getByFilter(session, clusters, {}, {}, {}, {}, more);
}
std::vector<Artist::pointer>
Artist::getByFilter(Session& session,
const std::set<IdType>& clusters,
const std::vector<std::string>& keywords,
std::optional<TrackArtistLink::Type> linkType,
std::optional<std::size_t> offset,
std::optional<std::size_t> size,
bool& moreResults)
{
session.checkSharedLocked();
Wt::Dbo::collection<Artist::pointer> collection = getQuery(session, clusters, keywords)
Wt::Dbo::collection<Artist::pointer> collection = getQuery(session, clusters, keywords, linkType)
.limit(size ? static_cast<int>(*size) + 1 : -1)
.offset(offset ? static_cast<int>(*offset) : -1);
+1
View File
@@ -57,6 +57,7 @@ class Artist : public Wt::Dbo::Dbo<Artist>
static std::vector<pointer> getByFilter(Session& session,
const std::set<IdType>& clusters, // if non empty, at least one artist that belongs to these clusters
const std::vector<std::string>& keywords, // if non empty, name must match all of these keywords
std::optional<TrackArtistLink::Type> linkType, // if set, only artists that have produced at least one track with this link type
std::optional<std::size_t> offset,
std::optional<std::size_t> size,
bool& moreExpected);
+17 -1
View File
@@ -19,13 +19,15 @@
#include "ArtistsView.hpp"
#include <optional>
#include <Wt/WAnchor.h>
#include <Wt/WLineEdit.h>
#include <Wt/WLocalDateTime.h>
#include <Wt/WTemplate.h>
#include "common/ValueStringModel.hpp"
#include "database/Artist.hpp"
#include "utils/Logger.hpp"
#include "utils/Utils.hpp"
@@ -36,6 +38,8 @@ using namespace Database;
namespace UserInterface {
using ArtistLinkModel = ValueStringModel<std::optional<TrackArtistLink::Type>>;
Artists::Artists(Filters* filters)
: Wt::WTemplate(Wt::WString::tr("Lms.Explore.Artists.template")),
_filters(filters)
@@ -46,6 +50,16 @@ Artists::Artists(Filters* filters)
_search->setPlaceholderText(Wt::WString::tr("Lms.Explore.search-placeholder"));
_search->textInput().connect(this, &Artists::refresh);
_linkType = bindNew<Wt::WComboBox>("link-type");
{
auto linkTypeModel {std::make_shared<ArtistLinkModel>()};
linkTypeModel->add(Wt::WString::tr("Lms.Explore.Artists.linktype-all"), {});
linkTypeModel->add(Wt::WString::tr("Lms.Explore.Artists.linktype-artist"), TrackArtistLink::Type::Artist);
linkTypeModel->add(Wt::WString::tr("Lms.Explore.Artists.linktype-releaseartist"), TrackArtistLink::Type::ReleaseArtist);
_linkType->setModel(linkTypeModel);
}
_linkType->changed().connect(this, &Artists::refresh);
_container = bindNew<Wt::WContainerWidget>("artists");
_showMore = bindNew<Wt::WPushButton>("show-more", Wt::WString::tr("Lms.Explore.show-more"));
@@ -72,6 +86,7 @@ Artists::addSome()
auto searchKeywords = splitString(_search->text().toUTF8(), " ");
auto clusterIds = _filters->getClusterIds();
auto linkModel = static_cast<ArtistLinkModel*>(_linkType->model().get());
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
@@ -79,6 +94,7 @@ Artists::addSome()
const std::vector<Artist::pointer> artists {Artist::getByFilter(LmsApp->getDbSession(),
clusterIds,
searchKeywords,
linkModel->getValue(_linkType->currentIndex()),
_container->count(), 20, moreResults)};
for (const auto& artist : artists)
+2
View File
@@ -19,6 +19,7 @@
#pragma once
#include <Wt/WComboBox.h>
#include <Wt/WContainerWidget.h>
#include <Wt/WLineEdit.h>
#include <Wt/WPushButton.h>
@@ -46,6 +47,7 @@ class Artists : public Wt::WTemplate
Filters* _filters;
Wt::WPushButton* _showMore;
Wt::WLineEdit* _search;
Wt::WComboBox* _linkType;
Wt::WContainerWidget* _container;
};
+10
View File
@@ -306,6 +306,16 @@ testSingleTrackSingleArtistMultiRoles(Session& session)
CHECK(Artist::getAllOrphans(session).empty());
}
{
auto transaction {session.createSharedTransaction()};
bool hasMore{};
CHECK(Artist::getByFilter(session, {}, {}, {}, {}, {}, hasMore).size() == 1);
CHECK(Artist::getByFilter(session, {}, {}, TrackArtistLink::Type::Artist, {}, {}, hasMore).size() == 1);
CHECK(Artist::getByFilter(session, {}, {}, TrackArtistLink::Type::ReleaseArtist, {}, {}, hasMore).size() == 1);
CHECK(Artist::getByFilter(session, {}, {}, TrackArtistLink::Type::Writer, {}, {}, hasMore).size() == 1);
CHECK(Artist::getByFilter(session, {}, {}, TrackArtistLink::Type::Composer, {}, {}, hasMore).empty());
}
{
auto transaction {session.createSharedTransaction()};