diff --git a/package.json b/package.json index e064613b..39f4ee06 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "recogito-client", "type": "module", - "version": "1.2.0", + "version": "1.2.1", "scripts": { "dev": "astro dev", "start": "astro dev", diff --git a/public/templates/reset.html b/public/templates/reset.html new file mode 100644 index 00000000..47621027 --- /dev/null +++ b/public/templates/reset.html @@ -0,0 +1,382 @@ + + + + + + Passowrd Reset Email + + + + + + + + + + + + diff --git a/src/components/Annotation/AnnotationCardSection.tsx b/src/components/Annotation/AnnotationCardSection.tsx index 271064ee..80ab5aa6 100644 --- a/src/components/Annotation/AnnotationCardSection.tsx +++ b/src/components/Annotation/AnnotationCardSection.tsx @@ -125,7 +125,11 @@ export const AnnotationCardSection = (props: AnnotationCardSectionProps) => { } }, [annotation, comment, index, present, tags]); - const isMine = creator?.id === me.id; + // Note that 'me' being undefined caused problems in the past, so we're + // just being a little defensive here. Context: me is usually derived from + // the (initialized) Annotorious user, which means it will be undefined + // until annotations are loaded. + const isMine = creator?.id === me?.id; // Comments are editable if they are mine, or I'm a layer admin const canEdit = !isReadOnly && (isMine || props.policies?.get('layers').has('INSERT')) && !isProjectLocked; diff --git a/src/components/AnnotationDesktop/DocumentNotes/DocumentNotes/DocumentNotes.tsx b/src/components/AnnotationDesktop/DocumentNotes/DocumentNotes/DocumentNotes.tsx index e8b648a0..842171b8 100644 --- a/src/components/AnnotationDesktop/DocumentNotes/DocumentNotes/DocumentNotes.tsx +++ b/src/components/AnnotationDesktop/DocumentNotes/DocumentNotes/DocumentNotes.tsx @@ -61,14 +61,12 @@ export const DocumentNotes = (props: DocumentNotesProps) => { const [channel, setChannel] = useState(); - useEffect(() => { - if (embeddedNotes) setNotes(current => ([...current, ...embeddedNotes])); - }, [embeddedNotes]); - useEffect(() => { if (documentLayerIds) { fetchNotes(documentLayerIds) - .then(notes => setNotes(current => ([...current, ...notes]))) + .then(notes => { + setNotes([...notes, ...(embeddedNotes || [])]) + }) .catch(onError); // Set up realtime channel @@ -109,7 +107,7 @@ export const DocumentNotes = (props: DocumentNotesProps) => { setChannel(undefined); } } - }, [documentLayerIds, props.present]); + }, [embeddedNotes, documentLayerIds, props.present]); return ( number; -const Newest = (a: DocumentNote, b: DocumentNote) => - b.created_at.getTime() - a.created_at.getTime(); +const Newest = (a: DocumentNote | SupabaseAnnotation, b: DocumentNote | SupabaseAnnotation) => { + const createdA = 'created_at' in a ? a.created_at : a.target.created; + const createdB = 'created_at' in b ? b.created_at : b.target.created; + return createdA && createdB ? createdB.getTime() - createdA.getTime() : 0; +} -const Oldest = (a: DocumentNote, b: DocumentNote) => - a.created_at.getTime() - b.created_at.getTime(); +const Oldest = (a: DocumentNote | SupabaseAnnotation, b: DocumentNote | SupabaseAnnotation) => { + const createdA = 'created_at' in a ? a.created_at : a.target.created; + const createdB = 'created_at' in b ? b.created_at : b.target.created; + return createdA && createdB ? createdA.getTime() - createdB.getTime() : 0; +} export const Sorting = { Newest, Oldest }; diff --git a/src/pages/[lang]/projects/[project]/export/pdf.ts b/src/pages/[lang]/projects/[project]/export/pdf.ts index 2d579086..b67009a7 100644 --- a/src/pages/[lang]/projects/[project]/export/pdf.ts +++ b/src/pages/[lang]/projects/[project]/export/pdf.ts @@ -170,9 +170,9 @@ const exportForAssignment = async ( ); } -export const GET: APIRoute = async ({ params, cookies, url }) => { +export const GET: APIRoute = async ({ request, params, cookies, url }) => { // Verify if the user is logged in - const supabase = await createSupabaseServerClient(cookies); + const supabase = await createSupabaseServerClient(request, cookies); const projectId = params.project!; diff --git a/src/util/export/sanitizeFilename.ts b/src/util/export/sanitizeFilename.ts index 4ff99c1f..b692b3bf 100644 --- a/src/util/export/sanitizeFilename.ts +++ b/src/util/export/sanitizeFilename.ts @@ -7,9 +7,12 @@ export const sanitizeFilename = (unsafe: string) => { replacement: '_', remove: /[*+~.()'"!:@]/g, lower: false, - strict: false, + strict: true, locale: 'en' }); - return sanitize(slugified); + // Additional safety net to remove or replace non-ASCII characters + const asciiOnly = slugified.replace(/[^\x00-\x7F]/g, '_'); + + return sanitize(asciiOnly); } \ No newline at end of file