New UI: filters now operational on all views
This commit is contained in:
@@ -19,7 +19,7 @@ LMS is written entirely in C++. Therefore, it is suitable to run on embedded dev
|
|||||||
### Debian
|
### Debian
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ apt-get install g++ autoconf automake libboost-dev libboost-locale-dev libboost-iostreams-dev libavcodec-dev libwtdbosqlite-dev libwthttp-dev libwtdbo-dev libwt-dev libmagick++-dev libavcodec-dev libavformat-dev libav-tools libpstreams-dev libcurl-dev libcurlpp-dev libconfig++-dev ffmpeg
|
$ apt-get install g++ autoconf automake libboost-dev libboost-locale-dev libboost-iostreams-dev libavcodec-dev libavutil-dev libavformat-dev libav-tools libwtdbosqlite-dev libwthttp-dev libwtdbo-dev libwt-dev libmagick++-dev libpstreams-dev libcurlpp-dev libconfig++-dev libpstreams-dev ffmpeg libtag1-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ getQuery(Wt::Dbo::Session& session,
|
|||||||
WhereClause clusterClause;
|
WhereClause clusterClause;
|
||||||
|
|
||||||
for (auto id : clusterIds)
|
for (auto id : clusterIds)
|
||||||
clusterClause.And(WhereClause("c.id = ?")).bind(std::to_string(id));
|
clusterClause.Or(WhereClause("c.id = ?")).bind(std::to_string(id));
|
||||||
|
|
||||||
where.And(clusterClause);
|
where.And(clusterClause);
|
||||||
}
|
}
|
||||||
@@ -195,17 +195,48 @@ Release::hasVariousArtists() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Wt::Dbo::ptr<Track>>
|
std::vector<Wt::Dbo::ptr<Track>>
|
||||||
Release::getTracks() const
|
Release::getTracks(const std::vector<id_type>& clusterIds) const
|
||||||
{
|
{
|
||||||
assert(self());
|
assert(self());
|
||||||
|
assert(self()->id() != Wt::Dbo::dbo_traits<Release>::invalidId() );
|
||||||
assert(session());
|
assert(session());
|
||||||
|
|
||||||
Wt::Dbo::collection<Wt::Dbo::ptr<Track>> res = session()->query<Wt::Dbo::ptr<Track>>(
|
WhereClause where;
|
||||||
"SELECT t FROM track t INNER JOIN release r ON t.release_id = r.id")
|
|
||||||
.where("r.id = ?")
|
|
||||||
.orderBy("t.disc_number,t.track_number")
|
|
||||||
.bind(id());
|
|
||||||
|
|
||||||
return std::vector<Wt::Dbo::ptr<Track>>(res.begin(), res.end());
|
std::ostringstream oss;
|
||||||
|
oss << "SELECT t FROM track t INNER JOIN release r ON t.release_id = r.id";
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
where.And(clusterClause);
|
||||||
|
}
|
||||||
|
|
||||||
|
where.And(WhereClause("r.id = ?")).bind(std::to_string(id()));
|
||||||
|
|
||||||
|
oss << " " << where.get();
|
||||||
|
|
||||||
|
if (!clusterIds.empty())
|
||||||
|
oss << " GROUP BY t.id HAVING COUNT(*) = " << clusterIds.size();
|
||||||
|
|
||||||
|
oss << " ORDER BY t.disc_number,t.track_number";
|
||||||
|
|
||||||
|
Wt::Dbo::Query<Track::pointer> query = session()->query<Track::pointer>( oss.str() );
|
||||||
|
|
||||||
|
for (const std::string& bindArg : where.getBindArgs())
|
||||||
|
{
|
||||||
|
query.bind(bindArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
Wt::Dbo::collection< Wt::Dbo::ptr<Track> > res = query;
|
||||||
|
|
||||||
|
return std::vector< Wt::Dbo::ptr<Track> > (res.begin(), res.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Database
|
} // namespace Database
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class Release : public Wt::Dbo::Dbo<Release>
|
|||||||
int size,
|
int size,
|
||||||
bool& moreExpected);
|
bool& moreExpected);
|
||||||
|
|
||||||
std::vector<Wt::Dbo::ptr<Track>> getTracks() const;
|
std::vector<Wt::Dbo::ptr<Track>> getTracks(const std::vector<id_type>& clusters = std::vector<id_type>()) const;
|
||||||
|
|
||||||
// Create
|
// Create
|
||||||
static pointer create(Wt::Dbo::Session& session, const std::string& name, const std::string& MBID = "");
|
static pointer create(Wt::Dbo::Session& session, const std::string& name, const std::string& MBID = "");
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ getQuery(Wt::Dbo::Session& session,
|
|||||||
WhereClause clusterClause;
|
WhereClause clusterClause;
|
||||||
|
|
||||||
for (auto id : clusterIds)
|
for (auto id : clusterIds)
|
||||||
clusterClause.And(WhereClause("c.id = ?")).bind(std::to_string(id));
|
clusterClause.Or(WhereClause("c.id = ?")).bind(std::to_string(id));
|
||||||
|
|
||||||
where.And(clusterClause);
|
where.And(clusterClause);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,8 +84,8 @@ Artist::refresh()
|
|||||||
entry->addFunction("tr", Wt::WTemplate::Functions::tr);
|
entry->addFunction("tr", Wt::WTemplate::Functions::tr);
|
||||||
|
|
||||||
{
|
{
|
||||||
Wt::WAnchor *coverAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/release/" + std::to_string(release.id())));
|
Wt::WAnchor* coverAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/release/" + std::to_string(release.id())));
|
||||||
Wt::WImage *cover = new Wt::WImage(coverAnchor);
|
Wt::WImage* cover = new Wt::WImage(coverAnchor);
|
||||||
cover->setImageLink(SessionImageResource()->getReleaseUrl(release.id(), 128));
|
cover->setImageLink(SessionImageResource()->getReleaseUrl(release.id(), 128));
|
||||||
// Some images may not be square
|
// Some images may not be square
|
||||||
cover->setWidth(128);
|
cover->setWidth(128);
|
||||||
@@ -93,8 +93,8 @@ Artist::refresh()
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Wt::WAnchor *releaseAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/release/" + std::to_string(release.id())));
|
Wt::WAnchor* releaseAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/release/" + std::to_string(release.id())));
|
||||||
Wt::WText *releaseName = new Wt::WText(releaseAnchor);
|
Wt::WText* releaseName = new Wt::WText(releaseAnchor);
|
||||||
releaseName->setText(Wt::WString::fromUTF8(release->getName(), Wt::PlainText));
|
releaseName->setText(Wt::WString::fromUTF8(release->getName(), Wt::PlainText));
|
||||||
entry->bindWidget("name", releaseAnchor);
|
entry->bindWidget("name", releaseAnchor);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -83,9 +83,9 @@ Explore::Explore(Wt::WContainerWidget* parent)
|
|||||||
|
|
||||||
stack->addWidget(new Artists(filters));
|
stack->addWidget(new Artists(filters));
|
||||||
stack->addWidget(new Artist(filters));
|
stack->addWidget(new Artist(filters));
|
||||||
stack->addWidget(new Releases(/*filters*/));
|
stack->addWidget(new Releases(filters));
|
||||||
stack->addWidget(new Release(/*filters*/));
|
stack->addWidget(new Release(filters));
|
||||||
stack->addWidget(new Tracks(/*filters*/));
|
stack->addWidget(new Tracks(filters));
|
||||||
|
|
||||||
wApp->internalPathChanged().connect(std::bind([=]
|
wApp->internalPathChanged().connect(std::bind([=]
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,8 +33,9 @@
|
|||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|
||||||
Release::Release(Wt::WContainerWidget* parent)
|
Release::Release(Filters* filters, Wt::WContainerWidget* parent)
|
||||||
: Wt::WContainerWidget(parent)
|
: Wt::WContainerWidget(parent),
|
||||||
|
_filters(filters)
|
||||||
{
|
{
|
||||||
wApp->internalPathChanged().connect(std::bind([=]
|
wApp->internalPathChanged().connect(std::bind([=]
|
||||||
{
|
{
|
||||||
@@ -109,10 +110,9 @@ Release::refresh()
|
|||||||
auto tracksContainer = new Wt::WContainerWidget();
|
auto tracksContainer = new Wt::WContainerWidget();
|
||||||
t->bindWidget("tracks", tracksContainer);
|
t->bindWidget("tracks", tracksContainer);
|
||||||
|
|
||||||
std::vector<Database::Cluster::id_type> clusterIds; // TODO fill
|
auto clusterIds = _filters->getClusterIds();
|
||||||
|
auto tracks = release->getTracks(clusterIds);
|
||||||
|
|
||||||
// auto tracks = release->getTracks(clusterIds);
|
|
||||||
auto tracks = release->getTracks();
|
|
||||||
bool variousArtists = release->hasVariousArtists();
|
bool variousArtists = release->hasVariousArtists();
|
||||||
|
|
||||||
for (auto track : tracks)
|
for (auto track : tracks)
|
||||||
|
|||||||
@@ -21,15 +21,19 @@
|
|||||||
|
|
||||||
#include <Wt/WContainerWidget>
|
#include <Wt/WContainerWidget>
|
||||||
|
|
||||||
|
#include "Filters.hpp"
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|
||||||
class Release : public Wt::WContainerWidget
|
class Release : public Wt::WContainerWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Release(Wt::WContainerWidget* parent = 0);
|
Release(Filters* filters, Wt::WContainerWidget* parent = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void refresh();
|
void refresh();
|
||||||
|
|
||||||
|
Filters* _filters;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace UserInterface
|
} // namespace UserInterface
|
||||||
|
|||||||
@@ -36,8 +36,9 @@ namespace UserInterface {
|
|||||||
|
|
||||||
using namespace Database;
|
using namespace Database;
|
||||||
|
|
||||||
Releases::Releases(Wt::WContainerWidget* parent)
|
Releases::Releases(Filters* filters, Wt::WContainerWidget* parent)
|
||||||
: Wt::WContainerWidget(parent)
|
: Wt::WContainerWidget(parent),
|
||||||
|
_filters(filters)
|
||||||
{
|
{
|
||||||
auto releases = new Wt::WTemplate(Wt::WString::tr("template-releases"), this);
|
auto releases = new Wt::WTemplate(Wt::WString::tr("template-releases"), this);
|
||||||
releases->addFunction("tr", &Wt::WTemplate::Functions::tr);
|
releases->addFunction("tr", &Wt::WTemplate::Functions::tr);
|
||||||
@@ -63,7 +64,7 @@ Releases::refresh(std::vector<std::string> searchKeywords)
|
|||||||
{
|
{
|
||||||
_releasesContainer->clear();
|
_releasesContainer->clear();
|
||||||
|
|
||||||
std::vector<Cluster::id_type> clusterIds; // TODO fill
|
auto clusterIds = _filters->getClusterIds();
|
||||||
|
|
||||||
Wt::Dbo::Transaction transaction(DboSession());
|
Wt::Dbo::Transaction transaction(DboSession());
|
||||||
|
|
||||||
@@ -75,8 +76,8 @@ Releases::refresh(std::vector<std::string> searchKeywords)
|
|||||||
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("template-releases-entry"), _releasesContainer);
|
Wt::WTemplate* entry = new Wt::WTemplate(Wt::WString::tr("template-releases-entry"), _releasesContainer);
|
||||||
entry->addFunction("tr", Wt::WTemplate::Functions::tr);
|
entry->addFunction("tr", Wt::WTemplate::Functions::tr);
|
||||||
|
|
||||||
Wt::WAnchor *coverAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/release/" + std::to_string(release.id())));
|
Wt::WAnchor* coverAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/release/" + std::to_string(release.id())));
|
||||||
Wt::WImage *cover = new Wt::WImage(coverAnchor);
|
Wt::WImage* cover = new Wt::WImage(coverAnchor);
|
||||||
cover->setImageLink(SessionImageResource()->getReleaseUrl(release.id(), 128));
|
cover->setImageLink(SessionImageResource()->getReleaseUrl(release.id(), 128));
|
||||||
// Some images may not be square
|
// Some images may not be square
|
||||||
cover->setWidth(128);
|
cover->setWidth(128);
|
||||||
@@ -91,8 +92,8 @@ Releases::refresh(std::vector<std::string> searchKeywords)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Wt::WAnchor *artistAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/artist/" + std::to_string(artists.front().id())));
|
Wt::WAnchor* artistAnchor = new Wt::WAnchor(Wt::WLink(Wt::WLink::InternalPath, "/artist/" + std::to_string(artists.front().id())));
|
||||||
Wt::WText *artist = new Wt::WText(artistAnchor);
|
Wt::WText* artist = new Wt::WText(artistAnchor);
|
||||||
artist->setText(Wt::WString::fromUTF8(artists.front()->getName(), Wt::PlainText));
|
artist->setText(Wt::WString::fromUTF8(artists.front()->getName(), Wt::PlainText));
|
||||||
entry->bindWidget("artist-name", artistAnchor);
|
entry->bindWidget("artist-name", artistAnchor);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,17 +21,20 @@
|
|||||||
|
|
||||||
#include <Wt/WContainerWidget>
|
#include <Wt/WContainerWidget>
|
||||||
|
|
||||||
|
#include "Filters.hpp"
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|
||||||
class Releases : public Wt::WContainerWidget
|
class Releases : public Wt::WContainerWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Releases(Wt::WContainerWidget* parent = 0);
|
Releases(Filters* filters, Wt::WContainerWidget* parent = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void refresh(std::vector<std::string> searchKeywords = std::vector<std::string>());
|
void refresh(std::vector<std::string> searchKeywords = std::vector<std::string>());
|
||||||
|
|
||||||
Wt::WContainerWidget *_releasesContainer;
|
Filters* _filters;
|
||||||
|
Wt::WContainerWidget* _releasesContainer;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace UserInterface
|
} // namespace UserInterface
|
||||||
|
|||||||
@@ -35,8 +35,9 @@ namespace UserInterface {
|
|||||||
|
|
||||||
using namespace Database;
|
using namespace Database;
|
||||||
|
|
||||||
Tracks::Tracks(Wt::WContainerWidget* parent)
|
Tracks::Tracks(Filters* filters, Wt::WContainerWidget* parent)
|
||||||
: Wt::WContainerWidget(parent)
|
: Wt::WContainerWidget(parent),
|
||||||
|
_filters(filters)
|
||||||
{
|
{
|
||||||
auto tracks = new Wt::WTemplate(Wt::WString::tr("template-tracks"), this);
|
auto tracks = new Wt::WTemplate(Wt::WString::tr("template-tracks"), this);
|
||||||
tracks->addFunction("tr", &Wt::WTemplate::Functions::tr);
|
tracks->addFunction("tr", &Wt::WTemplate::Functions::tr);
|
||||||
@@ -62,7 +63,7 @@ Tracks::refresh(std::vector<std::string> searchKeywords)
|
|||||||
{
|
{
|
||||||
_tracksContainer->clear();
|
_tracksContainer->clear();
|
||||||
|
|
||||||
std::vector<Cluster::id_type> clusterIds; // TODO fill
|
auto clusterIds = _filters->getClusterIds();
|
||||||
|
|
||||||
Wt::Dbo::Transaction transaction(DboSession());
|
Wt::Dbo::Transaction transaction(DboSession());
|
||||||
|
|
||||||
|
|||||||
@@ -21,17 +21,20 @@
|
|||||||
|
|
||||||
#include <Wt/WContainerWidget>
|
#include <Wt/WContainerWidget>
|
||||||
|
|
||||||
|
#include "Filters.hpp"
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|
||||||
class Tracks : public Wt::WContainerWidget
|
class Tracks : public Wt::WContainerWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Tracks(Wt::WContainerWidget* parent = 0);
|
Tracks(Filters* filters, Wt::WContainerWidget* parent = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void refresh(std::vector<std::string> searchKeywords = std::vector<std::string>());
|
void refresh(std::vector<std::string> searchKeywords = std::vector<std::string>());
|
||||||
|
|
||||||
Wt::WContainerWidget *_tracksContainer;
|
Wt::WContainerWidget* _tracksContainer;
|
||||||
|
Filters* _filters;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace UserInterface
|
} // namespace UserInterface
|
||||||
|
|||||||
Reference in New Issue
Block a user