Added Tracks information panel
This commit is contained in:
+2
-1
@@ -41,7 +41,8 @@ lms_approot_DATA = \
|
|||||||
approot/releasesinfo.xml \
|
approot/releasesinfo.xml \
|
||||||
approot/settings.xml \
|
approot/settings.xml \
|
||||||
approot/templates.xml \
|
approot/templates.xml \
|
||||||
approot/tracks.xml
|
approot/tracks.xml \
|
||||||
|
approot/tracksinfo.xml
|
||||||
|
|
||||||
sysconf_DATA = \
|
sysconf_DATA = \
|
||||||
$(top_srcdir)/conf/lms.conf
|
$(top_srcdir)/conf/lms.conf
|
||||||
|
|||||||
@@ -81,6 +81,11 @@
|
|||||||
<message id="Lms.Explore.ReleasesInfo.recently-added">Recently added</message>
|
<message id="Lms.Explore.ReleasesInfo.recently-added">Recently added</message>
|
||||||
<message id="Lms.Explore.ReleasesInfo.most-played">Top releases</message>
|
<message id="Lms.Explore.ReleasesInfo.most-played">Top releases</message>
|
||||||
|
|
||||||
|
<!--Explore:Tracks-->
|
||||||
|
<message id="Lms.Explore.TracksInfo.recently-added">Recently added</message>
|
||||||
|
<message id="Lms.Explore.TracksInfo.most-played">Top tracks</message>
|
||||||
|
|
||||||
|
|
||||||
<!--Playque-->
|
<!--Playque-->
|
||||||
<message id="Lms.PlayQueue.nb-tracks">{1} tracks</message>
|
<message id="Lms.PlayQueue.nb-tracks">{1} tracks</message>
|
||||||
<message id="Lms.PlayQueue.nb-tracks-added">Added {1} tracks</message>
|
<message id="Lms.PlayQueue.nb-tracks-added">Added {1} tracks</message>
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<messages xmlns:if="Wt.WTemplate.conditions">
|
||||||
|
<!--FORMS message blocks-->
|
||||||
|
|
||||||
|
<message id="Lms.Explore.TracksInfo.template">
|
||||||
|
<h3>${tr:Lms.Explore.TracksInfo.most-played}</h3>
|
||||||
|
${most-played}
|
||||||
|
<h3>${tr:Lms.Explore.TracksInfo.recently-added}</h3>
|
||||||
|
${recently-added}
|
||||||
|
</message>
|
||||||
|
|
||||||
|
<message id="Lms.Explore.TracksInfo.template.entry">
|
||||||
|
<div class="row Lms-explore-tracksinfo-entry Lms-vertical-align">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
${name}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</message>
|
||||||
|
|
||||||
|
</messages>
|
||||||
@@ -169,6 +169,16 @@ a:hover {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Lms-explore-tracksinfo-entry {
|
||||||
|
min-height: 28px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Lms-explore-tracksinfo-entry:hover {
|
||||||
|
background-color: lightgrey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.Lms-explore-btn {
|
.Lms-explore-btn {
|
||||||
font-size: 22px !important;
|
font-size: 22px !important;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|||||||
+3
-2
@@ -31,13 +31,14 @@ lms_SOURCES = \
|
|||||||
$(srcdir)/ui/admin/UsersView.cpp \
|
$(srcdir)/ui/admin/UsersView.cpp \
|
||||||
$(srcdir)/ui/common/Validators.cpp \
|
$(srcdir)/ui/common/Validators.cpp \
|
||||||
$(srcdir)/ui/explore/ArtistView.cpp \
|
$(srcdir)/ui/explore/ArtistView.cpp \
|
||||||
$(srcdir)/ui/explore/ArtistsView.cpp \
|
|
||||||
$(srcdir)/ui/explore/ArtistsInfoView.cpp \
|
$(srcdir)/ui/explore/ArtistsInfoView.cpp \
|
||||||
|
$(srcdir)/ui/explore/ArtistsView.cpp \
|
||||||
$(srcdir)/ui/explore/Explore.cpp \
|
$(srcdir)/ui/explore/Explore.cpp \
|
||||||
$(srcdir)/ui/explore/Filters.cpp \
|
$(srcdir)/ui/explore/Filters.cpp \
|
||||||
$(srcdir)/ui/explore/ReleasesView.cpp \
|
|
||||||
$(srcdir)/ui/explore/ReleasesInfoView.cpp \
|
$(srcdir)/ui/explore/ReleasesInfoView.cpp \
|
||||||
|
$(srcdir)/ui/explore/ReleasesView.cpp \
|
||||||
$(srcdir)/ui/explore/ReleaseView.cpp \
|
$(srcdir)/ui/explore/ReleaseView.cpp \
|
||||||
|
$(srcdir)/ui/explore/TracksInfoView.cpp \
|
||||||
$(srcdir)/ui/explore/TracksView.cpp \
|
$(srcdir)/ui/explore/TracksView.cpp \
|
||||||
$(srcdir)/ui/resource/ImageResource.cpp \
|
$(srcdir)/ui/resource/ImageResource.cpp \
|
||||||
$(srcdir)/ui/resource/TranscodeResource.cpp \
|
$(srcdir)/ui/resource/TranscodeResource.cpp \
|
||||||
|
|||||||
@@ -96,6 +96,17 @@ Track::getChecksumDuplicates(Wt::Dbo::Session& session)
|
|||||||
return std::vector<pointer>(res.begin(), res.end());
|
return std::vector<pointer>(res.begin(), res.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<Track::pointer>
|
||||||
|
Track::getLastAdded(Wt::Dbo::Session& session, Wt::WDateTime after, int limit)
|
||||||
|
{
|
||||||
|
Wt::Dbo::collection<Track::pointer> res = session.find<Track>()
|
||||||
|
.where("file_added > ?").bind(after)
|
||||||
|
.orderBy("file_added DESC")
|
||||||
|
.limit(limit);
|
||||||
|
|
||||||
|
return std::vector<pointer>(res.begin(), res.end());
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<Cluster::pointer>
|
std::vector<Cluster::pointer>
|
||||||
Track::getClusters(void) const
|
Track::getClusters(void) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
#include <Wt/Dbo/Dbo.h>
|
#include <Wt/Dbo/Dbo.h>
|
||||||
|
|
||||||
#include <Wt/WDateTime.h>
|
#include <Wt/WDateTime.h>
|
||||||
|
|
||||||
#include "Types.hpp"
|
#include "Types.hpp"
|
||||||
@@ -74,6 +73,7 @@ class Track : public Wt::Dbo::Dbo<Track>
|
|||||||
static std::vector<boost::filesystem::path> getAllPaths(Wt::Dbo::Session& session); // nested transaction
|
static std::vector<boost::filesystem::path> getAllPaths(Wt::Dbo::Session& session); // nested transaction
|
||||||
static std::vector<pointer> getMBIDDuplicates(Wt::Dbo::Session& session);
|
static std::vector<pointer> getMBIDDuplicates(Wt::Dbo::Session& session);
|
||||||
static std::vector<pointer> getChecksumDuplicates(Wt::Dbo::Session& session);
|
static std::vector<pointer> getChecksumDuplicates(Wt::Dbo::Session& session);
|
||||||
|
static std::vector<pointer> getLastAdded(Wt::Dbo::Session& session, Wt::WDateTime after, int size = 1);
|
||||||
|
|
||||||
// Create utility
|
// Create utility
|
||||||
static pointer create(Wt::Dbo::Session& session, const boost::filesystem::path& p);
|
static pointer create(Wt::Dbo::Session& session, const boost::filesystem::path& p);
|
||||||
|
|||||||
@@ -222,6 +222,21 @@ TrackList::getTopReleases(int limit) const
|
|||||||
return std::vector<Release::pointer>(res.begin(), res.end());
|
return std::vector<Release::pointer>(res.begin(), res.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<Track::pointer>
|
||||||
|
TrackList::getTopTracks(int limit) const
|
||||||
|
{
|
||||||
|
assert(session());
|
||||||
|
assert(IdIsValid(self()->id()));
|
||||||
|
|
||||||
|
Wt::Dbo::collection<Track::pointer> res = session()->query<Track::pointer>("SELECT t from track t INNER JOIN tracklist_entry p_e ON p_e.track_id = t.id INNER JOIN tracklist p ON p.id = p_e.tracklist_id")
|
||||||
|
.where("p.id = ?").bind(self()->id())
|
||||||
|
.groupBy("t.id")
|
||||||
|
.orderBy("COUNT(t.id) DESC")
|
||||||
|
.limit(limit);
|
||||||
|
|
||||||
|
return std::vector<Track::pointer>(res.begin(), res.end());
|
||||||
|
}
|
||||||
|
|
||||||
TrackListEntry::TrackListEntry(Wt::Dbo::ptr<Track> track, Wt::Dbo::ptr<TrackList> tracklist)
|
TrackListEntry::TrackListEntry(Wt::Dbo::ptr<Track> track, Wt::Dbo::ptr<TrackList> tracklist)
|
||||||
: _track(track),
|
: _track(track),
|
||||||
_tracklist(tracklist)
|
_tracklist(tracklist)
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ class TrackList : public Wt::Dbo::Dbo<TrackList>
|
|||||||
// Stats utility
|
// Stats utility
|
||||||
std::vector<Wt::Dbo::ptr<Artist>> getTopArtists(int limit = 1) const;
|
std::vector<Wt::Dbo::ptr<Artist>> getTopArtists(int limit = 1) const;
|
||||||
std::vector<Wt::Dbo::ptr<Release>> getTopReleases(int limit = 1) const;
|
std::vector<Wt::Dbo::ptr<Release>> getTopReleases(int limit = 1) const;
|
||||||
|
std::vector<Wt::Dbo::ptr<Track>> getTopTracks(int limit = 1) const;
|
||||||
|
|
||||||
// Search utility
|
// Search utility
|
||||||
static pointer get(Wt::Dbo::Session& session, std::string name, Wt::Dbo::ptr<User> user);
|
static pointer get(Wt::Dbo::Session& session, std::string name, Wt::Dbo::ptr<User> user);
|
||||||
|
|||||||
@@ -106,8 +106,9 @@ LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnecti
|
|||||||
messageResourceBundle().use(appRoot() + "releases");
|
messageResourceBundle().use(appRoot() + "releases");
|
||||||
messageResourceBundle().use(appRoot() + "releasesinfo");
|
messageResourceBundle().use(appRoot() + "releasesinfo");
|
||||||
messageResourceBundle().use(appRoot() + "settings");
|
messageResourceBundle().use(appRoot() + "settings");
|
||||||
messageResourceBundle().use(appRoot() + "tracks");
|
|
||||||
messageResourceBundle().use(appRoot() + "templates");
|
messageResourceBundle().use(appRoot() + "templates");
|
||||||
|
messageResourceBundle().use(appRoot() + "tracks");
|
||||||
|
messageResourceBundle().use(appRoot() + "tracksinfo");
|
||||||
|
|
||||||
// Require js here to avoid async problems
|
// Require js here to avoid async problems
|
||||||
requireJQuery("/js/jquery-1.10.2.min.js");
|
requireJQuery("/js/jquery-1.10.2.min.js");
|
||||||
|
|||||||
@@ -27,13 +27,14 @@
|
|||||||
|
|
||||||
#include "LmsApplication.hpp"
|
#include "LmsApplication.hpp"
|
||||||
|
|
||||||
#include "Filters.hpp"
|
|
||||||
#include "ArtistsView.hpp"
|
|
||||||
#include "ArtistsInfoView.hpp"
|
#include "ArtistsInfoView.hpp"
|
||||||
|
#include "ArtistsView.hpp"
|
||||||
#include "ArtistView.hpp"
|
#include "ArtistView.hpp"
|
||||||
#include "ReleasesView.hpp"
|
#include "Filters.hpp"
|
||||||
#include "ReleasesInfoView.hpp"
|
#include "ReleasesInfoView.hpp"
|
||||||
|
#include "ReleasesView.hpp"
|
||||||
#include "ReleaseView.hpp"
|
#include "ReleaseView.hpp"
|
||||||
|
#include "TracksInfoView.hpp"
|
||||||
#include "TracksView.hpp"
|
#include "TracksView.hpp"
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
@@ -80,7 +81,7 @@ handleInfoPathChange(Wt::WStackedWidget* stack)
|
|||||||
{
|
{
|
||||||
IdxArtists = 0,
|
IdxArtists = 0,
|
||||||
IdxReleases,
|
IdxReleases,
|
||||||
IdxEmpty,
|
IdxTracks,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::map<std::string, int> indexes =
|
static const std::map<std::string, int> indexes =
|
||||||
@@ -89,7 +90,7 @@ handleInfoPathChange(Wt::WStackedWidget* stack)
|
|||||||
{ "/artist", IdxArtists },
|
{ "/artist", IdxArtists },
|
||||||
{ "/releases", IdxReleases },
|
{ "/releases", IdxReleases },
|
||||||
{ "/release", IdxReleases },
|
{ "/release", IdxReleases },
|
||||||
{ "/tracks", IdxEmpty },
|
{ "/tracks", IdxTracks },
|
||||||
};
|
};
|
||||||
|
|
||||||
LMS_LOG(UI, DEBUG) << "Internal path changed to '" << wApp->internalPath() << "'";
|
LMS_LOG(UI, DEBUG) << "Internal path changed to '" << wApp->internalPath() << "'";
|
||||||
@@ -158,18 +159,22 @@ Explore::Explore()
|
|||||||
auto releasesInfoRaw = releasesInfo.get();
|
auto releasesInfoRaw = releasesInfo.get();
|
||||||
infoStack->addWidget(std::move(releasesInfo));
|
infoStack->addWidget(std::move(releasesInfo));
|
||||||
|
|
||||||
infoStack->addWidget(std::make_unique<Wt::WContainerWidget>());
|
auto tracksInfo = std::make_unique<TracksInfo>();
|
||||||
|
auto tracksInfoRaw = tracksInfo.get();
|
||||||
|
infoStack->addWidget(std::move(tracksInfo));
|
||||||
|
|
||||||
_dbChanged.connect([=]
|
_dbChanged.connect([=]
|
||||||
{
|
{
|
||||||
artistsInfoRaw->refreshRecentlyAdded();
|
artistsInfoRaw->refreshRecentlyAdded();
|
||||||
releasesInfoRaw->refreshRecentlyAdded();
|
releasesInfoRaw->refreshRecentlyAdded();
|
||||||
|
tracksInfoRaw->refreshRecentlyAdded();
|
||||||
});
|
});
|
||||||
|
|
||||||
_trackPlayed.connect([=]
|
_trackPlayed.connect([=]
|
||||||
{
|
{
|
||||||
artistsInfoRaw->refreshMostPlayed();
|
artistsInfoRaw->refreshMostPlayed();
|
||||||
releasesInfoRaw->refreshMostPlayed();
|
releasesInfoRaw->refreshMostPlayed();
|
||||||
|
tracksInfoRaw->refreshMostPlayed();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Emeric Poupon
|
||||||
|
*
|
||||||
|
* This file is part of LMS.
|
||||||
|
*
|
||||||
|
* LMS is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LMS is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TracksInfoView.hpp"
|
||||||
|
|
||||||
|
#include <Wt/WAnchor.h>
|
||||||
|
#include <Wt/WLocalDateTime.h>
|
||||||
|
|
||||||
|
#include "database/Track.hpp"
|
||||||
|
#include "database/TrackList.hpp"
|
||||||
|
|
||||||
|
#include "utils/Utils.hpp"
|
||||||
|
|
||||||
|
#include "LmsApplication.hpp"
|
||||||
|
|
||||||
|
using namespace Database;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using namespace UserInterface;
|
||||||
|
|
||||||
|
void addEntries(Wt::WContainerWidget *container, const std::vector<Track::pointer>& tracks)
|
||||||
|
{
|
||||||
|
for (auto track : tracks)
|
||||||
|
{
|
||||||
|
Wt::WTemplate* entry = container->addNew<Wt::WTemplate>(Wt::WString::tr("Lms.Explore.TracksInfo.template.entry"));
|
||||||
|
|
||||||
|
entry->bindString("name", Wt::WString::fromUTF8(track->getName()), Wt::TextFormat::Plain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace UserInterface {
|
||||||
|
|
||||||
|
TracksInfo::TracksInfo()
|
||||||
|
: Wt::WTemplate(Wt::WString::tr("Lms.Explore.TracksInfo.template"))
|
||||||
|
{
|
||||||
|
addFunction("tr", &Wt::WTemplate::Functions::tr);
|
||||||
|
|
||||||
|
_mostPlayedContainer = bindNew<Wt::WContainerWidget>("most-played");
|
||||||
|
_recentlyAddedContainer = bindNew<Wt::WContainerWidget>("recently-added");
|
||||||
|
|
||||||
|
refreshMostPlayed();
|
||||||
|
refreshRecentlyAdded();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TracksInfo::refreshRecentlyAdded()
|
||||||
|
{
|
||||||
|
auto after = Wt::WLocalDateTime::currentServerDateTime().toUTC().addMonths(-1);
|
||||||
|
|
||||||
|
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
|
||||||
|
auto tracks = Track::getLastAdded(LmsApp->getDboSession(), after, 5);
|
||||||
|
|
||||||
|
_recentlyAddedContainer->clear();
|
||||||
|
addEntries(_recentlyAddedContainer, tracks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TracksInfo::refreshMostPlayed()
|
||||||
|
{
|
||||||
|
Wt::Dbo::Transaction transaction(LmsApp->getDboSession());
|
||||||
|
auto tracks = LmsApp->getUser()->getPlayedTrackList()->getTopTracks(5);
|
||||||
|
|
||||||
|
_mostPlayedContainer->clear();
|
||||||
|
addEntries(_mostPlayedContainer, tracks);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace UserInterface
|
||||||
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Emeric Poupon
|
||||||
|
*
|
||||||
|
* This file is part of LMS.
|
||||||
|
*
|
||||||
|
* LMS is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LMS is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Wt/WContainerWidget.h>
|
||||||
|
#include <Wt/WTemplate.h>
|
||||||
|
|
||||||
|
namespace UserInterface {
|
||||||
|
|
||||||
|
class TracksInfo : public Wt::WTemplate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TracksInfo();
|
||||||
|
|
||||||
|
void refreshRecentlyAdded();
|
||||||
|
void refreshMostPlayed();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Wt::WContainerWidget* _mostPlayedContainer;
|
||||||
|
Wt::WContainerWidget* _recentlyAddedContainer;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace UserInterface
|
||||||
|
|
||||||
Reference in New Issue
Block a user