dailp/comment.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
//! Types that power our features for reading / leaving comments on words and
//! paragraphs
use crate::{user::User, AnnotatedForm};
use crate::{Database, DateTime, DocumentParagraph};
use async_graphql::Context;
use async_graphql::{dataloader::DataLoader, FieldResult, MaybeUndefined};
use serde::{Deserialize, Serialize};
use sqlx::types::Uuid;
/// A comment a user has made on some piece of a document.
#[derive(Clone, Serialize, Deserialize, Debug, async_graphql::SimpleObject)]
#[serde(rename_all = "camelCase")]
// #[graphql(complex)]
pub struct Comment {
/// Unique identifier of this comment
pub id: Uuid,
/// When the comment was posted
pub posted_at: DateTime,
/// Who posted the comment
pub posted_by: User,
/// The text of the comment
pub text_content: String,
/// An optional classification of the comment's content
pub comment_type: Option<CommentType>,
/// Whether the comment has been edited since it was posted
pub edited: bool,
/// The id of the word or paragraph this comment is attached to
#[graphql(skip = true)]
pub parent_id: Uuid,
/// The kind of entity parent ID points to
#[graphql(skip = true)]
pub parent_type: CommentParentType,
}
/// An enum listing the possible types that a comment could be attached to
#[derive(
sqlx::Type, async_graphql::Enum, Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize,
)]
#[sqlx(type_name = "comment_parent_type")]
pub enum CommentParentType {
/// A comment attached to a word
Word,
/// A comment attached to a paragraph
Paragraph,
}
impl CommentParentType {
/// Get the actual object referenced by this type, given an id
pub async fn resolve(&self, db: &Database, parent_id: &Uuid) -> FieldResult<CommentParent> {
match &self {
CommentParentType::Word => {
Ok(CommentParent::WordParent(db.word_by_id(parent_id).await?))
}
CommentParentType::Paragraph => Ok(CommentParent::ParagraphParent(
db.paragraph_by_id(parent_id).await?,
)),
}
}
}
#[async_graphql::ComplexObject]
impl Comment {
/// The parent entity of this comment
pub async fn parent(&self, context: &Context<'_>) -> FieldResult<CommentParent> {
let db = context.data::<DataLoader<Database>>()?.loader();
self.parent_type.resolve(db, &self.parent_id).await
}
}
/// A type describing the kind of comment being made
#[derive(
sqlx::Type, async_graphql::Enum, Clone, Copy, Eq, PartialEq, Hash, Debug, Serialize, Deserialize,
)]
#[sqlx(type_name = "comment_type_enum")]
pub enum CommentType {
/// A comment sharing a story or similar information related to the parent object
Story,
/// A comment with a suggestion to improve the information shown about the parent object
Suggestion,
/// A comment asking a question about our information regarding the parent object
Question,
}
/// PgHasArrayType for CommentType
impl sqlx::postgres::PgHasArrayType for CommentType {
fn array_type_info() -> sqlx::postgres::PgTypeInfo {
// The array type name in PostgreSQL is prefixed with an underscore
sqlx::postgres::PgTypeInfo::with_name("_comment_type_enum")
}
}
/// Type representing the object that a comment is attached to
#[derive(async_graphql::Union)]
pub enum CommentParent {
/// The word that the given comment is attached to
WordParent(AnnotatedForm),
/// The paragraph that the given comment is attached to
ParagraphParent(DocumentParagraph),
}
/// Input object for posting a new comment on some object
#[derive(async_graphql::InputObject)]
pub struct PostCommentInput {
/// ID of the object that is being commented on
pub parent_id: Uuid,
/// Type of the object being commented on
pub parent_type: CommentParentType,
/// Content of the comment
pub text_content: String,
/// A classifcation for the comment (optional)
pub comment_type: Option<CommentType>,
}
/// Input object for deleting an existing comment
#[derive(async_graphql::InputObject)]
pub struct DeleteCommentInput {
/// ID of the comment to delete
pub comment_id: Uuid,
}
/// Used for updating comments.
/// All fields except id are optional.
#[derive(async_graphql::InputObject)]
pub struct CommentUpdate {
/// The UUID of the comment to perform this operation on.
pub id: Uuid,
/// The text of the comment.
pub text_content: MaybeUndefined<String>,
/// The type of content in this comment. See dailp::comment::CommentType.
pub comment_type: MaybeUndefined<Option<CommentType>>,
/// Whether this comment has been edited in the past
pub edited: bool,
}