@mirrormedia/lilith-draft-editor
Version:
## Installation
432 lines (389 loc) • 15.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.VideoSelector = VideoSelector;
var _react = _interopRequireWildcard(require("react"));
var _debounce = _interopRequireDefault(require("lodash/debounce"));
var _styledComponents = _interopRequireDefault(require("styled-components"));
var _modals = require("@keystone-ui/modals");
var _apollo = require("@keystone-6/core/admin-ui/apollo");
var _searchBox = require("./search-box");
var _pagination = require("./pagination");
var _fields = require("@keystone-ui/fields");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
const videosQuery = (0, _apollo.gql)`
query Videos($searchText: String!, $take: Int, $skip: Int) {
videosCount(where: { name: { contains: $searchText } })
videos(
where: { name: { contains: $searchText } }
orderBy: { id: desc }
take: $take
skip: $skip
) {
id
name
videoSrc
file {
filename
filesize
url
}
coverPhoto {
id
name
resized {
original
}
}
}
}
`;
const _ = {
debounce: _debounce.default
};
const VideoSearchBox = (0, _styledComponents.default)(_searchBox.SearchBox)`
margin-top: 10px;
`;
const VideoSelectionWrapper = _styledComponents.default.div`
overflow: auto;
margin-top: 10px;
`;
const VideoGridsWrapper = _styledComponents.default.div`
display: flex;
flex-wrap: wrap;
overflow: auto;
`;
const VideoGridWrapper = _styledComponents.default.div`
flex: 0 0 33.3333%;
cursor: pointer;
padding: 0 10px 10px;
`;
const VideoMetaGridsWrapper = _styledComponents.default.div`
display: flex;
flex-wrap: wrap;
overflow: auto;
`;
const VideoMetaGridWrapper = _styledComponents.default.div`
flex: 0 0 33.3333%;
cursor: pointer;
padding: 0 10px 10px;
`;
const Video = _styledComponents.default.video`
display: block;
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
`;
const SeparationLine = _styledComponents.default.div`
border: #e1e5e9 1px solid;
margin-top: 10px;
margin-bottom: 10px;
`;
const VideoSelected = _styledComponents.default.div`
height: 1.4rem;
`;
const ErrorWrapper = _styledComponents.default.div`
& * {
margin: 0;
}
`;
const VideoName = _styledComponents.default.p`
text-align: center;
`;
const Label = _styledComponents.default.label`
display: block;
margin: 10px 0;
font-weight: 600;
`;
const getYoutubeId = url => {
if (!url) return null;
const match = url.match(/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/);
return match ? match[1] : null;
};
function VideosGrids(props) {
const {
videos,
selected,
onSelect
} = props;
return /*#__PURE__*/_react.default.createElement(VideoGridsWrapper, null, videos.map(video => {
return /*#__PURE__*/_react.default.createElement(VideoGrid, {
key: video.id,
isSelected: selected === null || selected === void 0 ? void 0 : selected.some(s => s.id === video.id),
onSelect: () => onSelect(video),
video: video
});
}));
}
function VideoGrid(props) {
var _video$file, _video$coverPhoto, _video$coverPhoto$res;
const {
video,
onSelect,
isSelected
} = props;
const [isPlaying, setIsPlaying] = (0, _react.useState)(false);
(0, _react.useEffect)(() => {
setIsPlaying(false);
}, [video.id]);
const youtubeId = getYoutubeId(video === null || video === void 0 ? void 0 : video.videoSrc);
const fileUrl = video === null || video === void 0 ? void 0 : (_video$file = video.file) === null || _video$file === void 0 ? void 0 : _video$file.url;
const posterUrl = (video === null || video === void 0 ? void 0 : (_video$coverPhoto = video.coverPhoto) === null || _video$coverPhoto === void 0 ? void 0 : (_video$coverPhoto$res = _video$coverPhoto.resized) === null || _video$coverPhoto$res === void 0 ? void 0 : _video$coverPhoto$res.original) || (youtubeId ? `https://img.youtube.com/vi/${encodeURIComponent(youtubeId)}/hqdefault.jpg` : "");
const handlePlayAndSelect = e => {
e.stopPropagation();
if (isPlaying) {
setIsPlaying(false);
} else {
setIsPlaying(true);
onSelect(video);
}
};
return /*#__PURE__*/_react.default.createElement(VideoGridWrapper, {
key: video === null || video === void 0 ? void 0 : video.id,
onClick: () => onSelect(video)
}, /*#__PURE__*/_react.default.createElement(VideoSelected, {
style: {
height: '24px',
marginBottom: '4px'
}
}, isSelected ? /*#__PURE__*/_react.default.createElement("i", {
className: "fas fa-check-circle",
style: {
color: '#007bff'
}
}) : null), /*#__PURE__*/_react.default.createElement("div", {
onClick: handlePlayAndSelect,
style: {
width: '100%',
aspectRatio: '16/9',
position: 'relative',
backgroundColor: '#000',
borderRadius: '4px',
overflow: 'hidden'
}
}, isPlaying ? youtubeId ? /*#__PURE__*/_react.default.createElement("iframe", {
style: {
width: '100%',
height: '100%',
border: 'none',
display: 'block'
},
src: `https://www.youtube.com/embed/${youtubeId}?autoplay=1&mute=1&rel=0`,
allow: "autoplay; encrypted-media",
allowFullScreen: true
}) : /*#__PURE__*/_react.default.createElement(Video, {
autoPlay: true,
controls: true,
muted: true,
style: {
width: '100%',
height: '100%',
objectFit: 'cover'
}
}, (fileUrl || (video === null || video === void 0 ? void 0 : video.videoSrc)) && /*#__PURE__*/_react.default.createElement("source", {
src: fileUrl || (video === null || video === void 0 ? void 0 : video.videoSrc)
})) : /*#__PURE__*/_react.default.createElement("div", {
style: {
width: '100%',
height: '100%',
backgroundImage: `url(${posterUrl})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}
}, /*#__PURE__*/_react.default.createElement("i", {
className: youtubeId ? "fab fa-youtube" : "fas fa-play-circle",
style: {
color: 'white',
fontSize: '2.5rem',
opacity: 0.8
}
}))), /*#__PURE__*/_react.default.createElement(VideoName, {
style: {
marginTop: '8px',
fontSize: '14px',
height: '1.2em',
lineHeight: '1.2',
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
color: isSelected ? '#007bff' : 'inherit'
}
}, (video === null || video === void 0 ? void 0 : video.name) || "Untitled"));
}
function VideoMetaGrids(props) {
const {
videoMetas,
onChange
} = props;
return /*#__PURE__*/_react.default.createElement(VideoMetaGridsWrapper, null, videoMetas.map(videoMeta => {
var _videoMeta$video;
return /*#__PURE__*/_react.default.createElement(VideoMetaGrid, {
key: videoMeta === null || videoMeta === void 0 ? void 0 : (_videoMeta$video = videoMeta.video) === null || _videoMeta$video === void 0 ? void 0 : _videoMeta$video.id,
videoMeta: videoMeta,
onChange: onChange
});
}));
}
function VideoMetaGrid(props) {
var _video$coverPhoto2, _video$coverPhoto2$re, _video$file2, _video$file3;
const {
videoMeta,
onChange
} = props;
const {
video,
desc
} = videoMeta;
const youtubeId = getYoutubeId(video === null || video === void 0 ? void 0 : video.videoSrc);
const posterUrl = (video === null || video === void 0 ? void 0 : (_video$coverPhoto2 = video.coverPhoto) === null || _video$coverPhoto2 === void 0 ? void 0 : (_video$coverPhoto2$re = _video$coverPhoto2.resized) === null || _video$coverPhoto2$re === void 0 ? void 0 : _video$coverPhoto2$re.original) || (youtubeId ? `https://img.youtube.com/vi/${youtubeId}/hqdefault.jpg` : "");
const onVideoDescriptionChange = e => {
onChange({
video,
desc: e.target.value
});
};
return /*#__PURE__*/_react.default.createElement(VideoMetaGridWrapper, null, youtubeId ? /*#__PURE__*/_react.default.createElement("iframe", {
width: "100%",
style: {
aspectRatio: '16/9',
border: 'none',
backgroundColor: '#000'
},
src: `https://www.youtube.com/embed/${youtubeId}?rel=0&autoplay=0`,
allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
allowFullScreen: true,
loading: "lazy"
}) : /*#__PURE__*/_react.default.createElement(Video, {
muted: true,
autoPlay: true,
loop: true,
controls: true,
poster: posterUrl,
style: {
width: '100%',
aspectRatio: '16/9'
}
}, ((video === null || video === void 0 ? void 0 : video.videoSrc) || (video === null || video === void 0 ? void 0 : (_video$file2 = video.file) === null || _video$file2 === void 0 ? void 0 : _video$file2.url)) && /*#__PURE__*/_react.default.createElement("source", {
src: (video === null || video === void 0 ? void 0 : video.videoSrc) || (video === null || video === void 0 ? void 0 : (_video$file3 = video.file) === null || _video$file3 === void 0 ? void 0 : _video$file3.url)
})), /*#__PURE__*/_react.default.createElement(Label, null, "Video Name"), /*#__PURE__*/_react.default.createElement(VideoName, {
style: {
textAlign: 'left',
fontSize: '14px',
fontWeight: '500'
}
}, (video === null || video === void 0 ? void 0 : video.name) || 'Untitled'), /*#__PURE__*/_react.default.createElement(Label, {
htmlFor: "description"
}, "Video Description"), /*#__PURE__*/_react.default.createElement(_fields.TextInput, {
id: "description",
type: "text",
placeholder: "(Optional)",
defaultValue: desc,
onChange: _.debounce(onVideoDescriptionChange, 300)
}));
}
function VideoSelector(props) {
const [queryVideos, {
loading,
error,
data: {
videos = [],
videosCount = 0
} = {}
}] = (0, _apollo.useLazyQuery)(videosQuery, {
fetchPolicy: 'no-cache'
});
const [currentPage, setCurrentPage] = (0, _react.useState)(0); // page starts with 1, 0 is used to detect initialization
const [searchText, setSearchText] = (0, _react.useState)('');
const [selected, setSelected] = (0, _react.useState)([]);
const pageSize = 6;
const {
onChange
} = props;
const onSave = () => {
onChange(selected);
};
const onCancel = () => {
onChange([]);
};
const onSearchBoxChange = async searchInput => {
setSearchText(searchInput);
setCurrentPage(1);
};
const onVideoMetaChange = videoEntityWithMeta => {
setSelected([videoEntityWithMeta]);
};
const onVideosGridSelect = videoEntity => {
setSelected(selected => {
const filterdSelected = selected.filter(ele => {
var _ele$video;
return ((_ele$video = ele.video) === null || _ele$video === void 0 ? void 0 : _ele$video.id) !== videoEntity.id;
}); // deselect the video
if (filterdSelected.length !== selected.length) {
return filterdSelected;
} // single select
return [{
video: videoEntity,
desc: ''
}];
});
};
const selectedVideos = selected.map(ele => {
return ele.video;
});
(0, _react.useEffect)(() => {
if (currentPage !== 0) {
queryVideos({
variables: {
searchText: searchText,
skip: (currentPage - 1) * pageSize,
take: pageSize
}
});
}
}, [currentPage, searchText]);
let searchResult = /*#__PURE__*/_react.default.createElement(_react.Fragment, null, /*#__PURE__*/_react.default.createElement(VideosGrids, {
videos: videos,
selected: selectedVideos,
onSelect: onVideosGridSelect
}), /*#__PURE__*/_react.default.createElement(_pagination.Pagination, {
currentPage: currentPage,
total: videosCount,
pageSize: pageSize,
onChange: pageIndex => {
setCurrentPage(pageIndex);
}
}));
if (loading) {
searchResult = /*#__PURE__*/_react.default.createElement("p", null, "searching...");
}
if (error) {
var _videosQuery$loc;
searchResult = /*#__PURE__*/_react.default.createElement(ErrorWrapper, null, /*#__PURE__*/_react.default.createElement("h3", null, "Errors occurs in the `videos` query"), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("br", null), /*#__PURE__*/_react.default.createElement("b", null, "Message:"), /*#__PURE__*/_react.default.createElement("div", null, error.message), /*#__PURE__*/_react.default.createElement("br", null), /*#__PURE__*/_react.default.createElement("b", null, "Stack:"), /*#__PURE__*/_react.default.createElement("div", null, error.stack), /*#__PURE__*/_react.default.createElement("br", null), /*#__PURE__*/_react.default.createElement("b", null, "Query:"), /*#__PURE__*/_react.default.createElement("pre", null, (_videosQuery$loc = videosQuery.loc) === null || _videosQuery$loc === void 0 ? void 0 : _videosQuery$loc.source.body)));
}
return /*#__PURE__*/_react.default.createElement(_modals.DrawerController, {
isOpen: true
}, /*#__PURE__*/_react.default.createElement(_modals.Drawer, {
title: "Select video",
actions: {
cancel: {
label: 'Cancel',
action: onCancel
},
confirm: {
label: 'Confirm',
action: onSave
}
}
}, /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(VideoSearchBox, {
onChange: onSearchBoxChange
}), /*#__PURE__*/_react.default.createElement(VideoSelectionWrapper, null, /*#__PURE__*/_react.default.createElement("div", null, searchResult), !!selected.length && /*#__PURE__*/_react.default.createElement(SeparationLine, null), /*#__PURE__*/_react.default.createElement(VideoMetaGrids, {
videoMetas: selected,
onChange: onVideoMetaChange
})))));
}