跳至正文
Wener Notes

TinaCMS

约 2 分钟阅读

在 Web 上添加属性编辑功能。

    • 目前主要集成 next 和 gatsby
    • 后端交互目前以 git 为主
    • 实现自定义后端可参照 next 的 local json 方式
  • 虽然名字是 tinacms 但更偏向编辑器 - Contextual Editing
    • 模型 -formify->表单<->API
    • 基于 Git 的 CMS - 但个人认为其编辑功能更有意思
    • Git 后端生成 GraphQL API
  • 使用 final-form 构建 form

schema

.tina/schema.ts
import { defineSchema } from 'tinacms';

const schema = defineSchema({
  // entity
  collections: [
    {
      label: 'Blog Posts',
      name: 'post',
      path: 'content/posts',
      fields: [
        {
          // scalar - string, datetime, boolean, image, number
          // nonscalar - object, reference, rich-text, image
          type: 'string',

          // string
          isBody: false,
          isTitle: true,

          // datetime
          dateFormat: '',
          timeFormat: '',

          // reference
          reverseLookup: { label: '', name: '' },
          collections: [],

          // object
          visualSelector: false,
          templates: '',
          fields: [],

          // 基础字段
          label: 'Title',
          name: 'title',
          required: true,
          description: '',
          list: false,

          ui: {
            defaultValue: 'A new title', // 定义默认值
            component: 'textarea', // 定义 UI 组件
          },
        },
        {
          type: 'string',
          label: 'Post Body',
          name: 'body',
          // markdown body
          isBody: true,
        },
        {
          label: 'Tags',
          name: 'tags',
          type: 'string',
          // array
          list: true,
        },
        {
          label: 'Categories',
          name: 'categories',
          type: 'string',
          list: true,
          // 限定值
          options: [
            {
              value: 'movies',
              label: 'Movies',
            },
            {
              value: 'music',
              label: 'Music',
            },
          ],
        },
        // 嵌套对象
        {
          label: 'Testimonial',
          name: 'testimonial',
          type: 'object',
          fields: [
            {
              label: 'Quote',
              name: 'quote',
              type: 'string',
              ui: {
                component: 'textarea',
              },
            },
          ],
        },
        {
          label: 'Author',
          name: 'author',
          type: 'reference',
          collections: ['author'], // 引用已有 entity
        },
      ],
    },
  ],
});

export default schema;

next-tinacms-json

基于 本地 JSON 提供编辑数据,已废弃。

  • useJsonForm
  • useLocalJsonForm
  • useGlobalJsonForm
  • InlineJsonForm: A render-children component
  • inlineJsonForm: A higher-order component
  • 实现
    • 获取 json 文件数据
    • next 全局初始化时候配置 json 映射关系 {fileRelativePath:string,data:any}
    • 通过 useLocalJsonForm 获取映射的文件数据
TypeScript
export function useLocalJsonForm<T = any>(
  // 文件映射定义
  jsonFile: JsonFile<T>,
  options?: Options,
) {
  const [values, form] = useJsonForm(jsonFile, options);

  usePlugins(form);

  return [values, form];
}
TypeScript
import { useCallback } from 'react';
import { useWatchFormValues, useForm, useCMS, FormOptions, Field } from 'tinacms';
import { generateFields } from './generate-fields';

/**
 * 表示 git 存储的文件
 */
export interface JsonFile<T = any> {
  fileRelativePath: string;
  data: T;
}

export interface Options {
  id?: string;
  label?: string;
  fields?: Field[];
  actions?: FormOptions<any>['actions'];
}
/**
 * 创建一个编辑 GIT 里 JSON 的表单
 */
export function useJsonForm<T = any>(jsonFile: JsonFile<T>, options: Options = {}) {
  const cms = useCMS();

  const id = options.id || jsonFile.fileRelativePath;
  const label = options.label || jsonFile.fileRelativePath;
  const fields = options.fields || generateFields(jsonFile);
  const actions = options.actions || [];
  // 创建表单
  const [values, form] = useForm(
    {
      id,
      label,
      fields,
      actions,
      loadInitialValues() {
        // 通过 git 接口初始化数据
        return cms.api.git.show(jsonFile.fileRelativePath).then((git: { content: string }) => {
          const jsonFileInGit = JSON.parse(git.content);

          return jsonFileInGit;
        });
      },
      onSubmit() {
        // 通过 git 接口提交数据 - 版本概念
        return cms.api.git.commit({
          files: [jsonFile.fileRelativePath],
          message: `Commit from Tina: Update ${jsonFile.fileRelativePath}`,
        });
      },
      reset() {
        // 重置修改
        return cms.api.git.reset({ files: [id] });
      },
    },
    //
    { values: jsonFile.data, label },
  );

  const writeToDisk = useCallback(
    (formState) => {
      // 变化修改到文件
      cms.api.git.writeToDisk({
        fileRelativePath: jsonFile.fileRelativePath,
        content: JSON.stringify(formState.values, null, 2),
      });
    },
    [jsonFile.fileRelativePath],
  );
  // 监听表单变化
  useWatchFormValues(form, writeToDisk);

  return [values || jsonFile.data, form];
}

关联信息

反向链接、本文链接的其他页面和外部资料。

参考资料

GitHub5 条
最近更新commit fc53617编辑