commit
3af994fcc4
@ -27,6 +27,7 @@
|
|||||||
"mnemonic-id": "^3.2.7",
|
"mnemonic-id": "^3.2.7",
|
||||||
"moment": "^2.28.0",
|
"moment": "^2.28.0",
|
||||||
"prismjs": "^1.27.0",
|
"prismjs": "^1.27.0",
|
||||||
|
"qrcode.react": "^3.1.0",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-cookie-consent": "^7.2.1",
|
"react-cookie-consent": "^7.2.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
@ -37,6 +38,8 @@
|
|||||||
"react-redux": "^7.2.4",
|
"react-redux": "^7.2.4",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "^5.0.0",
|
"react-scripts": "^5.0.0",
|
||||||
|
"react-share": "^4.4.0",
|
||||||
|
"react-spinners": "^0.13.3",
|
||||||
"reactour": "^1.18.7",
|
"reactour": "^1.18.7",
|
||||||
"redux": "^4.0.5",
|
"redux": "^4.0.5",
|
||||||
"redux-thunk": "^2.3.0",
|
"redux-thunk": "^2.3.0",
|
||||||
|
@ -3,26 +3,32 @@ import PropTypes from "prop-types";
|
|||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { shareProject } from "../../actions/projectActions";
|
import { shareProject } from "../../actions/projectActions";
|
||||||
import { clearMessages } from "../../actions/messageActions";
|
import { clearMessages } from "../../actions/messageActions";
|
||||||
|
import QRCode from 'qrcode.react';
|
||||||
|
import { createId } from "mnemonic-id";
|
||||||
|
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
|
||||||
import Dialog from "../Dialog";
|
import Dialog from "../Dialog";
|
||||||
import Snackbar from "../Snackbar";
|
import Snackbar from "../Snackbar";
|
||||||
|
|
||||||
import { Link } from "react-router-dom";
|
// import { Link } from "react-router-dom";
|
||||||
|
|
||||||
|
import GridLoader from "react-spinners/GridLoader";
|
||||||
|
import { EmailShareButton, FacebookShareButton, TwitterShareButton, WhatsappShareButton} from "react-share";
|
||||||
|
import { EmailIcon, FacebookIcon, TwitterIcon, WhatsappIcon} from "react-share";
|
||||||
import { withStyles } from "@material-ui/core/styles";
|
import { withStyles } from "@material-ui/core/styles";
|
||||||
import IconButton from "@material-ui/core/IconButton";
|
import IconButton from "@material-ui/core/IconButton";
|
||||||
|
import Button from '@material-ui/core/Button';
|
||||||
import Tooltip from "@material-ui/core/Tooltip";
|
import Tooltip from "@material-ui/core/Tooltip";
|
||||||
import Typography from "@material-ui/core/Typography";
|
import Typography from "@material-ui/core/Typography";
|
||||||
|
|
||||||
import { faShareAlt, faCopy } from "@fortawesome/free-solid-svg-icons";
|
import { faShareAlt, faCopy, faDownload } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import * as Blockly from "blockly/core";
|
import * as Blockly from "blockly/core";
|
||||||
|
|
||||||
const styles = (theme) => ({
|
const styles = (theme) => ({
|
||||||
button: {
|
iconButton: {
|
||||||
backgroundColor: theme.palette.primary.main,
|
backgroundColor: theme.palette.primary.main,
|
||||||
color: theme.palette.primary.contrastText,
|
color: theme.palette.primary.contrastText,
|
||||||
width: "40px",
|
width: "40px",
|
||||||
@ -32,6 +38,15 @@ const styles = (theme) => ({
|
|||||||
color: theme.palette.primary.contrastText,
|
color: theme.palette.primary.contrastText,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
button: {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
color: theme.palette.primary.contrastText,
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
color: theme.palette.primary.contrastText,
|
||||||
|
},
|
||||||
|
borderRadius: 20,
|
||||||
|
},
|
||||||
link: {
|
link: {
|
||||||
color: theme.palette.primary.main,
|
color: theme.palette.primary.main,
|
||||||
textDecoration: "none",
|
textDecoration: "none",
|
||||||
@ -55,6 +70,9 @@ class WorkspaceFunc extends Component {
|
|||||||
content: "",
|
content: "",
|
||||||
open: false,
|
open: false,
|
||||||
id: "",
|
id: "",
|
||||||
|
shortLink: "",
|
||||||
|
isFetching: false,
|
||||||
|
loading: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,6 +83,7 @@ class WorkspaceFunc extends Component {
|
|||||||
(!this.props.multiple ||
|
(!this.props.multiple ||
|
||||||
this.props.message.status === this.props.project._id)
|
this.props.message.status === this.props.project._id)
|
||||||
) {
|
) {
|
||||||
|
this.createShortlink(this.props.message.status);
|
||||||
this.setState({
|
this.setState({
|
||||||
share: true,
|
share: true,
|
||||||
open: true,
|
open: true,
|
||||||
@ -112,12 +131,38 @@ class WorkspaceFunc extends Component {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
createShortlink(id) {
|
||||||
|
this.setState({ isFetching: true, loading: true })
|
||||||
|
const requestOptions = {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ "slug": `blockly-${createId(5)}`, "url": `${window.location.origin}/share/${id}` })
|
||||||
|
};
|
||||||
|
fetch('https://www.snsbx.de/api/shorty', requestOptions)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => this.setState({ shortLink: data[0].link, isFetching: false, loading: false }));
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadQRCode = () => {
|
||||||
|
// Generate download with use canvas and stream
|
||||||
|
const canvas = document.getElementById("qr-gen");
|
||||||
|
const pngUrl = canvas
|
||||||
|
.toDataURL("image/png")
|
||||||
|
.replace("image/png", "image/octet-stream");
|
||||||
|
let downloadLink = document.createElement("a");
|
||||||
|
downloadLink.href = pngUrl;
|
||||||
|
downloadLink.download = `${this.state.shortLink}.png`;
|
||||||
|
document.body.appendChild(downloadLink);
|
||||||
|
downloadLink.click();
|
||||||
|
document.body.removeChild(downloadLink);
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div style={this.props.style}>
|
<div style={this.props.style}>
|
||||||
<Tooltip title={Blockly.Msg.tooltip_share_project} arrow>
|
<Tooltip title={Blockly.Msg.tooltip_share_project} arrow>
|
||||||
<IconButton
|
<IconButton
|
||||||
className={`shareBlocks ${this.props.classes.button}`}
|
className={`shareBlocks ${this.props.classes.iconButton}`}
|
||||||
onClick={() => this.shareBlocks()}
|
onClick={() => this.shareBlocks()}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon icon={faShareAlt} size="xs" />
|
<FontAwesomeIcon icon={faShareAlt} size="xs" />
|
||||||
@ -137,72 +182,116 @@ class WorkspaceFunc extends Component {
|
|||||||
onClose={this.toggleDialog}
|
onClose={this.toggleDialog}
|
||||||
onClick={this.toggleDialog}
|
onClick={this.toggleDialog}
|
||||||
button={Blockly.Msg.button_close}
|
button={Blockly.Msg.button_close}
|
||||||
>
|
>
|
||||||
<div style={{ marginTop: "10px" }}>
|
{ this.state.isFetching ? (
|
||||||
<Typography>
|
<div style={{ display: 'flex', justifyContent: 'center'}}>
|
||||||
Über den folgenden Link kannst du dein Programm teilen:
|
<GridLoader color={"#4EAF47"} loading={this.state.loading} size={50} />
|
||||||
</Typography>
|
</div>
|
||||||
<Link
|
|
||||||
to={`/share/${this.state.id}`}
|
|
||||||
onClick={() => this.toggleDialog()}
|
|
||||||
className={this.props.classes.link}
|
|
||||||
>{`${window.location.origin}/share/${this.state.id}`}</Link>
|
|
||||||
<Tooltip
|
|
||||||
title={Blockly.Msg.tooltip_copy_link}
|
|
||||||
arrow
|
|
||||||
style={{ marginRight: "5px" }}
|
|
||||||
>
|
|
||||||
<IconButton
|
|
||||||
onClick={() => {
|
|
||||||
navigator.clipboard.writeText(
|
|
||||||
`${window.location.origin}/share/${this.state.id}`
|
|
||||||
);
|
|
||||||
this.setState({
|
|
||||||
snackbar: true,
|
|
||||||
key: Date.now(),
|
|
||||||
message: Blockly.Msg.messages_copylink_success,
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FontAwesomeIcon icon={faCopy} size="xs" />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
{this.props.project &&
|
|
||||||
this.props.project.shared &&
|
|
||||||
this.props.message.id !== "SHARE_SUCCESS" ? (
|
|
||||||
<Typography
|
|
||||||
variant="body2"
|
|
||||||
style={{ marginTop: "20px" }}
|
|
||||||
>{`Das Projekt wurde bereits geteilt. Der Link ist noch mindestens ${
|
|
||||||
moment(this.props.project.shared).diff(
|
|
||||||
moment().utc(),
|
|
||||||
"days"
|
|
||||||
) === 0
|
|
||||||
? moment(this.props.project.shared).diff(
|
|
||||||
moment().utc(),
|
|
||||||
"hours"
|
|
||||||
) === 0
|
|
||||||
? `${moment(this.props.project.shared).diff(
|
|
||||||
moment().utc(),
|
|
||||||
"minutes"
|
|
||||||
)} Minuten`
|
|
||||||
: `${moment(this.props.project.shared).diff(
|
|
||||||
moment().utc(),
|
|
||||||
"hours"
|
|
||||||
)} Stunden`
|
|
||||||
: `${moment(this.props.project.shared).diff(
|
|
||||||
moment().utc(),
|
|
||||||
"days"
|
|
||||||
)} Tage`
|
|
||||||
} gültig.`}</Typography>
|
|
||||||
) : (
|
) : (
|
||||||
<Typography
|
<div style={{ marginTop: "10px" }}>
|
||||||
variant="body2"
|
<Typography>
|
||||||
style={{ marginTop: "20px" }}
|
Über den folgenden Link kannst du dein Programm teilen:
|
||||||
>{`Der Link ist nun ${process.env.REACT_APP_SHARE_LINK_EXPIRES} Tage gültig.`}</Typography>
|
</Typography>
|
||||||
)}
|
<div style={{ textAlign: "center" }}>
|
||||||
</div>
|
<a
|
||||||
|
href={this.state.shortLink}
|
||||||
|
onClick={() => this.toggleDialog()}
|
||||||
|
className={this.props.classes.link}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>{this.state.shortLink}</a>
|
||||||
|
<Tooltip
|
||||||
|
title={Blockly.Msg.tooltip_copy_link}
|
||||||
|
arrow
|
||||||
|
style={{ marginRight: "5px" }}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(
|
||||||
|
this.state.shortLink
|
||||||
|
);
|
||||||
|
this.setState({
|
||||||
|
snackbar: true,
|
||||||
|
key: Date.now(),
|
||||||
|
message: Blockly.Msg.messages_copylink_success,
|
||||||
|
type: "success",
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faCopy} size="xs" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<div style={{ marginTop: "10px", display: 'flex', justifyContent: 'center' }}>
|
||||||
|
<QRCode
|
||||||
|
id="qr-gen"
|
||||||
|
value={this.state.shortLink}
|
||||||
|
size={256}
|
||||||
|
level={"L"}
|
||||||
|
includeMargin={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'center', marginTop: '20px'}}>
|
||||||
|
<Button className={`download QR Code ${this.props.classes.button}`} onClick={() => this.downloadQRCode()} variant="contained" startIcon={<FontAwesomeIcon icon={faDownload} size="xs" />}>
|
||||||
|
Download QR code
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'center', marginTop: "20px"}}>
|
||||||
|
<FacebookShareButton url={this.state.shortLink} quote={"I created this sketch for my senseBox. Have a look!"} hashtag={"#senseBox"}>
|
||||||
|
<FacebookIcon size={32} round />
|
||||||
|
</FacebookShareButton>
|
||||||
|
<TwitterShareButton url={this.state.shortLink} title={"I created this sketch for my senseBox. Have a look!"} hashtags={["senseBox", "Blockly", "citizenScience"]}>
|
||||||
|
<TwitterIcon size={32} round />
|
||||||
|
</TwitterShareButton>
|
||||||
|
<WhatsappShareButton url={this.state.shortLink} title={"Look at my SenseBox sketch that I created with Blockly!"} separator={": "}>
|
||||||
|
<WhatsappIcon size={32} round />
|
||||||
|
</WhatsappShareButton>
|
||||||
|
<EmailShareButton url={this.state.shortLink} subject={"SenseBox Blockly Sketch"} body={"I created this sketch for my senseBox. Have a look!"} separator={": "}>
|
||||||
|
<EmailIcon size={32} round />
|
||||||
|
</EmailShareButton>
|
||||||
|
</div>
|
||||||
|
{ this.props.project &&
|
||||||
|
this.props.project.shared &&
|
||||||
|
this.props.message.id !== "SHARE_SUCCESS" ? (
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
style={{ marginTop: "20px" }}
|
||||||
|
>
|
||||||
|
{`Das Projekt wurde bereits geteilt. Der Link ist noch mindestens ${
|
||||||
|
moment(this.props.project.shared).diff(
|
||||||
|
moment().utc(),
|
||||||
|
"days"
|
||||||
|
) === 0
|
||||||
|
? moment(this.props.project.shared).diff(
|
||||||
|
moment().utc(),
|
||||||
|
"hours"
|
||||||
|
) === 0
|
||||||
|
? `${moment(this.props.project.shared).diff(
|
||||||
|
moment().utc(),
|
||||||
|
"minutes"
|
||||||
|
)} Minuten`
|
||||||
|
: `${moment(this.props.project.shared).diff(
|
||||||
|
moment().utc(),
|
||||||
|
"hours"
|
||||||
|
)} Stunden`
|
||||||
|
: `${moment(this.props.project.shared).diff(
|
||||||
|
moment().utc(),
|
||||||
|
"days"
|
||||||
|
)} Tage`
|
||||||
|
} gültig.`}
|
||||||
|
</Typography>
|
||||||
|
) : (
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
style={{ marginTop: "20px" }}
|
||||||
|
>
|
||||||
|
{`Der Link ist nun ${process.env.REACT_APP_SHARE_LINK_EXPIRES} Tage gültig.`}
|
||||||
|
</Typography>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user