Fix conflicts

This commit is contained in:
Aurélien Georget 2019-02-21 15:45:20 +01:00
commit bccf12e3b1
11 changed files with 167 additions and 333 deletions

View File

@ -15,8 +15,8 @@ import '../../../../node_modules/video-react/dist/video-react.css';
import styles from './styles.scss';
class OnboardingVideo extends React.Component {
hiddenPlayer = React.createRef();
player = React.createRef();
hiddenPlayer = React.createRef();
componentDidMount() {
this.hiddenPlayer.current.subscribeToStateChange(
@ -27,26 +27,60 @@ class OnboardingVideo extends React.Component {
handleChangeState = (state, prevState) => {
const { duration } = state;
const { id } = this.props;
if (duration !== prevState.duration) {
this.props.setVideoDuration(id, duration);
}
};
handleChangeIsPlayingState = (state, prevState) => {
const { isActive } = state;
const { id } = this.props;
// Manual play
if (isActive !== prevState.isActive && isActive) {
this.props.didPlayVideo(id, this.props.video.startTime);
}
};
handleCurrentTimeChange = (curr) => {
this.props.getVideoCurrentTime(this.props.id, curr);
this.props.getVideoCurrentTime(this.props.id, curr, this.props.video.duration);
}
afterOpenModal = () => {
this.player.current.subscribeToStateChange(
this.handleChangeIsPlayingState,
);
this.player.current.play();
if (this.props.video.startTime === 0) {
const { player } = this.player.current.getState();
player.isActive = true;
this.props.didPlayVideo(this.props.id, this.props.video.startTime);
} else {
this.player.current.pause();
}
};
onModalClose = () => {
const { player } = this.player.current.getState();
const paused = player.paused;
if (!paused) {
this.videoPause();
}
};
videoPause = () => {
const { player } = this.player.current.getState();
const currTime = player.currentTime;
this.handleCurrentTimeChange(currTime);
this.props.didStopVideo(this.props.id, currTime);
};
render() {
@ -61,6 +95,7 @@ class OnboardingVideo extends React.Component {
>
<div className={styles.thumbWrapper}>
<img src={video.preview} />
<div className={styles.overlay}/>
<div className={styles.play} />
</div>
<div className={styles.txtWrapper}>
@ -85,15 +120,20 @@ class OnboardingVideo extends React.Component {
<div>
<Player
ref={this.player}
className={styles.videoPlayer}
poster="/assets/poster.png"
src={video.video}
startTime={video.startTime}
preload="auto"
onPause={this.videoPause}
onplay={this.videoStart}
subscribeToStateChange={this.subscribeToStateChange}
/>
</div>
</ModalBody>
</Modal>
{!video.duration && (
{!this.props.video.duration && (
<div className={cn(styles.hiddenPlayerWrapper)}>
<Player
ref={this.hiddenPlayer}
@ -114,6 +154,8 @@ OnboardingVideo.defaultProps = {
video: {},
setVideoDuration: () => {},
getVideoCurrentTime: () => {},
didStopVideo: () => {},
didPlayVideo: () => {},
};
OnboardingVideo.propTypes = {
@ -121,6 +163,8 @@ OnboardingVideo.propTypes = {
videos: PropTypes.object,
setVideoDuration: PropTypes.func,
getVideoCurrentTime: PropTypes.func,
didStopVideo: PropTypes.func,
didPlayVideo: PropTypes.func,
};
export default OnboardingVideo;

View File

@ -2,20 +2,7 @@ li.listItem {
display: block;
padding: 10px 15px;
cursor: pointer;
&.finished {
.title {
color: #919bae;
}
.thumbWrapper {
.play {
background-color: #5a9e06;
&::before {
content: '\f00c';
font-size: 11px;
}
}
}
}
&:hover {
background-color: #f7f8f8;
.title {
@ -34,9 +21,20 @@ li.listItem {
border-radius: 2px;
overflow: hidden;
position: relative;
.overlay {
width: 100%;
height: 100%;
background-color: rgba(#0E7DE7, .8);
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
img {
width: 100%;
height: 100%;
position: relative;
z-index: 0;
}
.play {
width: 20px;
@ -44,22 +42,47 @@ li.listItem {
line-height: 20px;
border-radius: 50%;
background-color: #0e7de7;
border: 1px solid white;
position: absolute;
top: 50%;
margin-top: -10px;
left: 50%;
margin-left: -10px;
text-align: center;
z-index: 2;
&::before {
content: '\f04b';
font-family: 'FontAwesome';
font-size: 9px;
color: white;
display: inline-block;
vertical-align: middle;
vertical-align: top;
height: 100%;
}
}
}
&.finished {
.title {
color: #919bae;
}
.thumbWrapper {
.overlay {
background-color: transparent;
}
img {
opacity: 0.6;
}
.play {
background-color: #5a9e06;
border-color: #5a9e06;
&::before {
content: '\f00c';
font-size: 11px;
}
}
}
}
.txtWrapper {
padding: 0 15px;
p {
@ -73,9 +96,6 @@ li.listItem {
}
}
}
.modal .modal-dialog {
background: red;
}
.hiddenPlayerWrapper {
display: none;
@ -97,4 +117,12 @@ li.listItem {
margin-right: 0;
}
}
}
.videoPlayer {
> button {
top: 50%;
margin-top: -0.75em;
left: 50%;
margin-left: -1.5em;
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,152 +0,0 @@
.videosWrapper {
position: fixed;
right: 15px;
bottom: 15px;
button,
button:focus,
a {
cursor: pointer;
outline: 0;
}
p {
margin-bottom: 0;
}
.videosHeader {
padding: 15px 15px 0 15px;
p {
font-family: Lato-Bold;
font-size: 11px;
text-transform: uppercase;
display: inline-block;
width: 50%;
vertical-align: top;
color: #5c5f66;
&:last-of-type {
text-align: right;
color: #5a9e06;
}
}
}
.videosContent {
background-color: white;
margin-bottom: 10px;
margin-right: 15px;
box-shadow: 0 2px 4px 0 #e3e9f3;
border-radius: 3px;
transition: all 0.3s linear;
&.shown {
visibility: visible;
opacity: 1;
}
&.hide {
opacity: 0;
visibility: hidden;
}
ul {
list-style: none;
padding: 10px 0;
li {
&.finished {
.title {
color: #919bae;
}
.thumbWrapper {
.play {
background-color: #5a9e06;
&::before {
content: '\f00c';
font-size: 11px;
}
}
}
}
a {
display: block;
padding: 10px 15px;
&:hover {
background-color: #f7f8f8;
.title {
color: #0e7de7;
}
}
}
.txtWrapper,
.thumbWrapper {
display: inline-block;
vertical-align: middle;
}
.thumbWrapper {
width: 55px;
height: 38px;
background-color: #d8d8d8;
border-radius: 2px;
overflow: hidden;
position: relative;
img {
width: 100%;
height: 100%;
}
.play {
width: 20px;
height: 20px;
line-height: 20px;
border-radius: 50%;
background-color: #0e7de7;
position: absolute;
top: 50%;
margin-top: -10px;
left: 50%;
margin-left: -10px;
text-align: center;
&::before {
content: '\f04b';
font-family: 'FontAwesome';
font-size: 9px;
color: white;
display: inline-block;
vertical-align: middle;
}
}
}
.txtWrapper {
padding: 0 15px;
p {
font-size: 14px;
font-family: Lato-SemiBold;
}
.time {
font-size: 11px;
color: #919bae;
font-family: Lato-Bold;
}
}
}
}
}
.openBtn {
width: 38px;
height: 38px;
float: right;
button {
width: 100%;
height: 100%;
border-radius: 50%;
color: white;
background: #0e7de7;
-webkit-box-shadow: 0px 2px 4px 0px rgba(227, 233, 243, 1);
-moz-box-shadow: 0px 2px 4px 0px rgba(227, 233, 243, 1);
box-shadow: 0px 2px 4px 0px rgba(227, 233, 243, 1);
i:last-of-type {
display: none;
}
&.active {
i:first-of-type {
display: none;
}
i:last-of-type {
display: block;
}
}
}
}
}

View File

@ -26,6 +26,6 @@ export function emitEvent(event, properties) {
return {
type: EMIT_EVENT,
event,
properties,
properties
};
}

View File

@ -284,7 +284,7 @@ export class AdminPage extends React.Component {
isOpen={this.props.blockApp && this.props.showGlobalAppBlocker}
{...this.props.overlayBlockerData}
/>
<Onboarding />
{this.shouldDisplayLogout() && <Onboarding/>}
</div>
);
}

View File

@ -4,7 +4,7 @@
*
*/
import { GET_VIDEOS, GET_VIDEOS_SUCCEEDED, ON_CLICK, SET_VIDEOS_DURATION, UPDATE_VIDEO_START_TIME } from './constants';
import { GET_VIDEOS, GET_VIDEOS_SUCCEEDED, ON_CLICK, SET_VIDEOS_DURATION, UPDATE_VIDEO_START_TIME, SET_VIDEO_END, REMOVE_VIDEOS } from './constants';
export function getVideos() {
return {
@ -41,3 +41,17 @@ export function updateVideoStartTime(index, startTime) {
startTime: parseFloat(startTime, 10),
};
}
export function setVideoEnd(index, end) {
return {
type: SET_VIDEO_END,
index: parseInt(index, 10),
end,
};
}
export function removeVideos() {
return {
type: REMOVE_VIDEOS,
};
}

View File

@ -10,3 +10,5 @@ export const GET_VIDEOS_SUCCEEDED =
export const ON_CLICK = 'StrapiAdmin/Onboarding/ON_CLICK';
export const SET_VIDEOS_DURATION = 'StrapiAdmin/Onboarding/SET_VIDEOS_DURATION';
export const UPDATE_VIDEO_START_TIME = 'StrapiAdmin/Onboarding/UPDATE_VIDEO_START_TIME';
export const SET_VIDEO_END = 'StrapiAdmin/Onboarding/SET_VIDEO_END';
export const REMOVE_VIDEOS = 'StrapiAdmin/Onboarding/REMOVE_VIDEOS';

View File

@ -9,7 +9,7 @@ import PropTypes from 'prop-types';
import cn from 'classnames';
import { connect } from 'react-redux';
import { bindActionCreators, compose } from 'redux';
import { getVideos, onClick, setVideoDuration, updateVideoStartTime } from './actions';
import { getVideos, onClick, setVideoDuration, updateVideoStartTime, setVideoEnd, removeVideos } from './actions';
import injectSaga from 'utils/injectSaga';
import injectReducer from 'utils/injectReducer';
@ -24,11 +24,16 @@ import styles from './styles.scss';
export class Onboarding extends React.Component {
state = { showVideos: false };
componentWillMount() {
componentDidMount() {
this.setState({ showVideos: true });
this.props.getVideos();
}
componentWillUnmount() {
this.props.removeVideos();
localStorage.removeItem('videos');
}
toggleVideos = () => {
// Display videos card
this.setState(prevState => ({ showVideos: !prevState.showVideos }));
@ -39,14 +44,38 @@ export class Onboarding extends React.Component {
this.context.emitEvent(eventName);
};
updateLocalStorage = (index, current) => {
setVideoEnd = () => {
this.setVideoEnd();
}
didPlayVideo = (index, currTime) => {
const eventName = `didPlay${index}GetStartedVideo`;
this.context.emitEvent(eventName, {timestamp: currTime});
}
didStopVideo = (index, currTime) => {
const eventName = `didStop${index}Video`;
this.context.emitEvent(eventName, {timestamp: currTime});
}
updateLocalStorage = (index, current, duration) => {
// Update store
this.props.updateVideoStartTime(index, current);
// Update localStorage
let videosTime = JSON.parse(localStorage.getItem('videos'));
videosTime.fill(0);
videosTime[index] = current;
videosTime[index].startTime = current;
let percent = current * 100 / duration;
if (percent >= 80) {
if (videosTime[index].end === false) {
videosTime[index].end = true;
this.props.setVideoEnd(index, true);
}
}
localStorage.setItem('videos', JSON.stringify(videosTime));
};
@ -77,6 +106,8 @@ export class Onboarding extends React.Component {
onClick={onClick}
setVideoDuration={setVideoDuration}
getVideoCurrentTime={this.updateLocalStorage}
didPlayVideo={this.didPlayVideo}
didStopVideo={this.didStopVideo}
/>
);
})}
@ -108,7 +139,7 @@ Onboarding.propTypes = {
const mapStateToProps = makeSelectOnboarding();
function mapDispatchToProps(dispatch) {
return bindActionCreators({ getVideos, onClick, setVideoDuration, updateVideoStartTime }, dispatch);
return bindActionCreators({ getVideos, onClick, setVideoDuration, updateVideoStartTime, setVideoEnd, removeVideos }, dispatch);
}
const withConnect = connect(

View File

@ -5,7 +5,7 @@
*/
import { fromJS } from 'immutable';
import { GET_VIDEOS_SUCCEEDED, ON_CLICK, SET_VIDEOS_DURATION, UPDATE_VIDEO_START_TIME } from './constants';
import { GET_VIDEOS_SUCCEEDED, ON_CLICK, SET_VIDEOS_DURATION, UPDATE_VIDEO_START_TIME, SET_VIDEO_END, REMOVE_VIDEOS } from './constants';
const initialState = fromJS({
videos: fromJS([]),
@ -39,6 +39,10 @@ function onboardingReducer(state = initialState, action) {
return acc.updateIn([index, 'startTime'], () => 0);
}, list);
});
case SET_VIDEO_END:
return state.updateIn(['videos', action.index, 'end'], () => action.end);
case REMOVE_VIDEOS:
return initialState;
default:
return state;
}

View File

@ -17,8 +17,15 @@ function* getVideos() {
{ noAuth: true },
);
let currTimes = Array.apply(null, Array(videos.length)).map(Number.prototype.valueOf,0);
let currTimes = Array.apply(null, Array(videos.length)).map((e, i) => {
return {
startTime: 0,
end: false,
key: i,
id: videos[i].id,
}
});
// Retrieve start time if enable in localStorage
if (localStorage.getItem('videos')) {
currTimes.splice(0, currTimes.length, ...JSON.parse(localStorage.getItem('videos')));
@ -31,7 +38,8 @@ function* getVideos() {
videos.map((video, index) => {
video.isOpen = false;
video.duration = null;
video.startTime = currTimes[index];
video.startTime = currTimes[index].startTime;
video.end = currTimes[index].end;
return video;
}),