Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0eed896aec | |||
| e8ae224414 | |||
| fa3dcd8fd2 | |||
| 2c0c0a2632 | |||
| 501ee57430 | |||
| 0f6ec17fef | |||
| 112541275b | |||
| e08b879691 | |||
| 527351c232 | |||
| 0ed8da11e1 | |||
| f522e4389e | |||
| efb6527b9b | |||
| ba43bcddc7 | |||
| 3523cc95ee | |||
| c0d32cee12 | |||
| 3b6aa331db | |||
| fe7932e5ae | |||
| 05b64ac44c | |||
| 446e13ceba | |||
| 6570e28bbd | |||
| d146da7ab3 | |||
| ae06e730ad | |||
| f386b93dd2 | |||
| cebdf4d1d2 | |||
| e6738a1565 | |||
| ce9b8b6031 | |||
| 00eac45913 | |||
| 89719a8bbc |
@@ -5,7 +5,7 @@
|
||||
Download the example [or clone the repo](https://git.e-declic.net/talents-tube/app.git):
|
||||
|
||||
```bash
|
||||
git clone
|
||||
git clone
|
||||
```
|
||||
|
||||
Install it and run:
|
||||
@@ -27,10 +27,11 @@ https://redux-saga.js.org/docs/basics/ErrorHandling.html
|
||||
is a library that aims to make application side effect asynchronous things like data fetching and impure things like accessing the browser cache
|
||||
|
||||
## Integration
|
||||
### Naming conventions
|
||||
style classes name syntax : Camel case
|
||||
Try to name without too much precision
|
||||
|
||||
### Naming conventions
|
||||
|
||||
style classes name syntax : Camel case
|
||||
Try to name without too much precision
|
||||
|
||||
### Material UI
|
||||
|
||||
@@ -52,16 +53,16 @@ sudo docker exec -it frontnginx.nginx bash
|
||||
nginx -t && nginx -s reload
|
||||
|
||||
## Test
|
||||
|
||||
### Cypress
|
||||
|
||||
[Gmail-tester]
|
||||
https://github.com/levz0r/gmail-tester
|
||||
|
||||
## Continuous Integration
|
||||
|
||||
### Jenkins
|
||||
|
||||
>in case of emergency
|
||||
make docker-restart ENV=dev
|
||||
|
||||
adduser jenkins root
|
||||
|
||||
> in case of emergency
|
||||
> make docker-restart ENV=dev
|
||||
> adduser jenkins root
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import {
|
||||
UPLOAD_MEDIA_REQUEST,
|
||||
UPLOAD_MEDIA_FAILURE,
|
||||
UPLOAD_MEDIA_SUCCESS
|
||||
UPLOAD_MEDIA_SUCCESS,
|
||||
UPLOAD_MEDIA_PRES_REQUEST,
|
||||
UPLOAD_MEDIA_PRES_FAILURE,
|
||||
UPLOAD_MEDIA_PRES_SUCCESS,
|
||||
UPLOAD_MEDIA_CV_REQUEST,
|
||||
UPLOAD_MEDIA_CV_FAILURE,
|
||||
UPLOAD_MEDIA_CV_SUCCESS,
|
||||
|
||||
} from "../types";
|
||||
|
||||
export const uploadMedia = payload => ({
|
||||
@@ -18,6 +25,35 @@ import {
|
||||
type: UPLOAD_MEDIA_SUCCESS,
|
||||
res
|
||||
});
|
||||
|
||||
export const uploadMediaPres = payload => ({
|
||||
type: UPLOAD_MEDIA_PRES_REQUEST,
|
||||
payload
|
||||
});
|
||||
|
||||
export const uploadMediaPresFailure = errors => ({
|
||||
type: UPLOAD_MEDIA_PRES_FAILURE,
|
||||
errors
|
||||
});
|
||||
|
||||
|
||||
export const uploadMediaPresSuccess = res => ({
|
||||
type: UPLOAD_MEDIA_PRES_SUCCESS,
|
||||
res
|
||||
});
|
||||
|
||||
export const uploadMediaCv = payload => ({
|
||||
type: UPLOAD_MEDIA_CV_REQUEST,
|
||||
payload
|
||||
});
|
||||
|
||||
export const uploadMediaCvFailure = errors => ({
|
||||
type: UPLOAD_MEDIA_CV_FAILURE,
|
||||
errors
|
||||
});
|
||||
|
||||
export const uploadMediaCvSuccess = res => ({
|
||||
type: UPLOAD_MEDIA_CV_SUCCESS,
|
||||
res
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import React from 'react'
|
||||
import { JobPostingJsonLd } from 'next-seo';
|
||||
|
||||
const JobPosting = props => {
|
||||
return (
|
||||
|
||||
<JobPostingJsonLd
|
||||
datePosted="2020-01-06T03:37:40Z"
|
||||
description={props.job_description}
|
||||
hiringOrganization={{
|
||||
name: props.job_brand,
|
||||
sameAs: props.job_brand_link,
|
||||
}}
|
||||
jobLocation={{
|
||||
addressLocality: props.job_location,
|
||||
|
||||
}}
|
||||
title={props.job_title}
|
||||
validThrough="2020-01-06"
|
||||
applicantLocationRequirements="FR"
|
||||
/>
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
JobPosting.propTypes = {
|
||||
// seo_title: PropTypes.string.isRequired,
|
||||
// seo_description: PropTypes.string.isRequired,
|
||||
// seo_url: PropTypes.string.isRequired,
|
||||
// image: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
export default JobPosting
|
||||
@@ -6,8 +6,9 @@ const OgHead = props => {
|
||||
return (
|
||||
<Head>
|
||||
<title key="title">{props.seo_title}</title>
|
||||
<meta name="description" key="description" content={props.seo_description} />
|
||||
|
||||
<meta name="robots" content="noindex, nofollow"></meta>
|
||||
<meta name="description" kenoindexy="description" content={props.seo_title} />
|
||||
<meta name="keywords" content={props.seo_key}/>
|
||||
<meta key="og:url" property="og:url" content={props.seo_url} />
|
||||
<meta key="og:type" property="og:type" content="article" />
|
||||
<meta key="og:title" property="og:title" content={props.seo_title} />
|
||||
@@ -16,10 +17,16 @@ const OgHead = props => {
|
||||
property="og:description"
|
||||
content={props.seo_description}
|
||||
/>
|
||||
<meta name="keywords" content={props.seo_key}/>
|
||||
<meta key="og:image" property="og:image" content={props.image} />
|
||||
|
||||
<link rel="canonical" href={"https://www.application.bzh/" + props.seo_url} />
|
||||
<meta name="twitter:card" content="summary"/>
|
||||
<meta name="twitter:site" content="@TalentsTube"/>
|
||||
<meta name="twitter:title" content={props.seo_title}/>
|
||||
<meta name="twitter:description" content={props.seo_title}/>
|
||||
<meta name="twitter:image" content={props.image}/>
|
||||
<link rel="canonical" href={ props.seo_url} />
|
||||
</Head>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,32 @@ const useStyles = makeStyles(theme => ({
|
||||
height: '100%',
|
||||
},
|
||||
},
|
||||
},
|
||||
videoPresentation: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
position: 'relative',
|
||||
paddingBottom: '56%', /* 16:9 58%*/
|
||||
'& iframe': {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 'calc(50% - 50vw)',
|
||||
width: '100vw',
|
||||
height: '100%',
|
||||
},
|
||||
[theme.breakpoints.up('md')]: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
position: 'relative',
|
||||
paddingBottom: '56.5%', /* 16:9 */
|
||||
'& iframe': {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 'calc(50% - 32vw)',
|
||||
width: '64vw',
|
||||
height: '100%',
|
||||
},
|
||||
},
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -37,14 +63,20 @@ export default function VideoVimeo(props) {
|
||||
|
||||
const {videoId, title, options, classesOverride, autoplay} = props;
|
||||
const classes = useStyles();
|
||||
|
||||
let className = classes.video;
|
||||
if (classesOverride) {
|
||||
className = classes.videoPresentation;
|
||||
}
|
||||
|
||||
return (
|
||||
<section className={classes.video +' '+classesOverride}>
|
||||
|
||||
<section className={className +' '+classesOverride}>
|
||||
<iframe className='player'
|
||||
src={"https://player.vimeo.com/video/"+ videoId + options+"?autoplay="+autoplay}
|
||||
frameBorder="0"
|
||||
title={title}
|
||||
webkitallowfullscreen="true" mozallowfullscreen="true" allowFullScreen></iframe>
|
||||
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,14 +2,13 @@ import React, { Component, Fragment } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from "react-redux";
|
||||
import { subscribeUserToPushRequest } from '../../actions/user'
|
||||
import getConfig from 'next/config'
|
||||
|
||||
|
||||
import { urlB64ToUint8Array, payloadFromSubscription } from './Utility'
|
||||
|
||||
var swRegistration = null
|
||||
|
||||
//TODO: put in config
|
||||
const applicationServerPublicKey = 'BNFyiyPiLH97Dgc0m1vXluUNaCN6y3Hkgd4YcqS2lVkP8my3tq2D5gM5g7cY6R4VxC7GljSzkLRu+k+oO+2TtjU=';
|
||||
|
||||
const WebPushContext = React.createContext()
|
||||
|
||||
function WebPushConsumer(props) {
|
||||
@@ -26,6 +25,8 @@ function WebPushConsumer(props) {
|
||||
</WebPushContext.Consumer>
|
||||
)
|
||||
}
|
||||
|
||||
const { publicRuntimeConfig } = getConfig()
|
||||
class WebPush extends Component {
|
||||
static Consumer = WebPushConsumer;
|
||||
|
||||
@@ -91,7 +92,7 @@ class WebPush extends Component {
|
||||
if (isSubscribed) {
|
||||
this.onUpdateSubscriptionOnServer(subscription)
|
||||
} else {
|
||||
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey)
|
||||
const applicationServerKey = urlB64ToUint8Array(publicRuntimeConfig.applicationServerPublicKey)
|
||||
swRegistration.pushManager.subscribe({
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: applicationServerKey
|
||||
|
||||
@@ -0,0 +1,478 @@
|
||||
import React, { useState, Component, Fragment } from 'react'
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import TextField from '@material-ui/core/TextField';
|
||||
import { Alert, AlertTitle } from '@material-ui/lab';
|
||||
import Snackbar from '@material-ui/core/Snackbar';
|
||||
import { connect } from 'react-redux'
|
||||
import { updateUserRequest } from '../../actions/user'
|
||||
import getConfig from 'next/config'
|
||||
import Validator from "validator";
|
||||
import ReactHtmlParser, { processNodes, convertNodeToElement, htmlparser2 } from 'react-html-parser';
|
||||
|
||||
|
||||
const styles = theme => ({
|
||||
container: {
|
||||
width: '85%',
|
||||
},
|
||||
form: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: '24px',
|
||||
paddingBottom: theme.spacing(8),
|
||||
marginBottom: theme.spacing(8),
|
||||
'&>div': {
|
||||
marginTop: theme.spacing(1.5),
|
||||
marginBottom: theme.spacing(1.5),
|
||||
}
|
||||
|
||||
},
|
||||
textField: {
|
||||
width: '85%',
|
||||
'&:disabled': {
|
||||
color: theme.palette.secondary.dark,
|
||||
},
|
||||
'& label': {
|
||||
color: theme.palette.primary.dark,
|
||||
},
|
||||
'& fieldset:hover': {
|
||||
borderColor: theme.palette.primary.main + ' !important',
|
||||
},
|
||||
},
|
||||
textFieldSmall: {
|
||||
width: '32%',
|
||||
'&:disabled': {
|
||||
color: theme.palette.secondary.dark,
|
||||
},
|
||||
'& label': {
|
||||
color: theme.palette.primary.dark,
|
||||
},
|
||||
'& fieldset:hover': {
|
||||
borderColor: theme.palette.primary.main + ' !important',
|
||||
},
|
||||
padding: '5px',
|
||||
},
|
||||
});
|
||||
|
||||
const { publicRuntimeConfig } = getConfig();
|
||||
|
||||
//https://xd.adobe.com/view/ba98331a-9145-4d67-7e27-25a36e519ef4-cca9/screen/a96779d7-bdb3-410a-8f19-e6987acb98ee/Candidature-Step-3
|
||||
class Accountdetails extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
// This binding is necessary to make `this` work in the callback
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.handleClose = this.handleClose.bind(this);
|
||||
this.onBlur = this.onBlur.bind(this)
|
||||
this.onSubmit = this.onSubmit.bind(this);
|
||||
}
|
||||
|
||||
state = {
|
||||
file: null,
|
||||
firstname: '',
|
||||
lastname: '',
|
||||
email:'',
|
||||
phone: '',
|
||||
currentJob: '',
|
||||
address1:'',
|
||||
address2 : '',
|
||||
zipCode : '',
|
||||
city : '',
|
||||
country : '',
|
||||
linkedin: '',
|
||||
twitter: '',
|
||||
website: '',
|
||||
mediaId: null,
|
||||
companyId: null,
|
||||
|
||||
};
|
||||
|
||||
handleChange = (e) => {
|
||||
this.setState({ [e.target.name]: e.target.value });
|
||||
|
||||
//console.log(this.refs.myTextField.input.value);
|
||||
//this.soumettre(e);
|
||||
|
||||
}
|
||||
|
||||
handleClose = (e, reason) => {
|
||||
|
||||
if (reason === 'clickaway') {
|
||||
return;
|
||||
}
|
||||
|
||||
//setOpen(false);
|
||||
};
|
||||
|
||||
onBlur(e) {
|
||||
console.log("blur")
|
||||
this.setState({ [e.target.name]: e.target.value });
|
||||
this.soumettre();
|
||||
}
|
||||
|
||||
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
this.setState({
|
||||
firstname: nextProps.user.firstname,
|
||||
lastname: nextProps.user.lastname,
|
||||
phone: nextProps.user.phone,
|
||||
email: nextProps.user.email,
|
||||
currentJob: nextProps.user.currentJob,
|
||||
address1 : nextProps.user.address1,
|
||||
address2 : nextProps.user.address2,
|
||||
zipCode : nextProps.user.zipCode,
|
||||
city : nextProps.user.city,
|
||||
country : nextProps.user.country,
|
||||
linkedin: nextProps.user.linkedin,
|
||||
twitter: nextProps.user.twitter,
|
||||
website: nextProps.user.website,
|
||||
companyId: nextProps.companyId,
|
||||
errors: !!!nextProps.errors ? { errors: { message: "" } } : nextProps.errors,
|
||||
})
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setState({
|
||||
firstname: this.props.user.firstname,
|
||||
lastname: this.props.user.lastname,
|
||||
phone: this.props.user.phone,
|
||||
email: this.props.user.email,
|
||||
address1: this.props.user.address1,
|
||||
address2 : this.props.user.address2,
|
||||
zipCode : this.props.user.zipCode,
|
||||
city : this.props.user.city,
|
||||
country : this.props.user.country,
|
||||
currentJob: this.props.user.currentJob,
|
||||
linkedin: this.props.user.linkedin,
|
||||
twitter: this.props.user.twitter,
|
||||
website: this.props.user.website,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
onSubmit = (e) => {
|
||||
|
||||
e.preventDefault();
|
||||
this.soumettre(e);
|
||||
|
||||
}
|
||||
soumettre(e){
|
||||
|
||||
const errors = this.validate(this.state);
|
||||
const success = {};
|
||||
this.setState({ errors });
|
||||
if (!this.state.errors || !this.state.errors.message){
|
||||
|
||||
success.message ="Profil mis à jour";
|
||||
this.setState({ success });
|
||||
const data = new FormData()
|
||||
data.append('firstname', this.state.firstname)
|
||||
data.append('lastname', this.state.lastname)
|
||||
data.append('phone', this.state.phone)
|
||||
//data.append('email', this.state.email)
|
||||
data.append('currentJob', this.state.currentJob)
|
||||
data.append('address1', this.state.address1)
|
||||
data.append('address2', this.state.address2)
|
||||
data.append('zipCode', this.state.zipCode)
|
||||
data.append('city', this.state.city)
|
||||
data.append('country', this.state.country)
|
||||
data.append('linkedin', this.state.linkedin)
|
||||
data.append('twitter', this.state.twitter)
|
||||
data.append('website', this.state.website)
|
||||
|
||||
//TODO:maybe add this two in a single transactionnal saga
|
||||
this.props.updateUserRequest(data)
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
validate = data => {
|
||||
const errors = {};
|
||||
errors.message ="";
|
||||
//if (!Validator.isEmail(data.currentJob)) errors.message += "Le poste actuel doit etre un email\n";
|
||||
if (!data.firstname || data.firstname==="") errors.message += "Veuillez saisir votre prénom<br />";
|
||||
if (!data.lastname || data.lastname==="") errors.message += " Veuillez saisir saisir votre nom<br />";
|
||||
if (!data.phone || data.phone==="") errors.message += "Veuillez saisir un numéro de téléphone valide<br />";
|
||||
if (!data.currentJob || data.currentJob==="") errors.message += "Veuillez saisir votre intitulé de poste actuel ou poste recherché<br />";
|
||||
if ((data.zipCode && data.zipCode!="") && !Validator.isPostalCode(data.zipCode, "FR")) errors.message += "Le code postal n'est pas correct<br />";
|
||||
if ((data.website && data.website!="") && !Validator.isURL(data.website)) errors.message += " Veuillez ajouter un site internet avec une url valide<br />";
|
||||
if (!Validator.isMobilePhone(data.phone, "fr-FR") && !Validator.isNumeric(data.phone, "fr-FR")) errors.message += "Le téléphone n'est pas correct<br />";
|
||||
//console.log(errors.email);
|
||||
|
||||
return errors;
|
||||
};
|
||||
AfficherErreurs() {
|
||||
if (!this.state.errors || !this.state.errors.message){
|
||||
return "";
|
||||
}else if (this.state.errors.length != 0 && this.state.errors.message!="") {
|
||||
return (
|
||||
<Alert severity="error">
|
||||
{ ReactHtmlParser(this.state.errors.message)}
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
AfficherSuccess() {
|
||||
if (this.state.success && this.state.success.length != 0 && this.state.success.message != "") {
|
||||
return (
|
||||
<Snackbar open={open} autoHideDuration={1000} onClose={() => this.setState({open: false})}>
|
||||
<Alert onClose={() => this.setState({open: false})} severity="success">
|
||||
{ReactHtmlParser(this.state.success.message)}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
inputFilesystemChange = (e) => {
|
||||
|
||||
console.log("inputFilesystemChange");
|
||||
var file = e.target.files[0]
|
||||
this.setState({ picture: file })
|
||||
|
||||
const data = new FormData()
|
||||
data.append('file', file)
|
||||
this.props.updateUserPictureRequest(data)
|
||||
}
|
||||
|
||||
render() {
|
||||
const { classes, user } = this.props
|
||||
const logoUrl = user.picture;
|
||||
return (
|
||||
<section className={classes.container}>
|
||||
<form className={classes.form}
|
||||
autoComplete="off" focused="true" name="monForm" ref="formToSubmit">
|
||||
{/* {!!logoUrl && <Avatar className={classes.logo}
|
||||
classes={{ img: classes.MuiAvatarImg }}
|
||||
src={publicRuntimeConfig.symphonyUrl + publicRuntimeConfig.postedContentUrl + logoUrl} alt="candidatLogo" />} */}
|
||||
|
||||
{/* {!!user.pictureLoading && <Loader />}
|
||||
{!!!user.pictureLoading && !!!logoUrl &&
|
||||
(<Fragment><input
|
||||
type="file" accept="image/*" capture="filesystem"
|
||||
className={classes.input}
|
||||
style={{ display: 'none' }}
|
||||
id="raised-button-file"
|
||||
multiple
|
||||
type="file"
|
||||
onChange={this.inputFilesystemChange}
|
||||
/>
|
||||
<label htmlFor="raised-button-file">
|
||||
<Button component="span" className={classes.importButton} classes={{ root: classes.rootButton }}>
|
||||
<img alt="talents-tube" src='/static/images/default/account-avatar-default.svg'
|
||||
className={classes.iconButton} />
|
||||
<Typography align="left" className={classes.textButton}>
|
||||
J'<span className={classes.underlined}>importe</span> ma photo de profil
|
||||
</Typography>
|
||||
<KeyboardArrowRightIcon className={classes.InputKeyboardArrowRightIcon} />
|
||||
</Button>
|
||||
</label></Fragment>)
|
||||
} */}
|
||||
{this.AfficherErreurs()}
|
||||
{this.AfficherSuccess()}
|
||||
|
||||
|
||||
<TextField
|
||||
name="firstname"
|
||||
required
|
||||
id="outlined-required"
|
||||
label="Prénom"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
value={this.state.firstname}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="lastname"
|
||||
required
|
||||
id="outlined-required"
|
||||
label="Nom"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
value={this.state.lastname}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
disabled
|
||||
name="email"
|
||||
id="outlined"
|
||||
label="E-mail"
|
||||
required
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
value={this.state.email}
|
||||
onChange={this.handleChange}
|
||||
type="mail"
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="phone"
|
||||
id="outlined"
|
||||
label="Téléphone"
|
||||
required
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
value={this.state.phone ? this.state.phone: ''}
|
||||
onChange={this.handleChange}
|
||||
type="tel"
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
|
||||
|
||||
<TextField
|
||||
name="currentJob"
|
||||
id="outlined"
|
||||
label="Poste actuel"
|
||||
required
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
value={this.state.currentJob && this.state.currentJob !='null' ? this.state.currentJob : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="address1"
|
||||
id="outlined"
|
||||
label="Adresse"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
value={this.state.address1 && this.state.address1 !='null' ? this.state.address1 : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="address2"
|
||||
id="outlined"
|
||||
label="Adresse complémentaire"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
value={this.state.address2 && this.state.address2 !='null' ? this.state.address2 : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
<div className={classes.container}>
|
||||
<TextField
|
||||
name="zipCode"
|
||||
id="outlined"
|
||||
label="Code postal"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.textFieldSmall }}
|
||||
variant="outlined"
|
||||
value={this.state.zipCode && this.state.zipCode !='null' ? this.state.zipCode : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="city"
|
||||
id="outlined"
|
||||
label="Ville"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.textFieldSmall }}
|
||||
variant="outlined"
|
||||
value={this.state.city && this.state.city !='null' ? this.state.city : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="country"
|
||||
id="outlined"
|
||||
label="Pays"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.textFieldSmall }}
|
||||
variant="outlined"
|
||||
value={this.state.country && this.state.country !='null' ? this.state.country : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<TextField
|
||||
name="linkedin"
|
||||
id="outlined"
|
||||
label="Linkedin"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
placeholder="http://www.linkedin.com/in/"
|
||||
value={this.state.linkedin && this.state.linkedin !='null' ? this.state.linkedin : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="twitter"
|
||||
id="outlined"
|
||||
label="Twitter"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
placeholder="http://twitter.com/.."
|
||||
value={this.state.twitter && this.state.twitter !='null' ? this.state.twitter : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
name="website"
|
||||
id="outlined"
|
||||
label="Site internet"
|
||||
className={classes.textField}
|
||||
classes={{ root: classes.rootTextfield }}
|
||||
variant="outlined"
|
||||
placeholder="http://monsite.fr"
|
||||
value={this.state.website && this.state.website !='null' ? this.state.website : ''}
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.onBlur}
|
||||
/>
|
||||
</form>
|
||||
{/* <div id="F" className={classes.foot}>
|
||||
<Button variant="contained" className={classes.button + ' cypButtonSendApplication'} onClick={this.onSubmit}>Mettre à jour!</Button>
|
||||
</div> */}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
return {
|
||||
user: state.user ,
|
||||
loading: !!state.user.loading,
|
||||
pictureLoading: !!state.user.pictureLoading,
|
||||
errors: state.user.errors || ownProps.errors,
|
||||
mediaId: state.media.message && state.media.message.mediaId,
|
||||
};
|
||||
}
|
||||
|
||||
export default withStyles(styles)(connect(mapStateToProps, { updateUserRequest })(Accountdetails))
|
||||
@@ -0,0 +1,317 @@
|
||||
import React, {Fragment} from 'react'
|
||||
import {connect} from "react-redux";
|
||||
import {makeStyles} from '@material-ui/styles';
|
||||
import KeyboardArrowRightIcon from '@material-ui/icons/KeyboardArrowRight';
|
||||
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
|
||||
import {Button, Typography} from '@material-ui/core';
|
||||
import dynamic from 'next/dynamic'
|
||||
import {withStyles} from '@material-ui/core/styles'
|
||||
import {uploadMediaPres} from '../../actions/media'
|
||||
import {errorMessageSelector} from '../../reducers/media'
|
||||
import {fetchCompanyRequest} from '../../actions/companies'
|
||||
import {fetchCurrentUserRequest} from '../../actions/user'
|
||||
import VideoVimeo from '../atoms/VideoVimeo'
|
||||
import Router from 'next/router'
|
||||
import Loader from '../templates/loader'
|
||||
import Ar from "lodash/array"
|
||||
import Snackbar from '@material-ui/core/Snackbar';
|
||||
import { Alert, AlertTitle } from '@material-ui/lab';
|
||||
import ReactHtmlParser, { processNodes, convertNodeToElement, htmlparser2 } from 'react-html-parser';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import Container from '@material-ui/core/Container';
|
||||
import Hidden from '@material-ui/core/Hidden';
|
||||
|
||||
const styles = theme => ({
|
||||
container: {
|
||||
width: '100%',
|
||||
},
|
||||
root: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
margin: theme.spacing(1),
|
||||
flexWrap: 'wrap',
|
||||
overflow: 'hidden',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
|
||||
recorderContainer: {
|
||||
//display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
width: '100%'
|
||||
},
|
||||
rootButton: {
|
||||
textTransform: 'inherit'
|
||||
},
|
||||
underlined: {
|
||||
textDecoration: 'underline'
|
||||
},
|
||||
textButton: {
|
||||
fontWeight: '700',
|
||||
fontSize: '1.15em',
|
||||
paddingLeft: theme.spacing(2)
|
||||
},
|
||||
videoPresentation: {
|
||||
width: "100%",
|
||||
height: "100%"
|
||||
},
|
||||
conseilButton: {
|
||||
color: "#ffffff",
|
||||
backgroundColor: "#25D89A",
|
||||
padding: theme.spacing(3, 2),
|
||||
margin: theme.spacing(1),
|
||||
width: "100%",
|
||||
textAlign: "right",
|
||||
boxShadow: '0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12), 0 3px 5px -1' +
|
||||
'px rgba(0, 0, 0, 0.14)',
|
||||
'&:hover': {
|
||||
color: "#ffffff",
|
||||
backgroundColor: "#25D89A",
|
||||
}
|
||||
},
|
||||
importButton: {
|
||||
color: theme.palette.primary.main,
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
padding: theme.spacing(3, 2),
|
||||
margin: theme.spacing(1),
|
||||
width: "100%",
|
||||
textAlign: "right",
|
||||
boxShadow: '0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12), 0 3px 5px -1' +
|
||||
'px rgba(0, 0, 0, 0.14)',
|
||||
'&:hover': {
|
||||
color: theme.palette.primary.main,
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
}
|
||||
},
|
||||
InputKeyboardArrowDownIconBlank: {
|
||||
fontSize: '2.5em',
|
||||
color: "#ffffff",
|
||||
textAlign: "right"
|
||||
},
|
||||
InputKeyboardArrowDownIcon: {
|
||||
fontSize: '2.5em',
|
||||
color: "#1689FB",
|
||||
textAlign: "right"
|
||||
}
|
||||
});
|
||||
const Recorder = dynamic(() => import ('../organisms/Recorder'), {ssr: false})
|
||||
class Etape2 extends React.Component {
|
||||
state = {
|
||||
loading: true,
|
||||
activeStep: 0,
|
||||
data: {},
|
||||
openSnack: false,
|
||||
errors: {},
|
||||
success : {}
|
||||
};
|
||||
|
||||
|
||||
componentDidMount() {
|
||||
localStorage.setItem('loginRedirect', window.location)
|
||||
|
||||
if (!!!localStorage.getItem('ttJWT')) {
|
||||
Router.push("/Login")
|
||||
} else
|
||||
this.setState({loading: false, firstname: this.props.user.firstname, videoPres: this.props.user.videoPres, video: this.props.user.presentation_video_id})
|
||||
}
|
||||
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
|
||||
this.setState({
|
||||
loading: nextProps.loading,
|
||||
openSnack: !!!_.isEmpty(nextProps.errors),
|
||||
errors: !!!nextProps.errors
|
||||
? {
|
||||
errors: {
|
||||
message: ""
|
||||
}
|
||||
}
|
||||
: nextProps.errors,
|
||||
videoPres: nextProps.videoPres,
|
||||
video: nextProps.video
|
||||
})
|
||||
//window.location.reload(false);
|
||||
if (nextProps.media.status === 'success') {
|
||||
const success = {};
|
||||
success.message ="Vidéo mis à jour";
|
||||
this.setState({ success });
|
||||
this.setActiveStep(1);
|
||||
}
|
||||
}
|
||||
|
||||
setActiveStep = (step) => {
|
||||
this.setState({activeStep: step})
|
||||
}
|
||||
|
||||
inputFilesystemChange = (e) => {
|
||||
this.uploadMediaPres(e)
|
||||
}
|
||||
|
||||
inputCamRecorderChange = (e) => {
|
||||
this.uploadMediaPres(e)
|
||||
}
|
||||
|
||||
uploadMediaPres = (e) => {
|
||||
var file = e.target.files[0]
|
||||
|
||||
const data = new FormData()
|
||||
data.append('upload', file)
|
||||
//this.setState({ videoPres: videoPres })
|
||||
|
||||
this
|
||||
.props
|
||||
.uploadMediaPres(data)
|
||||
}
|
||||
|
||||
AfficherSuccess() {
|
||||
if (!this.state.success || !this.state.success.message) {
|
||||
|
||||
} else if (this.state.success.length != 0 && this.state.success.message != "") {
|
||||
return (
|
||||
<Snackbar open={open} autoHideDuration={1000} onClose={() => this.setState({open: false})}>
|
||||
<Alert onClose={() => this.setState({open: false})} severity="success">
|
||||
{ReactHtmlParser(this.state.success.message)}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
handleClose = (event, reason) => {
|
||||
this.setState({openSnack: false});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {classes, company} = this.props;
|
||||
const {loading, activeStep} = this.state;
|
||||
let video;
|
||||
if (this.state.videoPres) {
|
||||
video = <VideoVimeo videoId={Ar.last(_.split(this.state.videoPres, '/'))} autoplay='1' classesOverride="videoPresentation"/>;
|
||||
} else {
|
||||
video = "";
|
||||
}
|
||||
return (
|
||||
<section className={classes.container}>
|
||||
<Fragment>
|
||||
{this.AfficherSuccess()}
|
||||
{ loading ? <Loader/> : <div></div> }
|
||||
|
||||
<div className={classes.root}>
|
||||
<Hidden xsUp>
|
||||
|
||||
</Hidden>
|
||||
<Container maxWidth="md">
|
||||
|
||||
<Grid container
|
||||
justify="center"
|
||||
alignItems="center"
|
||||
spacing={2}>
|
||||
<Grid item xs={12} sm={12} md={12} lg={6} lg={6}>
|
||||
<div className={classes.recorderContainer}>
|
||||
<Recorder uploader={this.props.uploadMediaPres} titreBouton="Remplacer ma vidéo"/>
|
||||
</div>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={12} md={12} lg={6} xl={6}>
|
||||
<div>
|
||||
<label htmlFor="import-conseil">
|
||||
<Button
|
||||
component="span"
|
||||
className={classes.conseilButton}
|
||||
classes={{
|
||||
root: classes.rootButton}}
|
||||
onClick={() => Router.push(`/Conseils`)}>
|
||||
<img
|
||||
alt="talents-tube"
|
||||
src='/statique/images/conseils-talentstube.svg'
|
||||
className={classes.iconButton}/>
|
||||
<Typography align="left" className={classes.textButton}>
|
||||
<span className={classes.underlined}>Comment</span> créer ma vidéo
|
||||
</Typography>
|
||||
<KeyboardArrowDownIcon className={classes.InputKeyboardArrowDownIconBlank}/>
|
||||
</Button>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="file"
|
||||
accept="video/*"
|
||||
className={classes.input + ' cypButtonImportVid'}
|
||||
style={{display: 'none'}}
|
||||
id="import-button-file"
|
||||
onChange={this.inputFilesystemChange}/>
|
||||
<label htmlFor="import-button-file">
|
||||
<Button
|
||||
component="span"
|
||||
className={classes.importButton}
|
||||
classes={{
|
||||
root: classes.rootButton}}>
|
||||
<img
|
||||
alt="talents-tube"
|
||||
src='/statique/images/Import.svg'
|
||||
className={classes.iconButton}/>
|
||||
<Typography align="left" className={classes.textButton}>
|
||||
J'<span className={classes.underlined}>importe</span> ma vidéo de réponse
|
||||
|
||||
</Typography>
|
||||
<KeyboardArrowDownIcon className={classes.InputKeyboardArrowDownIcon}/>
|
||||
</Button>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</Grid>
|
||||
<Hidden xsUp>
|
||||
|
||||
</Hidden>
|
||||
|
||||
<Grid item xs={12} sm={12} md={12} lg={12} xl={12}>
|
||||
<div className={classes.videoPresentation}>
|
||||
{video}
|
||||
</div>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</Container>
|
||||
</div>
|
||||
{/* <div className={classes.textContainer}>
|
||||
|
||||
</div> */}
|
||||
|
||||
</Fragment>
|
||||
</section>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Etape2.getInitialProps = function (context) {
|
||||
|
||||
const {companyId} = context.query
|
||||
const {res} = context
|
||||
//TODO :really needed ?
|
||||
context
|
||||
.store
|
||||
.dispatch(fetchCurrentUserRequest())
|
||||
|
||||
if (!!companyId)
|
||||
context.store.dispatch(fetchCompanyRequest(companyId))
|
||||
|
||||
return {}; //leave this please
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
|
||||
return {
|
||||
loading: !!state.media.loading,
|
||||
media: state.media,
|
||||
offre: state.ad,
|
||||
//errors: errorMessageSelector(state),
|
||||
user: state.user,
|
||||
company: state.company
|
||||
};
|
||||
}
|
||||
|
||||
export default withStyles(styles)(connect(mapStateToProps, {fetchCurrentUserRequest, fetchCompanyRequest, uploadMediaPres})(Etape2));
|
||||
@@ -0,0 +1,233 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { connect } from "react-redux";
|
||||
import { fetchCurrentUserRequest } from '../../actions/user'
|
||||
import { fetchCompanyRequest } from '../../actions/companies'
|
||||
import { uploadMediaCv } from '../../actions/media'
|
||||
import { withStyles } from '@material-ui/core/styles'
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import { Button, Typography, Divider, Hidden } from '@material-ui/core';
|
||||
import KeyboardArrowRightIcon from '@material-ui/icons/KeyboardArrowRight';
|
||||
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
|
||||
import Loader from '../../components/templates/loader'
|
||||
import Snack from '../../components/atoms/snack';
|
||||
import Snackbar from '@material-ui/core/Snackbar';
|
||||
import { Alert, AlertTitle } from '@material-ui/lab';
|
||||
import ReactHtmlParser from 'react-html-parser';
|
||||
import getConfig from 'next/config'
|
||||
import Card from '@material-ui/core/Card';
|
||||
import CardActions from '@material-ui/core/CardActions';
|
||||
import CardContent from '@material-ui/core/CardContent';
|
||||
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
margin: theme.spacing(1),
|
||||
},
|
||||
rootButton: {
|
||||
textTransform: 'inherit',
|
||||
},
|
||||
underlined: {
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
textButton: {
|
||||
fontWeight: '700',
|
||||
fontSize: '1.15em',
|
||||
paddingLeft: theme.spacing(2),
|
||||
},
|
||||
InputKeyboardArrowDownIcon: {
|
||||
fontSize: '2.5em',
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
importButton: {
|
||||
color: theme.palette.primary.main,
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
padding: theme.spacing(3, 2),
|
||||
margin: theme.spacing(1),
|
||||
width: "400px",
|
||||
boxShadow: '0 6px 10px 0 rgba(0, 0, 0, 0.14), 0 1px 18px 0 rgba(0, 0, 0, 0.12), 0 3px 5px -1' +
|
||||
'px rgba(0, 0, 0, 0.14)',
|
||||
'&:hover': {
|
||||
color: theme.palette.primary.main,
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
const { publicRuntimeConfig } = getConfig();
|
||||
class Etape3 extends React.Component {
|
||||
state = {
|
||||
loading: true,
|
||||
openSnack: false,
|
||||
cv:false,
|
||||
errors: {},
|
||||
success : {}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
localStorage.setItem('loginRedirect', window.location)
|
||||
|
||||
if(!!!localStorage.getItem('ttJWT'))
|
||||
{
|
||||
Router.push("/Login")
|
||||
}
|
||||
else
|
||||
this.setState({
|
||||
loading: false,
|
||||
cvLink: this.props.user.cv
|
||||
})
|
||||
}
|
||||
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
|
||||
this.setState({
|
||||
cvLink: nextProps.cvLink,
|
||||
loading: nextProps.loading,
|
||||
openSnack: !!!_.isEmpty(nextProps.errors),
|
||||
errors: !!!nextProps.errors ? { errors: { message: "" } } : nextProps.errors,
|
||||
})
|
||||
this.state.cvLink = nextProps.cvLink;
|
||||
if (nextProps.loading) {
|
||||
const success = {};
|
||||
success.message ="CV mis à jour";
|
||||
console.log("CV mis à jour!!!")
|
||||
if(this.state.cvLink) console.log(this.state.cvLink)
|
||||
this.setState({ success });
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
inputFilesystemChange = (e) => {
|
||||
this.uploadMediaCv(e)
|
||||
}
|
||||
|
||||
uploadMediaCv = (e) => {
|
||||
var file = e.target.files[0]
|
||||
|
||||
const data = new FormData()
|
||||
data.append('upload', file)
|
||||
|
||||
this.props.uploadMediaCv(data)
|
||||
}
|
||||
|
||||
AfficherSuccess() {
|
||||
if (!this.state.success || !this.state.success.message) {
|
||||
console.log("Erreur Upload CV");
|
||||
return "";
|
||||
} else if (this.state.success.length != 0 && this.state.success.message != "") {
|
||||
return (
|
||||
<Snackbar open={open} autoHideDuration={1000} onClose={() => this.setState({open: false})}>
|
||||
<Alert onClose={() => this.setState({open: false})} severity="success">
|
||||
{ReactHtmlParser(this.state.success.message)}
|
||||
</Alert>
|
||||
</Snackbar>
|
||||
);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
AfficherLienCv() {
|
||||
console.log("afficher lien");
|
||||
if (this.props.user.cv !="") {
|
||||
|
||||
return (
|
||||
|
||||
<Fragment>
|
||||
<Hidden> </Hidden>
|
||||
<Hidden> </Hidden>
|
||||
<Divider style={{width:400+"px"}}/>
|
||||
<Hidden> </Hidden>
|
||||
<Card variant="outlined" style={{width:400+"px"}}>
|
||||
<CardActions>
|
||||
<Button size="small">Mon CV numérique</Button>
|
||||
</CardActions>
|
||||
<CardContent>
|
||||
<Typography>
|
||||
<a href={publicRuntimeConfig.symphonyUrl + publicRuntimeConfig.postedContentCv + this.state.cvLink} target="_blank">Lien vers le cv téléchargé</a><br />
|
||||
{/* <a href="https://www.permatheque.fr/PDF/mansobufukuoka-larevolutiondunseulbrindepaille.pdf" target="_blank">lien</a> */}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
|
||||
</Card>
|
||||
</Fragment>
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
render() {
|
||||
const { classes, company } = this.props;
|
||||
const { loading } = this.state;
|
||||
return (
|
||||
<Fragment>
|
||||
{ loading ?
|
||||
<Loader /> :
|
||||
<Fragment>
|
||||
{this.AfficherSuccess()}
|
||||
|
||||
<input
|
||||
type="file"
|
||||
accept=".doc,.docx,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document, .pdf, .odt"
|
||||
className={classes.input+' cypButtonImportVid'}
|
||||
style={{ display: 'none' }}
|
||||
id="import-button-file"
|
||||
onChange={this.inputFilesystemChange}
|
||||
/>
|
||||
<label htmlFor="import-button-file">
|
||||
<Button component="span" className={classes.importButton} classes={{ root: classes.rootButton }}>
|
||||
<img alt="talents-tube" src='/statique/images/Import-cv-candidat.svg' className={classes.iconButton} />
|
||||
<Typography className={classes.textButton}>
|
||||
J'<span className={classes.underlined}>importe</span> mon CV au format PDF
|
||||
</Typography>
|
||||
<KeyboardArrowDownIcon className={ classes. InputKeyboardArrowDownIcon }/>
|
||||
</Button>
|
||||
</label>
|
||||
{this.AfficherLienCv()}
|
||||
|
||||
</Fragment>
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Etape3.getInitialProps = function (context) {
|
||||
|
||||
const { adId, companyId } = context.query
|
||||
const {res} = context
|
||||
//TODO :really needed ?
|
||||
context.store.dispatch(fetchCurrentUserRequest())
|
||||
|
||||
if(!!adId)
|
||||
context.store.dispatch(fetchAdRequest(adId))
|
||||
else if(!!companyId)
|
||||
context.store.dispatch(fetchCompanyRequest(companyId))
|
||||
|
||||
return {};//leave this please
|
||||
}
|
||||
|
||||
function mapStateToProps(state) {
|
||||
// console.log("mapStateToProps")
|
||||
// console.log(state.loading)
|
||||
// console.log(state.user)
|
||||
// console.log(state.media.message)
|
||||
return {
|
||||
user: state.user ,
|
||||
cvLink : state.media.message,
|
||||
loading: !!state.media.loading,
|
||||
cv : true,
|
||||
//errors: errorMessageSelector(state),
|
||||
user: state.user,
|
||||
company: state.company
|
||||
};
|
||||
}
|
||||
export default withStyles(styles)(connect(mapStateToProps, { fetchCurrentUserRequest, fetchCompanyRequest, uploadMediaCv })(Etape3));
|
||||
@@ -0,0 +1,403 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import clsx from 'clsx';
|
||||
import AccountStep from "../../components/organisms/AccountStep";
|
||||
import AccountEtape1 from '../organisms/AccountEtape1';
|
||||
import AccountEtape2 from '../organisms/AccountEtape2';
|
||||
import AccountEtape3 from '../organisms/AccountEtape3';
|
||||
import {withStyles} from '@material-ui/core/styles';
|
||||
import Switch from '@material-ui/core/Switch';
|
||||
import PhoneIcon from '@material-ui/icons/Phone';
|
||||
import MailIcon from '@material-ui/icons/Mail';
|
||||
import PublicIcon from '@material-ui/icons/Public';
|
||||
import LinkedInIcon from '@material-ui/icons/LinkedIn';
|
||||
import FormGroup from '@material-ui/core/FormGroup';
|
||||
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
||||
import FormControl from '@material-ui/core/FormControl';
|
||||
import {updateUserRequest, updateUserPictureRequest} from '../../actions/user'
|
||||
import {makeStyles} from '@material-ui/styles';
|
||||
import {connect} from 'react-redux'
|
||||
import getConfig from 'next/config'
|
||||
import BottomNavigation from '@material-ui/core/BottomNavigation';
|
||||
import BottomNavigationAction from '@material-ui/core/BottomNavigationAction';
|
||||
import RefreshIcon from '@material-ui/icons/Refresh';
|
||||
import FavoriteIcon from '@material-ui/icons/Favorite';
|
||||
import LocationOnIcon from '@material-ui/icons/LocationOn';
|
||||
|
||||
import Box from '@material-ui/core/Box';
|
||||
|
||||
import {
|
||||
Card,
|
||||
CardActions,
|
||||
CardContent,
|
||||
Avatar,
|
||||
Typography,
|
||||
Divider,
|
||||
Button,
|
||||
LinearProgress,
|
||||
Stepper,
|
||||
Step,
|
||||
StepLabel,
|
||||
StepContent,
|
||||
StepButton,
|
||||
Paper,
|
||||
Grid
|
||||
} from '@material-ui/core';
|
||||
|
||||
const styles = theme => ({
|
||||
container: {
|
||||
width: '100%'
|
||||
},
|
||||
button: {
|
||||
textTransform: 'inherit',
|
||||
marginLeft: theme.spacing(8),
|
||||
marginRight: theme.spacing(8),
|
||||
padding: theme.spacing(1.2, 2),
|
||||
color: theme.palette.secondary.main,
|
||||
backgroundColor: theme.palette.primary.important
|
||||
},
|
||||
stickToBottom: {
|
||||
width: '100%',
|
||||
position: 'fixed',
|
||||
bottom: 0
|
||||
}
|
||||
});
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
root: {},
|
||||
details: {
|
||||
display: 'flex'
|
||||
},
|
||||
avatar: {
|
||||
marginLeft: 'auto',
|
||||
height: 110,
|
||||
width: 100,
|
||||
flexShrink: 0,
|
||||
flexGrow: 0
|
||||
},
|
||||
progress: {
|
||||
marginTop: theme.spacing(2)
|
||||
},
|
||||
uploadButton: {
|
||||
marginRight: theme.spacing(2)
|
||||
},
|
||||
button: {
|
||||
marginTop: theme.spacing(1),
|
||||
marginRight: theme.spacing(1)
|
||||
},
|
||||
actionsContainer: {
|
||||
marginBottom: theme.spacing(2)
|
||||
},
|
||||
resetContainer: {
|
||||
padding: theme.spacing(3)
|
||||
}
|
||||
}));
|
||||
|
||||
function getSteps() {
|
||||
return ['Informations personnelles', 'Vidéo de présentation', 'Expériences professionnelles'];
|
||||
}
|
||||
|
||||
function getStepContent(step) {
|
||||
switch (step) {
|
||||
case 0:
|
||||
return <AccountEtape1 ></AccountEtape1>;
|
||||
case 1:
|
||||
return <AccountEtape2></AccountEtape2>;
|
||||
case 2:
|
||||
return <AccountEtape3></AccountEtape3>;
|
||||
default:
|
||||
return 'Unknown step';
|
||||
}
|
||||
}
|
||||
|
||||
const AccountProfile = props => {
|
||||
const {
|
||||
className,
|
||||
user,
|
||||
...rest
|
||||
} = props;
|
||||
const logoUrl = user.picture;
|
||||
const classes = useStyles();
|
||||
|
||||
// const user = { name: 'Laurent Laniau', city: 'Questembert', country:
|
||||
// 'France', timezone: '', avatar: '/images/avatars/avatar_11.png' };
|
||||
const {publicRuntimeConfig} = getConfig()
|
||||
const [activeStep,
|
||||
setActiveStep] = React.useState(0);
|
||||
const [completed,
|
||||
setCompleted] = React.useState(new Set());
|
||||
const [skipped,
|
||||
setSkipped] = React.useState(new Set());
|
||||
const [state,
|
||||
setState] = React.useState({checkedA: true, checkedB: true});
|
||||
const steps = getSteps();
|
||||
|
||||
const totalSteps = () => {
|
||||
return getSteps().length;
|
||||
};
|
||||
|
||||
const isStepOptional = (step) => {
|
||||
return step === 4;
|
||||
};
|
||||
|
||||
const handleSkip = () => {
|
||||
if (!isStepOptional(activeStep)) {
|
||||
// You probably want to guard against something like this it should never occur
|
||||
// unless someone's actively trying to break something.
|
||||
throw new Error("You can't skip a step that isn't optional.");
|
||||
}
|
||||
|
||||
setActiveStep((prevActiveStep) => prevActiveStep + 1);
|
||||
setSkipped((prevSkipped) => {
|
||||
const newSkipped = new Set(prevSkipped.values());
|
||||
newSkipped.add(activeStep);
|
||||
return newSkipped;
|
||||
});
|
||||
};
|
||||
|
||||
const skippedSteps = () => {
|
||||
return skipped.size;
|
||||
};
|
||||
|
||||
const completedSteps = () => {
|
||||
return completed.size;
|
||||
};
|
||||
|
||||
const allStepsCompleted = () => {
|
||||
return completedSteps() === totalSteps() - skippedSteps();
|
||||
};
|
||||
|
||||
const isLastStep = () => {
|
||||
return activeStep === totalSteps() - 1;
|
||||
};
|
||||
|
||||
const handleNext = () => {
|
||||
const newActiveStep = isLastStep() && !allStepsCompleted()
|
||||
? // It's the last step, but not all steps have been completed
|
||||
// find the first step that has been completed
|
||||
steps.findIndex((step, i) => !completed.has(i))
|
||||
: activeStep + 1;
|
||||
|
||||
setActiveStep(newActiveStep);
|
||||
};
|
||||
|
||||
const handleBack = () => {
|
||||
setActiveStep((prevActiveStep) => prevActiveStep - 1);
|
||||
};
|
||||
|
||||
const handleStep = (step) => () => {
|
||||
console.log("step");
|
||||
console.log(step);
|
||||
setActiveStep(step);
|
||||
};
|
||||
|
||||
const handleComplete = () => {
|
||||
const newCompleted = new Set(completed);
|
||||
newCompleted.add(activeStep);
|
||||
setCompleted(newCompleted);
|
||||
|
||||
/**
|
||||
* Sigh... it would be much nicer to replace the following if conditional with
|
||||
* `if (!this.allStepsComplete())` however state is not set when we do this,
|
||||
* thus we have to resort to not being very DRY.
|
||||
*/
|
||||
if (completed.size !== totalSteps() - skippedSteps()) {
|
||||
handleNext();
|
||||
}
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
setActiveStep(0);
|
||||
setCompleted(new Set());
|
||||
setSkipped(new Set());
|
||||
};
|
||||
|
||||
const isStepSkipped = (step) => {
|
||||
return skipped.has(step);
|
||||
};
|
||||
|
||||
const handleChange = (event) => {
|
||||
setState({
|
||||
...state,
|
||||
[event.target.name]: event.target.checked
|
||||
});
|
||||
};
|
||||
|
||||
function isStepComplete(step) {
|
||||
return completed.has(step);
|
||||
}
|
||||
function refresh (){
|
||||
document.location.reload(true);
|
||||
console.log("refresh")
|
||||
}
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
spacing={4}
|
||||
direction="row"
|
||||
justify="space-between"
|
||||
alignItems="flex-start">
|
||||
<Grid item lg={3} md={6} xl={4} xs={12}>
|
||||
<Card {...rest} className={clsx(classes.root, className)}>
|
||||
<CardContent>
|
||||
<div className={classes.details}>
|
||||
<div>
|
||||
<Typography gutterBottom variant="h5">
|
||||
{user.lastname}
|
||||
{user.firstname} <a href="#" onClick={refresh}><RefreshIcon className={classes.menuButton}/></a>
|
||||
</Typography>
|
||||
<Typography
|
||||
className={classes.locationText}
|
||||
color="textSecondary"
|
||||
variant="body1">
|
||||
<MailIcon className={classes.menuButton}/> : {user.email}<br/>
|
||||
<PhoneIcon className={classes.menuButton}/> : {user.phone}<br/>
|
||||
<LinkedInIcon className={classes.menuButton}/> : {(user.linkedin && user.linkedin !='' && user.linkedin != 'null') ? <a href={user.linkedin} target="_blank">{user.linkedin}</a> : 'Non renseigné'}<br/>
|
||||
<PublicIcon className={classes.menuButton}/> : {(user.website && user.website !='' && user.website != 'null') ? <a href={user.website} target="_blank">{user.website}</a> : 'Non renseigné'}
|
||||
</Typography>
|
||||
<Typography className={classes.dateText} color="textSecondary" variant="body1"></Typography>
|
||||
</div>
|
||||
<Avatar
|
||||
className={classes.avatar}
|
||||
src={publicRuntimeConfig.symphonyUrl + publicRuntimeConfig.postedContentUrl + logoUrl}/>
|
||||
</div>
|
||||
{/* <div className={classes.progress}>
|
||||
<Typography variant="body1">Etat du Profil: 70%</Typography>
|
||||
<LinearProgress value={70} variant="determinate"/>
|
||||
</div> */}
|
||||
</CardContent>
|
||||
<Box m={2} />
|
||||
<Divider/>
|
||||
<Box m={2} />
|
||||
{/* <CardActions>
|
||||
<Button className={classes.uploadButton} color="primary" variant="text">
|
||||
Remplacer une photo de profil
|
||||
</Button>
|
||||
<Button variant="text">Supprimer photo de profil</Button>
|
||||
</CardActions> */}
|
||||
<Box m={1} />
|
||||
<Divider/>
|
||||
<Box m={1} />
|
||||
{/* <CardContent>
|
||||
<Typography variant="body1"></Typography>
|
||||
<FormControlLabel
|
||||
value="end"
|
||||
control={< Switch checked = {
|
||||
state.checkedA
|
||||
}
|
||||
onChange = {
|
||||
handleChange
|
||||
}
|
||||
name = "checkedA" color = "primary" />}
|
||||
label="Je souhaite afficher mon profil sur la CV Vidéothèque Talents Tube"
|
||||
labelPlacement="start"/>
|
||||
|
||||
</CardContent> */}
|
||||
|
||||
<Box m={3} />
|
||||
<Divider/>
|
||||
<CardActions>
|
||||
|
||||
<Stepper nonLinear activeStep={activeStep} orientation="vertical">
|
||||
{steps.map((label, index) => {
|
||||
const stepProps = {};
|
||||
const buttonProps = {};
|
||||
if (isStepOptional(index)) {
|
||||
buttonProps.optional = <Typography variant="caption">Optional</Typography>;
|
||||
}
|
||||
if (isStepSkipped(index)) {
|
||||
stepProps.completed = false;
|
||||
}
|
||||
return (
|
||||
<Step key={label} className={classes.actionsContainer} {...stepProps}>
|
||||
<StepButton
|
||||
onClick={handleStep(index)}
|
||||
completed={isStepComplete(index)}
|
||||
{...buttonProps}>
|
||||
{label}
|
||||
</StepButton>
|
||||
|
||||
</Step>
|
||||
);
|
||||
})}
|
||||
</Stepper>
|
||||
</CardActions>
|
||||
<Divider/>
|
||||
|
||||
<div>
|
||||
|
||||
<div>
|
||||
|
||||
<div>
|
||||
|
||||
{/* {isStepOptional(activeStep) && !completed.has(activeStep) && (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleSkip}
|
||||
className={classes.button}
|
||||
>
|
||||
Skip
|
||||
</Button>
|
||||
)} */}
|
||||
|
||||
{/* {activeStep !== steps.length &&
|
||||
(completed.has(activeStep) ? (
|
||||
<Typography variant="caption" className={classes.completed}>
|
||||
Step {activeStep + 1} already completed
|
||||
</Typography>
|
||||
) : (
|
||||
<Button variant="contained" color="primary" onClick={handleComplete}>
|
||||
{completedSteps() === totalSteps() - 1 ? 'Finish' : 'Complete Step'}
|
||||
</Button>
|
||||
))} */}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</Card>
|
||||
<Box m={2} />
|
||||
<CardContent>
|
||||
<BottomNavigation className={classes.stickToBottom}>
|
||||
<Button
|
||||
disabled={activeStep === 0}
|
||||
onClick={handleBack}
|
||||
className={classes.button}>
|
||||
Etape précédente
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleNext}
|
||||
className={classes.button}>
|
||||
Etape suivante
|
||||
</Button>
|
||||
{/* <BottomNavigationAction label="Recents" icon={< RestoreIcon />}/>
|
||||
<BottomNavigationAction label="Favorites" icon={< FavoriteIcon />}/>
|
||||
<BottomNavigationAction label="Nearby" icon={< LocationOnIcon />}/> */}
|
||||
</BottomNavigation>
|
||||
</CardContent>
|
||||
</Grid>
|
||||
<Grid item lg={9} md={6} xl={8} xs={12}>
|
||||
{getStepContent(activeStep)}
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
AccountProfile.propTypes = {
|
||||
className: PropTypes.string
|
||||
};
|
||||
function mapStateToProps(state, ownProps) {
|
||||
return {
|
||||
user: state.user,
|
||||
loading: !!state.user.loading,
|
||||
errors: state.user.errors || ownProps.errors
|
||||
};
|
||||
}
|
||||
|
||||
export default withStyles(styles)(connect(mapStateToProps, {updateUserRequest})(AccountProfile))
|
||||
@@ -0,0 +1,147 @@
|
||||
import React from 'react';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import Stepper from '@material-ui/core/Stepper';
|
||||
import Step from '@material-ui/core/Step';
|
||||
import StepButton from '@material-ui/core/StepButton';
|
||||
import Button from '@material-ui/core/Button';
|
||||
import Typography from '@material-ui/core/Typography';
|
||||
import AccountEtape1 from '../organisms/AccountEtape1';
|
||||
import AccountEtape2 from '../organisms/AccountEtape2';
|
||||
import AccountEtape3 from '../organisms/AccountEtape3';
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
width: '100%',
|
||||
},
|
||||
button: {
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
completed: {
|
||||
display: 'inline-block',
|
||||
},
|
||||
instructions: {
|
||||
marginTop: theme.spacing(1),
|
||||
marginBottom: theme.spacing(1),
|
||||
},
|
||||
}));
|
||||
|
||||
function getSteps() {
|
||||
return ['Informations personnelles', 'Vidéo de présentation', 'Expériences professionnelles'];
|
||||
}
|
||||
|
||||
function getStepContent(step) {
|
||||
switch (step) {
|
||||
case 0:
|
||||
return <AccountEtape1 ></AccountEtape1>;
|
||||
case 1:
|
||||
return <AccountEtape2></AccountEtape2>;
|
||||
case 2:
|
||||
return <AccountEtape3></AccountEtape3>;
|
||||
default:
|
||||
return 'Unknown step';
|
||||
}
|
||||
}
|
||||
|
||||
export default function HorizontalNonLinearStepper() {
|
||||
const classes = useStyles();
|
||||
const [activeStep, setActiveStep] = React.useState(0);
|
||||
const [completed, setCompleted] = React.useState({});
|
||||
const steps = getSteps();
|
||||
|
||||
const totalSteps = () => {
|
||||
return steps.length;
|
||||
};
|
||||
|
||||
const completedSteps = () => {
|
||||
return Object.keys(completed).length;
|
||||
};
|
||||
|
||||
const isLastStep = () => {
|
||||
return activeStep === totalSteps() - 1;
|
||||
};
|
||||
|
||||
const allStepsCompleted = () => {
|
||||
return completedSteps() === totalSteps();
|
||||
};
|
||||
|
||||
const handleNext = () => {
|
||||
const newActiveStep =
|
||||
isLastStep() && !allStepsCompleted()
|
||||
? // It's the last step, but not all steps have been completed,
|
||||
// find the first step that has been completed
|
||||
steps.findIndex((step, i) => !(i in completed))
|
||||
: activeStep + 1;
|
||||
setActiveStep(newActiveStep);
|
||||
};
|
||||
|
||||
const handleBack = () => {
|
||||
setActiveStep((prevActiveStep) => prevActiveStep - 1);
|
||||
};
|
||||
|
||||
const handleStep = (step) => () => {
|
||||
setActiveStep(step);
|
||||
};
|
||||
|
||||
const handleComplete = () => {
|
||||
const newCompleted = completed;
|
||||
newCompleted[activeStep] = true;
|
||||
setCompleted(newCompleted);
|
||||
handleNext();
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
setActiveStep(0);
|
||||
setCompleted({});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={classes.root}>
|
||||
<Stepper alternativeLabel nonLinear activeStep={activeStep}>
|
||||
{steps.map((label, index) => (
|
||||
<Step key={label}>
|
||||
<StepButton onClick={handleStep(index)} completed={completed[index]}>
|
||||
{label}
|
||||
</StepButton>
|
||||
</Step>
|
||||
))}
|
||||
</Stepper>
|
||||
<div>
|
||||
{allStepsCompleted() ? (
|
||||
<div>
|
||||
{/* <Typography className={classes.instructions}>
|
||||
Toutes les étapes sont terminées -
|
||||
</Typography>
|
||||
<Button onClick={handleReset}>Annuler</Button> */}
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<Typography className={classes.instructions}>{getStepContent(activeStep)}</Typography>
|
||||
<div>
|
||||
{/* <Button disabled={activeStep === 0} onClick={handleBack} className={classes.button}>
|
||||
Précédent
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={handleNext}
|
||||
className={classes.button}
|
||||
>
|
||||
Suivant
|
||||
</Button> */}
|
||||
{/* {activeStep !== steps.length &&
|
||||
(completed[activeStep] ? (
|
||||
<Typography variant="caption" className={classes.completed}>
|
||||
Step {activeStep + 1} already completed
|
||||
</Typography>
|
||||
) : (
|
||||
<Button variant="contained" color="primary" onClick={handleComplete}>
|
||||
{completedSteps() === totalSteps() - 1 ? 'Etape valide' : 'Processus terminé'}
|
||||
</Button>
|
||||
))} */}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import React, { useState } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import PropTypes from 'prop-types';
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import Link from 'next/link';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
import Box from '@material-ui/core/Box';
|
||||
import {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardContent,
|
||||
CardActions,
|
||||
Divider,
|
||||
Grid,
|
||||
Button,
|
||||
TextField
|
||||
} from '@material-ui/core';
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
root: {}
|
||||
}));
|
||||
|
||||
const AccountVideoPres = props => {
|
||||
const { className, ...rest } = props;
|
||||
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<Card
|
||||
{...rest}
|
||||
className={clsx(classes.root, className)}
|
||||
>
|
||||
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
AccountVideoPres.propTypes = {
|
||||
className: PropTypes.string
|
||||
};
|
||||
|
||||
export default AccountVideoPres;
|
||||
@@ -20,6 +20,8 @@ import WorkOutlineIcon from '@material-ui/icons/WorkOutline';
|
||||
import AccountCircleOutlinedIcon from '@material-ui/icons/AccountCircleOutlined';
|
||||
import FolderSharedIcon from '@material-ui/icons/FolderShared';
|
||||
import AccountCircleIcon from '@material-ui/icons/AccountCircle';
|
||||
import PermContactCalendar from '@material-ui/icons/PermContactCalendar';
|
||||
import VideoCam from '@material-ui/icons/Videocam';
|
||||
import SettingsIcon from '@material-ui/icons/Settings';
|
||||
import PowerSettingsNewIcon from '@material-ui/icons/PowerSettingsNew';
|
||||
import ArrowForward from '@material-ui/icons/ArrowForward';
|
||||
@@ -37,6 +39,7 @@ import { withRouter } from "next/router";
|
||||
import ActiveLink from "./../atoms/Activelink";
|
||||
import axios from 'axios';
|
||||
import setAuthorizationHeader from "../../data/setAuthorizationHeader";
|
||||
import getConfig from 'next/config'
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
@@ -327,7 +330,7 @@ class Header extends React.Component {
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
|
||||
const { publicRuntimeConfig } = getConfig();
|
||||
|
||||
|
||||
return (
|
||||
@@ -344,7 +347,7 @@ class Header extends React.Component {
|
||||
|
||||
<Link href="/" >
|
||||
<a className={classes.darkMenuItem}><ListItem classes={{ root: classes.rootListItem }}>
|
||||
<img alt="talents-tube" src='/static/images/logos/TalentsTube_logo-color.svg' className={classes.menuLogo} />
|
||||
<img alt="talents-tube" src='/statique/images/logos/TalentsTube_logo-color.svg' className={classes.menuLogo} />
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
|
||||
@@ -381,18 +384,9 @@ class Header extends React.Component {
|
||||
</ListItem></a>
|
||||
</ActiveLink>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className={classes.videothequeLinkGroup}>
|
||||
<a href="https://www.talentstube.com/faire-offre-emploi-video" className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
<VideoIcon className={classes.icon} />
|
||||
<ListItemText classes={{ primary: classes.ListItemText }} primary='CV vidéothèque'>
|
||||
</ListItemText>
|
||||
</ListItem>
|
||||
</a>
|
||||
</div>
|
||||
<div className={classes.blogLinkGroup}>
|
||||
<a href="https://blog.talentstube.com" className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
<a href={publicRuntimeConfig.blogUrl} className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
<NotesIcon className={classes.icon} />
|
||||
<ListItemText classes={{ primary: classes.ListItemText }} primary='Blog'>
|
||||
</ListItemText>
|
||||
@@ -400,7 +394,7 @@ class Header extends React.Component {
|
||||
</a>
|
||||
</div>
|
||||
<div className={classes.recruteurLinkGroup}>
|
||||
<a href="https://www.talentstube.com/faire-offre-emploi-video" className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
<a href={publicRuntimeConfig.symfonyUrl + "faire-offre-emploi-video"} className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
<SupervisorAccountIcon className={classes.icon} />
|
||||
<ListItemText classes={{ primary: classes.ListItemText }} primary='Recruteurs'>
|
||||
</ListItemText>
|
||||
@@ -430,7 +424,7 @@ class Header extends React.Component {
|
||||
<List>
|
||||
<Link href="/" >
|
||||
<a className={classes.darkMenuItem + ' cypFrontPage'}><ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
<img alt="talents-tube" src='/static/images/logos/TalentsTube_logo-blanc.svg' className={classes.menuLogo} />
|
||||
<img alt="talents-tube" src='/statique/images/logos/TalentsTube_logo-blanc.svg' className={classes.menuLogo} />
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
|
||||
@@ -458,7 +452,7 @@ class Header extends React.Component {
|
||||
<Divider light={true} />
|
||||
|
||||
<div className={classes.linkGroup}>
|
||||
<a href="https://www.talentstube.com/faire-offre-emploi-video" className={classes.lightMenuItem}><ListItem classes={{ primary: classes.ListItemText }} classes={{ root: classes.rootListItemIcon }}>
|
||||
<a href={publicRuntimeConfig.symfonyUrl + "/faire-offre-emploi-video"} className={classes.lightMenuItem}><ListItem classes={{ primary: classes.ListItemText }} classes={{ root: classes.rootListItemIcon }}>
|
||||
<WorkOutlineIcon className={classes.icon} />
|
||||
<ListItemText primary='Connexion recruteurs'>
|
||||
</ListItemText>
|
||||
@@ -470,7 +464,7 @@ class Header extends React.Component {
|
||||
{!!!this.props.loading && !!this.props.fetched &&
|
||||
<Fragment>
|
||||
{this.props.user.picture ?
|
||||
<img alt="talents-tube" src={`http://localhost/uploads/img/${this.props.user.picture}`} className={classes.menuAvatar} />
|
||||
<img alt="talents-tube" src={publicRuntimeConfig.symfonyUrl +publicRuntimeConfig.postedContentUrl+ this.props.user.picture} className={classes.menuAvatar} />
|
||||
:
|
||||
<img alt="talents-tube" src='/static/images/default/account-avatar-default.svg' className={classes.menuAvatar} />
|
||||
}
|
||||
@@ -494,17 +488,18 @@ class Header extends React.Component {
|
||||
</ListItemText>
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
<Link href="" >
|
||||
<a onClick={this.onRedirectAccount} className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
<Link href="/profileStep" >
|
||||
<a className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
<AccountCircleIcon className={classes.icon} />
|
||||
<ListItemText primary='Mon compte'>
|
||||
</ListItemText>
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
|
||||
<Link href="/Parametres" >
|
||||
<a className={classes.lightMenuItem}><ListItem classes={{ root: classes.rootListItemIcon }}>
|
||||
<SettingsIcon className={classes.icon} />
|
||||
<ListItemText primary='Paramètres'>
|
||||
<ListItemText primary='Paramètres de notification'>
|
||||
</ListItemText>
|
||||
</ListItem></a>
|
||||
</Link>
|
||||
@@ -530,7 +525,7 @@ class Header extends React.Component {
|
||||
<Link href="/" >
|
||||
<a className={classes.darkMenuItem}>
|
||||
<ListItem classes={{ root: classes.rootListItemDesktop }}>
|
||||
<img alt="talents-tube" src='/static/images/logos/TalentsTube_logo-color.svg' className={classes.desktopMenuLogo} />
|
||||
<img alt="talents-tube" src='/statique/images/logos/TalentsTube_logo-color.svg' className={classes.desktopMenuLogo} />
|
||||
</ListItem>
|
||||
</a>
|
||||
</Link>
|
||||
@@ -610,7 +605,7 @@ class Header extends React.Component {
|
||||
</section>
|
||||
<section className={classes.appBarDesktopSection + ' ' + classes.appBarDesktopSection3}>
|
||||
|
||||
<a href="https://www.talentstube.com/faire-offre-emploi-video" className={classes.desktopMenuItem}>
|
||||
<a href={publicRuntimeConfig.symfonyUrl + "/faire-offre-emploi-video"} className={classes.desktopMenuItem}>
|
||||
<ListItemText primary='Espace recruteurs'>
|
||||
</ListItemText>
|
||||
<ArrowForward className={classes.icon} />
|
||||
@@ -628,7 +623,7 @@ class Header extends React.Component {
|
||||
</IconButton>
|
||||
<div className={classes.grow} />
|
||||
<Link href="/" >
|
||||
<a><img alt="talents-tube" src='/static/images/logos/TalentsTube_logo-color.svg' className={classes.menuLogo} /></a>
|
||||
<a><img alt="talents-tube" src='/statique/images/logos/TalentsTube_logo-color.svg' className={classes.menuLogo} /></a>
|
||||
</Link>
|
||||
<div className={classes.grow} />
|
||||
<IconButton
|
||||
|
||||
@@ -18,6 +18,8 @@ import Link from 'next/link'
|
||||
import withWidth, { isWidthUp } from '@material-ui/core/withWidth'
|
||||
import VideoVimeo from '../atoms/VideoVimeo'
|
||||
import OgHead from '../atoms/OgHead'
|
||||
import JobPosting from '../atoms/JobPosting'
|
||||
import Moment from 'react-moment';
|
||||
|
||||
const styles = theme => ({
|
||||
primary: {
|
||||
@@ -304,11 +306,20 @@ function OffreDetail(props) {
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
|
||||
<OgHead seo_title={offre.title}
|
||||
seo_description={offre.description}
|
||||
seo_url={socialShareUrl}
|
||||
image={imgUrlDesktop}
|
||||
></OgHead>
|
||||
<JobPosting job_title={offre.title}
|
||||
job_description={offre.description}
|
||||
job_brand= {offre.company.brand_name && offre.company.brand_name}
|
||||
job_brand_link= {entrepriseLink}
|
||||
job_title = {offre.title}
|
||||
job_location = {offre.location.gmap_address.formatted_address}
|
||||
job_date = {offre.published_at}
|
||||
></JobPosting>
|
||||
{offre.video && (
|
||||
<Fragment>
|
||||
<Hidden smDown>
|
||||
@@ -319,13 +330,13 @@ function OffreDetail(props) {
|
||||
<div className={classes.logoContainer}>
|
||||
|
||||
<Avatar className={classes.logo} classes={{ img: classes.MuiAvatarImg }}
|
||||
src={logoUrl} alt="companyLogo" />
|
||||
src={logoUrl} alt={offre.company.brand_name && offre.company.brand_name} />
|
||||
|
||||
</div>
|
||||
</a>
|
||||
<div className={classes.infoContainer}>
|
||||
<Typography gutterBottom className={classes.offreTitle}>
|
||||
{offre.title}
|
||||
{offre.title} {/*- publié le <Moment format="DD/MM/YYYY" date={offre.published_at} /> */}
|
||||
</Typography>
|
||||
<a href={entrepriseLink} >
|
||||
<Typography gutterBottom variant="subtitle1" className={classes.companyName}>
|
||||
@@ -413,7 +424,7 @@ function OffreDetail(props) {
|
||||
variant="contained"
|
||||
className={classes.button}
|
||||
|
||||
>Postuler ! </Button>
|
||||
>Postuler</Button>
|
||||
</Link>
|
||||
<Typography className={classes.contentCondition}>
|
||||
ou
|
||||
|
||||
@@ -130,7 +130,15 @@ class Recorder extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
const { classes, titreBouton } = this.props;
|
||||
let titreButtonLabel= "Envoyer";
|
||||
|
||||
|
||||
if (titreBouton) {
|
||||
titreButtonLabel = titreBouton;
|
||||
console.log("titre");
|
||||
console.log(titreButtonLabel);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div data-vjs-player>
|
||||
@@ -140,7 +148,7 @@ class Recorder extends Component {
|
||||
{ this.state.canSend && <Button type="submit" variant="outlined" color="primary"
|
||||
className={classes.button}
|
||||
onClick={this.sendBlob}>
|
||||
Envoyer
|
||||
{titreButtonLabel}
|
||||
</Button>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -120,6 +120,22 @@ export default {
|
||||
withCredentials: true
|
||||
}).then(res => res)
|
||||
},
|
||||
uploadMediaPres: (payload) => {
|
||||
return axios.post("/api/mediaPres", payload, {
|
||||
headers: {
|
||||
'Content-Type': `multipart/form-data;`
|
||||
},
|
||||
withCredentials: true
|
||||
}).then(res => res)
|
||||
},
|
||||
uploadMediaCv: (payload) => {
|
||||
return axios.post("/api/mediaCv", payload, {
|
||||
headers: {
|
||||
'Content-Type': `multipart/form-data;`
|
||||
},
|
||||
withCredentials: true
|
||||
}).then(res => res)
|
||||
}
|
||||
},
|
||||
stats: {
|
||||
countAdView: id => {
|
||||
@@ -135,4 +151,4 @@ export default {
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
};
|
||||
@@ -33,21 +33,24 @@ module.exports = withPlugins(
|
||||
}
|
||||
],
|
||||
importScripts:
|
||||
['/static/js/Edeclic-service-worker.js',
|
||||
'/static/js/backgroundSync-sw.js'
|
||||
['/statique/js/Edeclic-service-worker.js',
|
||||
'/statique/js/backgroundSync-sw.js'
|
||||
]
|
||||
},
|
||||
}],
|
||||
[{
|
||||
publicRuntimeConfig: {
|
||||
symphonyUrl: 'https://www.talentstube.com',
|
||||
frontServerUrl: 'https://pp.app.talentstube.com',
|
||||
adListDefaultUrl: '/static/images/default/default_picture_company.svg',
|
||||
blogUrl: 'https://blog.talentstube.com',
|
||||
frontServerUrl: 'https://app.talentstube.com',
|
||||
adListDefaultUrl: '/statique/images/default/default_picture_company.svg',
|
||||
cachedMediaUrl: '/media/cache/profile_thumb/uploads/img/',
|
||||
postedContentUrl: '/uploads/img/',
|
||||
postedContentCv: '/uploads/cv/',
|
||||
ReCAPTCHA: {
|
||||
"siteKey": "6LdyqLwUAAAAADKI5uC7d5W9VqVgzd8VEmMU2Yi-"
|
||||
},
|
||||
applicationServerPublicKey: 'BC9XGBLNGm0RWczR4IjEPWQ9_P1BmlvT-oaVgr_GJTI2OZtT85olmi3xzQhgZF4-Bi0rPafpa8vqt5pudQ4Na6w'
|
||||
}
|
||||
}]
|
||||
],
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@blunck/next-alias": "^1.0.0",
|
||||
"@material-ui/core": "^4.2.0",
|
||||
"@material-ui/icons": "^3.0.1",
|
||||
"@material-ui/core": "^4.9.10",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "^4.0.0-alpha.56",
|
||||
"@ostai/next-css": "^1.0.2",
|
||||
"axios": "^0.18.0",
|
||||
"connect-mongo": "^2.0.1",
|
||||
@@ -33,6 +34,7 @@
|
||||
"next-optimized-images": "^1.4.1",
|
||||
"next-redux-saga": "^4.0.2",
|
||||
"next-redux-wrapper": "^3.0.0-alpha.2",
|
||||
"next-seo": "^4.7.3",
|
||||
"next-transpile-modules": "^2.3.1",
|
||||
"node-mailjet": "^3.3.1",
|
||||
"nodemailer": "^4.6.8",
|
||||
@@ -44,10 +46,13 @@
|
||||
"passport-oauth2": "https://github.com/Huaoe/passport-oauth2.git",
|
||||
"prop-types": "latest",
|
||||
"react": "^16.9.0",
|
||||
"react-ad-block-detect": "^1.0.1",
|
||||
"react-dom": "^16.9.0",
|
||||
"react-ga": "^2.5.7",
|
||||
"react-google-recaptcha": "^2.0.1",
|
||||
"react-html-parser": "^2.0.2",
|
||||
"react-jss": "latest",
|
||||
"react-moment": "^0.9.7",
|
||||
"react-redux": "^7.0.3",
|
||||
"react-swipeable-views": "^0.13.3",
|
||||
"reactstrap": "^6.4.0",
|
||||
|
||||
@@ -178,7 +178,7 @@ class Confidentialite extends Component {
|
||||
<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 d’informations 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 l’organisme EDAA (European Interactive Digital Advertising Alliance).
|
||||
Pour plus d’informations 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 l’organisme EDAA (European Interactive Digital Advertising Alliance).
|
||||
`
|
||||
}
|
||||
</Typography>
|
||||
|
||||
@@ -12,7 +12,7 @@ const styles = theme => ({
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
padding: theme.spacing(3,2),
|
||||
padding: theme.spacing(3, 2),
|
||||
width: '100%',
|
||||
},
|
||||
vimeoVideo: {
|
||||
@@ -26,17 +26,17 @@ class Conseils extends React.Component {
|
||||
const { classes } = this.props
|
||||
|
||||
return (
|
||||
<LayoutBack text="Quelques conseils !">
|
||||
<LayoutBack text="Quelques conseils !">
|
||||
<Head>
|
||||
<title>Quelques conseils !</title>
|
||||
<meta name="description" content="Quelques conseils !" />
|
||||
<meta key="robots" name="robots" content="noindex, nofollow"></meta>
|
||||
<link rel="canonical" href="https://app.talentstube.com" />
|
||||
</Head>
|
||||
<section className={ classes.container }>
|
||||
<VideoVimeo videoId='356411947' autoplay='1'/>
|
||||
<section className={classes.container}>
|
||||
<VideoVimeo videoId='356411947' autoplay='1' />
|
||||
</section>
|
||||
</LayoutBack>
|
||||
</LayoutBack>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -357,9 +357,9 @@ class Entreprise extends React.Component {
|
||||
|
||||
render() {
|
||||
const { classes, company } = this.props;
|
||||
const logoUrl = (company.logo ? publicRuntimeConfig.symphonyUrl + publicRuntimeConfig.cachedMediaUrl + company.logo : "https://www.talentstube.com/img/default_picture_svg")
|
||||
const logoUrl = (company.logo ? publicRuntimeConfig.symphonyUrl + publicRuntimeConfig.cachedMediaUrl + company.logo : publicRuntimeConfig.symfonyUrl + "/img/default_picture_svg")
|
||||
|
||||
const DefaultUrl = "https://www.talentstube.com/img/default_picture_svg"
|
||||
const DefaultUrl = publicRuntimeConfig.symfonyUrl + "/img/default_picture_svg"
|
||||
const imgUrl = (company.presentation_video && company.presentation_video.thumbnails[0] && company.presentation_video.thumbnails[0].sizes[2]) ? company.presentation_video.thumbnails[0].sizes[2].link : DefaultUrl
|
||||
|
||||
const offre = (company.count_ads == 1) ? company.count_ads + ' offre' : company.count_ads + ' offres'
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import getConfig from 'next/config'
|
||||
import { withStyles } from '@material-ui/core/styles';
|
||||
import _ from "lodash"
|
||||
import Grid from "../components/templates/Grid"
|
||||
@@ -11,6 +12,7 @@ import { fetchCompaniesRequest } from '../actions/companies'
|
||||
import { CompaniesSelector } from '../reducers/companies'
|
||||
import { connect } from "react-redux";
|
||||
import Head from 'next/head'
|
||||
import OgHead from '../components/atoms/OgHead';
|
||||
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
@@ -64,13 +66,41 @@ class Entreprises extends React.Component {
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
|
||||
const { publicRuntimeConfig } = getConfig();
|
||||
const socialShareUrl = typeof window !== 'undefined' ? window.location
|
||||
: publicRuntimeConfig.frontServerUrl + `/Entreprises`;
|
||||
const DefaultUrl = publicRuntimeConfig.symphonyUrl + "/img/default_picture_svg"
|
||||
const imgUrl = DefaultUrl ;
|
||||
return (
|
||||
<LayoutGrid backLink="/">
|
||||
<Head>
|
||||
{/* <Head>
|
||||
<title key="title">Entreprises qui recrutent – Talents Tube</title>
|
||||
<meta name="description" content="Les entreprises en vidéo." />
|
||||
</Head>
|
||||
|
||||
<meta name="twitter:card" content="summary"/>
|
||||
<meta name="twitter:site" content="@TalentsTube"/>
|
||||
<meta name="twitter:title" content="Les entreprises qui recrutent en vidéo | TalentsTube"/>
|
||||
<meta name="twitter:description" content="Découvrez les entreprises qui recrutent en vidéo, elles dévoilent leurs marques employeur et leurs offres d'emploi en vidéo. Postulez rapidement à l'offre qui vous convient."/>
|
||||
<meta name="twitter:image" content=""/>
|
||||
|
||||
|
||||
<meta property="og:title" content="Les entreprises qui recrutent en vidéo | TalentsTube"/>
|
||||
<meta property="og:type" content="article"/>
|
||||
<meta property="og:image" content=""/>
|
||||
<meta property="og:description"
|
||||
content="Découvrez les entreprises qui recrutent en vidéo, elles dévoilent leurs marques employeur et leurs offres d'emploi en vidéo. Postulez rapidement à l'offre qui vous convient."/>
|
||||
<meta property="og:site_name" content="Talents Tube"/>
|
||||
<meta property="og:url"
|
||||
content=""/>
|
||||
|
||||
</Head> */}
|
||||
<OgHead seo_title="Entreprises qui recrutent – Talents Tube"
|
||||
seo_description="Les entreprises en vidéo."
|
||||
seo_url={socialShareUrl}
|
||||
image={imgUrl}
|
||||
seo_key="Recrutement, video"
|
||||
|
||||
></OgHead>
|
||||
<Typography gutterBottom component="h1"
|
||||
className={classes.title}>
|
||||
Les entreprises en <span className={classes.primary}>vidéo</span>
|
||||
|
||||
@@ -120,7 +120,7 @@ function Help(props) {
|
||||
<img alt="talents-tube" src='/static/images/help/image-aide-web-app.svg' className={classes.teamworkingImg} />
|
||||
<Typography gutterBottom component="h2"
|
||||
className={classes.subTitle}>
|
||||
Découvrez les offres d'emploi en vidéo
|
||||
Comment postuler à une offre d’emploi en vidéo
|
||||
</Typography>
|
||||
<VideoVimeo videoId='356411947' classesOverride={classes.video} autoplay='0'/>
|
||||
<Typography
|
||||
@@ -128,15 +128,8 @@ function Help(props) {
|
||||
gutterBottom>
|
||||
Suivez nos conseils pour postuler simplement aux offres d’emploi. La vidéo de motivation vous permet de dévoiler votre personnalité, vos compétences, votre parcours, vos valeurs, vos soft-skills, votre ambition,…. et bien plus encore.
|
||||
</Typography>
|
||||
<Typography gutterBottom component="h2"
|
||||
className={classes.subTitle}>
|
||||
Vous possédez déjà un CV vidéo ?
|
||||
</Typography>
|
||||
<Typography
|
||||
className={classes.text}
|
||||
gutterBottom>
|
||||
Vous n'avez pas trouvé votre bonheur dans nos offres d'emploi, mais vous souhaitez diffuser votre <span className={classes.bold}>CV vidéo à l'ensemble de notre communauté de talents.</span> <br></br> Découvrez les vidéos de nos talents sur notre CV vidéothèque.
|
||||
</Typography>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
<Footer />
|
||||
|
||||
@@ -90,6 +90,7 @@ class Offres extends React.Component {
|
||||
<Head>
|
||||
<title key="title">Offres d’emploi en vidéo – Talents Tube</title>
|
||||
<meta name="description" content="Les offres d'emploi en vidéo." />
|
||||
<meta key="robots" name="robots" content="noindex, nofollow"></meta>
|
||||
|
||||
</Head>
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ import { isEmpty } from "lodash"
|
||||
import NoResult from './../components/atoms/NoResult';
|
||||
import Head from 'next/head'
|
||||
import dynamic from 'next/dynamic'
|
||||
import OgHead from '../components/atoms/OgHead';
|
||||
import getConfig from 'next/config'
|
||||
|
||||
const VideoSlider = dynamic(() => import('../components/organisms/ShortVideoHooker'), {
|
||||
ssr: false
|
||||
@@ -34,7 +36,7 @@ const TileOffre = dynamic(() => import('../components/organisms/TileOffre'), {
|
||||
const Footer = dynamic(() => import('../components/organisms/Footer'), {
|
||||
ssr: false
|
||||
});
|
||||
|
||||
const { publicRuntimeConfig } = getConfig();
|
||||
const styles = theme => ({
|
||||
root: {
|
||||
position: 'relative',
|
||||
@@ -154,12 +156,20 @@ class Index extends React.Component {
|
||||
}
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
|
||||
const socialShareUrl = typeof window !== 'undefined' ? window.location
|
||||
: publicRuntimeConfig.frontServerUrl ;
|
||||
const DefaultUrl = publicRuntimeConfig.symphonyUrl + "/img/default_picture_svg"
|
||||
const imgUrl = DefaultUrl
|
||||
return (
|
||||
<Layout>
|
||||
<Head>
|
||||
<title key="title"> Talents tube - La recherche d'emploi en vidéo</title>
|
||||
<meta name="description" content="Talents Tube est la première plateforme réservée aux offres d'emploi et aux CV vidéos. Découvrez un nouvelle méthode de recrutement ! Installez notre application." />
|
||||
</Head>
|
||||
<OgHead seo_title="Entreprises qui recrutent – Talents Tube"
|
||||
seo_description="Les entreprises en vidéo."
|
||||
seo_url={socialShareUrl}
|
||||
image={imgUrl}
|
||||
seo_key="Recrutement, video"
|
||||
|
||||
></OgHead>
|
||||
<div className={classes.container}>
|
||||
|
||||
<VideoSlider />
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import React from 'react';
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
import { Grid } from '@material-ui/core';
|
||||
import Layout from "../components/templates/Layout";
|
||||
import AccountProfile from "../components/organisms/AccountProfile";
|
||||
import AccountVideoPres from "../components/organisms/AccountVideoPres";
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
root: {
|
||||
padding: theme.spacing(4)
|
||||
}
|
||||
}));
|
||||
|
||||
const Account = () => {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<div className={classes.root}>
|
||||
<Grid
|
||||
container
|
||||
spacing={4}
|
||||
direction="row"
|
||||
justify="space-between"
|
||||
alignItems="flex-start"
|
||||
>
|
||||
<Grid
|
||||
item
|
||||
lg={4}
|
||||
md={6}
|
||||
xl={4}
|
||||
xs={12}
|
||||
>
|
||||
<AccountProfile />
|
||||
<div><br/></div>
|
||||
<AccountVideoPres />
|
||||
</Grid>
|
||||
<Grid
|
||||
item
|
||||
lg={8}
|
||||
md={6}
|
||||
xl={8}
|
||||
xs={12}
|
||||
>
|
||||
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
export default Account;
|
||||
@@ -0,0 +1,43 @@
|
||||
import React from 'react';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import Layout from "../components/templates/Layout";
|
||||
import AccountProfile from "../components/organisms/AccountProfile";
|
||||
import Head from 'next/head'
|
||||
// import AdBlockDetect from 'react-ad-block-detect';
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
root: {
|
||||
width: '100%',
|
||||
},
|
||||
button: {
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
completed: {
|
||||
display: 'inline-block',
|
||||
},
|
||||
instructions: {
|
||||
marginTop: theme.spacing(1),
|
||||
marginBottom: theme.spacing(1),
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
|
||||
export default function HorizontalNonLinearStepper() {
|
||||
const classes = useStyles();
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Head>
|
||||
<title key="title">Profile – Talents Tube</title>
|
||||
</Head>
|
||||
<div >
|
||||
<AccountProfile />
|
||||
</div>
|
||||
|
||||
{/* <AdBlockDetect>
|
||||
<p>AdBlocks a été détecté. Pour que Talents Tube puisse fonctionner correctement, veuillez désactiver Ad Blocks</p>
|
||||
</AdBlockDetect> */}
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"name": "Talents Tube",
|
||||
"short_name": "Talents Tube",
|
||||
"lang": "fr",
|
||||
"orientation":"portrait",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco16x16.png",
|
||||
"sizes": "16x16",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco32x32.png",
|
||||
"sizes": "32x32",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco57x57.png",
|
||||
"sizes": "57x57",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco114x114.png",
|
||||
"sizes": "114x114",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco128x128.png",
|
||||
"sizes": "128x128",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco152x152.png",
|
||||
"sizes": "152x152",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco180x180.png",
|
||||
"sizes": "180x180",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco256x256.png",
|
||||
"sizes": "256x256",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#1689FB",
|
||||
"theme_color": "#1689FB",
|
||||
"gcm_sender_id":"103953800507"
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,35 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="73.762" height="69.644" viewBox="0 0 73.762 69.644">
|
||||
<g id="Import" transform="translate(0 13.219)">
|
||||
<g id="Groupe_7895" data-name="Groupe 7895" transform="translate(53.502 2.911) rotate(131)">
|
||||
<rect id="Rectangle_316" data-name="Rectangle 316" width="37.465" height="23.87" transform="translate(0.976 1.838)"/>
|
||||
<rect id="Rectangle_321" data-name="Rectangle 321" width="4.656" height="4.656" transform="translate(2.783 18.724)" fill="#fff"/>
|
||||
<rect id="Rectangle_398" data-name="Rectangle 398" width="1.656" height="12.656" transform="translate(2.781 4.725)" fill="#fff"/>
|
||||
<rect id="Rectangle_399" data-name="Rectangle 399" width="1.656" height="8.656" transform="translate(5.781 8.725)" fill="#fff"/>
|
||||
<rect id="Rectangle_400" data-name="Rectangle 400" width="1.656" height="18.656" transform="translate(10.781 4.725)" fill="#fff"/>
|
||||
<path id="Tracé_396" data-name="Tracé 396" d="M0-3H1.656V8.656H0Z" transform="translate(13.781 14.724)" fill="#fff"/>
|
||||
<rect id="Rectangle_401" data-name="Rectangle 401" width="1.656" height="18.656" transform="translate(17.781 4.725)" fill="#fff"/>
|
||||
<path id="Tracé_397" data-name="Tracé 397" d="M0-3H1.656V15.656H0Z" transform="translate(20.781 7.725)" fill="#fff"/>
|
||||
<path id="Tracé_398" data-name="Tracé 398" d="M0-3H1.656V10.788H0Z" transform="translate(23.781 12.593)" fill="#fff"/>
|
||||
<rect id="Rectangle_402" data-name="Rectangle 402" width="1.656" height="18.656" transform="translate(27.781 4.725)" fill="#fff"/>
|
||||
<path id="Tracé_399" data-name="Tracé 399" d="M0,9H1.656v6.656H0Z" transform="translate(33.781 7.725)" fill="#fff"/>
|
||||
<path id="Tracé_400" data-name="Tracé 400" d="M0-3H1.656V10.788H0Z" transform="translate(30.781 12.593)" fill="#fff"/>
|
||||
</g>
|
||||
<path id="Tracé_279" data-name="Tracé 279" d="M217.367,282.859l-6.93,6.93-48.507-6.93L155,275.93l6.93-6.93h55.437Z" transform="translate(-155 -233.363)" fill="#155ee4"/>
|
||||
<path id="Tracé_280" data-name="Tracé 280" d="M173,269v6.93h48.507l6.93-6.93Z" transform="translate(-166.07 -233.363)" opacity="0.25"/>
|
||||
<g id="Groupe_7897" data-name="Groupe 7897" transform="translate(28.442 19.099)">
|
||||
<g id="Groupe_7896" data-name="Groupe 7896" transform="translate(3.551)">
|
||||
<path id="Tracé_281" data-name="Tracé 281" d="M239.065,257.45a.488.488,0,0,1-.231-.039.939.939,0,0,1-.693-1.155,50.925,50.925,0,0,0,1.463-12.088,51.857,51.857,0,0,0-.346-6.006.969.969,0,1,1,1.925-.231,55.915,55.915,0,0,1,.346,6.237,52.807,52.807,0,0,1-1.5,12.55A.952.952,0,0,1,239.065,257.45Z" transform="translate(-238.104 -232.827)" fill="#25d89a"/>
|
||||
<path id="Tracé_282" data-name="Tracé 282" d="M240.5,229.337a1.021,1.021,0,0,1-.962-.808c-.077-.462-.154-.885-.27-1.347a.944.944,0,0,1,1.848-.385c.077.462.192.924.269,1.386a.969.969,0,0,1-.77,1.116A.141.141,0,0,1,240.5,229.337Z" transform="translate(-238.804 -226.042)" fill="#25d89a"/>
|
||||
</g>
|
||||
<path id="Tracé_283" data-name="Tracé 283" d="M233.084,279.525l-4.042-6.237a.972.972,0,1,1,1.617-1.078l3,4.62,4.62-3a.972.972,0,0,1,1.078,1.617Z" transform="translate(-228.879 -254.171)" fill="#25d89a"/>
|
||||
</g>
|
||||
<path id="Tracé_284" data-name="Tracé 284" d="M316.393,300.545h-9.008a.385.385,0,1,1,0-.77h8.7l5.505-5.659a.381.381,0,1,1,.539.539Z" transform="translate(-248.483 -248.739)" fill="#25d89a"/>
|
||||
<path id="Tracé_285" data-name="Tracé 285" d="M317.93,299.2h-6.545a.385.385,0,0,1,0-.77h6.237l4.2-4.312a.381.381,0,1,1,.539.539Z" transform="translate(-250.943 -248.739)" fill="#fa6362"/>
|
||||
<g id="Groupe_7899" data-name="Groupe 7899" transform="translate(30.144 40.641)">
|
||||
<g id="Groupe_7898" data-name="Groupe 7898" transform="translate(0 0)">
|
||||
<path id="Tracé_286" data-name="Tracé 286" d="M233.3,282l2.5,3.811,5.89-3.811h-3.542l-.654.423a1.636,1.636,0,0,0,.077-.423H233.3Z" transform="translate(-233.3 -282)" fill="#21b77e"/>
|
||||
</g>
|
||||
</g>
|
||||
<rect id="Rectangle_325" data-name="Rectangle 325" width="55.437" height="13.859" transform="translate(0 42.566)" fill="#1689fb"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="73.762" height="56.426" viewBox="0 0 73.762 56.426"><defs><style>.a{fill:#fff;}.b{fill:#155ee4;}.c{opacity:0.25;}.d{fill:#25d89a;}.e{fill:#fa6362;}.f{fill:#21b77e;}.g{fill:#1689fb;}</style></defs><g transform="translate(0 0)"><g transform="translate(9.499)"><rect width="42.463" height="23.869" transform="translate(0 3.769) rotate(-5.093)"/><rect class="a" width="2.656" height="2.656" transform="translate(1.401 6.158) rotate(-5.093)"/><rect class="a" width="2.656" height="2.656" transform="translate(1.866 11.472) rotate(-5.093)"/><rect class="a" width="2.656" height="2.656" transform="translate(2.327 16.747) rotate(-5.093)"/><rect class="a" width="2.656" height="2.656" transform="translate(2.826 22.019) rotate(-5.093)"/><rect class="a" width="2.656" height="2.656" transform="translate(38.67 2.848) rotate(-5.093)"/><rect class="a" width="2.656" height="2.656" transform="translate(39.131 8.123) rotate(-5.093)"/><rect class="a" width="2.656" height="2.656" transform="translate(39.633 13.433) rotate(-5.093)"/><rect class="a" width="2.656" height="2.656" transform="translate(40.094 18.708) rotate(-5.093)"/><path class="a" d="M229.4,202.9l6.275,3.311-5.582,4.35Z" transform="translate(-210.257 -192.71)"/></g><path class="b" d="M217.367,282.859l-6.93,6.93-48.507-6.93L155,275.93l6.93-6.93h55.437Z" transform="translate(-155 -233.363)"/><path class="c" d="M173,269v6.93h48.507l6.93-6.93Z" transform="translate(-166.07 -233.363)"/><g transform="translate(28.442 19.099)"><g transform="translate(3.551)"><path class="d" d="M239.065,257.45a.488.488,0,0,1-.231-.039.939.939,0,0,1-.693-1.155,50.925,50.925,0,0,0,1.463-12.088,51.857,51.857,0,0,0-.346-6.006.969.969,0,0,1,1.925-.231,55.915,55.915,0,0,1,.346,6.237,52.807,52.807,0,0,1-1.5,12.55A.952.952,0,0,1,239.065,257.45Z" transform="translate(-238.104 -232.827)"/><path class="d" d="M240.5,229.337a1.021,1.021,0,0,1-.962-.808c-.077-.462-.154-.885-.27-1.347a.944.944,0,0,1,1.848-.385c.077.462.192.924.269,1.386a.969.969,0,0,1-.77,1.116A.141.141,0,0,1,240.5,229.337Z" transform="translate(-238.804 -226.042)"/></g><path class="d" d="M233.084,279.525l-4.042-6.237a.972.972,0,1,1,1.617-1.078l3,4.62,4.62-3a.972.972,0,0,1,1.078,1.617Z" transform="translate(-228.879 -254.171)"/></g><path class="d" d="M316.393,300.545h-9.008a.385.385,0,1,1,0-.77h8.7l5.505-5.659a.381.381,0,1,1,.539.539Z" transform="translate(-248.483 -248.739)"/><path class="e" d="M317.93,299.2h-6.545a.385.385,0,0,1,0-.77h6.237l4.2-4.312a.381.381,0,1,1,.539.539Z" transform="translate(-250.943 -248.739)"/><g transform="translate(30.144 40.641)"><g transform="translate(0 0)"><path class="f" d="M233.3,282l2.5,3.811,5.89-3.811h-3.542l-.654.423a1.636,1.636,0,0,0,.077-.423H233.3Z" transform="translate(-233.3 -282)"/></g></g><rect class="g" width="55.437" height="13.859" transform="translate(0 42.566)"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="65.694" height="55" viewBox="0 0 65.694 55"><defs><style>.a{fill:#fff;}.b{fill:#fa6362;}.c{fill:#25d89a;}.d{fill:#d0e7fe;}.e{fill:#f8fcff;}</style></defs><g transform="translate(6.99 12.604)"><rect class="a" width="0.382" height="6.302" transform="translate(8.135)"/><rect class="b" width="0.382" height="6.302" transform="translate(8.25 10.503)"/><rect class="b" width="6.302" height="0.382" transform="translate(0 8.288)"/><rect class="a" width="6.302" height="0.382" transform="translate(10.503 8.135)"/><rect class="a" width="0.382" height="4.125" transform="translate(4.324 4.686) rotate(-45)"/><rect class="a" width="0.382" height="4.125" transform="translate(9.254 9.481) rotate(-45)"/><rect class="b" width="4.125" height="0.382" transform="translate(4.392 12.164) rotate(-45)"/><rect class="a" width="4.125" height="0.382" transform="translate(9.186 7.288) rotate(-45)"/></g><path class="c" d="M249.806,254.569H236.819A3.831,3.831,0,0,1,233,250.75v-9.931A3.831,3.831,0,0,1,236.819,237h12.986a3.831,3.831,0,0,1,3.819,3.819v9.931A3.831,3.831,0,0,1,249.806,254.569Z" transform="translate(-206.646 -214.465)"/><path class="d" d="M235.875,281.75,229,288.625l-48.125-6.875L174,274.875,180.875,268h55Z" transform="translate(-170.181 -233.625)"/><rect class="a" width="55" height="13.75" transform="translate(3.819 41.25)"/><path class="d" d="M185.58,296.5h-9.549a3.748,3.748,0,0,1-2.483-.917c-.8-.687.382-8.441.382-9.587H189.4v6.684A3.831,3.831,0,0,1,185.58,296.5Z" transform="translate(-169.73 -244.75)"/><path d="M177.368,258.556h-9.549A3.831,3.831,0,0,1,164,254.736V231.819A3.831,3.831,0,0,1,167.819,228h9.549a3.831,3.831,0,0,1,3.819,3.819v22.917A3.831,3.831,0,0,1,177.368,258.556Z" transform="translate(-164 -208.903)"/><path class="a" d="M178.533,259.028h-9.778c-2.1,0-3.056-1.719-3.056-3.819V233.819c0-2.1.955-3.819,3.056-3.819h9.778c2.1,0,3.056,1.719,3.056,3.819v21.389C181.589,257.309,180.634,259.028,178.533,259.028Z" transform="translate(-165.051 -210.139)"/><circle class="c" cx="6.875" cy="6.875" r="6.875" transform="translate(29.792 6.875)"/><path class="c" d="M180.042,279h-1.3A3.749,3.749,0,0,1,175,275.254v-6.111a3.749,3.749,0,0,1,3.743-3.743h1.3a3.749,3.749,0,0,1,3.743,3.743v6.111A3.749,3.749,0,0,1,180.042,279Z" transform="translate(-170.799 -232.018)"/><circle class="c" cx="2.941" cy="2.941" r="2.941" transform="translate(5.653 26.736)"/><path d="M181.589,282.1v5.309c0,2.1-.955,3.819-3.056,3.819h-9.778c-2.1,0-3.056-1.719-3.056-3.819V282.1Z" transform="translate(-165.051 -242.34)"/><circle class="a" cx="1.91" cy="1.91" r="1.91" transform="translate(6.875 42.396)"/><circle class="b" cx="1.26" cy="1.26" r="1.26" transform="translate(7.524 43.045)"/><g transform="translate(48.15)"><path class="e" d="M303.981,180.368a8.149,8.149,0,0,0-12.069,10.924,3.012,3.012,0,0,1-1.3,1.49.77.77,0,0,0,.229,1.451,2.89,2.89,0,0,0,.573.038h0a5.282,5.282,0,0,0,2.941-.955,8.018,8.018,0,0,0,3.858.955,8.183,8.183,0,0,0,5.767-2.368,7.961,7.961,0,0,0,2.368-5.767A8.183,8.183,0,0,0,303.981,180.368Zm-.649,10.885a7.129,7.129,0,0,1-5.118,2.1,7.236,7.236,0,0,1-3.667-.993.543.543,0,0,0-.229-.076.552.552,0,0,0-.267.076,4.7,4.7,0,0,1-2.559.955,4.748,4.748,0,0,0,1.375-1.91.48.48,0,0,0-.076-.5,7.219,7.219,0,0,1,.306-9.892,7.129,7.129,0,0,1,5.118-2.1,7.219,7.219,0,0,1,5.118,12.337Z" transform="translate(-290.064 -178)"/><path class="e" d="M308.557,192.3h-6.8a.458.458,0,1,0,0,.917h6.8a.458.458,0,1,0,0-.917Z" transform="translate(-297.009 -186.838)"/><path class="e" d="M308.557,198.1h-6.8a.458.458,0,1,0,0,.917h6.8a.458.458,0,1,0,0-.917Z" transform="translate(-297.009 -190.423)"/><path class="e" d="M306.265,203.9h-4.507a.458.458,0,1,0,0,.917h4.507a.441.441,0,0,0,.458-.458A.464.464,0,0,0,306.265,203.9Z" transform="translate(-297.009 -194.008)"/></g></svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
@@ -0,0 +1,12 @@
|
||||
<svg id="Groupe_8099" data-name="Groupe 8099" xmlns="http://www.w3.org/2000/svg" width="65.497" height="40.618" viewBox="0 0 65.497 40.618">
|
||||
<path id="Tracé_401" data-name="Tracé 401" d="M0,0H62.62V35.2H0Z" transform="translate(0 5.559) rotate(-5.093)"/>
|
||||
<rect id="Rectangle_317" data-name="Rectangle 317" width="3.917" height="3.917" transform="translate(2.066 9.081) rotate(-5.093)" fill="#fff"/>
|
||||
<rect id="Rectangle_318" data-name="Rectangle 318" width="3.917" height="3.917" transform="translate(2.751 16.917) rotate(-5.093)" fill="#fff"/>
|
||||
<rect id="Rectangle_319" data-name="Rectangle 319" width="3.917" height="3.917" transform="translate(3.431 24.696) rotate(-5.093)" fill="#fff"/>
|
||||
<rect id="Rectangle_320" data-name="Rectangle 320" width="3.917" height="3.917" transform="translate(4.167 32.47) rotate(-5.093)" fill="#fff"/>
|
||||
<rect id="Rectangle_321" data-name="Rectangle 321" width="3.917" height="3.917" transform="translate(57.023 4.199) rotate(-5.093)" fill="#fff"/>
|
||||
<rect id="Rectangle_322" data-name="Rectangle 322" width="3.917" height="3.917" transform="translate(57.703 11.978) rotate(-5.093)" fill="#fff"/>
|
||||
<rect id="Rectangle_323" data-name="Rectangle 323" width="3.917" height="3.917" transform="translate(58.444 19.809) rotate(-5.093)" fill="#fff"/>
|
||||
<rect id="Rectangle_324" data-name="Rectangle 324" width="3.917" height="3.917" transform="translate(59.124 27.588) rotate(-5.093)" fill="#fff"/>
|
||||
<text id="_" data-name="?" transform="matrix(0.996, -0.087, 0.087, 0.996, 26.298, 31.189)" fill="#fff" font-size="29" font-family="Roboto-Bold, Roboto" font-weight="700"><tspan x="0" y="0">?</tspan></text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 400 400" style="enable-background:new 0 0 400 400;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#F3F9FF;}
|
||||
.st1{fill:#1689FB;}
|
||||
</style>
|
||||
<g>
|
||||
<circle class="st0" cx="200.32" cy="200.12" r="194.12"/>
|
||||
<circle class="st1" cx="200.32" cy="144.75" r="69.37"/>
|
||||
<path class="st1" d="M265.84,233.39H134.8c-21.2,0-38.54,17.34-38.54,38.54v92.09c30.08,19.14,65.77,30.22,104.06,30.22
|
||||
s73.98-11.09,104.06-30.22v-92.09C304.38,250.73,287.04,233.39,265.84,233.39z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 755 B |
@@ -0,0 +1,42 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1920" height="1080" viewBox="0 0 1920 1080">
|
||||
<defs>
|
||||
<radialGradient id="radial-gradient" cx="0.403" cy="0.395" r="1.057" gradientTransform="translate(0.146 -0.002) scale(0.637 1.004)" gradientUnits="objectBoundingBox">
|
||||
<stop offset="0" stop-color="#155ee4"/>
|
||||
<stop offset="1" stop-color="#8dc6ff"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="radial-gradient-2" cx="0.319" cy="0.609" r="1.639" gradientTransform="matrix(0.358, 0.411, -0.161, 0.912, 0.303, -0.077)" gradientUnits="objectBoundingBox">
|
||||
<stop offset="0" stop-color="#1689fb"/>
|
||||
<stop offset="1" stop-color="#54d7e6"/>
|
||||
</radialGradient>
|
||||
<filter id="Tracé_105" x="781.117" y="346.457" width="822.06" height="723.468" filterUnits="userSpaceOnUse">
|
||||
<feOffset dy="-27" input="SourceAlpha"/>
|
||||
<feGaussianBlur stdDeviation="43" result="blur"/>
|
||||
<feFlood flood-opacity="0.161"/>
|
||||
<feComposite operator="in" in2="blur"/>
|
||||
<feComposite in="SourceGraphic"/>
|
||||
</filter>
|
||||
<radialGradient id="radial-gradient-3" cx="0.524" cy="0.704" r="0.76" gradientTransform="matrix(-0.323, -0.938, 0.872, -0.347, 0.079, 1.439)" gradientUnits="objectBoundingBox">
|
||||
<stop offset="0" stop-color="#1689fb" stop-opacity="0.6"/>
|
||||
<stop offset="1" stop-color="#54d7e6" stop-opacity="0.6"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="radial-gradient-4" cx="0.447" cy="0.416" r="1.057" gradientTransform="translate(0.162 -0.002) scale(0.637 1.004)" xlink:href="#radial-gradient-2"/>
|
||||
<radialGradient id="radial-gradient-5" cx="0.915" cy="0.609" r="1.568" gradientTransform="matrix(0.184, 0.259, -0.081, 1.582, 0.795, -0.591)" gradientUnits="objectBoundingBox">
|
||||
<stop offset="0" stop-color="#fff" stop-opacity="0.475"/>
|
||||
<stop offset="1" stop-color="#fff" stop-opacity="0"/>
|
||||
</radialGradient>
|
||||
<clipPath id="clip-Youtube_4">
|
||||
<rect width="1920" height="1080"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g id="Youtube_4" data-name="Youtube – 4" clip-path="url(#clip-Youtube_4)">
|
||||
<rect width="1920" height="1080" fill="#fff"/>
|
||||
<path id="Tracé_106" data-name="Tracé 106" d="M12369.043,2300.3s-141.664-1034.519,765.283-1034.519c214.947,0,511.67,196.543,697.428,58.283,408.648-304.154,352.379-1089.441,934.215-1425.363,574.066-331.437,1213.727-72.058,1566.926,55.155s-251.332,2385.215-251.332,2385.215" transform="translate(-14153.795 -949.145)" fill="url(#radial-gradient)"/>
|
||||
<path id="Tracé_101" data-name="Tracé 101" d="M11762.942,398.383s55.409-341.747,332.711-280.328,290.146,146.232,543.427,0,251.155-350.119,595.736-131.889,887.4,587.9,856.8,724.362-2328.67,85.529-2328.67,85.529Z" transform="translate(-11803 322)" fill="url(#radial-gradient-2)"/>
|
||||
<g transform="matrix(1, 0, 0, 1, 0, 0)" filter="url(#Tracé_105)">
|
||||
<path id="Tracé_105-2" data-name="Tracé 105" d="M12760.129,408.192c118.317,8.328,220.3,90.749,319.038-145.828s198.01,114.584,198.01,114.584l-493.051,268.977S12641.812,399.864,12760.129,408.192Z" transform="translate(-11803 322)" fill="#fff"/>
|
||||
</g>
|
||||
<path id="Tracé_102" data-name="Tracé 102" d="M534.949,72.539C818.824,72.539,1028,230.126,1028,514s-230.126,514-514,514S0,797.874,0,514,251.075,72.539,534.949,72.539Z" transform="translate(-200 201)" fill="url(#radial-gradient-3)"/>
|
||||
<path id="Tracé_103" data-name="Tracé 103" d="M12364.285,780.991s-57.706-421.407,311.735-421.407c87.558,0,208.426,80.061,284.094,23.741,166.461-123.9,143.54-443.779,380.548-580.615,233.844-135.01,494.406-29.353,638.281,22.467s-102.379,971.607-102.379,971.607" transform="translate(-11803 322)" fill="url(#radial-gradient-4)"/>
|
||||
<path id="Tracé_107" data-name="Tracé 107" d="M11779.612,537.613s427.922-55.028,1287.072,146.785,1121.613,162.176,1983.9-332.047,198.711,587.6,198.711,587.6L11739.1,909.484Z" transform="translate(-12748.872 179.263)" fill="url(#radial-gradient-5)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 254 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 21 KiB |
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="277.043" height="328" viewBox="0 0 277.043 328">
|
||||
<g id="Groupe_7859" data-name="Groupe 7859" transform="translate(-4.489 -11.849)">
|
||||
<circle id="Ellipse_105" data-name="Ellipse 105" cx="40.594" cy="40.594" r="40.594" transform="translate(119.489 270.847) rotate(-90.438)"/>
|
||||
<circle id="Ellipse_106" data-name="Ellipse 106" cx="40.594" cy="40.594" r="40.594" transform="translate(119.554 163.329) rotate(-90.438)"/>
|
||||
<circle id="Ellipse_107" data-name="Ellipse 107" cx="48.799" cy="48.799" r="48.799" transform="translate(5.344 225.063) rotate(-90.438)"/>
|
||||
<circle id="Ellipse_108" data-name="Ellipse 108" cx="48.799" cy="48.799" r="48.799" transform="matrix(-0.008, -1, 1, -0.008, 5.253, 110.195)"/>
|
||||
<circle id="Ellipse_109" data-name="Ellipse 109" cx="48.799" cy="48.799" r="48.799" transform="translate(5.235 339.849) rotate(-90.438)"/>
|
||||
<circle id="Ellipse_110" data-name="Ellipse 110" cx="33.901" cy="33.901" r="33.901" transform="translate(213.73 210.028) rotate(-90.438)"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 370 B |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 709 B |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 127 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 33 KiB |
@@ -0,0 +1,144 @@
|
||||
///
|
||||
/// Thomas Berrod
|
||||
/// A generic service worker
|
||||
/// inspired by https://github.com/gauntface/web-push-book
|
||||
///
|
||||
|
||||
; (function () {
|
||||
"use strict";
|
||||
|
||||
self.importScripts('/static/js/analytics-helper.js');
|
||||
|
||||
function focusWindow(event) {
|
||||
const url = event.notification.data["link"]; //TODO : there are 2 web server now...
|
||||
const urlToOpen = new URL(url, self.location.origin).href;
|
||||
|
||||
const promiseChain = clients.matchAll({
|
||||
type: 'window',
|
||||
includeUncontrolled: true
|
||||
})
|
||||
.then((windowClients) => {
|
||||
let matchingClient = null;
|
||||
|
||||
for (let i = 0; i < windowClients.length; i++) {
|
||||
const windowClient = windowClients[i];
|
||||
if (windowClient.url === urlToOpen) {
|
||||
matchingClient = windowClient;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (matchingClient) {
|
||||
return matchingClient.focus();
|
||||
} else {
|
||||
return clients.openWindow(urlToOpen);
|
||||
}
|
||||
});
|
||||
event.waitUntil(promiseChain);
|
||||
}
|
||||
|
||||
function isClientFocused() {
|
||||
return clients.matchAll({
|
||||
type: 'window',
|
||||
includeUncontrolled: true
|
||||
})
|
||||
.then((windowClients) => {
|
||||
let clientIsFocused = false;
|
||||
|
||||
for (let i = 0; i < windowClients.length; i++) {
|
||||
const windowClient = windowClients[i];
|
||||
if (windowClient.focused) {
|
||||
clientIsFocused = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return clientIsFocused;
|
||||
});
|
||||
}
|
||||
|
||||
function demoMustShowNotificationCheck(event) {
|
||||
const promiseChain = isClientFocused()
|
||||
.then((clientIsFocused) => {
|
||||
if (clientIsFocused) {
|
||||
|
||||
//could alert
|
||||
demoSendMessageToPage(event);
|
||||
return;
|
||||
}
|
||||
|
||||
// Client isn't focused, we need to show a notification.
|
||||
return self.registration.showNotification(
|
||||
event.data.json().notification.title,
|
||||
event.data.json().notification);
|
||||
});
|
||||
|
||||
event.waitUntil(promiseChain);
|
||||
}
|
||||
|
||||
function demoSendMessageToPage(event) {
|
||||
|
||||
const promiseChain = isClientFocused()
|
||||
.then((clientIsFocused) => {
|
||||
if (clientIsFocused) {
|
||||
clients.matchAll({
|
||||
type: 'window',
|
||||
includeUncontrolled: true
|
||||
}).then((windowClients) => {
|
||||
let clientIsFocused = false;
|
||||
|
||||
for (let i = 0; i < windowClients.length; i++) {
|
||||
const windowClient = windowClients[i];
|
||||
if (windowClient.focused) {
|
||||
console.info('Posting message to page');
|
||||
windowClient.postMessage(event.data.json().notification);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
return self.registration.showNotification('No focused windows', {
|
||||
body: 'Had to show a notification instead of messaging each page.'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
event.waitUntil(promiseChain);
|
||||
}
|
||||
|
||||
self.addEventListener('push', function (event) {
|
||||
|
||||
demoMustShowNotificationCheck(event);
|
||||
|
||||
});
|
||||
|
||||
self.addEventListener('notificationclick', function (event) {
|
||||
event.waitUntil(
|
||||
sendAnalyticsEvent('click', 'Push', event.notification.title)
|
||||
);
|
||||
|
||||
event.notification.close();
|
||||
switch (event.notification.tag) {
|
||||
case 'open-window':
|
||||
focusWindow(event);
|
||||
break;
|
||||
default:
|
||||
//
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
const notificationCloseAnalytics = () => {
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
self.addEventListener('notificationclose', function (event) {
|
||||
const dismissedNotification = event.notification;
|
||||
event.waitUntil(
|
||||
sendAnalyticsEvent('close', 'Push', event.notification.title)
|
||||
);
|
||||
const promiseChain = notificationCloseAnalytics();
|
||||
event.waitUntil(promiseChain);
|
||||
});
|
||||
|
||||
})()
|
||||
|
After Width: | Height: | Size: 5.5 KiB |
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// INFO : this file is required to track push event inside the serviceworker
|
||||
//
|
||||
|
||||
// Set this to your tracking ID
|
||||
var trackingId = 'UA-98246968-6';
|
||||
|
||||
function sendAnalyticsEvent(eventAction, eventCategory, eventLabel) {
|
||||
'use strict';
|
||||
|
||||
console.info('Sending analytics event: ' + eventCategory + '/' + eventAction);
|
||||
|
||||
if (!trackingId) {
|
||||
console.error('You need your tracking ID in analytics-helper.js');
|
||||
console.error('Add this code:\nvar trackingId = \'UA-XXXXXXXX-X\';');
|
||||
// We want this to be a safe method, so avoid throwing unless absolutely necessary.
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
if (!eventAction && !eventCategory && !eventLabel) {
|
||||
console.warn('sendAnalyticsEvent() called with no eventAction or ' +
|
||||
'eventCategory or '+
|
||||
'eventLabel');
|
||||
// We want this to be a safe method, so avoid throwing unless absolutely necessary.
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return self.registration.pushManager.getSubscription()
|
||||
.then(function(subscription) {
|
||||
if (subscription === null) {
|
||||
throw new Error('No subscription currently available.');
|
||||
}
|
||||
|
||||
// Create hit data
|
||||
var payloadData = {
|
||||
// Version Number
|
||||
v: 1,
|
||||
// Client ID
|
||||
cid: subscription.endpoint,
|
||||
// Tracking ID
|
||||
tid: trackingId,
|
||||
// Hit Type
|
||||
t: 'event',
|
||||
// Event Category
|
||||
ec: eventCategory,
|
||||
// Event Action
|
||||
ea: eventAction,
|
||||
// Event Label
|
||||
el: eventLabel
|
||||
};
|
||||
|
||||
// Format hit data into URI
|
||||
var payloadString = Object.keys(payloadData)
|
||||
.filter(function(analyticsKey) {
|
||||
return payloadData[analyticsKey];
|
||||
})
|
||||
.map(function(analyticsKey) {
|
||||
return analyticsKey + '=' + encodeURIComponent(payloadData[analyticsKey]);
|
||||
})
|
||||
.join('&');
|
||||
|
||||
// Post to Google Analytics endpoint
|
||||
return fetch('https://www.google-analytics.com/collect', {
|
||||
method: 'post',
|
||||
body: payloadString
|
||||
});
|
||||
})
|
||||
.then(function(response) {
|
||||
if (!response.ok) {
|
||||
return response.text()
|
||||
.then(function(responseText) {
|
||||
throw new Error(
|
||||
'Bad response from Google Analytics:\n' + response.status
|
||||
);
|
||||
});
|
||||
} else {
|
||||
console.info(eventCategory + '/' + eventAction +
|
||||
'hit sent, check the Analytics dashboard');
|
||||
}
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.warn('Unable to send the analytics event', err);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright 2018 Google Inc.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
// importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.5.0/workbox-sw.js');
|
||||
|
||||
if (workbox) {
|
||||
console.info(`Yay! Workbox from backgroundSync-sw.js is loaded 🎉`);
|
||||
workbox.precaching.precacheAndRoute([]);
|
||||
|
||||
// const showNotification = (z) => {
|
||||
// console.log(z);
|
||||
// self.registration.showNotification('🔄 Votre message a été envoyé !', {
|
||||
// body: '🎉`🎉`🎉`'
|
||||
// });
|
||||
// };
|
||||
|
||||
const bgSyncPlugin = new workbox.backgroundSync.Plugin(
|
||||
'dashboardr-queue'
|
||||
);
|
||||
|
||||
const networkWithBackgroundSync = new workbox.strategies.NetworkOnly({
|
||||
plugins: [bgSyncPlugin],
|
||||
});
|
||||
|
||||
workbox.routing.registerRoute(
|
||||
/\/feedback/,
|
||||
networkWithBackgroundSync,
|
||||
'POST'
|
||||
);
|
||||
|
||||
} else {
|
||||
console.info(`Boo! Workbox from backgroundSync-sw.js didn't load 😬`);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
|
||||
|
||||
function promptInstall() {
|
||||
if (deferredPrompt == null) {
|
||||
console.info('beforeinstallprompt has not been triggerred yet');
|
||||
return;
|
||||
}
|
||||
// never show it if the app was launched standalone
|
||||
if (navigator.standalone) {
|
||||
return;
|
||||
}
|
||||
// Show the prompt
|
||||
deferredPrompt.prompt();
|
||||
// Wait for the user to respond to the prompt
|
||||
deferredPrompt.userChoice
|
||||
.then((choiceResult) => {
|
||||
if (choiceResult.outcome === 'accepted') {
|
||||
console.info('User accepted the A2HS prompt');
|
||||
} else {
|
||||
console.info('User dismissed the A2HS prompt');
|
||||
}
|
||||
deferredPrompt = null;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var deferredPrompt;
|
||||
|
||||
/// cf https://developers.google.com/web/fundamentals/app-install-banners/
|
||||
///
|
||||
window.addEventListener('beforeinstallprompt', (e) => {
|
||||
// Prevent Chrome 67 and earlier from automatically showing the prompt
|
||||
e.preventDefault();
|
||||
// Stash the event so it can be triggered later.
|
||||
deferredPrompt = e;
|
||||
});
|
||||
|
||||
window.addEventListener('appinstalled', (evt) => {
|
||||
console.info('a2hs installed');
|
||||
});
|
||||
|
||||
const isInStandaloneMode = () =>
|
||||
(window.matchMedia('(display-mode: standalone)').matches) || (window.navigator.standalone);
|
||||
|
||||
console.info('EdeclicLib loaded');
|
||||
|
||||
// window.addEventListener('error', function (e) {
|
||||
// var errorText = [
|
||||
// e.message,
|
||||
// 'URL: ' + e.filename,
|
||||
// 'Line: ' + e.lineno + ', Column: ' + e.colno,
|
||||
// 'Stack: ' + (e.error && e.error.stack || '(no stack trace)')
|
||||
// ].join('');
|
||||
// console.log(errorText);
|
||||
// // Example: log errors as visual output into the host page.
|
||||
// // Note: you probably don’t want to show such errors to users, or
|
||||
// // have the errors get indexed by Googlebot; however, it may
|
||||
// // be a useful feature while actively debugging the page.
|
||||
// var DOM_ID = 'rendering-debug-pre';
|
||||
// if (!document.getElementById(DOM_ID)) {
|
||||
// var log = document.createElement('pre');
|
||||
// log.id = DOM_ID;
|
||||
// log.style.whiteSpace = 'pre-wrap';
|
||||
// log.textContent = errorText;
|
||||
// if (!document.body) document.body = document.createElement('body');
|
||||
// document.body.insertBefore(log, document.body.firstChild);
|
||||
// } else {
|
||||
// document.getElementById(DOM_ID).textContent += ' ' + errorText;
|
||||
// }
|
||||
// });
|
||||
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"name": "Talents Tube",
|
||||
"short_name": "Talents Tube",
|
||||
"lang": "fr",
|
||||
"orientation":"portrait",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco16x16.png",
|
||||
"sizes": "16x16",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco32x32.png",
|
||||
"sizes": "32x32",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco57x57.png",
|
||||
"sizes": "57x57",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco114x114.png",
|
||||
"sizes": "114x114",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco128x128.png",
|
||||
"sizes": "128x128",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco152x152.png",
|
||||
"sizes": "152x152",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco180x180.png",
|
||||
"sizes": "180x180",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco256x256.png",
|
||||
"sizes": "256x256",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/static/images/icons/talentstubeIco512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#1689FB",
|
||||
"theme_color": "#1689FB",
|
||||
"gcm_sender_id":"103953800507"
|
||||
}
|
||||
@@ -2,6 +2,12 @@ import {
|
||||
UPLOAD_MEDIA_REQUEST,
|
||||
UPLOAD_MEDIA_SUCCESS,
|
||||
UPLOAD_MEDIA_FAILURE,
|
||||
UPLOAD_MEDIA_PRES_REQUEST,
|
||||
UPLOAD_MEDIA_PRES_FAILURE,
|
||||
UPLOAD_MEDIA_PRES_SUCCESS,
|
||||
UPLOAD_MEDIA_CV_REQUEST,
|
||||
UPLOAD_MEDIA_CV_FAILURE,
|
||||
UPLOAD_MEDIA_CV_SUCCESS,
|
||||
} from "../types";
|
||||
|
||||
export function media(state = {
|
||||
@@ -24,6 +30,40 @@ export function media(state = {
|
||||
errors: action.errors,
|
||||
loading: false
|
||||
};
|
||||
case UPLOAD_MEDIA_PRES_REQUEST:
|
||||
return {
|
||||
...state,
|
||||
loading: true
|
||||
};
|
||||
case UPLOAD_MEDIA_PRES_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
...action.res.data,
|
||||
loading: false
|
||||
};
|
||||
case UPLOAD_MEDIA_PRES_FAILURE:
|
||||
return {
|
||||
...state,
|
||||
errors: action.errors,
|
||||
loading: false
|
||||
};
|
||||
case UPLOAD_MEDIA_CV_REQUEST:
|
||||
return {
|
||||
...state,
|
||||
loading: true
|
||||
};
|
||||
case UPLOAD_MEDIA_CV_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
...action.res.data,
|
||||
loading: false
|
||||
};
|
||||
case UPLOAD_MEDIA_CV_FAILURE:
|
||||
return {
|
||||
...state,
|
||||
errors: action.errors,
|
||||
loading: false
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
} from './sagas/userSaga.js'
|
||||
import { requestAdsSaga, requestAdSaga, requestEmphasisAdsSaga, countAdViewRequestSaga } from './sagas/offreSaga.js'
|
||||
import { requestCompaniesSaga, requestCompanySaga, requestEmphasisCompaniesSaga, countCompanyViewRequestSaga } from './sagas/companySaga.js'
|
||||
import { postAnswerMessageSaga, postAdAnswerRequestSaga, uploadMediaSaga, fetchAdsAnsweredRequestSaga, fetchAnswerRequestSaga, fetchAnswerMessagesRequestSaga } from './sagas/answerSaga.js'
|
||||
import { postAnswerMessageSaga, postAdAnswerRequestSaga, uploadMediaSaga, uploadMediaPresSaga, uploadMediaCvSaga, fetchAdsAnsweredRequestSaga, fetchAnswerRequestSaga, fetchAnswerMessagesRequestSaga } from './sagas/answerSaga.js'
|
||||
|
||||
import {
|
||||
REQUEST_LOGIN,
|
||||
@@ -29,6 +29,8 @@ import {
|
||||
ACCOUNT_CONFIRMATION_REQUEST,
|
||||
POST_AD_ANSWER_REQUEST,
|
||||
UPLOAD_MEDIA_REQUEST,
|
||||
UPLOAD_MEDIA_PRES_REQUEST,
|
||||
UPLOAD_MEDIA_CV_REQUEST,
|
||||
UPDATE_USER_REQUEST,
|
||||
FETCH_ADS_ANSWER_REQUEST,
|
||||
FETCH_ANSWER_REQUEST,
|
||||
@@ -65,6 +67,8 @@ function* rootSaga() {
|
||||
takeLatest(ACCOUNT_CONFIRMATION_REQUEST, requestConfirmationAccountSaga),
|
||||
takeLatest(POST_AD_ANSWER_REQUEST, postAdAnswerRequestSaga),
|
||||
takeLatest(UPLOAD_MEDIA_REQUEST, uploadMediaSaga),
|
||||
takeLatest(UPLOAD_MEDIA_PRES_REQUEST, uploadMediaPresSaga),
|
||||
takeLatest(UPLOAD_MEDIA_CV_REQUEST, uploadMediaCvSaga),
|
||||
takeLatest(FETCH_ADS_ANSWER_REQUEST, fetchAdsAnsweredRequestSaga),
|
||||
takeLatest(FETCH_ANSWER_REQUEST, fetchAnswerRequestSaga),
|
||||
takeLatest(VERIFY_USER_REQUEST, verifyUserSaga),
|
||||
@@ -79,4 +83,4 @@ function* rootSaga() {
|
||||
])
|
||||
}
|
||||
|
||||
export default rootSaga
|
||||
export default rootSaga
|
||||
@@ -23,7 +23,11 @@ import {
|
||||
|
||||
import {
|
||||
uploadMediaSuccess,
|
||||
uploadMediaFailure
|
||||
uploadMediaFailure,
|
||||
uploadMediaPresSuccess,
|
||||
uploadMediaPresFailure,
|
||||
uploadMediaCvSuccess,
|
||||
uploadMediaCvFailure
|
||||
} from "../actions/media";
|
||||
import AuthRouter from "../pages/AuthRouter";
|
||||
|
||||
@@ -70,6 +74,46 @@ export function* uploadMediaSaga(action) {
|
||||
}
|
||||
}
|
||||
|
||||
export function* uploadMediaPresSaga(action) {
|
||||
try {
|
||||
|
||||
const res = yield call(api.medias.uploadMediaPres, action.payload);
|
||||
|
||||
if (!!res.data)
|
||||
yield put(uploadMediaPresSuccess(res));
|
||||
else
|
||||
yield put(uploadMediaPresFailure(res));
|
||||
|
||||
} catch (err) {
|
||||
if (_.includes(err, "401") || err.response.status === 401) {
|
||||
|
||||
localStorage.setItem('loginRedirect', window.location)
|
||||
Router.push("/Login");
|
||||
}
|
||||
yield put(uploadMediaPresFailure(err.response));
|
||||
}
|
||||
}
|
||||
|
||||
export function* uploadMediaCvSaga(action) {
|
||||
try {
|
||||
|
||||
const res = yield call(api.medias.uploadMediaCv, action.payload);
|
||||
|
||||
if (!!res.data)
|
||||
yield put(uploadMediaCvSuccess(res));
|
||||
else
|
||||
yield put(uploadMediaCvFailure(res));
|
||||
|
||||
} catch (err) {
|
||||
if (_.includes(err, "401") || err.response.status === 401) {
|
||||
|
||||
localStorage.setItem('loginRedirect', window.location)
|
||||
Router.push("/Login");
|
||||
}
|
||||
yield put(uploadMediaCvFailure(err.response));
|
||||
}
|
||||
}
|
||||
|
||||
export function* fetchAdsAnsweredRequestSaga(action) {
|
||||
try {
|
||||
const res = yield call(api.answers.fetchAdsAnswered, action.payload);
|
||||
|
||||
@@ -112,4 +112,12 @@ export const COUNT_COMPANY_VIEW = "COUNT_COMPANY_VIEW";
|
||||
|
||||
export const UPLOAD_MEDIA_REQUEST = "UPLOAD_MEDIA_REQUEST";
|
||||
export const UPLOAD_MEDIA_SUCCESS = "UPLOAD_MEDIA_SUCCESS";
|
||||
export const UPLOAD_MEDIA_FAILURE = "UPLOAD_MEDIA_FAILURE";
|
||||
export const UPLOAD_MEDIA_FAILURE = "UPLOAD_MEDIA_FAILURE";
|
||||
|
||||
export const UPLOAD_MEDIA_PRES_REQUEST = "UPLOAD_MEDIA_PRES_REQUEST";
|
||||
export const UPLOAD_MEDIA_PRES_SUCCESS = "UPLOAD_MEDIA_PRES_SUCCESS";
|
||||
export const UPLOAD_MEDIA_PRES_FAILURE = "UPLOAD_MEDIA_PRES_FAILURE";
|
||||
|
||||
export const UPLOAD_MEDIA_CV_REQUEST = "UPLOAD_MEDIA_CV_REQUEST";
|
||||
export const UPLOAD_MEDIA_CV_SUCCESS = "UPLOAD_MEDIA_CV_SUCCESS";
|
||||
export const UPLOAD_MEDIA_CV_FAILURE = "UPLOAD_MEDIA_CV_FAILURE";
|
||||
@@ -171,6 +171,7 @@ class Contact extends React.Component {
|
||||
<title>Devis Développement PWA</title>
|
||||
<meta name="description" content="Vous souhaitez créer une PWA, développer des fonctionnalités à votre site web et améliorer l'expérience utilisateur sur votre site internet? Contactez-nous pour parler de votre projet." />
|
||||
<link rel="canonical" href="https://www.application.bzh/contact"/>
|
||||
<meta key="robots" name="robots" content="noindex, nofollow"></meta>
|
||||
</Head>
|
||||
<div className={classes.root}>
|
||||
<div className={classes.wrapper}>
|
||||
|
||||
@@ -57,6 +57,7 @@ class Index extends React.Component {
|
||||
<title>Boilerplate PWA</title>
|
||||
<meta name="description" content="Vous souhaitez créer une PWA, développer des fonctionnalités à votre site web et améliorer l'expérience utilisateur sur votre site internet? Contactez-nous pour parler de votre projet." />
|
||||
<link rel="canonical" href="https://pwa-boiler.bzh" />
|
||||
<meta key="robots" name="robots" content="noindex, nofollow"></meta>
|
||||
</Head>
|
||||
|
||||
<div className={classes.root}>
|
||||
|
||||