Skip to content

Commit

Permalink
fix: upgrade to be compatible with strapi v5 while the media lib and …
Browse files Browse the repository at this point in the history
…translation functions and custom configuration is broken
  • Loading branch information
kwinyyyc committed Oct 6, 2024
1 parent 771b760 commit ea67c22
Show file tree
Hide file tree
Showing 17 changed files with 549 additions and 776 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Default it uses below commands in sequence:
]`

You can customize the value in plugins/config.ts file.
```javascript
```js
export default {
"wysiwyg-react-md-editor": {
enabled: true,
Expand Down
35 changes: 17 additions & 18 deletions admin/src/components/MediaLib.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,36 @@
import {FC as FunctionComponent} from 'react';

import {useStrapiApp} from '@strapi/admin/strapi-admin';
import type {Schema} from '@strapi/types';
import { FC as FunctionComponent } from "react";

import { useStrapiApp } from "@strapi/admin/strapi-admin";
import type { Schema } from "@strapi/types";

const prefixFileUrlWithBackendUrl = (fileURL: string) => {
return !!fileURL &&
fileURL.startsWith('/') &&
'strapi' in window &&
fileURL.startsWith("/") &&
"strapi" in window &&
window.strapi instanceof Object &&
'backendURL' in window.strapi &&
window.strapi.backendURL ?
`${window.strapi.backendURL}${fileURL}` :
fileURL;
"backendURL" in window.strapi &&
window.strapi.backendURL
? `${window.strapi.backendURL}${fileURL}`
: fileURL;
};

interface MediaLibComponentProps {
isOpen: boolean,
onChange: (files: Schema.Attribute.MediaValue<true>) => void,
onToggle: () => void,
isOpen: boolean;
onChange: (files: Schema.Attribute.MediaValue<true>) => void;
onToggle: () => void;
}

const MediaLib: FunctionComponent<MediaLibComponentProps> = ({
isOpen,
onChange,
onToggle,
}) => {
const components = useStrapiApp('ImageDialog', (state) => state.components);
const components = useStrapiApp("ImageDialog", (state) => state.components);
if (!components || !isOpen) return null;

const MediaLibraryDialog = components['media-library'] as FunctionComponent<{
onClose: () => void,
onSelectAssets: (_images: Schema.Attribute.MediaValue<true>) => void,
const MediaLibraryDialog = components["media-library"] as FunctionComponent<{
onClose: () => void;
onSelectAssets: (_images: Schema.Attribute.MediaValue<true>) => void;
}>;

const handleSelectAssets = (files: Schema.Attribute.MediaValue<true>) => {
Expand All @@ -58,4 +57,4 @@ MediaLib.defaultProps = {
onToggle: () => {},
};

export {MediaLib};
export { MediaLib };
144 changes: 66 additions & 78 deletions admin/src/components/ReactMdEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import {FC as FunctionComponent, useState, useEffect, useMemo} from 'react';
import { FC as FunctionComponent, useState, useEffect, useMemo } from "react";

import {Box, Flex, Typography} from '@strapi/design-system';
import type {Schema} from '@strapi/types';
import MDEditor, {commands, ICommand} from '@uiw/react-md-editor';
import {useIntl} from 'react-intl';
import {styled} from 'styled-components';
import { Box, Flex, Typography } from "@strapi/design-system";
import type { Schema } from "@strapi/types";
import MDEditor, { commands, ICommand } from "@uiw/react-md-editor";
import { useIntl } from "react-intl";
import { styled } from "styled-components";

import '@uiw/react-markdown-preview/markdown.css';

import pluginId from '../pluginId';
import {MediaLib} from './MediaLib';
import "@uiw/react-markdown-preview/markdown.css";

import pluginId from "../pluginId";
import { MediaLib } from "./MediaLib";
import { useField } from "@strapi/strapi/admin";

const Wrapper = styled.div`
> div:nth-child(2) {
Expand Down Expand Up @@ -58,80 +58,76 @@ const Wrapper = styled.div`
`;

interface EditorProps {
name: string,
onChange: (e: {target: {name: string; value: string}}) => void,
value: string,
name: string;
onChange: (e: { target: { name: string; value: string } }) => void;
value: string;
intlLabel: {
id: string,
defaultMessage: string,
},
disabled?: boolean,
error?: string,
id: string;
defaultMessage: string;
};
disabled?: boolean;
error?: string;
description?: {
id: string,
defaultMessage: string,
},
required?: boolean,
id: string;
defaultMessage: string;
};
required?: boolean;
}

const Editor: FunctionComponent<EditorProps> = ({
name,
onChange,
value,
intlLabel,
disabled,
error,
description,
required,
}) => {
const {formatMessage} = useIntl();
// const { formatMessage } = useIntl();
const { onChange, value }: any = useField(name);
const formatMessage = (message: { id: string; defaultMessage: string }) =>
message?.defaultMessage ?? "";
const [mediaLibVisible, setMediaLibVisible] = useState(false);
const [mediaLibSelection, setMediaLibSelection] = useState(-1);

const handleToggleMediaLib = () => setMediaLibVisible((prev) => !prev);

const handleChangeAssets = (assets: Schema.Attribute.MediaValue<true>) => {
let newValue = value ? value : '';
let newValue = value ? value : "";
assets.map((asset) => {
if (asset.mime.includes('image')) {
if (asset.mime.includes("image")) {
const imgTag = `![${asset.alt}](${asset.url})`;
if (mediaLibSelection > -1) {
const preValue = value?.substring(0, mediaLibSelection) ?? '';
const postValue = value?.substring(mediaLibSelection) ?? '';
const preValue = value?.substring(0, mediaLibSelection) ?? "";
const postValue = value?.substring(mediaLibSelection) ?? "";
newValue = `${
preValue && !preValue.endsWith(' ') ? preValue + ' ' : preValue
preValue && !preValue.endsWith(" ") ? preValue + " " : preValue
}${imgTag}${
postValue && !postValue.startsWith(' ') ?
' ' + postValue :
postValue
postValue && !postValue.startsWith(" ")
? " " + postValue
: postValue
}`;
} else {
newValue = `${newValue}${imgTag}`;
}
}
// Handle videos and other type of files by adding some code
});
onChange({target: {name,
value: newValue ?? ''}});
onChange({ target: { name, value: newValue ?? "" } });
handleToggleMediaLib();
};

const [configs, setConfigs] = useState<{toolbarCommands?: string[]}>({});
const [configs, setConfigs] = useState<{ toolbarCommands?: string[] }>({});

const toolbarCommands = useMemo(() => {
const strapiMediaLibrary: ICommand = {
name: 'image',
keyCommand: 'image',
buttonProps: {'aria-label': 'Insert title3'},
name: "image",
keyCommand: "image",
buttonProps: { "aria-label": "Insert title3" },
icon: (
<svg
width='12'
height='12'
viewBox='0 0 20 20'
>
<svg width="12" height="12" viewBox="0 0 20 20">
<path
fill='currentColor'
d='M15 9c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm4-7H1c-.55 0-1 .45-1 1v14c0 .55.45 1 1 1h18c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm-1 13l-6-5-2 2-4-5-4 8V4h16v11z'
fill="currentColor"
d="M15 9c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm4-7H1c-.55 0-1 .45-1 1v14c0 .55.45 1 1 1h18c.55 0 1-.45 1-1V3c0-.55-.45-1-1-1zm-1 13l-6-5-2 2-4-5-4 8V4h16v11z"
></path>
</svg>
),
Expand Down Expand Up @@ -164,15 +160,19 @@ const Editor: FunctionComponent<EditorProps> = ({
commands.checkedListCommand,
] as ICommand[];
}
const customCommands = configs?.toolbarCommands?.map((config) => {
if (config === 'strapiMediaLibrary') return strapiMediaLibrary;
if (
config in commands &&
commands[config as unknown as keyof typeof commands]
) {
return commands[config as unknown as keyof typeof commands] as ICommand;
};
}).filter((command): command is ICommand => command !== undefined);
const customCommands = configs?.toolbarCommands
?.map((config) => {
if (config === "strapiMediaLibrary") return strapiMediaLibrary;
if (
config in commands &&
commands[config as unknown as keyof typeof commands]
) {
return commands[
config as unknown as keyof typeof commands
] as ICommand;
}
})
.filter((command): command is ICommand => command !== undefined);

return customCommands;
}, [JSON.stringify(configs)]);
Expand All @@ -188,18 +188,11 @@ const Editor: FunctionComponent<EditorProps> = ({
return (
<Flex gap={4}>
<Box>
<Typography
variant='pi'
fontWeight='bold'
>
<Typography variant="pi" fontWeight="bold">
{formatMessage(intlLabel)}
</Typography>
{required && (
<Typography
variant='pi'
fontWeight='bold'
textColor='danger600'
>
<Typography variant="pi" fontWeight="bold" textColor="danger600">
*
</Typography>
)}
Expand All @@ -208,33 +201,28 @@ const Editor: FunctionComponent<EditorProps> = ({
<MDEditor
hidden={disabled}
commands={toolbarCommands}
value={value || ''}
value={value || ""}
onChange={(newValue) => {
onChange({target: {name,
value: newValue || ''}});
onChange({ target: { name, value: newValue || "" } });
}}
/>
<div style={{padding: '50px 0 0 0'}}/>
<MediaLib
<div style={{ padding: "50px 0 0 0" }} />
{/* <MediaLib
isOpen={mediaLibVisible}
onChange={handleChangeAssets}
onToggle={handleToggleMediaLib}
/>
/> */}
</Wrapper>
{error && (
<Typography
variant='pi'
textColor='danger600'
>
{formatMessage({id: error,
defaultMessage: error})}
<Typography variant="pi" textColor="danger600">
{formatMessage({ id: error, defaultMessage: error })}
</Typography>
)}
{description && (
<Typography variant='pi'>{formatMessage(description)}</Typography>
<Typography variant="pi">{formatMessage(description)}</Typography>
)}
</Flex>
);
};

export {Editor};
export { Editor };
23 changes: 9 additions & 14 deletions admin/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import pluginPkg from "../../package.json";
import pluginId from "./pluginId";
import {Initializer} from "./components/Initializer";
import {Editor as ReactMdEditor} from "./components/ReactMdEditor";
import {getTranslation} from "./utils/getTranslation";
import { Initializer } from "./components/Initializer";
import { Editor as ReactMdEditor } from "./components/ReactMdEditor";
import { getTranslation } from "./utils/getTranslation";

const name = pluginPkg.strapi.name;

export default {
register(app: any) {
app.addFields({ type: "wysiwyg", Component: ReactMdEditor });
app.addFields({ type: "richtext", Component: ReactMdEditor });
const plugin = {
id: pluginId,
initializer: Initializer,
Expand All @@ -18,18 +18,13 @@ export default {

app.registerPlugin(plugin);
},

bootstrap(app: any) {},

async registerTrads(app: any) {
const { locales } = app;

const importedTranslations = await Promise.all(
(locales as string[]).map((locale) => {
async registerTrads({ locales }: any) {
const importedTrads = await Promise.all(
locales.map((locale: any) => {
return import(`./translations/${locale}.json`)
.then(({ default: data }) => {
return {
data: getTranslation(data),
data: data,
locale,
};
})
Expand All @@ -42,6 +37,6 @@ export default {
})
);

return importedTranslations;
return Promise.resolve(importedTrads);
},
};
4 changes: 3 additions & 1 deletion admin/src/translations/en.json
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
{}
{
"test": ""
}
4 changes: 3 additions & 1 deletion admin/src/translations/fr.json
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
{}
{
"test": ""
}
Loading

0 comments on commit ea67c22

Please sign in to comment.