Merge pull request #1 from foomo/chor/eslint-and-prettier

Chor: eslint and prettier
This commit is contained in:
Cristian Vidmar 2023-02-21 11:00:52 +01:00 committed by GitHub
commit dbed81f5c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 1447 additions and 1017 deletions

35
.eslintrc.json Normal file
View File

@ -0,0 +1,35 @@
{
"env": {
"es6": true,
"node": true,
"browser": true
},
"extends": [
"plugin:react/recommended",
"standard-with-typescript",
"plugin:prettier/recommended"
],
"ignorePatterns": [
"**/dist/**",
"**/node_modules/**",
".eslintrc.json",
"tsconfig.json",
"package.json"
],
"overrides": [],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module",
"project": "tsconfig.json"
},
"plugins": [
"react",
"prettier",
"@typescript-eslint"
],
"rules": {
"@typescript-eslint/strict-boolean-expressions": 0,
"prettier/prettier": "error"
}
}

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
dist
node_modules
# misc
.DS_Store

1
.prettierignore Normal file
View File

@ -0,0 +1 @@
dist

38
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,38 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"editor.formatOnSave": true,
"[typescript]": {
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
},
"[javascript]": {
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
},
"[typescriptreact]": {
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
},
"[json]": {
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
},
"eslint.packageManager": "yarn",
"files.exclude": {
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/CVS": true,
"**/.DS_Store": true,
"**/Thumbs.db": true,
"**/node_modules": true
}
}

View File

@ -1,2 +1,3 @@
# contentfultree
A React component to display a tree of entries and references in a contentful app

14
dist/ContentTree.d.ts vendored
View File

@ -1,14 +0,0 @@
import { PlainClientAPI } from 'contentful-management';
import { PageExtensionSDK } from 'contentful-ui-extensions-sdk';
export interface ContentTreeProps {
sdkInstance: PageExtensionSDK;
cma: PlainClientAPI;
rootType: string;
nodeContentTypes: string[];
titleFields: string[];
locales: string[];
iconRegistry?: {
[index: string]: string;
};
}
export declare const ContentTree: (props: ContentTreeProps) => JSX.Element;

321
dist/ContentTree.js vendored
View File

@ -1,321 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ContentTree = void 0;
var react_1 = __importStar(require("react"));
var use_immer_1 = require("use-immer");
var ContentTree_styled_1 = require("./ContentTree.styled");
var ContentTreeNode_1 = __importDefault(require("./ContentTreeNode"));
var emptyNodeProps = function () {
return { id: '', name: '', expand: false, parentId: '' };
};
var ContentTree = function (props) {
var _a = (0, react_1.useState)(props.locales[0]), stLocale = _a[0], setStLocale = _a[1];
var _b = (0, use_immer_1.useImmer)(emptyNodeProps()), stRoot = _b[0], setStRoot = _b[1];
(0, react_1.useEffect)(function () {
if (props.sdkInstance) {
loadRootData();
}
}, [props.sdkInstance]);
var addChildNodes = function (node) { return __awaiter(void 0, void 0, void 0, function () {
var childNodes, cfChildren;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
childNodes = [];
return [4, getContentfulChildEntries(node.id)];
case 1:
cfChildren = _a.sent();
childNodes = cfEntriesToNodes(cfChildren, node.id);
setStRoot(function (draft) {
recursiveProcessNodes(node.id, function (targetNode) {
targetNode.childNodes = childNodes;
targetNode.expand = true;
}, draft);
console.log('🎈draft', draft);
});
return [2];
}
});
}); };
var recursiveProcessNodes = function (targetNodeId, processNode, node) {
if (node.id === targetNodeId) {
processNode(node);
}
if (node.childNodes) {
for (var _i = 0, _a = node.childNodes; _i < _a.length; _i++) {
var targetNode = _a[_i];
recursiveProcessNodes(targetNodeId, processNode, targetNode);
}
}
};
var editEntry = function (entryId) {
props.sdkInstance.navigator.openEntry(entryId, { slideIn: true });
};
var getContentfulChildEntries = function (parentId) { return __awaiter(void 0, void 0, void 0, function () {
var parentItem, allChildIds, _i, _a, key, childNodeRefs, _b, childNodeRefs_1, childNodeRef, allItems, done, skip, col, cfChildren, idPositionMap, _c, allChildIds_1, childId;
return __generator(this, function (_d) {
switch (_d.label) {
case 0: return [4, props.cma.entry.get({ entryId: parentId })];
case 1:
parentItem = _d.sent();
allChildIds = [];
for (_i = 0, _a = Object.keys(parentItem.fields); _i < _a.length; _i++) {
key = _a[_i];
if (props.nodeContentTypes.includes(key)) {
childNodeRefs = parentItem.fields[key][stLocale];
if (Array.isArray(childNodeRefs)) {
for (_b = 0, childNodeRefs_1 = childNodeRefs; _b < childNodeRefs_1.length; _b++) {
childNodeRef = childNodeRefs_1[_b];
allChildIds.push(childNodeRef.sys.id);
}
}
else {
allChildIds.push(childNodeRefs.sys.id);
}
}
}
allItems = [];
done = false;
skip = 0;
_d.label = 2;
case 2:
if (!!done) return [3, 4];
return [4, props.cma.entry.getMany({ query: {
'sys.id[in]': allChildIds.join(','),
skip: skip
} })];
case 3:
col = _d.sent();
allItems.push.apply(allItems, col.items);
if (allItems.length < col.total) {
skip += 100;
}
else {
done = true;
}
return [3, 2];
case 4:
cfChildren = [];
idPositionMap = allItems.reduce(function (acc, el, i) {
acc[el.sys.id] = i;
return acc;
}, {});
for (_c = 0, allChildIds_1 = allChildIds; _c < allChildIds_1.length; _c++) {
childId = allChildIds_1[_c];
if (allItems[idPositionMap[childId]]) {
cfChildren.push(allItems[idPositionMap[childId]]);
}
}
return [2, cfChildren];
}
});
}); };
var cfEntriesToNodes = function (entries, parentId) {
if (entries.length === 0) {
return [];
}
var nodeArray = [];
entries.forEach(function (entry) {
if (!entry) {
console.log('this entry is nil');
return;
}
var name = '';
for (var _i = 0, _a = props.titleFields; _i < _a.length; _i++) {
var titleField = _a[_i];
if (entry.fields[titleField] && entry.fields[titleField][stLocale]) {
name = entry.fields[titleField][stLocale];
break;
}
}
if (name === '') {
name = entry.sys.id;
}
var node = {
id: entry.sys.id,
name: name,
contentType: entry.sys.contentType.sys.id,
icon: props.iconRegistry ? props.iconRegistry[entry.sys.contentType.sys.id] : '',
expand: !parentId,
parentId: parentId,
hasChildNodes: cfEntryHasChildren(entry),
publishingStatus: cfEntryPublishingStatus(entry),
updatedAt: entry.sys.updatedAt,
publishedAt: entry.sys.publishedAt
};
nodeArray.push(node);
});
return nodeArray;
};
var cfEntryHasChildren = function (entry) {
for (var _i = 0, _a = props.nodeContentTypes; _i < _a.length; _i++) {
var nodeContentType = _a[_i];
for (var _b = 0, _c = props.locales; _b < _c.length; _b++) {
var locale = _c[_b];
if (entry.fields[nodeContentType] && entry.fields[nodeContentType][locale]) {
return true;
}
}
}
return false;
};
var cfEntryPublishingStatus = function (entry) {
if (!entry.sys.publishedVersion) {
return 'draft';
}
if (entry.sys.version - entry.sys.publishedVersion == 1) {
return 'published';
}
return 'changed';
};
var loadRootData = function () { return __awaiter(void 0, void 0, void 0, function () {
var CfRootData, rootNodes, _loop_1, _i, rootNodes_1, rootNode;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, props.cma.entry.getMany({ query: { content_type: props.rootType } })];
case 1:
CfRootData = _a.sent();
rootNodes = cfEntriesToNodes(CfRootData.items);
_loop_1 = function (rootNode) {
var childEntries, childNodes, nodes, newIdPositionMap_1, tree_1;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4, getContentfulChildEntries(rootNode.id)];
case 1:
childEntries = _b.sent();
childNodes = cfEntriesToNodes(childEntries, rootNode.id);
nodes = __spreadArray([rootNode], childNodes, true);
if (nodes.length > 0) {
newIdPositionMap_1 = nodes.reduce(function (acc, el, i) {
acc[el.id] = i;
return acc;
}, {});
tree_1 = emptyNodeProps();
nodes.forEach(function (node) {
node.childNodes = [];
if (!node.parentId) {
tree_1 = node;
return;
}
var parentEl = nodes[newIdPositionMap_1[node.parentId]];
if (parentEl) {
parentEl.childNodes = __spreadArray(__spreadArray([], (parentEl.childNodes || []), true), [node], false);
parentEl.expand = true;
}
});
console.log('🌴 tree', tree_1);
setStRoot(tree_1);
}
return [2];
}
});
};
_i = 0, rootNodes_1 = rootNodes;
_a.label = 2;
case 2:
if (!(_i < rootNodes_1.length)) return [3, 5];
rootNode = rootNodes_1[_i];
return [5, _loop_1(rootNode)];
case 3:
_a.sent();
_a.label = 4;
case 4:
_i++;
return [3, 2];
case 5: return [2];
}
});
}); };
var removeChildNodes = function (node) {
setStRoot(function (draft) {
recursiveProcessNodes(node.id, function (targetNode) {
targetNode.childNodes = [];
targetNode.expand = false;
}, draft);
console.log('🎈draft', draft);
});
};
console.log('=============================== RENDER ====================================', stRoot);
return (react_1.default.createElement(react_1.default.Fragment, null,
react_1.default.createElement(ContentTree_styled_1.StyledContentTreeTable, null,
react_1.default.createElement("tbody", null,
react_1.default.createElement("tr", null,
react_1.default.createElement("th", null, "Nodes"),
react_1.default.createElement("th", null, "Content Type"),
react_1.default.createElement("th", null, "Status"),
react_1.default.createElement("th", null, "Last Modified"),
react_1.default.createElement("th", null, "Last Published")),
react_1.default.createElement(ContentTreeNode_1.default, { node: stRoot, depth: 0, addChildNodes: addChildNodes, removeChildNodes: removeChildNodes, editEntry: editEntry })))));
};
exports.ContentTree = ContentTree;

View File

@ -1,14 +0,0 @@
export interface UiPalette {
publishingStatusBg?: string;
publishingStatusFg?: string;
}
export declare const StyledContentTreeTable: import("styled-components").StyledComponent<"table", any, {}, never>;
export declare const StyledContentTreeTableNodeCell: import("styled-components").StyledComponent<"td", any, {
depth?: number | undefined;
}, never>;
export declare const StyledContentTreeNodeWedge: import("styled-components").StyledComponent<"div", any, {}, never>;
export declare const StyledContentTreeNodeName: import("styled-components").StyledComponent<"div", any, {}, never>;
export declare const StyledContentTreeNodePublishingStatus: import("styled-components").StyledComponent<"div", any, {
status: string;
}, never>;
export declare const StyledSpinner: import("styled-components").StyledComponent<"div", any, {}, never>;

View File

@ -1,37 +0,0 @@
"use strict";
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.StyledSpinner = exports.StyledContentTreeNodePublishingStatus = exports.StyledContentTreeNodeName = exports.StyledContentTreeNodeWedge = exports.StyledContentTreeTableNodeCell = exports.StyledContentTreeTable = void 0;
var styled_components_1 = __importDefault(require("styled-components"));
exports.StyledContentTreeTable = styled_components_1.default.table(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n color: black;\n border: 0;\n margin: 0 auto;\n td {\n padding: 0.2em 1em 0.2em 0.2em;\n color: #999999; \n border-bottom: 1px solid #efefef;\n }\n th {\n text-align: left;\n font-weight: normal;\n font-size: 85%;\n color: #666666;\n background: #efefef;\n padding: 0.2em;\n }\n th.first {\n font-weight: bold !important;\n color:black !important;\n }\n"], ["\n color: black;\n border: 0;\n margin: 0 auto;\n td {\n padding: 0.2em 1em 0.2em 0.2em;\n color: #999999; \n border-bottom: 1px solid #efefef;\n }\n th {\n text-align: left;\n font-weight: normal;\n font-size: 85%;\n color: #666666;\n background: #efefef;\n padding: 0.2em;\n }\n th.first {\n font-weight: bold !important;\n color:black !important;\n }\n"])));
exports.StyledContentTreeTableNodeCell = styled_components_1.default.td(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n padding-left: ", "em !important;\n padding-right: 2em !important;\n color: black !important;\n min-width: 450px !important;\n"], ["\n padding-left: ", "em !important;\n padding-right: 2em !important;\n color: black !important;\n min-width: 450px !important;\n"])), function (props) { return 0.2 + props.depth; });
exports.StyledContentTreeNodeWedge = styled_components_1.default.div(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n display: inline-block;\n width: 1em;\n text-align: left;\n a {\n cursor:pointer;\n font-size: 130%;\n line-height: 100%;\n }\n"], ["\n display: inline-block;\n width: 1em;\n text-align: left;\n a {\n cursor:pointer;\n font-size: 130%;\n line-height: 100%;\n }\n"])));
exports.StyledContentTreeNodeName = styled_components_1.default.div(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n display: inline-block;\n a {\n cursor: pointer; \n }\n a:hover {\n text-decoration:underline;\n }\n"], ["\n display: inline-block;\n a {\n cursor: pointer; \n }\n a:hover {\n text-decoration:underline;\n }\n"])));
var getPublishingStatusColors = function (status) {
switch (status) {
case 'draft':
return {
publishingStatusBg: 'rgb(253, 229, 192)',
publishingStatusFg: 'rgb(177, 45, 0)'
};
case 'changed':
return {
publishingStatusBg: 'rgb(206, 236, 255)',
publishingStatusFg: 'rgb(0, 89, 200)'
};
case 'published':
return {
publishingStatusBg: 'rgb(205, 243, 198)',
publishingStatusFg: 'rgb(0, 109, 35)'
};
}
};
exports.StyledContentTreeNodePublishingStatus = styled_components_1.default.div(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n display: inline-block;\n font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;\n font-weight: 600;\n font-size: 80%;\n text-transform: uppercase;\n letter-spacing: 0.06rem;\n border-radius: 4px;\n padding: 0 0.2rem;\n color: ", " !important;\n background-color: ", " !important;\n}\n"], ["\n display: inline-block;\n font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;\n font-weight: 600;\n font-size: 80%;\n text-transform: uppercase;\n letter-spacing: 0.06rem;\n border-radius: 4px;\n padding: 0 0.2rem;\n color: ", " !important;\n background-color: ", " !important;\n}\n"])), function (props) { var _a; return (_a = getPublishingStatusColors(props.status)) === null || _a === void 0 ? void 0 : _a.publishingStatusFg; }, function (props) { var _a; return (_a = getPublishingStatusColors(props.status)) === null || _a === void 0 ? void 0 : _a.publishingStatusBg; });
exports.StyledSpinner = styled_components_1.default.div(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n display:inline-block;\n width: 1em;\n animation: rotate 1s infinite;\n @keyframes rotate {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n"], ["\n display:inline-block;\n width: 1em;\n animation: rotate 1s infinite;\n @keyframes rotate {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n"])));
var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6;

View File

@ -1,21 +0,0 @@
export interface ContentTreeNodeProps {
id: string;
name: string;
contentType: string;
icon: string;
expand: boolean;
parentId: string;
childNodes?: ContentTreeNodeProps[];
hasChildNodes?: boolean;
publishingStatus: string;
updatedAt?: string;
publishedAt?: string;
}
declare const ContentTreeNode: (props: {
node: ContentTreeNodeProps;
depth?: number | undefined;
addChildNodes: (node: ContentTreeNodeProps) => void;
removeChildNodes: (node: ContentTreeNodeProps) => void;
editEntry: (nodeId: string) => void;
}) => JSX.Element;
export default ContentTreeNode;

View File

@ -1,98 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = __importStar(require("react"));
var ContentTree_styled_1 = require("./ContentTree.styled");
var Icons_1 = require("./Icons");
var ContentTreeNode = function (props) {
var _a;
var _b = (0, react_1.useState)(false), loading = _b[0], setLoading = _b[1];
var _c = (0, react_1.useState)(props.node), node = _c[0], setNode = _c[1];
var addChildren = function () { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
setLoading(true);
return [4, props.addChildNodes(node)];
case 1:
_a.sent();
setLoading(false);
return [2];
}
});
}); };
return (react_1.default.createElement(react_1.default.Fragment, null,
react_1.default.createElement("tr", null,
react_1.default.createElement(ContentTree_styled_1.StyledContentTreeTableNodeCell, { depth: props.depth },
react_1.default.createElement(ContentTree_styled_1.StyledContentTreeNodeWedge, null, loading ? (react_1.default.createElement(ContentTree_styled_1.StyledSpinner, null, "-")) : props.node.hasChildNodes ? props.node.expand ? (react_1.default.createElement("a", { onClick: function () { return props.removeChildNodes(props.node); } }, "-")) : (react_1.default.createElement("a", { onClick: function () { return addChildren(); } }, "+")) : null),
react_1.default.createElement(Icons_1.Icon, { id: props.node.icon }),
react_1.default.createElement(ContentTree_styled_1.StyledContentTreeNodeName, null,
react_1.default.createElement("a", { onClick: function () { return props.editEntry(props.node.id); }, title: props.node.id }, props.node.name))),
react_1.default.createElement("td", null, props.node.contentType),
react_1.default.createElement("td", null,
react_1.default.createElement(ContentTree_styled_1.StyledContentTreeNodePublishingStatus, { status: props.node.publishingStatus }, props.node.publishingStatus)),
react_1.default.createElement("td", null, props.node.updatedAt),
react_1.default.createElement("td", null, props.node.publishedAt)), (_a = props.node.childNodes) === null || _a === void 0 ? void 0 :
_a.map(function (node, i) {
return react_1.default.createElement(ContentTreeNode, { key: i, node: node, depth: props.depth + 1, addChildNodes: props.addChildNodes, removeChildNodes: props.removeChildNodes, editEntry: props.editEntry });
})));
};
exports.default = ContentTreeNode;

9
dist/Icons.d.ts vendored
View File

@ -1,9 +0,0 @@
import { FC, SVGProps } from 'react';
export declare type SVGIcon = FC<SVGProps<SVGSVGElement>>;
export interface IconProps {
icon?: SVGIcon;
}
export declare const Icon: (props: {
id?: string;
}) => JSX.Element;
export declare const StyledIcon: import("styled-components").StyledComponent<"span", any, {}, never>;

80
dist/Icons.js vendored
View File

@ -1,80 +0,0 @@
"use strict";
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.StyledIcon = exports.Icon = void 0;
var react_1 = __importDefault(require("react"));
var styled_components_1 = __importDefault(require("styled-components"));
var Icon = function (props) {
switch (props.id) {
case 'WORLD':
return react_1.default.createElement(exports.StyledIcon, null,
react_1.default.createElement("svg", { id: "Layer_1", "data-name": "Layer 1", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 128 128" },
react_1.default.createElement("title", null, "WORLD"),
react_1.default.createElement("path", { d: "M113.66,23.69q-.345-.435-.72-.87A63.786,63.786,0,0,0,64.92.02C64.61.01,64.31,0,64,0s-.61.01-.92.02A63.789,63.789,0,0,0,14.93,22.98a6.164,6.164,0,0,0-.47.57.138.138,0,0,1-.03.04,63.8,63.8,0,0,0,0,80.82.138.138,0,0,1,.03.04,6.171,6.171,0,0,0,.47.57l.01.01a63.776,63.776,0,0,0,48.14,22.95c.614.02,1.226.02,1.84,0a63.786,63.786,0,0,0,48.02-22.8q.375-.435.72-.87a63.826,63.826,0,0,0,0-80.62ZM99.49,62.25a106.208,106.208,0,0,0-4.07-28.03,69.57,69.57,0,0,0,16.19-7.51,60.158,60.158,0,0,1,12.86,35.54ZM65.75,3.59c10.69,1.1,19.99,12.14,25.36,28.3a100.612,100.612,0,0,1-25.36,3.58Zm-3.5,31.88a100.612,100.612,0,0,1-25.36-3.58c5.37-16.16,14.67-27.2,25.36-28.3Zm0,3.5V62.25H32.01a104.4,104.4,0,0,1,3.85-27.02A104.159,104.159,0,0,0,62.25,38.97Zm0,26.78V89.03a104.161,104.161,0,0,0-26.39,3.74,104.4,104.4,0,0,1-3.85-27.02Zm0,26.78v31.88c-10.69-1.1-19.99-12.14-25.36-28.3A100.612,100.612,0,0,1,62.25,92.53Zm3.5,0a100.612,100.612,0,0,1,25.36,3.58c-5.37,16.16-14.67,27.2-25.36,28.3Zm0-3.5V65.75H95.99a104.477,104.477,0,0,1-3.85,27.03A103.333,103.333,0,0,0,65.75,89.03Zm0-26.78V38.97a103.33,103.33,0,0,0,26.39-3.75,104.478,104.478,0,0,1,3.85,27.03Zm43.6-38.26A66.171,66.171,0,0,1,94.37,30.9C90.53,19.48,84.76,10.4,77.89,5.11A60.6,60.6,0,0,1,109.35,23.99ZM50.11,5.11C43.24,10.4,37.47,19.48,33.63,30.9A67.031,67.031,0,0,1,18.65,24,60.513,60.513,0,0,1,50.11,5.11ZM16.39,26.7a69.605,69.605,0,0,0,16.19,7.53,106.07,106.07,0,0,0-4.07,28.02H3.53A60.188,60.188,0,0,1,16.39,26.7ZM28.51,65.75a106.069,106.069,0,0,0,4.07,28.02v.01a69.183,69.183,0,0,0-16.19,7.52A60.188,60.188,0,0,1,3.53,65.75ZM18.65,104a67.031,67.031,0,0,1,14.98-6.9c3.84,11.42,9.61,20.5,16.48,25.79A60.514,60.514,0,0,1,18.65,104Zm59.24,18.89c6.87-5.29,12.64-14.37,16.48-25.79a66.169,66.169,0,0,1,14.98,6.91A60.6,60.6,0,0,1,77.89,122.89Zm33.72-21.6a69.573,69.573,0,0,0-16.19-7.51,106.208,106.208,0,0,0,4.07-28.03h24.98A60.158,60.158,0,0,1,111.61,101.29Z" })));
case 'PAGE':
return react_1.default.createElement(exports.StyledIcon, null,
react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 48 48" },
react_1.default.createElement("defs", null),
react_1.default.createElement("title", null, "Asset 47ldpi"),
react_1.default.createElement("g", { id: "Layer_2", "data-name": "Layer 2" },
react_1.default.createElement("g", { id: "layer_1-2", "data-name": "layer 1" },
react_1.default.createElement("path", { d: "M47,48H1a1,1,0,0,1-1-1V1A1,1,0,0,1,1,0H47a1,1,0,0,1,1,1V47A1,1,0,0,1,47,48ZM2,46H46V2H2Z" }),
react_1.default.createElement("rect", { x: "34", y: "25", width: "8", height: "2" }),
react_1.default.createElement("rect", { x: "22", y: "25", width: "10", height: "2" }),
react_1.default.createElement("rect", { x: "31", y: "30", width: "7", height: "2" }),
react_1.default.createElement("rect", { x: "22", y: "30", width: "7", height: "2" }),
react_1.default.createElement("rect", { x: "36", y: "35", width: "6", height: "2" }),
react_1.default.createElement("rect", { x: "22", y: "35", width: "12", height: "2" }),
react_1.default.createElement("rect", { x: "22", y: "40", width: "9", height: "2" }),
react_1.default.createElement("path", { d: "M18,42H7a1,1,0,0,1-1-1V26a1,1,0,0,1,1-1H18a1,1,0,0,1,1,1V41A1,1,0,0,1,18,42ZM8,40h9V27H8Z" }),
react_1.default.createElement("path", { d: "M41,22H7a1,1,0,0,1-1-1V15a1,1,0,0,1,1-1H41a1,1,0,0,1,1,1v6A1,1,0,0,1,41,22ZM8,20H40V16H8Z" }),
react_1.default.createElement("rect", { x: "4", y: "4", width: "2", height: "2" }),
react_1.default.createElement("rect", { x: "8", y: "4", width: "2", height: "2" }),
react_1.default.createElement("rect", { x: "12", y: "4", width: "2", height: "2" }),
react_1.default.createElement("rect", { x: "1", y: "8", width: "46", height: "2" })))));
case 'APP':
return react_1.default.createElement(exports.StyledIcon, null,
react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 32 32" },
react_1.default.createElement("title", null, "8-Book"),
react_1.default.createElement("g", { id: "_8-Book", "data-name": "8-Book" },
react_1.default.createElement("path", { d: "M27,23a5,5,0,0,0-3-1H6a5,5,0,0,0-3,1V5A3,3,0,0,1,6,2H18V0H6A5,5,0,0,0,1,5V27a5,5,0,0,0,5,5H28a1,1,0,0,0,1-1V19H27Zm0,7H6a3,3,0,0,1,0-6H24a3,3,0,0,1,2.82,2H10v2H27Z" }),
react_1.default.createElement("rect", { x: "6", y: "26", width: "2", height: "2" }),
react_1.default.createElement("path", { d: "M15,7V5H7A1,1,0,0,0,6,6v4a1,1,0,0,0,1,1h8V9H8V7Z" }),
react_1.default.createElement("rect", { x: "6", y: "14", width: "2", height: "2" }),
react_1.default.createElement("rect", { x: "10", y: "14", width: "2", height: "2" }),
react_1.default.createElement("path", { d: "M31,11V9H28.9a5,5,0,0,0-.73-1.75l1.54-1.54L28.29,4.29,26.75,5.83A5,5,0,0,0,25,5.1V3H23V5.1a5,5,0,0,0-1.75.73L19.71,4.29,18.29,5.71l1.54,1.54A5,5,0,0,0,19.1,9H17v2h2.1a5,5,0,0,0,.73,1.75l-1.54,1.54,1.41,1.41,1.54-1.54A5,5,0,0,0,23,14.9V17h2V14.9a5,5,0,0,0,1.75-.73l1.54,1.54,1.41-1.41-1.54-1.54A5,5,0,0,0,28.9,11Zm-7,2a3,3,0,1,1,3-3A3,3,0,0,1,24,13Z" }))));
case 'CART':
return react_1.default.createElement(exports.StyledIcon, null,
react_1.default.createElement("svg", { version: "1.1", id: "shopping_x5F_carts_1_", xmlns: "http://www.w3.org/2000/svg", x: "0", y: "0", viewBox: "0 0 128 128" },
react_1.default.createElement("g", { id: "_x31__1_" },
react_1.default.createElement("path", { d: "M92.1 96c-5.2 0-9.3 4.2-9.3 9.3 0 5.2 4.2 9.3 9.3 9.3s9.3-4.2 9.3-9.3c0-5.1-4.1-9.3-9.3-9.3zm0 16a6.7 6.7 0 1 1 6.7-6.7c0 3.8-3 6.7-6.7 6.7zM41.4 96c-5.2 0-9.3 4.2-9.3 9.3 0 5.2 4.2 9.3 9.3 9.3s9.3-4.2 9.3-9.3c0-5.1-4.2-9.3-9.3-9.3zm0 16a6.7 6.7 0 1 1 6.7-6.7c0 3.8-3 6.7-6.7 6.7zm86.2-73.5c-.5-.8-1.3-1.2-2.2-1.2h-102L19 15.4c-.3-1.2-1.3-2.1-2.6-2.1H2.7C1.2 13.3 0 14.5 0 16c0 1.5 1.2 2.7 2.7 2.7h11.4l14.6 72.6c.3 1.2 1.3 2.1 2.6 2.1h72.2c1.1 0 2-.6 2.4-1.6L127.8 41c.3-.8.3-1.7-.2-2.5zM101.7 88H33.5l-2.7-13.3h76.7L101.7 88zm6.9-16H30.3l-2.7-13.3h86.8L108.6 72zm6.9-16H27l-2.7-13.3h96.9L115.5 56z", id: "icon_14_" }))));
case 'FOLDER':
return react_1.default.createElement(exports.StyledIcon, null,
react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 64 64" },
react_1.default.createElement("path", { d: "M64 15v37a5.006 5.006 0 0 1-5 5H5a5.006 5.006 0 0 1-5-5V12a5.006 5.006 0 0 1 5-5h14.116a6.966 6.966 0 0 1 5.466 2.627l5 6.247A2.983 2.983 0 0 0 31.922 17H59a1 1 0 0 1 0 2H31.922a4.979 4.979 0 0 1-3.9-1.876l-5-6.247A4.976 4.976 0 0 0 19.116 9H5a3 3 0 0 0-3 3v40a3 3 0 0 0 3 3h54a3 3 0 0 0 3-3V15a3 3 0 0 0-3-3H30a1 1 0 0 1 0-2h29a5.006 5.006 0 0 1 5 5z" })));
case 'LOVE':
return react_1.default.createElement(exports.StyledIcon, null,
react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24" },
react_1.default.createElement("path", { d: "M22.813 7.338a6.736 6.736 0 0 0-3.8-4.49c-3.206-1.471-6 .878-7.016 1.9-1.013-1.025-3.813-3.374-7.016-1.9a6.736 6.736 0 0 0-3.8 4.49 5.818 5.818 0 0 0 1 4.98c1.708 2.215 9.156 8.891 9.472 9.174a.514.514 0 0 0 .688 0c.316-.283 7.764-6.959 9.472-9.174a5.815 5.815 0 0 0 1-4.98zM21 11.689c-1.448 1.878-7.488 7.362-9 8.726-1.512-1.364-7.552-6.848-9-8.726a4.8 4.8 0 0 1-.812-4.1 5.711 5.711 0 0 1 3.226-3.8c2.229-1.027 4.731.311 6.186 2.05a.516.516 0 0 0 .4.188.516.516 0 0 0 .4-.188c.029-.035 2.958-3.536 6.188-2.055a5.714 5.714 0 0 1 3.226 3.8A4.8 4.8 0 0 1 21 11.689z" }),
react_1.default.createElement("path", { d: "M6.346 5a4.39 4.39 0 0 0-2.473 2.928 3.818 3.818 0 0 0 .656 3.272.515.515 0 0 0 .816-.629 2.8 2.8 0 0 1-.472-2.392 3.366 3.366 0 0 1 1.9-2.237A.515.515 0 0 0 6.346 5z" })));
case 'SHORTCUT':
return react_1.default.createElement(exports.StyledIcon, null,
react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24" },
react_1.default.createElement("g", { "data-name": "13.Arrow up" },
react_1.default.createElement("path", { d: "M12 24a12 12 0 1 1 12-12 12.013 12.013 0 0 1-12 12zm0-22a10 10 0 1 0 10 10A10.011 10.011 0 0 0 12 2z" }),
react_1.default.createElement("path", { d: "M18 12h-2V9h-4V7h6v5z" }),
react_1.default.createElement("path", { d: "m3.707 17.707-1.414-1.414L6.586 12h5l4.707-4.707 1.414 1.414L12.414 14h-5l-3.707 3.707z" }))));
}
return react_1.default.createElement(exports.StyledIcon, null,
react_1.default.createElement("svg", { xmlns: "http://www.w3.org/2000/svg", width: "20.088", height: "20.087" },
react_1.default.createElement("path", { d: "M10.044 0a10.044 10.044 0 1 0 10.044 10.043A10.043 10.043 0 0 0 10.044 0zm.047 15.033a4.99 4.99 0 1 1 4.99-4.99 4.989 4.989 0 0 1-4.99 4.99z" })));
};
exports.Icon = Icon;
exports.StyledIcon = styled_components_1.default.span(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n line-height: 1px;\n position: relative;\n display: inline-block;\n vertical-align: top;\n width: 16px;\n height: 16px;\n margin: 2px 4px;\n"], ["\n line-height: 1px;\n position: relative;\n display: inline-block;\n vertical-align: top;\n width: 16px;\n height: 16px;\n margin: 2px 4px;\n"])));
var templateObject_1;

3
dist/index.d.ts vendored
View File

@ -1,3 +0,0 @@
export * from "./ContentTree";
export * from "./ContentTree.styled";
export * from "./ContentTreeNode";

19
dist/index.js vendored
View File

@ -1,19 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./ContentTree"), exports);
__exportStar(require("./ContentTree.styled"), exports);
__exportStar(require("./ContentTreeNode"), exports);

View File

@ -7,27 +7,46 @@
"scripts": {
"clean": "rm -f ./tsconfig.tsbuildinfo && rm -rvf dist",
"build": "yarn clean && tsc -b -v .",
"dev": "yarn tsc -b tsconfig.json -w"
"dev": "yarn tsc -b tsconfig.json -w",
"lint": "eslint --ext=js,jsx,ts,tsx,json .",
"lint:fix": "eslint --ext=js,jsx,ts,tsx,json . --fix"
},
"prettier": {
"useTabs": true,
"tabWidth": 2,
"singleQuote": true
},
"devDependencies": {
"@types/react": "^18.0.20",
"@types/styled-components": "^5.1.26",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.38.0",
"contentful-management": "^10.6.3",
"contentful-ui-extensions-sdk": "^4.8.1",
"eslint": "^8.23.1",
"eslint": "^8.0.1",
"eslint-config-prettier": "^8.5.0",
"eslint-config-standard-with-typescript": "^23.0.0",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-json": "3.1.0",
"eslint-plugin-n": "^15.0.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-react": "^7.31.8",
"immer": "^9.0.15",
"install-peers": "^1.0.4",
"prettier": "2.7.1",
"react": "18.2.0",
"styled-components": "^5.3.5",
"typescript": "^4.8.3",
"typescript": "*",
"use-immer": "^0.7.0"
},
"peerDependencies": {},
"peerDependencies": {
"install-peers": "^1.0.4"
},
"dependencies": {
"contentful-management": "^10.15.0",
"contentful-ui-extensions-sdk": "^4.12.1",
"immer": "^9.0.15",
"install-peers": "^1.0.4",
"react": "^18.2.0",
"styled-components": "^5.3.5",
"use-immer": "^0.7.0"

View File

@ -1,82 +1,84 @@
import styled from 'styled-components';
export interface UiPalette {
publishingStatusBg?: string,
publishingStatusFg?: string,
publishingStatusBg?: string;
publishingStatusFg?: string;
}
export const StyledContentTreeTable = styled.table`
color: black;
border: 0;
margin: 0 auto;
td {
padding: 0.2em 1em 0.2em 0.2em;
color: #999999;
border-bottom: 1px solid #efefef;
}
th {
text-align: left;
font-weight: normal;
font-size: 85%;
color: #666666;
background: #efefef;
padding: 0.2em;
}
th.first {
font-weight: bold !important;
color:black !important;
}
color: black;
border: 0;
margin: 0 auto;
td {
padding: 0.2em 1em 0.2em 0.2em;
color: #999999;
border-bottom: 1px solid #efefef;
}
th {
text-align: left;
font-weight: normal;
font-size: 85%;
color: #666666;
background: #efefef;
padding: 0.2em;
}
th.first {
font-weight: bold !important;
color: black !important;
}
`;
export const StyledContentTreeTableNodeCell = styled.td<{ depth?: number }>`
padding-left: ${(props) => 0.2 + props.depth!}em !important;
padding-right: 2em !important;
color: black !important;
min-width: 450px !important;
padding-left: ${(props) => props.depth}em !important;
padding-right: 2em !important;
color: black !important;
min-width: 450px !important;
`;
export const StyledContentTreeNodeWedge = styled.div`
display: inline-block;
width: 1em;
text-align: left;
a {
cursor:pointer;
font-size: 130%;
line-height: 100%;
}
`
display: inline-block;
width: 1em;
text-align: left;
a {
cursor: pointer;
font-size: 130%;
line-height: 100%;
}
`;
export const StyledContentTreeNodeName = styled.div`
display: inline-block;
a {
cursor: pointer;
}
a:hover {
text-decoration:underline;
}
`
display: inline-block;
a {
cursor: pointer;
}
a:hover {
text-decoration: underline;
}
`;
const getPublishingStatusColors = (status: string):UiPalette|undefined => {
switch (status) {
case 'draft':
return {
publishingStatusBg: 'rgb(253, 229, 192)',
publishingStatusFg: 'rgb(177, 45, 0)'
}
case 'changed':
return {
publishingStatusBg: 'rgb(206, 236, 255)',
publishingStatusFg: 'rgb(0, 89, 200)'
}
case 'published':
return {
publishingStatusBg: 'rgb(205, 243, 198)',
publishingStatusFg: 'rgb(0, 109, 35)'
}
}
}
const getPublishingStatusColors = (status: string): UiPalette | undefined => {
switch (status) {
case 'draft':
return {
publishingStatusBg: 'rgb(253, 229, 192)',
publishingStatusFg: 'rgb(177, 45, 0)',
};
case 'changed':
return {
publishingStatusBg: 'rgb(206, 236, 255)',
publishingStatusFg: 'rgb(0, 89, 200)',
};
case 'published':
return {
publishingStatusBg: 'rgb(205, 243, 198)',
publishingStatusFg: 'rgb(0, 109, 35)',
};
}
};
export const StyledContentTreeNodePublishingStatus = styled.div<{ status: string }>`
export const StyledContentTreeNodePublishingStatus = styled.div<{
status: string;
}>`
display: inline-block;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
font-weight: 600;
@ -85,17 +87,23 @@ export const StyledContentTreeNodePublishingStatus = styled.div<{ status: string
letter-spacing: 0.06rem;
border-radius: 4px;
padding: 0 0.2rem;
color: ${(props) => getPublishingStatusColors(props.status)?.publishingStatusFg} !important;
background-color: ${(props) => getPublishingStatusColors(props.status)?.publishingStatusBg} !important;
color: ${(props) =>
getPublishingStatusColors(props.status)?.publishingStatusFg} !important;
background-color: ${(props) =>
getPublishingStatusColors(props.status)?.publishingStatusBg} !important;
}
`
`;
export const StyledSpinner = styled.div`
display:inline-block;
width: 1em;
animation: rotate 1s infinite;
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
`
display: inline-block;
width: 1em;
animation: rotate 1s infinite;
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
`;

View File

@ -1,238 +1,270 @@
import { EntryProps, KeyValueMap, Link, PlainClientAPI } from 'contentful-management';
import {
EntryProps,
KeyValueMap,
Link,
PlainClientAPI,
} from 'contentful-management';
import { PageExtensionSDK } from 'contentful-ui-extensions-sdk';
import React, { useEffect, useState } from 'react';
import React, { ReactElement, useEffect, useState } from 'react';
import { useImmer } from 'use-immer';
import { StyledContentTreeTable } from './ContentTree.styled';
import ContentTreeNode, { ContentTreeNodeProps } from './ContentTreeNode';
export interface ContentTreeProps {
sdkInstance: PageExtensionSDK;
cma: PlainClientAPI;
rootType: string;
nodeContentTypes: string[];
titleFields: string[];
locales: string[]; //the first is the default locale
iconRegistry?: {[index:string]:string}
sdkInstance: PageExtensionSDK;
cma: PlainClientAPI;
rootType: string;
nodeContentTypes: string[];
titleFields: string[];
locales: string[]; // the first is the default locale
iconRegistry?: { [index: string]: string };
}
const emptyNodeProps = (): ContentTreeNodeProps => {
return { id: '', name: '', expand: false, parentId: '' } as ContentTreeNodeProps;
return { id: '', name: '', expand: false, parentId: '' };
};
export const ContentTree = (props: ContentTreeProps): ReactElement => {
const [stLocale] = useState(props.locales[0]);
const [stRoot, setStRoot] = useImmer(emptyNodeProps());
export const ContentTree = (props: ContentTreeProps) => {
const [stLocale, setStLocale] = useState(props.locales[0]);
const [stRoot, setStRoot] = useImmer(emptyNodeProps());
// EFFECTS
// EFFECTS
useEffect(() => {
if (props.sdkInstance) {
loadRootData().catch((err) => {
throw new Error('loadRootData', err);
});
}
}, [props.sdkInstance]);
useEffect(() => {
if (props.sdkInstance) {
loadRootData();
}
}, [props.sdkInstance]);
// FUNCTIONS
// FUNCTIONS
const addChildNodes = async (node: ContentTreeNodeProps): Promise<void> => {
let childNodes: ContentTreeNodeProps[] = [];
const cfChildren = await getContentfulChildEntries(node.id);
childNodes = cfEntriesToNodes(cfChildren, node.id);
setStRoot((draft) => {
recursiveProcessNodes(
node.id,
(targetNode) => {
targetNode.childNodes = childNodes;
targetNode.expand = true;
},
draft
);
console.log('🎈draft', draft);
});
};
const addChildNodes = async (node: ContentTreeNodeProps) => {
let childNodes: ContentTreeNodeProps[] = []
const cfChildren = await getContentfulChildEntries(node.id)
childNodes = cfEntriesToNodes(cfChildren, node.id)
setStRoot((draft) => {
recursiveProcessNodes(node.id,
(targetNode) => {
targetNode.childNodes = childNodes
targetNode.expand = true
},
draft)
console.log('🎈draft',draft)
})
}
const recursiveProcessNodes = (
targetNodeId: string,
processNode: (node:ContentTreeNodeProps)=>void,
node: ContentTreeNodeProps
) => {
if (node.id === targetNodeId) {
processNode(node)
}
if (node.childNodes) {
for (let targetNode of node.childNodes!) {
recursiveProcessNodes(targetNodeId,processNode, targetNode)
}
}
}
const recursiveProcessNodes = (
targetNodeId: string,
processNode: (node: ContentTreeNodeProps) => void,
node: ContentTreeNodeProps
): void => {
if (node.id === targetNodeId) {
processNode(node);
}
if (node.childNodes != null) {
for (const targetNode of node.childNodes) {
recursiveProcessNodes(targetNodeId, processNode, targetNode);
}
}
};
const editEntry = (entryId: string) => {
props.sdkInstance.navigator.openEntry(entryId, {slideIn:true})
}
const editEntry = async (entryId: string): Promise<void> => {
await props.sdkInstance.navigator.openEntry(entryId, { slideIn: true });
};
const getContentfulChildEntries = async (parentId: string): Promise<EntryProps<KeyValueMap>[]> => {
const parentItem = await props.cma.entry.get({ entryId: parentId });
let allChildIds: string[] = [];
for (const key of Object.keys(parentItem.fields)) {
if (props.nodeContentTypes.includes(key)) {
const childNodeRefs = parentItem.fields[key][stLocale] as Link<string> | Link<string>[];
if (Array.isArray(childNodeRefs)) {
for (const childNodeRef of childNodeRefs) {
allChildIds.push(childNodeRef.sys.id);
}
} else {
allChildIds.push(childNodeRefs.sys.id);
}
}
}
const allItems: EntryProps<KeyValueMap>[] = []
let done = false;
let skip=0;
while (!done) {
const col = await props.cma.entry.getMany({ query:{
'sys.id[in]': allChildIds.join(','),
skip: skip
}})
allItems.push(...col.items)
if (allItems.length < col.total) {
skip += 100
} else {
done = true
}
}
const cfChildren: EntryProps<KeyValueMap>[] = [];
const idPositionMap: {[index:string]: number} = allItems.reduce((acc: any, el, i) => {
acc[el.sys.id] = i;
return acc;
}, {});
for (const childId of allChildIds) {
if (allItems[idPositionMap[childId]]) {
cfChildren.push(allItems[idPositionMap[childId]]);
}
}
return cfChildren
};
const getContentfulChildEntries = async (
parentId: string
): Promise<Array<EntryProps<KeyValueMap>>> => {
const parentItem = await props.cma.entry.get({ entryId: parentId });
const allChildIds: string[] = [];
for (const key of Object.keys(parentItem.fields)) {
if (props.nodeContentTypes.includes(key)) {
const childNodeRefs = parentItem.fields[key][stLocale] as
| Link<string>
| Array<Link<string>>;
if (Array.isArray(childNodeRefs)) {
for (const childNodeRef of childNodeRefs) {
allChildIds.push(childNodeRef.sys.id);
}
} else {
allChildIds.push(childNodeRefs.sys.id);
}
}
}
const allItems: Array<EntryProps<KeyValueMap>> = [];
let done = false;
let skip = 0;
while (!done) {
const col = await props.cma.entry.getMany({
query: {
'sys.id[in]': allChildIds.join(','),
skip,
},
});
allItems.push(...col.items);
if (allItems.length < col.total) {
skip += 100;
} else {
done = true;
}
}
const cfChildren: Array<EntryProps<KeyValueMap>> = [];
const idPositionMap: { [index: string]: number } = allItems.reduce(
(acc: any, el, i) => {
acc[el.sys.id] = i;
return acc;
},
{}
);
for (const childId of allChildIds) {
if (allItems[idPositionMap[childId]]) {
cfChildren.push(allItems[idPositionMap[childId]]);
}
}
return cfChildren;
};
const cfEntriesToNodes = (entries: EntryProps<KeyValueMap>[], parentId?: string): ContentTreeNodeProps[] => {
if (entries.length === 0) {
return [];
}
const nodeArray: ContentTreeNodeProps[] = [];
entries.forEach((entry) => {
if (!entry) {
console.log('this entry is nil');
return
}
let name = '';
for (const titleField of props.titleFields) {
if (entry.fields[titleField] && entry.fields[titleField][stLocale]) {
name = entry.fields[titleField][stLocale];
break;
}
}
if (name === '') {
name = entry.sys.id;
}
const node: ContentTreeNodeProps = {
id: entry.sys.id,
name: name,
contentType: entry.sys.contentType.sys.id,
icon: props.iconRegistry ? props.iconRegistry[entry.sys.contentType.sys.id]:'',
expand: !parentId,
parentId: parentId!,
hasChildNodes: cfEntryHasChildren(entry),
publishingStatus: cfEntryPublishingStatus(entry),
updatedAt:entry.sys.updatedAt,
publishedAt:entry.sys.publishedAt
};
nodeArray.push(node);
});
return nodeArray;
};
const cfEntryHasChildren = (entry: EntryProps<KeyValueMap>): boolean => {
for (const nodeContentType of props.nodeContentTypes) {
for (const locale of props.locales) {
if (entry.fields[nodeContentType] && entry.fields[nodeContentType][locale]) {
return true
}
}
}
return false;
}
const cfEntriesToNodes = (
entries: Array<EntryProps<KeyValueMap>>,
parentId?: string
): ContentTreeNodeProps[] => {
if (entries.length === 0) {
return [];
}
const nodeArray: ContentTreeNodeProps[] = [];
entries.forEach((entry) => {
if (!entry) {
console.log('this entry is nil');
return;
}
let name = '';
for (const titleField of props.titleFields) {
if (entry.fields[titleField]?.[stLocale]) {
name = entry.fields[titleField][stLocale];
break;
}
}
if (name === '') {
name = entry.sys.id;
}
const node: ContentTreeNodeProps = {
id: entry.sys.id,
name,
contentType: entry.sys.contentType.sys.id,
icon:
props.iconRegistry != null
? props.iconRegistry[entry.sys.contentType.sys.id]
: '',
expand: !!parentId,
parentId,
hasChildNodes: cfEntryHasChildren(entry),
publishingStatus: cfEntryPublishingStatus(entry),
updatedAt: entry.sys.updatedAt,
publishedAt: entry.sys.publishedAt,
};
nodeArray.push(node);
});
return nodeArray;
};
const cfEntryPublishingStatus = (entry: EntryProps<KeyValueMap>): string => {
if (!entry.sys.publishedVersion) {
return 'draft';
}
if (entry.sys.version - entry.sys.publishedVersion == 1) {
return 'published';
}
return 'changed';
}
const loadRootData = async () => {
const CfRootData = await props.cma.entry.getMany({ query: { content_type: props.rootType } });
const rootNodes = cfEntriesToNodes(CfRootData.items);
for (const rootNode of rootNodes) {
const childEntries = await getContentfulChildEntries(rootNode.id)
const childNodes = cfEntriesToNodes(childEntries,rootNode.id)
const nodes = [rootNode,...childNodes]
if (nodes.length > 0) {
const newIdPositionMap = nodes.reduce((acc: any, el, i) => {
acc[el.id] = i;
return acc;
}, {});
let tree: ContentTreeNodeProps = emptyNodeProps();
nodes.forEach((node: ContentTreeNodeProps) => {
node.childNodes = []
if (!node.parentId) {
tree = node;
return;
}
const parentEl = nodes[newIdPositionMap[node.parentId]];
if (parentEl) {
parentEl.childNodes = [...(parentEl.childNodes || []), node];
parentEl.expand = true
}
});
console.log('🌴 tree',tree);
setStRoot(tree)
}
}
};
const removeChildNodes = (node: ContentTreeNodeProps) => {
setStRoot((draft) => {
recursiveProcessNodes(node.id,
(targetNode) => {
targetNode.childNodes = []
targetNode.expand = false
},draft)
console.log('🎈draft',draft)
})
}
const cfEntryHasChildren = (entry: EntryProps<KeyValueMap>): boolean => {
for (const nodeContentType of props.nodeContentTypes) {
for (const locale of props.locales) {
if (entry.fields[nodeContentType]?.[locale]) {
return true;
}
}
}
return false;
};
console.log('=============================== RENDER ====================================', stRoot);
// create ID mapping
return (
<>
<StyledContentTreeTable>
<tbody>
<tr>
<th>Nodes</th>
<th>Content Type</th>
<th>Status</th>
<th>Last Modified</th>
<th>Last Published</th>
</tr>
<ContentTreeNode
node={stRoot}
depth={0}
addChildNodes={addChildNodes}
removeChildNodes={removeChildNodes}
editEntry={editEntry}/>
</tbody>
</StyledContentTreeTable>
</>
);
const cfEntryPublishingStatus = (entry: EntryProps<KeyValueMap>): string => {
if (!entry.sys.publishedVersion) {
return 'draft';
}
if (entry.sys.version - entry.sys.publishedVersion === 1) {
return 'published';
}
return 'changed';
};
const loadRootData = async (): Promise<void> => {
const CfRootData = await props.cma.entry.getMany({
query: { content_type: props.rootType },
});
const rootNodes = cfEntriesToNodes(CfRootData.items);
for (const rootNode of rootNodes) {
const childEntries = await getContentfulChildEntries(rootNode.id);
const childNodes = cfEntriesToNodes(childEntries, rootNode.id);
const nodes = [rootNode, ...childNodes];
if (nodes.length > 0) {
const newIdPositionMap = nodes.reduce((acc: any, el, i) => {
acc[el.id] = i;
return acc;
}, {});
let tree: ContentTreeNodeProps = emptyNodeProps();
nodes.forEach((node: ContentTreeNodeProps) => {
node.childNodes = [];
if (!node.parentId) {
tree = node;
return;
}
const parentEl = nodes[newIdPositionMap[node.parentId]];
if (parentEl) {
parentEl.childNodes = [...(parentEl.childNodes ?? []), node];
parentEl.expand = true;
}
});
console.log('🌴 tree', tree);
setStRoot(tree);
}
}
};
const removeChildNodes = (node: ContentTreeNodeProps): void => {
setStRoot((draft) => {
recursiveProcessNodes(
node.id,
(targetNode) => {
targetNode.childNodes = [];
targetNode.expand = false;
},
draft
);
console.log('🎈draft', draft);
});
};
console.log(
'=============================== RENDER ====================================',
stRoot
);
// create ID mapping
return (
<>
<StyledContentTreeTable>
<tbody>
<tr>
<th>Nodes</th>
<th>Content Type</th>
<th>Status</th>
<th>Last Modified</th>
<th>Last Published</th>
</tr>
<ContentTreeNode
node={stRoot}
depth={0}
addChildNodes={addChildNodes}
removeChildNodes={removeChildNodes}
editEntry={editEntry}
/>
</tbody>
</StyledContentTreeTable>
</>
);
};

View File

@ -1,73 +1,105 @@
import React, { useState } from 'react';
import React, { ReactElement, useState } from 'react';
import {
StyledContentTreeNodeName,
StyledContentTreeNodePublishingStatus,
StyledContentTreeNodeWedge,
StyledContentTreeTableNodeCell,
StyledSpinner,
StyledContentTreeNodeName,
StyledContentTreeNodePublishingStatus,
StyledContentTreeNodeWedge,
StyledContentTreeTableNodeCell,
StyledSpinner,
} from './ContentTree.styled';
import { Icon } from './Icons';
export interface ContentTreeNodeProps {
id: string;
name: string;
contentType: string;
icon: string;
expand: boolean;
parentId: string;
childNodes?: ContentTreeNodeProps[];
hasChildNodes?: boolean;
publishingStatus: string;
updatedAt?: string;
publishedAt?: string;
id: string;
name: string;
contentType?: string;
icon?: string;
expand: boolean;
parentId?: string;
childNodes?: ContentTreeNodeProps[];
hasChildNodes?: boolean;
publishingStatus?: string;
updatedAt?: string;
publishedAt?: string;
}
const ContentTreeNode = (props: {
node: ContentTreeNodeProps;
depth?: number;
addChildNodes: (node: ContentTreeNodeProps) => void;
removeChildNodes: (node: ContentTreeNodeProps) => void;
editEntry: (nodeId:string) => void;
}) => {
const [loading, setLoading] = useState(false);
const [node, setNode] = useState(props.node)
const ContentTreeNode = (props: {
node: ContentTreeNodeProps;
depth?: number;
addChildNodes: (node: ContentTreeNodeProps) => Promise<void>;
removeChildNodes: (node: ContentTreeNodeProps) => void;
editEntry: (nodeId: string) => Promise<void>;
}): ReactElement => {
const [loading, setLoading] = useState(false);
const [node] = useState(props.node);
// React.useEffect(()=>{setLoading(false)},[props.node.childNodes])
// React.useEffect(()=>{setLoading(false)},[props.node.childNodes])
const addChildren = async () => {
setLoading(true);
await props.addChildNodes(node)
setLoading(false);
}
const addChildren = async (): Promise<void> => {
setLoading(true);
await props.addChildNodes(node);
setLoading(false);
};
return (
<>
<tr>
<StyledContentTreeTableNodeCell depth={props.depth}>
<StyledContentTreeNodeWedge>
{loading? (<StyledSpinner>-</StyledSpinner>): props.node.hasChildNodes ? props.node.expand? (
<a onClick={() => props.removeChildNodes(props.node)}>-</a>
) : (
<a onClick={() => addChildren()}>+</a>
): null}
</StyledContentTreeNodeWedge>
<Icon id={props.node.icon}></Icon>
<StyledContentTreeNodeName>
<a onClick={() => props.editEntry(props.node.id)} title={props.node.id}>{props.node.name}</a>
</StyledContentTreeNodeName>
</StyledContentTreeTableNodeCell>
<td>{props.node.contentType}</td>
<td><StyledContentTreeNodePublishingStatus status={props.node.publishingStatus}>{props.node.publishingStatus}</StyledContentTreeNodePublishingStatus></td>
<td>{props.node.updatedAt}</td>
<td>{props.node.publishedAt}</td>
</tr>
{props.node.childNodes?.map((node, i) => {
return <ContentTreeNode key={i} node={node} depth={props.depth! + 1} addChildNodes={props.addChildNodes} removeChildNodes={props.removeChildNodes} editEntry={props.editEntry}/>;
})}
</>
);
const handleEditEntry = (): void => {
props.editEntry(props.node.id).catch((err) => {
throw new Error('handleEditEntry', err);
});
};
const handleAddChildren = (): void => {
addChildren().catch((err) => {
throw new Error('handleAddChildren', err);
});
};
return (
<>
<tr>
<StyledContentTreeTableNodeCell depth={props.depth}>
<StyledContentTreeNodeWedge>
{loading ? (
<StyledSpinner>-</StyledSpinner>
) : props.node.hasChildNodes ? (
props.node.expand ? (
<a onClick={() => props.removeChildNodes(props.node)}>-</a>
) : (
<a onClick={() => handleAddChildren()}>+</a>
)
) : null}
</StyledContentTreeNodeWedge>
<Icon id={props.node.icon}></Icon>
<StyledContentTreeNodeName>
<a onClick={() => handleEditEntry()} title={props.node.id}>
{props.node.name}
</a>
</StyledContentTreeNodeName>
</StyledContentTreeTableNodeCell>
<td>{props.node.contentType}</td>
<td>
<StyledContentTreeNodePublishingStatus
status={props.node.publishingStatus ?? ''}
>
{props.node.publishingStatus}
</StyledContentTreeNodePublishingStatus>
</td>
<td>{props.node.updatedAt}</td>
<td>{props.node.publishedAt}</td>
</tr>
{props.node.childNodes?.map((node, i) => {
return (
<ContentTreeNode
key={i}
node={node}
depth={props.depth && props.depth + 1}
addChildNodes={props.addChildNodes}
removeChildNodes={props.removeChildNodes}
editEntry={props.editEntry}
/>
);
})}
</>
);
};
export default ContentTreeNode;

View File

@ -1,37 +1,135 @@
import React, { FC, MouseEvent, ReactElement, SVGProps } from 'react';
import React, { FC, ReactElement, SVGProps } from 'react';
import styled from 'styled-components';
export type SVGIcon = FC<SVGProps<SVGSVGElement>>;
export interface IconProps {
icon?: SVGIcon;
}
export const Icon = (props: {id?: string}) => {
switch (props.id) {
case 'WORLD':
return <StyledIcon><svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><title>WORLD</title><path d="M113.66,23.69q-.345-.435-.72-.87A63.786,63.786,0,0,0,64.92.02C64.61.01,64.31,0,64,0s-.61.01-.92.02A63.789,63.789,0,0,0,14.93,22.98a6.164,6.164,0,0,0-.47.57.138.138,0,0,1-.03.04,63.8,63.8,0,0,0,0,80.82.138.138,0,0,1,.03.04,6.171,6.171,0,0,0,.47.57l.01.01a63.776,63.776,0,0,0,48.14,22.95c.614.02,1.226.02,1.84,0a63.786,63.786,0,0,0,48.02-22.8q.375-.435.72-.87a63.826,63.826,0,0,0,0-80.62ZM99.49,62.25a106.208,106.208,0,0,0-4.07-28.03,69.57,69.57,0,0,0,16.19-7.51,60.158,60.158,0,0,1,12.86,35.54ZM65.75,3.59c10.69,1.1,19.99,12.14,25.36,28.3a100.612,100.612,0,0,1-25.36,3.58Zm-3.5,31.88a100.612,100.612,0,0,1-25.36-3.58c5.37-16.16,14.67-27.2,25.36-28.3Zm0,3.5V62.25H32.01a104.4,104.4,0,0,1,3.85-27.02A104.159,104.159,0,0,0,62.25,38.97Zm0,26.78V89.03a104.161,104.161,0,0,0-26.39,3.74,104.4,104.4,0,0,1-3.85-27.02Zm0,26.78v31.88c-10.69-1.1-19.99-12.14-25.36-28.3A100.612,100.612,0,0,1,62.25,92.53Zm3.5,0a100.612,100.612,0,0,1,25.36,3.58c-5.37,16.16-14.67,27.2-25.36,28.3Zm0-3.5V65.75H95.99a104.477,104.477,0,0,1-3.85,27.03A103.333,103.333,0,0,0,65.75,89.03Zm0-26.78V38.97a103.33,103.33,0,0,0,26.39-3.75,104.478,104.478,0,0,1,3.85,27.03Zm43.6-38.26A66.171,66.171,0,0,1,94.37,30.9C90.53,19.48,84.76,10.4,77.89,5.11A60.6,60.6,0,0,1,109.35,23.99ZM50.11,5.11C43.24,10.4,37.47,19.48,33.63,30.9A67.031,67.031,0,0,1,18.65,24,60.513,60.513,0,0,1,50.11,5.11ZM16.39,26.7a69.605,69.605,0,0,0,16.19,7.53,106.07,106.07,0,0,0-4.07,28.02H3.53A60.188,60.188,0,0,1,16.39,26.7ZM28.51,65.75a106.069,106.069,0,0,0,4.07,28.02v.01a69.183,69.183,0,0,0-16.19,7.52A60.188,60.188,0,0,1,3.53,65.75ZM18.65,104a67.031,67.031,0,0,1,14.98-6.9c3.84,11.42,9.61,20.5,16.48,25.79A60.514,60.514,0,0,1,18.65,104Zm59.24,18.89c6.87-5.29,12.64-14.37,16.48-25.79a66.169,66.169,0,0,1,14.98,6.91A60.6,60.6,0,0,1,77.89,122.89Zm33.72-21.6a69.573,69.573,0,0,0-16.19-7.51,106.208,106.208,0,0,0,4.07-28.03h24.98A60.158,60.158,0,0,1,111.61,101.29Z"/></svg></StyledIcon>
case 'PAGE':
return <StyledIcon><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><defs></defs><title>Asset 47ldpi</title><g id="Layer_2" data-name="Layer 2"><g id="layer_1-2" data-name="layer 1"><path d="M47,48H1a1,1,0,0,1-1-1V1A1,1,0,0,1,1,0H47a1,1,0,0,1,1,1V47A1,1,0,0,1,47,48ZM2,46H46V2H2Z"/><rect x="34" y="25" width="8" height="2"/><rect x="22" y="25" width="10" height="2"/><rect x="31" y="30" width="7" height="2"/><rect x="22" y="30" width="7" height="2"/><rect x="36" y="35" width="6" height="2"/><rect x="22" y="35" width="12" height="2"/><rect x="22" y="40" width="9" height="2"/><path d="M18,42H7a1,1,0,0,1-1-1V26a1,1,0,0,1,1-1H18a1,1,0,0,1,1,1V41A1,1,0,0,1,18,42ZM8,40h9V27H8Z"/><path d="M41,22H7a1,1,0,0,1-1-1V15a1,1,0,0,1,1-1H41a1,1,0,0,1,1,1v6A1,1,0,0,1,41,22ZM8,20H40V16H8Z"/><rect x="4" y="4" width="2" height="2"/><rect x="8" y="4" width="2" height="2"/><rect x="12" y="4" width="2" height="2"/><rect x="1" y="8" width="46" height="2"/></g></g></svg></StyledIcon>
case 'APP':
return <StyledIcon><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><title>8-Book</title><g id="_8-Book" data-name="8-Book"><path d="M27,23a5,5,0,0,0-3-1H6a5,5,0,0,0-3,1V5A3,3,0,0,1,6,2H18V0H6A5,5,0,0,0,1,5V27a5,5,0,0,0,5,5H28a1,1,0,0,0,1-1V19H27Zm0,7H6a3,3,0,0,1,0-6H24a3,3,0,0,1,2.82,2H10v2H27Z"/><rect x="6" y="26" width="2" height="2"/><path d="M15,7V5H7A1,1,0,0,0,6,6v4a1,1,0,0,0,1,1h8V9H8V7Z"/><rect x="6" y="14" width="2" height="2"/><rect x="10" y="14" width="2" height="2"/><path d="M31,11V9H28.9a5,5,0,0,0-.73-1.75l1.54-1.54L28.29,4.29,26.75,5.83A5,5,0,0,0,25,5.1V3H23V5.1a5,5,0,0,0-1.75.73L19.71,4.29,18.29,5.71l1.54,1.54A5,5,0,0,0,19.1,9H17v2h2.1a5,5,0,0,0,.73,1.75l-1.54,1.54,1.41,1.41,1.54-1.54A5,5,0,0,0,23,14.9V17h2V14.9a5,5,0,0,0,1.75-.73l1.54,1.54,1.41-1.41-1.54-1.54A5,5,0,0,0,28.9,11Zm-7,2a3,3,0,1,1,3-3A3,3,0,0,1,24,13Z"/></g></svg></StyledIcon>
case 'CART':
return <StyledIcon><svg version="1.1" id="shopping_x5F_carts_1_" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 128 128"><g id="_x31__1_"><path d="M92.1 96c-5.2 0-9.3 4.2-9.3 9.3 0 5.2 4.2 9.3 9.3 9.3s9.3-4.2 9.3-9.3c0-5.1-4.1-9.3-9.3-9.3zm0 16a6.7 6.7 0 1 1 6.7-6.7c0 3.8-3 6.7-6.7 6.7zM41.4 96c-5.2 0-9.3 4.2-9.3 9.3 0 5.2 4.2 9.3 9.3 9.3s9.3-4.2 9.3-9.3c0-5.1-4.2-9.3-9.3-9.3zm0 16a6.7 6.7 0 1 1 6.7-6.7c0 3.8-3 6.7-6.7 6.7zm86.2-73.5c-.5-.8-1.3-1.2-2.2-1.2h-102L19 15.4c-.3-1.2-1.3-2.1-2.6-2.1H2.7C1.2 13.3 0 14.5 0 16c0 1.5 1.2 2.7 2.7 2.7h11.4l14.6 72.6c.3 1.2 1.3 2.1 2.6 2.1h72.2c1.1 0 2-.6 2.4-1.6L127.8 41c.3-.8.3-1.7-.2-2.5zM101.7 88H33.5l-2.7-13.3h76.7L101.7 88zm6.9-16H30.3l-2.7-13.3h86.8L108.6 72zm6.9-16H27l-2.7-13.3h96.9L115.5 56z" id="icon_14_"/></g></svg></StyledIcon>
case 'FOLDER':
return <StyledIcon><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><path d="M64 15v37a5.006 5.006 0 0 1-5 5H5a5.006 5.006 0 0 1-5-5V12a5.006 5.006 0 0 1 5-5h14.116a6.966 6.966 0 0 1 5.466 2.627l5 6.247A2.983 2.983 0 0 0 31.922 17H59a1 1 0 0 1 0 2H31.922a4.979 4.979 0 0 1-3.9-1.876l-5-6.247A4.976 4.976 0 0 0 19.116 9H5a3 3 0 0 0-3 3v40a3 3 0 0 0 3 3h54a3 3 0 0 0 3-3V15a3 3 0 0 0-3-3H30a1 1 0 0 1 0-2h29a5.006 5.006 0 0 1 5 5z"/></svg></StyledIcon>
case 'LOVE':
return <StyledIcon><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M22.813 7.338a6.736 6.736 0 0 0-3.8-4.49c-3.206-1.471-6 .878-7.016 1.9-1.013-1.025-3.813-3.374-7.016-1.9a6.736 6.736 0 0 0-3.8 4.49 5.818 5.818 0 0 0 1 4.98c1.708 2.215 9.156 8.891 9.472 9.174a.514.514 0 0 0 .688 0c.316-.283 7.764-6.959 9.472-9.174a5.815 5.815 0 0 0 1-4.98zM21 11.689c-1.448 1.878-7.488 7.362-9 8.726-1.512-1.364-7.552-6.848-9-8.726a4.8 4.8 0 0 1-.812-4.1 5.711 5.711 0 0 1 3.226-3.8c2.229-1.027 4.731.311 6.186 2.05a.516.516 0 0 0 .4.188.516.516 0 0 0 .4-.188c.029-.035 2.958-3.536 6.188-2.055a5.714 5.714 0 0 1 3.226 3.8A4.8 4.8 0 0 1 21 11.689z"/><path d="M6.346 5a4.39 4.39 0 0 0-2.473 2.928 3.818 3.818 0 0 0 .656 3.272.515.515 0 0 0 .816-.629 2.8 2.8 0 0 1-.472-2.392 3.366 3.366 0 0 1 1.9-2.237A.515.515 0 0 0 6.346 5z"/></svg></StyledIcon>
case 'SHORTCUT':
return <StyledIcon><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g data-name="13.Arrow up"><path d="M12 24a12 12 0 1 1 12-12 12.013 12.013 0 0 1-12 12zm0-22a10 10 0 1 0 10 10A10.011 10.011 0 0 0 12 2z"/><path d="M18 12h-2V9h-4V7h6v5z"/><path d="m3.707 17.707-1.414-1.414L6.586 12h5l4.707-4.707 1.414 1.414L12.414 14h-5l-3.707 3.707z"/></g></svg></StyledIcon>
}
return <StyledIcon><svg xmlns="http://www.w3.org/2000/svg" width="20.088" height="20.087"><path d="M10.044 0a10.044 10.044 0 1 0 10.044 10.043A10.043 10.043 0 0 0 10.044 0zm.047 15.033a4.99 4.99 0 1 1 4.99-4.99 4.989 4.989 0 0 1-4.99 4.99z"/></svg></StyledIcon>
icon?: SVGIcon;
}
export const Icon = (props: { id?: string }): ReactElement => {
switch (props.id) {
case 'WORLD':
return (
<StyledIcon>
<svg
id="Layer_1"
data-name="Layer 1"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 128 128"
>
<title>WORLD</title>
<path d="M113.66,23.69q-.345-.435-.72-.87A63.786,63.786,0,0,0,64.92.02C64.61.01,64.31,0,64,0s-.61.01-.92.02A63.789,63.789,0,0,0,14.93,22.98a6.164,6.164,0,0,0-.47.57.138.138,0,0,1-.03.04,63.8,63.8,0,0,0,0,80.82.138.138,0,0,1,.03.04,6.171,6.171,0,0,0,.47.57l.01.01a63.776,63.776,0,0,0,48.14,22.95c.614.02,1.226.02,1.84,0a63.786,63.786,0,0,0,48.02-22.8q.375-.435.72-.87a63.826,63.826,0,0,0,0-80.62ZM99.49,62.25a106.208,106.208,0,0,0-4.07-28.03,69.57,69.57,0,0,0,16.19-7.51,60.158,60.158,0,0,1,12.86,35.54ZM65.75,3.59c10.69,1.1,19.99,12.14,25.36,28.3a100.612,100.612,0,0,1-25.36,3.58Zm-3.5,31.88a100.612,100.612,0,0,1-25.36-3.58c5.37-16.16,14.67-27.2,25.36-28.3Zm0,3.5V62.25H32.01a104.4,104.4,0,0,1,3.85-27.02A104.159,104.159,0,0,0,62.25,38.97Zm0,26.78V89.03a104.161,104.161,0,0,0-26.39,3.74,104.4,104.4,0,0,1-3.85-27.02Zm0,26.78v31.88c-10.69-1.1-19.99-12.14-25.36-28.3A100.612,100.612,0,0,1,62.25,92.53Zm3.5,0a100.612,100.612,0,0,1,25.36,3.58c-5.37,16.16-14.67,27.2-25.36,28.3Zm0-3.5V65.75H95.99a104.477,104.477,0,0,1-3.85,27.03A103.333,103.333,0,0,0,65.75,89.03Zm0-26.78V38.97a103.33,103.33,0,0,0,26.39-3.75,104.478,104.478,0,0,1,3.85,27.03Zm43.6-38.26A66.171,66.171,0,0,1,94.37,30.9C90.53,19.48,84.76,10.4,77.89,5.11A60.6,60.6,0,0,1,109.35,23.99ZM50.11,5.11C43.24,10.4,37.47,19.48,33.63,30.9A67.031,67.031,0,0,1,18.65,24,60.513,60.513,0,0,1,50.11,5.11ZM16.39,26.7a69.605,69.605,0,0,0,16.19,7.53,106.07,106.07,0,0,0-4.07,28.02H3.53A60.188,60.188,0,0,1,16.39,26.7ZM28.51,65.75a106.069,106.069,0,0,0,4.07,28.02v.01a69.183,69.183,0,0,0-16.19,7.52A60.188,60.188,0,0,1,3.53,65.75ZM18.65,104a67.031,67.031,0,0,1,14.98-6.9c3.84,11.42,9.61,20.5,16.48,25.79A60.514,60.514,0,0,1,18.65,104Zm59.24,18.89c6.87-5.29,12.64-14.37,16.48-25.79a66.169,66.169,0,0,1,14.98,6.91A60.6,60.6,0,0,1,77.89,122.89Zm33.72-21.6a69.573,69.573,0,0,0-16.19-7.51,106.208,106.208,0,0,0,4.07-28.03h24.98A60.158,60.158,0,0,1,111.61,101.29Z" />
</svg>
</StyledIcon>
);
case 'PAGE':
return (
<StyledIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
<defs></defs>
<title>Asset 47ldpi</title>
<g id="Layer_2" data-name="Layer 2">
<g id="layer_1-2" data-name="layer 1">
<path d="M47,48H1a1,1,0,0,1-1-1V1A1,1,0,0,1,1,0H47a1,1,0,0,1,1,1V47A1,1,0,0,1,47,48ZM2,46H46V2H2Z" />
<rect x="34" y="25" width="8" height="2" />
<rect x="22" y="25" width="10" height="2" />
<rect x="31" y="30" width="7" height="2" />
<rect x="22" y="30" width="7" height="2" />
<rect x="36" y="35" width="6" height="2" />
<rect x="22" y="35" width="12" height="2" />
<rect x="22" y="40" width="9" height="2" />
<path d="M18,42H7a1,1,0,0,1-1-1V26a1,1,0,0,1,1-1H18a1,1,0,0,1,1,1V41A1,1,0,0,1,18,42ZM8,40h9V27H8Z" />
<path d="M41,22H7a1,1,0,0,1-1-1V15a1,1,0,0,1,1-1H41a1,1,0,0,1,1,1v6A1,1,0,0,1,41,22ZM8,20H40V16H8Z" />
<rect x="4" y="4" width="2" height="2" />
<rect x="8" y="4" width="2" height="2" />
<rect x="12" y="4" width="2" height="2" />
<rect x="1" y="8" width="46" height="2" />
</g>
</g>
</svg>
</StyledIcon>
);
case 'APP':
return (
<StyledIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<title>8-Book</title>
<g id="_8-Book" data-name="8-Book">
<path d="M27,23a5,5,0,0,0-3-1H6a5,5,0,0,0-3,1V5A3,3,0,0,1,6,2H18V0H6A5,5,0,0,0,1,5V27a5,5,0,0,0,5,5H28a1,1,0,0,0,1-1V19H27Zm0,7H6a3,3,0,0,1,0-6H24a3,3,0,0,1,2.82,2H10v2H27Z" />
<rect x="6" y="26" width="2" height="2" />
<path d="M15,7V5H7A1,1,0,0,0,6,6v4a1,1,0,0,0,1,1h8V9H8V7Z" />
<rect x="6" y="14" width="2" height="2" />
<rect x="10" y="14" width="2" height="2" />
<path d="M31,11V9H28.9a5,5,0,0,0-.73-1.75l1.54-1.54L28.29,4.29,26.75,5.83A5,5,0,0,0,25,5.1V3H23V5.1a5,5,0,0,0-1.75.73L19.71,4.29,18.29,5.71l1.54,1.54A5,5,0,0,0,19.1,9H17v2h2.1a5,5,0,0,0,.73,1.75l-1.54,1.54,1.41,1.41,1.54-1.54A5,5,0,0,0,23,14.9V17h2V14.9a5,5,0,0,0,1.75-.73l1.54,1.54,1.41-1.41-1.54-1.54A5,5,0,0,0,28.9,11Zm-7,2a3,3,0,1,1,3-3A3,3,0,0,1,24,13Z" />
</g>
</svg>
</StyledIcon>
);
case 'CART':
return (
<StyledIcon>
<svg
version="1.1"
id="shopping_x5F_carts_1_"
xmlns="http://www.w3.org/2000/svg"
x="0"
y="0"
viewBox="0 0 128 128"
>
<g id="_x31__1_">
<path
d="M92.1 96c-5.2 0-9.3 4.2-9.3 9.3 0 5.2 4.2 9.3 9.3 9.3s9.3-4.2 9.3-9.3c0-5.1-4.1-9.3-9.3-9.3zm0 16a6.7 6.7 0 1 1 6.7-6.7c0 3.8-3 6.7-6.7 6.7zM41.4 96c-5.2 0-9.3 4.2-9.3 9.3 0 5.2 4.2 9.3 9.3 9.3s9.3-4.2 9.3-9.3c0-5.1-4.2-9.3-9.3-9.3zm0 16a6.7 6.7 0 1 1 6.7-6.7c0 3.8-3 6.7-6.7 6.7zm86.2-73.5c-.5-.8-1.3-1.2-2.2-1.2h-102L19 15.4c-.3-1.2-1.3-2.1-2.6-2.1H2.7C1.2 13.3 0 14.5 0 16c0 1.5 1.2 2.7 2.7 2.7h11.4l14.6 72.6c.3 1.2 1.3 2.1 2.6 2.1h72.2c1.1 0 2-.6 2.4-1.6L127.8 41c.3-.8.3-1.7-.2-2.5zM101.7 88H33.5l-2.7-13.3h76.7L101.7 88zm6.9-16H30.3l-2.7-13.3h86.8L108.6 72zm6.9-16H27l-2.7-13.3h96.9L115.5 56z"
id="icon_14_"
/>
</g>
</svg>
</StyledIcon>
);
case 'FOLDER':
return (
<StyledIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<path d="M64 15v37a5.006 5.006 0 0 1-5 5H5a5.006 5.006 0 0 1-5-5V12a5.006 5.006 0 0 1 5-5h14.116a6.966 6.966 0 0 1 5.466 2.627l5 6.247A2.983 2.983 0 0 0 31.922 17H59a1 1 0 0 1 0 2H31.922a4.979 4.979 0 0 1-3.9-1.876l-5-6.247A4.976 4.976 0 0 0 19.116 9H5a3 3 0 0 0-3 3v40a3 3 0 0 0 3 3h54a3 3 0 0 0 3-3V15a3 3 0 0 0-3-3H30a1 1 0 0 1 0-2h29a5.006 5.006 0 0 1 5 5z" />
</svg>
</StyledIcon>
);
case 'LOVE':
return (
<StyledIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M22.813 7.338a6.736 6.736 0 0 0-3.8-4.49c-3.206-1.471-6 .878-7.016 1.9-1.013-1.025-3.813-3.374-7.016-1.9a6.736 6.736 0 0 0-3.8 4.49 5.818 5.818 0 0 0 1 4.98c1.708 2.215 9.156 8.891 9.472 9.174a.514.514 0 0 0 .688 0c.316-.283 7.764-6.959 9.472-9.174a5.815 5.815 0 0 0 1-4.98zM21 11.689c-1.448 1.878-7.488 7.362-9 8.726-1.512-1.364-7.552-6.848-9-8.726a4.8 4.8 0 0 1-.812-4.1 5.711 5.711 0 0 1 3.226-3.8c2.229-1.027 4.731.311 6.186 2.05a.516.516 0 0 0 .4.188.516.516 0 0 0 .4-.188c.029-.035 2.958-3.536 6.188-2.055a5.714 5.714 0 0 1 3.226 3.8A4.8 4.8 0 0 1 21 11.689z" />
<path d="M6.346 5a4.39 4.39 0 0 0-2.473 2.928 3.818 3.818 0 0 0 .656 3.272.515.515 0 0 0 .816-.629 2.8 2.8 0 0 1-.472-2.392 3.366 3.366 0 0 1 1.9-2.237A.515.515 0 0 0 6.346 5z" />
</svg>
</StyledIcon>
);
case 'SHORTCUT':
return (
<StyledIcon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g data-name="13.Arrow up">
<path d="M12 24a12 12 0 1 1 12-12 12.013 12.013 0 0 1-12 12zm0-22a10 10 0 1 0 10 10A10.011 10.011 0 0 0 12 2z" />
<path d="M18 12h-2V9h-4V7h6v5z" />
<path d="m3.707 17.707-1.414-1.414L6.586 12h5l4.707-4.707 1.414 1.414L12.414 14h-5l-3.707 3.707z" />
</g>
</svg>
</StyledIcon>
);
}
return (
<StyledIcon>
<svg xmlns="http://www.w3.org/2000/svg" width="20.088" height="20.087">
<path d="M10.044 0a10.044 10.044 0 1 0 10.044 10.043A10.043 10.043 0 0 0 10.044 0zm.047 15.033a4.99 4.99 0 1 1 4.99-4.99 4.989 4.989 0 0 1-4.99 4.99z" />
</svg>
</StyledIcon>
);
};
export const StyledIcon = styled.span`
line-height: 1px;
position: relative;
display: inline-block;
vertical-align: top;
width: 16px;
height: 16px;
margin: 2px 4px;
line-height: 1px;
position: relative;
display: inline-block;
vertical-align: top;
width: 16px;
height: 16px;
margin: 2px 4px;
`;

View File

@ -1,3 +1,3 @@
export * from "./ContentTree";
export * from "./ContentTree.styled";
export * from "./ContentTreeNode";
export * from './ContentTree';
export * from './ContentTree.styled';
export * from './ContentTreeNode';

815
yarn.lock

File diff suppressed because it is too large Load Diff