Add tag and namespace model and socket namespace
Signed-off-by: trivernis <trivernis@protonmail.com>pull/4/head
parent
4cebfc7eb2
commit
17edb0a72f
@ -0,0 +1,7 @@
|
||||
/// Parses a normalized tag into its two components of namespace and tag
|
||||
pub fn parse_namespace_and_tag(norm_tag: String) -> (Option<String>, String) {
|
||||
norm_tag
|
||||
.split_once(':')
|
||||
.map(|(n, t)| (Some(n.trim().to_string()), t.trim().to_string()))
|
||||
.unwrap_or((None, norm_tag.trim().to_string()))
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
pub mod file;
|
||||
pub mod file_type;
|
||||
pub mod hash;
|
||||
pub mod namespace;
|
||||
pub mod repo;
|
||||
pub mod storage;
|
||||
pub mod tag;
|
||||
pub mod thumbnail;
|
||||
pub mod type_keys;
|
||||
|
@ -0,0 +1,62 @@
|
||||
use mediarepo_core::error::RepoResult;
|
||||
use mediarepo_database::entities::namespace;
|
||||
use sea_orm::prelude::*;
|
||||
use sea_orm::{DatabaseConnection, Set};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Namespace {
|
||||
db: DatabaseConnection,
|
||||
model: namespace::Model,
|
||||
}
|
||||
|
||||
impl Namespace {
|
||||
pub(crate) fn new(db: DatabaseConnection, model: namespace::Model) -> Self {
|
||||
Self { db, model }
|
||||
}
|
||||
|
||||
/// Retrieves the namespace by id
|
||||
pub async fn by_id(db: DatabaseConnection, id: i64) -> RepoResult<Option<Self>> {
|
||||
let namespace = namespace::Entity::find_by_id(id)
|
||||
.one(&db)
|
||||
.await?
|
||||
.map(|model| Self::new(db, model));
|
||||
|
||||
Ok(namespace)
|
||||
}
|
||||
|
||||
/// Retrieves a namespace by its name
|
||||
pub async fn by_name<S: AsRef<str>>(
|
||||
db: DatabaseConnection,
|
||||
name: S,
|
||||
) -> RepoResult<Option<Self>> {
|
||||
let namespace = namespace::Entity::find()
|
||||
.filter(namespace::Column::Name.eq(name.as_ref()))
|
||||
.one(&db)
|
||||
.await?
|
||||
.map(|model| Self::new(db, model));
|
||||
|
||||
Ok(namespace)
|
||||
}
|
||||
|
||||
/// Adds a namespace to the database
|
||||
pub async fn add<S: ToString>(db: DatabaseConnection, name: S) -> RepoResult<Self> {
|
||||
let active_model = namespace::ActiveModel {
|
||||
name: Set(name.to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
let active_model = active_model.insert(&db).await?;
|
||||
let namespace = Self::by_id(db, active_model.id.unwrap()).await?.unwrap();
|
||||
|
||||
Ok(namespace)
|
||||
}
|
||||
|
||||
/// The ID of the namespace
|
||||
pub fn id(&self) -> i64 {
|
||||
self.model.id
|
||||
}
|
||||
|
||||
/// The name of the namespace
|
||||
pub fn name(&self) -> &String {
|
||||
&self.model.name
|
||||
}
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
use crate::namespace::Namespace;
|
||||
use mediarepo_core::error::RepoResult;
|
||||
use mediarepo_database::entities::namespace;
|
||||
use mediarepo_database::entities::tag;
|
||||
use sea_orm::prelude::*;
|
||||
use sea_orm::QuerySelect;
|
||||
use sea_orm::{DatabaseConnection, JoinType, Set};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Tag {
|
||||
db: DatabaseConnection,
|
||||
model: tag::Model,
|
||||
namespace: Option<namespace::Model>,
|
||||
}
|
||||
|
||||
impl Tag {
|
||||
pub(crate) fn new(
|
||||
db: DatabaseConnection,
|
||||
model: tag::Model,
|
||||
namespace: Option<namespace::Model>,
|
||||
) -> Self {
|
||||
Self {
|
||||
db,
|
||||
model,
|
||||
namespace,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns all tags stored in the database
|
||||
pub async fn all(db: DatabaseConnection) -> RepoResult<Vec<Self>> {
|
||||
let tags: Vec<Self> = tag::Entity::find()
|
||||
.find_also_related(namespace::Entity)
|
||||
.all(&db)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|(tag, namespace)| Self::new(db.clone(), tag, namespace))
|
||||
.collect();
|
||||
|
||||
Ok(tags)
|
||||
}
|
||||
|
||||
/// Returns the tag by id
|
||||
pub async fn by_id(db: DatabaseConnection, id: i64) -> RepoResult<Option<Self>> {
|
||||
let tag = tag::Entity::find_by_id(id)
|
||||
.find_also_related(namespace::Entity)
|
||||
.one(&db)
|
||||
.await?
|
||||
.map(|(model, namespace)| Self::new(db, model, namespace));
|
||||
|
||||
Ok(tag)
|
||||
}
|
||||
|
||||
/// Retrieves the unnamespaced tag by name
|
||||
pub async fn by_name<S: AsRef<str>>(
|
||||
db: DatabaseConnection,
|
||||
name: S,
|
||||
) -> RepoResult<Option<Self>> {
|
||||
let tag = tag::Entity::find()
|
||||
.filter(tag::Column::Name.eq(name.as_ref()))
|
||||
.filter(tag::Column::NamespaceId.eq(Option::<i64>::None))
|
||||
.one(&db)
|
||||
.await?
|
||||
.map(|t| Tag::new(db, t, None));
|
||||
|
||||
Ok(tag)
|
||||
}
|
||||
|
||||
/// Retrieves the namespaced tag by name and namespace
|
||||
pub async fn by_name_and_namespace<S1: AsRef<str>, S2: AsRef<str>>(
|
||||
db: DatabaseConnection,
|
||||
name: S1,
|
||||
namespace: S2,
|
||||
) -> RepoResult<Option<Self>> {
|
||||
let tag = tag::Entity::find()
|
||||
.find_also_related(namespace::Entity)
|
||||
.join(JoinType::InnerJoin, namespace::Relation::Tag.def())
|
||||
.filter(namespace::Column::Name.eq(namespace.as_ref()))
|
||||
.filter(tag::Column::Name.eq(name.as_ref()))
|
||||
.one(&db)
|
||||
.await?
|
||||
.map(|(t, n)| Self::new(db.clone(), t, n));
|
||||
|
||||
Ok(tag)
|
||||
}
|
||||
|
||||
/// Adds a new tag to the database
|
||||
pub async fn add<S: ToString>(
|
||||
db: DatabaseConnection,
|
||||
name: S,
|
||||
namespace_id: Option<i64>,
|
||||
) -> RepoResult<Self> {
|
||||
let active_model = tag::ActiveModel {
|
||||
name: Set(name.to_string()),
|
||||
namespace_id: Set(namespace_id),
|
||||
..Default::default()
|
||||
};
|
||||
let active_model = active_model.insert(&db).await?;
|
||||
let tag = Self::by_id(db, active_model.id.unwrap()).await?.unwrap();
|
||||
|
||||
Ok(tag)
|
||||
}
|
||||
|
||||
/// The ID of the tag
|
||||
pub fn id(&self) -> i64 {
|
||||
self.model.id
|
||||
}
|
||||
|
||||
/// The name of the tag
|
||||
pub fn name(&self) -> &String {
|
||||
&self.model.name
|
||||
}
|
||||
|
||||
/// The namespace of the tag
|
||||
pub fn namespace(&self) -> Option<Namespace> {
|
||||
self.namespace
|
||||
.clone()
|
||||
.map(|n| Namespace::new(self.db.clone(), n))
|
||||
}
|
||||
}
|
@ -1,7 +1,10 @@
|
||||
use mediarepo_core::rmp_ipc::{namespace, namespace::Namespace, IPCBuilder};
|
||||
|
||||
pub mod files;
|
||||
pub mod tags;
|
||||
|
||||
pub fn build_namespaces(builder: IPCBuilder) -> IPCBuilder {
|
||||
builder.add_namespace(namespace!(files::FilesNamespace))
|
||||
builder
|
||||
.add_namespace(namespace!(files::FilesNamespace))
|
||||
.add_namespace(namespace!(tags::TagsNamespace))
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
use crate::types::responses::TagResponse;
|
||||
use crate::utils::get_repo_from_context;
|
||||
use mediarepo_core::rmp_ipc::prelude::*;
|
||||
|
||||
pub struct TagsNamespace;
|
||||
|
||||
impl NamespaceProvider for TagsNamespace {
|
||||
fn name() -> &'static str {
|
||||
"tags"
|
||||
}
|
||||
|
||||
fn register(handler: &mut EventHandler) {
|
||||
events!(handler,
|
||||
"all_tags" => Self::all_tags
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl TagsNamespace {
|
||||
async fn all_tags(ctx: &Context, event: Event) -> IPCResult<()> {
|
||||
let repo = get_repo_from_context(ctx).await;
|
||||
let tags: Vec<TagResponse> = repo
|
||||
.tags()
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(TagResponse::from)
|
||||
.collect();
|
||||
ctx.emitter
|
||||
.emit_response_to(event.id(), Self::name(), "all_tags", tags)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue