Merge pull request #183 from sensebox/qr-code-shorty

Qr code shorty
This commit is contained in:
Mario Pesch 2022-09-22 16:54:07 +02:00 committed by GitHub
commit 3af994fcc4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 161 additions and 69 deletions

View File

@ -27,6 +27,7 @@
"mnemonic-id": "^3.2.7",
"moment": "^2.28.0",
"prismjs": "^1.27.0",
"qrcode.react": "^3.1.0",
"react": "^17.0.2",
"react-cookie-consent": "^7.2.1",
"react-dom": "^17.0.2",
@ -37,6 +38,8 @@
"react-redux": "^7.2.4",
"react-router-dom": "^5.2.0",
"react-scripts": "^5.0.0",
"react-share": "^4.4.0",
"react-spinners": "^0.13.3",
"reactour": "^1.18.7",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",

View File

@ -3,26 +3,32 @@ import PropTypes from "prop-types";
import { connect } from "react-redux";
import { shareProject } from "../../actions/projectActions";
import { clearMessages } from "../../actions/messageActions";
import QRCode from 'qrcode.react';
import { createId } from "mnemonic-id";
import moment from "moment";
import Dialog from "../Dialog";
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 IconButton from "@material-ui/core/IconButton";
import Button from '@material-ui/core/Button';
import Tooltip from "@material-ui/core/Tooltip";
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 * as Blockly from "blockly/core";
const styles = (theme) => ({
button: {
iconButton: {
backgroundColor: theme.palette.primary.main,
color: theme.palette.primary.contrastText,
width: "40px",
@ -32,6 +38,15 @@ const styles = (theme) => ({
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: {
color: theme.palette.primary.main,
textDecoration: "none",
@ -55,6 +70,9 @@ class WorkspaceFunc extends Component {
content: "",
open: false,
id: "",
shortLink: "",
isFetching: false,
loading: false,
};
}
@ -65,6 +83,7 @@ class WorkspaceFunc extends Component {
(!this.props.multiple ||
this.props.message.status === this.props.project._id)
) {
this.createShortlink(this.props.message.status);
this.setState({
share: 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() {
return (
<div style={this.props.style}>
<Tooltip title={Blockly.Msg.tooltip_share_project} arrow>
<IconButton
className={`shareBlocks ${this.props.classes.button}`}
className={`shareBlocks ${this.props.classes.iconButton}`}
onClick={() => this.shareBlocks()}
>
<FontAwesomeIcon icon={faShareAlt} size="xs" />
@ -137,72 +182,116 @@ class WorkspaceFunc extends Component {
onClose={this.toggleDialog}
onClick={this.toggleDialog}
button={Blockly.Msg.button_close}
>
<div style={{ marginTop: "10px" }}>
<Typography>
Über den folgenden Link kannst du dein Programm teilen:
</Typography>
<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>
>
{ this.state.isFetching ? (
<div style={{ display: 'flex', justifyContent: 'center'}}>
<GridLoader color={"#4EAF47"} loading={this.state.loading} size={50} />
</div>
) : (
<Typography
variant="body2"
style={{ marginTop: "20px" }}
>{`Der Link ist nun ${process.env.REACT_APP_SHARE_LINK_EXPIRES} Tage gültig.`}</Typography>
)}
</div>
<div style={{ marginTop: "10px" }}>
<Typography>
Über den folgenden Link kannst du dein Programm teilen:
</Typography>
<div style={{ textAlign: "center" }}>
<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>
</div>
);