UNPKG

@pnp/spfx-property-controls

Version:

Reusable property pane controls for SharePoint Framework solutions

183 lines 8.34 kB
import * as React from 'react'; import { Async } from '@fluentui/react/lib/Utilities'; import { PrimaryButton, DefaultButton, IconButton } from '@fluentui/react/lib/Button'; import { Panel, PanelType } from '@fluentui/react/lib/Panel'; import { PropertyFieldCodeEditorLanguages } from './IPropertyFieldCodeEditor'; import { Label } from '@fluentui/react/lib/Label'; import { TextField } from '@fluentui/react/lib/TextField'; import { CodeFormatter } from './CodeFormatter'; import styles from './PropertyFieldCodeEditorHost.module.scss'; import FieldErrorMessage from '../errorMessage/FieldErrorMessage'; import * as telemetry from '../../common/telemetry'; import * as strings from 'PropertyControlStrings'; import AceEditor from 'react-ace'; import 'brace/mode/json'; import 'brace/mode/javascript'; import 'brace/mode/sass'; import 'brace/mode/typescript'; import 'brace/mode/html'; import 'brace/mode/handlebars'; import 'brace/mode/xml'; import 'brace/theme/monokai'; import { setPropertyValue } from '../../helpers/GeneralHelper'; /** * Renders the controls for PropertyFieldCodeEditor component */ export default class PropertyFieldCodeEditorHost extends React.Component { /** * Constructor method */ constructor(props) { super(props); this.cancel = true; telemetry.track('PropertyFieldCodeEditor', { language: props.language, disabled: props.disabled }); this.state = { code: typeof this.props.initialValue !== 'undefined' ? this.props.initialValue : '', loaded: false, openPanel: false, errorMessage: '' }; this.onOpenPanel = this.onOpenPanel.bind(this); this.onClosePanel = this.onClosePanel.bind(this); this.onFormatCode = this.onFormatCode.bind(this); this.onChange = this.onChange.bind(this); this.onSave = this.onSave.bind(this); this.async = new Async(this); } /** * UNSAFE_componentWillUpdate lifecycle hook * * @param nextProps * @param nextState */ UNSAFE_componentWillUpdate(nextProps, nextState) { if (nextProps.initialValue !== this.props.initialValue) { this.setState({ code: typeof nextProps.initialValue !== 'undefined' ? nextProps.initialValue : '' }); } } /** * Open the right Panel */ onOpenPanel() { if (this.props.disabled) { return; } // Store the current code value this.previousValue = this.state.code; this.cancel = true; this.setState({ openPanel: true, loaded: false }); } /** * Close the panel */ onClosePanel() { this.setState((crntState) => { const newState = { openPanel: false, loaded: false }; // Check if the property has to be reset if (this.cancel) { newState.code = this.previousValue; } return newState; }); } /** * Format the code */ onFormatCode() { let formattedCode; const codeFormatter = new CodeFormatter(); switch (this.props.language) { case PropertyFieldCodeEditorLanguages.JSON: { formattedCode = codeFormatter.formatJSON(this.state.code.trim()); break; } case PropertyFieldCodeEditorLanguages.XML: case PropertyFieldCodeEditorLanguages.HTML: { formattedCode = codeFormatter.formatHTML(this.state.code.trim()); break; } case PropertyFieldCodeEditorLanguages.Sass: case PropertyFieldCodeEditorLanguages.css: { formattedCode = codeFormatter.formatCSS(this.state.code.trim()); break; } case PropertyFieldCodeEditorLanguages.JavaScript: case PropertyFieldCodeEditorLanguages.TypeScript: case PropertyFieldCodeEditorLanguages.Handlebars: { formattedCode = codeFormatter.formatScript(this.state.code.trim()); break; } } // const beautify = require('beautify'); // let formattedCode: any = beautify(this.state.code.trim(), { format: codeLanguage }); this.setState({ code: formattedCode }); } /** * Called when the component will unmount */ componentWillUnmount() { if (typeof this.async !== 'undefined') { this.async.dispose(); } } /** * Called when the save button gets clicked */ onSave() { this.cancel = false; setPropertyValue(this.props.properties, this.props.targetProperty, this.state.code); this.props.onPropertyChange(this.props.targetProperty, this.props.initialValue, this.state.code); // Trigger the apply button if (typeof this.props.onChange !== 'undefined' && this.props.onChange !== null) { this.props.onChange(this.props.targetProperty, this.state.code); } this.setState((current) => (Object.assign(Object.assign({}, current), { openPanel: false }))); } /** * Called when the code gets changed */ onChange(newValue) { this.setState((current) => (Object.assign(Object.assign({}, current), { code: newValue }))); } /** * Renders the SPListpicker controls with Office UI Fabric */ render() { return (React.createElement("div", null, this.props.label && React.createElement(Label, null, this.props.label), React.createElement("table", { className: styles.codeFieldTable }, React.createElement("tbody", null, React.createElement("tr", null, React.createElement("td", null, React.createElement(TextField, { disabled: this.props.disabled, readOnly: true, value: this.state.code, onClick: this.onOpenPanel })), React.createElement("td", { className: styles.codeFieldRow }, React.createElement(IconButton, { disabled: this.props.disabled, iconProps: { iconName: 'Code' }, onClick: this.onOpenPanel }))))), React.createElement(FieldErrorMessage, { errorMessage: this.state.errorMessage }), React.createElement(Panel, { isOpen: this.state.openPanel, hasCloseButton: true, onDismiss: this.onClosePanel, isLightDismiss: true, type: this.props.panelWidth ? PanelType.custom : PanelType.medium, customWidth: this.props.panelWidth, headerText: this.props.panelTitle, isFooterAtBottom: true, styles: { content: { height: '100%', width: '100%', boxSizing: 'border-box' } }, layerProps: { eventBubblingEnabled: true }, onRenderFooterContent: () => (React.createElement("div", { className: styles.actions }, React.createElement("div", { className: "ms-Grid", dir: "ltr" }, React.createElement("div", { className: "ms-Grid-row" }, React.createElement(PrimaryButton, { iconProps: { iconName: 'Save' }, text: strings.SaveButtonLabel, value: strings.SaveButtonLabel, onClick: this.onSave }), React.createElement(DefaultButton, { iconProps: { iconName: 'Cancel' }, text: strings.CancelButtonLabel, value: strings.CancelButtonLabel, onClick: this.onClosePanel }), this.props.language !== PropertyFieldCodeEditorLanguages["Plain Text"] && React.createElement(DefaultButton, { color: "ms-bgColor-themeLight", iconProps: { iconName: 'ClearFormatting' }, text: strings.FormatCodeButtonLabel, value: strings.ExportButtonLabel, onClick: this.onFormatCode }))))) }, React.createElement(AceEditor, { mode: this.props.language, theme: "monokai", onChange: this.onChange, value: this.state.code, name: `code-${this.props.targetProperty}`, editorProps: { $blockScrolling: true }, setOptions: this.props.options, width: "100%", height: "100%" })))); } } //# sourceMappingURL=PropertyFieldCodeEditorHost.js.map