{@html clean(note.content)}
+diff --git a/src/langs/json/en.json b/src/langs/json/en.json index 1611e768e..c07aa8438 100644 --- a/src/langs/json/en.json +++ b/src/langs/json/en.json @@ -822,7 +822,6 @@ "modifyDesc": "Rearrange, rotate, delete, insert, and split pages.", "info": "Edit Document Info", "infoDesc": "Modify document information like description and related URL.", - "data": "Edit Tags and Data", "dataDesc": "Add tags and key/value pairs to categorize your document.", "sections": "Edit Sections", "sectionsDesc": "Add sections to organize your document with a table of contents.", @@ -838,11 +837,28 @@ "title": "Add-Ons", "pinned": "Pinned add-ons will appear here" }, + "data": { + "title": "Data & Tags", + "empty": "Use tags or key/value data to organize documents", + "tags": "Tags", + "data": "Data" + }, "projects": { "title": "Projects", "pinned": "Pinned projects will appear here" + }, + "toc": { + "empty": "Sections organize your document with a table of contents", + "notes": "Notes", + "pageAbbrev": "p.", + "sections": "Sections", + "title": "Notes & Sections" } }, + "notes": { + "empty": "Add notes to highlight and comment on your document", + "cta": "Annotate this document" + }, "viewer": { "notFound": "Document not found", "notFoundDesc": "The document you requested either does not exist or you lack permission to access it", diff --git a/src/lib/api/documents.test.ts b/src/lib/api/documents.test.ts index 41cc944a4..ffa3a0ff8 100644 --- a/src/lib/api/documents.test.ts +++ b/src/lib/api/documents.test.ts @@ -291,6 +291,9 @@ describe("document helper methods", () => { // invalid hash returns page 1 expect(documents.pageFromHash("#nopage")).toStrictEqual(1); + + // match a note hash + expect(documents.pageFromHash("#document/p2/a2000002")).toStrictEqual(2); }); test("pageUrl", ({ document }) => { diff --git a/src/lib/api/documents.ts b/src/lib/api/documents.ts index bda07bf9b..268bf2681 100644 --- a/src/lib/api/documents.ts +++ b/src/lib/api/documents.ts @@ -70,7 +70,7 @@ export async function get( "projects", "revisions", "sections", - "notes", + "notes.user", ]; endpoint.searchParams.set("expand", expand.join(",")); @@ -293,12 +293,13 @@ export function pageHashUrl(page: number): string { } /** - * The opposite of pageHashUrl, extracting a page number from a URL hash + * The opposite of pageHashUrl, extracting a page number from a URL hash. + * Note that this will also match note hash URLs, which use the same prefix. * * @param hash URL hash */ export function pageFromHash(hash: string): number { - const re = /^#document\/p(\d+)$/; + const re = /^#document\/p(\d+)/; // match pages and notes const match = re.exec(hash); if (!match) return 1; diff --git a/src/lib/api/fixtures/documents/document-expanded.json b/src/lib/api/fixtures/documents/document-expanded.json index 9b51b69a0..758eb2dcd 100644 --- a/src/lib/api/fixtures/documents/document-expanded.json +++ b/src/lib/api/fixtures/documents/document-expanded.json @@ -74,7 +74,17 @@ "notes": [ { "id": 551, - "user": 126, + "user": { + "id": 126, + "avatar_url": "", + "name": "Chris Amico", + "organization": 14187, + "organizations": [14187], + "admin_organizations": [14187], + "username": "ChrisAmico_lSozDZNW", + "uuid": "caea06a2-ee1c-43e6-865a-a09078522bf1", + "verified_journalist": true + }, "organization": 60, "page_number": 0, "access": "public", @@ -90,7 +100,17 @@ }, { "id": 549, - "user": 126, + "user": { + "id": 126, + "avatar_url": "", + "name": "Chris Amico", + "organization": 14187, + "organizations": [14187], + "admin_organizations": [14187], + "username": "ChrisAmico_lSozDZNW", + "uuid": "caea06a2-ee1c-43e6-865a-a09078522bf1", + "verified_journalist": true + }, "organization": 60, "page_number": 0, "access": "public", @@ -106,7 +126,17 @@ }, { "id": 550, - "user": 126, + "user": { + "id": 126, + "avatar_url": "", + "name": "Chris Amico", + "organization": 14187, + "organizations": [14187], + "admin_organizations": [14187], + "username": "ChrisAmico_lSozDZNW", + "uuid": "caea06a2-ee1c-43e6-865a-a09078522bf1", + "verified_journalist": true + }, "organization": 60, "page_number": 0, "access": "public", @@ -122,7 +152,17 @@ }, { "id": 552, - "user": 126, + "user": { + "id": 126, + "avatar_url": "", + "name": "Chris Amico", + "organization": 14187, + "organizations": [14187], + "admin_organizations": [14187], + "username": "ChrisAmico_lSozDZNW", + "uuid": "caea06a2-ee1c-43e6-865a-a09078522bf1", + "verified_journalist": true + }, "organization": 60, "page_number": 0, "access": "public", @@ -138,7 +178,17 @@ }, { "id": 554, - "user": 126, + "user": { + "id": 126, + "avatar_url": "", + "name": "Chris Amico", + "organization": 14187, + "organizations": [14187], + "admin_organizations": [14187], + "username": "ChrisAmico_lSozDZNW", + "uuid": "caea06a2-ee1c-43e6-865a-a09078522bf1", + "verified_journalist": true + }, "organization": 60, "page_number": 1, "access": "public", @@ -154,7 +204,17 @@ }, { "id": 553, - "user": 126, + "user": { + "id": 126, + "avatar_url": "", + "name": "Chris Amico", + "organization": 14187, + "organizations": [14187], + "admin_organizations": [14187], + "username": "ChrisAmico_lSozDZNW", + "uuid": "caea06a2-ee1c-43e6-865a-a09078522bf1", + "verified_journalist": true + }, "organization": 60, "page_number": 1, "access": "public", @@ -170,7 +230,17 @@ }, { "id": 556, - "user": 126, + "user": { + "id": 126, + "avatar_url": "", + "name": "Chris Amico", + "organization": 14187, + "organizations": [14187], + "admin_organizations": [14187], + "username": "ChrisAmico_lSozDZNW", + "uuid": "caea06a2-ee1c-43e6-865a-a09078522bf1", + "verified_journalist": true + }, "organization": 60, "page_number": 2, "access": "public", @@ -186,7 +256,17 @@ }, { "id": 555, - "user": 126, + "user": { + "id": 126, + "avatar_url": "", + "name": "Chris Amico", + "organization": 14187, + "organizations": [14187], + "admin_organizations": [14187], + "username": "ChrisAmico_lSozDZNW", + "uuid": "caea06a2-ee1c-43e6-865a-a09078522bf1", + "verified_journalist": true + }, "organization": 60, "page_number": 2, "access": "public", @@ -202,7 +282,17 @@ }, { "id": 557, - "user": 126, + "user": { + "id": 126, + "avatar_url": "", + "name": "Chris Amico", + "organization": 14187, + "organizations": [14187], + "admin_organizations": [14187], + "username": "ChrisAmico_lSozDZNW", + "uuid": "caea06a2-ee1c-43e6-865a-a09078522bf1", + "verified_journalist": true + }, "organization": 60, "page_number": 2, "access": "public", @@ -218,7 +308,17 @@ }, { "id": 558, - "user": 126, + "user": { + "id": 126, + "avatar_url": "", + "name": "Chris Amico", + "organization": 14187, + "organizations": [14187], + "admin_organizations": [14187], + "username": "ChrisAmico_lSozDZNW", + "uuid": "caea06a2-ee1c-43e6-865a-a09078522bf1", + "verified_journalist": true + }, "organization": 60, "page_number": 2, "access": "public", @@ -234,7 +334,17 @@ }, { "id": 560, - "user": 126, + "user": { + "id": 126, + "avatar_url": "", + "name": "Chris Amico", + "organization": 14187, + "organizations": [14187], + "admin_organizations": [14187], + "username": "ChrisAmico_lSozDZNW", + "uuid": "caea06a2-ee1c-43e6-865a-a09078522bf1", + "verified_journalist": true + }, "organization": 60, "page_number": 4, "access": "public", @@ -250,7 +360,17 @@ }, { "id": 559, - "user": 126, + "user": { + "id": 126, + "avatar_url": "", + "name": "Chris Amico", + "organization": 14187, + "organizations": [14187], + "admin_organizations": [14187], + "username": "ChrisAmico_lSozDZNW", + "uuid": "caea06a2-ee1c-43e6-865a-a09078522bf1", + "verified_journalist": true + }, "organization": 60, "page_number": 4, "access": "public", @@ -266,7 +386,17 @@ }, { "id": 562, - "user": 126, + "user": { + "id": 126, + "avatar_url": "", + "name": "Chris Amico", + "organization": 14187, + "organizations": [14187], + "admin_organizations": [14187], + "username": "ChrisAmico_lSozDZNW", + "uuid": "caea06a2-ee1c-43e6-865a-a09078522bf1", + "verified_journalist": true + }, "organization": 60, "page_number": 5, "access": "public", @@ -282,7 +412,17 @@ }, { "id": 561, - "user": 126, + "user": { + "id": 126, + "avatar_url": "", + "name": "Chris Amico", + "organization": 14187, + "organizations": [14187], + "admin_organizations": [14187], + "username": "ChrisAmico_lSozDZNW", + "uuid": "caea06a2-ee1c-43e6-865a-a09078522bf1", + "verified_journalist": true + }, "organization": 60, "page_number": 5, "access": "public", @@ -298,7 +438,17 @@ }, { "id": 563, - "user": 126, + "user": { + "id": 126, + "avatar_url": "", + "name": "Chris Amico", + "organization": 14187, + "organizations": [14187], + "admin_organizations": [14187], + "username": "ChrisAmico_lSozDZNW", + "uuid": "caea06a2-ee1c-43e6-865a-a09078522bf1", + "verified_journalist": true + }, "organization": 60, "page_number": 6, "access": "public", diff --git a/src/lib/api/fixtures/documents/examples/agreement-between-conservatives-and-liberal-democrats-to-form-a-coalition-government.pdf b/src/lib/api/fixtures/documents/examples/agreement-between-conservatives-and-liberal-democrats-to-form-a-coalition-government.pdf new file mode 100644 index 000000000..60a92f531 Binary files /dev/null and b/src/lib/api/fixtures/documents/examples/agreement-between-conservatives-and-liberal-democrats-to-form-a-coalition-government.pdf differ diff --git a/src/lib/api/notes.test.ts b/src/lib/api/notes.test.ts index 9648b9a5f..705c9c040 100644 --- a/src/lib/api/notes.test.ts +++ b/src/lib/api/notes.test.ts @@ -33,6 +33,16 @@ describe("note helper methods", () => { ); }); + test("noteHashUrl", () => { + expect(notes.noteHashUrl(n)).toStrictEqual("#document/p3/a557"); + }); + + test("noteFromHash", () => { + const hash = notes.noteHashUrl(n); + + expect(notes.noteFromHash(hash)).toStrictEqual(n.id); + }); + test("width", () => { expect(notes.width(n)).toStrictEqual(n.x2 - n.x1); }); diff --git a/src/lib/api/notes.ts b/src/lib/api/notes.ts index 91d6eeac2..6a2f87ff0 100644 --- a/src/lib/api/notes.ts +++ b/src/lib/api/notes.ts @@ -71,6 +71,29 @@ export function noteUrl(document: Document, note: Note): URL { ); } +/** + * Generate the hash URL for a note, without the document URL + * @param note + * @returns hash + */ +export function noteHashUrl(note: Note): string { + return `#document/p${note.page_number + 1}/a${note.id}`; +} + +/** + * Opposite of noteHashUrl, returning a note ID. + * To get the page number, use pageFromHash + * @param hash + */ +export function noteFromHash(hash: string): number { + const re = /^#document\/p(\d+)\/a(\d+)$/; + const match = re.exec(hash); + + if (!match) return null; + + return +match[2] || null; +} + /** Width of a note, relative to the document */ export function width(note: Note): number { return note.x2 - note.x1; diff --git a/src/lib/components/common/Action.svelte b/src/lib/components/common/Action.svelte index 6dd7bb41d..6b0783790 100644 --- a/src/lib/components/common/Action.svelte +++ b/src/lib/components/common/Action.svelte @@ -26,8 +26,8 @@ border-radius: 0.5rem; background: transparent; - color: var(--primary, --blue-3, #4294f0); - fill: var(--primary, --blue-3, #4294f0); + color: var(--color, var(--primary, --blue-3, #4294f0)); + fill: var(--fill, var(--primary, --blue-3, #4294f0)); font-size: var(--font-xs, 0.75rem); font-weight: var(--font-bold, 700); diff --git a/src/lib/components/common/KV.svelte b/src/lib/components/common/KV.svelte index cb6678a92..08e204888 100644 --- a/src/lib/components/common/KV.svelte +++ b/src/lib/components/common/KV.svelte @@ -1,11 +1,12 @@ -
{@html clean(note.content)}
+Use tags or key/value data to organize documents
+{$_("sidebar.data.empty")}
{$_("notes.empty")}
+ {/if} +Sections organize your document with a table of contents
+{$_("sidebar.toc.empty")}