dailp/person.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
use std::{fmt, str::FromStr};
use crate::{user::User, Database, PersonFullName};
use async_graphql::{SimpleObject, Union};
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, Type};
/// Record for a DAILP admin
#[derive(Clone, Debug, Serialize, Deserialize, async_graphql::SimpleObject)]
pub struct Admin {
/// Inherits from User
pub user: User,
}
/// An individual or organization that contributed to the creation or analysis
/// of a particular document or source. Each contributor has a name and a role
/// that specifies the type of their contributions.
#[derive(Clone, Debug, Serialize, Deserialize, async_graphql::SimpleObject, PartialEq, Eq)]
#[graphql(complex)]
pub struct Contributor {
/// UUID of the contributor
pub id: uuid::Uuid,
/// Full name of the contributor
pub name: String,
/// The role that defines most of their contributions to the associated item
pub role: Option<ContributorRole>,
}
/// Input Object for Contributor
#[derive(async_graphql::InputObject, Clone, Debug, Serialize, Deserialize)]
pub struct ContributorInput {
/// Full name of the contributor
pub name: String,
/// The role that defines most of their contributions to the associated item
pub role: String,
}
#[async_graphql::ComplexObject]
impl Contributor {
async fn details(
&self,
ctx: &async_graphql::Context<'_>,
) -> async_graphql::FieldResult<Option<ContributorDetails>> {
use async_graphql::dataloader::*;
Ok(ctx
.data::<DataLoader<Database>>()?
.load_one(PersonFullName(self.name.clone()))
.await?)
}
}
/// Basic personal details of an individual contributor, which can be retrieved
/// from a particular instance of [`Contributor`].
///
/// They may have transcribed a handwritten manuscript, translated it into
/// English, or analyzed it for linguistic information.
/// This information can be used to track who contributed to the development of
/// each individual document, and track contributions to the archive as a whole.
#[derive(async_graphql::SimpleObject, Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ContributorDetails {
/// Full name of this person, this exact string must be used to identify
/// them elsewhere, like in the attribution for a particular document.
pub full_name: String,
/// Alternate name of this person, may be in a different language or writing
/// system. Used only for descriptive purposes.
pub alternate_name: Option<String>,
/// The optional date that this contributor was born on.
pub birth_date: Option<crate::Date>,
/// Whether or not the contributor's profile is linked to their contributions
pub is_visible: bool,
}
/// A contributor can have to any number of roles, which define most of their
/// contributions to the associated item (add or revise as needed)
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, async_graphql::Enum, Type)]
#[sqlx(type_name = "contributor_role")]
#[sqlx(rename_all = "snake_case")]
pub enum ContributorRole {
/// Typed or transcribed handwritten materials
Transcriber,
/// Translated text into another language
Translator,
/// Added linguistic, cultural, etc. annotations
Annotator,
/// Provided cultural context for a document
CulturalAdvisor,
/// Author of a document
Author,
/// Edited a document
Editor,
}
impl From<String> for ContributorRole {
//type Err = String;
fn from(s: String) -> Self {
match s.to_lowercase().as_str() {
"transcriber" => ContributorRole::Transcriber,
"translator" => ContributorRole::Translator,
"annotator" => ContributorRole::Annotator,
"culturaladvisor" => ContributorRole::CulturalAdvisor,
"author" => ContributorRole::Author,
"editor" => ContributorRole::Editor,
other => panic!("{} is not a valid contributor role", s),
}
}
}
impl fmt::Display for ContributorRole {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
ContributorRole::Transcriber => "Transcriber",
ContributorRole::Translator => "Translator",
ContributorRole::Annotator => "Annotator",
ContributorRole::CulturalAdvisor => "CulturalAdvisor",
ContributorRole::Author => "Author",
ContributorRole::Editor => "Editor",
};
write!(f, "{}", s)
}
}
impl ContributorRole {
/// Attempts to parse a string into a ContributorRole, returning None if parsing fails
pub fn from_option_str(s: &str) -> Option<Self> {
// TODO: Make ContributorRole::from return a ContributorRole instead of a panic
Some(ContributorRole::from(s.to_string()))
}
/// Converts a ContributorRole into its string representation
pub fn to_option_string(role: &Option<ContributorRole>) -> Option<String> {
role.as_ref().map(|r| r.to_string())
}
}
#[derive(async_graphql::InputObject, Debug, Clone)]
pub struct ContributorAttributionInput {
pub name: String,
pub role: Option<ContributorRole>,
}
/// The creator of a document
#[derive(async_graphql::SimpleObject, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[graphql(complex)]
pub struct Creator {
/// UUID of the creator
pub id: uuid::Uuid,
/// Name of the creator
pub name: String,
}
// For updating creators
#[derive(async_graphql::InputObject, Clone, Debug)]
pub struct CreatorUpdate {
/// UUID for the creator
pub id: uuid::Uuid,
/// Name of the creator
pub name: String,
}
#[async_graphql::ComplexObject]
impl Creator {}
/// Attribution for a particular source, whether an institution or an individual.
/// Most commonly, this will represent the details of a library or archive that
/// houses documents used elsewhere.
#[derive(async_graphql::SimpleObject, Clone, Debug, Serialize, Deserialize)]
pub struct SourceAttribution {
/// Name of the source, i.e. "The Newberry Library"
pub name: String,
/// URL of this source's homepage, i.e. "https://www.newberry.org/"
pub link: String,
}