Compare commits

...

9 Commits

Author SHA1 Message Date
Huaoe 901280363e supp import
tt-app/app/saga Build queued...
2019-11-05 14:10:26 +01:00
Huaoe 6612f91047 push notification fixed 2019-11-04 16:36:20 +01:00
Huaoe 5e7fabe1ce Merge branch 'webRTCIntegration' into saga 2019-11-04 14:10:50 +01:00
Huaoe e05aadd5c3 fix slash positionning in /api/talent?bearer= 2019-11-04 12:26:27 +01:00
Huaoe 567a282dcf Merge branch 'Saga' of https://git.e-declic.net/talents-tube/app into Saga 2019-11-04 10:25:08 +01:00
Huaoe 400340aaef repair Reponse + public folder usage
tt-app/app/webRTCIntegration There was a failure building this commit
2019-10-18 12:20:09 +02:00
Huaoe 5a43a2a9e1 upload webrtc + Link stalling 2019-10-18 10:54:10 +02:00
Huaoe 69848dbe38 made this url work
tt-app/app/webRTCIntegration There was a failure building this commit
: http://localhost:3000/Reponse?adId=80
2019-10-17 17:24:52 +02:00
Huaoe ad40f73997 webRtc repaired 2019-10-16 16:34:05 +02:00
62 changed files with 375 additions and 12693 deletions
-1
View File
@@ -1,4 +1,3 @@
/node_modules/ /node_modules/
.next/ .next/
.env .env
+1 -1
View File
@@ -14,5 +14,5 @@ RUN apk add --no-cache bash
RUN apk add --no-cache yarn RUN apk add --no-cache yarn
CMD cd /home/app/nextjs && yarn cache dir && yarn cache clean && yarn build && pm2 startOrReload ecosystem.config.js --env production --no-daemon CMD cd /home/app/nextjs && yarn cache dir && yarn cache clean && yarn install && yarn build && pm2 startOrReload ecosystem.config.js --env production --no-daemon
+12
View File
@@ -39,6 +39,18 @@ Try to name without too much precision
[components/organisms] General components [components/organisms] General components
[components/templates] Layouts components [components/templates] Layouts components
## MEP
=================================
Mise en PRE-production de lapplication PWA
=================================
Aller dans la preproduction et git pull dans le répertoire /app (pas www)
Possibilité de devoir git stash
Attention de bien avoir le .env
Restart docker preproduction (sudo make ENV=preprod docker-restart)
sudo docker exec -it frontnginx.nginx bash
nginx -t && nginx -s reload
## Test ## Test
### Cypress ### Cypress
+1 -3
View File
@@ -4,8 +4,6 @@ import { withStyles } from '@material-ui/core/styles'
import IconButton from '@material-ui/core/IconButton'; import IconButton from '@material-ui/core/IconButton';
import CloseIcon from '@material-ui/icons/Close'; import CloseIcon from '@material-ui/icons/Close';
import Link from 'next/link'
const styles = theme => ({ const styles = theme => ({
close: { close: {
padding: theme.spacing.unit / 2, padding: theme.spacing.unit / 2,
@@ -96,7 +94,7 @@ class Messager extends Component {
}} }}
message={<span id="message-id">{this.state.title + " : " + this.state.body}</span>} message={<span id="message-id">{this.state.title + " : " + this.state.body}</span>}
action={[ action={[
<Link href={this.state.link}><a>Voir</a></Link>, <a href={this.state.link}>Voir</a>,
<IconButton <IconButton
key="close" key="close"
aria-label="Close" aria-label="Close"
+79 -81
View File
@@ -35,7 +35,7 @@ class WebPush extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
} }
componentDidMount() { componentDidMount() {
if (swRegistration === null) { if (swRegistration === null) {
@@ -44,12 +44,12 @@ class WebPush extends Component {
} }
UNSAFE_componentWillReceiveProps(nextProps) { UNSAFE_componentWillReceiveProps(nextProps) {
console.log("isUserSubscribedToPush ::: " + nextProps.isUserSubscribedToPush);
if (this.props.subscriveUserEnabled != nextProps.subscriveUserEnabled && nextProps.subscriveUserEnabled) { if (this.props.subscriveUserEnabled != nextProps.subscriveUserEnabled && nextProps.subscriveUserEnabled) {
this.onSubscribeUser() this.onSubscribeUser()
} }
if (!!nextProps.isUserSubscribedToPush) {
if(!!nextProps.isUserSubscribedToPush){ this.setState({ on: true })
this.setState({on: true})
} }
} }
@@ -80,99 +80,97 @@ class WebPush extends Component {
} }
} }
onSubscribeUser = () => { onSubscribeUser = () => {
if (swRegistration == null) { if (swRegistration == null) {
return return
}
swRegistration.pushManager.getSubscription()
.then((subscription) => {
var isSubscribed = !(subscription === null)
if (isSubscribed) {
this.onUpdateSubscriptionOnServer(subscription)
} else {
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey)
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
})
.then((subscription) => {
console.log('User is subscribed.')
if (this.onUpdateSubscriptionOnServer) {
this.onUpdateSubscriptionOnServer(subscription)
}
})
.catch((err) => {
console.log('Failed to subscribe the user: ', err)
if (onSubscribeFailed) {
this.onSubscriptionFailed(err)
}
});
}
})
} }
swRegistration.pushManager.getSubscription() onUnSubscribeUser = () => {
.then((subscription) => { swRegistration.pushManager.getSubscription()
var isSubscribed = !(subscription === null)
if (isSubscribed) {
this.onUpdateSubscriptionOnServer(subscription)
} else {
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey)
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
})
.then((subscription) => {
console.log('User is subscribed.')
if (this.onUpdateSubscriptionOnServer) {
this.onUpdateSubscriptionOnServer(subscription)
}
})
.catch((err) => {
console.log('Failed to subscribe the user: ', err)
if (onSubscribeFailed) {
this.onSubscriptionFailed(err)
}
});
}
})
}
onUnSubscribeUser = () => { .then((subscription) => {
swRegistration.pushManager.getSubscription() if (subscription) {
.then((subscription) => { return subscription.unsubscribe();
if (subscription) { }
})
.then(() =>
this.setState(({ on }) => ({ on: false })))
//TODO: facultatif update DB
// .then(() => {
// return fetch(//, {
// method: 'POST',
// headers: {
// 'Content-Type': 'application/json'
// },
// body: JSON.stringify(subscription)
// })
// .then((response) => {
// if (!response.ok) {
// throw new Error('Bad status code from server.');
// }
// ///TODO bind UI
// return true;
// })
return subscription.unsubscribe(); // })
} .catch((err) => {
}) console.error('Failed to unsubscribe the user.', err);
.then(() =>
this.setState(({ on }) => ({ on: false })))
//TODO: facultatif update DB
// .then(() => {
// return fetch(//, {
// method: 'POST',
// headers: {
// 'Content-Type': 'application/json'
// },
// body: JSON.stringify(subscription)
// })
// .then((response) => {
// if (!response.ok) {
// throw new Error('Bad status code from server.');
// }
// ///TODO bind UI
// return true;
// })
// }) });
.catch((err) => { }
console.error('Failed to unsubscribe the user.', err);
}); onRegisterServiceWorker = () => {
} navigator.serviceWorker.register('/static/js/Edeclic-service-worker.js')
.then(function (swReg) {
console.info('Service Worker is registered', swReg);
onRegisterServiceWorker = () => { swRegistration = swReg;
navigator.serviceWorker.register('/static/js/Edeclic-service-worker.js') })
.then(function (swReg) { }
console.info('Service Worker is registered', swReg);
swRegistration = swReg; render() {
}) return (<WebPushContext.Provider
} value={{ on: this.state.on, toggleSubscription: this.toggleSubscription }}
{...this.props}
render() { />)
return (<WebPushContext.Provider }
value={{ on: this.state.on, toggleSubscription: this.toggleSubscription }}
{...this.props}
/>)
}
} }
WebPush.propTypes = { WebPush.propTypes = {
} }
function mapStateToProps(state) { function mapStateToProps(state) {
return { return {
isUserSubscribedToPush: state.isUserSubscribedToPush isUserSubscribedToPush: state.user.isUserSubscribedToPush
}; };
} }
export default connect(mapStateToProps, { subscribeUserToPushRequest })(WebPush); export default connect(mapStateToProps, { subscribeUserToPushRequest })(WebPush);
+3 -5
View File
@@ -267,11 +267,9 @@ function Footer(props) {
<Typography gutterBottom component="p" className={classes.textContainerRegion} align="center" > <Typography gutterBottom component="p" className={classes.textContainerRegion} align="center" >
Entreprise soutenue par Entreprise soutenue par
</Typography> </Typography>
<Link href="https://www.bretagne.bzh/" > <a href="https://www.bretagne.bzh/" target="_blank" className={classes.darkMenuItem} rel="noopener">
<a target="_blank" className={classes.darkMenuItem} rel="noopener"> <img alt="Région Bretagne" src='/static/images/logos/Logo-region.svg' className={classes.footerLogo} />
<img alt="Région Bretagne" src='/static/images/logos/Logo-region.svg' className={classes.footerLogo} /> </a>
</a>
</Link>
</section> </section>
</div> </div>
); );
+44 -50
View File
@@ -198,9 +198,9 @@ const styles = theme => ({
}, },
}, },
active: { active: {
'& span, & svg': { '& span, & svg': {
color: theme.palette.primary.main+ ' !important', color: theme.palette.primary.main + ' !important',
}, },
}, },
@@ -317,9 +317,9 @@ class Header extends React.Component {
}; };
onRedirectAccount = e => { onRedirectAccount = e => {
urlEnv = (process.env.NODE_ENV !== 'production') ? '//localhost/app_dev.php/' : process.env.SERVER_URL; urlEnv = (process.env.NODE_ENV !== 'production') ? '//localhost/app_dev.php' : process.env.SERVER_URL;
e.preventDefault(); e.preventDefault();
var redirectAccountUrl = urlEnv + "api/talent?bearer=" + localStorage.getItem("ttJWT"); var redirectAccountUrl = urlEnv + "/api/talent?bearer=" + localStorage.getItem("ttJWT");
window.open(redirectAccountUrl); window.open(redirectAccountUrl);
} }
@@ -329,7 +329,7 @@ class Header extends React.Component {
const { classes } = this.props; const { classes } = this.props;
return ( return (
<div className={classes.root}> <div className={classes.root}>
<Drawer anchor="left" open={this.state.left} onClose={this.toggleDrawer('left', false)}> <Drawer anchor="left" open={this.state.left} onClose={this.toggleDrawer('left', false)}>
@@ -352,29 +352,29 @@ class Header extends React.Component {
<Divider /> <Divider />
<div className={classes.links}> <div className={classes.links}>
<div className={classes.linkGroup}> <div className={classes.linkGroup}>
<ActiveLink activeClassName={ classes.active } href="/" > <ActiveLink activeClassName={classes.active} href="/" >
<a className={classes.darkMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}> <a className={classes.darkMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
<HomeIcon className={classes.icon} /> <HomeIcon className={classes.icon} />
<ListItemText classes={{ primary: classes.ListItemText }} primary='Accueil'> <ListItemText classes={{ primary: classes.ListItemText }} primary='Accueil'>
</ListItemText> </ListItemText>
</ListItem></a> </ListItem></a>
</ActiveLink> </ActiveLink>
<ActiveLink activeClassName={ classes.active } href="/Offres" > <ActiveLink activeClassName={classes.active} href="/Offres" >
<a className={classes.darkMenuItem +' '+ classes.darkMenuItemSpecific}><ListItem classes={{ root: classes.rootListItemIcon }}> <a className={classes.darkMenuItem + ' ' + classes.darkMenuItemSpecific}><ListItem classes={{ root: classes.rootListItemIcon }}>
<OfferIcon className={classes.icon} /> <OfferIcon className={classes.icon} />
<ListItemText classes={{ primary: classes.ListItemText }} primary={`Offres d'emploi`}> <ListItemText classes={{ primary: classes.ListItemText }} primary={`Offres d'emploi`}>
</ListItemText> </ListItemText>
</ListItem></a> </ListItem></a>
</ActiveLink> </ActiveLink>
<ActiveLink activeClassName={ classes.active } href="/Entreprises" > <ActiveLink activeClassName={classes.active} href="/Entreprises" >
<a className={classes.darkMenuItem +' '+ classes.darkMenuItemSpecific}><ListItem classes={{ root: classes.rootListItemIcon }}> <a className={classes.darkMenuItem + ' ' + classes.darkMenuItemSpecific}><ListItem classes={{ root: classes.rootListItemIcon }}>
<CompanyIcon className={classes.icon} /> <CompanyIcon className={classes.icon} />
<ListItemText classes={{ primary: classes.ListItemText }} primary='Nos entreprises'> <ListItemText classes={{ primary: classes.ListItemText }} primary='Nos entreprises'>
</ListItemText> </ListItemText>
</ListItem></a> </ListItem></a>
</ActiveLink> </ActiveLink>
<ActiveLink activeClassName={ classes.active } href="/Help" > <ActiveLink activeClassName={classes.active} href="/Help" >
<a className={classes.darkMenuItem +' '+ classes.darkMenuItemSpecific}><ListItem classes={{ root: classes.rootListItem }}> <a className={classes.darkMenuItem + ' ' + classes.darkMenuItemSpecific}><ListItem classes={{ root: classes.rootListItem }}>
<HelpIcon className={classes.icon} /> <HelpIcon className={classes.icon} />
<ListItemText classes={{ primary: classes.ListItemText }} primary='Comment ça marche ?'> <ListItemText classes={{ primary: classes.ListItemText }} primary='Comment ça marche ?'>
</ListItemText> </ListItemText>
@@ -384,31 +384,27 @@ class Header extends React.Component {
<div> <div>
<div className={classes.videothequeLinkGroup}> <div className={classes.videothequeLinkGroup}>
<Link href="https://www.talentstube.com/faire-offre-emploi-video" > <a href="https://www.talentstube.com/faire-offre-emploi-video" className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
<a className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}> <VideoIcon className={classes.icon} />
<VideoIcon className={classes.icon} /> <ListItemText classes={{ primary: classes.ListItemText }} primary='CV vidéothèque'>
<ListItemText classes={{ primary: classes.ListItemText }} primary='CV vidéothèque'> </ListItemText>
</ListItemText> </ListItem>
</ListItem></a> </a>
</Link>
</div> </div>
<div className={classes.blogLinkGroup}> <div className={classes.blogLinkGroup}>
<Link href="https://blog.talentstube.com" > <a href="https://blog.talentstube.com" className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
<a className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}> <NotesIcon className={classes.icon} />
<NotesIcon className={classes.icon} /> <ListItemText classes={{ primary: classes.ListItemText }} primary='Blog'>
<ListItemText classes={{ primary: classes.ListItemText }} primary='Blog'> </ListItemText>
</ListItemText> </ListItem>
</ListItem></a> </a>
</Link>
</div> </div>
<div className={classes.recruteurLinkGroup}> <div className={classes.recruteurLinkGroup}>
<Link href="https://www.talentstube.com/faire-offre-emploi-video" > <a href="https://www.talentstube.com/faire-offre-emploi-video" className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
<a className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}> <SupervisorAccountIcon className={classes.icon} />
<SupervisorAccountIcon className={classes.icon} /> <ListItemText classes={{ primary: classes.ListItemText }} primary='Recruteurs'>
<ListItemText classes={{ primary: classes.ListItemText }} primary='Recruteurs'> </ListItemText>
</ListItemText> </ListItem></a>
</ListItem></a>
</Link>
</div> </div>
</div> </div>
@@ -462,13 +458,12 @@ class Header extends React.Component {
<Divider light={true} /> <Divider light={true} />
<div className={classes.linkGroup}> <div className={classes.linkGroup}>
<Link href="https://www.talentstube.com/faire-offre-emploi-video" > <a href="https://www.talentstube.com/faire-offre-emploi-video" className={classes.lightMenuItem}><ListItem classes={{ primary: classes.ListItemText }} classes={{ root: classes.rootListItemIcon }}>
<a className={classes.lightMenuItem}><ListItem classes={{ primary: classes.ListItemText }} classes={{ root: classes.rootListItemIcon }}> <WorkOutlineIcon className={classes.icon} />
<WorkOutlineIcon className={classes.icon} /> <ListItemText primary='Connexion recruteurs'>
<ListItemText primary='Connexion recruteurs'> </ListItemText>
</ListItemText> </ListItem>
</ListItem></a> </a>
</Link>
</div> </div>
</List> </List>
</div>} </div>}
@@ -548,19 +543,19 @@ class Header extends React.Component {
<List className={classes.desktopMenuList}> <List className={classes.desktopMenuList}>
<div> <div>
<ActiveLink activeClassName={ classes.active } href="/Offres" > <ActiveLink activeClassName={classes.active} href="/Offres" >
<a className={classes.desktopMenuItem}> <a className={classes.desktopMenuItem}>
<ListItemText primary="Offres d'emploi"> <ListItemText primary="Offres d'emploi">
</ListItemText> </ListItemText>
</a> </a>
</ActiveLink> </ActiveLink>
<ActiveLink activeClassName={ classes.active } href="/Entreprises" > <ActiveLink activeClassName={classes.active} href="/Entreprises" >
<a className={classes.desktopMenuItem}> <a className={classes.desktopMenuItem}>
<ListItemText primary='Nos entreprises'> <ListItemText primary='Nos entreprises'>
</ListItemText> </ListItemText>
</a> </a>
</ActiveLink> </ActiveLink>
<ActiveLink activeClassName={ classes.active } href="/Help" > <ActiveLink activeClassName={classes.active} href="/Help" >
<a className={classes.desktopMenuItem}> <a className={classes.desktopMenuItem}>
<ListItemText primary='Comment ça marche ?'> <ListItemText primary='Comment ça marche ?'>
</ListItemText> </ListItemText>
@@ -614,13 +609,12 @@ class Header extends React.Component {
</List> </List>
</section> </section>
<section className={classes.appBarDesktopSection + ' ' + classes.appBarDesktopSection3}> <section className={classes.appBarDesktopSection + ' ' + classes.appBarDesktopSection3}>
<Link href="https://www.talentstube.com/faire-offre-emploi-video" >
<a className={classes.desktopMenuItem}> <a href="https://www.talentstube.com/faire-offre-emploi-video" className={classes.desktopMenuItem}>
<ListItemText primary='Espace recruteurs'> <ListItemText primary='Espace recruteurs'>
</ListItemText> </ListItemText>
<ArrowForward className={classes.icon} /> <ArrowForward className={classes.icon} />
</a> </a>
</Link>
</section> </section>
</Toolbar> </Toolbar>
</AppBar>) </AppBar>)
+64 -68
View File
@@ -268,9 +268,9 @@ const styles = theme => ({
}, },
}, },
videoTerritory: { videoTerritory: {
paddingBottom: '56% !important', paddingBottom: '56% !important',
[theme.breakpoints.up('md')]: { [theme.breakpoints.up('md')]: {
paddingBottom: '56% !important', paddingBottom: '56% !important',
} }
}, },
territoryTitle: { territoryTitle: {
@@ -299,8 +299,8 @@ function OffreDetail(props) {
const imgUrlDesktop = (offre.company && offre.company.presentation_video && offre.company.presentation_video.thumbnails && offre.company.presentation_video.thumbnails[0] && offre.company.presentation_video.thumbnails[0].sizes[4]) ? offre.company.presentation_video.thumbnails[0].sizes[4].link : DefaultUrl const imgUrlDesktop = (offre.company && offre.company.presentation_video && offre.company.presentation_video.thumbnails && offre.company.presentation_video.thumbnails[0] && offre.company.presentation_video.thumbnails[0].sizes[4]) ? offre.company.presentation_video.thumbnails[0].sizes[4].link : DefaultUrl
const socialShareUrl = typeof window !== 'undefined' ? window.location : publicRuntimeConfig.frontServerUrl + `/Offre/${offre.id}-${_.kebabCase(offre.title)}-${_.kebabCase(offre.location.gmap_address.name)}`; const socialShareUrl = typeof window !== 'undefined' ? window.location : publicRuntimeConfig.frontServerUrl + `/Offre/${offre.id}-${_.kebabCase(offre.title)}-${_.kebabCase(offre.location.gmap_address.name)}`;
const entrepriseLink = (offre.company && `/Entreprise/${offre.company.id}-${_.kebabCase(offre.company.brand_name)}-${_.kebabCase(offre.location.gmap_address.name)}`); const entrepriseLink = (offre.company && `/Entreprise/${offre.company.id}-${_.kebabCase(offre.company.brand_name)}-${_.kebabCase(offre.location.gmap_address.name)}`);
const territoryVideoUrlTab = (offre.territories && offre.territories[0] && offre.territories[0].territory)?offre.territories[0].territory.presentation_video.cdn_url.split('/'):''; const territoryVideoUrlTab = (offre.territories && offre.territories[0] && offre.territories[0].territory) ? offre.territories[0].territory.presentation_video.cdn_url.split('/') : '';
const territoryVideoId = territoryVideoUrlTab[2] const territoryVideoId = territoryVideoUrlTab[2]
return ( return (
<Fragment> <Fragment>
@@ -314,27 +314,24 @@ function OffreDetail(props) {
<Hidden smDown> <Hidden smDown>
<section className={classes.headerContainerDesktop}> <section className={classes.headerContainerDesktop}>
<div className={classes.offerInfoContainer}> <div className={classes.offerInfoContainer}>
<Link href={entrepriseLink} >
<a>
<div className={classes.logoContainer}>
<Avatar className={classes.logo} classes={{ img: classes.MuiAvatarImg }} <a href={entrepriseLink} >
src={logoUrl} alt="companyLogo" /> <div className={classes.logoContainer}>
</div> <Avatar className={classes.logo} classes={{ img: classes.MuiAvatarImg }}
</a> src={logoUrl} alt="companyLogo" />
</Link>
</div>
</a>
<div className={classes.infoContainer}> <div className={classes.infoContainer}>
<Typography gutterBottom className={classes.offreTitle}> <Typography gutterBottom className={classes.offreTitle}>
{offre.title} {offre.title}
</Typography> </Typography>
<Link href={entrepriseLink} > <a href={entrepriseLink} >
<a> <Typography gutterBottom variant="subtitle1" className={classes.companyName}>
<Typography gutterBottom variant="subtitle1" className={classes.companyName}> {offre.company.brand_name && offre.company.brand_name}
{offre.company.brand_name && offre.company.brand_name} </Typography>
</Typography> </a>
</a>
</Link>
{offre.is_promoted && ( {offre.is_promoted && (
<Chip label="Pourvue" className={classes.chip} /> <Chip label="Pourvue" className={classes.chip} />
)} )}
@@ -342,11 +339,12 @@ function OffreDetail(props) {
</div> </div>
</div> </div>
{!!!offre.is_promoted && ( {!!!offre.is_promoted && (
<Button <Link href={`/Reponse?adId=${offre.id}`}>
variant="contained" <Button
className={classes.button + ' cypButtonApply'} variant="contained"
onClick={() => Router.push(`/Reponse?adId=${offre.id}`)} className={classes.button + ' cypButtonApply'}
>Postuler</Button> >Postuler</Button>
</Link>
)} )}
</section> </section>
</Hidden> </Hidden>
@@ -356,27 +354,23 @@ function OffreDetail(props) {
<div className={classes.container}> <div className={classes.container}>
<Hidden mdUp> <Hidden mdUp>
<section className={classes.headerContainer}> <section className={classes.headerContainer}>
<Link href={entrepriseLink} > <div className={classes.logoContainer}>
<div className={classes.logoContainer}>
<a> <a href={entrepriseLink} >
<Avatar className={classes.logo} classes={{ img: classes.MuiAvatarImg }} <Avatar className={classes.logo} classes={{ img: classes.MuiAvatarImg }}
src={logoUrl} alt="companylogo" /> src={logoUrl} alt="companylogo" />
</a> </a>
</div> </div>
</Link>
<div className={classes.infoContainer}> <div className={classes.infoContainer}>
<Typography gutterBottom variant="h5" component="h1" className={classes.title}> <Typography gutterBottom variant="h5" component="h1" className={classes.title}>
{offre.title} {offre.title}
</Typography> </Typography>
<Link href={entrepriseLink} > <a href={entrepriseLink} >
<a> <Typography gutterBottom variant="subtitle1" className={classes.text}>
<Typography gutterBottom variant="subtitle1" className={classes.text}> {offre.company.brand_name && offre.company.brand_name}
{offre.company.brand_name && offre.company.brand_name} </Typography>
</Typography> </a>
</a>
</Link>
{/* ville */} {/* ville */}
</div> </div>
</section> </section>
@@ -403,22 +397,24 @@ function OffreDetail(props) {
{offre.description} {offre.description}
</Typography> </Typography>
<section className={classes.tagsContainer}> <section className={classes.tagsContainer}>
{offre.public_tag.map((label, index) => { {offre.public_tag.map((label, index) => {
return ( return (
<Chip label={label} className={classes.tags} key={index} /> <Chip label={label} className={classes.tags} key={index} />
); );
})} })}
</section> </section>
</SimpleCollapse> </SimpleCollapse>
{!offre.is_promoted && ( {!offre.is_promoted && (
<div className={classes.shareContainer}> <div className={classes.shareContainer}>
<Button <Link href={`/Reponse?adId=${offre.id}`}>
cyp="ButtonApply" <Button
variant="contained" cyp="ButtonApply"
className={classes.button} variant="contained"
onClick={() => Router.push(`/Reponse?adId=${offre.id}`)} className={classes.button}
>Postuler</Button>
>Postuler ! </Button>
</Link>
<Typography className={classes.contentCondition}> <Typography className={classes.contentCondition}>
ou ou
</Typography> </Typography>
@@ -439,33 +435,33 @@ function OffreDetail(props) {
Découvrir l'entreprise <span className={classes.primary}>{offre.company.brand_name && offre.company.brand_name}</span> Découvrir l'entreprise <span className={classes.primary}>{offre.company.brand_name && offre.company.brand_name}</span>
</Typography> </Typography>
<Link href={entrepriseLink} > <a href={entrepriseLink}>
<div className={classes.discoverContainerImage}> <div className={classes.discoverContainerImage}>
<img src={isWidthUp('sm', props.width) ? imgUrlDesktop : imgUrl} alt="company" /> <img src={isWidthUp('sm', props.width) ? imgUrlDesktop : imgUrl} alt="company" />
<KeyboardArrowleftIcon className={classes.iconPlay} /> <KeyboardArrowleftIcon className={classes.iconPlay} />
</div> </div>
</Link> </a>
</section> </section>
</div> </div>
)} )}
{offre.territories && territoryVideoId && ( {offre.territories && territoryVideoId && (
<div className={classes.container + ' ' + classes.discoverContainerTerritory}> <div className={classes.container + ' ' + classes.discoverContainerTerritory}>
<section> <section>
<Typography gutterBottom className={classes.title + ' ' + classes.discoverTitle} align="center"> <Typography gutterBottom className={classes.title + ' ' + classes.discoverTitle} align="center">
Découvrir le <span className={classes.primary}>territoire</span> Découvrir le <span className={classes.primary}>territoire</span>
</Typography>
<section className={classes.discoverTerritoryContentContainer}>
<VideoVimeo classesOverride={classes.videoTerritory} videoId={territoryVideoId} autoplay='0' />
<Typography className={classes.territoryTitle}>
{(!!!offre.territories) ? offre.territories[0].territory.brand_name : ''}
</Typography>
<Typography className={classes.territoryType} gutterBottom>
{(!!!offre.territories) ? offre.territories[0].territory.extra.terType : ''}
</Typography> </Typography>
<section className={classes.discoverTerritoryContentContainer}>
<VideoVimeo classesOverride={classes.videoTerritory} videoId={territoryVideoId} autoplay='0' />
<Typography className={classes.territoryTitle}>
{(!!!offre.territories) ? offre.territories[0].territory.brand_name : ''}
</Typography>
<Typography className={classes.territoryType} gutterBottom>
{(!!!offre.territories) ? offre.territories[0].territory.extra.terType : ''}
</Typography>
</section>
</section> </section>
</div> </section>
) </div>
)
} }
</Fragment> </Fragment>
)} )}
+55 -23
View File
@@ -15,6 +15,31 @@ const RTCRecorder = dynamic(() => import('RecordRTC'), {
ssr: false ssr: false
}) })
const videoJsOptions = {
controls: true,
fluid: true,
plugins: {
/*
// wavesurfer section is only needed when recording audio-only
wavesurfer: {
src: 'live',
waveColor: '#36393b',
progressColor: 'black',
debug: true,
cursorWidth: 1,
msDisplayMax: 20,
hideScrollbar: true
},
*/
record: {
audio: true,
video: true,
maxLength: 600,
//debug: true
}
}
};
const styles = theme => ({ const styles = theme => ({
root: { root: {
@@ -22,19 +47,34 @@ const styles = theme => ({
maxWidth: '400px', [theme.breakpoints.down('md')]: { maxWidth: '400px', [theme.breakpoints.down('md')]: {
maxWidth: `${100 - (theme.spacing(1))}vw` maxWidth: `${100 - (theme.spacing(1))}vw`
}, },
sendContainer: {
textAlign: 'center'
},
button: { button: {
textTransform: 'inherit',
marginLeft: theme.spacing(8),
marginRight: theme.spacing(8),
marginTop: theme.spacing(4),
marginBottom: theme.spacing(2),
padding: theme.spacing(1.2, 2),
//borderRadius: '3px',
[theme.breakpoints.up('sm')]: {
margin: 'auto',
},
margin: theme.spacing(1),
alignSelf: 'flex-end'
}, },
} }
}) })
class Recorder extends Component { class Recorder extends Component {
state={
canSend:false
}
async componentDidMount() { async componentDidMount() {
var record = (await import('videojs-record')).default var record = (await import('videojs-record')).default
// instantiate Video.js // instantiate Video.js
this.player = videojs(this.videoNode, this.props, () => { this.player = videojs(this.videoNode, videoJsOptions, () => {
// print version information at startup // print version information at startup
var version_info = 'Using video.js ' + videojs.VERSION + var version_info = 'Using video.js ' + videojs.VERSION +
' with videojs-record ' + videojs.getPluginVersion('record') + ' with videojs-record ' + videojs.getPluginVersion('record') +
@@ -45,11 +85,13 @@ class Recorder extends Component {
// device is ready // device is ready
this.player.on('deviceReady', () => { this.player.on('deviceReady', () => {
console.info('device is ready!'); console.info('device is ready!');
this.setState({canSend:false});
}); });
// user clicked the record button and started recording // user clicked the record button and started recording
this.player.on('startRecord', () => { this.player.on('startRecord', () => {
console.log('started recording!'); console.log('started recording!');
this.setState({canSend:false});
}); });
// user completed recording and stream is available // user completed recording and stream is available
@@ -57,19 +99,22 @@ class Recorder extends Component {
// recordedData is a blob object containing the recorded data that // recordedData is a blob object containing the recorded data that
// can be downloaded by the user, stored on server etc. // can be downloaded by the user, stored on server etc.
console.log('finished recording: ', this.player.recordedData); console.log('finished recording: ', this.player.recordedData);
this.setState({canSend:true});
}); });
// error handling // error handling
this.player.on('error', (element, error) => { this.player.on('error', (element, error) => {
console.warn(error); console.warn(error);
this.setState({canSend:false});
}); });
this.player.on('deviceError', () => { this.player.on('deviceError', () => {
console.error('device error:', this.player.deviceErrorCode); console.error('device error:', this.player.deviceErrorCode);
this.setState({canSend:false});
}); });
} }
// destroy player on unmount //destroy player on unmount
componentWillUnmount() { componentWillUnmount() {
if (this.player) { if (this.player) {
this.player.dispose(); this.player.dispose();
@@ -77,24 +122,11 @@ class Recorder extends Component {
} }
sendBlob = () => { sendBlob = () => {
console.log('accessing recording: ', this.player.recordedData) // console.log('accessing recording: ', this.player.recordedData)
var formData = new FormData(); var formData = new FormData();
formData.append('upload', this.player.recordedData, "myupload"); formData.append('upload', this.player.recordedData, "myupload");
// formData.append('user', 7);//TODO: taking from auth
setAuthorizationHeader('eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE1NTk4OTE4ODIsImV4cCI6MTU1OTg5NTQ4Miwicm9sZXMiOlsiUk9MRV9UQUxFTlQiLCJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJ0aG9tYXMuYmVycm9kQGUtZGVjbGljLmNvbSJ9.dnXiifet5SIyZf1zOBnu6RvVqA6k-aT16O_YNy6ZAhRZUuQtqP21enNkug0KxLEFMy91gcj0gkGuETqMwcHBL_xkx7rJvb2dLoOo0yduZxJLzngWKroCZE152t-V5Edn2Gje3CHMGqTZLwjBowEgUTpgfyTE9IaJn-q2pizukWBzjmfmdz5mYFgoIQrsjThkPxRH8cNOTit0bj6SebjsCCsPb_jdM6rek03qtwELz2ABJaHJU1FiGGTLYtcF3k32AGlRwa5P9etKwQUrz0AL5q3lroKgbtwhxY3cKyRKAo-o68s3v12_T6R86WqEegOx6TyBb06GJhTcP1MIGBMMgNIm5GxSi0U0RvRDmLuFtsuZv5wBUZqkpth8Z_dK5H003k67XjLrYC4TnMhQXxUGV6Eji3lkCY5fOWbQjwXRO9R_rPCNSiPEZj0o_-ach0a4Y5nLhzVlnb3J0plpb4lwpN3D9t9FNfizKQ5VX9eLoozrzkI-apIbV-Z0is8i6j4yt7R24PR9dyreQXZ3-e_tEwu5UTKi-zYAaHaHrRgCSjWg4d6ozuyXQmzi64d1-Fnx6IkU_KtXtUYRVsZhQUvJpri2x1szLLM-Hqdsh2Ljuu5qDdJrHRKeG1gZeKWPfvZweZ3SWrfvlNZHKNWX-2pmEvz9sJdpsAO-NnmTEUVrpzY') this.props.uploader(formData);
axios.post("http://localhost/app_dev.php/api/media",
formData,
{
headers: {
'Content-Type': `multipart/form-data;`
},
withCredentials: true
})
.then(res => console.info(res)).catch(err => console.error(err))
console.info('end send Blob')
} }
render() { render() {
@@ -104,12 +136,12 @@ class Recorder extends Component {
<div data-vjs-player> <div data-vjs-player>
<video id="myVideo" ref={node => this.videoNode = node} className="video-js vjs-default-skin" playsInline></video> <video id="myVideo" ref={node => this.videoNode = node} className="video-js vjs-default-skin" playsInline></video>
</div> </div>
<div> <div className={classes.sendContainer}>
<Button type="submit" variant="outlined" color="secondary" { this.state.canSend && <Button type="submit" variant="outlined" color="primary"
className={classes.button} className={classes.button}
onClick={this.sendBlob}> onClick={this.sendBlob}>
Send Envoyer
</Button> </Button>}
</div> </div>
</div> </div>
); );
+12 -19
View File
@@ -23,7 +23,7 @@ const useStyles = makeStyles(theme => ({
padding: theme.spacing(1.5), padding: theme.spacing(1.5),
borderRadius: '20px', borderRadius: '20px',
fontSize: '1em', fontSize: '1em',
textAlign: 'center', textAlign: 'center',
}, },
FacebookIcon: { FacebookIcon: {
backgroundColor: theme.palette.social.facebook, backgroundColor: theme.palette.social.facebook,
@@ -51,26 +51,19 @@ export default function SocialShare(props) {
return ( return (
<div className={classes.root}> <div className={classes.root}>
<Link href={"https://www.facebook.com/sharer/sharer.php?u=" + encodeURIComponent(props.url)} > <a href={"https://www.facebook.com/sharer/sharer.php?u=" + encodeURIComponent(props.url)}>
<a> <Icon className={clsx(classes.icon, classes.FacebookIcon, 'fab fa-facebook-f')} color="secondary" />
<Icon className={clsx(classes.icon, classes.FacebookIcon, 'fab fa-facebook-f')} color="secondary" /> </a>
</a> <a href={"http://twitter.com/share?url=" + encodeURIComponent(props.url)}>
</Link> <Icon className={clsx(classes.icon, classes.TwitterIcon, 'fab fa-twitter')} color="secondary" />
<Link href={"http://twitter.com/share?url=" + encodeURIComponent(props.url)} > </a>
<a> <a href={"https://www.linkedin.com/shareArticle?mini=true&url=" + encodeURIComponent(props.url + "&title=Talent's Tube")}>
<Icon className={clsx(classes.icon, classes.TwitterIcon, 'fab fa-twitter')} color="secondary" />
</a>
</Link>
<Link href={"https://www.linkedin.com/shareArticle?mini=true&url=" +encodeURIComponent( props.url + "&title=Talent's Tube")} >
<a>
<Icon className={clsx(classes.icon, classes.LinkedinIcon, 'fab fa-linkedin-in')} color="secondary" /> <Icon className={clsx(classes.icon, classes.LinkedinIcon, 'fab fa-linkedin-in')} color="secondary" />
</a> </a>
</Link> {/* change because of https://github.com/zeit/next.js/blob/master/errors/invalid-href-passed.md */}
<Link href={"mailto:?subject=Offre d'emploi Talent's Tube&body=Regardez cette offre : " + props.url} > <a href={"mailto:?subject=Offre d'emploi Talent's Tube&body=Regardez cette offre : " + props.url} >
<a>
<Icon className={clsx(classes.icon, classes.MailIcon, 'fas fa-envelope')} color="secondary" /> <Icon className={clsx(classes.icon, classes.MailIcon, 'fas fa-envelope')} color="secondary" />
</a> </a>
</Link>
</div> </div>
); );
} }
-2
View File
@@ -1,7 +1,5 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import Router from 'next/router'
import getConfig from 'next/config'
import { withStyles } from '@material-ui/core/styles'; import { withStyles } from '@material-ui/core/styles';
import Typography from '@material-ui/core/Typography'; import Typography from '@material-ui/core/Typography';
import IconText from './../atoms/IconText'; import IconText from './../atoms/IconText';
@@ -6,12 +6,9 @@ import RootContainer from '../atoms/RootContainer'
import ButtonBase from "@material-ui/core/ButtonBase"; import ButtonBase from "@material-ui/core/ButtonBase";
import ArrowLeft from '@material-ui/icons/KeyboardArrowLeft'; import ArrowLeft from '@material-ui/icons/KeyboardArrowLeft';
import HideOnScroll from '../atoms/CollapsibleBack'; import HideOnScroll from '../atoms/CollapsibleBack';
import Fragment from 'react';
import withWidth, { isWidthUp } from '@material-ui/core/withWidth' import withWidth, { isWidthUp } from '@material-ui/core/withWidth'
import Header from '../organisms/Header' import Header from '../organisms/Header'
import {AppBar,CssBaseline,Container,Toolbar,IconButton,Typography} from "@material-ui/core"; import {AppBar,CssBaseline,Container,Toolbar,IconButton,Typography} from "@material-ui/core";
import MenuIcon from "@material-ui/icons/Menu";
import Box from "@material-ui/core/Box";
import Hidden from '@material-ui/core/Hidden'; import Hidden from '@material-ui/core/Hidden';
const styles = theme => ({ const styles = theme => ({
@@ -108,8 +105,6 @@ function LayoutCompany(props) {
<Hidden mdUp> <Hidden mdUp>
<div id="F" className={classes.foot}> <div id="F" className={classes.foot}>
{/* <div className={classes.inner}>
<div className={classes.grow} /> */}
<Button <Button
variant="contained" variant="contained"
className={classes.button} className={classes.button}
@@ -117,8 +112,6 @@ function LayoutCompany(props) {
onClick={() => Router.push(`/Reponse?companyId=${companyId}`)} onClick={() => Router.push(`/Reponse?companyId=${companyId}`)}
> >
Candidature spontanée</Button> Candidature spontanée</Button>
{/* <div className={classes.grow} />
</div> */}
</div> </div>
</Hidden> </Hidden>
-2
View File
@@ -122,7 +122,6 @@ export default {
}, },
}, },
stats: { stats: {
//
countAdView: id => { countAdView: id => {
if (!!localStorage.ttJWT) if (!!localStorage.ttJWT)
setAuthorizationHeader(localStorage.ttJWT) setAuthorizationHeader(localStorage.ttJWT)
@@ -131,7 +130,6 @@ export default {
countCompanyView: id => { countCompanyView: id => {
if (!!localStorage.ttJWT) if (!!localStorage.ttJWT)
setAuthorizationHeader(localStorage.ttJWT) setAuthorizationHeader(localStorage.ttJWT)
console.log(localStorage.ttJWT)
axios.get(`api/companyAjaxRecStat/${id}`) axios.get(`api/companyAjaxRecStat/${id}`)
}, },
} }
+3 -3
View File
@@ -8,7 +8,7 @@
<lastmod>2019-09-17</lastmod> <lastmod>2019-09-17</lastmod>
</url>,<url> </url>,<url>
<loc>https://app.talentstube.com/Confidentialite</loc> <loc>https://app.talentstube.com/Confidentialite</loc>
<lastmod>2019-09-17</lastmod> <lastmod>2019-11-04</lastmod>
</url>,<url> </url>,<url>
<loc>https://app.talentstube.com/Entreprises</loc> <loc>https://app.talentstube.com/Entreprises</loc>
<lastmod>2019-09-17</lastmod> <lastmod>2019-09-17</lastmod>
@@ -20,9 +20,9 @@
<lastmod>2019-10-14</lastmod> <lastmod>2019-10-14</lastmod>
</url>,<url> </url>,<url>
<loc>https://app.talentstube.com/MentionsLegales</loc> <loc>https://app.talentstube.com/MentionsLegales</loc>
<lastmod>2019-09-17</lastmod> <lastmod>2019-11-04</lastmod>
</url>,<url> </url>,<url>
<loc>https://app.talentstube.com/Offres</loc> <loc>https://app.talentstube.com/Offres</loc>
<lastmod>2019-09-17</lastmod> <lastmod>2019-10-16</lastmod>
</url> </url>
</urlset> </urlset>
+4 -4
View File
@@ -1,5 +1,5 @@
{ {
"name": "nextjs", "name": "talentstube",
"version": "1.0.0", "version": "1.0.0",
"private": true, "private": true,
"resolutions": { "resolutions": {
@@ -62,14 +62,14 @@
"terser": "3.14", "terser": "3.14",
"universal-cookie": "^3.0.4", "universal-cookie": "^3.0.4",
"validator": "^11.0.0", "validator": "^11.0.0",
"video.js": "latest", "videojs-record": "^3.8.0",
"videojs-record": "latest",
"webrtc-adapter": "^7.2.3" "webrtc-adapter": "^7.2.3"
}, },
"scripts": { "scripts": {
"dev": "cross-env PORT=3000 node server.js", "dev": "cross-env PORT=3000 node server.js",
"build": "next build && yarn postExport && yarn copysw && yarn copySiteMap", "build": "next build && yarn postExport && yarn copysw && yarn copySiteMap",
"start": "cross-env PORT=8000 NODE_ENV=production node server.js", "start": "cross-env PORT=8000 NODE_ENV=production node server.js",
"startPreprod": "cross-env PORT=8000 NODE_ENV=preproduction node server.js",
"pm2-prod": "yarn build && pm2 start --name 'next' -- start", "pm2-prod": "yarn build && pm2 start --name 'next' -- start",
"bs": "yarn build && yarn start", "bs": "yarn build && yarn start",
"test": "yarn cypress run", "test": "yarn cypress run",
@@ -82,7 +82,7 @@
"backupdb": "docker exec -t tt-website.postgres.dev pg_dumpall --database database -c -U postgres > cypress/postgres.sql", "backupdb": "docker exec -t tt-website.postgres.dev pg_dumpall --database database -c -U postgres > cypress/postgres.sql",
"copySiteMap": "cp out/* .next/", "copySiteMap": "cp out/* .next/",
"postExport": "node src/postExport.js", "postExport": "node src/postExport.js",
"copysw": "cp -R static/js .next/static/" "copysw": "cp -R public/static/js .next/static/"
}, },
"devDependencies": { "devDependencies": {
"gmail-tester": "^1.1.3", "gmail-tester": "^1.1.3",
+10 -10
View File
@@ -57,7 +57,7 @@ class Confidentialite extends Component {
</Head> </Head>
<div className={classes.container}> <div className={classes.container}>
<Typography className={classes.text} gutterBottom align="left"> <Typography className={classes.text} gutterBottom align="left">
Nous vous invitons à lire avec attention le présent document. Pour toute question concernant ce document et, dune manière générale, sur la collecte et le traitement de vos informations personnelles par la société talentstube.com, nhésitez pas à nous contacter via le formulaire présent sur la page contact : <Link href="https://blog.talentstube.com/contact.html"><a className={classes.link} target="_blank">https://blog.talentstube.com/contact.html</a></Link> Nous vous invitons à lire avec attention le présent document. Pour toute question concernant ce document et, dune manière générale, sur la collecte et le traitement de vos informations personnelles par la société talentstube.com, nhésitez pas à nous contacter via le formulaire présent sur la page contact : <a href="https://blog.talentstube.com/contact.html" className={classes.link} target="_blank">https://blog.talentstube.com/contact.html</a>
</Typography> </Typography>
<Typography className={classes.title} component="h2" gutterBottom align="left"> <Typography className={classes.title} component="h2" gutterBottom align="left">
@@ -155,7 +155,7 @@ class Confidentialite extends Component {
` `
Vous disposez d'un droit d'accès, de rectification, de suppression, dopposition et de portabilité des données. Nous disposons dun délai de 30 jours à compter de votre demande pour apporter une réponse. Vous disposez d'un droit d'accès, de rectification, de suppression, dopposition et de portabilité des données. Nous disposons dun délai de 30 jours à compter de votre demande pour apporter une réponse.
Vous pouvez demander une limitation du traitement des données collectées. Lexercice de ces droits peut exercer ce droit auprès de TALENTS TUBE en adressant une requête soit par voie postale à l'adresse suivante : 3 Rue Louis de Broglie, Village By CA 56000 Vannes, soit par courrier électronique via le formulaire présent sur la page Contact ` Vous pouvez demander une limitation du traitement des données collectées. Lexercice de ces droits peut exercer ce droit auprès de TALENTS TUBE en adressant une requête soit par voie postale à l'adresse suivante : 3 Rue Louis de Broglie, Village By CA 56000 Vannes, soit par courrier électronique via le formulaire présent sur la page Contact `
}<Link href="https://blog.talentstube.com/contact.html"><a className={classes.link} target="_blank">https://blog.talentstube.com/contact.html</a></Link>{`. Cette requête devra être accompagnée d'une pièce d'identité revêtant la signature de l'Utilisateur et devra préciser l'adresse et le moyen par lesquelles une réponse pourra être envoyée.. }<a href="https://blog.talentstube.com/contact.html" className={classes.link} target="_blank">https://blog.talentstube.com/contact.html</a>{`. Cette requête devra être accompagnée d'une pièce d'identité revêtant la signature de l'Utilisateur et devra préciser l'adresse et le moyen par lesquelles une réponse pourra être envoyée..
` `
} }
</Typography> </Typography>
@@ -171,14 +171,14 @@ class Confidentialite extends Component {
Vous avez la possibilité de désactiver les cookies en vous rendant dans les options de votre navigateur. Cliquez sur le lien correspondant à votre navigateur pour découvrir comment faire : Vous avez la possibilité de désactiver les cookies en vous rendant dans les options de votre navigateur. Cliquez sur le lien correspondant à votre navigateur pour découvrir comment faire :
` `
} }
<Link href="https://support.google.com/chrome/answer/95647?hl=fr"><a className={classes.link} target="_blank">Google Chrome</a></Link><br /> <a className={classes.link} href="https://support.google.com/chrome/answer/95647?hl=fr" target="_blank">Google Chrome</a><br />
<Link href="https://support.mozilla.org/fr/kb/activer-desactiver-cookies"><a className={classes.link} target="_blank">Mozilla Firefox</a></Link><br /> <a href="https://support.mozilla.org/fr/kb/activer-desactiver-cookies" className={classes.link} target="_blank">Mozilla Firefox</a><br />
<Link href="http://support.apple.com/kb/PH17191?viewlocale=fr_FR&locale=en_US"><a className={classes.link} target="_blank">Safari</a></Link><br /> <a href="http://support.apple.com/kb/PH17191?viewlocale=fr_FR&locale=en_US" className={classes.link} target="_blank">Safari</a><br />
<Link href="http://help.opera.com/Windows/10.20/fr/cookies.html"><a className={classes.link} target="_blank">Opera</a></Link><br /> <a href="http://help.opera.com/Windows/10.20/fr/cookies.html" className={classes.link} target="_blank">Opera</a><br />
<Link href="http://windows.microsoft.com/fr-fr/internet-explorer/delete-manage-cookies#ie=ie-11"><a className={classes.link} target="_blank">Internet Explorer</a></Link><br /> <a href="http://windows.microsoft.com/fr-fr/internet-explorer/delete-manage-cookies#ie=ie-11" className={classes.link} target="_blank">Internet Explorer</a><br />
{
` `
Pour plus dinformations sur les cookies et la façon de les gérer, nous vous recommandons de consulter le site `} <Link href="http://www.youronlinechoices.com/fr/"><a className={classes.link} target="_blank">www.youronlinechoices.com</a></Link>{`, développé par lorganisme EDAA (European Interactive Digital Advertising Alliance). Pour plus dinformations sur les cookies et la façon de les gérer, nous vous recommandons de consulter le site `} <a href="http://www.youronlinechoices.com/fr/" className={classes.link} target="_blank">www.youronlinechoices.com</a>{`, développé par lorganisme EDAA (European Interactive Digital Advertising Alliance).
` `
} }
</Typography> </Typography>
@@ -192,7 +192,7 @@ class Confidentialite extends Component {
Ce site utilise le service danalyse web Google Analytics. Cela nous permet danalyser la façon dont les internautes utilisent notre site afin de leur proposer une meilleure expérience de navigation. Pour ce faire, Google Analytics utilise des cookies de pistage permettant de suivre le parcours dun internaute sur le site. Ces cookies sont conservés pour une durée de 26 mois. Ce site utilise le service danalyse web Google Analytics. Cela nous permet danalyser la façon dont les internautes utilisent notre site afin de leur proposer une meilleure expérience de navigation. Pour ce faire, Google Analytics utilise des cookies de pistage permettant de suivre le parcours dun internaute sur le site. Ces cookies sont conservés pour une durée de 26 mois.
Nous avons activé lanonymisation des adresses IP pour ce site. Cela signifie que les adresses IP collectées par Google Analytics sont systématiquement raccourcies pour rendre impossible lidentification des internautes. Dans certains cas exceptionnels, ladresse IP complète peut être transférée sur un serveur de Google localisé aux Etats-Unis, et est ensuite raccourcie immédiatement sur celui-ci. Google utilise les informations récoltées via les cookies pour le compte de talents tube, dans le but danalyser les habitudes de navigation des internautes et de fournir des rapports sur lactivité du site. Nous avons activé lanonymisation des adresses IP pour ce site. Cela signifie que les adresses IP collectées par Google Analytics sont systématiquement raccourcies pour rendre impossible lidentification des internautes. Dans certains cas exceptionnels, ladresse IP complète peut être transférée sur un serveur de Google localisé aux Etats-Unis, et est ensuite raccourcie immédiatement sur celui-ci. Google utilise les informations récoltées via les cookies pour le compte de talents tube, dans le but danalyser les habitudes de navigation des internautes et de fournir des rapports sur lactivité du site.
Google met à disposition des utilisateurs un plug-in pour leur navigateur leur permettant dempêcher la récolte de données relatives à leur navigation sur les sites web utilisant Google Analytics. Google met à disposition des utilisateurs un plug-in pour leur navigateur leur permettant dempêcher la récolte de données relatives à leur navigation sur les sites web utilisant Google Analytics.
Ce plug-in est disponible à cette adresse : `} <Link href="https://tools.google.com/dlpage/gaoptout?hl=fr"><a className={classes.link} target="_blank">tools.google.com/dlpage/gaoptout</a></Link> {` Ce plug-in est disponible à cette adresse : `} <a href="https://tools.google.com/dlpage/gaoptout?hl=fr" className={classes.link} target="_blank">tools.google.com/dlpage/gaoptout</a>{`
` `
} }
</Typography> </Typography>
+5 -6
View File
@@ -456,11 +456,10 @@ class Entreprise extends React.Component {
: '' : ''
} }
{(company.website) ? {(company.website) ?
(<Link href={company.website} > (
<a className={classes.websiteLink} rel="noopener" target="_blank" rel="noopener"> <a href={company.website} className={classes.websiteLink} rel="noopener" target="_blank" rel="noopener">
<IconText classes={{ root: classes.iconText, icon: classes.iconTextIcon, text: classes.iconTextText }} variant="business_center" text={!!company.website ? company.website : "website"} /> <IconText classes={{ root: classes.iconText, icon: classes.iconTextIcon, text: classes.iconTextText }} variant="business_center" text={!!company.website ? company.website : "website"} />
</a> </a>
</Link>
) )
: '' : ''
} }
@@ -476,9 +475,9 @@ class Entreprise extends React.Component {
<section className={classes.IconTextContainerDesktop}> <section className={classes.IconTextContainerDesktop}>
<IconTextInline classes={{ icon: classes.iconTextIcon, text: classes.iconTextText }} variant="location_on" text={company.addresses.billing.city} /> <IconTextInline classes={{ icon: classes.iconTextIcon, text: classes.iconTextText }} variant="location_on" text={company.addresses.billing.city} />
{(company.website) ? {(company.website) ?
(<Link href={!!company.website ? company.website : "website"} > (
<a target="_blank" rel="noopener" className={classes.websiteLink}><IconTextInline classes={{ icon: classes.iconTextIcon, text: classes.iconTextText }} variant="business_center" text={!!company.website ? company.website : "website"} /></a> <a href={!!company.website ? company.website : "website"} target="_blank" rel="noopener" className={classes.websiteLink}><IconTextInline classes={{ icon: classes.iconTextIcon, text: classes.iconTextText }} variant="business_center" text={!!company.website ? company.website : "website"} /></a>
</Link>) )
: '' : ''
} }
+2 -2
View File
@@ -75,7 +75,7 @@ class MentionsLegales extends Component {
{ {
` `
TALENTS TUBE est joignable : TALENTS TUBE est joignable :
- Par internet : via le formulaire de contact sur le site ` }<Link href="http://blog.talentstube.com"><a className={classes.link} target="_blank">blog.talentstube.com</a></Link>{`; - Par internet : via le formulaire de contact sur le site ` }<a href="http://blog.talentstube.com" className={classes.link} target="_blank">blog.talentstube.com</a>{`;
- Par téléphone au 02 30 05 06 31, du lundi au vendredi de 9 h à 18 h; - Par téléphone au 02 30 05 06 31, du lundi au vendredi de 9 h à 18 h;
- Par voie postale : - Par voie postale :
TALENTS TUBE TALENTS TUBE
@@ -90,7 +90,7 @@ class MentionsLegales extends Component {
</Typography> </Typography>
<Typography className={classes.text} gutterBottom align="center"> <Typography className={classes.text} gutterBottom align="center">
<Link href="https://www.e-declic.com/"><a className={classes.link} target="_blank">e-declic</a></Link> <a href="https://www.e-declic.com/" className={classes.link} target="_blank">e-declic</a>
{ {
` `
27 Rue du Danemark - Porte océane 2 27 Rue du Danemark - Porte océane 2
+2 -2
View File
@@ -62,8 +62,8 @@ const styles = theme => ({
}, },
}) })
//TODO: put in config // //TODO: put in config
const applicationServerPublicKey = 'BNFyiyPiLH97Dgc0m1vXluUNaCN6y3Hkgd4YcqS2lVkP8my3tq2D5gM5g7cY6R4VxC7GljSzkLRu+k+oO+2TtjU='; // const applicationServerPublicKey = 'BNFyiyPiLH97Dgc0m1vXluUNaCN6y3Hkgd4YcqS2lVkP8my3tq2D5gM5g7cY6R4VxC7GljSzkLRu+k+oO+2TtjU=';
class Parametres extends Component { class Parametres extends Component {
+56 -58
View File
@@ -22,6 +22,9 @@ import KeyboardArrowRightIcon from '@material-ui/icons/KeyboardArrowRight';
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown'; import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
import Router from 'next/router' import Router from 'next/router'
import { errorMessageSelector } from '../reducers/media' import { errorMessageSelector } from '../reducers/media'
import dynamic from 'next/dynamic'
// import Recorder from '../components/organisms/Recorder'
const styles = theme => ({ const styles = theme => ({
root: { root: {
@@ -82,11 +85,17 @@ const styles = theme => ({
border: 'solid 5px white', border: 'solid 5px white',
borderRadius: '6px', borderRadius: '6px',
}, },
recorderContainer: {
//display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
},
helpContainer: { helpContainer: {
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
width: '100%', width: '400px',
}, },
logo: { logo: {
width: 'inherit', width: 'inherit',
@@ -191,35 +200,12 @@ const styles = theme => ({
}, },
}); });
const videoJsOptions = {
controls: true,
// width: 800,
// height: 600,
fluid: true,
plugins: {
/*
// wavesurfer section is only needed when recording audio-only
wavesurfer: {
src: 'live',
waveColor: '#36393b',
progressColor: 'black',
debug: true,
cursorWidth: 1,
msDisplayMax: 20,
hideScrollbar: true
},
*/
record: {
audio: true,
video: true,
// maxLength: 10,
debug: true
}
}
};
const steps = ["", ""] const steps = ["", ""]
const Recorder = dynamic(() => import('../components/organisms/Recorder'), {
ssr: false
})
const { publicRuntimeConfig } = getConfig() const { publicRuntimeConfig } = getConfig()
class Reponse extends React.Component { class Reponse extends React.Component {
state = { state = {
@@ -299,11 +285,15 @@ class Reponse extends React.Component {
<link rel="canonical" href="https://app.talentstube.com" /> <link rel="canonical" href="https://app.talentstube.com" />
</Head> </Head>
{/* https://codesandbox.io/s/ii0us */} {/* https://codesandbox.io/s/ii0us */}
{ loading ? <Loader /> : { loading ?
<Loader /> :
<Fragment> <Fragment>
<section className={classes.headerContainer}> <section className={classes.headerContainer}>
{ !!offre.company &&(<Fragment><div className={classes.logoContainer}> { !!offre.company && (
<Fragment>
<div className={classes.logoContainer}>
<Avatar className={classes.logo} classes={{ img: classes.MuiAvatarImg }} src={logoUrl} alt="companylogo"/> <Avatar className={classes.logo} classes={{ img: classes.MuiAvatarImg }} src={logoUrl} alt="companylogo"/>
</div> </div>
<div className={classes.infoContainer}> <div className={classes.infoContainer}>
@@ -314,7 +304,8 @@ class Reponse extends React.Component {
{!!offre.company.brand_name? offre.company.brand_name: ''} {!!offre.company.brand_name? offre.company.brand_name: ''}
</Typography> </Typography>
{/* ville */} {/* ville */}
</div></Fragment>) </div>
</Fragment>)
} }
{ !!company.brand_name && (<Fragment><div className={classes.logoContainer}> { !!company.brand_name && (<Fragment><div className={classes.logoContainer}>
<Avatar className={classes.logo} classes={{ img: classes.MuiAvatarImg }} src={logoCompanyUrl} alt="companylogo"/> <Avatar className={classes.logo} classes={{ img: classes.MuiAvatarImg }} src={logoCompanyUrl} alt="companylogo"/>
@@ -342,7 +333,8 @@ class Reponse extends React.Component {
})} })}
</Stepper> </Stepper>
{loading ? ( <Loader />) {loading ? ( <Loader />)
: activeStep === 0 ? ( : activeStep === 0 ?
(
<div className={classes.root}> <div className={classes.root}>
<div className={classes.textContainer}> <div className={classes.textContainer}>
@@ -362,25 +354,35 @@ class Reponse extends React.Component {
<KeyboardArrowRightIcon className={ classes.HelpKeyboardArrowRightIcon }/> <KeyboardArrowRightIcon className={ classes.HelpKeyboardArrowRightIcon }/>
</Button> </Button>
</div> </div>
{ /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ?
<input (
type="file" accept="video/*" capture="camcorder" <Fragment>
className={classes.input} <input
style={{ display: 'none' }} type="file" accept="video/*" capture="camcorder"
id="record-button-file" className={classes.input}
multiple style={{ display: 'none' }}
onChange={this.inputCamRecorderChange} id="record-button-file"
/> multiple
<label htmlFor="record-button-file"> onChange={this.inputCamRecorderChange}
<Button component="span" className={classes.captureButton} classes={{ root: classes.rootButton }}> />
<img alt="talents-tube" src='/static/images/capture.svg' className={classes.iconButton} /> <label htmlFor="record-button-file">
<Typography align="left" className={classes.textButton}> <Button component="span" className={classes.captureButton} classes={{ root: classes.rootButton }}>
Je <span className={classes.underlined}>réalise</span> ma vidéo de réponse <img alt="talents-tube" src='/static/images/capture.svg' className={classes.iconButton} />
</Typography> <Typography align="left" className={classes.textButton}>
<KeyboardArrowRightIcon className={ classes.InputKeyboardArrowRightIcon }/> Je <span className={classes.underlined}>réalise</span> ma vidéo de réponse
</Button> </Typography>
</label> <KeyboardArrowRightIcon className={ classes.InputKeyboardArrowRightIcon }/>
</Button>
</label>
</Fragment>
):
(
<div className={classes.recorderContainer}>
<Recorder uploader={this.props.uploadMedia} />
</div>
)
}
<input <input
type="file" type="file"
accept="video/*" accept="video/*"
@@ -399,9 +401,8 @@ class Reponse extends React.Component {
<KeyboardArrowDownIcon className={ classes. InputKeyboardArrowDownIcon }/> <KeyboardArrowDownIcon className={ classes. InputKeyboardArrowDownIcon }/>
</Button> </Button>
</label> </label>
</div> </div>
) : ) :
( (
<Answer mediaId={!!this.props.media && this.props.media.id} <Answer mediaId={!!this.props.media && this.props.media.id}
@@ -424,12 +425,9 @@ Reponse.getInitialProps = function (context) {
const { adId, companyId } = context.query const { adId, companyId } = context.query
const {res} = context const {res} = context
// if (!!!context.store.user.fetched) { //TODO :really needed ?
context.store.dispatch(fetchCurrentUserRequest()) context.store.dispatch(fetchCurrentUserRequest())
// }else{
// if (!!!context.store.getState().user.fetched) {
// redirect({Router:Router, ctx:context, location:'/Login'})
// }
if(!!adId) if(!!adId)
context.store.dispatch(fetchAdRequest(adId)) context.store.dispatch(fetchAdRequest(adId))
else if(!!companyId) else if(!!companyId)

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Before

Width:  |  Height:  |  Size: 755 B

After

Width:  |  Height:  |  Size: 755 B

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Before

Width:  |  Height:  |  Size: 254 KiB

After

Width:  |  Height:  |  Size: 254 KiB

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Before

Width:  |  Height:  |  Size: 370 B

After

Width:  |  Height:  |  Size: 370 B

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

Before

Width:  |  Height:  |  Size: 709 B

After

Width:  |  Height:  |  Size: 709 B

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 83 KiB

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 93 KiB

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 127 KiB

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

+3 -2
View File
@@ -181,19 +181,20 @@ export function user(state = {
return { return {
...state, ...state,
loading: false, loading: false,
pushSubscribed: true isUserSubscribedToPush: true
} }
case SUBSCRIBE_USER_TO_PUSH_FAILURE: case SUBSCRIBE_USER_TO_PUSH_FAILURE:
return { return {
...state, ...state,
loading: false, loading: false,
pushSubscribed: false, isUserSubscribedToPush: false,
errors: action.err, errors: action.err,
} }
case FETCH_USER_SUBSCRIPTION_TO_PUSH_REQUEST: case FETCH_USER_SUBSCRIPTION_TO_PUSH_REQUEST:
return { return {
...state, ...state,
loading: true, loading: true,
isUserSubscribedToPush: false,
} }
case FETCH_USER_SUBSCRIPTION_TO_PUSH_SUCCESS: case FETCH_USER_SUBSCRIPTION_TO_PUSH_SUCCESS:
return { return {
+1 -2
View File
@@ -258,9 +258,8 @@ export function* requestUpdateUserRequestSaga(action) {
yield put(updateUserPictureFailure()); yield put(updateUserPictureFailure());
} catch (err) { } catch (err) {
console.log(err);
if (_.includes(err, "401") || (!!err.response && err.response.status === 401)) { if (_.includes(err, "401") || (!!err.response && err.response.status === 401)) {
localStorage.setItem('loginRedirect', window.location) localStorage.setItem('loginRedirect', window.location)
Router.push("/Login"); Router.push("/Login");
} }
-12331
View File
File diff suppressed because it is too large Load Diff
+18 -11
View File
@@ -20,7 +20,6 @@ const { ANALYZE, DEV } = process.env
}); });
module.exports = withPlugins( module.exports = withPlugins(
[ [
[{target: 'serverless'}],
[withCSS], [withCSS],
[optimizedImages, { [optimizedImages, {
/* config for next-optimized-images */ /* config for next-optimized-images */
@@ -68,18 +67,26 @@ module.exports = withPlugins(
staticFolder: '/static', staticFolder: '/static',
push: { push: {
'defaultAction': 'https://application.bzh/', 'defaultAction': 'https://application.bzh/',
'defaultIconLink': 'https://application.bzh/static/images/icons/talentstubeIco152x152.png', 'defaultIconLink': 'https://application.bzh/static/images/icons/e-declicIco152x152.png',
'defaultImageLink': 'https://application.bzh/static/images/banner/atc-site-web-responsive.jpg', 'defaultImageLink': 'https://application.bzh/static/images/banner/atc-site-web-responsive.jpg',
'topics': [ 'topics': [
{ key: 'e-declic', value: false }, { key: 'e-declic', value: false },
{ key: 'PWA', value: false } { key: 'PWA', value: false }
] ]
}, },
wordpressUrl: {
'menu': 'https://api.e-declic.net/wp-json/menus/v1/menus/top',
'posts': 'https://api.e-declic.net/wp-json/wp/v2/posts',
'postDetail': 'https://api.e-declic.net/wp-json/wp/v2/posts',
'pageDetail': 'https://api.e-declic.net/wp-json/wp/v2/pages',
'categories': 'https://api.e-declic.net/wp-json/wp/v2/categories',
'media': 'https://api.e-declic.net/wp-json/wp/v2/media'
},
ReCAPTCHA: { ReCAPTCHA: {
"siteKey": "6LdyqLwUAAAAADKI5uC7d5W9VqVgzd8VEmMU2Yi-" "siteKey": "6LcCvHcUAAAAAEw2gBZkoJcVvsNp1IgU4MnrIaRI"
}, },
eDeclicUrl: 'http://www.e-declic.com', eDeclicUrl: 'http://www.e-declic.com',
enableVideo: DEV ? false : true
} }
}] }]
@@ -112,14 +119,14 @@ module.exports = withPlugins(
config.resolve.alias = { ...config.resolve.alias, ...videojsAlias }; config.resolve.alias = { ...config.resolve.alias, ...videojsAlias };
config.plugins.push(videojsPlugin); config.plugins.push(videojsPlugin);
config.module.rules.push( // config.module.rules.push(
{ // {
test: /\.css$/, // test: /\.css$/,
loader: 'style-loader!css-loader', // loader: 'style-loader!css-loader',
// include: [/node_modules/] // // include: [/node_modules/]
}, // },
) // )
console.log(config); console.log(config);
return config return config