diff --git a/client/cypress/e2e/frontend/modules/highlights.cy.ts b/client/cypress/e2e/frontend/modules/highlights.cy.ts index ae0360fd..ad773ace 100644 --- a/client/cypress/e2e/frontend/modules/highlights.cy.ts +++ b/client/cypress/e2e/frontend/modules/highlights.cy.ts @@ -1,6 +1,14 @@ +import log from 'loglevel'; import { defaultModuleQueriesandMutations } from '../../../support/helpers'; import { instrumentWithLongContent } from './instrument-highlights'; +const contentBlockId = window.btoa('ContentBlockNode:1'); +const instrumentId = window.btoa('InstrumentNode:2'); +const instrumentSlug = 'my-instrument'; +const chapterId = window.btoa('ChapterNode:3'); +const moduleId = window.btoa('ModuleNode:3'); +const moduleSlug = 'my-module'; + const getModule = (contents) => { return { intro: '

Introducing this great paragraph!

', @@ -9,6 +17,8 @@ const getModule = (contents) => { { title: 'A Chapter', description: 'This is something else', + highlights: [], + id: chapterId, contentBlocks: [ { title: 'A Content Block', @@ -48,14 +58,8 @@ const contentListContents = [ }, ]; -const contentBlockId = window.btoa('ContentBlockNode:1'); -const instrumentId = window.btoa('InstrumentNode:2'); -const instrumentSlug = 'my-instrument'; -const chapterId = window.btoa('ChapterNode:3'); -const moduleId = window.btoa('ModuleNode:3'); -const moduleSlug = 'my-module'; - const getAddHighlight = (pageType: string = 'ModuleNode') => { + log.debug(`adding highlight for page ${pageType}`); let page: { id: string; __typename: string; slug?: string }; if (pageType === 'ChapterNode') { page = { @@ -84,6 +88,7 @@ const getAddHighlight = (pageType: string = 'ModuleNode') => { }; const getAddContentHighlight = (pageType: string = 'ContentBlockNode') => { + log.debug(`adding content highlight for page type ${pageType}`); let page: { id: string; __typename: string; slug?: string }; if (pageType === 'InstrumentNode') { page = { @@ -114,7 +119,7 @@ const getAddContentHighlight = (pageType: string = 'ContentBlockNode') => { let lastHighlight; const defaultModule = getModule(defaultContents); -const operations = { +const getOperations = (pageType = 'ModuleNode') => ({ ...defaultModuleQueriesandMutations, ModuleDetailsQuery: { module: defaultModule, @@ -124,8 +129,8 @@ const operations = { lastModule: defaultModule, }, }, - AddHighlight: getAddHighlight(), - AddContentHighlight: getAddContentHighlight(), + AddHighlight: getAddHighlight(pageType), + AddContentHighlight: getAddContentHighlight(pageType), UpdateHighlight: ({ input: { note, color } }) => { lastHighlight = { ...lastHighlight, @@ -143,7 +148,9 @@ const operations = { success: true, }, }, -}; +}); + +const operations = getOperations(); const selectText = (elm: Node, start: number, end: number) => { const range = document.createRange(); @@ -335,7 +342,7 @@ describe('Highlights', () => { it('visits a module and highlights the chapter description', () => { cy.mockGraphqlOps({ - operations, + operations: getOperations('ChapterNode'), }); cy.visit('/module/my-module'); @@ -348,6 +355,8 @@ describe('Highlights', () => { cy.wait('@AddHighlight'); updateHighlight(highlightedText); cy.getByDataCy('highlight-mark').should('have.length', 1); + + deleteHighlight(); }); it('visits a module and highlights the module description', () => { cy.mockGraphqlOps({ diff --git a/client/src/__generated__/gql.ts b/client/src/__generated__/gql.ts index 8f5d9be2..6f945250 100644 --- a/client/src/__generated__/gql.ts +++ b/client/src/__generated__/gql.ts @@ -32,8 +32,10 @@ const documents = { "\n mutation UpdateHighlight($input: UpdateHighlightInput!) {\n updateHighlight(input: $input) {\n highlight {\n ...HighlightParts\n }\n }\n }\n": types.UpdateHighlightDocument, "\n mutation AddHighlight($input: AddHighlightInput!) {\n addHighlight(input: $input) {\n __typename\n highlight {\n ...HighlightParts\n }\n }\n }\n": types.AddHighlightDocument, "\n mutation AddContentHighlight($input: AddContentHighlightInput!) {\n addContentHighlight(input: $input) {\n __typename\n highlight {\n ...HighlightParts\n }\n }\n }\n": types.AddContentHighlightDocument, - "\n fragment InstrumentHighlightsWithIdOnlyFragment on InstrumentNode {\n highlights {\n id\n }\n }\n ": types.InstrumentHighlightsWithIdOnlyFragmentFragmentDoc, - "\n fragment ContentBlockHighlightsWithIdOnlyFragment on ContentBlockNode {\n highlights {\n id\n }\n }\n ": types.ContentBlockHighlightsWithIdOnlyFragmentFragmentDoc, + "\n fragment InstrumentHighlightsWithIdOnlyFragment on InstrumentNode {\n highlights {\n id\n }\n }\n ": types.InstrumentHighlightsWithIdOnlyFragmentFragmentDoc, + "\n fragment ChapterHighlightsWithIdOnlyFragment on ChapterNode {\n highlights {\n id\n }\n }\n ": types.ChapterHighlightsWithIdOnlyFragmentFragmentDoc, + "\n fragment ModuleHighlightsWithIdOnlyFragment on ModuleNode {\n highlights {\n id\n }\n }\n ": types.ModuleHighlightsWithIdOnlyFragmentFragmentDoc, + "\n fragment ContentBlockHighlightsWithIdOnlyFragment on ContentBlockNode {\n highlights {\n id\n }\n }\n ": types.ContentBlockHighlightsWithIdOnlyFragmentFragmentDoc, "\n mutation UpdateInstrumentBookmark($input: UpdateInstrumentBookmarkInput!) {\n updateInstrumentBookmark(input: $input) {\n success\n }\n }\n ": types.UpdateInstrumentBookmarkDocument, "\n mutation UpdateContentBookmark($input: UpdateContentBookmarkInput!) {\n updateContentBookmark(input: $input) {\n success\n }\n }\n ": types.UpdateContentBookmarkDocument, "\n query MyActivitiesQuery {\n myActivities {\n instruments {\n id\n slug\n title\n path\n highlights {\n ...HighlightParts\n }\n bookmarks {\n ... on InstrumentBookmarkNode {\n path\n }\n }\n }\n topics {\n id\n title\n modules {\n id\n slug\n title\n metaTitle\n myHighlights {\n ...HighlightParts\n }\n myBookmarks {\n ... on ChapterBookmarkNode {\n chapter {\n path\n }\n path\n note {\n id\n text\n }\n }\n ... on ContentBlockBookmarkNode {\n id\n uuid\n path\n contentBlock {\n id\n path\n }\n note {\n id\n text\n }\n }\n ... on ModuleBookmarkNode {\n path\n note {\n id\n text\n }\n }\n }\n mySubmissions {\n id\n text\n assignment {\n id\n title\n path\n module {\n slug\n }\n }\n }\n myAnswers {\n id\n survey {\n path\n id\n title\n }\n }\n }\n }\n }\n }\n ": types.MyActivitiesQueryDocument, @@ -140,11 +142,19 @@ export function graphql(source: "\n mutation AddContentHighlight($input: AddCon /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n fragment InstrumentHighlightsWithIdOnlyFragment on InstrumentNode {\n highlights {\n id\n }\n }\n "): (typeof documents)["\n fragment InstrumentHighlightsWithIdOnlyFragment on InstrumentNode {\n highlights {\n id\n }\n }\n "]; +export function graphql(source: "\n fragment InstrumentHighlightsWithIdOnlyFragment on InstrumentNode {\n highlights {\n id\n }\n }\n "): (typeof documents)["\n fragment InstrumentHighlightsWithIdOnlyFragment on InstrumentNode {\n highlights {\n id\n }\n }\n "]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n fragment ContentBlockHighlightsWithIdOnlyFragment on ContentBlockNode {\n highlights {\n id\n }\n }\n "): (typeof documents)["\n fragment ContentBlockHighlightsWithIdOnlyFragment on ContentBlockNode {\n highlights {\n id\n }\n }\n "]; +export function graphql(source: "\n fragment ChapterHighlightsWithIdOnlyFragment on ChapterNode {\n highlights {\n id\n }\n }\n "): (typeof documents)["\n fragment ChapterHighlightsWithIdOnlyFragment on ChapterNode {\n highlights {\n id\n }\n }\n "]; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql(source: "\n fragment ModuleHighlightsWithIdOnlyFragment on ModuleNode {\n highlights {\n id\n }\n }\n "): (typeof documents)["\n fragment ModuleHighlightsWithIdOnlyFragment on ModuleNode {\n highlights {\n id\n }\n }\n "]; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql(source: "\n fragment ContentBlockHighlightsWithIdOnlyFragment on ContentBlockNode {\n highlights {\n id\n }\n }\n "): (typeof documents)["\n fragment ContentBlockHighlightsWithIdOnlyFragment on ContentBlockNode {\n highlights {\n id\n }\n }\n "]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/client/src/__generated__/graphql.ts b/client/src/__generated__/graphql.ts index 093dced7..c12d4bd9 100644 --- a/client/src/__generated__/graphql.ts +++ b/client/src/__generated__/graphql.ts @@ -763,7 +763,7 @@ export type HighlightNode = Node & { /** The ID of the object */ id: Scalars['ID']['output']; note?: Maybe; - page?: Maybe; + page: HighlightableNode; paragraphIndex: Scalars['Int']['output']; selectionLength: Scalars['Int']['output']; startPosition: Scalars['Int']['output']; @@ -2667,7 +2667,7 @@ export type ChapterHighlightsFragmentFragment = { __typename: 'ChapterNode', id: & { ' $fragmentRefs'?: { 'HighlightPartsFragment': HighlightPartsFragment } } ) | null> | null } & { ' $fragmentName'?: 'ChapterHighlightsFragmentFragment' }; -export type HighlightPartsFragment = { __typename?: 'HighlightNode', id: string, contentIndex?: number | null, paragraphIndex: number, selectionLength: number, contentUuid?: any | null, startPosition: number, color: string, text: string, note?: { __typename?: 'NoteNode', text: string } | null, page?: { __typename: 'ChapterNode', id: string, path?: string | null, slug: string } | { __typename: 'ContentBlockNode', id: string, path?: string | null } | { __typename: 'InstrumentNode', id: string, slug: string } | { __typename: 'ModuleNode', id: string, slug: string, path?: string | null } | null } & { ' $fragmentName'?: 'HighlightPartsFragment' }; +export type HighlightPartsFragment = { __typename?: 'HighlightNode', id: string, contentIndex?: number | null, paragraphIndex: number, selectionLength: number, contentUuid?: any | null, startPosition: number, color: string, text: string, note?: { __typename?: 'NoteNode', text: string } | null, page: { __typename: 'ChapterNode', id: string, path?: string | null, slug: string } | { __typename: 'ContentBlockNode', id: string, path?: string | null } | { __typename: 'InstrumentNode', id: string, slug: string } | { __typename: 'ModuleNode', id: string, slug: string, path?: string | null } } & { ' $fragmentName'?: 'HighlightPartsFragment' }; export type ContentBlockHighlightsFragmentFragment = { __typename: 'ContentBlockNode', id: string, highlights?: Array<( { __typename?: 'HighlightNode' } @@ -2775,6 +2775,10 @@ export type AddContentHighlightMutation = { __typename?: 'Mutation', addContentH export type InstrumentHighlightsWithIdOnlyFragmentFragment = { __typename?: 'InstrumentNode', highlights: Array<{ __typename?: 'HighlightNode', id: string }> } & { ' $fragmentName'?: 'InstrumentHighlightsWithIdOnlyFragmentFragment' }; +export type ChapterHighlightsWithIdOnlyFragmentFragment = { __typename?: 'ChapterNode', highlights?: Array<{ __typename?: 'HighlightNode', id: string } | null> | null } & { ' $fragmentName'?: 'ChapterHighlightsWithIdOnlyFragmentFragment' }; + +export type ModuleHighlightsWithIdOnlyFragmentFragment = { __typename?: 'ModuleNode', highlights?: Array<{ __typename?: 'HighlightNode', id: string } | null> | null } & { ' $fragmentName'?: 'ModuleHighlightsWithIdOnlyFragmentFragment' }; + export type ContentBlockHighlightsWithIdOnlyFragmentFragment = { __typename?: 'ContentBlockNode', highlights?: Array<{ __typename?: 'HighlightNode', id: string } | null> | null } & { ' $fragmentName'?: 'ContentBlockHighlightsWithIdOnlyFragmentFragment' }; export type UpdateInstrumentBookmarkMutationVariables = Exact<{ @@ -2867,6 +2871,8 @@ export const SnapshotListItemFragmentDoc = {"kind":"Document","definitions":[{"k export const SnapshotTitleFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SnapshotTitleFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"SnapshotNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"title"}}]}}]} as unknown as DocumentNode; export const SnapshotDetailsFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"SnapshotDetailsFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"SnapshotNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"shared"}},{"kind":"Field","name":{"kind":"Name","value":"created"}},{"kind":"Field","name":{"kind":"Name","value":"creator"}},{"kind":"Field","name":{"kind":"Name","value":"mine"}}]}}]} as unknown as DocumentNode; export const InstrumentHighlightsWithIdOnlyFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"InstrumentHighlightsWithIdOnlyFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"InstrumentNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"highlights"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode; +export const ChapterHighlightsWithIdOnlyFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ChapterHighlightsWithIdOnlyFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ChapterNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"highlights"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode; +export const ModuleHighlightsWithIdOnlyFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ModuleHighlightsWithIdOnlyFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ModuleNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"highlights"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode; export const ContentBlockHighlightsWithIdOnlyFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ContentBlockHighlightsWithIdOnlyFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ContentBlockNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"highlights"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode; export const InstrumentPartsFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"InstrumentParts"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"InstrumentNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"intro"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"language"}},{"kind":"Field","name":{"kind":"Name","value":"bookmarks"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"uuid"}},{"kind":"Field","name":{"kind":"Name","value":"note"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"text"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"type"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"category"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"foreground"}},{"kind":"Field","name":{"kind":"Name","value":"background"}}]}},{"kind":"Field","name":{"kind":"Name","value":"type"}}]}},{"kind":"Field","name":{"kind":"Name","value":"contents"}},{"kind":"Field","name":{"kind":"Name","value":"highlights"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"HighlightParts"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"HighlightParts"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"HighlightNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"contentIndex"}},{"kind":"Field","name":{"kind":"Name","value":"paragraphIndex"}},{"kind":"Field","name":{"kind":"Name","value":"selectionLength"}},{"kind":"Field","name":{"kind":"Name","value":"contentUuid"}},{"kind":"Field","name":{"kind":"Name","value":"startPosition"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"note"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"text"}}]}},{"kind":"Field","name":{"kind":"Name","value":"text"}},{"kind":"Field","name":{"kind":"Name","value":"page"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ContentBlockNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"path"}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"InstrumentNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ModuleNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"path"}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ChapterNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"path"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}}]}}]}}]}}]} as unknown as DocumentNode; export const InstrumentHighlightsFragmentFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"instrumentHighlightsFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"InstrumentNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"highlights"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"HighlightParts"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"HighlightParts"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"HighlightNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"contentIndex"}},{"kind":"Field","name":{"kind":"Name","value":"paragraphIndex"}},{"kind":"Field","name":{"kind":"Name","value":"selectionLength"}},{"kind":"Field","name":{"kind":"Name","value":"contentUuid"}},{"kind":"Field","name":{"kind":"Name","value":"startPosition"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"note"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"text"}}]}},{"kind":"Field","name":{"kind":"Name","value":"text"}},{"kind":"Field","name":{"kind":"Name","value":"page"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ContentBlockNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"path"}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"InstrumentNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ModuleNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"path"}}]}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ChapterNode"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"path"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}}]}}]}}]}}]} as unknown as DocumentNode; diff --git a/client/src/components/content-blocks/ContentComponent.vue b/client/src/components/content-blocks/ContentComponent.vue index e7a882f7..2dbaae69 100644 --- a/client/src/components/content-blocks/ContentComponent.vue +++ b/client/src/components/content-blocks/ContentComponent.vue @@ -218,7 +218,7 @@ const bookmarkContent = (bookmarked: boolean) => { const markHighlights = () => { for (const highlight of filteredHighlights.value) { const element = childElements.value[highlight.paragraphIndex]; - markHighlight(highlight, element, contentComponentDiv.value); + markHighlight(highlight, element, contentComponentDiv.value as HTMLElement); } }; diff --git a/client/src/helpers/highlight.ts b/client/src/helpers/highlight.ts index 81cf77e9..957c68ba 100644 --- a/client/src/helpers/highlight.ts +++ b/client/src/helpers/highlight.ts @@ -338,7 +338,7 @@ const markClickListenerCurry = }); }; -export const markHighlight = (highlight: HighlightNode, element: HTMLElement, popoverElement: HTMLElement | null) => { +export const markHighlight = (highlight: HighlightNode, element: HTMLElement, popoverElement: HTMLElement) => { const instance = new Mark(element); const ranges: Mark.Range[] = [ { @@ -365,6 +365,67 @@ export const markHighlight = (highlight: HighlightNode, element: HTMLElement, po }); }; +// type them out, so the static codegen can do its work +const fragments = { + InstrumentNode: graphql(` + fragment InstrumentHighlightsWithIdOnlyFragment on InstrumentNode { + highlights { + id + } + } + `), + ChapterNode: graphql(` + fragment ChapterHighlightsWithIdOnlyFragment on ChapterNode { + highlights { + id + } + } + `), + ModuleNode: graphql(` + fragment ModuleHighlightsWithIdOnlyFragment on ModuleNode { + highlights { + id + } + } + `), + ContentBlockNode: graphql(` + fragment ContentBlockHighlightsWithIdOnlyFragment on ContentBlockNode { + highlights { + id + } + } + `), +}; + +const getCacheProperties = (cache, page, typename, identifier) => { + log.debug(`page is a ${typename}, remove highlights`); + const fragment = fragments[typename]; + const id = cache.identify({ + __typename: typename, + [identifier]: page[identifier], + }); + log.debug(`id found: ${id}`); + return { fragment, id }; +}; + +const cacheIdentifiers = { + InstrumentNode: 'slug', + ModuleNode: 'slug', + ChapterNode: 'id', + ContentBlockNode: 'id', +}; + +const getFragment = (cache, page: HighlightableNode) => { + const typename = page.__typename as string; + const identifier = cacheIdentifiers[typename]; + const { fragment, id } = getCacheProperties(cache, page, typename, identifier); + const foundFragment = cache.readFragment({ + fragment, + id, + }); + return { fragment, id, foundFragment }; +}; + export const deleteHighlightCurry = (highlight: HighlightNode) => () => { doDeleteHighlight( { @@ -382,37 +443,11 @@ export const deleteHighlightCurry = (highlight: HighlightNode) => () => { } ) => { if (success) { + log.debug('delete successful'); const page = highlight.page; - let fragment: DocumentNode, id; - if (page?.__typename === 'InstrumentNode') { - fragment = graphql(` - fragment InstrumentHighlightsWithIdOnlyFragment on InstrumentNode { - highlights { - id - } - } - `); - id = cache.identify({ - __typename: 'InstrumentNode', - slug: highlight.page.slug, - }); - } else { - fragment = graphql(` - fragment ContentBlockHighlightsWithIdOnlyFragment on ContentBlockNode { - highlights { - id - } - } - `); - id = cache.identify({ - __typename: 'ContentBlockNode', - id: highlight.page.id, - }); - } - const foundFragment = cache.readFragment({ - fragment, - id, - }); + log.debug(page.__typename); + const { fragment, id, foundFragment } = getFragment(cache, page); + log.debug(foundFragment); if (foundFragment) { const data = { ...foundFragment, diff --git a/server/notes/schema.py b/server/notes/schema.py index a3c1c857..bede0390 100644 --- a/server/notes/schema.py +++ b/server/notes/schema.py @@ -105,7 +105,7 @@ class HighlightableNode(graphene.Union): class HighlightNode(DjangoObjectType): - page = graphene.Field(HighlightableNode) + page = graphene.Field(HighlightableNode, required=True) class Meta: model = Highlight diff --git a/server/schema.graphql b/server/schema.graphql index 8d0af943..e42b96ca 100644 --- a/server/schema.graphql +++ b/server/schema.graphql @@ -171,7 +171,7 @@ type HighlightNode implements Node { """The ID of the object""" id: ID! user: PrivateUserNode! - page: HighlightableNode + page: HighlightableNode! contentIndex: Int contentUuid: UUID paragraphIndex: Int!