diff --git a/apps/web/src/pages/___editor_preview.tsx b/apps/web/src/pages/___editor_preview.tsx index a887ed7f28..d8c5f5e66c 100644 --- a/apps/web/src/pages/___editor_preview.tsx +++ b/apps/web/src/pages/___editor_preview.tsx @@ -1,3 +1,4 @@ +import { EditorMetaContext } from '@editor/core/contexts/editor-meta-context' import { EditStringsProvider } from '@editor/i18n/edit-strings-provider' import { editStrings as editStringsDe } from '@editor/i18n/strings/de/edit' import { editStrings as editStringsEn } from '@editor/i18n/strings/en/edit' @@ -100,64 +101,68 @@ function Content() { : editStringsEn } > -
-
-
-

Edit

-
- { - const pastedString = clipboardData - .getData('text/plain') - .trim() - const cleanJsonString = pastedString - .replace(/'/g, '') - .replace(/\\"/g, '"') + +
+
+
+

Edit

+
+ { + const pastedString = clipboardData + .getData('text/plain') + .trim() + const cleanJsonString = pastedString + .replace(/'/g, '') + .replace(/\\"/g, '"') - try { - const jsonObject = JSON.parse( - cleanJsonString - ) as AnyEditorDocument - setPreviewState(JSON.stringify(jsonObject)) - } catch (error) { - // eslint-disable-next-line no-console - console.error('Error parsing JSON:', error) - showToastNotice('sorry, invalid json', 'warning') - } - }} - className="mt-0.5 w-20 bg-gray-100 text-sm" - placeholder="paste json" - /> - {' | '} - {' '} - |{' '} - + try { + const jsonObject = JSON.parse( + cleanJsonString + ) as AnyEditorDocument + setPreviewState(JSON.stringify(jsonObject)) + } catch (error) { + // eslint-disable-next-line no-console + console.error('Error parsing JSON:', error) + showToastNotice('sorry, invalid json', 'warning') + } + }} + className="mt-0.5 w-20 bg-gray-100 text-sm" + placeholder="paste json" + /> + {' | '} + {' '} + |{' '} + +
+
+
{editor}
+
+
+

+ Preview +

+
+
-
-
{editor}
-
-
-

- Preview -

-
- -
-
-
+ + + ) } diff --git a/apps/web/src/serlo-editor-integration/serlo-editor.tsx b/apps/web/src/serlo-editor-integration/serlo-editor.tsx index e2d3e88ba5..555e035c43 100644 --- a/apps/web/src/serlo-editor-integration/serlo-editor.tsx +++ b/apps/web/src/serlo-editor-integration/serlo-editor.tsx @@ -1,4 +1,5 @@ import { type EditorProps } from '@editor/core' +import { EditorMetaContext } from '@editor/core/contexts/editor-meta-context' import { EditStringsProvider } from '@editor/i18n/edit-strings-provider' import { editStrings as editStringsDe } from '@editor/i18n/strings/de/edit' import { editStrings as editStringsEn } from '@editor/i18n/strings/en/edit' @@ -18,6 +19,7 @@ import { SaveButton } from './components/save-button' import { createPlugins } from './create-plugins' import { createRenderers } from './create-renderers' import { useSerloHandleLearnerEvent } from './use-handle-learner-event' +import { useAuthentication } from '@/auth/use-authentication' import { useInstanceData } from '@/contexts/instance-context' import type { SetEntityMutationData } from '@/mutations/use-set-entity-mutation/types' @@ -39,6 +41,7 @@ export function SerloEditor({ children, }: SerloEditorProps) { const { lang, licenses } = useInstanceData() + const auth = useAuthentication() const handleLearnerEvent = useSerloHandleLearnerEvent() @@ -57,20 +60,24 @@ export function SerloEditor({ return ( - - - - {isNewEntity ? ( - - ) : null} + + + + {isNewEntity ? ( + + ) : null} - {children} - - + {children} + + + ) } diff --git a/packages/editor/src/core/contexts/editor-meta-context.tsx b/packages/editor/src/core/contexts/editor-meta-context.tsx new file mode 100644 index 0000000000..b6bf17e25e --- /dev/null +++ b/packages/editor/src/core/contexts/editor-meta-context.tsx @@ -0,0 +1,12 @@ +import type { EditorVariant } from '@editor/package/storage-format' +import { createContext } from 'react' + +export interface EditorMeta { + editorVariant: EditorVariant + userId?: string + ltik?: string +} + +export const EditorMetaContext = createContext({ + editorVariant: 'unknown', +}) diff --git a/packages/editor/src/core/contexts/editor-variant-context.tsx b/packages/editor/src/core/contexts/editor-variant-context.tsx deleted file mode 100644 index 11f78bf50b..0000000000 --- a/packages/editor/src/core/contexts/editor-variant-context.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import type { EditorVariant } from '@editor/package/storage-format' -import { createContext } from 'react' - -export const EditorVariantContext = createContext('unknown') diff --git a/packages/editor/src/package/editor.tsx b/packages/editor/src/package/editor.tsx index 924a45ef05..519c3c4ef0 100644 --- a/packages/editor/src/package/editor.tsx +++ b/packages/editor/src/package/editor.tsx @@ -1,5 +1,5 @@ import { Editor, type EditorProps } from '@editor/core' -import { EditorVariantContext } from '@editor/core/contexts/editor-variant-context' +import { EditorMetaContext } from '@editor/core/contexts/editor-meta-context' import { type GetDocument } from '@editor/core/types' import { createBasicPlugins } from '@editor/editor-integration/create-basic-plugins' import { createRenderers } from '@editor/editor-integration/create-renderers' @@ -7,7 +7,6 @@ import { EditStringsProvider } from '@editor/i18n/edit-strings-provider' import { StaticStringsProvider } from '@editor/i18n/static-strings-provider' import { editorPlugins } from '@editor/plugin/helpers/editor-plugins' import { editorRenderers } from '@editor/plugin/helpers/editor-renderer' -import { LtikContext } from '@editor/plugins/edusharing-asset/ltik-context' import { EditorPluginType } from '@editor/types/editor-plugin-type' import { SupportedLanguage } from '@editor/types/language-data' import { TemplatePluginType } from '@editor/types/template-plugin-type' @@ -23,7 +22,6 @@ import { type EditorVariant, } from './storage-format' -// TODO: figure out styling // eslint-disable-next-line import/no-unassigned-import import '../tailwind/editor.css' @@ -35,6 +33,7 @@ export interface SerloEditorProps { language?: SupportedLanguage editorVariant: EditorVariant isProductionEnvironment?: boolean + userId?: string _testingSecret?: string | null _ltik?: string } @@ -48,6 +47,7 @@ export function SerloEditor(props: SerloEditorProps) { language, plugins, isProductionEnvironment, + userId, _testingSecret, _ltik, } = { @@ -76,17 +76,17 @@ export function SerloEditor(props: SerloEditorProps) { return ( - - - {isProductionEnvironment ? null : renderTestEnvironmentWarning()} - - {children} - - - + + {isProductionEnvironment ? null : renderTestEnvironmentWarning()} + + {children} + + ) diff --git a/packages/editor/src/package/serlo-renderer.tsx b/packages/editor/src/package/serlo-renderer.tsx index 35dec7295d..3c9ef5f7d3 100644 --- a/packages/editor/src/package/serlo-renderer.tsx +++ b/packages/editor/src/package/serlo-renderer.tsx @@ -1,8 +1,8 @@ +import { EditorMetaContext } from '@editor/core/contexts/editor-meta-context' import { createRenderers } from '@editor/editor-integration/create-renderers' import { EditStringsProvider } from '@editor/i18n/edit-strings-provider' import { StaticStringsProvider } from '@editor/i18n/static-strings-provider' import { editorRenderers } from '@editor/plugin/helpers/editor-renderer' -import { LtikContext } from '@editor/plugins/edusharing-asset/ltik-context' import { StaticRenderer } from '@editor/static-renderer/static-renderer' import type { SupportedLanguage } from '@editor/types/language-data' @@ -37,14 +37,14 @@ export function SerloRenderer(props: SerloRendererProps) { return ( - +
-
+
) diff --git a/packages/editor/src/plugins/edusharing-asset/editor.tsx b/packages/editor/src/plugins/edusharing-asset/editor.tsx index 242968c19b..0af5b0383f 100644 --- a/packages/editor/src/plugins/edusharing-asset/editor.tsx +++ b/packages/editor/src/plugins/edusharing-asset/editor.tsx @@ -1,10 +1,10 @@ +import { EditorMetaContext } from '@editor/core/contexts/editor-meta-context' import { useEditStrings } from '@editor/i18n/edit-strings-provider' import * as t from 'io-ts' import { useContext, useEffect, useRef, useState } from 'react' import Modal from 'react-modal' import type { EdusharingAssetProps } from '.' -import { LtikContext } from './ltik-context' import { EdusharingAssetRenderer } from './renderer' import { PluginToolbar } from '../../editor-ui/plugin-toolbar' import { PluginDefaultTools } from '../../editor-ui/plugin-toolbar/plugin-tool-menu/plugin-default-tools' @@ -52,7 +52,7 @@ export function EdusharingAssetEditor({ return () => window.removeEventListener('message', handleIFrameEvent) }, [state.edusharingAsset]) - const ltik = useContext(LtikContext) + const { ltik } = useContext(EditorMetaContext) if (!ltik) return

Error: ltik missing

return ( diff --git a/packages/editor/src/plugins/edusharing-asset/ltik-context.ts b/packages/editor/src/plugins/edusharing-asset/ltik-context.ts deleted file mode 100644 index 7c63be4249..0000000000 --- a/packages/editor/src/plugins/edusharing-asset/ltik-context.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { createContext } from 'react' - -export const LtikContext = createContext(undefined) diff --git a/packages/editor/src/plugins/edusharing-asset/static.tsx b/packages/editor/src/plugins/edusharing-asset/static.tsx index c052826be8..81c866be28 100644 --- a/packages/editor/src/plugins/edusharing-asset/static.tsx +++ b/packages/editor/src/plugins/edusharing-asset/static.tsx @@ -1,7 +1,7 @@ +import { EditorMetaContext } from '@editor/core/contexts/editor-meta-context' import { EditorEdusharingAssetDocument } from '@editor/types/editor-plugins' import { useContext } from 'react' -import { LtikContext } from './ltik-context' import { EdusharingAssetRenderer } from './renderer' export function EdusharingAssetStaticRenderer( @@ -12,7 +12,7 @@ export function EdusharingAssetStaticRenderer( const { contentWidth: widthInPercent } = props.state - const ltik = useContext(LtikContext) + const { ltik } = useContext(EditorMetaContext) if (!ltik) return null diff --git a/packages/editor/src/plugins/image/utils/upload-file.ts b/packages/editor/src/plugins/image/utils/upload-file.ts index d3b74b5676..da7e1374e8 100644 --- a/packages/editor/src/plugins/image/utils/upload-file.ts +++ b/packages/editor/src/plugins/image/utils/upload-file.ts @@ -1,15 +1,19 @@ -import { EditorVariantContext } from '@editor/core/contexts/editor-variant-context' -import { type EditorVariant } from '@editor/package/storage-format' +import { + EditorMetaContext, + type EditorMeta, +} from '@editor/core/contexts/editor-meta-context' import { type UploadHandler } from '@editor/plugin' import { useContext } from 'react' import { handleError, validateFile } from './validate-file' -export function useUploadFile(oldFileUploader: UploadHandler) { - const editorVariant = useContext(EditorVariantContext) - return shouldUseNewUpload() - ? (file: File) => uploadFile(file, editorVariant) - : oldFileUploader +type UploadMeta = Pick + +export function useUploadFile(oldUploader: UploadHandler) { + const { editorVariant, userId } = useContext(EditorMetaContext) + + const uploader = (file: File) => uploadFile({ file, editorVariant, userId }) + return shouldUseNewUpload() ? uploader : oldUploader } // while testing @@ -30,11 +34,21 @@ export function shouldUseNewUpload() { return isDevOrPreviewOrStaging } -export async function uploadFile(file: File, editorVariant: EditorVariant) { +async function uploadFile({ + file, + editorVariant, + userId, +}: UploadMeta & { + file: File +}) { const validated = validateFile(file) if (!validated) return Promise.reject() - const data = await getSignedUrlAndSrc(file.type, editorVariant) + const data = await getSignedUrlAndSrc({ + mimeType: file.type, + editorVariant, + userId, + }) if (!data) return Promise.reject('Could not get signed URL') const { signedUrl, imgSrc } = data @@ -49,11 +63,15 @@ const signedUrlHost = ? 'editor.serlo.dev' : 'editor.serlo.dev' // TODO: Change to production bucket after testing -async function getSignedUrlAndSrc( - mimeType: string, - editorVariant: EditorVariant -) { - const url = `https://${signedUrlHost}/media/presigned-url?mimeType=${encodeURIComponent(mimeType)}&editorVariant=${encodeURIComponent(editorVariant)}` +async function getSignedUrlAndSrc({ + mimeType, + editorVariant, + userId, +}: UploadMeta & { + mimeType: string +}) { + const params = `mimeType=${encodeURIComponent(mimeType)}&editorVariant=${encodeURIComponent(editorVariant)}&userId=${encodeURIComponent(userId ?? '')}` + const url = `https://${signedUrlHost}/media/presigned-url?${params}` const result = await fetch(url).catch((e) => { // eslint-disable-next-line no-console