samling 0.13.1

App for managing apparel collections
Documentation
use chrono::{DateTime, FixedOffset};
use samling_clorinde::client::GenericClient;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use url::Url;

use crate::{
    auth::User,
    entity_ref::{ExternalId, ExternalIdEntity},
    organizations::Organization,
    Color, ColorSummary, EntityRefPathParam, Id, Ref, RefTarget,
};
use samling_clorinde::queries::image::get_image_id;

#[derive(Debug, Copy, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum ImageVariant {
    Original,
    Medium,
    Thumbnail,
}

impl ImageVariant {
    pub(crate) fn snake_cased_name(&self) -> &'static str {
        match self {
            Self::Original => "original",
            Self::Medium => "medium",
            Self::Thumbnail => "thumbnail",
        }
    }
}

/// Image
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct Image {
    pub id: Id<Self>,
    pub color: ColorSummary,
    pub url: url::Url,
    pub external_checksum: Option<String>,
    pub external_id: Option<ExternalId<Self>>,
    pub uploaded_by: Option<Id<User>>,
    pub uploaded_at: DateTime<FixedOffset>,
    pub updated_at: DateTime<FixedOffset>,
    pub position: i32,
}

impl EntityRefPathParam for Image {
    fn parameter_name() -> &'static str {
        "image_ref"
    }
}

/// Image summary
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct ImageSummary {
    pub id: Id<Image>,
    pub url: url::Url,
    pub external_id: Option<ExternalId<Image>>,
}

impl RefTarget for Image {
    async fn lookup_id(
        client: &impl GenericClient,
        organization_id: Id<Organization>,
        entity_ref: &crate::entity_ref::Ref<Self>,
    ) -> crate::Result<Option<Id<Self>>> {
        let (id, external_id, _) = entity_ref.to_owned().take_all_inner();
        Ok(get_image_id()
            .bind(
                client,
                &organization_id.into(),
                &id,
                &external_id.as_deref(),
            )
            .opt()
            .await?
            .map(Id::new))
    }
}

/// Image, for upload
#[derive(Debug, Clone, Deserialize)]
pub struct UploadSourceImage {
    pub source_url: Url,
    pub color: Ref<Color>,
    /// An optional checksum. If it's provided this will be used to avoid unnecessary uploads.
    pub external_checksum: Option<String>,
    pub external_id: Option<ExternalId<Image>>,
    #[serde(default)]
    pub position: Option<i32>,
}

impl ExternalIdEntity for UploadSourceImage {
    type RefTarget = Image;

    fn external_id(&self) -> Option<ExternalId<Self::RefTarget>> {
        self.external_id.clone()
    }

    fn set_external_id(&mut self, value: ExternalId<Self::RefTarget>) {
        self.external_id = Some(value);
    }
}

/// Image, for creation
#[derive(Debug, Clone, Deserialize)]
pub struct UploadedImage {
    pub url: url::Url,
    pub color: Ref<Color>,
    pub external_id: Option<ExternalId<Image>>,
}

impl ExternalIdEntity for UploadedImage {
    type RefTarget = Image;

    fn external_id(&self) -> Option<ExternalId<Self::RefTarget>> {
        self.external_id.clone()
    }

    fn set_external_id(&mut self, value: ExternalId<Self::RefTarget>) {
        self.external_id = Some(value);
    }
}