Skip to content
This repository was archived by the owner on Dec 13, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/mongo/remoteTextMongo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@ import {Option} from "tsla-util/lib/option"
import {RemoteTextRecord} from "../core/remoteTextRecord"
import {RemoteTextDocument} from "../core/remoteTextValue"

const allowedTags = sanitizeHtml.defaults.allowedTags.filter(e => e !== "iframe")
const allowedTags = sanitizeHtml.defaults.allowedTags.filter(e => e !== "iframe").concat("span")

const allowedAttributes = {
a: ["href", "name", "target", "style"],
img: ["src"],
p: ["style"],
span: ["style"],
div: ["style"]
}

export interface RemoteTextSchema {
namespace: string
Expand Down Expand Up @@ -47,7 +55,8 @@ export class RemoteTextMongo {
$set: {
[`document.${record.id}`]: {
html: sanitizeHtml(record.html, {
allowedTags
allowedTags,
allowedAttributes
})
}
}
Expand Down
84 changes: 31 additions & 53 deletions src/mui/editModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import Button from "@material-ui/core/Button"
import Grid from "@material-ui/core/Grid"
import Modal, {ModalProps} from "@material-ui/core/Modal"
import Paper from "@material-ui/core/Paper"
import {SvgIconProps} from "@material-ui/core/SvgIcon"
import EditIcon from "@material-ui/icons/Edit"
import * as React from "react"
import {RemoteTextRecord} from "../core/remoteTextRecord"
import {RemoteTextNode, RemoteTextValue} from "../core/remoteTextValue"
Expand All @@ -16,12 +14,10 @@ declare module "medium-editor" {
}
}

export interface EditModalProps<T extends RemoteTextNode> {
export interface EditModalProps<T extends RemoteTextNode> extends ModalProps {
t: (document: T) => RemoteTextValue
namespace?: string
modalProps?: Partial<ModalProps>
onModalOpen?: (open: boolean) => any
editIconProps?: SvgIconProps
onSave?: () => any
}

export interface EditModal<T extends RemoteTextNode> extends WithRemoteTextContext<T> {
Expand All @@ -48,19 +44,6 @@ export class EditModal<T extends RemoteTextNode> extends React.Component<EditMod
el = document.createElement("div")
mediumEditor: MediumEditor | null = null

state = {
modalOpen: false
}

changeModalOpen = (modalOpen: boolean) => {
this.setState({modalOpen}, () => {
const {onModalOpen} = this.props
if (onModalOpen != null) {
onModalOpen(this.state.modalOpen)
}
})
}

componentDidMount() {
document.body.appendChild(this.el)
}
Expand All @@ -86,7 +69,10 @@ export class EditModal<T extends RemoteTextNode> extends React.Component<EditMod
id: t(this.remoteTextStore.document).id
})
)
this.changeModalOpen(false)
const {onSave} = this.props
if (onSave != null) {
onSave()
}
}
}
}
Expand All @@ -96,40 +82,32 @@ export class EditModal<T extends RemoteTextNode> extends React.Component<EditMod
}

render() {
const {t, modalProps, editIconProps, onModalOpen, namespace} = this.props
const {modalOpen} = this.state
const closeModal = () => this.changeModalOpen(false)

return <>
<EditIcon style={{cursor: "pointer"}} onClick={() => this.changeModalOpen(true)} {...editIconProps}/>

<Modal
disableAutoFocus
disableEnforceFocus
disableRestoreFocus
open={modalOpen}
onClose={closeModal}
{...modalProps}
>
<Grid container direction="column" wrap="nowrap" component={Paper} style={styles.modalBody}>
<Grid container direction="column" item style={{flex: 1}}>
<MediumEditor
style={{flex: 1}}
ref={this.mediumEditorRef}
text={t(this.remoteTextStore.document).html}
/>
</Grid>
const {t, namespace, onSave, ...rest} = this.props

return <Modal
disableAutoFocus
disableEnforceFocus
disableRestoreFocus
{...rest}
>
<Grid container direction="column" wrap="nowrap" component={Paper} style={styles.modalBody}>
<Grid container direction="column" item style={{flex: 1}}>
<MediumEditor
style={{flex: 1}}
ref={this.mediumEditorRef}
text={t(this.remoteTextStore.document).html}
/>
</Grid>

<Grid item container direction="row" style={{margin: "8px 4px"}} justify="flex-end">
<Button color="primary">
Cancel
</Button>
<Button onClick={this.handleSave} color="primary">
Save
</Button>
</Grid>
<Grid item container direction="row" style={{margin: "8px 4px"}} justify="flex-end">
<Button color="primary">
Cancel
</Button>
<Button onClick={this.handleSave} color="primary">
Save
</Button>
</Grid>
</Modal>
</>
</Grid>
</Modal>
}
}
46 changes: 46 additions & 0 deletions src/mui/editModalButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {SvgIconProps} from "@material-ui/core/SvgIcon"
import EditIcon from "@material-ui/icons/Edit"
import * as React from "react"
import {RemoteTextNode, RemoteTextValue} from "../core/remoteTextValue"
import {WithRemoteTextContext} from "../react/withRemoteText"
import {EditModal, EditModalProps} from "./editModal"

export interface EditModalButtonProps<T extends RemoteTextNode> {
t: (document: T) => RemoteTextValue
namespace?: string
editModalProps?: Partial<EditModalProps<T>>
onModalOpen?: (open: boolean) => any
editIconProps?: SvgIconProps
}

export interface EditModalButton<T extends RemoteTextNode> extends WithRemoteTextContext<T> {

}

export class EditModalButton<T extends RemoteTextNode> extends React.Component<EditModalButtonProps<T>> {
state = {
modalOpen: false
}

changeModalOpen = (modalOpen: boolean) => {
this.setState({modalOpen}, () => {
const {onModalOpen} = this.props
if (onModalOpen != null) {
onModalOpen(this.state.modalOpen)
}
})
}

render() {
const {t, editModalProps, editIconProps, onModalOpen, namespace} = this.props
const {modalOpen} = this.state
const closeModal = () => this.changeModalOpen(false)

return <>
<EditIcon style={{cursor: "pointer"}} onClick={() => this.changeModalOpen(true)} {...editIconProps}/>

<EditModal t={t} open={modalOpen} onClose={closeModal} onSave={closeModal}
namespace={namespace} {...editModalProps}/>
</>
}
}
10 changes: 6 additions & 4 deletions src/mui/editRemoteTextModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import * as React from "react"
import {RemoteTextNode, RemoteTextValue} from "../core/remoteTextValue"
import {RemoteText} from "../react/remoteText"
import {withRemoteText, WithRemoteTextContext} from "../react/withRemoteText"
import {EditModal} from "./editModal"
import {EditModal, EditModalProps} from "./editModal"
import {EditModalButton} from "./editModalButton"

export interface EditRemoteTextModalProps<T extends RemoteTextNode> extends Partial<GridProps> {
t: (document: T) => RemoteTextValue
namespace?: string
children: (value: RemoteTextValue) => React.ReactElement<any>
editIconProps?: SvgIconProps
modalProps?: Partial<ModalProps>
editModalProps?: Partial<EditModalProps<T>>
onModalOpen?: (open: boolean) => any
}

Expand All @@ -29,7 +30,7 @@ export class EditRemoteTextModal<T extends RemoteTextNode> extends React.Compone
changeShowEditIcon = (showEditIcon: boolean) => this.setState({showEditIcon})

render() {
const {t, children, modalProps, onModalOpen, namespace, editIconProps, ...rest} = this.props
const {t, children, editModalProps, onModalOpen, namespace, editIconProps, ...rest} = this.props
const {showEditIcon} = this.state
return <>
<Grid container direction="row" wrap="nowrap" alignItems="center"
Expand All @@ -39,7 +40,8 @@ export class EditRemoteTextModal<T extends RemoteTextNode> extends React.Compone
<RemoteText t={t}>{children}</RemoteText>
</Grid>
<Grid item>
{showEditIcon && <EditModal t={t} modalProps={modalProps} onModalOpen={onModalOpen} namespace={namespace}/>}
{showEditIcon &&
<EditModalButton t={t} editModalProps={editModalProps} onModalOpen={onModalOpen} namespace={namespace}/>}
</Grid>
</Grid>
</>
Expand Down
3 changes: 2 additions & 1 deletion src/react/mediumEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ export class MediumEditor extends React.Component<MediumEditorProps> {
this.medium = new MediumEditorBase(dom, {
paste: {
forcePlainText: false
}
},
targetBlank: true
})
this.medium.subscribe("editableInput", () => {
const {onTextChange} = this.props
Expand Down