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" /> | ||||||
| @ -138,15 +183,23 @@ class WorkspaceFunc extends Component { | |||||||
|           onClick={this.toggleDialog} |           onClick={this.toggleDialog} | ||||||
|           button={Blockly.Msg.button_close} |           button={Blockly.Msg.button_close} | ||||||
|         >             |         >             | ||||||
|  |           { this.state.isFetching ? ( | ||||||
|  |             <div style={{ display: 'flex', justifyContent: 'center'}}> | ||||||
|  |               <GridLoader color={"#4EAF47"} loading={this.state.loading} size={50} />  | ||||||
|  |             </div> | ||||||
|  |             ) : ( | ||||||
|               <div style={{ marginTop: "10px" }}> |               <div style={{ marginTop: "10px" }}> | ||||||
|                 <Typography> |                 <Typography> | ||||||
|                   Über den folgenden Link kannst du dein Programm teilen: |                   Über den folgenden Link kannst du dein Programm teilen: | ||||||
|                 </Typography> |                 </Typography> | ||||||
|             <Link |                 <div style={{ textAlign: "center" }}> | ||||||
|               to={`/share/${this.state.id}`} |                   <a | ||||||
|  |                     href={this.state.shortLink} | ||||||
|                     onClick={() => this.toggleDialog()} |                     onClick={() => this.toggleDialog()} | ||||||
|                     className={this.props.classes.link} |                     className={this.props.classes.link} | ||||||
|             >{`${window.location.origin}/share/${this.state.id}`}</Link> |                     target="_blank" | ||||||
|  |                     rel="noreferrer" | ||||||
|  |                   >{this.state.shortLink}</a> | ||||||
|                   <Tooltip |                   <Tooltip | ||||||
|                   title={Blockly.Msg.tooltip_copy_link} |                   title={Blockly.Msg.tooltip_copy_link} | ||||||
|                   arrow |                   arrow | ||||||
| @ -155,7 +208,7 @@ class WorkspaceFunc extends Component { | |||||||
|                     <IconButton |                     <IconButton | ||||||
|                       onClick={() => { |                       onClick={() => { | ||||||
|                         navigator.clipboard.writeText( |                         navigator.clipboard.writeText( | ||||||
|                     `${window.location.origin}/share/${this.state.id}` |                           this.state.shortLink | ||||||
|                         ); |                         ); | ||||||
|                         this.setState({ |                         this.setState({ | ||||||
|                           snackbar: true, |                           snackbar: true, | ||||||
| @ -168,13 +221,43 @@ class WorkspaceFunc extends Component { | |||||||
|                       <FontAwesomeIcon icon={faCopy} size="xs" /> |                       <FontAwesomeIcon icon={faCopy} size="xs" /> | ||||||
|                     </IconButton> |                     </IconButton> | ||||||
|                   </Tooltip> |                   </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 && | ||||||
|                   this.props.project.shared && |                   this.props.project.shared && | ||||||
|                   this.props.message.id !== "SHARE_SUCCESS" ? ( |                   this.props.message.id !== "SHARE_SUCCESS" ? ( | ||||||
|                   <Typography |                   <Typography | ||||||
|                     variant="body2" |                     variant="body2" | ||||||
|                     style={{ marginTop: "20px" }} |                     style={{ marginTop: "20px" }} | ||||||
|               >{`Das Projekt wurde bereits geteilt. Der Link ist noch mindestens ${ |                   > | ||||||
|  |                     {`Das Projekt wurde bereits geteilt. Der Link ist noch mindestens ${ | ||||||
|                       moment(this.props.project.shared).diff( |                       moment(this.props.project.shared).diff( | ||||||
|                         moment().utc(), |                         moment().utc(), | ||||||
|                         "days" |                         "days" | ||||||
| @ -195,14 +278,20 @@ class WorkspaceFunc extends Component { | |||||||
|                           moment().utc(), |                           moment().utc(), | ||||||
|                           "days" |                           "days" | ||||||
|                         )} Tage` |                         )} Tage` | ||||||
|               } gültig.`}</Typography>
 |                     } gültig.`}
 | ||||||
|  |                   </Typography> | ||||||
|                   ) : ( |                   ) : ( | ||||||
|                     <Typography |                     <Typography | ||||||
|                       variant="body2" |                       variant="body2" | ||||||
|                       style={{ marginTop: "20px" }} |                       style={{ marginTop: "20px" }} | ||||||
|               >{`Der Link ist nun ${process.env.REACT_APP_SHARE_LINK_EXPIRES} Tage gültig.`}</Typography> |                     > | ||||||
|             )} |                       {`Der Link ist nun ${process.env.REACT_APP_SHARE_LINK_EXPIRES} Tage gültig.`} | ||||||
|  |                     </Typography> | ||||||
|  |                   ) | ||||||
|  |                 } | ||||||
|               </div>  |               </div>  | ||||||
|  |             ) | ||||||
|  |           } | ||||||
|         </Dialog> |         </Dialog> | ||||||
|       </div> |       </div> | ||||||
|     ); |     ); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user