Added a way to filter by release type
This commit is contained in:
@@ -192,6 +192,7 @@
|
||||
<message id="Lms.Explore.recently-modified">Recently modified</message>
|
||||
<message id="Lms.Explore.recently-played">Recently played</message>
|
||||
<message id="Lms.Explore.release-info">Release information</message>
|
||||
<message id="Lms.Explore.release-type">Release type</message>
|
||||
<message id="Lms.Explore.releases">Albums</message>
|
||||
<message id="Lms.Explore.search">Search</message>
|
||||
<message id="Lms.Explore.star">Star</message>
|
||||
|
||||
@@ -192,6 +192,7 @@
|
||||
<message id="Lms.Explore.recently-modified">Modifiés récemment</message>
|
||||
<message id="Lms.Explore.recently-played">Joués récemment</message>
|
||||
<message id="Lms.Explore.release-info">Informations sur l'album</message>
|
||||
<message id="Lms.Explore.release-type">Type de publication</message>
|
||||
<message id="Lms.Explore.releases">Albums</message>
|
||||
<message id="Lms.Explore.search">Rechercher</message>
|
||||
<message id="Lms.Explore.star">Ajouter aux favoris</message>
|
||||
|
||||
@@ -192,6 +192,7 @@
|
||||
<message id="Lms.Explore.recently-modified">Modificati di recente</message>
|
||||
<message id="Lms.Explore.recently-played">Riprodotti di recente</message>
|
||||
<message id="Lms.Explore.release-info">Informazioni sull'album</message>
|
||||
<message id="Lms.Explore.release-type">Tipo di pubblicazione</message>
|
||||
<message id="Lms.Explore.releases">Album</message>
|
||||
<message id="Lms.Explore.search">Ricerca</message>
|
||||
<message id="Lms.Explore.star">Aggiungi ai preferiti</message>
|
||||
|
||||
@@ -209,6 +209,7 @@
|
||||
<message id="Lms.Explore.recently-modified">Ostatnio zmienione</message>
|
||||
<message id="Lms.Explore.recently-played">Ostatnio odtwarzane</message>
|
||||
<message id="Lms.Explore.release-info">Informacje o wydaniu</message>
|
||||
<message id="Lms.Explore.release-type">Typ wydania</message>
|
||||
<message id="Lms.Explore.releases">Albumy</message>
|
||||
<message id="Lms.Explore.search">Szukaj</message>
|
||||
<message id="Lms.Explore.star">Wyróżnij</message>
|
||||
|
||||
@@ -192,6 +192,7 @@
|
||||
<message id="Lms.Explore.recently-modified">最近更改</message>
|
||||
<message id="Lms.Explore.recently-played">最近播放</message>
|
||||
|
||||
|
||||
<message id="Lms.Explore.releases">专辑</message>
|
||||
<message id="Lms.Explore.search">搜索</message>
|
||||
<message id="Lms.Explore.star">收藏</message>
|
||||
|
||||
@@ -51,7 +51,8 @@ namespace lms::db
|
||||
|| params.release.isValid()
|
||||
|| params.filters.clusters.size() == 1
|
||||
|| params.filters.mediaLibrary.isValid()
|
||||
|| params.filters.label.isValid())
|
||||
|| params.filters.label.isValid()
|
||||
|| params.filters.releaseType.isValid())
|
||||
{
|
||||
query.join("track_artist_link t_a_l ON t_a_l.artist_id = a.id");
|
||||
}
|
||||
@@ -61,7 +62,8 @@ namespace lms::db
|
||||
|| params.writtenAfter.isValid()
|
||||
|| params.release.isValid()
|
||||
|| params.filters.mediaLibrary.isValid()
|
||||
|| params.filters.label.isValid())
|
||||
|| params.filters.label.isValid()
|
||||
|| params.filters.releaseType.isValid())
|
||||
{
|
||||
query.join("track t ON t.id = t_a_l.track_id");
|
||||
|
||||
@@ -79,6 +81,12 @@ namespace lms::db
|
||||
query.join("release_label r_l ON r_l.release_id = t.release_id");
|
||||
query.where("r_l.label_id = ?").bind(params.filters.label);
|
||||
}
|
||||
|
||||
if (params.filters.releaseType.isValid())
|
||||
{
|
||||
query.join("release_release_type r_r_t ON r_r_t.release_id = t.release_id");
|
||||
query.where("r_r_t.release_type_id = ?").bind(params.filters.releaseType);
|
||||
}
|
||||
}
|
||||
|
||||
if (params.linkType)
|
||||
|
||||
@@ -42,18 +42,26 @@ namespace lms::db
|
||||
|
||||
assert(!params.artist.isValid()); // poor check
|
||||
|
||||
if (params.filters.mediaLibrary.isValid() || params.filters.label.isValid())
|
||||
if (params.filters.mediaLibrary.isValid()
|
||||
|| params.filters.label.isValid()
|
||||
|| params.filters.releaseType.isValid())
|
||||
{
|
||||
query.join("track t ON t.id = t_a_l.track_id");
|
||||
}
|
||||
|
||||
if (params.filters.mediaLibrary.isValid())
|
||||
query.where("t.media_library_id = ?").bind(params.filters.mediaLibrary);
|
||||
if (params.filters.mediaLibrary.isValid())
|
||||
query.where("t.media_library_id = ?").bind(params.filters.mediaLibrary);
|
||||
|
||||
if (params.filters.label.isValid())
|
||||
{
|
||||
query.join("release_label r_l ON t.release_id = r_l.release_id");
|
||||
query.where("r_l.label_id = ?").bind(params.filters.label);
|
||||
if (params.filters.label.isValid())
|
||||
{
|
||||
query.join("release_label r_l ON r_l.release_id = t.release_id");
|
||||
query.where("r_l.label_id = ?").bind(params.filters.label);
|
||||
}
|
||||
|
||||
if (params.filters.releaseType.isValid())
|
||||
{
|
||||
query.join("release_release_type r_r_t ON r_r_t.release_id = t.release_id");
|
||||
query.where("r_r_t.release_type_id = ?").bind(params.filters.releaseType);
|
||||
}
|
||||
}
|
||||
|
||||
if (params.linkType)
|
||||
@@ -127,6 +135,12 @@ namespace lms::db
|
||||
query.where("r_l.label_id = ?").bind(params.filters.label);
|
||||
}
|
||||
|
||||
if (params.filters.releaseType.isValid())
|
||||
{
|
||||
query.join("release_release_type r_r_t ON r_r_t.release_id = r.id");
|
||||
query.where("r_r_t.release_type_id = ?").bind(params.filters.releaseType);
|
||||
}
|
||||
|
||||
if (!params.filters.clusters.empty())
|
||||
{
|
||||
std::ostringstream oss;
|
||||
@@ -180,6 +194,12 @@ namespace lms::db
|
||||
query.where("r_l.label_id = ?").bind(params.filters.label);
|
||||
}
|
||||
|
||||
if (params.filters.releaseType.isValid())
|
||||
{
|
||||
query.join("release_release_type r_r_t ON r_r_t.release_id = t.release_id");
|
||||
query.where("r_r_t.release_type_id = ?").bind(params.filters.releaseType);
|
||||
}
|
||||
|
||||
if (!params.filters.clusters.empty())
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
@@ -83,6 +83,12 @@ namespace lms::db
|
||||
query.where("r_l.label_id = ?").bind(params.filters.label);
|
||||
}
|
||||
|
||||
if (params.filters.releaseType.isValid())
|
||||
{
|
||||
query.join("release_release_type r_r_t ON r_r_t.release_id = r.id");
|
||||
query.where("r_r_t.release_type_id = ?").bind(params.filters.releaseType);
|
||||
}
|
||||
|
||||
if (params.directory.isValid())
|
||||
query.where("t.directory_id = ?").bind(params.directory);
|
||||
|
||||
@@ -401,6 +407,24 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<Wt::Dbo::ptr<ReleaseType>>("SELECT r_t from release_type r_t").where("r_t.name = ?").bind(name));
|
||||
}
|
||||
|
||||
void ReleaseType::find(Session& session, ReleaseTypeSortMethod sortMethod, std::function<void(const ReleaseType::pointer& releaseType)> func)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession()->find<ReleaseType>() };
|
||||
switch (sortMethod)
|
||||
{
|
||||
case ReleaseTypeSortMethod::None:
|
||||
break;
|
||||
case ReleaseTypeSortMethod::Name:
|
||||
query.orderBy("name COLLATE NOCASE");
|
||||
}
|
||||
|
||||
utils::forEachQueryResult(query, [&](const ReleaseType::pointer& releaseType) {
|
||||
func(releaseType);
|
||||
});
|
||||
}
|
||||
|
||||
RangeResults<ReleaseTypeId> ReleaseType::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -238,7 +238,9 @@ namespace lms::db
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_mbid_idx ON release(mbid)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_name_idx ON release(name)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_name_nocase_idx ON release(name COLLATE NOCASE)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_type_name_idx ON release_type(name)");
|
||||
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_type_id_idx ON release_type(id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_type_name_idx ON release_type(name COLLATE NOCASE)");
|
||||
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_id_idx ON track(id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_absolute_path_idx ON track(absolute_file_path)");
|
||||
|
||||
@@ -168,6 +168,12 @@ namespace lms::db
|
||||
query.where("r_l.label_id = ?").bind(params.filters.label);
|
||||
}
|
||||
|
||||
if (params.filters.releaseType.isValid())
|
||||
{
|
||||
query.join("release_release_type r_r_t ON r_r_t.release_id = t.release_id");
|
||||
query.where("r_r_t.release_type_id = ?").bind(params.filters.releaseType);
|
||||
}
|
||||
|
||||
if (params.directory.isValid())
|
||||
query.where("t.directory_id = ?").bind(params.directory);
|
||||
|
||||
|
||||
@@ -54,7 +54,8 @@ namespace lms::db
|
||||
query.where("t_l.name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind("%" + utils::escapeLikeKeyword(keyword) + "%");
|
||||
|
||||
if (params.filters.mediaLibrary.isValid()
|
||||
|| params.filters.label.isValid())
|
||||
|| params.filters.label.isValid()
|
||||
|| params.filters.releaseType.isValid())
|
||||
{
|
||||
query.join("track t ON t.id = t_l_e.track_id");
|
||||
|
||||
@@ -66,6 +67,12 @@ namespace lms::db
|
||||
query.join("release_label r_l ON r_l.release_id = t.release_id");
|
||||
query.where("r_l.label_id = ?").bind(params.filters.label);
|
||||
}
|
||||
|
||||
if (params.filters.releaseType.isValid())
|
||||
{
|
||||
query.join("release_release_type r_r_t ON r_r_t.release_id = t.release_id");
|
||||
query.where("r_r_t.release_type_id = ?").bind(params.filters.releaseType);
|
||||
}
|
||||
}
|
||||
|
||||
if (params.user.isValid())
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "database/ClusterId.hpp"
|
||||
#include "database/LabelId.hpp"
|
||||
#include "database/MediaLibraryId.hpp"
|
||||
#include "database/ReleaseTypeId.hpp"
|
||||
|
||||
namespace lms::db
|
||||
{
|
||||
@@ -32,6 +33,7 @@ namespace lms::db
|
||||
MediaLibraryId mediaLibrary; // tracks that belongs to this library
|
||||
std::vector<ClusterId> clusters; // tracks that belong to all these clusters
|
||||
LabelId label; // tracks which release has this label
|
||||
ReleaseTypeId releaseType; // tracks which release has this type
|
||||
|
||||
Filters& setClusters(std::span<const ClusterId> _clusters)
|
||||
{
|
||||
@@ -48,5 +50,10 @@ namespace lms::db
|
||||
label = _label;
|
||||
return *this;
|
||||
}
|
||||
Filters& setReleaseType(ReleaseTypeId _releaseType)
|
||||
{
|
||||
releaseType = _releaseType;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
} // namespace lms::db
|
||||
@@ -124,6 +124,7 @@ namespace lms::db
|
||||
static std::size_t getCount(Session& session);
|
||||
static pointer find(Session& session, ReleaseTypeId id);
|
||||
static pointer find(Session& session, std::string_view name);
|
||||
static void find(Session& session, ReleaseTypeSortMethod sortMethod, std::function<void(const ReleaseType::pointer& releaseType)> func);
|
||||
static RangeResults<ReleaseTypeId> findOrphanIds(Session& session, std::optional<Range> range = std::nullopt);
|
||||
|
||||
// Accessors
|
||||
|
||||
@@ -158,6 +158,12 @@ namespace lms::db
|
||||
StarredDateDesc,
|
||||
};
|
||||
|
||||
enum class ReleaseTypeSortMethod
|
||||
{
|
||||
None,
|
||||
Name,
|
||||
};
|
||||
|
||||
enum class TrackListSortMethod
|
||||
{
|
||||
None,
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "database/LabelId.hpp"
|
||||
#include "database/MediaLibrary.hpp"
|
||||
#include "database/Release.hpp"
|
||||
#include "database/ReleaseTypeId.hpp"
|
||||
#include "database/Session.hpp"
|
||||
|
||||
#include "LmsApplication.hpp"
|
||||
@@ -50,7 +51,11 @@ namespace lms::ui
|
||||
{
|
||||
};
|
||||
|
||||
using TypeVariant = std::variant<db::ClusterTypeId, MediaLibraryTag, LabelTag>;
|
||||
struct ReleaseTypeTag
|
||||
{
|
||||
};
|
||||
|
||||
using TypeVariant = std::variant<db::ClusterTypeId, MediaLibraryTag, LabelTag, ReleaseTypeTag>;
|
||||
using TypeModel = ValueStringModel<TypeVariant>;
|
||||
|
||||
std::unique_ptr<TypeModel> createTypeModel()
|
||||
@@ -66,11 +71,12 @@ namespace lms::ui
|
||||
|
||||
typeModel->add(Wt::WString::tr("Lms.Explore.media-library"), MediaLibraryTag{});
|
||||
typeModel->add(Wt::WString::tr("Lms.Explore.label"), LabelTag{});
|
||||
typeModel->add(Wt::WString::tr("Lms.Explore.release-type"), ReleaseTypeTag{});
|
||||
|
||||
return typeModel;
|
||||
}
|
||||
|
||||
using ValueVariant = std::variant<db::ClusterId, db::MediaLibraryId, db::LabelId>;
|
||||
using ValueVariant = std::variant<db::ClusterId, db::MediaLibraryId, db::LabelId, db::ReleaseTypeId>;
|
||||
using ValueModel = ValueStringModel<ValueVariant>;
|
||||
|
||||
std::unique_ptr<ValueModel> createValueModel(TypeVariant type)
|
||||
@@ -93,6 +99,12 @@ namespace lms::ui
|
||||
valueModel->add(Wt::WString::fromUTF8(std::string{ label->getName() }), label->getId());
|
||||
});
|
||||
}
|
||||
else if (std::holds_alternative<ReleaseTypeTag>(type))
|
||||
{
|
||||
db::ReleaseType::find(session, db::ReleaseTypeSortMethod::Name, [&](const db::ReleaseType::pointer& releaseType) {
|
||||
valueModel->add(Wt::WString::fromUTF8(std::string{ releaseType->getName() }), releaseType->getId());
|
||||
});
|
||||
}
|
||||
else if (const db::ClusterTypeId * clusterTypeId{ std::get_if<db::ClusterTypeId>(&type) })
|
||||
{
|
||||
db::Cluster::FindParameters params;
|
||||
@@ -136,6 +148,11 @@ namespace lms::ui
|
||||
set(*labelId);
|
||||
state::writeValue<db::LabelId::ValueType>("filters_label_id", labelId->getValue());
|
||||
}
|
||||
else if (const db::ReleaseTypeId * releaseTypeId{ std::get_if<db::ReleaseTypeId>(&value) })
|
||||
{
|
||||
set(*releaseTypeId);
|
||||
state::writeValue<db::ReleaseTypeId::ValueType>("filters_release_type_id", releaseTypeId->getValue());
|
||||
}
|
||||
else if (const db::ClusterId * clusterId{ std::get_if<db::ClusterId>(&value) })
|
||||
{
|
||||
add(*clusterId);
|
||||
@@ -176,8 +193,10 @@ namespace lms::ui
|
||||
|
||||
if (const std::optional<db::MediaLibraryId::ValueType> mediaLibraryId{ state::readValue<db::MediaLibraryId::ValueType>("filters_media_library_id") })
|
||||
set(db::MediaLibraryId{ *mediaLibraryId });
|
||||
if (const std::optional<db::LabelId::ValueType> mediaLibraryId{ state::readValue<db::LabelId::ValueType>("filters_label_id") })
|
||||
set(db::LabelId{ *mediaLibraryId });
|
||||
if (const std::optional<db::LabelId::ValueType> labelId{ state::readValue<db::LabelId::ValueType>("filters_label_id") })
|
||||
set(db::LabelId{ *labelId });
|
||||
if (const std::optional<db::ReleaseTypeId::ValueType> releaseTypeId{ state::readValue<db::ReleaseTypeId::ValueType>("filters_release_type_id") })
|
||||
set(db::ReleaseTypeId{ *releaseTypeId });
|
||||
}
|
||||
|
||||
void Filters::add(db::ClusterId clusterId)
|
||||
@@ -272,6 +291,39 @@ namespace lms::ui
|
||||
emitFilterAddedNotification();
|
||||
}
|
||||
|
||||
void Filters::set(db::ReleaseTypeId releaseTypeId)
|
||||
{
|
||||
if (_releaseTypeFilter)
|
||||
{
|
||||
_filters->removeWidget(_releaseTypeFilter);
|
||||
_releaseTypeFilter = nullptr;
|
||||
_dbFilters.releaseType = db::ReleaseTypeId{};
|
||||
}
|
||||
|
||||
std::string name;
|
||||
{
|
||||
auto transaction{ LmsApp->getDbSession().createReadTransaction() };
|
||||
|
||||
const auto releaseType{ db::ReleaseType::find(LmsApp->getDbSession(), releaseTypeId) };
|
||||
if (!releaseType)
|
||||
return;
|
||||
|
||||
name = releaseType->getName();
|
||||
}
|
||||
|
||||
_dbFilters.releaseType = releaseTypeId;
|
||||
_releaseTypeFilter = _filters->addWidget(utils::createFilter(Wt::WString::fromUTF8(name), Wt::WString::tr("Lms.Explore.release-type"), "bg-dark", true));
|
||||
_releaseTypeFilter->clicked().connect(_releaseTypeFilter, [this] {
|
||||
_filters->removeWidget(_releaseTypeFilter);
|
||||
_dbFilters.releaseType = db::ReleaseTypeId{};
|
||||
_releaseTypeFilter = nullptr;
|
||||
_sigUpdated.emit();
|
||||
state::writeValue<db::LabelId::ValueType>("filters_release_type_id", std::nullopt);
|
||||
});
|
||||
|
||||
emitFilterAddedNotification();
|
||||
}
|
||||
|
||||
void Filters::emitFilterAddedNotification()
|
||||
{
|
||||
LmsApp->notifyMsg(Notification::Type::Info,
|
||||
|
||||
@@ -19,9 +19,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
#include <Wt/WContainerWidget.h>
|
||||
#include <Wt/WSignal.h>
|
||||
#include <Wt/WTemplate.h>
|
||||
@@ -45,11 +42,13 @@ namespace lms::ui
|
||||
void showDialog();
|
||||
void set(db::LabelId labelId);
|
||||
void set(db::MediaLibraryId mediaLibraryId);
|
||||
void set(db::ReleaseTypeId releaseTypeId);
|
||||
void emitFilterAddedNotification();
|
||||
|
||||
Wt::WContainerWidget* _filters{};
|
||||
Wt::WInteractWidget* _mediaLibraryFilter{};
|
||||
Wt::WInteractWidget* _labelFilter{};
|
||||
Wt::WInteractWidget* _releaseTypeFilter{};
|
||||
|
||||
Wt::Signal<> _sigUpdated;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user