diff --git a/client/cypress/e2e/frontend/modules/highlights.cy.ts b/client/cypress/e2e/frontend/modules/highlights.cy.ts index ad773ace..1ce882fe 100644 --- a/client/cypress/e2e/frontend/modules/highlights.cy.ts +++ b/client/cypress/e2e/frontend/modules/highlights.cy.ts @@ -66,6 +66,12 @@ const getAddHighlight = (pageType: string = 'ModuleNode') => { id: chapterId, __typename: 'ChapterNode', }; + } else if (pageType === 'InstrumentNode') { + page = { + slug: instrumentSlug, + id: instrumentId, + __typename: 'InstrumentNode', + }; } else { page = { id: moduleId, @@ -373,6 +379,7 @@ describe('Highlights', () => { cy.wait('@AddHighlight'); updateHighlight(highlightedText); cy.getByDataCy('highlight-mark').should('have.length', 1); + deleteHighlight(); }); it('visits an instrument and highlights some text', () => { @@ -462,4 +469,41 @@ describe('Highlights', () => { addNote(); deleteHighlight(); }); + + it('visits an instrument and highlights the intro', () => { + const intro = '

Something here in the intro, right?

'; + cy.mockGraphqlOps({ + operations: { + ...operations, + AddHighlight: getAddHighlight('InstrumentNode'), + InstrumentQuery: { + instrument: { + title: 'My Instrument', + id: instrumentId, + slug: instrumentSlug, + intro, + highlights: [], + contents: [ + { + type: 'text_block', + id: 'some-other-content-component-id', + value: { + text: '

Hello my beautiful World!

', + }, + }, + ], + }, + }, + }, + }); + cy.visit(`/instrument/${instrumentSlug}`); + cy.wait('@InstrumentQuery'); + cy.getByDataCy('instrument-intro').should('have.html', intro); + markText('instrument-intro'); + const highlightedText = 'mething he'; + createHighlight(highlightedText, false); + updateHighlight(highlightedText); + addNote(); + deleteHighlight(); + }); }); diff --git a/client/cypress/fixtures/mocks.ts b/client/cypress/fixtures/mocks.ts index ff72a8ab..73d23171 100644 --- a/client/cypress/fixtures/mocks.ts +++ b/client/cypress/fixtures/mocks.ts @@ -125,5 +125,6 @@ export default { }), HighlightNode: () => ({ note: null, + contentUuid: null, }), }; diff --git a/client/src/helpers/highlight.ts b/client/src/helpers/highlight.ts index 957c68ba..a3a0e8f7 100644 --- a/client/src/helpers/highlight.ts +++ b/client/src/helpers/highlight.ts @@ -253,12 +253,15 @@ export const createHighlightCurry = { update: (cache, { data }) => { const id = cache.identify(cacheSignature); + log.debug(id); const fragmentWithHighlights = cache.readFragment({ id, fragment, fragmentName, }); + log.debug(fragmentWithHighlights); const highlight = isContentHighlight ? data?.addContentHighlight?.highlight : data?.addHighlight?.highlight; + log.debug(highlight); if (highlight) { cache.writeFragment({ id, diff --git a/client/src/pages/instrument.vue b/client/src/pages/instrument.vue index e49b2f73..236ce3da 100644 --- a/client/src/pages/instrument.vue +++ b/client/src/pages/instrument.vue @@ -48,6 +48,7 @@ import { } from '@/helpers/highlight'; import { doUpdateHighlight } from '@/graphql/mutations'; import highlightSidebar from '@/helpers/highlight-sidebar'; +import Mark from 'mark.js'; const instrumentDiv = ref(null); const highlightIntro = ref(null); @@ -122,6 +123,9 @@ const markHighlights = (highlights: HighlightNode[], element: HTMLElement) => { let contentSelectionHandler: SelectionHandlerType, introSelectionHandler: SelectionHandlerType; onResult(async () => { + /* + * Important reminder: onResult gets called everytime the query result changes, also on cache updates! + */ const element = instrumentDiv.value; const intro = highlightIntro.value; const fragment = instrumentHighlightsFragment; @@ -191,12 +195,16 @@ onResult(async () => { } if (intro !== null) { - const introHighlights = instrument.value.highlights.filter((h) => h.contentUuid === null); await nextTick(); - markHighlights(introHighlights, intro); + unmark(); + markHighlights(introHighlights.value, intro); } }); +const introHighlights = computed(() => { + return instrument.value?.highlights?.filter((h) => h.contentUuid === null) || []; +}); + onUnmounted(() => { const element = instrumentDiv.value; @@ -205,6 +213,13 @@ onUnmounted(() => { element.removeEventListener('mouseup', introSelectionHandler); } }); + +const unmark = () => { + for (const paragraph of (highlightIntro.value as HTMLElement).children) { + const instance = new Mark(paragraph); + instance.unmark(); + } +};