import React, { useCallback, useEffect, useState, } from 'react'; import assert from 'assert'; import { Lang } from '@growi/core'; import { extractSupportedLocales, getLocalizedTemplate, type TemplateSummary, } from '@growi/pluginkit/dist/v4'; import { useTranslation } from 'next-i18next'; import { Modal, ModalHeader, ModalBody, ModalFooter, UncontrolledDropdown, DropdownToggle, DropdownMenu, DropdownItem, } from 'reactstrap'; import { useSWRxTemplate, useSWRxTemplates } from '~/features/templates/stores'; import { useTemplateModal, type TemplateModalStatus } from '~/stores/modal'; import { usePersonalSettings } from '~/stores/personal-settings'; import { usePreviewOptions } from '~/stores/renderer'; import loggerFactory from '~/utils/logger'; import Preview from '../PageEditor/Preview'; import { useFormatter } from './use-formatter'; const logger = loggerFactory('growi:components:TemplateModal'); function constructTemplateId(templateSummary: TemplateSummary): string { const defaultTemplate = templateSummary.default; return `${defaultTemplate.pluginId ?? ''}_${defaultTemplate.id}`; } type TemplateItemProps = { templateId: string, templateSummary: TemplateSummary, selectedLocale?: string, onClick?: () => void, isSelected?: boolean, usersDefaultLang?: Lang, } const TemplateItem: React.FC = ({ templateId, templateSummary, onClick, isSelected, usersDefaultLang, }) => { const localizedTemplate = getLocalizedTemplate(templateSummary, usersDefaultLang); const templateLocales = extractSupportedLocales(templateSummary); assert(localizedTemplate?.isValid); return (

{localizedTemplate.title}

{localizedTemplate.desc}

{ templateLocales != null && Array.from(templateLocales).map(locale => ( {locale} ))}
); }; type TemplateMenuProps = { templateSummaries: TemplateSummary[], onClickHandler: (templateSummary: TemplateSummary) => void, usersDefaultLang?: Lang, selectedTemplateSummary?: TemplateSummary, } const TemplateMenu: React.FC = ({ templateSummaries, onClickHandler, usersDefaultLang, selectedTemplateSummary, }) => { return ( <> {templateSummaries.map((templateSummary) => { const templateId = constructTemplateId(templateSummary); const isSelected = selectedTemplateSummary != null && constructTemplateId(selectedTemplateSummary) === templateId; return ( onClickHandler(templateSummary)} isSelected={isSelected} usersDefaultLang={usersDefaultLang} /> ); })} ); }; type TemplateModalSubstanceProps = { templateModalStatus: TemplateModalStatus, close: () => void, } const TemplateModalSubstance = (props: TemplateModalSubstanceProps): JSX.Element => { const { templateModalStatus, close } = props; const { t } = useTranslation(['translation', 'commons']); const { data: personalSettingsInfo } = usePersonalSettings(); const { data: rendererOptions } = usePreviewOptions(); const { data: templateSummaries } = useSWRxTemplates(); const [selectedTemplateSummary, setSelectedTemplateSummary] = useState(); const [selectedTemplateLocale, setSelectedTemplateLocale] = useState(); const { data: selectedTemplateMarkdown } = useSWRxTemplate(selectedTemplateSummary, selectedTemplateLocale); const { format } = useFormatter(); const usersDefaultLang = personalSettingsInfo?.lang; const selectedLocalizedTemplate = getLocalizedTemplate(selectedTemplateSummary, usersDefaultLang); const selectedTemplateLocales = extractSupportedLocales(selectedTemplateSummary); const submitHandler = useCallback((markdown?: string) => { if (markdown == null) { return; } if (templateModalStatus.onSubmit == null) { close(); return; } templateModalStatus.onSubmit(format(selectedTemplateMarkdown)); close(); }, [close, format, selectedTemplateMarkdown, templateModalStatus]); const onClickHandler = useCallback(( templateSummary: TemplateSummary, ) => { let localeToSet: string | Lang | undefined; if (selectedTemplateLocale != null && selectedTemplateLocale in templateSummary) { localeToSet = selectedTemplateLocale; } else if (usersDefaultLang != null && usersDefaultLang in templateSummary) { localeToSet = usersDefaultLang; } else { localeToSet = undefined; } setSelectedTemplateLocale(localeToSet); setSelectedTemplateSummary(templateSummary); }, [selectedTemplateLocale, usersDefaultLang]); useEffect(() => { if (!templateModalStatus.isOpened) { setSelectedTemplateSummary(undefined); setSelectedTemplateLocale(undefined); } }, [templateModalStatus.isOpened]); if (templateSummaries == null) { return <>; } return ( <> {t('template.modal_label.Select template')}
{/* List Group */}
{/* Dropdown */}
{selectedLocalizedTemplate != null && selectedLocalizedTemplate.isValid ? selectedLocalizedTemplate.title : t('Select template')}

{t('preview')}

{selectedTemplateLocale != null ? selectedTemplateLocale : t('Language')} { selectedTemplateLocales != null && Array.from(selectedTemplateLocales).map((locale) => { return ( setSelectedTemplateLocale(locale)}> {locale} ); }) }
{ rendererOptions != null && selectedTemplateSummary != null && ( ) }
); }; export const TemplateModal = (): JSX.Element => { const { data: templateModalStatus, close } = useTemplateModal(); if (templateModalStatus == null) { return <>; } return ( { templateModalStatus.isOpened && ( ) } ); };