Skip to content

Commit

Permalink
feat(db) added queries and implemented database_sql.rs functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
sammcvicker committed Nov 18, 2024
1 parent 5f4c5d3 commit dc24c43
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 32 deletions.
43 changes: 21 additions & 22 deletions graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -197,30 +197,30 @@ Element within a spreadsheet before being transformed into a full document.
union AnnotatedSeg = AnnotatedForm | LineBreak

"""
Request to attach user-recorded audio to a word
Request to attach user-recorded audio to a document
"""
input AttachAudioToWordInput {
input AttachAudioToDocumentInput {
"""
Word to bind audio to
Document to bind audio to
"""
wordId: UUID!
documentId: UUID!
"""
A URL to a Cloudfront-proxied user-recorded pronunciation of a word.
A URL to a Cloudfront-proxied user-recorded reading of a document.
A new resource will be created to represent the recording if one does not exist already
"""
contributorAudioUrl: String!
}

"""
Request to attach user-recorded audio to a document
Request to attach user-recorded audio to a word
"""
input AttachAudioToDocumentInput {
input AttachAudioToWordInput {
"""
Document to bind audio to
Word to bind audio to
"""
documentId: UUID!
wordId: UUID!
"""
A URL to a Cloudfront-proxied user-recorded reading of a document.
A URL to a Cloudfront-proxied user-recorded pronunciation of a word.
A new resource will be created to represent the recording if one does not exist already
"""
contributorAudioUrl: String!
Expand Down Expand Up @@ -433,13 +433,13 @@ type ContributorDetails {
}

"""
Request to update if a piece of word audio should be included in an edited collection
Request to update if a piece of document audio should be included in an edited collection
"""
input CurateWordAudioInput {
input CurateDocumentAudioInput {
"""
Word audio is attached to
Document audio is attached to
"""
wordId: UUID!
documentId: UUID!
"""
Audio to include/exclude
"""
Expand All @@ -451,13 +451,13 @@ input CurateWordAudioInput {
}

"""
Request to update if a piece of document audio should be included in an edited collection
Request to update if a piece of word audio should be included in an edited collection
"""
input CurateDocumentAudioInput {
input CurateWordAudioInput {
"""
Document audio is attached to
Word audio is attached to
"""
documentId: UUID!
wordId: UUID!
"""
Audio to include/exclude
"""
Expand Down Expand Up @@ -856,19 +856,18 @@ type Mutation {
"""
removeBookmark(documentId: UUID!): AnnotatedDoc!
"""
Decide if a piece word audio should be included in edited collection
Decide if a piece of word audio should be included in edited collection
"""
curateWordAudio(input: CurateWordAudioInput!): AnnotatedForm!
"""
Decide if a piece document audio should be included in edited collection
Decide if a piece of document audio should be included in edited collection
"""
curateDocumentAudio(input: CurateDocumentAudioInput!): AnnotatedDoc!
"""
Attach audio that has already been uploaded to S3 to a particular word
Assumes user requesting mutation recorded the audio
Assumes user requesting mutation recoreded the audio
"""
attachAudioToWord(input: AttachAudioToWordInput!): AnnotatedForm!
updateDocumentMetadata(document: DocumentMetadataUpdate!): UUID!
"""
Attach audio that has already been uploaded to S3 to a particular document
Assumes user requesting mutation recorded the audio
Expand Down
14 changes: 7 additions & 7 deletions graphql/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ impl Mutation {
let word_id = context
.data::<DataLoader<Database>>()?
.loader()
.update_audio_visibility(
.update_word_audio_visibility(
&input.word_id,
&input.audio_slice_id,
input.include_in_edited_collection,
Expand Down Expand Up @@ -608,9 +608,10 @@ impl Mutation {
.await?;
Ok(context
.data::<DataLoader<Database>>()?
.loader()
.load_one(&document_id.ok_or_else(|| anyhow::format_err!("Document audio not found"))?)
.await?)
.load_one(dailp::DocumentId(
document_id.ok_or_else(|| anyhow::format_err!("Document not found"))?
))
.await?.ok_or_else(|| anyhow::format_err!("Document not found"))?)
}

/// Attach audio that has already been uploaded to S3 to a particular word
Expand Down Expand Up @@ -655,9 +656,8 @@ impl Mutation {
.await?;
Ok(context
.data::<DataLoader<Database>>()?
.loader()
.load_one(&input.document_id)
.await?)
.load_one(dailp::DocumentId(input.document_id))
.await?.ok_or_else(|| anyhow::format_err!("Document not found"))?)
}

#[graphql(guard = "GroupGuard::new(UserGroup::Editors)")]
Expand Down
23 changes: 23 additions & 0 deletions types/queries/attach_audio_to_document.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-- Binds: user_id, resource_url, start, end, document_id

with upserted_audio_resource as (
insert into media_resource (url, recorded_at, recorded_by)
select $2::text, now(), $1
-- we do this no-op update to ensure an id is returned
on conflict (url) do update set url=excluded.url
returning id
),

inserted_audio_slice as (
insert into media_slice (resource_id, time_range)
select upserted_audio_resource.id, int8range($3, $4)
from upserted_audio_resource
returning id
)

insert into document_user_media (document_id, media_slice_id)
select $5, inserted_audio_slice.id
from inserted_audio_slice
join document on document.id = $5
on conflict (media_slice_id, document_id) do nothing -- document already associated
returning media_slice_id
18 changes: 18 additions & 0 deletions types/queries/document_contributor_audio.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
select
media_slice.id as "id",
media_slice.time_range as "range?",
media_resource.url as "resource_url",
document_user_media.include_in_edited_collection as "include_in_edited_collection",
media_resource.recorded_at as "recorded_at?",
contributor.id as "recorded_by?",
contributor.display_name as "recorded_by_name?",
editor.id as "edited_by?",
editor.display_name as "edited_by_name?"
from document_user_media
left join media_slice on media_slice.id = document_user_media.media_slice_id
left join media_resource on media_resource.id = media_slice.resource_id
left join dailp_user contributor on contributor.id = media_resource.recorded_by
left join dailp_user editor on editor.id = document_user_media.edited_by
where
document_id = $1
order by media_resource.recorded_at desc
28 changes: 28 additions & 0 deletions types/queries/update_document_audio_visibility.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-- Binds: document_id, slice_id, include_in_edited_collection, editor_id

with document_update as (
-- update ingested audio, if the slice_id was ingested audio
update document
set include_audio_in_edited_collection=$3,
audio_edited_by=$4
where document.id = $1
-- if the slice_id given doesn't match, we won't update
and document.audio_slice_id = $2
returning document.id as document_id
),
document_user_media_update as (
-- update user contributed audio, if the slice id is user contributed audio tied to the document
update document_user_media
set include_in_edited_collection=$3,
edited_by=$4
where document_id = $1
and media_slice_id = $2
returning document_id
)

select distinct t.document_id
from (
select document_id from document_update
union
select document_id from document_user_media_update
) as t
File renamed without changes.
63 changes: 60 additions & 3 deletions types/src/database_sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,20 @@ impl Database {
.collect())
}

pub async fn document_contributor_audio(&self, document_id: &Uuid) -> Result<Vec<AudioSlice>> {
let contributor_audio = query_file_as!(
BasicAudioSlice,
"queries/document_contributor_audio.sql",
document_id
)
.fetch_all(&self.client)
.await?;
Ok(contributor_audio
.into_iter()
.map(AudioSlice::from)
.collect())
}

pub async fn words_by_doc(
&self,
document_id: Option<DocumentId>,
Expand Down Expand Up @@ -666,17 +680,39 @@ impl Database {
Ok(media_slice_id)
}

/// Update if a piece of audio will be shown to readers
/// As above in `attach_audio_to_word`:
/// Creates media slice if doesn't yet exist for provided audio recording.
/// Adds join table entry attaching media slice to document.
/// Returns `id` of upserted media slice.
pub async fn attach_audio_to_document(
&self,
upload: &AttachAudioToDocumentInput,
contributor_id: &Uuid,
) -> Result<Uuid> {
let media_slice_id = query_file_scalar!(
"queries/attach_audio_to_document.sql",
contributor_id,
upload.contributor_audio_url as _,
0,
0,
upload.document_id
)
.fetch_one(&self.client)
.await?;
Ok(media_slice_id)
}

/// Update if a piece of word audio will be shown to readers
/// Will return None if the word and audio assocation could not be found, otherwise word id.
pub async fn update_audio_visibility(
pub async fn update_word_audio_visibility(
&self,
word_id: &Uuid,
audio_slice_id: &Uuid,
include_in_edited_collection: bool,
editor_id: &Uuid,
) -> Result<Option<Uuid>> {
let _word_id = query_file_scalar!(
"queries/update_audio_visibility.sql",
"queries/update_word_audio_visibility.sql",
word_id,
audio_slice_id,
include_in_edited_collection,
Expand All @@ -687,6 +723,27 @@ impl Database {
Ok(_word_id)
}

/// Update if a piece of document audio will be shown to readers
/// Will return None if the document and audio assocation could not be found, otherwise document id.
pub async fn update_document_audio_visibility(
&self,
document_id: &Uuid,
audio_slice_id: &Uuid,
include_in_edited_collection: bool,
editor_id: &Uuid,
) -> Result<Option<Uuid>> {
let _document_id = query_file_scalar!(
"queries/update_document_audio_visibility.sql",
document_id,
audio_slice_id,
include_in_edited_collection,
editor_id
)
.fetch_one(&self.client)
.await?;
Ok(_document_id)
}

pub async fn update_document_metadata(&self, document: DocumentMetadataUpdate) -> Result<Uuid> {
let title = document.title.into_vec();
let written_at: Option<Date> = document.written_at.value().map(Into::into);
Expand Down

0 comments on commit dc24c43

Please sign in to comment.