UNPKG

terriajs

Version:

Geospatial data visualization platform.

157 lines 6.47 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { lazy, Component, Suspense } from "react"; import PropTypes from "prop-types"; import classNames from "classnames"; import Styles from "./story-editor.scss"; import { withTranslation } from "react-i18next"; import tinymce from "tinymce"; import Text from "../../Styled/Text"; import Box from "../../Styled/Box"; import Button from "../../Styled/Button"; // Lazy load the Editor component as the tinyMCE library is large const Editor = lazy(() => import("../Generic/Editor.tsx")); class StoryEditor extends Component { constructor(props) { super(props); this.state = { title: "", text: "", id: undefined, inView: false }; this.keys = { ctrl: false, enter: false }; this.saveStory = this.saveStory.bind(this); this.cancelEditing = this.cancelEditing.bind(this); this.updateTitle = this.updateTitle.bind(this); this.onKeyDown = this.onKeyDown.bind(this); this.onKeyUp = this.onKeyUp.bind(this); this.slideInTimer = null; this.slideOutTimer = null; this.escKeyListener = null; } UNSAFE_componentWillMount() { const story = this.props.story; this.setState({ title: story.title, text: story.text, id: story.id }); } componentDidMount() { this.slideIn(); } slideIn() { this.slideInTimer = setTimeout(() => { this.setState({ inView: true }); this.titleInput.focus(); }, 300); } slideOut() { this.slideOutTimer = this.setState({ inView: false }); setTimeout(() => { this.cancelEditing(); }, 300); } componentWillUnmount() { clearTimeout(this.slideInTimer); if (this.slideOutTimer) { clearTimeout(this.slideOutTimer); } this.setState({ title: "", text: "", id: undefined }); } updateTitle(event) { this.setState({ title: event.target.value }); } saveStory() { this.props.saveStory({ title: this.state.title, text: this.state.text, id: this.state.id }); this.setState({ isPopupEditorOpen: false }); } cancelEditing() { this.props.exitEditingMode(); this.setState({ title: this.props.story.title, text: this.props.story.text }); } onKeyDown(event) { if (event.keyCode === 27) { this.cancelEditing(); } if (event.keyCode === 13) { this.keys.enter = true; } if (event.keyCode === 17) { this.keys.ctrl = true; } } onKeyUp(event) { if ((event.keyCode === 13 || event.keyCode === 17) && this.keys.enter && this.keys.ctrl) { this.saveStory(); } if (event.keyCode === 13) { this.keys.enter = false; } if (event.keyCode === 17) { this.keys.ctrl = false; } } handleChange(value) { this.setState({ text: value }); } removeStory() { this.props.exitEditingMode(); if (this.state.id) { this.props.removeStory(this.state.id); } } render() { const { t } = this.props; const maxImageHeight = "350px"; // TODO: where to put this to reduce coupling? return (_jsx("div", { onKeyDown: this.onKeyDown, onKeyUp: this.onKeyUp, className: classNames(Styles.popupEditor, { [Styles.isMounted]: this.state.inView }), children: _jsxs("div", { className: Styles.inner, children: [_jsx("div", { className: Styles.header, children: _jsx(Text, { textLight: true, as: "h3", css: { margin: "0" }, children: t("story.editor.modalHeader") }) }), _jsx("label", { htmlFor: "title", children: _jsx(Text, { small: true, textGreyLighter: true, css: { marginBottom: "8px" }, children: t("story.editor.titleLabel") }) }), _jsx("input", { ref: (titleInput) => (this.titleInput = titleInput), placeholder: t("story.editor.placeholder"), autoComplete: "off", className: Styles.field, type: "text", id: "title", value: this.state.title, onChange: this.updateTitle }), _jsxs("div", { className: Styles.body, children: [_jsx(Text, { small: true, textGreyLighter: true, css: { marginBottom: "8px" }, children: t("story.editor.descriptionLabel") }), _jsx(Suspense, { fallback: _jsx("div", { children: "Loading..." }), children: _jsx(Editor, { language: this.props.i18n.language, html: this.state.text, onChange: (_newValue, editor) => { // TODO: This makes StoryEditor tightly coupled to Editor. How to reduce coupling? tinymce.activeEditor.dom.setStyles(tinymce.activeEditor.dom.select("img"), { "max-height": `${maxImageHeight}`, width: "auto" }); const text = editor.getBody().innerHTML; this.setState({ text }); } }) })] }), _jsxs(Box, { centered: true, gap: 3, children: [_jsx(Button, { styledWidth: "240px", transparentBg: true, onClick: this.cancelEditing, type: "button", title: t("story.editor.cancelBtn"), textProps: { textGreyLighter: true, medium: true }, children: t("story.editor.cancelEditing") }), _jsx(Button, { styledWidth: "240px", primary: true, disabled: !this.state.title.length, onClick: this.saveStory, type: "button", title: t("story.editor.saveBtn"), textProps: { medium: true }, children: t("story.editor.saveStory") })] })] }) })); } } StoryEditor.propTypes = { story: PropTypes.object, removeStory: PropTypes.func, saveStory: PropTypes.func, exitEditingMode: PropTypes.func, t: PropTypes.func.isRequired, i18n: PropTypes.object, terria: PropTypes.object }; StoryEditor.defaultProps = { story: { title: "", text: "", id: undefined } }; export default withTranslation()(StoryEditor); //# sourceMappingURL=StoryEditor.js.map