From 75964408729fb14903bf743ea5ed696354148671 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 28 Nov 2024 08:44:27 +0100 Subject: [PATCH 1/6] More aggressive download filename sanitization --- src/util/export/sanitizeFilename.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 From a2b7428ca59dd313fcc2bd06aef8736c7d1d4890 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Tue, 3 Dec 2024 07:24:22 +0100 Subject: [PATCH 2/6] package.json version number --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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", From 124f62bf278907b278ea864e5707879b5f39ec14 Mon Sep 17 00:00:00 2001 From: lorinjameson Date: Tue, 3 Dec 2024 09:16:17 -0500 Subject: [PATCH 3/6] Email template for self hosting --- public/templates/reset.html | 382 ++++++++++++++++++++++++++++++++++++ 1 file changed, 382 insertions(+) create mode 100644 public/templates/reset.html 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 + + + + + + + + + + + + From 068a8b7fa59ba03e8fcd8a786d3ef32dc49376b3 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Wed, 4 Dec 2024 09:07:07 +0100 Subject: [PATCH 4/6] Fixing duplicate notes + JS exception when sorting embedded notes --- .../DocumentNotes/DocumentNotes/DocumentNotes.tsx | 10 ++++------ .../DocumentNotes/SortSelector/Sorting.ts | 15 +++++++++++---- 2 files changed, 15 insertions(+), 10 deletions(-) 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 }; From 9b1cc77b614c9070ec57f922c9a6e2e87722cb7e Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Wed, 4 Dec 2024 09:24:34 +0100 Subject: [PATCH 5/6] Extra safety net for AnnotationCardSection --- src/components/Annotation/AnnotationCardSection.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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; From 1395c25db92f4f4f1453488d29ba107327bb1b25 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Wed, 4 Dec 2024 14:14:32 +0100 Subject: [PATCH 6/6] Minor regression fix --- src/pages/[lang]/projects/[project]/export/pdf.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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!;