Frontent dev env (#247)

* Added frontend development files/environment

* More items-categories related removals

* Improvements in pages templates (inc. static pages)

* Improvements in video player

* Added empty home page message + cta

* Updates in media, playlist and management pages

* Improvements in material icons font loading

* Replaced media & playlists links in frontend dev-env

* frontend package version update

* chnaged frontend dev url port

* static files update

* Changed default position of theme switcher

* enabled frontend docker container
This commit is contained in:
Yiannis Stergiou
2021-07-11 18:01:34 +03:00
committed by GitHub
parent 060bb45725
commit aa6520daac
555 changed files with 201927 additions and 66002 deletions

View File

@@ -0,0 +1,185 @@
import React, { useState, useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import { PageStore, MediaPageStore } from '../../utils/stores/';
import { PageActions, MediaPageActions } from '../../utils/actions/';
import { CircleIconButton, MaterialIcon } from '../_shared';
import { PlaylistCreationForm } from '../playlist-form/PlaylistCreationForm';
import './PlaylistsSelection.scss';
function PlaylistsSingleSelection(props) {
function onChange(ev) {
ev.persist();
if (props.isChecked) {
MediaPageActions.removeMediaFromPlaylist(props.playlistId, MediaPageStore.get('media-id'));
} else {
MediaPageActions.addMediaToPlaylist(props.playlistId, MediaPageStore.get('media-id'));
}
}
return !!props.renderDate ? (
<label>
<input type="checkbox" checked={props.isChecked} onChange={onChange} />
<span>{props.title}</span>
{/*<MaterialIcon type={ "private" === this.props.privacy ? "lock" : ( "unlisted" === this.props.privacy ? "link" : "public" ) } />*/}
</label>
) : null;
}
PlaylistsSingleSelection.propTypes = {
playlistId: PropTypes.string,
isChecked: PropTypes.bool,
title: PropTypes.string,
};
PlaylistsSingleSelection.defaultProps = {
isChecked: false,
title: '',
};
export function PlaylistsSelection(props) {
const containerRef = useRef(null);
const saveToSelectRef = useRef(null);
const [date, setDate] = useState(new Date());
const [playlists, setPlaylists] = useState(MediaPageStore.get('playlists'));
const [openCreatePlaylist, setOpenCreatePlaylist] = useState(false);
function onWindowResize() {
updateSavetoSelectMaxHeight();
}
function onLoadPlaylists() {
setPlaylists(MediaPageStore.get('playlists'));
setDate(new Date());
}
function onPlaylistMediaAdditionComplete() {
setPlaylists(MediaPageStore.get('playlists'));
setDate(new Date());
setTimeout(function () {
PageActions.addNotification('Media added to playlist', 'playlistMediaAdditionComplete');
}, 100);
}
function onPlaylistMediaAdditionFail() {
setTimeout(function () {
PageActions.addNotification("Media's addition to playlist failed", 'playlistMediaAdditionFail');
}, 100);
}
function onPlaylistMediaRemovalComplete() {
setPlaylists(MediaPageStore.get('playlists'));
setDate(new Date());
setTimeout(function () {
PageActions.addNotification('Media removed from playlist', 'playlistMediaRemovalComplete');
}, 100);
}
function onPlaylistMediaRemovalFail() {
setTimeout(function () {
PageActions.addNotification("Media's removal from playlist failed", 'playlistMediaaRemovalFail');
}, 100);
}
function updateSavetoSelectMaxHeight() {
if (null !== saveToSelectRef.current) {
saveToSelectRef.current.style.maxHeight =
window.innerHeight -
(56 + 18) -
(containerRef.current.offsetHeight - saveToSelectRef.current.offsetHeight) +
'px';
}
}
function getCreatedPlaylists() {
const mediaId = MediaPageStore.get('media-id');
let ret = [];
let i = 0;
while (i < playlists.length) {
ret.push(
<div key={'playlist_' + playlists[i].playlist_id}>
<PlaylistsSingleSelection
renderDate={date}
title={playlists[i].title}
privacy={playlists[i].status}
isChecked={-1 < playlists[i].media_list.indexOf(mediaId)}
playlistId={playlists[i].playlist_id}
/>
</div>
);
i += 1;
}
return ret;
}
function togglePlaylistCreationForm() {
setOpenCreatePlaylist(!openCreatePlaylist);
updateSavetoSelectMaxHeight();
}
function onClickExit() {
setOpenCreatePlaylist(false);
if (void 0 !== props.triggerPopupClose) {
props.triggerPopupClose();
}
}
function onPlaylistCreation(newPlaylistData) {
MediaPageActions.addNewPlaylist(newPlaylistData);
togglePlaylistCreationForm();
}
useEffect(() => {
updateSavetoSelectMaxHeight();
});
useEffect(() => {
PageStore.on('window_resize', onWindowResize);
MediaPageStore.on('playlists_load', onLoadPlaylists);
MediaPageStore.on('media_playlist_addition_completed', onPlaylistMediaAdditionComplete);
MediaPageStore.on('media_playlist_addition_failed', onPlaylistMediaAdditionFail);
MediaPageStore.on('media_playlist_removal_completed', onPlaylistMediaRemovalComplete);
MediaPageStore.on('media_playlist_removal_failed', onPlaylistMediaRemovalFail);
return () => {
PageStore.removeListener('window_resize', onWindowResize);
MediaPageStore.removeListener('playlists_load', onLoadPlaylists);
MediaPageStore.removeListener('media_playlist_addition_completed', onPlaylistMediaAdditionComplete);
MediaPageStore.removeListener('media_playlist_addition_failed', onPlaylistMediaAdditionFail);
MediaPageStore.removeListener('media_playlist_removal_completed', onPlaylistMediaRemovalComplete);
MediaPageStore.removeListener('media_playlist_removal_failed', onPlaylistMediaRemovalFail);
};
}, []);
return (
<div ref={containerRef} className="saveto-popup">
<div className="saveto-title">
Save to...
<CircleIconButton type="button" onClick={onClickExit}>
<MaterialIcon type="close" />
</CircleIconButton>
</div>
{playlists.length ? (
<div ref={saveToSelectRef} className="saveto-select">
{getCreatedPlaylists()}
</div>
) : null}
{openCreatePlaylist ? (
<div className="saveto-new-playlist">
<PlaylistCreationForm onCancel={togglePlaylistCreationForm} onPlaylistSave={onPlaylistCreation} />
</div>
) : (
<CircleIconButton className="saveto-create" type="button" onClick={togglePlaylistCreationForm}>
<MaterialIcon type="add" />
Create a new playlist
</CircleIconButton>
)}
</div>
);
}
PlaylistsSelection.propTypes = {
triggerPopupClose: PropTypes.func,
};

View File

@@ -0,0 +1,145 @@
.media-title-banner .media-actions > * > *.save .popup-fullscreen .popup-main > div.saveto-popup {
color: var( --playlist-save-popup-text-color );
.saveto-select,
.saveto-create,
.saveto-new-playlist{
border-color: var( --playlist-save-popup-border-color );
}
.saveto-title{
.circle-icon-button{
&:hover,
&:focus,
&:active{
color: var( --playlist-save-popup-text-color );
}
}
}
.saveto-create{
color: var( --playlist-save-popup-text-color );
.material-icons{
color: var( --playlist-save-popup-create-icon-text-color );
}
&:focus{
> * {
background-color: var( --playlist-save-popup-create-focus-bg-color );
}
}
}
.saveto-new-playlist{
}
}
.media-title-banner .media-actions > * > *.save .popup-fullscreen{
padding-top:64px;
padding-bottom:8px;
}
.media-title-banner .media-actions > * > *.save .popup-fullscreen .popup-main > div.saveto-popup {
max-width:280px;
padding:0;
.saveto-select,
.saveto-create,
.saveto-new-playlist{
border-width:1px 0 0;
border-style:solid;
}
.saveto-title{
height:52px;
padding:16px 52px 15px 24px;
line-height: 20px;
font-size:16px;
.circle-icon-button{
position:absolute;
top:6px;
right:6px;
background:none;
}
}
.saveto-select{
overflow:auto;
padding:12px 18px 12px 24px;
> *{
width:100%;
}
label{
position:relative;
display:table;
width:100%;
padding:4px 0;
font-size:14px;
line-height:24px;
cursor: pointer;
> * {
display:table-cell;
}
input[type="checkbox"]{
display:inline-block;
}
span{
width:100%;
padding:0 4px 0 16px;
text-align:initial;
}
.material-icons{
width:18px;
padding-top:4px;
text-align:right;
font-size:18px;
vertical-align:top;
color:rgb(144, 144, 144);
}
}
}
.saveto-create{
width:100%;
height:52px;
font-size:14px;
line-height:21px;
text-align:initial;
background:none;
border-radius: 0;
> *{
padding:0 24px;
border-radius: 0;
}
span{
}
.material-icons{
margin-right:16px;
}
}
.saveto-new-playlist{
}
}