[New Feature] Add othe social network sharing buttons
This commit is contained in:
@@ -53,6 +53,7 @@
|
|||||||
"react-router-dom": "^4.1.1",
|
"react-router-dom": "^4.1.1",
|
||||||
"react-router-redux": "^5.0.0-alpha.6",
|
"react-router-redux": "^5.0.0-alpha.6",
|
||||||
"react-scripts-ts": "2.13.0",
|
"react-scripts-ts": "2.13.0",
|
||||||
|
"react-share": "^2.0.0",
|
||||||
"react-string-replace": "^0.4.0",
|
"react-string-replace": "^0.4.0",
|
||||||
"react-tap-event-plugin": "^3.0.2",
|
"react-tap-event-plugin": "^3.0.2",
|
||||||
"redux": "^3.7.2",
|
"redux": "^3.7.2",
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
|||||||
import { Card, CardActions, CardHeader, CardMedia, CardContent } from 'material-ui'
|
import { Card, CardActions, CardHeader, CardMedia, CardContent } from 'material-ui'
|
||||||
import Typography from 'material-ui/Typography'
|
import Typography from 'material-ui/Typography'
|
||||||
import SvgShare from 'material-ui-icons/Share'
|
import SvgShare from 'material-ui-icons/Share'
|
||||||
import SvgLink from 'material-ui-icons/Link'
|
|
||||||
import SvgComment from 'material-ui-icons/Comment'
|
import SvgComment from 'material-ui-icons/Comment'
|
||||||
import SvgFavorite from 'material-ui-icons/Favorite'
|
import SvgFavorite from 'material-ui-icons/Favorite'
|
||||||
import SvgFavoriteBorder from 'material-ui-icons/FavoriteBorder'
|
import SvgFavoriteBorder from 'material-ui-icons/FavoriteBorder'
|
||||||
@@ -39,6 +38,7 @@ import reactStringReplace from 'react-string-replace'
|
|||||||
|
|
||||||
// - Import app components
|
// - Import app components
|
||||||
import CommentGroup from 'components/commentGroup'
|
import CommentGroup from 'components/commentGroup'
|
||||||
|
import ShareDialog from 'components/shareDialog'
|
||||||
import PostWrite from 'components/postWrite'
|
import PostWrite from 'components/postWrite'
|
||||||
import Img from 'components/img'
|
import Img from 'components/img'
|
||||||
import IconButtonElement from 'layouts/IconButtonElement'
|
import IconButtonElement from 'layouts/IconButtonElement'
|
||||||
@@ -80,18 +80,6 @@ const styles = (theme: any) => ({
|
|||||||
pointerEvents: 'none',
|
pointerEvents: 'none',
|
||||||
zIndex: 0
|
zIndex: 0
|
||||||
},
|
},
|
||||||
shareLinkPaper: {
|
|
||||||
minHeight: 80,
|
|
||||||
padding: 10,
|
|
||||||
minWidth: 460
|
|
||||||
},
|
|
||||||
clipboard: {
|
|
||||||
fontSize: '18px',
|
|
||||||
textAlign: 'center',
|
|
||||||
marginTop: '10px',
|
|
||||||
color: '#1e882d',
|
|
||||||
fontWeight: 400
|
|
||||||
},
|
|
||||||
postBody: {
|
postBody: {
|
||||||
wordWrap: 'break-word',
|
wordWrap: 'break-word',
|
||||||
color: 'rgba(0, 0, 0, 0.87)',
|
color: 'rgba(0, 0, 0, 0.87)',
|
||||||
@@ -103,6 +91,14 @@ const styles = (theme: any) => ({
|
|||||||
image: {
|
image: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: 500
|
height: 500
|
||||||
|
},
|
||||||
|
fullPageXs: {
|
||||||
|
[theme.breakpoints.down('xs')]: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
margin: 0,
|
||||||
|
overflowY: 'auto'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -450,30 +446,14 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
|
|||||||
|
|
||||||
<CommentGroup open={this.state.openComments} comments={commentList} ownerPostUserId={post.ownerUserId!} onToggleRequest={this.handleOpenComments} isPostOwner={this.props.isPostOwner!} disableComments={post.disableComments!} postId={post.id!} />
|
<CommentGroup open={this.state.openComments} comments={commentList} ownerPostUserId={post.ownerUserId!} onToggleRequest={this.handleOpenComments} isPostOwner={this.props.isPostOwner!} disableComments={post.disableComments!} postId={post.id!} />
|
||||||
|
|
||||||
{/* Copy link dialog*/}
|
<ShareDialog
|
||||||
<Dialog
|
onClose={this.handleCloseShare}
|
||||||
title='Share On'
|
shareOpen={this.state.shareOpen}
|
||||||
open={this.state.shareOpen}
|
onCopyLink={this.handleCopyLink}
|
||||||
onClose={this.handleCloseShare}
|
openCopyLink={this.state.openCopyLink}
|
||||||
>
|
post={post}
|
||||||
<Paper className={classes.shareLinkPaper}>
|
|
||||||
{!this.state.openCopyLink
|
/>
|
||||||
? (<MenuList>
|
|
||||||
<MenuItem onClick={this.handleCopyLink} >
|
|
||||||
<ListItemIcon>
|
|
||||||
<SvgLink />
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText inset primary={translate!('post.copyLinkButton')} />
|
|
||||||
</MenuItem>
|
|
||||||
</MenuList>)
|
|
||||||
: <div>
|
|
||||||
<TextField autoFocus fullWidth={true} id='text-field-default' defaultValue={`${location.origin}/${post.ownerUserId}/posts/${post.id}`} />
|
|
||||||
<Typography className={classNames('animate-top', classes.clipboard)} variant='headline' component='h2'>
|
|
||||||
Link has been copied to clipboard ...
|
|
||||||
</Typography>
|
|
||||||
</div>}
|
|
||||||
</Paper>
|
|
||||||
</Dialog>
|
|
||||||
|
|
||||||
<PostWrite
|
<PostWrite
|
||||||
open={this.state.openPostWrite}
|
open={this.state.openPostWrite}
|
||||||
|
|||||||
40
src/components/shareDialog/IShareDialogComponentProps.ts
Normal file
40
src/components/shareDialog/IShareDialogComponentProps.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { Post } from 'core/domain/posts'
|
||||||
|
|
||||||
|
export interface IShareDialogComponentProps {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether share dialog is open
|
||||||
|
*/
|
||||||
|
shareOpen: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On close share dialog
|
||||||
|
*/
|
||||||
|
onClose: () => void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether copy link is displayed
|
||||||
|
*/
|
||||||
|
openCopyLink: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On copy link
|
||||||
|
*/
|
||||||
|
onCopyLink: () => void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The post object for sharing
|
||||||
|
*/
|
||||||
|
post: Post
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Styles
|
||||||
|
*/
|
||||||
|
classes?: any
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translate to locale string
|
||||||
|
*/
|
||||||
|
translate?: (state: any) => any
|
||||||
|
|
||||||
|
}
|
||||||
4
src/components/shareDialog/IShareDialogComponentState.ts
Normal file
4
src/components/shareDialog/IShareDialogComponentState.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
export interface IShareDialogComponentState {
|
||||||
|
|
||||||
|
}
|
||||||
213
src/components/shareDialog/ShareDialogComponent.tsx
Normal file
213
src/components/shareDialog/ShareDialogComponent.tsx
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
// - Import react components
|
||||||
|
import React, { Component } from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import SvgImage from 'material-ui-icons/Image'
|
||||||
|
import { withStyles } from 'material-ui/styles'
|
||||||
|
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||||
|
import classNames from 'classnames'
|
||||||
|
|
||||||
|
import {
|
||||||
|
FacebookShareButton,
|
||||||
|
FacebookIcon,
|
||||||
|
|
||||||
|
TwitterShareButton,
|
||||||
|
TwitterIcon,
|
||||||
|
|
||||||
|
GooglePlusShareButton,
|
||||||
|
GooglePlusIcon,
|
||||||
|
|
||||||
|
LinkedinShareButton,
|
||||||
|
LinkedinIcon
|
||||||
|
} from 'react-share'
|
||||||
|
|
||||||
|
// - Import app components
|
||||||
|
|
||||||
|
// - Import API
|
||||||
|
|
||||||
|
// - Import actions
|
||||||
|
import { IShareDialogComponentProps } from './IShareDialogComponentProps'
|
||||||
|
import { IShareDialogComponentState } from './IShareDialogComponentState'
|
||||||
|
import { Dialog, Paper, MenuList, MenuItem, ListItemIcon, ListItemText, TextField, Typography } from 'material-ui'
|
||||||
|
import SvgLink from 'material-ui-icons/Link'
|
||||||
|
|
||||||
|
const styles = (theme: any) => ({
|
||||||
|
image: {
|
||||||
|
verticalAlign: 'top',
|
||||||
|
maxWidth: '100%',
|
||||||
|
minWidth: '100%',
|
||||||
|
width: '100%'
|
||||||
|
},
|
||||||
|
clipboard: {
|
||||||
|
fontSize: '18px',
|
||||||
|
textAlign: 'center',
|
||||||
|
marginTop: '10px',
|
||||||
|
color: '#1e882d',
|
||||||
|
fontWeight: 400
|
||||||
|
},
|
||||||
|
networkShare: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%'
|
||||||
|
},
|
||||||
|
fullPageXs: {
|
||||||
|
[theme.breakpoints.down('xs')]: {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
margin: 0,
|
||||||
|
overflowY: 'auto'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
shareLinkPaper: {
|
||||||
|
minHeight: 80,
|
||||||
|
padding: 10,
|
||||||
|
minWidth: 460
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create component class
|
||||||
|
*/
|
||||||
|
export class ShareDialogComponent extends Component<IShareDialogComponentProps, IShareDialogComponentState> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component constructor
|
||||||
|
* @param {object} props is an object properties of component
|
||||||
|
*/
|
||||||
|
constructor(props: IShareDialogComponentProps) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
// Defaul state
|
||||||
|
this.state = {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binding functions to `this`
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reneder component DOM
|
||||||
|
* @return {react element} return the DOM which rendered by component
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
|
||||||
|
let { classes, translate, shareOpen, onClose, openCopyLink, post, onCopyLink } = this.props
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
className={classes.fullPageXs}
|
||||||
|
title='Share On'
|
||||||
|
open={shareOpen}
|
||||||
|
onClose={onClose}
|
||||||
|
>
|
||||||
|
<Paper className={classes.shareLinkPaper}>
|
||||||
|
{!openCopyLink
|
||||||
|
? (<MenuList>
|
||||||
|
<div>
|
||||||
|
<FacebookShareButton
|
||||||
|
onShareWindowClose={onClose}
|
||||||
|
url={`https://test-4515a.firebaseapp.com/${post.ownerUserId}/posts/${post.id}`}
|
||||||
|
quote={post.body}
|
||||||
|
hashtag={`#${post.tags![0]}`}>
|
||||||
|
<MenuItem >
|
||||||
|
<ListItemIcon classes={{ root: classes.networkShare }}>
|
||||||
|
<FacebookIcon
|
||||||
|
size={32}
|
||||||
|
round />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText inset primary={translate!('post.facebookButton')} />
|
||||||
|
</MenuItem>
|
||||||
|
</FacebookShareButton>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<TwitterShareButton
|
||||||
|
onShareWindowClose={onClose}
|
||||||
|
url={`https://test-4515a.firebaseapp.com/${post.ownerUserId}/posts/${post.id}`}
|
||||||
|
quote={post.body}
|
||||||
|
hashtag={`#${post.tags![0]}`}>
|
||||||
|
<MenuItem >
|
||||||
|
<ListItemIcon classes={{ root: classes.networkShare }}>
|
||||||
|
<TwitterIcon
|
||||||
|
size={32}
|
||||||
|
round />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText inset primary={translate!('post.twitterButton')} />
|
||||||
|
</MenuItem>
|
||||||
|
</TwitterShareButton>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<LinkedinShareButton
|
||||||
|
onShareWindowClose={onClose}
|
||||||
|
url={`https://test-4515a.firebaseapp.com/${post.ownerUserId}/posts/${post.id}`}
|
||||||
|
quote={post.body}
|
||||||
|
hashtag={`#${post.tags![0]}`}>
|
||||||
|
<MenuItem >
|
||||||
|
<ListItemIcon classes={{ root: classes.networkShare }}>
|
||||||
|
<LinkedinIcon
|
||||||
|
size={32}
|
||||||
|
round />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText inset primary={translate!('post.linkedinButton')} />
|
||||||
|
</MenuItem>
|
||||||
|
</LinkedinShareButton>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<GooglePlusShareButton
|
||||||
|
onShareWindowClose={onClose}
|
||||||
|
url={`https://test-4515a.firebaseapp.com/${post.ownerUserId}/posts/${post.id}`}
|
||||||
|
quote={post.body}
|
||||||
|
hashtag={`#${post.tags![0]}`}>
|
||||||
|
<MenuItem >
|
||||||
|
<ListItemIcon classes={{ root: classes.networkShare }}>
|
||||||
|
<GooglePlusIcon
|
||||||
|
size={32}
|
||||||
|
round />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText inset primary={translate!('post.googlePlusButton')} />
|
||||||
|
</MenuItem>
|
||||||
|
</GooglePlusShareButton>
|
||||||
|
</div>
|
||||||
|
<MenuItem onClick={onCopyLink} >
|
||||||
|
<ListItemIcon>
|
||||||
|
<SvgLink />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText inset primary={translate!('post.copyLinkButton')} />
|
||||||
|
</MenuItem>
|
||||||
|
</MenuList>)
|
||||||
|
: <div>
|
||||||
|
<TextField autoFocus fullWidth={true} id='text-field-default' defaultValue={`${location.origin}/${post.ownerUserId}/posts/${post.id}`} />
|
||||||
|
<Typography className={classNames('animate-top', classes.clipboard)} variant='headline' component='h2'>
|
||||||
|
Link has been copied to clipboard ...
|
||||||
|
</Typography>
|
||||||
|
</div>}
|
||||||
|
</Paper>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map dispatch to props
|
||||||
|
* @param {func} dispatch is the function to dispatch action to reducers
|
||||||
|
* @param {object} ownProps is the props belong to component
|
||||||
|
* @return {object} props of component
|
||||||
|
*/
|
||||||
|
const mapDispatchToProps = (dispatch: any, ownProps: IShareDialogComponentProps) => {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map state to props
|
||||||
|
* @param {object} state is the obeject from redux store
|
||||||
|
* @param {object} ownProps is the props belong to component
|
||||||
|
* @return {object} props of component
|
||||||
|
*/
|
||||||
|
const mapStateToProps = (state: any, ownProps: IShareDialogComponentProps) => {
|
||||||
|
return {
|
||||||
|
translate: getTranslate(state.locale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// - Connect component to redux store
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles as any)(ShareDialogComponent as any) as any)
|
||||||
2
src/components/shareDialog/index.ts
Normal file
2
src/components/shareDialog/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
import ShareDialogComponent from './ShareDialogComponent'
|
||||||
|
export default ShareDialogComponent
|
||||||
@@ -30,7 +30,11 @@
|
|||||||
"postButton": "POST",
|
"postButton": "POST",
|
||||||
"cancelButton": "CANCEL",
|
"cancelButton": "CANCEL",
|
||||||
"updateButton": "UPDATE",
|
"updateButton": "UPDATE",
|
||||||
"copyLinkButton": "Copy Link"
|
"copyLinkButton": "Copy Link",
|
||||||
|
"facebookButton": "Share in Facebook",
|
||||||
|
"twitterButton": "Share in Twitter",
|
||||||
|
"linkedinButton": "Share in Linkedin",
|
||||||
|
"googlePlusButton": "Share in Google+"
|
||||||
|
|
||||||
},
|
},
|
||||||
"imageGallery": {
|
"imageGallery": {
|
||||||
|
|||||||
1
src/typings/react-share.ts
Normal file
1
src/typings/react-share.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
declare module 'react-share'
|
||||||
19
yarn.lock
19
yarn.lock
@@ -691,7 +691,7 @@ babel-register@^6.26.0:
|
|||||||
mkdirp "^0.5.1"
|
mkdirp "^0.5.1"
|
||||||
source-map-support "^0.4.15"
|
source-map-support "^0.4.15"
|
||||||
|
|
||||||
babel-runtime@^6.22.0, babel-runtime@^6.26.0:
|
babel-runtime@^6.22.0, babel-runtime@^6.26.0, babel-runtime@^6.6.1:
|
||||||
version "6.26.0"
|
version "6.26.0"
|
||||||
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
|
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -1659,7 +1659,7 @@ date-now@^0.1.4:
|
|||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
|
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
|
||||||
|
|
||||||
debug@2, debug@2.6.9, debug@^2.2.0, debug@^2.6.0, debug@^2.6.6, debug@^2.6.8:
|
debug@2, debug@2.6.9, debug@^2.1.3, debug@^2.2.0, debug@^2.6.0, debug@^2.6.6, debug@^2.6.8:
|
||||||
version "2.6.9"
|
version "2.6.9"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3978,6 +3978,12 @@ jsonify@~0.0.0:
|
|||||||
version "0.0.0"
|
version "0.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
|
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
|
||||||
|
|
||||||
|
jsonp@^0.2.1:
|
||||||
|
version "0.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/jsonp/-/jsonp-0.2.1.tgz#a65b4fa0f10bda719a05441ea7b94c55f3e15bae"
|
||||||
|
dependencies:
|
||||||
|
debug "^2.1.3"
|
||||||
|
|
||||||
jsonparse@^1.2.0:
|
jsonparse@^1.2.0:
|
||||||
version "1.3.1"
|
version "1.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
|
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
|
||||||
@@ -6249,6 +6255,15 @@ react-scrollbar-size@^2.0.2:
|
|||||||
react-event-listener "^0.5.1"
|
react-event-listener "^0.5.1"
|
||||||
stifle "^1.0.2"
|
stifle "^1.0.2"
|
||||||
|
|
||||||
|
react-share@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-share/-/react-share-2.0.0.tgz#be07224dfe01ea0613e84e9412dddf0a1ed07a20"
|
||||||
|
dependencies:
|
||||||
|
babel-runtime "^6.6.1"
|
||||||
|
classnames "^2.2.5"
|
||||||
|
jsonp "^0.2.1"
|
||||||
|
prop-types "^15.5.8"
|
||||||
|
|
||||||
react-string-replace@^0.4.0:
|
react-string-replace@^0.4.0:
|
||||||
version "0.4.1"
|
version "0.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-string-replace/-/react-string-replace-0.4.1.tgz#024c6ac0a91163ecae439a1b197d3e1660c98c0d"
|
resolved "https://registry.yarnpkg.com/react-string-replace/-/react-string-replace-0.4.1.tgz#024c6ac0a91163ecae439a1b197d3e1660c98c0d"
|
||||||
|
|||||||
Reference in New Issue
Block a user