mirror of
https://github.com/strapi/strapi.git
synced 2025-08-10 01:38:10 +00:00
Fix conflicts
This commit is contained in:
commit
bccf12e3b1
@ -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;
|
||||
|
@ -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
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -26,6 +26,6 @@ export function emitEvent(event, properties) {
|
||||
return {
|
||||
type: EMIT_EVENT,
|
||||
event,
|
||||
properties,
|
||||
properties
|
||||
};
|
||||
}
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
@ -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';
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}),
|
||||
|
Loading…
x
Reference in New Issue
Block a user