Added clusters for track list
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
<div class="mb-3">
|
||||
<h2>${name}</h2>
|
||||
<div class="small text-muted">${track-count} · ${duration}</div>
|
||||
${clusters class="mb-2"}
|
||||
<div class="btn-group">
|
||||
${play-btn class="btn btn-primary"}
|
||||
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false"/>
|
||||
|
||||
@@ -466,6 +466,57 @@ TrackList::getClusters() const
|
||||
return std::vector<Cluster::pointer>(res.begin(), res.end());
|
||||
}
|
||||
|
||||
std::vector<std::vector<Cluster::pointer>>
|
||||
TrackList::getClusterGroups(const std::vector<ClusterType::pointer>& clusterTypes, std::size_t size) const
|
||||
{
|
||||
assert(session());
|
||||
std::vector<std::vector<Cluster::pointer>> res;
|
||||
|
||||
if (clusterTypes.empty())
|
||||
return res;
|
||||
|
||||
auto query {session()->query<Wt::Dbo::ptr<Cluster>>("SELECT c from cluster c")};
|
||||
|
||||
query.join("track t ON c.id = t_c.cluster_id")
|
||||
.join("track_cluster t_c ON t_c.track_id = t.id")
|
||||
.join("cluster_type c_type ON c.cluster_type_id = c_type.id")
|
||||
.join("tracklist_entry t_l_e ON t_l_e.track_id = t.id")
|
||||
.join("tracklist t_l ON t_l.id = t_l_e.tracklist_id")
|
||||
.where("t_l.id = ?").bind(getId());
|
||||
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "c_type.id IN (";
|
||||
bool first {true};
|
||||
for (auto clusterType : clusterTypes)
|
||||
{
|
||||
if (!first)
|
||||
oss << ", ";
|
||||
oss << "?";
|
||||
query.bind(clusterType ->getId());
|
||||
first = false;
|
||||
}
|
||||
oss << ")";
|
||||
query.where(oss.str());
|
||||
}
|
||||
query.groupBy("c.id");
|
||||
query.orderBy("COUNT(c.id) DESC");
|
||||
|
||||
auto queryRes {query.resultList()};
|
||||
|
||||
std::map<ClusterTypeId, std::vector<Cluster::pointer>> clustersByType;
|
||||
for (const Wt::Dbo::ptr<Cluster>& cluster : queryRes)
|
||||
{
|
||||
if (clustersByType[cluster->getType()->getId()].size() < size)
|
||||
clustersByType[cluster->getType()->getId()].push_back(cluster);
|
||||
}
|
||||
|
||||
for (const auto& [clusterTypeId, clusters] : clustersByType)
|
||||
res.push_back(clusters);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool
|
||||
TrackList::hasTrack(TrackId trackId) const
|
||||
{
|
||||
|
||||
@@ -38,6 +38,7 @@ namespace Database {
|
||||
|
||||
class Artist;
|
||||
class Cluster;
|
||||
class ClusterType;
|
||||
class Release;
|
||||
class Session;
|
||||
class Track;
|
||||
@@ -107,6 +108,7 @@ class TrackList : public Object<TrackList, TrackListId>
|
||||
|
||||
// Get clusters, order by occurence
|
||||
std::vector<ObjectPtr<Cluster>> getClusters() const;
|
||||
std::vector<std::vector<ObjectPtr<Cluster>>> getClusterGroups(const std::vector<ObjectPtr<ClusterType>>& clusterTypes, std::size_t size) const;
|
||||
|
||||
bool hasTrack(TrackId trackId) const;
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
#include <Wt/WPushButton.h>
|
||||
|
||||
#include "services/database/Cluster.hpp"
|
||||
#include "services/database/ScanSettings.hpp"
|
||||
#include "services/database/Session.hpp"
|
||||
#include "services/database/Track.hpp"
|
||||
#include "services/database/TrackList.hpp"
|
||||
@@ -52,6 +54,7 @@ namespace UserInterface
|
||||
{
|
||||
TrackList::TrackList(Filters& filters)
|
||||
: Template {Wt::WString::tr("Lms.Explore.TrackList.template")}
|
||||
, _filters {filters}
|
||||
{
|
||||
addFunction("tr", &Wt::WTemplate::Functions::tr);
|
||||
addFunction("id", &Wt::WTemplate::Functions::id);
|
||||
@@ -61,7 +64,7 @@ namespace UserInterface
|
||||
refreshView();
|
||||
});
|
||||
|
||||
filters.updated().connect([this]
|
||||
_filters.updated().connect([this]
|
||||
{
|
||||
refreshView();
|
||||
});
|
||||
@@ -93,6 +96,25 @@ namespace UserInterface
|
||||
bindString("duration", Utils::durationToString(trackList->getDuration()));
|
||||
bindString("track-count", Wt::WString::trn("Lms.Explore.TrackList.track-count", trackList->getCount()).arg(trackList->getCount()));
|
||||
|
||||
Wt::WContainerWidget* clusterContainers {bindNew<Wt::WContainerWidget>("clusters")};
|
||||
{
|
||||
const auto clusterTypes {ScanSettings::get(LmsApp->getDbSession())->getClusterTypes()};
|
||||
const auto clusterGroups {trackList->getClusterGroups(clusterTypes, 3)};
|
||||
|
||||
for (const auto& clusters : clusterGroups)
|
||||
{
|
||||
for (const Database::Cluster::pointer& cluster : clusters)
|
||||
{
|
||||
const ClusterId clusterId {cluster->getId()};
|
||||
Wt::WInteractWidget* entry {clusterContainers->addWidget(Utils::createCluster(clusterId))};
|
||||
entry->clicked().connect([=]
|
||||
{
|
||||
_filters.add(clusterId);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bindNew<Wt::WPushButton>("play-btn", Wt::WString::tr("Lms.Explore.play"), Wt::TextFormat::XHTML)
|
||||
->clicked().connect([=]
|
||||
{
|
||||
@@ -163,6 +185,7 @@ namespace UserInterface
|
||||
auto transaction {LmsApp->getDbSession().createSharedTransaction()};
|
||||
|
||||
Database::Track::FindParameters params;
|
||||
params.setClusters(_filters.getClusterIds());
|
||||
params.setTrackList(_trackListId);
|
||||
params.setSortMethod(Database::TrackSortMethod::TrackList);
|
||||
params.setRange({static_cast<std::size_t>(_container->getCount()), _batchSize});
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace UserInterface
|
||||
static constexpr std::size_t _batchSize {6};
|
||||
static constexpr std::size_t _maxCount {8000};
|
||||
|
||||
Filters& _filters;
|
||||
Database::TrackListId _trackListId;
|
||||
InfiniteScrollingContainer* _container {};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user