Просмотр исходного кода

impl previewing and submitting

Yuki Takei 2 лет назад
Родитель
Сommit
beebf2f605

+ 18 - 16
apps/app/src/components/TemplateModal/TemplateModal.tsx

@@ -6,7 +6,7 @@ import assert from 'assert';
 
 import { Lang } from '@growi/core';
 import type { ITemplate } from '@growi/core/dist/interfaces/template';
-import type { TemplateSummary } from '@growi/pluginkit/dist/interfaces/v4';
+import { getLocalizedTemplate, type TemplateSummary } from '@growi/pluginkit/dist/v4';
 import { useTranslation } from 'next-i18next';
 import {
   Modal,
@@ -15,7 +15,7 @@ import {
   ModalFooter,
 } from 'reactstrap';
 
-import { useSWRxTemplates } from '~/features/templates/stores';
+import { useSWRxTemplate, useSWRxTemplates } from '~/features/templates/stores';
 import { useTemplateModal } from '~/stores/modal';
 import { usePersonalSettings } from '~/stores/personal-settings';
 import { usePreviewOptions } from '~/stores/renderer';
@@ -80,28 +80,30 @@ export const TemplateModal = (): JSX.Element => {
   const { data: rendererOptions } = usePreviewOptions();
   const { data: templateSummaries } = useSWRxTemplates();
 
-  const [selectedTemplate, setSelectedTemplate] = useState<TemplateSummary>();
-  // const [selectedTemplateLocale, setSelectedTemplateLocale] = useState<string>();
+  const [selectedTemplateSummary, setSelectedTemplateSummary] = useState<TemplateSummary>();
+  const [selectedTemplateLocale, setSelectedTemplateLocale] = useState<string>();
+
+  const { data: selectedTemplateMarkdown } = useSWRxTemplate(selectedTemplateSummary, selectedTemplateLocale);
 
   const { format } = useFormatter();
 
-  const submitHandler = useCallback((template?: ITemplate) => {
-    if (templateModalStatus == null || selectedTemplate == null) {
+  const submitHandler = useCallback((markdown?: string) => {
+    if (templateModalStatus == null || markdown == null) {
       return;
     }
 
-    if (templateModalStatus.onSubmit == null || template == null) {
+    if (templateModalStatus.onSubmit == null) {
       close();
       return;
     }
 
-    // templateModalStatus.onSubmit(format(selectedTemplate));
+    templateModalStatus.onSubmit(format(selectedTemplateMarkdown));
     close();
-  }, [close, selectedTemplate, templateModalStatus]);
+  }, [close, format, selectedTemplateMarkdown, templateModalStatus]);
 
   useEffect(() => {
     if (!templateModalStatus?.isOpened) {
-      setSelectedTemplate(undefined);
+      setSelectedTemplateSummary(undefined);
     }
   }, [templateModalStatus?.isOpened]);
 
@@ -127,8 +129,8 @@ export const TemplateModal = (): JSX.Element => {
                     key={templateId}
                     templateSummary={templateSummary}
                     usersDefaultLang={personalSettingsInfo?.lang}
-                    onClick={() => setSelectedTemplate(templateSummary)}
-                    isSelected={selectedTemplate != null && constructTemplateId(selectedTemplate) === templateId}
+                    onClick={() => setSelectedTemplateSummary(templateSummary)}
+                    isSelected={selectedTemplateSummary != null && constructTemplateId(selectedTemplateSummary) === templateId}
                   />
                 );
               }) }
@@ -139,8 +141,8 @@ export const TemplateModal = (): JSX.Element => {
             <h3>{t('Preview')}</h3>
             <div className='card'>
               <div className="card-body" style={{ height: '400px', overflowY: 'auto' }}>
-                { rendererOptions != null && selectedTemplate != null && (
-                  <Preview rendererOptions={rendererOptions} markdown={'' /* format(selectedTemplate) */}/>
+                { rendererOptions != null && selectedTemplateSummary != null && (
+                  <Preview rendererOptions={rendererOptions} markdown={format(selectedTemplateMarkdown)}/>
                 ) }
               </div>
             </div>
@@ -155,8 +157,8 @@ export const TemplateModal = (): JSX.Element => {
         <button
           type="submit"
           className="btn btn-primary mx-1"
-          // onClick={() => submitHandler(selectedTemplate)}
-          disabled={selectedTemplate == null}>
+          onClick={() => submitHandler(selectedTemplateMarkdown)}
+          disabled={selectedTemplateSummary == null}>
           {t('commons:Insert')}
         </button>
       </ModalFooter>

+ 9 - 12
apps/app/src/components/TemplateModal/use-formatter.spec.tsx

@@ -47,26 +47,24 @@ describe('useFormatter', () => {
 
     // when
     const { format } = useFormatter();
-    const template = mock<ITemplate>();
-    template.markdown = 'markdown body';
-    const markdown = format(template);
+    const markdown = 'markdown body';
+    const formatted = format(markdown);
 
     // then
-    expect(markdown).toBe('markdown body');
+    expect(formatted).toBe('markdown body');
   });
 
   it('returns markdown formatted when currentPagePath is undefined', () => {
     // when
     const { format } = useFormatter();
-    const template = mock<ITemplate>();
-    template.markdown = `
+    const markdown = `
 title: {{{title}}}{{^title}}(empty){{/title}}
 path: {{{path}}}
 `;
-    const markdown = format(template);
+    const formatted = format(markdown);
 
     // then
-    expect(markdown).toBe(`
+    expect(formatted).toBe(`
 title: (empty)
 path: /
 `);
@@ -82,16 +80,15 @@ path: /
 
     // when
     const { format } = useFormatter();
-    const template = mock<ITemplate>();
-    template.markdown = `
+    const markdown = `
 title: {{{title}}}
 path: {{{path}}}
 date: {{yyyy}}/{{MM}}/{{dd}} {{HH}}:{{mm}}
 `;
-    const markdown = format(template);
+    const formatted = format(markdown);
 
     // then
-    expect(markdown).toBe(`
+    expect(formatted).toBe(`
 title: Sandbox
 path: /Sandbox
 date: 2023/05/31 15:01

+ 5 - 8
apps/app/src/components/TemplateModal/use-formatter.tsx

@@ -1,6 +1,5 @@
 import path from 'path';
 
-import type { ITemplate } from '@growi/core/dist/interfaces/template';
 import dateFnsFormat from 'date-fns/format';
 import mustache from 'mustache';
 
@@ -10,7 +9,7 @@ import loggerFactory from '~/utils/logger';
 const logger = loggerFactory('growi:components:TemplateModal:use-formatter');
 
 
-type FormatMethod = (selectedTemplate?: ITemplate) => string;
+type FormatMethod = (markdown?: string) => string;
 type FormatterData = {
   format: FormatMethod,
 }
@@ -18,16 +17,15 @@ type FormatterData = {
 export const useFormatter = (): FormatterData => {
   const { data: currentPagePath } = useCurrentPagePath();
 
-  const format: FormatMethod = (selectedTemplate) => {
-    if (selectedTemplate == null) {
+  const format: FormatMethod = (markdown) => {
+    if (markdown == null) {
       return '';
     }
 
     // replace placeholder
-    let markdown = selectedTemplate.markdown;
     const now = new Date();
     try {
-      markdown = mustache.render(selectedTemplate.markdown, {
+      return mustache.render(markdown, {
         title: path.basename(currentPagePath ?? '/'),
         path: currentPagePath ?? '/',
         yyyy: dateFnsFormat(now, 'yyyy'),
@@ -39,9 +37,8 @@ export const useFormatter = (): FormatterData => {
     }
     catch (err) {
       logger.warn('An error occured while ejs processing.', err);
+      return markdown;
     }
-
-    return markdown;
   };
 
   return { format };

+ 1 - 1
apps/app/src/features/templates/server/routes/apiv3/index.ts

@@ -1,4 +1,4 @@
-import { scanAllTemplateStatus, getMarkdown } from '@growi/pluginkit/dist/server/utils/v4';
+import { scanAllTemplateStatus, getMarkdown } from '@growi/pluginkit/dist/v4/server';
 import express from 'express';
 import { param, query } from 'express-validator';
 

+ 21 - 3
apps/app/src/features/templates/stores/template.tsx

@@ -1,4 +1,4 @@
-import type { TemplateSummary } from '@growi/pluginkit/dist/interfaces/v4';
+import { getLocalizedTemplate, type TemplateSummary } from '@growi/pluginkit/dist/v4';
 import useSWR, { type SWRResponse } from 'swr';
 
 import { apiv3Get } from '~/client/util/apiv3-client';
@@ -139,7 +139,25 @@ export const useSWRxTemplates = (): SWRResponse<TemplateSummary[], Error> => {
   //   },
   // );
   return useSWR(
-    ['/templates'],
-    ([endpoint]) => apiv3Get<{ summaries: TemplateSummary[] }>(endpoint).then(res => res.data.summaries),
+    '/templates',
+    endpoint => apiv3Get<{ summaries: TemplateSummary[] }>(endpoint).then(res => res.data.summaries),
+  );
+};
+
+export const useSWRxTemplate = (summary: TemplateSummary | undefined, locale?: string): SWRResponse<string, Error> => {
+  const pluginId = summary?.default.pluginId;
+  const targetTemplate = getLocalizedTemplate(summary, locale);
+
+  return useSWR(
+    () => {
+      if (targetTemplate == null) {
+        return null;
+      }
+
+      return pluginId == null
+        ? `/templates/preset-templates/${targetTemplate.id}/${targetTemplate.locale}`
+        : `/templates/plugin-templates/${pluginId}/${targetTemplate.id}/${targetTemplate.locale}`;
+    },
+    endpoint => apiv3Get<{ markdown: string }>(endpoint).then(res => res.data.markdown),
   );
 };

+ 2 - 0
packages/pluginkit/src/v4/index.ts

@@ -0,0 +1,2 @@
+export * from './interfaces';
+export * from './utils';

+ 0 - 0
packages/pluginkit/src/interfaces/v4/index.ts → packages/pluginkit/src/v4/interfaces/index.ts


+ 0 - 0
packages/pluginkit/src/interfaces/v4/template.ts → packages/pluginkit/src/v4/interfaces/template.ts


+ 1 - 0
packages/pluginkit/src/v4/server/index.ts

@@ -0,0 +1 @@
+export * from './utils';

+ 0 - 0
packages/pluginkit/src/server/utils/v4/index.ts → packages/pluginkit/src/v4/server/utils/index.ts


+ 0 - 0
packages/pluginkit/src/server/utils/v4/package-json/import.spec.ts → packages/pluginkit/src/v4/server/utils/package-json/import.spec.ts


+ 0 - 0
packages/pluginkit/src/server/utils/v4/package-json/import.ts → packages/pluginkit/src/v4/server/utils/package-json/import.ts


+ 0 - 0
packages/pluginkit/src/server/utils/v4/package-json/index.ts → packages/pluginkit/src/v4/server/utils/package-json/index.ts


+ 0 - 0
packages/pluginkit/src/server/utils/v4/package-json/validate.spec.ts → packages/pluginkit/src/v4/server/utils/package-json/validate.spec.ts


+ 0 - 0
packages/pluginkit/src/server/utils/v4/package-json/validate.ts → packages/pluginkit/src/v4/server/utils/package-json/validate.ts


+ 1 - 2
packages/pluginkit/src/server/utils/v4/template.ts → packages/pluginkit/src/v4/server/utils/template.ts

@@ -1,4 +1,3 @@
-import assert from 'assert';
 import fs from 'fs';
 import path from 'path';
 import { promisify } from 'util';
@@ -8,7 +7,7 @@ import { GrowiPluginType } from '@growi/core/dist/consts';
 import type { GrowiPluginValidationData, GrowiTemplatePluginValidationData } from '~/model';
 import { GrowiPluginValidationError } from '~/model';
 
-import { isTemplateStatusValid, type TemplateStatus, type TemplateSummary } from '../../../interfaces/v4';
+import { isTemplateStatusValid, type TemplateStatus, type TemplateSummary } from '../../interfaces';
 
 import { importPackageJson, validatePackageJson } from './package-json';
 

+ 1 - 0
packages/pluginkit/src/v4/utils/index.ts

@@ -0,0 +1 @@
+export * from './template';

+ 11 - 0
packages/pluginkit/src/v4/utils/template.ts

@@ -0,0 +1,11 @@
+import type { TemplateSummary, TemplateStatus } from '../interfaces';
+
+export const getLocalizedTemplate = (templateSummary: TemplateSummary | undefined, locale?: string): TemplateStatus | undefined => {
+  if (templateSummary == null) {
+    return undefined;
+  }
+
+  return locale != null
+    ? templateSummary[locale]
+    : templateSummary.default;
+};

+ 1 - 1
packages/preset-templates/test/index.test.ts

@@ -1,6 +1,6 @@
 import path from 'node:path';
 
-import { scanAllTemplateStatus, validateTemplatePluginPackageJson, validateTemplatePlugin } from '@growi/pluginkit/dist/server/utils/v4';
+import { scanAllTemplateStatus, validateTemplatePluginPackageJson, validateTemplatePlugin } from '@growi/pluginkit/dist/v4/server';
 
 
 const projectDirRoot = path.resolve(__dirname, '../');