@ovine/craft
Version:
Ovine json editor.
165 lines (164 loc) • 4.71 kB
JavaScript
import { get, includes, isEmpty, isObjectLike, map, cloneDeep, uniqueId, isArray } from 'lodash';
import React from 'react';
import { nodeIdKey } from "../../constants";
const getEditNodeInfo = (type) => {
const nodeConf = {
dialog: {
text: '弹窗',
},
drawer: {
text: '抽屉',
},
};
if (includes(Object.keys(nodeConf), type)) {
return nodeConf[type];
}
return false;
};
export const genNodeId = (type) => {
if (type === 'none') {
return uniqueId('none-');
}
return uniqueId('node-');
};
// 根据 ID 获取 key 的路径
export function getIdKeyPath(source, nodeId) {
if (!isObjectLike(source)) {
return [];
}
const path = [];
let found = false;
function search(stack) {
if (get(stack, nodeIdKey) === nodeId) {
found = true;
return;
}
map(stack, (value, key) => {
if (found) {
return;
}
path.push(key);
if (isObjectLike(stack[key])) {
search(value);
if (found) {
return;
}
}
path.pop();
});
}
search(source);
return path;
}
// 获取 渲染时 配置
export function getRenderSchema(self) {
const cursor = self.editCursor;
const schema = cursor.get();
// 异常数据
if (!isObjectLike(schema) || isEmpty(schema)) {
return {
type: 'tpl',
tpl: '请输入有效 schema',
};
}
if (!getEditNodeInfo(schema.type)) {
return schema;
}
// 重写 dialog/drawer 容器组件 禁止 预览时 弹出
const Component = ({ children }) => (React.createElement("div", { "data-id": schema[nodeIdKey], className: "bg-white" }, children));
const renderSchema = Object.assign(Object.assign({}, schema), { wrapperComponent: Component });
return renderSchema;
}
// 获取所有的节点信息
export function getAllNodes(schema) {
// 异常数据
if (!isObjectLike(schema) || isEmpty(schema)) {
return [];
}
const nodes = [];
// 遍历节点
const travel = (node, key, items = []) => {
if (!isObjectLike(node)) {
return;
}
const item = { children: [] };
if (isArray(node)) {
item.type = `${key}-array`;
item.id = genNodeId('none');
items.push(item);
}
else {
const type = get(node, 'type');
// 将每一个有 type 属性的渲染器,与 id 标记
const omitEditNode = getEditNodeInfo(schema.type) || !getEditNodeInfo(type);
if (type && omitEditNode && !!node[nodeIdKey]) {
item.type = type;
item.id = node[nodeIdKey];
items.push(item);
}
}
map(node, (subNode, subKey) => {
travel(subNode, subKey, item.children);
});
};
travel(schema, '', nodes);
return nodes;
}
// 获取需要独立编辑的 节点
export function getEditNodes(schema) {
const nodes = [
{
id: '',
label: '页面',
},
];
if (!isObjectLike(schema)) {
return nodes;
}
// 遍历设置
const travel = (node) => {
if (!isObjectLike(node)) {
return;
}
const type = get(node, 'type');
const id = get(node, nodeIdKey);
const info = getEditNodeInfo(type);
// 将每一个有 type 属性的渲染器,添加 id 标记
if (type && id && info) {
nodes.push({
id,
// TODO: label 需要优化 更明确的 标示
label: `${info.text}-${node.title || id}`,
});
}
map(node, travel);
};
travel(schema);
return nodes;
}
export function setSchemaNodeId(source, option = {}) {
const { isClone = false, forceUpdate = false } = option;
// 防止数据篡改
const schema = isClone ? cloneDeep(source) : source;
// 异常数据
if (!isObjectLike(schema) || isEmpty(schema)) {
return {
type: 'tpl',
tpl: '请输入有效 schema',
};
}
// 遍历设置
const travel = (node) => {
if (!isObjectLike(node)) {
return;
}
const type = get(node, 'type');
// 将每一个有 type 属性的渲染器,添加 id 标记
if (type && (!node[nodeIdKey] || forceUpdate)) {
node[nodeIdKey] = genNodeId();
}
map(node, travel);
};
travel(schema);
return schema;
}