Yuki Takei пре 2 година
родитељ
комит
d75938f5e9
2 измењених фајлова са 59 додато и 12 уклоњено
  1. 54 7
      apps/app/src/components/TemplateModal.tsx
  2. 5 5
      apps/app/src/stores/template.tsx

+ 54 - 7
apps/app/src/components/TemplateModal.tsx

@@ -1,6 +1,12 @@
-import React, { useCallback, useState } from 'react';
+import React, {
+  useCallback, useEffect, useMemo, useState,
+} from 'react';
 
-import { ITemplate } from '@growi/core';
+import path from 'path';
+
+import type { ITemplate } from '@growi/core';
+import dateFnsFormat from 'date-fns/format';
+import mustache from 'mustache';
 import { useTranslation } from 'next-i18next';
 import {
   Modal,
@@ -10,11 +16,15 @@ import {
 } from 'reactstrap';
 
 import { useTemplateModal } from '~/stores/modal';
+import { useCurrentPagePath } from '~/stores/page';
 import { usePreviewOptions } from '~/stores/renderer';
 import { useTemplates } from '~/stores/template';
+import loggerFactory from '~/utils/logger';
 
 import Preview from './PageEditor/Preview';
 
+const logger = loggerFactory('growi:components:TemplateModal');
+
 
 type TemplateRadioButtonProps = {
   template: ITemplate,
@@ -44,6 +54,8 @@ const TemplateRadioButton = ({ template, onChange, isSelected }: TemplateRadioBu
 export const TemplateModal = (): JSX.Element => {
   const { t } = useTranslation();
 
+  const { data: currentPagePath } = useCurrentPagePath();
+
   const { data: templateModalStatus, close } = useTemplateModal();
 
   const { data: rendererOptions } = usePreviewOptions();
@@ -51,16 +63,51 @@ export const TemplateModal = (): JSX.Element => {
 
   const [selectedTemplate, setSelectedTemplate] = useState<ITemplate>();
 
+  const formattedMarkdown = useMemo(() => {
+    if (selectedTemplate == null) {
+      return null;
+    }
+
+    // replace placeholder
+    let markdown = selectedTemplate.markdown;
+    const now = new Date();
+    try {
+      markdown = mustache.render(selectedTemplate.markdown, {
+        title: path.basename(currentPagePath ?? '/'),
+        path: currentPagePath ?? '/',
+        yyyy: dateFnsFormat(now, 'yyyy'),
+        MM: dateFnsFormat(now, 'MM'),
+        dd: dateFnsFormat(now, 'dd'),
+        HH: dateFnsFormat(now, 'HH'),
+        mm: dateFnsFormat(now, 'mm'),
+      });
+    }
+    catch (err) {
+      logger.warn('An error occured while ejs processing.', err);
+    }
+
+    return markdown;
+  }, [currentPagePath, selectedTemplate]);
+
   const submitHandler = useCallback((template?: ITemplate) => {
-    if (templateModalStatus == null) { return }
+    if (templateModalStatus == null || formattedMarkdown == null) {
+      return;
+    }
+
     if (templateModalStatus.onSubmit == null || template == null) {
       close();
       return;
     }
 
-    templateModalStatus.onSubmit(template.markdown);
+    templateModalStatus.onSubmit(formattedMarkdown);
     close();
-  }, [close, templateModalStatus]);
+  }, [close, formattedMarkdown, templateModalStatus]);
+
+  useEffect(() => {
+    if (!templateModalStatus?.isOpened) {
+      setSelectedTemplate(undefined);
+    }
+  }, [templateModalStatus?.isOpened]);
 
   if (templates == null || templateModalStatus == null) {
     return <></>;
@@ -86,13 +133,13 @@ export const TemplateModal = (): JSX.Element => {
           </div>
         </div>
 
-        { rendererOptions != null && (
+        { rendererOptions != null && formattedMarkdown != null && (
           <>
             <hr />
             <h3>Preview</h3>
             <div className='card'>
               <div className="card-body" style={{ maxHeight: '60vh', overflowY: 'auto' }}>
-                <Preview rendererOptions={rendererOptions} markdown={selectedTemplate?.markdown}/>
+                <Preview rendererOptions={rendererOptions} markdown={formattedMarkdown}/>
               </div>
             </div>
           </>

+ 5 - 5
apps/app/src/stores/template.tsx

@@ -8,7 +8,7 @@ const presetTemplates: ITemplate[] = [
   {
     id: '__preset1__',
     name: '日報',
-    markdown: `# yyyy/mm/dd 日報
+    markdown: `# {{yyyy}}/{{MM}}/{{dd}} 日報
 
 ## 今日の目標
 - 目標1
@@ -45,10 +45,10 @@ const presetTemplates: ITemplate[] = [
   {
     id: '__preset2__',
     name: '議事録',
-    markdown: `# <会議名>
+    markdown: `# {{title}}{{^title}}<会議名>{{/title}}
 
 ## 日時
-yyyy/mm/dd hh:mm〜hh:mm
+{{yyyy}}/{{MM}}/{{dd}} {{HH}}:{{mm}}〜hh:mm
 
 
 ## 参加者
@@ -82,7 +82,7 @@ yyyy/mm/dd hh:mm〜hh:mm
 ## 次回会議
 - 会議内容
 - 会議時間
-    - yyyy/mm/dd
+    - {{yyyy}}/{{MM}}/dd
 `,
   },
 
@@ -90,7 +90,7 @@ yyyy/mm/dd hh:mm〜hh:mm
   {
     id: '__preset3__',
     name: '企画書',
-    markdown: `# <企画タイトル>
+    markdown: `# {{title}}{{^title}}<企画タイトル>{{/title}}
 
 ## 目的