From c32aac0156e5fa32736b4af66f855a2f5b1718d3 Mon Sep 17 00:00:00 2001 From: zwiterrion Date: Thu, 26 Sep 2024 16:24:00 +0200 Subject: [PATCH] new mail editor --- daikoku/app/utils/ApiService.scala | 5 +- .../adminbackoffice/tenants/MailInput.tsx | 229 ++++++++++++++++++ .../tenants/MailingInternalization.tsx | 62 +++-- .../src/components/frontend/CmsViewer.tsx | 2 +- .../src/components/inputs/PillButton.tsx | 6 +- .../javascript/src/style/layout/style.scss | 46 +++- 6 files changed, 307 insertions(+), 43 deletions(-) create mode 100644 daikoku/javascript/src/components/adminbackoffice/tenants/MailInput.tsx diff --git a/daikoku/app/utils/ApiService.scala b/daikoku/app/utils/ApiService.scala index bbcab6ef4..e401cefbb 100644 --- a/daikoku/app/utils/ApiService.scala +++ b/daikoku/app/utils/ApiService.scala @@ -2617,7 +2617,6 @@ class ApiService( } yield Ok(Json.obj("creation" -> "refused")) } -<<<<<<< HEAD def getApis[T](ctx: ApiActionContext[T], notDeleted: Boolean = false) = { val repo = env.dataStore.apiRepo.forTenant(ctx.tenant) @@ -2644,7 +2643,8 @@ class ApiService( } }) } -======= + + case class ExtractTransferLink( subscription: ApiSubscription, childSubscriptions: Seq[ApiSubscription], @@ -2829,5 +2829,4 @@ class ApiService( ) ) } yield result ->>>>>>> master } diff --git a/daikoku/javascript/src/components/adminbackoffice/tenants/MailInput.tsx b/daikoku/javascript/src/components/adminbackoffice/tenants/MailInput.tsx new file mode 100644 index 000000000..76f48bb32 --- /dev/null +++ b/daikoku/javascript/src/components/adminbackoffice/tenants/MailInput.tsx @@ -0,0 +1,229 @@ +import { CodeInput, Form, format, SelectInput, type } from '@maif/react-forms'; +import { useContext, useEffect, useRef, useState } from "react"; +import { I18nContext } from "../../../contexts"; + +import showdown from 'showdown'; +import classNames from 'classnames'; + +import '@fortawesome/fontawesome-free/css/all.css'; +import 'highlight.js/styles/monokai.css'; +import { getCmsPage, getMailTranslations } from '../../../services'; +import { PillButton } from '../../inputs/PillButton'; +import { CmsViewer } from '../../frontend/CmsViewer' +import Select from 'react-select'; + +function extractRequiredVariables(str?: string) { + const dels: Array = []; + const words: Array = []; + + if (!str) + return [] + + for (let i = 0; i < str.length; i++) { + if (str[i] === '[') { + dels.push(i); + } else if (str[i] === ']' && dels.length > 0) { + let pos = dels[dels.length - 1]; + dels.pop(); + + const len = i - 1 - pos; + words.push(str.substring(pos + 1, (pos < len ? len : len + pos) + 1)); + } + } + return words; +} + +function overwriteParameters(parameters, content) { + let out = content; + for (const parameter in parameters) { + out = out?.replace(`[${parameters[parameter]}]`, "COUCOU") + } + return out; +} + +const converter = new showdown.Converter({ + omitExtraWLInCodeBlocks: true, + ghCompatibleHeaderId: true, + parseImgDimensions: true, + simplifiedAutoLink: true, + tables: true, + tasklists: true, + requireSpaceBeforeHeadingText: true, + ghMentions: true, + emoji: true, + ghMentionsLink: '/{u}' +}); + +interface Range { + from: any; + to: any; +} + + +const commands = [ + { + name: 'Add header', + icon: 'heading', + inject: (range: Range) => [{ from: range.from, insert: "# " }] + }, + { + name: 'Add bold text', + icon: 'bold', + inject: (range: Range) => [{ from: range.from, insert: "**" }, { from: range.to, insert: '**' }] + }, + { + name: 'Add italic text', + icon: 'italic', + inject: (range: Range) => [{ from: range.from, insert: '*' }, { from: range.to, insert: '*' }] + }, + { + name: 'Add strikethrough text', + icon: 'strikethrough', + inject: (range: Range) => [{ from: range.from, insert: '~~' }, { from: range.to, insert: '~~' }] + }, + { + name: 'Add link', + icon: 'link', + inject: (range: Range) => [{ from: range.from, insert: '[' }, { from: range.to, insert: '](url)' }] + }, + { + name: 'Add code', + icon: 'code', + inject: (range: Range) => [{ from: range.from, insert: '```\n' }, { from: range.to, insert: '\n```\n' }] + }, + { + name: 'Add quotes', + icon: 'quote-right', + inject: (range: Range) => [{ from: range.from, insert: '> ' }] + }, + { + name: 'Add image', + icon: 'image', + inject: (range: Range) => [{ from: range.from, insert: '![' }, { from: range.to, insert: '](image-url)' }] + }, + { + name: 'Add unordered list', + icon: 'list-ul', + inject: (range: Range) => [{ from: range.from, insert: '* ' }] + }, + { + name: 'Add ordered list', + icon: 'list-ol', + inject: (range: Range) => [{ from: range.from, insert: '1. ' }] + }, + { + name: 'Add check list', + icon: 'tasks', + inject: (range: Range) => [{ from: range.from, insert: '* [ ] ' }] + } +]; + +export function MailInput({ onSubmit, _id, translations, rawContent, defaultRawContent }) { + + // const { translate } = useContext(I18nContext); + + const [email, setEmail] = useState() + const [useCmsPage, toggleCmsPage] = useState(false) + const [language, toggleLanguage] = useState("fr") + + const [cmsPage, setCmsPage] = useState() + + const [emails, setEmails] = useState([]) + + let parameters = extractRequiredVariables(translations.find(t => t.language === language)?.value) + + if (parameters?.includes('email')) { + parameters = [ + ...parameters, + ...extractRequiredVariables(email) + ] + } + + useEffect(() => { + getCmsPage(`${_id}${language}`, { + email, + }) + .then(content => setCmsPage(content)) + }, [_id, language]) + + useEffect(() => { + getMailTranslations() + // @ts-ignore + .then(r => r.translations + .sort((a, b) => a._id.split(".")[1] < b._id.split(".")[1] ? -1 : 1) + .map(r => ({ label: r._id, value: r.content }))) + .then(setEmails) + + }, []) + + const ref = useRef() + + const cmsPageWithParameters = overwriteParameters(parameters, cmsPage) + + return
+
+
Format du mail
+ toggleCmsPage(false)} + onRightClick={() => toggleCmsPage(true)} + rightEnabled={!useCmsPage} + onChange={console.log} + /> +
Contenu
+ {!useCmsPage && ref.current = e} />} + + {useCmsPage &&

La page utilisé est {_id}

} +
+
+
Prévisualisation des mails
+
+ + toggleLanguage('fr')} + onRightClick={() => toggleLanguage('en')} + rightEnabled={language === 'fr'} + onChange={toggleLanguage} + /> +
+
+ + {parameters?.includes('email') && +
+ })} +
+
+ {useCmsPage ? +
: +
} +
+ +
+
+ +} \ No newline at end of file diff --git a/daikoku/javascript/src/components/adminbackoffice/tenants/MailingInternalization.tsx b/daikoku/javascript/src/components/adminbackoffice/tenants/MailingInternalization.tsx index 4914f75b8..5ebcb486e 100644 --- a/daikoku/javascript/src/components/adminbackoffice/tenants/MailingInternalization.tsx +++ b/daikoku/javascript/src/components/adminbackoffice/tenants/MailingInternalization.tsx @@ -15,6 +15,7 @@ import { Table, TableRef } from '../../inputs'; import { Can, Option, Spinner, tenant as TENANT, manage } from '../../utils'; import { BeautifulTitle } from '../../utils/BeautifulTitle'; import { EditFrontOfficeTranslations } from './EditFrontOfficeTranslations'; +import { MailInput } from './MailInput'; const MAIL_CATEGORIES = [ 'subscription', 'new', 'create', 'apikey', 'team', 'api', @@ -22,8 +23,9 @@ const MAIL_CATEGORIES = [ ] const EditMailtemplate = ({ - tenantId -}: { tenantId: string }) => { + tenantId, + mails +}: { tenantId: string, mails: any }) => { const [tenant, setTenant] = useState(); const [mailTemplateTranslations, setMailTemplateTranslations] = useState>([]); @@ -137,36 +139,29 @@ const EditMailtemplate = ({ } return (
-
- {translate('Default mail template')} -
-
-
-
{ - saveTenant({ - ...tenant, - mailerSettings: { - ...tenant.mailerSettings, - template: t.value, - }, - }) - }} /> -
-
- Render - {tenant?.mailerSettings?.template && - } -
-

Nothing to render

-
-
-
-
-
- {mailTemplateTranslations + { + setTenant({ + ...tenant, + mailerSettings: { + ...tenant.mailerSettings, + template + } + }) + // saveTenant({ + // ...tenant, + // mailerSettings: { + // ...tenant.mailerSettings, + // template + // }, + // }) + }} + title="Default mail template" /> + {/* {mailTemplateTranslations .map((translation) => { return (
{translate('Translation')} : {translation.language} @@ -174,7 +169,7 @@ const EditMailtemplate = ({
); - })} + })} */}
); }; @@ -378,7 +373,6 @@ export const MailingInternalization = () => { }, [domain]) useEffect(() => { - console.log('reload table', mails, category) if (table.current) table.current.update() }, [mails, category]) diff --git a/daikoku/javascript/src/components/frontend/CmsViewer.tsx b/daikoku/javascript/src/components/frontend/CmsViewer.tsx index 183bd7bda..ab3f637ff 100644 --- a/daikoku/javascript/src/components/frontend/CmsViewer.tsx +++ b/daikoku/javascript/src/components/frontend/CmsViewer.tsx @@ -15,7 +15,7 @@ export function CmsViewer({ pageId, fields }: CmsViewerProps) { .then(page => { setCmsPage(page) }) - }, [pageId]) + }, [pageId, fields]) if (cmsPage) return
diff --git a/daikoku/javascript/src/components/inputs/PillButton.tsx b/daikoku/javascript/src/components/inputs/PillButton.tsx index 3973c146e..585736632 100644 --- a/daikoku/javascript/src/components/inputs/PillButton.tsx +++ b/daikoku/javascript/src/components/inputs/PillButton.tsx @@ -10,13 +10,13 @@ export function PillButton({ pillButtonStyle = {}, }) { return ( -
+