diff --git a/src/components/IFrameWidget/editor.tsx b/src/components/IFrameWidget/editor.tsx new file mode 100644 index 00000000..21f7fc2a --- /dev/null +++ b/src/components/IFrameWidget/editor.tsx @@ -0,0 +1,203 @@ +import React, { Component } from 'react'; +import styled from 'styled-components'; +import { FirebaseDatabaseMutation } from '@react-firebase/database' +import { + TextField, + Button, + Typography, +} from '@material-ui/core'; +import type { IFrameWidgetProps } from './types'; + +type Props = { + id: string; + props: IFrameWidgetProps; +}; + +const FormGroup = styled.div` + display: flex; + margin-bottom: 1rem; + min-width: 480px; + & > div { + flex-grow: 1; + margin-left: 0.25rem; + } +` +class IFrameWidgetEditor extends Component { + constructor(props) { + super(props); + this.state = this.props.props; + } + + render() { + return ( +
+ + IFrameWidget : {this.props.id} + + + { + this.setState({ ...this.state, url: e.target.value }); + }} + value={this.state.url} + /> + { + this.setState({ ...this.state, retry_time: parseFloat(e.target.value) }); + }} + /> + { + this.setState({ ...this.state, retry_count: parseInt(e.target.value) }); + }} + /> + + + { + this.setState({ ...this.state, width: parseFloat(e.target.value) }); + }} + value={this.state.width} + /> + { + this.setState({ ...this.state, height: parseFloat(e.target.value) }); + }} + value={this.state.height} + /> + + + { + const pos = this.state.position || {}; + if (e.target.value !== "") { + const v = parseInt(e.target.value); + if (isNaN(v)) { + delete pos.top; + } else { + pos.top = v; + } + } else { + delete pos.top; + } + this.setState({ ...this.state, position: pos }); + }} + value={this.state?.position?.top} + /> + { + const pos = this.state.position || {}; + if (e.target.value !== "") { + const v = parseInt(e.target.value); + if (isNaN(v)) { + delete pos.right; + } else { + pos.right = v; + } + } else { + delete pos.right; + } + this.setState({ ...this.state, position: pos }); + }} + value={this.state.position?.right} + /> + { + const pos = this.state.position || {}; + if (e.target.value !== "") { + const v = parseInt(e.target.value); + if (isNaN(v)) { + delete pos.bottom; + } else { + pos.bottom = v; + } + } else { + delete pos.bottom; + } + this.setState({ ...this.state, position: pos }); + }} + value={this.state.position?.bottom} + /> + { + const pos = this.state.position || {}; + if (e.target.value !== "") { + const v = parseInt(e.target.value); + if (isNaN(v)) { + delete pos.left; + } else { + pos.left = v; + } + } else { + delete pos.left; + } + this.setState({ ...this.state, position: pos }); + }} + value={this.state.position?.left} + /> + + + + {({ runMutation }) => { + return ( + + + + ); + }} + +
+ ); + } +} + +export { IFrameWidgetEditor }; diff --git a/src/components/IFrameWidget/index.tsx b/src/components/IFrameWidget/index.tsx new file mode 100644 index 00000000..6eaec3cd --- /dev/null +++ b/src/components/IFrameWidget/index.tsx @@ -0,0 +1,2 @@ +export { IFrameWidget } from './widget'; +export { IFrameWidgetEditor } from './editor'; diff --git a/src/components/IFrameWidget/types.ts b/src/components/IFrameWidget/types.ts new file mode 100644 index 00000000..ed549b17 --- /dev/null +++ b/src/components/IFrameWidget/types.ts @@ -0,0 +1,17 @@ +type Position = { + top?: number; // px + right?: number; // px + bottom?: number; // px + left?: number; // px +}; + +type IFrameWidgetProps = { + url: string; + retry_time: number; + retry_count: number; + width: number; + height: number; + position?: Position; +} + +export type { Position, IFrameWidgetProps }; diff --git a/src/components/IFrameWidget/widget.tsx b/src/components/IFrameWidget/widget.tsx new file mode 100644 index 00000000..71333525 --- /dev/null +++ b/src/components/IFrameWidget/widget.tsx @@ -0,0 +1,43 @@ +import React, { VFC, useState, CSSProperties } from 'react'; +import styled from 'styled-components'; +import type { IFrameWidgetProps } from './types'; + +const IFrameWidget: VFC = ({ url, retry_time, retry_count, width, height, position }) => { + const [count, setCount] = useState(0); + + const handleLoaded = () => { + console.log(`iframe: ${url} loaded`); + }; + + const handleError = (e) => { + console.warn(`iframe: ${url}`, e); + if (count < retry_count) { + setTimeout(() => { + setCount(count + 1); + }, retry_time * 1000); + } + }; + + const style: CSSProperties = { + position: 'absolute', + }; + + if (position?.top !== undefined) style.top = position.top; + if (position?.right !== undefined) style.right = position.right; + if (position?.bottom !== undefined) style.bottom = position.bottom; + if (position?.left !== undefined) style.left = position.left; + + return ( +