diff --git a/src/edusharing-server/mocked-image-embed-html.ts b/src/edusharing-server/mocked-image-embed-html.ts deleted file mode 100644 index b3fc6ed9..00000000 --- a/src/edusharing-server/mocked-image-embed-html.ts +++ /dev/null @@ -1,698 +0,0 @@ -// Snapshot of what edu-sharing sends -export const mockedImageEmbedHtml = ` - -
- Inhalt von edu-sharing - Testbild - - -
-` diff --git a/src/edusharing-server/mocked-image-embed-json.ts b/src/edusharing-server/mocked-image-embed-json.ts new file mode 100644 index 00000000..9d611689 --- /dev/null +++ b/src/edusharing-server/mocked-image-embed-json.ts @@ -0,0 +1,185 @@ +// Snapshot of what edu-sharing sends when embedding an image +export const mockedImageEmbedJson = { + detailsSnippet: + " \n
\n \"Lars\n \n
\n \n \n
\n
", + mimeType: 'image/png', + node: { + nodeLTIDeepLink: null, + remote: null, + content: { + url: 'https://repository.staging.cloud.schulcampus-rlp.de/edu-sharing/components/render/1baf4a58-6d39-48d5-90d8-3cbc40db82ef', + hash: '1859269250', + version: '1.1', + }, + license: { + icon: 'https://repository.staging.cloud.schulcampus-rlp.de/edu-sharing/ccimages/licenses/none.svg', + url: null, + }, + isDirectory: false, + commentCount: 0, + rating: { + overall: { sum: 0, count: 0, rating: 0 }, + affiliation: {}, + user: 0, + }, + usedInCollections: [], + relations: null, + contributors: [ + { + property: 'ccm:metadatacontributer_creator', + firstname: 'sso', + lastname: 'schuelereins', + email: 'VCARD_EMAIL', + vcard: + 'BEGIN:VCARD\nVERSION:3.0\nUID:urn:uuid:ca43354b-2aae-4ede-9fb6-0a565ae91d5b\nN:schuelereins;sso\nFN:sso schuelereins\nORG:\nURL:\nTITLE:\nTEL;TYPE=WORK,VOICE:\nADR;TYPE=intl,postal,parcel,work:;;;;;;\nEMAIL;TYPE=PREF,INTERNET:dennis.hakenbeck2@pl.rlp.de\nEND:VCARD\n', + org: '', + }, + ], + ref: { + repo: 'local', + id: '1baf4a58-6d39-48d5-90d8-3cbc40db82ef', + archived: false, + isHomeRepo: true, + }, + parent: { + repo: 'local', + id: '80829653-a0f7-4f79-96a3-d0a7fdb714f4', + archived: false, + isHomeRepo: true, + }, + type: 'ccm:io', + aspects: [ + 'cclom:lifecycle', + 'ccm:eduscope', + 'cclom:technical', + 'ccm:iometadata', + 'cm:versionable', + 'ccm:usageaspect', + 'sys:referenceable', + 'sys:localized', + 'cm:thumbnailModification', + 'cclom:schema', + 'exif:exif', + 'cm:metadataset', + 'ccm:licenses', + 'ccm:commonlicenses', + 'cclom:rights', + 'cm:thumbnailed', + 'cm:auditable', + 'ccm:lomreplication', + 'cclom:meta-metadata', + 'cclom:general', + 'ccm:educontext', + ], + name: 'Lars Testbild.png', + title: 'Lars Testbild', + metadataset: 'mds', + repositoryType: 'ALFRESCO', + createdAt: '2024-03-18T15:38:36Z', + createdBy: { + profile: null, + firstName: 'sso', + lastName: 'schuelereins', + mailbox: null, + }, + modifiedAt: '2024-03-18T15:39:18Z', + modifiedBy: { + profile: null, + firstName: 'sso', + lastName: 'schuelereins', + mailbox: null, + }, + access: ['Read', 'ReadAll'], + downloadUrl: + 'https://repository.staging.cloud.schulcampus-rlp.de/edu-sharing/eduservlet/download?nodeId=1baf4a58-6d39-48d5-90d8-3cbc40db82ef', + properties: { + 'ccm:original': ['1baf4a58-6d39-48d5-90d8-3cbc40db82ef'], + 'cm:created': ['1710776316542'], + 'virtual:commentcount': ['0'], + 'ccm:metadatacontributer_creatorVCARD_ORG': [''], + 'cclom:size': ['88932'], + 'cclom:version': ['1.1'], + 'virtual:usagecount': ['1'], + 'sys:node-uuid': ['1baf4a58-6d39-48d5-90d8-3cbc40db82ef'], + 'virtual:childobjectcount': ['0'], + 'cclom:title': ['Lars Testbild'], + 'virtual:mediatype': ['Bild'], + 'sys:store-protocol': ['workspace'], + 'sys:store-identifier': ['SpacesStore'], + 'ccm:height': ['276'], + 'exif:pixelXDimension': ['252'], + 'ccm:version_comment': ['METADATA_UPDATE'], + 'cclom:format': ['image/png'], + 'ccm:metadatacontributer_creatorVCARD_URL': [''], + 'ccm:create_version': ['true'], + 'cm:modifiedISO8601': ['2024-03-18T15:39:18.549Z'], + 'ccm:metadatacontributer_creatorVCARD_REGION': [''], + 'sys:node-dbid': ['49717126'], + 'cm:edu_metadataset': ['mds'], + 'ccm:metadatacontributer_creatorVCARD_PLZ': [''], + 'cm:creator': ['15407f04-cf8b-4937-a831-b2ac0c71b512'], + 'cm:autoVersion': ['false'], + 'virtual:permalink': [ + 'https://repository.staging.cloud.schulcampus-rlp.de/edu-sharing/components/render/1baf4a58-6d39-48d5-90d8-3cbc40db82ef/1.1', + ], + 'ccm:metadatacontributer_creatorVCARD_GIVENNAME': ['sso'], + 'cm:versionLabel': ['1.1'], + 'ccm:search_context': ['campus_content'], + 'cm:versionable': ['true'], + 'ccm:metadatacontributer_creatorVCARD_COUNTRY': [''], + 'cm:created_LONG': ['1710776316542'], + 'virtual:primaryparent_nodeid': ['80829653-a0f7-4f79-96a3-d0a7fdb714f4'], + 'cm:lastThumbnailModification': ['imgpreview:1710776325980'], + 'ccm:width': ['252'], + 'ccm:metadatacontributer_creator': [ + 'BEGIN:VCARD\nVERSION:3.0\nUID:urn:uuid:ca43354b-2aae-4ede-9fb6-0a565ae91d5b\nN:schuelereins;sso\nFN:sso schuelereins\nORG:\nURL:\nTITLE:\nTEL;TYPE=WORK,VOICE:\nADR;TYPE=intl,postal,parcel,work:;;;;;;\nEMAIL;TYPE=PREF,INTERNET:dennis.hakenbeck2@pl.rlp.de\nEND:VCARD\n', + ], + 'ccm:metadatacontributer_creatorVCARD_TEL': [''], + 'exif:pixelYDimension': ['276'], + 'ccm:metadatacontributer_creatorVCARD_STREET': [''], + 'cm:createdISO8601': ['2024-03-18T15:38:36.542Z'], + 'cm:modified': ['1710776358549'], + 'cm:edu_forcemetadataset': ['false'], + 'ccm:metadatacontributer_creatorVCARD_CITY': [''], + 'cm:modifier': ['15407f04-cf8b-4937-a831-b2ac0c71b512'], + 'cm:autoVersionOnUpdateProps': ['false'], + 'cclom:location': ['ccrep://local/1baf4a58-6d39-48d5-90d8-3cbc40db82ef'], + 'ccm:educontextname': ['default'], + 'ccm:metadatacontributer_creatorVCARD_EMAIL': [ + 'dennis.hakenbeck2@pl.rlp.de', + ], + 'ccm:metadatacontributer_creatorFN': ['sso schuelereins'], + 'cm:modified_LONG': ['1710776358549'], + 'ccm:metadatacontributer_creatorVCARD_TITLE': [''], + 'cm:automaticUpdate': ['true'], + 'cm:name': ['Lars Testbild.png'], + 'virtual:type': ['ccm:io'], + 'ccm:search_context_DISPLAYNAME': ['Campus Inhalt'], + 'cm:initialVersion': ['false'], + 'ccm:metadatacontributer_creatorVCARD_SURNAME': ['schuelereins'], + }, + mimetype: 'image/png', + mediatype: 'file-image', + size: '88932', + preview: { + isIcon: false, + isGenerated: true, + type: 'TYPE_GENERATED', + mimetype: null, + data: null, + url: 'https://repository.staging.cloud.schulcampus-rlp.de/edu-sharing/preview?nodeId=1baf4a58-6d39-48d5-90d8-3cbc40db82ef&storeProtocol=workspace&storeId=SpacesStore&dontcache=1710776371376', + width: null, + height: null, + }, + iconURL: + 'https://repository.staging.cloud.schulcampus-rlp.de/edu-sharing/themes/default/images/common/mime-types/svg/file-image.svg', + collection: null, + owner: { + profile: null, + firstName: 'sso', + lastName: 'schuelereins', + mailbox: null, + }, + isPublic: false, + }, +} diff --git a/src/edusharing-server/server.ts b/src/edusharing-server/server.ts index 9b99b91e..8a4a0781 100644 --- a/src/edusharing-server/server.ts +++ b/src/edusharing-server/server.ts @@ -8,7 +8,7 @@ import { signJwtWithBase64Key, verifyJwt, } from '../server-utils' -import { mockedImageEmbedHtml } from './mocked-image-embed-html' +import { mockedImageEmbedJson } from './mocked-image-embed-json' // We define the absence of `versionComment` with `null` so that we can // tranfer it inside the cypress environment (only proper JSON can be @@ -278,11 +278,7 @@ export class EdusharingServer { }) this.app.get('/edu-sharing/rest/lti/v13/details/*/*', (_req, res) => { - res - .json({ - detailsSnippet: mockedImageEmbedHtml, - }) - .end() + res.json(mockedImageEmbedJson).end() }) this.app.all('*', (req, res) => { diff --git a/src/frontend/plugins/edusharing-asset/renderer.tsx b/src/frontend/plugins/edusharing-asset/renderer.tsx index cdae8534..4d1c16f9 100644 --- a/src/frontend/plugins/edusharing-asset/renderer.tsx +++ b/src/frontend/plugins/edusharing-asset/renderer.tsx @@ -5,10 +5,20 @@ import IframeResizer from 'iframe-resizer-react' type RenderMethod = 'dangerously-set-inner-html' | 'iframe' -type EmbeddedContent = { - detailsSnippet: string - [key: string]: any -} +const EmbedJson = t.type({ + detailsSnippet: t.string, + node: t.type({ + mediatype: t.string, + remote: t.union([ + t.null, + t.type({ + repository: t.type({ + repositoryType: t.string, + }), + }), + ]), + }), +}) export function EdusharingAssetRenderer(props: { nodeId?: string @@ -45,11 +55,12 @@ export function EdusharingAssetRenderer(props: { return } - const result: object = await response.json() + const result: unknown = await response.json() - if (!t.type({ detailsSnippet: t.string }).is(result)) { + if (!EmbedJson.is(result)) { + console.log(JSON.stringify(result)) setEmbedHtml( - 'Request to /lit/get-embed-html failed. "detailsSnipped" is missing or not of type string.', + 'Request to /lit/get-embed-html failed. Response json was malformed. Json was logged to console.', ) return } @@ -86,7 +97,7 @@ export function EdusharingAssetRenderer(props: { ) - function embedHtmlAndRenderMethod(content: EmbeddedContent): { + function embedHtmlAndRenderMethod(content: t.TypeOf): { html: string renderMethod: RenderMethod defineContainerHeight: boolean @@ -105,11 +116,8 @@ export function EdusharingAssetRenderer(props: { const parser = new DOMParser() const htmlDocument = parser.parseFromString(detailsSnippet, 'text/html') - // Sadly, LearningApps also have `mediatype: 'link'` so we need to check more stuff here than just `mediatype` - const isLink = - content.node.mediatype === 'link' && - !content.node.mimetype && - content.node.repositoryType === 'ALFRESCO' + // Sadly, LearningApps also have `mediatype: 'link'` so we need to check if `remote` is falsy as well + const isLink = content.node.mediatype === 'link' && !content.node.remote if (isLink) { const linkElement = htmlDocument.querySelector( '.edusharing_rendering_content_footer a', @@ -136,8 +144,8 @@ export function EdusharingAssetRenderer(props: { const image = getImageOrUndefined(htmlDocument) const isPixabayImage = - hasImageMimeType(content?.mimeType || '') && - content?.node?.remote?.repository?.repositoryType === 'PIXABAY' + content.node.mediatype === 'file-image' && + content.node.remote?.repository.repositoryType === 'PIXABAY' if (isPixabayImage) { const imageSnippet = buildImageSnippet(image) @@ -364,20 +372,6 @@ function buildImageSnippet(image: HTMLImageElement): string { ` } -const imageMimeTypes = [ - 'image/jpeg', - 'image/png', - 'image/gif', - 'image/webp', - 'image/svg+xml', - 'image/bmp', - 'image/tiff', -] - -function hasImageMimeType(mimeType: string): boolean { - return imageMimeTypes.includes(mimeType) -} - // Only re-render if `srcDoc` prop changed. We do not want to re-render the Iframe every time when EdusharingAssetRenderer is re-rendered because the state within the iframe is lost. const MemoizedIframeResizer = memo( IframeResizer,