diff --git a/lib/editor/widgets/Iframe/index.js b/lib/editor/widgets/Iframe/index.js index 53af98d3a2a5a60cb39b4b179bba20b80924deec..0234d68198f4163df74b1280bfb123138a39e695 100644 --- a/lib/editor/widgets/Iframe/index.js +++ b/lib/editor/widgets/Iframe/index.js @@ -47,6 +47,7 @@ var Iframe = function (_a) { } var manualMaxWidthSet = typeof data.maxWidth !== 'undefined'; + var manualHeightSet = typeof data.height !== 'undefined'; function handleChangeManualMaxWidth(e) { var newValue = e.target.checked; @@ -55,6 +56,7 @@ var Iframe = function (_a) { if (newValue) { update.maxWidth = 200; + delete update.ratio; } else { delete update.maxWidth; } @@ -62,12 +64,69 @@ var Iframe = function (_a) { onChange(update); } + function handleChangeManualHeight(e) { + var newValue = e.target.checked; + + var update = tslib_1.__assign({}, data); + + if (newValue) { + update.height = 200; + delete update.ratio; + } else { + delete update.height; + } + + onChange(update); + } + + var parseIframe = function (e) { + var value = e.target.value; + + if (value.startsWith('<iframe ')) { + var div = document.createElement('div'); + div.innerHTML = value.trim(); + var elements = div.getElementsByTagName('iframe'); + var iframe = Array.from(elements)[0]; + var srcValue = iframe.getAttribute('src'); + var widthValue = iframe.getAttribute('width'); + var heightValue = iframe.getAttribute('height'); + var newData = {}; + + if (srcValue) { + newData.src = srcValue; + } + + if (widthValue && !isNaN(Number(widthValue)) && heightValue && !isNaN(Number(heightValue))) { + newData.ratio = Number(parseFloat(String(Number(widthValue) / Number(heightValue))).toFixed(2)); + delete data.maxWidth; + delete data.height; + } else if (widthValue && !isNaN(Number(widthValue)) && (!heightValue || isNaN(Number(heightValue)))) { + newData.maxWidth = Number(widthValue); + delete data.ratio; + delete data.height; + } else if (height && !isNaN(Number(height)) && (!widthValue || isNaN(Number(widthValue)))) { + newData.height = Number(heightValue); + delete data.ratio; + delete data.maxWidth; + } + + onChange(tslib_1.__assign(tslib_1.__assign({}, data), newData)); + } + }; + var src = data.src || ''; + var ratio = data.ratio; var maxWidth = data.maxWidth; var height = (_b = data.height) !== null && _b !== void 0 ? _b : Iframe_1.DEFAULT_HEIGHT; return React.createElement(React.Fragment, null, React.createElement(Message_1["default"], { warning: true }, "Vsadzovanie obsahu tret\u00EDch str\u00E1n m\u00F4\u017Ee priamo ohrozi\u0165 bezpe\u010Dnos\u0165 v\u00E1\u0161ho webu.", React.createElement("br", null), "Uistite sa, \u017Ee URL je spr\u00E1vna a zobrazuje sa o\u010Dak\u00E1van\u00FD obsah."), React.createElement(FormField_1["default"], { + rows: 4, + placeholder: 'Napr. <iframe width="665" height="500" src="https://www.digisport.sk/wp-content/uploads/2017/10/digitalz_iframe_test_2.html?vimeo_video_id=493667032" />', + onChange: parseIframe, + type: "textarea", + label: "Z\u00EDska\u0165 z iframe tagu" + }), React.createElement(FormField_1["default"], { label: "URL", name: "src", type: "text", @@ -75,11 +134,24 @@ var Iframe = function (_a) { value: src, onChange: handleChangeInputValue, placeholder: "https://" + }), React.createElement(FormField_1["default"], { + onChange: handleChangeManualHeight, + label: "Manu\u00E1lne nastavi\u0165 v\u00FD\u0161ku", + type: "checkbox", + checked: manualHeightSet }), React.createElement(FormField_1["default"], { onChange: handleChangeManualMaxWidth, label: "Manu\u00E1lne nastavi\u0165 maxim\u00E1lnu \u0161\u00EDrku", type: "checkbox", checked: manualMaxWidthSet + }), !manualHeightSet && !manualMaxWidthSet && React.createElement(FormField_1["default"], { + label: "Pomer str\u00E1n", + name: "ratio", + type: "number", + required: true, + value: ratio, + onChange: handleChangeInputValue, + placeholder: "\u0160\u00EDrka/v\u00FD\u0161ka, napr. 1.33" }), manualMaxWidthSet && React.createElement(FormGroup_1["default"], null, React.createElement(Label_1["default"], null, "Maxim\u00E1lna \u0161\u00EDrka v pixeloch"), React.createElement(InputRange, { type: "range", min: 1, @@ -92,7 +164,7 @@ var Iframe = function (_a) { value: maxWidth, name: "maxWidth", onChange: handleChangeNumberInputValue - })), React.createElement(FormGroup_1["default"], null, React.createElement(Label_1["default"], { + })), manualHeightSet && React.createElement(FormGroup_1["default"], null, React.createElement(Label_1["default"], { required: true }, "V\u00FD\u0161ka v pixeloch"), React.createElement(InputRange, { type: "range", diff --git a/lib/editor/widgets/Table/RichTextEditor/Link.js b/lib/editor/widgets/Table/RichTextEditor/Link.js index 64c85a9f3a980f50ed467440e12deedfafb7c97c..69f8f1a73d3d29ad6fec673e2c500c258d13ce77 100644 --- a/lib/editor/widgets/Table/RichTextEditor/Link.js +++ b/lib/editor/widgets/Table/RichTextEditor/Link.js @@ -5,10 +5,10 @@ exports.findLinkEntities = void 0; var tslib_1 = require("tslib"); -var react_1 = tslib_1.__importDefault(require("react")); - var prop_types_1 = tslib_1.__importDefault(require("prop-types")); +var react_1 = tslib_1.__importDefault(require("react")); + function findLinkEntities(contentBlock, callback, contentState) { contentBlock.findEntityRanges(function (character) { var entityKey = character.getEntity(); diff --git a/lib/editor/widgets/Table/Spreadsheet/Table/Cell.js b/lib/editor/widgets/Table/Spreadsheet/Table/Cell.js index 60e26566f866e41e3c13108044c07c4a13c0e47a..5ce9a186919125d3f0c0a9232f1f785ee242aa72 100644 --- a/lib/editor/widgets/Table/Spreadsheet/Table/Cell.js +++ b/lib/editor/widgets/Table/Spreadsheet/Table/Cell.js @@ -16,6 +16,8 @@ var react_1 = tslib_1.__importStar(require("react")); var styled_components_1 = tslib_1.__importStar(require("styled-components")); +var Link_1 = tslib_1.__importStar(require("../../RichTextEditor/Link")); + var elements_1 = require("./elements"); var HANDLED = 'handled'; @@ -110,12 +112,17 @@ function (_super) { var _a = this.props, __editorState = _a.value.__editorState, active = _a.active; + var decorator = new draft_js_1.CompositeDecorator([{ + strategy: Link_1.findLinkEntities, + component: Link_1["default"] + }]); + var editorState = draft_js_1.EditorState.createWithContent(__editorState.getCurrentContent(), decorator); return react_1["default"].createElement(Wrapper, { onClick: this.focus, active: active }, react_1["default"].createElement(draft_js_1.Editor, { onFocus: this.handleFocus, - editorState: __editorState, + editorState: editorState, handleKeyCommand: this._handleKeyCommand, blockStyleFn: this.blockStyleFn, onChange: this.handleChange, diff --git a/lib/editor/widgets/Table/Spreadsheet/Toolbar.js b/lib/editor/widgets/Table/Spreadsheet/Toolbar.js index 3d7e0a7e1ef8500f9716e1e5f8990f8481285ee2..3914dd80707b7b34f6dba6a4c0b41980383d5990 100644 --- a/lib/editor/widgets/Table/Spreadsheet/Toolbar.js +++ b/lib/editor/widgets/Table/Spreadsheet/Toolbar.js @@ -14,6 +14,10 @@ var BlockAlignTool_1 = tslib_1.__importDefault(require("../RichTextEditor/tools/ var InlineStyleTool_1 = tslib_1.__importDefault(require("../RichTextEditor/tools/InlineStyleTool")); +var LinkRemovalTool_1 = tslib_1.__importDefault(require("../RichTextEditor/tools/LinkRemovalTool")); + +var LinkTool_1 = tslib_1.__importDefault(require("../RichTextEditor/tools/LinkTool")); + var styles_1 = require("../RichTextEditor/tools/styles"); var TableHeaderTool_1 = tslib_1.__importDefault(require("./tools/TableHeaderTool")); @@ -64,6 +68,12 @@ function (_super) { editorState: editorState, icon: "strikethrough", type: "STRIKETHROUGH" + })), react_1["default"].createElement(styles_1.ToolGroup, null, react_1["default"].createElement(LinkTool_1["default"], { + onToggle: onAction, + editorState: editorState + }), react_1["default"].createElement(LinkRemovalTool_1["default"], { + onToggle: onAction, + editorState: editorState })), react_1["default"].createElement(styles_1.ToolGroup, null, react_1["default"].createElement(BlockAlignTool_1["default"], { onToggle: onAction, editorState: editorState, diff --git a/lib/editor/widgets/Table/Spreadsheet/index.js b/lib/editor/widgets/Table/Spreadsheet/index.js index 6a3df4bd683412bf0772aa53e5aa5d94f058d945..487cb657d7da54946caa8c7a3cc33386acf7708f 100644 --- a/lib/editor/widgets/Table/Spreadsheet/index.js +++ b/lib/editor/widgets/Table/Spreadsheet/index.js @@ -15,15 +15,19 @@ var action_1 = tslib_1.__importDefault(require("../RichTextEditor/tools/BlockAli var action_2 = tslib_1.__importDefault(require("../RichTextEditor/tools/InlineStyleTool/action")); +var action_3 = tslib_1.__importDefault(require("../RichTextEditor/tools/LinkRemovalTool/action")); + +var action_4 = tslib_1.__importDefault(require("../RichTextEditor/tools/LinkTool/action")); + var Table_1 = tslib_1.__importDefault(require("./Table")); var Toolbar_1 = tslib_1.__importDefault(require("./Toolbar")); -var action_3 = tslib_1.__importDefault(require("./tools/HeaderOptionsTool/action")); +var action_5 = tslib_1.__importDefault(require("./tools/HeaderOptionsTool/action")); -var action_4 = tslib_1.__importDefault(require("./tools/TableHeaderTool/action")); +var action_6 = tslib_1.__importDefault(require("./tools/TableHeaderTool/action")); -var action_5 = tslib_1.__importDefault(require("./tools/TableSizeTool/action")); +var action_7 = tslib_1.__importDefault(require("./tools/TableSizeTool/action")); var utilities_1 = require("./utilities"); @@ -51,7 +55,7 @@ function (_super) { table: [], selectedCell: [] }; - _this.actionHandlers = [action_1["default"], action_2["default"]]; + _this.actionHandlers = [action_1["default"], action_2["default"], action_3["default"], action_4["default"]]; _this.handleFocusCell = function (selectedCell) { _this.setState({ @@ -71,7 +75,7 @@ function (_super) { var selectedCellEditorState = table[rowIdx].cells[colIdx].__editorState; if (action.type === 'TABLE_SIZE') { - var _c = action_5["default"]({ + var _c = action_7["default"]({ table: table, selectedCell: selectedCell }, action, { @@ -88,7 +92,7 @@ function (_super) { _this.propagateTableChange(_this.state.table); }); } else if (action.type === 'TABLE_STRUCTURE') { - var _d = action_3["default"]({ + var _d = action_5["default"]({ table: table, selectedCell: selectedCell }, action, { @@ -105,7 +109,7 @@ function (_super) { _this.propagateTableChange(_this.state.table); }); } else if (action.type === 'TABLE_HEADER') { - onChangeHeader(action_4["default"](header, action)); + onChangeHeader(action_6["default"](header, action)); } else { _this.handleChangeCell(selectedCell, _this.actionHandlers.reduce(function (editorState, actionHandler) { return actionHandler(editorState, action); diff --git a/lib/editor/widgets/Table/Spreadsheet/utilities.js b/lib/editor/widgets/Table/Spreadsheet/utilities.js index 4ba1d03046757139213f1fde8c1b9de4b1aa74cc..78bdf2f3a7fd71585d31a8e4c8a54fc3b627fc85 100644 --- a/lib/editor/widgets/Table/Spreadsheet/utilities.js +++ b/lib/editor/widgets/Table/Spreadsheet/utilities.js @@ -49,6 +49,20 @@ function contentStateToHtml(contentState) { } return undefined; + }, + entityStyleFn: function (entity) { + var entityType = entity.get('type').toLowerCase(); + + if (entityType === 'link') { + var data = entity.getData(); + return { + element: 'a', + attributes: { + target: data.openInNewWindow ? '_blank' : '', + href: data.url + } + }; + } } }); } diff --git a/lib/view/widgets/Iframe/index.js b/lib/view/widgets/Iframe/index.js index e6302e9fbe142beacd37de59e9e06d2f1823a992..104b1677bb5c7a36fc091a45d5643a2a40dfd681 100644 --- a/lib/view/widgets/Iframe/index.js +++ b/lib/view/widgets/Iframe/index.js @@ -5,6 +5,8 @@ exports.DEFAULT_HEIGHT = void 0; var tslib_1 = require("tslib"); +var polished_1 = require("polished"); + var react_1 = tslib_1.__importDefault(require("react")); var styled_components_1 = tslib_1.__importStar(require("../../../theme/styled-components")); @@ -12,14 +14,14 @@ var styled_components_1 = tslib_1.__importStar(require("../../../theme/styled-co var _utilities_1 = require("../../../utilities"); exports.DEFAULT_HEIGHT = 200; -var Wrapper = styled_components_1["default"].div(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n display: flex;\n"], ["\n display: flex;\n"]))); -var IframeElement = styled_components_1["default"].iframe(templateObject_4 || (templateObject_4 = tslib_1.__makeTemplateObject(["\n margin: 0 auto;\n padding: 0;\n width: 100%;\n border: none;\n background: transparent;\n font-weight: inherit;\n font-style: inherit;\n font-size: 100%;\n font-family: inherit;\n vertical-align: baseline;\n ", "\n ", "\n"], ["\n margin: 0 auto;\n padding: 0;\n width: 100%;\n border: none;\n background: transparent;\n font-weight: inherit;\n font-style: inherit;\n font-size: 100%;\n font-family: inherit;\n vertical-align: baseline;\n ", "\n ", "\n"])), function (_a) { - var maxWidth = _a.maxWidth; - return maxWidth && styled_components_1.css(templateObject_2 || (templateObject_2 = tslib_1.__makeTemplateObject(["\n max-width: ", "px;\n "], ["\n max-width: ", "px;\n "])), maxWidth); -}, function (_a) { - var height = _a.height; - return styled_components_1.css(templateObject_3 || (templateObject_3 = tslib_1.__makeTemplateObject(["\n height: ", "px;\n "], ["\n height: ", "px;\n "])), height); +var Wrapper = styled_components_1["default"]('div')(templateObject_3 || (templateObject_3 = tslib_1.__makeTemplateObject(["\n position: relative;\n display: flex;\n width: 100%;\n ", "\n"], ["\n position: relative;\n display: flex;\n width: 100%;\n ", "\n"])), function (_a) { + var hasRatio = _a.hasRatio, + width = _a.width, + height = _a.height; + return hasRatio ? styled_components_1.css(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n padding-top: ", "%;\n "], ["\n padding-top: ", "%;\n "])), 100 / (width / height)) : styled_components_1.css(templateObject_2 || (templateObject_2 = tslib_1.__makeTemplateObject(["\n height: ", ";\n max-width: ", ";\n "], ["\n height: ", ";\n max-width: ", ";\n "])), polished_1.rem(height), width ? polished_1.rem(width) : '100%'); }); +var Content = styled_components_1["default"].div(templateObject_4 || (templateObject_4 = tslib_1.__makeTemplateObject(["\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n"], ["\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n"]))); +var IframeElement = styled_components_1["default"].iframe(templateObject_5 || (templateObject_5 = tslib_1.__makeTemplateObject(["\n margin: 0 auto;\n height: 100%;\n padding: 0;\n width: 100%;\n border: none;\n background: transparent;\n font-weight: inherit;\n font-style: inherit;\n font-size: 100%;\n font-family: inherit;\n vertical-align: baseline;\n"], ["\n margin: 0 auto;\n height: 100%;\n padding: 0;\n width: 100%;\n border: none;\n background: transparent;\n font-weight: inherit;\n font-style: inherit;\n font-size: 100%;\n font-family: inherit;\n vertical-align: baseline;\n"]))); var Iframe = function (_a) { var _b; @@ -32,18 +34,12 @@ var Iframe = function (_a) { return null; } - var _d = _utilities_1.useDimensions({ - liveMeasure: true - }), - ref = _d[0], - width = _d[1].width; - - var _e = react_1["default"].useState({ + var _d = react_1["default"].useState({ height: data.height || exports.DEFAULT_HEIGHT, src: '' }), - newIframeSize = _e[0], - setNewIframeSize = _e[1]; + newIframeSize = _d[0], + setNewIframeSize = _d[1]; var locationSearch = ((_b = window === null || window === void 0 ? void 0 : window.location) === null || _b === void 0 ? void 0 : _b.search) || ''; var src = (data.src || '').replace(/{{location\.search}}/g, locationSearch).replace(/{{location\.query}}/g, locationSearch ? locationSearch.substring(1) : ''); @@ -58,14 +54,6 @@ var Iframe = function (_a) { return ''; } }, [src]); - react_1["default"].useEffect(function () { - if (data.ratio) { - setNewIframeSize({ - height: width / data.ratio, - src: newIframeSize.src - }); - } - }, [data.ratio, width]); react_1["default"].useEffect(function () { if (!src) { return; @@ -96,13 +84,13 @@ var Iframe = function (_a) { } return react_1["default"].createElement(Wrapper, { - ref: ref - }, react_1["default"].createElement(IframeElement, { - src: src, - maxWidth: data.maxWidth || undefined, - height: newIframeSize.height - })); + height: data.ratio ? 100 / data.ratio : newIframeSize.height, + width: data.ratio ? 100 : data.maxWidth, + hasRatio: !!data.ratio + }, react_1["default"].createElement(Content, null, react_1["default"].createElement(IframeElement, { + src: src + }))); }; exports["default"] = Iframe; -var templateObject_1, templateObject_2, templateObject_3, templateObject_4; \ No newline at end of file +var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5; \ No newline at end of file diff --git a/package.json b/package.json index 023533f1b20978f5be2d67d640cead3e41132ceb..3f3676ef2014e2bae8bead7d6b56c3f72cd62b22 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "content", - "version": "0.2.45", + "version": "0.2.46", "description": "", "main": "lib/view/index.js", "scripts": { diff --git a/src/editor/widgets/Iframe/index.tsx b/src/editor/widgets/Iframe/index.tsx index d3eaa6dbb8773f781b76540449945cb044af69a4..6e73ac62534d436ed49564931d4cb2b362791746 100644 --- a/src/editor/widgets/Iframe/index.tsx +++ b/src/editor/widgets/Iframe/index.tsx @@ -42,19 +42,90 @@ const Iframe: React.FC<IOwnProps> = ({ data = {} as IData, onChange }) => { } const manualMaxWidthSet = typeof data.maxWidth !== 'undefined'; + const manualHeightSet = typeof data.height !== 'undefined'; function handleChangeManualMaxWidth(e: React.ChangeEvent<HTMLInputElement>) { const newValue = e.target.checked; const update: IData = { ...data }; if (newValue) { update.maxWidth = 200; + delete update.ratio; } else { delete update.maxWidth; } onChange(update); } + function handleChangeManualHeight(e: React.ChangeEvent<HTMLInputElement>) { + const newValue = e.target.checked; + const update: IData = { ...data }; + if (newValue) { + update.height = 200; + delete update.ratio; + } else { + delete update.height; + } + onChange(update); + } + + const parseIframe = (e: React.ChangeEvent<HTMLTextAreaElement>) => { + const value: string = e.target.value; + if (value.startsWith('<iframe ')) { + const div = document.createElement('div'); + div.innerHTML = value.trim(); + const elements = div.getElementsByTagName('iframe'); + const iframe = Array.from(elements)[0]; + const srcValue = iframe.getAttribute('src'); + const widthValue = iframe.getAttribute('width'); + const heightValue = iframe.getAttribute('height'); + const newData: { + src?: string; + maxWidth?: number; + height?: number; + ratio?: number; + } = {}; + if (srcValue) { + newData.src = srcValue; + } + if ( + widthValue && + !isNaN(Number(widthValue)) && + heightValue && + !isNaN(Number(heightValue)) + ) { + newData.ratio = Number( + parseFloat(String(Number(widthValue) / Number(heightValue))).toFixed( + 2, + ), + ); + delete data.maxWidth; + delete data.height; + } else if ( + widthValue && + !isNaN(Number(widthValue)) && + (!heightValue || isNaN(Number(heightValue))) + ) { + newData.maxWidth = Number(widthValue); + delete data.ratio; + delete data.height; + } else if ( + height && + !isNaN(Number(height)) && + (!widthValue || isNaN(Number(widthValue))) + ) { + newData.height = Number(heightValue); + delete data.ratio; + delete data.maxWidth; + } + onChange({ + ...data, + ...newData, + }); + } + }; + const src = data.src || ''; + const ratio = data.ratio; const maxWidth = data.maxWidth; const height = data.height ?? DEFAULT_HEIGHT; @@ -66,6 +137,13 @@ const Iframe: React.FC<IOwnProps> = ({ data = {} as IData, onChange }) => { <br /> Uistite sa, že URL je správna a zobrazuje sa oÄakávaný obsah. </Message> + <FormField + rows={4} + placeholder='Napr. <iframe width="665" height="500" src="https://www.digisport.sk/wp-content/uploads/2017/10/digitalz_iframe_test_2.html?vimeo_video_id=493667032" />' + onChange={parseIframe} + type="textarea" + label="ZÃskaÅ¥ z iframe tagu" + /> <FormField label="URL" name="src" @@ -75,12 +153,29 @@ const Iframe: React.FC<IOwnProps> = ({ data = {} as IData, onChange }) => { onChange={handleChangeInputValue} placeholder="https://" /> + <FormField + onChange={handleChangeManualHeight} + label="Manuálne nastaviÅ¥ výšku" + type="checkbox" + checked={manualHeightSet} + /> <FormField onChange={handleChangeManualMaxWidth} label="Manuálne nastaviÅ¥ maximálnu Å¡Ãrku" type="checkbox" checked={manualMaxWidthSet} /> + {!manualHeightSet && !manualMaxWidthSet && ( + <FormField + label="Pomer strán" + name="ratio" + type="number" + required + value={ratio} + onChange={handleChangeInputValue} + placeholder="Å Ãrka/výška, napr. 1.33" + /> + )} {manualMaxWidthSet && ( <FormGroup> <Label>Maximálna Å¡Ãrka v pixeloch</Label> @@ -100,24 +195,26 @@ const Iframe: React.FC<IOwnProps> = ({ data = {} as IData, onChange }) => { /> </FormGroup> )} - <FormGroup> - <Label required>Výška v pixeloch</Label> - <InputRange - type="range" - min={1} - max={5000} - value={height === '' ? DEFAULT_HEIGHT : height} - name="height" - onChange={handleChangeNumberInputValue} - /> - <input - type="number" - value={height} - name="height" - placeholder={String(DEFAULT_HEIGHT)} - onChange={handleChangeNumberInputValue} - /> - </FormGroup> + {manualHeightSet && ( + <FormGroup> + <Label required>Výška v pixeloch</Label> + <InputRange + type="range" + min={1} + max={5000} + value={height === '' ? DEFAULT_HEIGHT : height} + name="height" + onChange={handleChangeNumberInputValue} + /> + <input + type="number" + value={height} + name="height" + placeholder={String(DEFAULT_HEIGHT)} + onChange={handleChangeNumberInputValue} + /> + </FormGroup> + )} </> ); }; diff --git a/src/editor/widgets/Table/RichTextEditor/Link.js b/src/editor/widgets/Table/RichTextEditor/Link.js index 6e2db8bdfac46fe584facbc9a78f65beb67ffbe2..58655c019a9f6883b5f2f50d5b6c136b0f4faad5 100644 --- a/src/editor/widgets/Table/RichTextEditor/Link.js +++ b/src/editor/widgets/Table/RichTextEditor/Link.js @@ -1,5 +1,5 @@ -import React from 'react'; import PropTypes from 'prop-types'; +import React from 'react'; export function findLinkEntities(contentBlock, callback, contentState) { contentBlock.findEntityRanges(character => { diff --git a/src/editor/widgets/Table/Spreadsheet/Table/Cell.js b/src/editor/widgets/Table/Spreadsheet/Table/Cell.js index 173d37a9694c2ead6e76b27b10b78e4ecd5027c2..bc57d6650cb5f9591689b9cf0a2091b4b84687af 100644 --- a/src/editor/widgets/Table/Spreadsheet/Table/Cell.js +++ b/src/editor/widgets/Table/Spreadsheet/Table/Cell.js @@ -1,9 +1,10 @@ -import { Editor, RichUtils } from 'draft-js'; +import { CompositeDecorator, Editor, EditorState, RichUtils } from 'draft-js'; import isSoftNewlineEvent from 'draft-js/lib/isSoftNewlineEvent'; import { rem } from 'polished'; import PropTypes from 'prop-types'; import React, { Component } from 'react'; import styled, { css } from 'styled-components'; +import Link, { findLinkEntities } from '../../RichTextEditor/Link'; import { DataCell } from './elements'; const HANDLED = 'handled'; @@ -107,11 +108,24 @@ class Cell extends Component { value: { __editorState }, active, } = this.props; + + const decorator = new CompositeDecorator([ + { + strategy: findLinkEntities, + component: Link, + }, + ]); + + const editorState = EditorState.createWithContent( + __editorState.getCurrentContent(), + decorator, + ); + return ( <Wrapper onClick={this.focus} active={active}> <Editor onFocus={this.handleFocus} - editorState={__editorState} + editorState={editorState} handleKeyCommand={this._handleKeyCommand} blockStyleFn={this.blockStyleFn} onChange={this.handleChange} diff --git a/src/editor/widgets/Table/Spreadsheet/Toolbar.js b/src/editor/widgets/Table/Spreadsheet/Toolbar.js index 0ca081d7602533b47c2502ffce6321fa42c9a58d..6ce3dd2b77e986a9d80ac8ac2b02fac21104b282 100644 --- a/src/editor/widgets/Table/Spreadsheet/Toolbar.js +++ b/src/editor/widgets/Table/Spreadsheet/Toolbar.js @@ -3,6 +3,8 @@ import React, { Component } from 'react'; import styled from 'styled-components'; import BlockAlignTool from '../RichTextEditor/tools/BlockAlignTool'; import InlineStyleTool from '../RichTextEditor/tools/InlineStyleTool'; +import LinkRemovalTool from '../RichTextEditor/tools/LinkRemovalTool'; +import LinkTool from '../RichTextEditor/tools/LinkTool'; import { ToolGroup } from '../RichTextEditor/tools/styles'; import TableHeaderTool from './tools/TableHeaderTool'; import TableSizeTool from './tools/TableSizeTool'; @@ -57,6 +59,11 @@ class Toolbar extends Component { /> </ToolGroup> + <ToolGroup> + <LinkTool onToggle={onAction} editorState={editorState} /> + <LinkRemovalTool onToggle={onAction} editorState={editorState} /> + </ToolGroup> + <ToolGroup> <BlockAlignTool onToggle={onAction} diff --git a/src/editor/widgets/Table/Spreadsheet/index.js b/src/editor/widgets/Table/Spreadsheet/index.js index b81daa18ae97e759fcc25e9c38360730feeb0b0e..1bb0c1027e2b7e3bad07e68ea2a12232ecd386e8 100644 --- a/src/editor/widgets/Table/Spreadsheet/index.js +++ b/src/editor/widgets/Table/Spreadsheet/index.js @@ -3,6 +3,8 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import blockAlignToolAction from '../RichTextEditor/tools/BlockAlignTool/action'; import inlineStyleToolAction from '../RichTextEditor/tools/InlineStyleTool/action'; +import linkRemovalToolAction from '../RichTextEditor/tools/LinkRemovalTool/action'; +import linkToolAction from '../RichTextEditor/tools/LinkTool/action'; import Table from './Table'; import Toolbar from './Toolbar'; import tableStructureReducer from './tools/HeaderOptionsTool/action'; @@ -31,7 +33,12 @@ class Spreadsheet extends Component { table: [], selectedCell: [], }; - actionHandlers = [blockAlignToolAction, inlineStyleToolAction]; + actionHandlers = [ + blockAlignToolAction, + inlineStyleToolAction, + linkRemovalToolAction, + linkToolAction, + ]; componentDidMount() { const originalTable = this.getTableFromProps(this.props); diff --git a/src/editor/widgets/Table/Spreadsheet/utilities.js b/src/editor/widgets/Table/Spreadsheet/utilities.js index f0a359662349a7d3db1d8a18dd829f67000a8907..7b23cfcaf5a70d3ebfbf0c6dd3af41f288d50e0f 100644 --- a/src/editor/widgets/Table/Spreadsheet/utilities.js +++ b/src/editor/widgets/Table/Spreadsheet/utilities.js @@ -34,6 +34,19 @@ export function contentStateToHtml(contentState) { } return undefined; }, + entityStyleFn: entity => { + const entityType = entity.get('type').toLowerCase(); + if (entityType === 'link') { + const data = entity.getData(); + return { + element: 'a', + attributes: { + target: data.openInNewWindow ? '_blank' : '', + href: data.url, + }, + }; + } + }, }); } diff --git a/src/fixtures/content.fixture.ts b/src/fixtures/content.fixture.ts index e02c56938eb5e2153c8fdc66e6b7eab5e267a500..a82d81b8863ad979e2b4ecc0e58c59717c789492 100644 --- a/src/fixtures/content.fixture.ts +++ b/src/fixtures/content.fixture.ts @@ -65,11 +65,16 @@ export const competitionStanding: IContent = [ export const iframeContent: IContent = [ { type: 'iframe', - // height: 589, - ratio: 1.33, src: 'https://www.digisport.sk/wp-content/uploads/2017/10/digitalz_iframe_test_2.html?vimeo_video_id=493667032', - // maxWidth: 200, + height: 500, + maxWidth: 665, + }, + { + type: 'iframe', + src: + 'https://www.ta3.com/embed/20210108-hw-d346260f-9865-4bbd-b5bf-d8403acb7f8b.html', + ratio: 1.78, }, ]; @@ -222,9 +227,9 @@ export const tableContent: IContent = [ '<p style="text-align: center"><strong>DEJISKO</strong></p>', ], [ - '<p>1. roÄnÃk</p>', - '<p>1969/1970</p>', - '<p>Slovan Bratislava</p>', + '<p><a href="https://google.sk">1. roÄnÃk</a></p>', + '<p><a target="_blank" href="https://google.uk">1969/1970</a></p>', + '<p><a target="" href="https://google.de">Slovan Bratislava</a></p>', '<p>Dukla Banská Bystrica</p>', '<p>2:2, 1:0</p>', '', @@ -1387,7 +1392,7 @@ const onlajnyFixtures: IContent = [ ]; export const realContent: IContent = [ - ...onlajnyFixtures, + // ...onlajnyFixtures, // ...socialContent, // ...textBlockContent, // ...textContent, diff --git a/src/view/widgets/Iframe/index.tsx b/src/view/widgets/Iframe/index.tsx index f8eb6f84ec606d85c16e373636e5f7eeb422abc6..0c643723e847f7fd3446f0e124a3144f3e6a7479 100644 --- a/src/view/widgets/Iframe/index.tsx +++ b/src/view/widgets/Iframe/index.tsx @@ -1,16 +1,41 @@ +import { rem } from 'polished'; import React from 'react'; import { IWidgetIframe } from '~library'; import styled, { css } from '~theme/styled-components'; -import { isBrowser, useDimensions } from '~utilities'; +import { isBrowser } from '~utilities'; export const DEFAULT_HEIGHT = 200; -const Wrapper = styled.div` +const Wrapper = styled('div')<{ + hasRatio: boolean; + width: number; + height: number; +}>` + position: relative; display: flex; + width: 100%; + ${({ hasRatio, width, height }) => + hasRatio + ? css` + padding-top: ${100 / (width / height)}%; + ` + : css` + height: ${rem(height)}; + max-width: ${width ? rem(width) : '100%'}; + `} +`; + +const Content = styled.div` + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; `; -const IframeElement = styled.iframe<{ maxWidth?: number; height: number }>` +const IframeElement = styled.iframe` margin: 0 auto; + height: 100%; padding: 0; width: 100%; border: none; @@ -20,14 +45,6 @@ const IframeElement = styled.iframe<{ maxWidth?: number; height: number }>` font-size: 100%; font-family: inherit; vertical-align: baseline; - ${({ maxWidth }) => - maxWidth && - css` - max-width: ${maxWidth}px; - `} - ${({ height }) => css` - height: ${height}px; - `} `; type IData = Omit<IWidgetIframe, 'type'>; @@ -49,8 +66,6 @@ const Iframe: React.FC<IProps> = ({ data = {} as IData, renderEmpty }) => { return null; } - const [ref, { width }] = useDimensions({ liveMeasure: true }); - const [newIframeSize, setNewIframeSize] = React.useState<INewIframeSize>({ height: data.height || DEFAULT_HEIGHT, src: '', @@ -75,12 +90,6 @@ const Iframe: React.FC<IProps> = ({ data = {} as IData, renderEmpty }) => { } }, [src]); - React.useEffect(() => { - if (data.ratio) { - setNewIframeSize({ height: width / data.ratio, src: newIframeSize.src }); - } - }, [data.ratio, width]); - React.useEffect(() => { if (!src) { return; @@ -112,12 +121,14 @@ const Iframe: React.FC<IProps> = ({ data = {} as IData, renderEmpty }) => { } return ( - <Wrapper ref={ref}> - <IframeElement - src={src} - maxWidth={data.maxWidth || undefined} - height={newIframeSize.height} - /> + <Wrapper + height={data.ratio ? 100 / data.ratio : newIframeSize.height} + width={data.ratio ? 100 : data.maxWidth} + hasRatio={!!data.ratio} + > + <Content> + <IframeElement src={src} /> + </Content> </Wrapper> ); };