Skip to content

Commit

Permalink
#3654: add image element to document builder (#3655)
Browse files Browse the repository at this point in the history
  • Loading branch information
twschiller committed Jun 13, 2022
1 parent f32b7c6 commit e97aa1b
Show file tree
Hide file tree
Showing 17 changed files with 255 additions and 34 deletions.
24 changes: 24 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Expand Up @@ -70,6 +70,7 @@
"handlebars": "^4.7.7",
"hex-rgb": "^5.0.0",
"history": "^4.10.1",
"holderjs": "^2.9.9",
"htmlmetaparser": "^2.1.1",
"htmlparser2": "^8.0.0",
"http-status-codes": "^2.1.4",
Expand Down Expand Up @@ -183,6 +184,7 @@
"@types/gapi.client.oauth2": "^2.0.2",
"@types/gapi.client.sheets": "^4.0.20201029",
"@types/google.picker": "0.0.39",
"@types/holderjs": "^2.9.2",
"@types/intro.js": "^3.0.2",
"@types/jest": "^28.1.1",
"@types/jquery": "^3.5.6",
Expand Down
20 changes: 20 additions & 0 deletions src/__mocks__/holderjs.js
@@ -0,0 +1,20 @@
/*
* Copyright (C) 2022 PixieBrix, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

export function run(...args) {
console.debug("holderjs:run", args);
}
10 changes: 1 addition & 9 deletions src/blocks/renderers/propertyTable.tsx
Expand Up @@ -20,6 +20,7 @@ import { Renderer } from "@/types";
import { propertiesToSchema } from "@/validators/generic";
import { BlockArg, BlockOptions, SafeHTML } from "@/core";
import { sortBy, isPlainObject } from "lodash";
import { isValidUrl } from "@/utils";

interface Item {
key: string;
Expand All @@ -30,15 +31,6 @@ interface Item {
children: Item[];
}

function isValidUrl(value: string): boolean {
try {
const url = new URL(value);
return url.protocol === "http:" || url.protocol === "https:";
} catch {
return false;
}
}

function richValue(value: unknown): unknown {
if (typeof value === "string" && isValidUrl(value)) {
return (
Expand Down
3 changes: 3 additions & 0 deletions src/components/documentBuilder/allowedElementTypes.ts
Expand Up @@ -26,6 +26,7 @@ export const ROOT_ELEMENT_TYPES: DocumentElementType[] = [
"header_2",
"header_3",
"text",
"image",
"container",
"card",
"pipeline",
Expand All @@ -49,6 +50,7 @@ const allowedChildTypes: Record<string, DocumentElementType[]> = {
"header_2",
"header_3",
"text",
"image",
"card",
"pipeline",
"button",
Expand All @@ -59,6 +61,7 @@ const allowedChildTypes: Record<string, DocumentElementType[]> = {
"header_2",
"header_3",
"text",
"image",
"container",
"pipeline",
"button",
Expand Down
4 changes: 4 additions & 0 deletions src/components/documentBuilder/createNewElement.ts
Expand Up @@ -35,6 +35,10 @@ export function createNewElement(elementType: DocumentElementType) {
element.config.text = "Paragraph text.";
break;

case "image":
element.config.url = null;
break;

case "container":
element.children = [createNewElement("row")];
break;
Expand Down
1 change: 1 addition & 0 deletions src/components/documentBuilder/documentBuilderTypes.ts
Expand Up @@ -25,6 +25,7 @@ export const DOCUMENT_ELEMENT_TYPES = [
"header_2",
"header_3",
"text",
"image",
"container",
"row",
"column",
Expand Down
9 changes: 8 additions & 1 deletion src/components/documentBuilder/documentTree.tsx
Expand Up @@ -20,7 +20,7 @@ import BlockElement from "@/components/documentBuilder/render/BlockElement";
import { isPipelineExpression } from "@/runtime/mapArgs";
import { UnknownObject } from "@/types";
import { get } from "lodash";
import { Card, Col, Container, Row } from "react-bootstrap";
import { Card, Col, Container, Row, Image } from "react-bootstrap";
import {
BuildDocumentBranch,
DocumentComponent,
Expand Down Expand Up @@ -75,6 +75,13 @@ export function getComponentDefinition(
return { Component: "p", props };
}

case "image": {
const { url, ...props } = config;
props.src = url;
props.height = props.height ?? 50;
return { Component: Image, props };
}

case "container":
case "row":
case "column": {
Expand Down
19 changes: 19 additions & 0 deletions src/components/documentBuilder/edit/getElementEditSchemas.ts
Expand Up @@ -52,6 +52,25 @@ function getElementEditSchemas(
return [textEdit, getClassNameEdit(elementName)];
}

case "image": {
const imageUrl: SchemaFieldProps = {
name: joinName(elementName, "config", "url"),
schema: { type: "string", format: "uri" },
label: "Image URL",
};
const height: SchemaFieldProps = {
name: joinName(elementName, "config", "height"),
schema: { type: ["string", "number"] },
label: "Height",
};
const width: SchemaFieldProps = {
name: joinName(elementName, "config", "width"),
schema: { type: ["string", "number"] },
label: "Width",
};
return [imageUrl, height, width, getClassNameEdit(elementName)];
}

case "card": {
const headingEdit: SchemaFieldProps = {
name: joinName(elementName, "config", "heading"),
Expand Down
1 change: 1 addition & 0 deletions src/components/documentBuilder/elementTypeLabels.ts
Expand Up @@ -26,6 +26,7 @@ const elementTypeLabels: Record<DocumentElementType, string> = {
column: "Column",
card: "Card",
text: "Text",
image: "Image",
button: "Button",
pipeline: "Brick",
list: "List",
Expand Down
Expand Up @@ -4,7 +4,7 @@ exports[`can preview default button 1`] = `
<DocumentFragment>
<div>
<div
class="root inlineWrapper wrapperShiftRight"
class="root inlineWrapper"
>
<button
class="btn btn-primary"
Expand All @@ -20,7 +20,7 @@ exports[`can preview default button 1`] = `
exports[`can preview default card 1`] = `
<DocumentFragment>
<div
class="wrapperShiftRight root"
class="shiftRightWrapper root"
>
<div
class="card"
Expand Down Expand Up @@ -208,7 +208,7 @@ exports[`can preview default container 1`] = `
exports[`can preview default header_1 1`] = `
<DocumentFragment>
<div
class="wrapperShiftRight root"
class="shiftRightWrapper root"
>
<h1>
Header
Expand All @@ -220,7 +220,7 @@ exports[`can preview default header_1 1`] = `
exports[`can preview default header_2 1`] = `
<DocumentFragment>
<div
class="wrapperShiftRight root"
class="shiftRightWrapper root"
>
<h2>
Header
Expand All @@ -232,7 +232,7 @@ exports[`can preview default header_2 1`] = `
exports[`can preview default header_3 1`] = `
<DocumentFragment>
<div
class="wrapperShiftRight root"
class="shiftRightWrapper root"
>
<h3>
Header
Expand All @@ -241,6 +241,22 @@ exports[`can preview default header_3 1`] = `
</DocumentFragment>
`;

exports[`can preview default image 1`] = `
<DocumentFragment>
<div
class="imageWrapper root"
height="50"
width="100"
>
<img
alt="Placeholder"
class=""
src="holder.js/100x50"
/>
</div>
</DocumentFragment>
`;

exports[`can preview default list 1`] = `
<DocumentFragment>
<div
Expand All @@ -257,7 +273,7 @@ exports[`can preview default list 1`] = `
Element key: @element
</div>
<div
class="wrapperShiftRight root"
class="shiftRightWrapper root"
>
<p>
Paragraph text.
Expand All @@ -270,7 +286,7 @@ exports[`can preview default list 1`] = `
exports[`can preview default pipeline 1`] = `
<DocumentFragment>
<div
class="wrapperShiftRight root"
class="shiftRightWrapper root"
>
<h3>
Brick
Expand Down Expand Up @@ -352,7 +368,7 @@ exports[`can preview default row 1`] = `
exports[`can preview default text 1`] = `
<DocumentFragment>
<div
class="wrapperShiftRight root"
class="shiftRightWrapper root"
>
<p>
Paragraph text.
Expand All @@ -364,7 +380,7 @@ exports[`can preview default text 1`] = `
exports[`can preview pipeline element with bricks 1`] = `
<DocumentFragment>
<div
class="wrapperShiftRight root"
class="shiftRightWrapper root"
>
<h3>
Brick
Expand Down
10 changes: 9 additions & 1 deletion src/components/documentBuilder/preview/documentTree.module.scss
Expand Up @@ -41,10 +41,18 @@

.inlineWrapper {
display: inline-block;
position: relative;
}

.wrapperShiftRight {
.shiftRightWrapper {
position: relative;
}

.imageWrapper {
padding: 2px;
display: inline-block;
position: relative;
min-width: 75px; // restrict min width so the popup label doesn't overflow
}

.labelShiftRight {
Expand Down

0 comments on commit e97aa1b

Please sign in to comment.