mirror of
https://github.com/mediacms-io/mediacms.git
synced 2026-01-20 07:12:58 -05:00
initial implementation
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -3,257 +3,278 @@ import { SiteContext } from '../../utils/contexts/';
|
|||||||
import { useUser, usePopup } from '../../utils/hooks/';
|
import { useUser, usePopup } from '../../utils/hooks/';
|
||||||
import { PageStore, MediaPageStore } from '../../utils/stores/';
|
import { PageStore, MediaPageStore } from '../../utils/stores/';
|
||||||
import { PageActions, MediaPageActions } from '../../utils/actions/';
|
import { PageActions, MediaPageActions } from '../../utils/actions/';
|
||||||
import { formatInnerLink, publishedOnDate } from '../../utils/helpers/';
|
import { formatInnerLink, inEmbeddedApp, publishedOnDate } from '../../utils/helpers/';
|
||||||
import { PopupMain } from '../_shared/';
|
import { PopupMain } from '../_shared/';
|
||||||
import CommentsList from '../comments/Comments';
|
import CommentsList from '../comments/Comments';
|
||||||
import { replaceString } from '../../utils/helpers/';
|
import { replaceString } from '../../utils/helpers/';
|
||||||
import { translateString } from '../../utils/helpers/';
|
import { translateString } from '../../utils/helpers/';
|
||||||
|
|
||||||
function metafield(arr) {
|
function metafield(arr) {
|
||||||
let i;
|
let i;
|
||||||
let sep;
|
let sep;
|
||||||
let ret = [];
|
let ret = [];
|
||||||
|
|
||||||
if (arr && arr.length) {
|
if (arr && arr.length) {
|
||||||
i = 0;
|
i = 0;
|
||||||
sep = 1 < arr.length ? ', ' : '';
|
sep = 1 < arr.length ? ', ' : '';
|
||||||
while (i < arr.length) {
|
while (i < arr.length) {
|
||||||
ret[i] = (
|
ret[i] = (
|
||||||
<div key={i}>
|
<div key={i}>
|
||||||
<a href={arr[i].url} title={arr[i].title}>
|
<a href={arr[i].url} title={arr[i].title}>
|
||||||
{arr[i].title}
|
{arr[i].title}
|
||||||
</a>
|
</a>
|
||||||
{i < arr.length - 1 ? sep : ''}
|
{i < arr.length - 1 ? sep : ''}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
i += 1;
|
i += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
function MediaAuthorBanner(props) {
|
function MediaAuthorBanner(props) {
|
||||||
return (
|
return (
|
||||||
<div className="media-author-banner">
|
<div className="media-author-banner">
|
||||||
<div>
|
<div>
|
||||||
<a className="author-banner-thumb" href={props.link || null} title={props.name}>
|
<a className="author-banner-thumb" href={props.link || null} title={props.name}>
|
||||||
<span style={{ backgroundImage: 'url(' + props.thumb + ')' }}>
|
<span style={{ backgroundImage: 'url(' + props.thumb + ')' }}>
|
||||||
<img src={props.thumb} loading="lazy" alt={props.name} title={props.name} />
|
<img src={props.thumb} loading="lazy" alt={props.name} title={props.name} />
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span>
|
<span>
|
||||||
<a href={props.link} className="author-banner-name" title={props.name}>
|
<a href={props.link} className="author-banner-name" title={props.name}>
|
||||||
<span>{props.name}</span>
|
<span>{props.name}</span>
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
{PageStore.get('config-media-item').displayPublishDate && props.published ? (
|
{PageStore.get('config-media-item').displayPublishDate && props.published ? (
|
||||||
<span className="author-banner-date">
|
<span className="author-banner-date">
|
||||||
{translateString('Published on')} {replaceString(publishedOnDate(new Date(props.published)))}
|
{translateString('Published on')} {replaceString(publishedOnDate(new Date(props.published)))}
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MediaMetaField(props) {
|
function MediaMetaField(props) {
|
||||||
return (
|
return (
|
||||||
<div className={props.id.trim() ? 'media-content-' + props.id.trim() : null}>
|
<div className={props.id.trim() ? 'media-content-' + props.id.trim() : null}>
|
||||||
<div className="media-content-field">
|
<div className="media-content-field">
|
||||||
<div className="media-content-field-label">
|
<div className="media-content-field-label">
|
||||||
<h4>{props.title}</h4>
|
<h4>{props.title}</h4>
|
||||||
|
</div>
|
||||||
|
<div className="media-content-field-content">{props.value}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="media-content-field-content">{props.value}</div>
|
);
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function EditMediaButton(props) {
|
function EditMediaButton(props) {
|
||||||
let link = props.link;
|
let link = props.link;
|
||||||
|
|
||||||
if (window.MediaCMS.site.devEnv) {
|
if (window.MediaCMS.site.devEnv) {
|
||||||
link = '/edit-media.html';
|
link = '/edit-media.html';
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<a href={link} rel="nofollow" title={translateString('Edit media')} className="edit-media-icon">
|
<a href={link} rel="nofollow" title={translateString('Edit media')} className="edit-media-icon">
|
||||||
<i className="material-icons">edit</i>
|
<i className="material-icons">edit</i>
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ViewerInfoContent(props) {
|
export default function ViewerInfoContent(props) {
|
||||||
const { userCan } = useUser();
|
const { userCan } = useUser();
|
||||||
|
|
||||||
const description = props.description.trim();
|
const description = props.description.trim();
|
||||||
const tagsContent =
|
const tagsContent =
|
||||||
!PageStore.get('config-enabled').taxonomies.tags || PageStore.get('config-enabled').taxonomies.tags.enabled
|
!PageStore.get('config-enabled').taxonomies.tags || PageStore.get('config-enabled').taxonomies.tags.enabled
|
||||||
? metafield(MediaPageStore.get('media-tags'))
|
? metafield(MediaPageStore.get('media-tags'))
|
||||||
: [];
|
: [];
|
||||||
const categoriesContent = PageStore.get('config-options').pages.media.categoriesWithTitle
|
const categoriesContent = PageStore.get('config-options').pages.media.categoriesWithTitle
|
||||||
? []
|
? []
|
||||||
: !PageStore.get('config-enabled').taxonomies.categories ||
|
: !PageStore.get('config-enabled').taxonomies.categories ||
|
||||||
PageStore.get('config-enabled').taxonomies.categories.enabled
|
PageStore.get('config-enabled').taxonomies.categories.enabled
|
||||||
? metafield(MediaPageStore.get('media-categories'))
|
? metafield(MediaPageStore.get('media-categories'))
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
let summary = MediaPageStore.get('media-summary');
|
let summary = MediaPageStore.get('media-summary');
|
||||||
|
|
||||||
summary = summary ? summary.trim() : '';
|
summary = summary ? summary.trim() : '';
|
||||||
|
|
||||||
const [popupContentRef, PopupContent, PopupTrigger] = usePopup();
|
const [popupContentRef, PopupContent, PopupTrigger] = usePopup();
|
||||||
|
|
||||||
const [hasSummary, setHasSummary] = useState('' !== summary);
|
const [hasSummary, setHasSummary] = useState('' !== summary);
|
||||||
const [isContentVisible, setIsContentVisible] = useState('' == summary);
|
const [isContentVisible, setIsContentVisible] = useState('' == summary);
|
||||||
|
|
||||||
function proceedMediaRemoval() {
|
function proceedMediaRemoval() {
|
||||||
MediaPageActions.removeMedia();
|
MediaPageActions.removeMedia();
|
||||||
popupContentRef.current.toggle();
|
popupContentRef.current.toggle();
|
||||||
}
|
|
||||||
|
|
||||||
function cancelMediaRemoval() {
|
|
||||||
popupContentRef.current.toggle();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMediaDelete(mediaId) {
|
|
||||||
// FIXME: Without delay creates conflict [ Uncaught Error: Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch. ].
|
|
||||||
setTimeout(function () {
|
|
||||||
PageActions.addNotification('Media removed. Redirecting...', 'mediaDelete');
|
|
||||||
setTimeout(function () {
|
|
||||||
window.location.href =
|
|
||||||
SiteContext._currentValue.url + '/' + MediaPageStore.get('media-data').author_profile.replace(/^\//g, '');
|
|
||||||
}, 2000);
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
if (void 0 !== mediaId) {
|
|
||||||
console.info("Removed media '" + mediaId + '"');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMediaDeleteFail(mediaId) {
|
|
||||||
// FIXME: Without delay creates conflict [ Uncaught Error: Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch. ].
|
|
||||||
setTimeout(function () {
|
|
||||||
PageActions.addNotification('Media removal failed', 'mediaDeleteFail');
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
if (void 0 !== mediaId) {
|
|
||||||
console.info('Media "' + mediaId + '"' + ' removal failed');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onClickLoadMore() {
|
|
||||||
setIsContentVisible(!isContentVisible);
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
MediaPageStore.on('media_delete', onMediaDelete);
|
|
||||||
MediaPageStore.on('media_delete_fail', onMediaDeleteFail);
|
|
||||||
return () => {
|
|
||||||
MediaPageStore.removeListener('media_delete', onMediaDelete);
|
|
||||||
MediaPageStore.removeListener('media_delete_fail', onMediaDeleteFail);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const authorLink = formatInnerLink(props.author.url, SiteContext._currentValue.url);
|
|
||||||
const authorThumb = formatInnerLink(props.author.thumb, SiteContext._currentValue.url);
|
|
||||||
|
|
||||||
function setTimestampAnchors(text) {
|
|
||||||
function wrapTimestampWithAnchor(match, string) {
|
|
||||||
let split = match.split(':'),
|
|
||||||
s = 0,
|
|
||||||
m = 1;
|
|
||||||
|
|
||||||
while (split.length > 0) {
|
|
||||||
s += m * parseInt(split.pop(), 10);
|
|
||||||
m *= 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
const wrapped = `<a href="#" data-timestamp="${s}" class="video-timestamp">${match}</a>`;
|
|
||||||
return wrapped;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const timeRegex = new RegExp('((\\d)?\\d:)?(\\d)?\\d:\\d\\d', 'g');
|
function cancelMediaRemoval() {
|
||||||
return text.replace(timeRegex, wrapTimestampWithAnchor);
|
popupContentRef.current.toggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
function onMediaDelete(mediaId) {
|
||||||
<div className="media-info-content">
|
// FIXME: Without delay creates conflict [ Uncaught Error: Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch. ].
|
||||||
{void 0 === PageStore.get('config-media-item').displayAuthor ||
|
setTimeout(function () {
|
||||||
null === PageStore.get('config-media-item').displayAuthor ||
|
PageActions.addNotification('Media removed. Redirecting...', 'mediaDelete');
|
||||||
!!PageStore.get('config-media-item').displayAuthor ? (
|
setTimeout(function () {
|
||||||
<MediaAuthorBanner link={authorLink} thumb={authorThumb} name={props.author.name} published={props.published} />
|
window.location.href =
|
||||||
) : null}
|
SiteContext._currentValue.url +
|
||||||
|
'/' +
|
||||||
|
MediaPageStore.get('media-data').author_profile.replace(/^\//g, '');
|
||||||
|
}, 2000);
|
||||||
|
}, 100);
|
||||||
|
|
||||||
<div className="media-content-banner">
|
if (void 0 !== mediaId) {
|
||||||
<div className="media-content-banner-inner">
|
console.info("Removed media '" + mediaId + '"');
|
||||||
{hasSummary ? <div className="media-content-summary">{summary}</div> : null}
|
}
|
||||||
{(!hasSummary || isContentVisible) && description ? (
|
}
|
||||||
<div
|
|
||||||
className="media-content-description"
|
|
||||||
dangerouslySetInnerHTML={{ __html: setTimestampAnchors(description) }}
|
|
||||||
></div>
|
|
||||||
) : null}
|
|
||||||
{hasSummary ? (
|
|
||||||
<button className="load-more" onClick={onClickLoadMore}>
|
|
||||||
{isContentVisible ? 'SHOW LESS' : 'SHOW MORE'}
|
|
||||||
</button>
|
|
||||||
) : null}
|
|
||||||
{tagsContent.length ? (
|
|
||||||
<MediaMetaField
|
|
||||||
value={tagsContent}
|
|
||||||
title={1 < tagsContent.length ? translateString('Tags') : translateString('Tag')}
|
|
||||||
id="tags"
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
{categoriesContent.length ? (
|
|
||||||
<MediaMetaField
|
|
||||||
value={categoriesContent}
|
|
||||||
title={1 < categoriesContent.length ? translateString('Categories') : translateString('Category')}
|
|
||||||
id="categories"
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
{userCan.editMedia ? (
|
function onMediaDeleteFail(mediaId) {
|
||||||
<div className="media-author-actions">
|
// FIXME: Without delay creates conflict [ Uncaught Error: Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch. ].
|
||||||
{userCan.editMedia ? <EditMediaButton link={MediaPageStore.get('media-data').edit_url} /> : null}
|
setTimeout(function () {
|
||||||
|
PageActions.addNotification('Media removal failed', 'mediaDeleteFail');
|
||||||
|
}, 100);
|
||||||
|
|
||||||
{userCan.deleteMedia ? (
|
if (void 0 !== mediaId) {
|
||||||
<PopupTrigger contentRef={popupContentRef}>
|
console.info('Media "' + mediaId + '"' + ' removal failed');
|
||||||
<button className="remove-media-icon" title={translateString('Delete media')}>
|
}
|
||||||
<i className="material-icons">delete</i>
|
}
|
||||||
</button>
|
|
||||||
</PopupTrigger>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
{userCan.deleteMedia ? (
|
function onClickLoadMore() {
|
||||||
<PopupContent contentRef={popupContentRef}>
|
setIsContentVisible(!isContentVisible);
|
||||||
<PopupMain>
|
}
|
||||||
<div className="popup-message">
|
|
||||||
<span className="popup-message-title">Media removal</span>
|
useEffect(() => {
|
||||||
<span className="popup-message-main">You're willing to remove media permanently?</span>
|
MediaPageStore.on('media_delete', onMediaDelete);
|
||||||
</div>
|
MediaPageStore.on('media_delete_fail', onMediaDeleteFail);
|
||||||
<hr />
|
return () => {
|
||||||
<span className="popup-message-bottom">
|
MediaPageStore.removeListener('media_delete', onMediaDelete);
|
||||||
<button className="button-link cancel-comment-removal" onClick={cancelMediaRemoval}>
|
MediaPageStore.removeListener('media_delete_fail', onMediaDeleteFail);
|
||||||
CANCEL
|
};
|
||||||
</button>
|
}, []);
|
||||||
<button className="button-link proceed-comment-removal" onClick={proceedMediaRemoval}>
|
|
||||||
PROCEED
|
const authorLink = formatInnerLink(props.author.url, SiteContext._currentValue.url);
|
||||||
</button>
|
const authorThumb = formatInnerLink(props.author.thumb, SiteContext._currentValue.url);
|
||||||
</span>
|
|
||||||
</PopupMain>
|
function setTimestampAnchors(text) {
|
||||||
</PopupContent>
|
function wrapTimestampWithAnchor(match, string) {
|
||||||
) : null}
|
let split = match.split(':'),
|
||||||
|
s = 0,
|
||||||
|
m = 1;
|
||||||
|
|
||||||
|
while (split.length > 0) {
|
||||||
|
s += m * parseInt(split.pop(), 10);
|
||||||
|
m *= 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
const wrapped = `<a href="#" data-timestamp="${s}" class="video-timestamp">${match}</a>`;
|
||||||
|
return wrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeRegex = new RegExp('((\\d)?\\d:)?(\\d)?\\d:\\d\\d', 'g');
|
||||||
|
return text.replace(timeRegex, wrapTimestampWithAnchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="media-info-content">
|
||||||
|
{void 0 === PageStore.get('config-media-item').displayAuthor ||
|
||||||
|
null === PageStore.get('config-media-item').displayAuthor ||
|
||||||
|
!!PageStore.get('config-media-item').displayAuthor ? (
|
||||||
|
<MediaAuthorBanner
|
||||||
|
link={authorLink}
|
||||||
|
thumb={authorThumb}
|
||||||
|
name={props.author.name}
|
||||||
|
published={props.published}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
<div className="media-content-banner">
|
||||||
|
<div className="media-content-banner-inner">
|
||||||
|
{hasSummary ? <div className="media-content-summary">{summary}</div> : null}
|
||||||
|
{(!hasSummary || isContentVisible) && description ? (
|
||||||
|
<div
|
||||||
|
className="media-content-description"
|
||||||
|
dangerouslySetInnerHTML={{ __html: setTimestampAnchors(description) }}
|
||||||
|
></div>
|
||||||
|
) : null}
|
||||||
|
{hasSummary ? (
|
||||||
|
<button className="load-more" onClick={onClickLoadMore}>
|
||||||
|
{isContentVisible ? 'SHOW LESS' : 'SHOW MORE'}
|
||||||
|
</button>
|
||||||
|
) : null}
|
||||||
|
{tagsContent.length ? (
|
||||||
|
<MediaMetaField
|
||||||
|
value={tagsContent}
|
||||||
|
title={1 < tagsContent.length ? translateString('Tags') : translateString('Tag')}
|
||||||
|
id="tags"
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
{categoriesContent.length ? (
|
||||||
|
<MediaMetaField
|
||||||
|
value={categoriesContent}
|
||||||
|
title={
|
||||||
|
1 < categoriesContent.length
|
||||||
|
? translateString('Categories')
|
||||||
|
: translateString('Category')
|
||||||
|
}
|
||||||
|
id="categories"
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{userCan.editMedia ? (
|
||||||
|
<div className="media-author-actions">
|
||||||
|
{userCan.editMedia ? (
|
||||||
|
<EditMediaButton link={MediaPageStore.get('media-data').edit_url} />
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{userCan.deleteMedia ? (
|
||||||
|
<PopupTrigger contentRef={popupContentRef}>
|
||||||
|
<button className="remove-media-icon" title={translateString('Delete media')}>
|
||||||
|
<i className="material-icons">delete</i>
|
||||||
|
</button>
|
||||||
|
</PopupTrigger>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{userCan.deleteMedia ? (
|
||||||
|
<PopupContent contentRef={popupContentRef}>
|
||||||
|
<PopupMain>
|
||||||
|
<div className="popup-message">
|
||||||
|
<span className="popup-message-title">Media removal</span>
|
||||||
|
<span className="popup-message-main">
|
||||||
|
You're willing to remove media permanently?
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
<span className="popup-message-bottom">
|
||||||
|
<button
|
||||||
|
className="button-link cancel-comment-removal"
|
||||||
|
onClick={cancelMediaRemoval}
|
||||||
|
>
|
||||||
|
CANCEL
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="button-link proceed-comment-removal"
|
||||||
|
onClick={proceedMediaRemoval}
|
||||||
|
>
|
||||||
|
PROCEED
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</PopupMain>
|
||||||
|
</PopupContent>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<CommentsList />
|
{!inEmbeddedApp() && <CommentsList />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,33 @@
|
|||||||
.page-main-wrap {
|
.page-main-wrap {
|
||||||
padding-top: var(--header-height);
|
padding-top: var(--header-height);
|
||||||
will-change: padding-left;
|
will-change: padding-left;
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.visible-sidebar & {
|
||||||
|
padding-left: var(--sidebar-width);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.visible-sidebar #page-media & {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.visible-sidebar & {
|
.visible-sidebar & {
|
||||||
padding-left: var(--sidebar-width);
|
#page-media {
|
||||||
opacity: 1;
|
padding-left: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.visible-sidebar #page-media & {
|
body.sliding-sidebar & {
|
||||||
padding-left: 0;
|
transition-property: padding-left;
|
||||||
}
|
transition-duration: 0.2s;
|
||||||
|
|
||||||
.visible-sidebar & {
|
|
||||||
#page-media {
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
body.sliding-sidebar & {
|
.embedded-app & {
|
||||||
transition-property: padding-left;
|
padding-top: 0;
|
||||||
transition-duration: 0.2s;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#page-profile-media,
|
#page-profile-media,
|
||||||
@@ -30,20 +35,20 @@
|
|||||||
#page-profile-about,
|
#page-profile-about,
|
||||||
#page-liked.profile-page-liked,
|
#page-liked.profile-page-liked,
|
||||||
#page-history.profile-page-history {
|
#page-history.profile-page-history {
|
||||||
.page-main {
|
.page-main {
|
||||||
min-height: calc(100vh - var(--header-height));
|
min-height: calc(100vh - var(--header-height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-main {
|
.page-main {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding-bottom: 16px;
|
padding-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-main-inner {
|
.page-main-inner {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 1em 1em 0 1em;
|
margin: 1em 1em 0 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#page-profile-media,
|
#page-profile-media,
|
||||||
@@ -51,7 +56,7 @@
|
|||||||
#page-profile-about,
|
#page-profile-about,
|
||||||
#page-liked.profile-page-liked,
|
#page-liked.profile-page-liked,
|
||||||
#page-history.profile-page-history {
|
#page-history.profile-page-history {
|
||||||
.page-main-wrap {
|
.page-main-wrap {
|
||||||
background-color: var(--body-bg-color);
|
background-color: var(--body-bg-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@ import { ProfileMediaFilters } from '../components/search-filters/ProfileMediaFi
|
|||||||
import { ProfileMediaTags } from '../components/search-filters/ProfileMediaTags';
|
import { ProfileMediaTags } from '../components/search-filters/ProfileMediaTags';
|
||||||
import { ProfileMediaSorting } from '../components/search-filters/ProfileMediaSorting';
|
import { ProfileMediaSorting } from '../components/search-filters/ProfileMediaSorting';
|
||||||
import { BulkActionsModals } from '../components/BulkActionsModals';
|
import { BulkActionsModals } from '../components/BulkActionsModals';
|
||||||
import { translateString } from '../utils/helpers';
|
import { inEmbeddedApp, translateString } from '../utils/helpers';
|
||||||
import { withBulkActions } from '../utils/hoc/withBulkActions';
|
import { withBulkActions } from '../utils/hoc/withBulkActions';
|
||||||
|
|
||||||
import { Page } from './_Page';
|
import { Page } from './_Page';
|
||||||
@@ -19,400 +19,443 @@ import { Page } from './_Page';
|
|||||||
import '../components/profile-page/ProfilePage.scss';
|
import '../components/profile-page/ProfilePage.scss';
|
||||||
|
|
||||||
function EmptySharedByMe(props) {
|
function EmptySharedByMe(props) {
|
||||||
return (
|
return (
|
||||||
<LinksConsumer>
|
<LinksConsumer>
|
||||||
{(links) => (
|
{(links) => (
|
||||||
<div className="empty-media empty-channel-media">
|
<div className="empty-media empty-channel-media">
|
||||||
<div className="welcome-title">No shared media</div>
|
<div className="welcome-title">No shared media</div>
|
||||||
<div className="start-uploading">
|
<div className="start-uploading">Media that you have shared with others will show up here.</div>
|
||||||
Media that you have shared with others will show up here.
|
</div>
|
||||||
</div>
|
)}
|
||||||
</div>
|
</LinksConsumer>
|
||||||
)}
|
);
|
||||||
</LinksConsumer>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProfileSharedByMePage extends Page {
|
class ProfileSharedByMePage extends Page {
|
||||||
constructor(props, pageSlug) {
|
constructor(props, pageSlug) {
|
||||||
super(props, 'string' === typeof pageSlug ? pageSlug : 'author-shared-by-me');
|
super(props, 'string' === typeof pageSlug ? pageSlug : 'author-shared-by-me');
|
||||||
|
|
||||||
this.profilePageSlug = 'string' === typeof pageSlug ? pageSlug : 'author-shared-by-me';
|
this.profilePageSlug = 'string' === typeof pageSlug ? pageSlug : 'author-shared-by-me';
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
channelMediaCount: -1,
|
channelMediaCount: -1,
|
||||||
author: ProfilePageStore.get('author-data'),
|
author: ProfilePageStore.get('author-data'),
|
||||||
uploadsPreviewItemsCount: 0,
|
uploadsPreviewItemsCount: 0,
|
||||||
title: this.props.title,
|
title: this.props.title,
|
||||||
query: ProfilePageStore.get('author-query'),
|
query: ProfilePageStore.get('author-query'),
|
||||||
requestUrl: null,
|
requestUrl: null,
|
||||||
hiddenFilters: true,
|
hiddenFilters: true,
|
||||||
hiddenTags: true,
|
hiddenTags: true,
|
||||||
hiddenSorting: true,
|
hiddenSorting: true,
|
||||||
filterArgs: '',
|
filterArgs: '',
|
||||||
availableTags: [],
|
availableTags: [],
|
||||||
selectedTag: 'all',
|
selectedTag: 'all',
|
||||||
selectedSort: 'date_added_desc',
|
selectedSort: 'date_added_desc',
|
||||||
};
|
};
|
||||||
|
|
||||||
this.authorDataLoad = this.authorDataLoad.bind(this);
|
this.authorDataLoad = this.authorDataLoad.bind(this);
|
||||||
this.onAuthorPreviewItemsCountCallback = this.onAuthorPreviewItemsCountCallback.bind(this);
|
this.onAuthorPreviewItemsCountCallback = this.onAuthorPreviewItemsCountCallback.bind(this);
|
||||||
this.getCountFunc = this.getCountFunc.bind(this);
|
this.getCountFunc = this.getCountFunc.bind(this);
|
||||||
this.changeRequestQuery = this.changeRequestQuery.bind(this);
|
this.changeRequestQuery = this.changeRequestQuery.bind(this);
|
||||||
this.onToggleFiltersClick = this.onToggleFiltersClick.bind(this);
|
this.onToggleFiltersClick = this.onToggleFiltersClick.bind(this);
|
||||||
this.onToggleTagsClick = this.onToggleTagsClick.bind(this);
|
this.onToggleTagsClick = this.onToggleTagsClick.bind(this);
|
||||||
this.onToggleSortingClick = this.onToggleSortingClick.bind(this);
|
this.onToggleSortingClick = this.onToggleSortingClick.bind(this);
|
||||||
this.onFiltersUpdate = this.onFiltersUpdate.bind(this);
|
this.onFiltersUpdate = this.onFiltersUpdate.bind(this);
|
||||||
this.onTagSelect = this.onTagSelect.bind(this);
|
this.onTagSelect = this.onTagSelect.bind(this);
|
||||||
this.onSortSelect = this.onSortSelect.bind(this);
|
this.onSortSelect = this.onSortSelect.bind(this);
|
||||||
this.onResponseDataLoaded = this.onResponseDataLoaded.bind(this);
|
this.onResponseDataLoaded = this.onResponseDataLoaded.bind(this);
|
||||||
|
|
||||||
ProfilePageStore.on('load-author-data', this.authorDataLoad);
|
ProfilePageStore.on('load-author-data', this.authorDataLoad);
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
ProfilePageActions.load_author_data();
|
|
||||||
}
|
|
||||||
|
|
||||||
authorDataLoad() {
|
|
||||||
const author = ProfilePageStore.get('author-data');
|
|
||||||
|
|
||||||
let requestUrl = this.state.requestUrl;
|
|
||||||
|
|
||||||
if (author) {
|
|
||||||
if (this.state.query) {
|
|
||||||
requestUrl = ApiUrlContext._currentValue.media + '?author=' + author.id + '&show=shared_by_me&q=' + encodeURIComponent(this.state.query) + this.state.filterArgs;
|
|
||||||
} else {
|
|
||||||
requestUrl = ApiUrlContext._currentValue.media + '?author=' + author.id + '&show=shared_by_me' + this.state.filterArgs;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
componentDidMount() {
|
||||||
author: author,
|
ProfilePageActions.load_author_data();
|
||||||
requestUrl: requestUrl,
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onAuthorPreviewItemsCountCallback(totalAuthorPreviewItems) {
|
authorDataLoad() {
|
||||||
this.setState({
|
const author = ProfilePageStore.get('author-data');
|
||||||
uploadsPreviewItemsCount: totalAuthorPreviewItems,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getCountFunc(count) {
|
let requestUrl = this.state.requestUrl;
|
||||||
this.setState(
|
|
||||||
{
|
|
||||||
channelMediaCount: count,
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
if (this.state.query) {
|
|
||||||
let title = '';
|
|
||||||
|
|
||||||
if (!count) {
|
if (author) {
|
||||||
title = 'No results for "' + this.state.query + '"';
|
if (this.state.query) {
|
||||||
} else if (1 === count) {
|
requestUrl =
|
||||||
title = '1 result for "' + this.state.query + '"';
|
ApiUrlContext._currentValue.media +
|
||||||
} else {
|
'?author=' +
|
||||||
title = count + ' results for "' + this.state.query + '"';
|
author.id +
|
||||||
}
|
'&show=shared_by_me&q=' +
|
||||||
|
encodeURIComponent(this.state.query) +
|
||||||
this.setState({
|
this.state.filterArgs;
|
||||||
title: title,
|
} else {
|
||||||
});
|
requestUrl =
|
||||||
|
ApiUrlContext._currentValue.media +
|
||||||
|
'?author=' +
|
||||||
|
author.id +
|
||||||
|
'&show=shared_by_me' +
|
||||||
|
this.state.filterArgs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
changeRequestQuery(newQuery) {
|
this.setState({
|
||||||
if (!this.state.author) {
|
author: author,
|
||||||
return;
|
requestUrl: requestUrl,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let requestUrl;
|
onAuthorPreviewItemsCountCallback(totalAuthorPreviewItems) {
|
||||||
|
this.setState({
|
||||||
if (newQuery) {
|
uploadsPreviewItemsCount: totalAuthorPreviewItems,
|
||||||
requestUrl = ApiUrlContext._currentValue.media + '?author=' + this.state.author.id + '&show=shared_by_me&q=' + encodeURIComponent(newQuery) + this.state.filterArgs;
|
});
|
||||||
} else {
|
|
||||||
requestUrl = ApiUrlContext._currentValue.media + '?author=' + this.state.author.id + '&show=shared_by_me' + this.state.filterArgs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let title = this.state.title;
|
getCountFunc(count) {
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
channelMediaCount: count,
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
if (this.state.query) {
|
||||||
|
let title = '';
|
||||||
|
|
||||||
if ('' === newQuery) {
|
if (!count) {
|
||||||
title = this.props.title;
|
title = 'No results for "' + this.state.query + '"';
|
||||||
|
} else if (1 === count) {
|
||||||
|
title = '1 result for "' + this.state.query + '"';
|
||||||
|
} else {
|
||||||
|
title = count + ' results for "' + this.state.query + '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
title: title,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
changeRequestQuery(newQuery) {
|
||||||
requestUrl: requestUrl,
|
|
||||||
query: newQuery,
|
|
||||||
title: title,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onToggleFiltersClick() {
|
|
||||||
this.setState({
|
|
||||||
hiddenFilters: !this.state.hiddenFilters,
|
|
||||||
hiddenTags: true,
|
|
||||||
hiddenSorting: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onToggleTagsClick() {
|
|
||||||
this.setState({
|
|
||||||
hiddenFilters: true,
|
|
||||||
hiddenTags: !this.state.hiddenTags,
|
|
||||||
hiddenSorting: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onToggleSortingClick() {
|
|
||||||
this.setState({
|
|
||||||
hiddenFilters: true,
|
|
||||||
hiddenTags: true,
|
|
||||||
hiddenSorting: !this.state.hiddenSorting,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onTagSelect(tag) {
|
|
||||||
this.setState({ selectedTag: tag }, () => {
|
|
||||||
this.onFiltersUpdate({
|
|
||||||
media_type: this.state.filterArgs.match(/media_type=([^&]+)/)?.[1],
|
|
||||||
upload_date: this.state.filterArgs.match(/upload_date=([^&]+)/)?.[1],
|
|
||||||
duration: this.state.filterArgs.match(/duration=([^&]+)/)?.[1],
|
|
||||||
publish_state: this.state.filterArgs.match(/publish_state=([^&]+)/)?.[1],
|
|
||||||
sort_by: this.state.selectedSort,
|
|
||||||
tag: tag,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onSortSelect(sortBy) {
|
|
||||||
this.setState({ selectedSort: sortBy }, () => {
|
|
||||||
this.onFiltersUpdate({
|
|
||||||
media_type: this.state.filterArgs.match(/media_type=([^&]+)/)?.[1],
|
|
||||||
upload_date: this.state.filterArgs.match(/upload_date=([^&]+)/)?.[1],
|
|
||||||
duration: this.state.filterArgs.match(/duration=([^&]+)/)?.[1],
|
|
||||||
publish_state: this.state.filterArgs.match(/publish_state=([^&]+)/)?.[1],
|
|
||||||
sort_by: sortBy,
|
|
||||||
tag: this.state.selectedTag,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onFiltersUpdate(updatedArgs) {
|
|
||||||
const args = {
|
|
||||||
media_type: null,
|
|
||||||
upload_date: null,
|
|
||||||
duration: null,
|
|
||||||
publish_state: null,
|
|
||||||
sort_by: null,
|
|
||||||
ordering: null,
|
|
||||||
t: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (updatedArgs.media_type) {
|
|
||||||
case 'video':
|
|
||||||
case 'audio':
|
|
||||||
case 'image':
|
|
||||||
case 'pdf':
|
|
||||||
args.media_type = updatedArgs.media_type;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (updatedArgs.upload_date) {
|
|
||||||
case 'today':
|
|
||||||
case 'this_week':
|
|
||||||
case 'this_month':
|
|
||||||
case 'this_year':
|
|
||||||
args.upload_date = updatedArgs.upload_date;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle duration filter
|
|
||||||
if (updatedArgs.duration && updatedArgs.duration !== 'all') {
|
|
||||||
args.duration = updatedArgs.duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle publish state filter
|
|
||||||
if (updatedArgs.publish_state && updatedArgs.publish_state !== 'all') {
|
|
||||||
args.publish_state = updatedArgs.publish_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (updatedArgs.sort_by) {
|
|
||||||
case 'date_added_desc':
|
|
||||||
// Default sorting, no need to add parameters
|
|
||||||
break;
|
|
||||||
case 'date_added_asc':
|
|
||||||
args.ordering = 'asc';
|
|
||||||
break;
|
|
||||||
case 'alphabetically_asc':
|
|
||||||
args.sort_by = 'title_asc';
|
|
||||||
break;
|
|
||||||
case 'alphabetically_desc':
|
|
||||||
args.sort_by = 'title_desc';
|
|
||||||
break;
|
|
||||||
case 'plays_least':
|
|
||||||
args.sort_by = 'views_asc';
|
|
||||||
break;
|
|
||||||
case 'plays_most':
|
|
||||||
args.sort_by = 'views_desc';
|
|
||||||
break;
|
|
||||||
case 'likes_least':
|
|
||||||
args.sort_by = 'likes_asc';
|
|
||||||
break;
|
|
||||||
case 'likes_most':
|
|
||||||
args.sort_by = 'likes_desc';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updatedArgs.tag && updatedArgs.tag !== 'all') {
|
|
||||||
args.t = updatedArgs.tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newArgs = [];
|
|
||||||
|
|
||||||
for (let arg in args) {
|
|
||||||
if (null !== args[arg]) {
|
|
||||||
newArgs.push(arg + '=' + args[arg]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState(
|
|
||||||
{
|
|
||||||
filterArgs: newArgs.length ? '&' + newArgs.join('&') : '',
|
|
||||||
},
|
|
||||||
function () {
|
|
||||||
if (!this.state.author) {
|
if (!this.state.author) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let requestUrl;
|
let requestUrl;
|
||||||
|
|
||||||
if (this.state.query) {
|
if (newQuery) {
|
||||||
requestUrl = ApiUrlContext._currentValue.media + '?author=' + this.state.author.id + '&show=shared_by_me&q=' + encodeURIComponent(this.state.query) + this.state.filterArgs;
|
requestUrl =
|
||||||
|
ApiUrlContext._currentValue.media +
|
||||||
|
'?author=' +
|
||||||
|
this.state.author.id +
|
||||||
|
'&show=shared_by_me&q=' +
|
||||||
|
encodeURIComponent(newQuery) +
|
||||||
|
this.state.filterArgs;
|
||||||
} else {
|
} else {
|
||||||
requestUrl = ApiUrlContext._currentValue.media + '?author=' + this.state.author.id + '&show=shared_by_me' + this.state.filterArgs;
|
requestUrl =
|
||||||
|
ApiUrlContext._currentValue.media +
|
||||||
|
'?author=' +
|
||||||
|
this.state.author.id +
|
||||||
|
'&show=shared_by_me' +
|
||||||
|
this.state.filterArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
let title = this.state.title;
|
||||||
|
|
||||||
|
if ('' === newQuery) {
|
||||||
|
title = this.props.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
requestUrl: requestUrl,
|
requestUrl: requestUrl,
|
||||||
|
query: newQuery,
|
||||||
|
title: title,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
onResponseDataLoaded(responseData) {
|
|
||||||
if (responseData && responseData.tags) {
|
|
||||||
const tags = responseData.tags.split(',').map((tag) => tag.trim()).filter((tag) => tag);
|
|
||||||
this.setState({ availableTags: tags });
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pageContent() {
|
onToggleFiltersClick() {
|
||||||
const authorData = ProfilePageStore.get('author-data');
|
this.setState({
|
||||||
|
hiddenFilters: !this.state.hiddenFilters,
|
||||||
|
hiddenTags: true,
|
||||||
|
hiddenSorting: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const isMediaAuthor = authorData && authorData.username === MemberContext._currentValue.username;
|
onToggleTagsClick() {
|
||||||
|
this.setState({
|
||||||
|
hiddenFilters: true,
|
||||||
|
hiddenTags: !this.state.hiddenTags,
|
||||||
|
hiddenSorting: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Check if any filters are active
|
onToggleSortingClick() {
|
||||||
const hasActiveFilters = this.state.filterArgs && (
|
this.setState({
|
||||||
this.state.filterArgs.includes('media_type=') ||
|
hiddenFilters: true,
|
||||||
this.state.filterArgs.includes('upload_date=') ||
|
hiddenTags: true,
|
||||||
this.state.filterArgs.includes('duration=') ||
|
hiddenSorting: !this.state.hiddenSorting,
|
||||||
this.state.filterArgs.includes('publish_state=')
|
});
|
||||||
);
|
}
|
||||||
|
|
||||||
return [
|
onTagSelect(tag) {
|
||||||
this.state.author ? (
|
this.setState({ selectedTag: tag }, () => {
|
||||||
<ProfilePagesHeader
|
this.onFiltersUpdate({
|
||||||
key="ProfilePagesHeader"
|
media_type: this.state.filterArgs.match(/media_type=([^&]+)/)?.[1],
|
||||||
author={this.state.author}
|
upload_date: this.state.filterArgs.match(/upload_date=([^&]+)/)?.[1],
|
||||||
type="shared_by_me"
|
duration: this.state.filterArgs.match(/duration=([^&]+)/)?.[1],
|
||||||
onQueryChange={this.changeRequestQuery}
|
publish_state: this.state.filterArgs.match(/publish_state=([^&]+)/)?.[1],
|
||||||
onToggleFiltersClick={this.onToggleFiltersClick}
|
sort_by: this.state.selectedSort,
|
||||||
onToggleTagsClick={this.onToggleTagsClick}
|
tag: tag,
|
||||||
onToggleSortingClick={this.onToggleSortingClick}
|
});
|
||||||
hasActiveFilters={hasActiveFilters}
|
});
|
||||||
hasActiveTags={this.state.selectedTag !== 'all'}
|
}
|
||||||
hasActiveSort={this.state.selectedSort !== 'date_added_desc'}
|
|
||||||
/>
|
onSortSelect(sortBy) {
|
||||||
) : null,
|
this.setState({ selectedSort: sortBy }, () => {
|
||||||
this.state.author ? (
|
this.onFiltersUpdate({
|
||||||
<ProfilePagesContent key="ProfilePagesContent">
|
media_type: this.state.filterArgs.match(/media_type=([^&]+)/)?.[1],
|
||||||
<MediaListWrapper
|
upload_date: this.state.filterArgs.match(/upload_date=([^&]+)/)?.[1],
|
||||||
title={this.state.title}
|
duration: this.state.filterArgs.match(/duration=([^&]+)/)?.[1],
|
||||||
className="items-list-ver"
|
publish_state: this.state.filterArgs.match(/publish_state=([^&]+)/)?.[1],
|
||||||
showBulkActions={isMediaAuthor}
|
sort_by: sortBy,
|
||||||
selectedCount={this.props.bulkActions.selectedMedia.size}
|
tag: this.state.selectedTag,
|
||||||
totalCount={this.props.bulkActions.availableMediaIds.length}
|
});
|
||||||
onBulkAction={this.props.bulkActions.handleBulkAction}
|
});
|
||||||
onSelectAll={this.props.bulkActions.handleSelectAll}
|
}
|
||||||
onDeselectAll={this.props.bulkActions.handleDeselectAll}
|
|
||||||
>
|
onFiltersUpdate(updatedArgs) {
|
||||||
<ProfileMediaFilters hidden={this.state.hiddenFilters} tags={this.state.availableTags} onFiltersUpdate={this.onFiltersUpdate} />
|
const args = {
|
||||||
<ProfileMediaTags hidden={this.state.hiddenTags} tags={this.state.availableTags} onTagSelect={this.onTagSelect} />
|
media_type: null,
|
||||||
<ProfileMediaSorting hidden={this.state.hiddenSorting} onSortSelect={this.onSortSelect} />
|
upload_date: null,
|
||||||
<LazyLoadItemListAsync
|
duration: null,
|
||||||
key={`${this.state.requestUrl}-${this.props.bulkActions.listKey}`}
|
publish_state: null,
|
||||||
requestUrl={this.state.requestUrl}
|
sort_by: null,
|
||||||
hideAuthor={true}
|
ordering: null,
|
||||||
itemsCountCallback={this.state.requestUrl ? this.getCountFunc : null}
|
t: null,
|
||||||
hideViews={!PageStore.get('config-media-item').displayViews}
|
};
|
||||||
hideDate={!PageStore.get('config-media-item').displayPublishDate}
|
|
||||||
canEdit={isMediaAuthor}
|
switch (updatedArgs.media_type) {
|
||||||
onResponseDataLoaded={this.onResponseDataLoaded}
|
case 'video':
|
||||||
showSelection={isMediaAuthor}
|
case 'audio':
|
||||||
hasAnySelection={this.props.bulkActions.selectedMedia.size > 0}
|
case 'image':
|
||||||
selectedMedia={this.props.bulkActions.selectedMedia}
|
case 'pdf':
|
||||||
onMediaSelection={this.props.bulkActions.handleMediaSelection}
|
args.media_type = updatedArgs.media_type;
|
||||||
onItemsUpdate={this.props.bulkActions.handleItemsUpdate}
|
break;
|
||||||
/>
|
}
|
||||||
{isMediaAuthor && 0 === this.state.channelMediaCount && !this.state.query ? (
|
|
||||||
<EmptySharedByMe name={this.state.author.name} />
|
switch (updatedArgs.upload_date) {
|
||||||
) : null}
|
case 'today':
|
||||||
</MediaListWrapper>
|
case 'this_week':
|
||||||
</ProfilePagesContent>
|
case 'this_month':
|
||||||
) : null,
|
case 'this_year':
|
||||||
this.state.author && isMediaAuthor ? (
|
args.upload_date = updatedArgs.upload_date;
|
||||||
<BulkActionsModals
|
break;
|
||||||
key="BulkActionsModals"
|
}
|
||||||
{...this.props.bulkActions}
|
|
||||||
selectedMediaIds={Array.from(this.props.bulkActions.selectedMedia)}
|
// Handle duration filter
|
||||||
csrfToken={this.props.bulkActions.getCsrfToken()}
|
if (updatedArgs.duration && updatedArgs.duration !== 'all') {
|
||||||
username={this.state.author.username}
|
args.duration = updatedArgs.duration;
|
||||||
onConfirmCancel={this.props.bulkActions.handleConfirmCancel}
|
}
|
||||||
onConfirmProceed={this.props.bulkActions.handleConfirmProceed}
|
|
||||||
onPermissionModalCancel={this.props.bulkActions.handlePermissionModalCancel}
|
// Handle publish state filter
|
||||||
onPermissionModalSuccess={this.props.bulkActions.handlePermissionModalSuccess}
|
if (updatedArgs.publish_state && updatedArgs.publish_state !== 'all') {
|
||||||
onPermissionModalError={this.props.bulkActions.handlePermissionModalError}
|
args.publish_state = updatedArgs.publish_state;
|
||||||
onPlaylistModalCancel={this.props.bulkActions.handlePlaylistModalCancel}
|
}
|
||||||
onPlaylistModalSuccess={this.props.bulkActions.handlePlaylistModalSuccess}
|
|
||||||
onPlaylistModalError={this.props.bulkActions.handlePlaylistModalError}
|
switch (updatedArgs.sort_by) {
|
||||||
onChangeOwnerModalCancel={this.props.bulkActions.handleChangeOwnerModalCancel}
|
case 'date_added_desc':
|
||||||
onChangeOwnerModalSuccess={this.props.bulkActions.handleChangeOwnerModalSuccess}
|
// Default sorting, no need to add parameters
|
||||||
onChangeOwnerModalError={this.props.bulkActions.handleChangeOwnerModalError}
|
break;
|
||||||
onPublishStateModalCancel={this.props.bulkActions.handlePublishStateModalCancel}
|
case 'date_added_asc':
|
||||||
onPublishStateModalSuccess={this.props.bulkActions.handlePublishStateModalSuccess}
|
args.ordering = 'asc';
|
||||||
onPublishStateModalError={this.props.bulkActions.handlePublishStateModalError}
|
break;
|
||||||
onCategoryModalCancel={this.props.bulkActions.handleCategoryModalCancel}
|
case 'alphabetically_asc':
|
||||||
onCategoryModalSuccess={this.props.bulkActions.handleCategoryModalSuccess}
|
args.sort_by = 'title_asc';
|
||||||
onCategoryModalError={this.props.bulkActions.handleCategoryModalError}
|
break;
|
||||||
onTagModalCancel={this.props.bulkActions.handleTagModalCancel}
|
case 'alphabetically_desc':
|
||||||
onTagModalSuccess={this.props.bulkActions.handleTagModalSuccess}
|
args.sort_by = 'title_desc';
|
||||||
onTagModalError={this.props.bulkActions.handleTagModalError}
|
break;
|
||||||
/>
|
case 'plays_least':
|
||||||
) : null,
|
args.sort_by = 'views_asc';
|
||||||
];
|
break;
|
||||||
}
|
case 'plays_most':
|
||||||
|
args.sort_by = 'views_desc';
|
||||||
|
break;
|
||||||
|
case 'likes_least':
|
||||||
|
args.sort_by = 'likes_asc';
|
||||||
|
break;
|
||||||
|
case 'likes_most':
|
||||||
|
args.sort_by = 'likes_desc';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatedArgs.tag && updatedArgs.tag !== 'all') {
|
||||||
|
args.t = updatedArgs.tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newArgs = [];
|
||||||
|
|
||||||
|
for (let arg in args) {
|
||||||
|
if (null !== args[arg]) {
|
||||||
|
newArgs.push(arg + '=' + args[arg]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
filterArgs: newArgs.length ? '&' + newArgs.join('&') : '',
|
||||||
|
},
|
||||||
|
function () {
|
||||||
|
if (!this.state.author) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let requestUrl;
|
||||||
|
|
||||||
|
if (this.state.query) {
|
||||||
|
requestUrl =
|
||||||
|
ApiUrlContext._currentValue.media +
|
||||||
|
'?author=' +
|
||||||
|
this.state.author.id +
|
||||||
|
'&show=shared_by_me&q=' +
|
||||||
|
encodeURIComponent(this.state.query) +
|
||||||
|
this.state.filterArgs;
|
||||||
|
} else {
|
||||||
|
requestUrl =
|
||||||
|
ApiUrlContext._currentValue.media +
|
||||||
|
'?author=' +
|
||||||
|
this.state.author.id +
|
||||||
|
'&show=shared_by_me' +
|
||||||
|
this.state.filterArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
requestUrl: requestUrl,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onResponseDataLoaded(responseData) {
|
||||||
|
if (responseData && responseData.tags) {
|
||||||
|
const tags = responseData.tags
|
||||||
|
.split(',')
|
||||||
|
.map((tag) => tag.trim())
|
||||||
|
.filter((tag) => tag);
|
||||||
|
this.setState({ availableTags: tags });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pageContent() {
|
||||||
|
const authorData = ProfilePageStore.get('author-data');
|
||||||
|
|
||||||
|
const isMediaAuthor = authorData && authorData.username === MemberContext._currentValue.username;
|
||||||
|
|
||||||
|
// Check if any filters are active
|
||||||
|
const hasActiveFilters =
|
||||||
|
this.state.filterArgs &&
|
||||||
|
(this.state.filterArgs.includes('media_type=') ||
|
||||||
|
this.state.filterArgs.includes('upload_date=') ||
|
||||||
|
this.state.filterArgs.includes('duration=') ||
|
||||||
|
this.state.filterArgs.includes('publish_state='));
|
||||||
|
|
||||||
|
return [
|
||||||
|
this.state.author ? (
|
||||||
|
<ProfilePagesHeader
|
||||||
|
key="ProfilePagesHeader"
|
||||||
|
author={this.state.author}
|
||||||
|
type="shared_by_me"
|
||||||
|
onQueryChange={this.changeRequestQuery}
|
||||||
|
onToggleFiltersClick={this.onToggleFiltersClick}
|
||||||
|
onToggleTagsClick={this.onToggleTagsClick}
|
||||||
|
onToggleSortingClick={this.onToggleSortingClick}
|
||||||
|
hasActiveFilters={hasActiveFilters}
|
||||||
|
hasActiveTags={this.state.selectedTag !== 'all'}
|
||||||
|
hasActiveSort={this.state.selectedSort !== 'date_added_desc'}
|
||||||
|
hideChannelBanner={inEmbeddedApp()}
|
||||||
|
/>
|
||||||
|
) : null,
|
||||||
|
this.state.author ? (
|
||||||
|
<ProfilePagesContent key="ProfilePagesContent">
|
||||||
|
<MediaListWrapper
|
||||||
|
title={this.state.title}
|
||||||
|
className="items-list-ver"
|
||||||
|
showBulkActions={isMediaAuthor}
|
||||||
|
selectedCount={this.props.bulkActions.selectedMedia.size}
|
||||||
|
totalCount={this.props.bulkActions.availableMediaIds.length}
|
||||||
|
onBulkAction={this.props.bulkActions.handleBulkAction}
|
||||||
|
onSelectAll={this.props.bulkActions.handleSelectAll}
|
||||||
|
onDeselectAll={this.props.bulkActions.handleDeselectAll}
|
||||||
|
>
|
||||||
|
<ProfileMediaFilters
|
||||||
|
hidden={this.state.hiddenFilters}
|
||||||
|
tags={this.state.availableTags}
|
||||||
|
onFiltersUpdate={this.onFiltersUpdate}
|
||||||
|
/>
|
||||||
|
<ProfileMediaTags
|
||||||
|
hidden={this.state.hiddenTags}
|
||||||
|
tags={this.state.availableTags}
|
||||||
|
onTagSelect={this.onTagSelect}
|
||||||
|
/>
|
||||||
|
<ProfileMediaSorting hidden={this.state.hiddenSorting} onSortSelect={this.onSortSelect} />
|
||||||
|
<LazyLoadItemListAsync
|
||||||
|
key={`${this.state.requestUrl}-${this.props.bulkActions.listKey}`}
|
||||||
|
requestUrl={this.state.requestUrl}
|
||||||
|
hideAuthor={true}
|
||||||
|
itemsCountCallback={this.state.requestUrl ? this.getCountFunc : null}
|
||||||
|
hideViews={!PageStore.get('config-media-item').displayViews}
|
||||||
|
hideDate={!PageStore.get('config-media-item').displayPublishDate}
|
||||||
|
canEdit={isMediaAuthor}
|
||||||
|
onResponseDataLoaded={this.onResponseDataLoaded}
|
||||||
|
showSelection={isMediaAuthor}
|
||||||
|
hasAnySelection={this.props.bulkActions.selectedMedia.size > 0}
|
||||||
|
selectedMedia={this.props.bulkActions.selectedMedia}
|
||||||
|
onMediaSelection={this.props.bulkActions.handleMediaSelection}
|
||||||
|
onItemsUpdate={this.props.bulkActions.handleItemsUpdate}
|
||||||
|
/>
|
||||||
|
{isMediaAuthor && 0 === this.state.channelMediaCount && !this.state.query ? (
|
||||||
|
<EmptySharedByMe name={this.state.author.name} />
|
||||||
|
) : null}
|
||||||
|
</MediaListWrapper>
|
||||||
|
</ProfilePagesContent>
|
||||||
|
) : null,
|
||||||
|
this.state.author && isMediaAuthor ? (
|
||||||
|
<BulkActionsModals
|
||||||
|
key="BulkActionsModals"
|
||||||
|
{...this.props.bulkActions}
|
||||||
|
selectedMediaIds={Array.from(this.props.bulkActions.selectedMedia)}
|
||||||
|
csrfToken={this.props.bulkActions.getCsrfToken()}
|
||||||
|
username={this.state.author.username}
|
||||||
|
onConfirmCancel={this.props.bulkActions.handleConfirmCancel}
|
||||||
|
onConfirmProceed={this.props.bulkActions.handleConfirmProceed}
|
||||||
|
onPermissionModalCancel={this.props.bulkActions.handlePermissionModalCancel}
|
||||||
|
onPermissionModalSuccess={this.props.bulkActions.handlePermissionModalSuccess}
|
||||||
|
onPermissionModalError={this.props.bulkActions.handlePermissionModalError}
|
||||||
|
onPlaylistModalCancel={this.props.bulkActions.handlePlaylistModalCancel}
|
||||||
|
onPlaylistModalSuccess={this.props.bulkActions.handlePlaylistModalSuccess}
|
||||||
|
onPlaylistModalError={this.props.bulkActions.handlePlaylistModalError}
|
||||||
|
onChangeOwnerModalCancel={this.props.bulkActions.handleChangeOwnerModalCancel}
|
||||||
|
onChangeOwnerModalSuccess={this.props.bulkActions.handleChangeOwnerModalSuccess}
|
||||||
|
onChangeOwnerModalError={this.props.bulkActions.handleChangeOwnerModalError}
|
||||||
|
onPublishStateModalCancel={this.props.bulkActions.handlePublishStateModalCancel}
|
||||||
|
onPublishStateModalSuccess={this.props.bulkActions.handlePublishStateModalSuccess}
|
||||||
|
onPublishStateModalError={this.props.bulkActions.handlePublishStateModalError}
|
||||||
|
onCategoryModalCancel={this.props.bulkActions.handleCategoryModalCancel}
|
||||||
|
onCategoryModalSuccess={this.props.bulkActions.handleCategoryModalSuccess}
|
||||||
|
onCategoryModalError={this.props.bulkActions.handleCategoryModalError}
|
||||||
|
onTagModalCancel={this.props.bulkActions.handleTagModalCancel}
|
||||||
|
onTagModalSuccess={this.props.bulkActions.handleTagModalSuccess}
|
||||||
|
onTagModalError={this.props.bulkActions.handleTagModalError}
|
||||||
|
/>
|
||||||
|
) : null,
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfileSharedByMePage.propTypes = {
|
ProfileSharedByMePage.propTypes = {
|
||||||
title: PropTypes.string.isRequired,
|
title: PropTypes.string.isRequired,
|
||||||
bulkActions: PropTypes.object.isRequired,
|
bulkActions: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
ProfileSharedByMePage.defaultProps = {
|
ProfileSharedByMePage.defaultProps = {
|
||||||
title: 'Shared by me',
|
title: 'Shared by me',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wrap with HOC and export as named export for compatibility
|
// Wrap with HOC and export as named export for compatibility
|
||||||
|
|||||||
@@ -10,364 +10,404 @@ import { LazyLoadItemListAsync } from '../components/item-list/LazyLoadItemListA
|
|||||||
import { ProfileMediaFilters } from '../components/search-filters/ProfileMediaFilters';
|
import { ProfileMediaFilters } from '../components/search-filters/ProfileMediaFilters';
|
||||||
import { ProfileMediaTags } from '../components/search-filters/ProfileMediaTags';
|
import { ProfileMediaTags } from '../components/search-filters/ProfileMediaTags';
|
||||||
import { ProfileMediaSorting } from '../components/search-filters/ProfileMediaSorting';
|
import { ProfileMediaSorting } from '../components/search-filters/ProfileMediaSorting';
|
||||||
import { translateString } from '../utils/helpers';
|
import { inEmbeddedApp, translateString } from '../utils/helpers';
|
||||||
|
|
||||||
import { Page } from './_Page';
|
import { Page } from './_Page';
|
||||||
|
|
||||||
import '../components/profile-page/ProfilePage.scss';
|
import '../components/profile-page/ProfilePage.scss';
|
||||||
|
|
||||||
function EmptySharedWithMe(props) {
|
function EmptySharedWithMe(props) {
|
||||||
return (
|
return (
|
||||||
<LinksConsumer>
|
<LinksConsumer>
|
||||||
{(links) => (
|
{(links) => (
|
||||||
<div className="empty-media empty-channel-media">
|
<div className="empty-media empty-channel-media">
|
||||||
<div className="welcome-title">No shared media</div>
|
<div className="welcome-title">No shared media</div>
|
||||||
<div className="start-uploading">
|
<div className="start-uploading">Media that others have shared with you will show up here.</div>
|
||||||
Media that others have shared with you will show up here.
|
</div>
|
||||||
</div>
|
)}
|
||||||
</div>
|
</LinksConsumer>
|
||||||
)}
|
);
|
||||||
</LinksConsumer>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ProfileSharedWithMePage extends Page {
|
export class ProfileSharedWithMePage extends Page {
|
||||||
constructor(props, pageSlug) {
|
constructor(props, pageSlug) {
|
||||||
super(props, 'string' === typeof pageSlug ? pageSlug : 'author-shared-with-me');
|
super(props, 'string' === typeof pageSlug ? pageSlug : 'author-shared-with-me');
|
||||||
|
|
||||||
this.profilePageSlug = 'string' === typeof pageSlug ? pageSlug : 'author-shared-with-me';
|
this.profilePageSlug = 'string' === typeof pageSlug ? pageSlug : 'author-shared-with-me';
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
channelMediaCount: -1,
|
channelMediaCount: -1,
|
||||||
author: ProfilePageStore.get('author-data'),
|
author: ProfilePageStore.get('author-data'),
|
||||||
uploadsPreviewItemsCount: 0,
|
uploadsPreviewItemsCount: 0,
|
||||||
title: this.props.title,
|
title: this.props.title,
|
||||||
query: ProfilePageStore.get('author-query'),
|
query: ProfilePageStore.get('author-query'),
|
||||||
requestUrl: null,
|
requestUrl: null,
|
||||||
hiddenFilters: true,
|
hiddenFilters: true,
|
||||||
hiddenTags: true,
|
hiddenTags: true,
|
||||||
hiddenSorting: true,
|
hiddenSorting: true,
|
||||||
filterArgs: '',
|
filterArgs: '',
|
||||||
availableTags: [],
|
availableTags: [],
|
||||||
selectedTag: 'all',
|
selectedTag: 'all',
|
||||||
selectedSort: 'date_added_desc',
|
selectedSort: 'date_added_desc',
|
||||||
};
|
};
|
||||||
|
|
||||||
this.authorDataLoad = this.authorDataLoad.bind(this);
|
this.authorDataLoad = this.authorDataLoad.bind(this);
|
||||||
this.onAuthorPreviewItemsCountCallback = this.onAuthorPreviewItemsCountCallback.bind(this);
|
this.onAuthorPreviewItemsCountCallback = this.onAuthorPreviewItemsCountCallback.bind(this);
|
||||||
this.getCountFunc = this.getCountFunc.bind(this);
|
this.getCountFunc = this.getCountFunc.bind(this);
|
||||||
this.changeRequestQuery = this.changeRequestQuery.bind(this);
|
this.changeRequestQuery = this.changeRequestQuery.bind(this);
|
||||||
this.onToggleFiltersClick = this.onToggleFiltersClick.bind(this);
|
this.onToggleFiltersClick = this.onToggleFiltersClick.bind(this);
|
||||||
this.onToggleTagsClick = this.onToggleTagsClick.bind(this);
|
this.onToggleTagsClick = this.onToggleTagsClick.bind(this);
|
||||||
this.onToggleSortingClick = this.onToggleSortingClick.bind(this);
|
this.onToggleSortingClick = this.onToggleSortingClick.bind(this);
|
||||||
this.onFiltersUpdate = this.onFiltersUpdate.bind(this);
|
this.onFiltersUpdate = this.onFiltersUpdate.bind(this);
|
||||||
this.onTagSelect = this.onTagSelect.bind(this);
|
this.onTagSelect = this.onTagSelect.bind(this);
|
||||||
this.onSortSelect = this.onSortSelect.bind(this);
|
this.onSortSelect = this.onSortSelect.bind(this);
|
||||||
this.onResponseDataLoaded = this.onResponseDataLoaded.bind(this);
|
this.onResponseDataLoaded = this.onResponseDataLoaded.bind(this);
|
||||||
|
|
||||||
ProfilePageStore.on('load-author-data', this.authorDataLoad);
|
ProfilePageStore.on('load-author-data', this.authorDataLoad);
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
ProfilePageActions.load_author_data();
|
|
||||||
}
|
|
||||||
|
|
||||||
authorDataLoad() {
|
|
||||||
const author = ProfilePageStore.get('author-data');
|
|
||||||
|
|
||||||
let requestUrl = this.state.requestUrl;
|
|
||||||
|
|
||||||
if (author) {
|
|
||||||
if (this.state.query) {
|
|
||||||
requestUrl = ApiUrlContext._currentValue.media + '?author=' + author.id + '&show=shared_with_me&q=' + encodeURIComponent(this.state.query) + this.state.filterArgs;
|
|
||||||
} else {
|
|
||||||
requestUrl = ApiUrlContext._currentValue.media + '?author=' + author.id + '&show=shared_with_me' + this.state.filterArgs;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
componentDidMount() {
|
||||||
author: author,
|
ProfilePageActions.load_author_data();
|
||||||
requestUrl: requestUrl,
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onAuthorPreviewItemsCountCallback(totalAuthorPreviewItems) {
|
authorDataLoad() {
|
||||||
this.setState({
|
const author = ProfilePageStore.get('author-data');
|
||||||
uploadsPreviewItemsCount: totalAuthorPreviewItems,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getCountFunc(count) {
|
let requestUrl = this.state.requestUrl;
|
||||||
this.setState(
|
|
||||||
{
|
|
||||||
channelMediaCount: count,
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
if (this.state.query) {
|
|
||||||
let title = '';
|
|
||||||
|
|
||||||
if (!count) {
|
if (author) {
|
||||||
title = 'No results for "' + this.state.query + '"';
|
if (this.state.query) {
|
||||||
} else if (1 === count) {
|
requestUrl =
|
||||||
title = '1 result for "' + this.state.query + '"';
|
ApiUrlContext._currentValue.media +
|
||||||
} else {
|
'?author=' +
|
||||||
title = count + ' results for "' + this.state.query + '"';
|
author.id +
|
||||||
}
|
'&show=shared_with_me&q=' +
|
||||||
|
encodeURIComponent(this.state.query) +
|
||||||
this.setState({
|
this.state.filterArgs;
|
||||||
title: title,
|
} else {
|
||||||
});
|
requestUrl =
|
||||||
|
ApiUrlContext._currentValue.media +
|
||||||
|
'?author=' +
|
||||||
|
author.id +
|
||||||
|
'&show=shared_with_me' +
|
||||||
|
this.state.filterArgs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
changeRequestQuery(newQuery) {
|
this.setState({
|
||||||
if (!this.state.author) {
|
author: author,
|
||||||
return;
|
requestUrl: requestUrl,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let requestUrl;
|
onAuthorPreviewItemsCountCallback(totalAuthorPreviewItems) {
|
||||||
|
this.setState({
|
||||||
if (newQuery) {
|
uploadsPreviewItemsCount: totalAuthorPreviewItems,
|
||||||
requestUrl = ApiUrlContext._currentValue.media + '?author=' + this.state.author.id + '&show=shared_with_me&q=' + encodeURIComponent(newQuery) + this.state.filterArgs;
|
});
|
||||||
} else {
|
|
||||||
requestUrl = ApiUrlContext._currentValue.media + '?author=' + this.state.author.id + '&show=shared_with_me' + this.state.filterArgs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let title = this.state.title;
|
getCountFunc(count) {
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
channelMediaCount: count,
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
if (this.state.query) {
|
||||||
|
let title = '';
|
||||||
|
|
||||||
if ('' === newQuery) {
|
if (!count) {
|
||||||
title = this.props.title;
|
title = 'No results for "' + this.state.query + '"';
|
||||||
|
} else if (1 === count) {
|
||||||
|
title = '1 result for "' + this.state.query + '"';
|
||||||
|
} else {
|
||||||
|
title = count + ' results for "' + this.state.query + '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
title: title,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
changeRequestQuery(newQuery) {
|
||||||
requestUrl: requestUrl,
|
|
||||||
query: newQuery,
|
|
||||||
title: title,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onToggleFiltersClick() {
|
|
||||||
this.setState({
|
|
||||||
hiddenFilters: !this.state.hiddenFilters,
|
|
||||||
hiddenTags: true,
|
|
||||||
hiddenSorting: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onToggleTagsClick() {
|
|
||||||
this.setState({
|
|
||||||
hiddenFilters: true,
|
|
||||||
hiddenTags: !this.state.hiddenTags,
|
|
||||||
hiddenSorting: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onToggleSortingClick() {
|
|
||||||
this.setState({
|
|
||||||
hiddenFilters: true,
|
|
||||||
hiddenTags: true,
|
|
||||||
hiddenSorting: !this.state.hiddenSorting,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onTagSelect(tag) {
|
|
||||||
this.setState({ selectedTag: tag }, () => {
|
|
||||||
this.onFiltersUpdate({
|
|
||||||
media_type: this.state.filterArgs.match(/media_type=([^&]+)/)?.[1],
|
|
||||||
upload_date: this.state.filterArgs.match(/upload_date=([^&]+)/)?.[1],
|
|
||||||
duration: this.state.filterArgs.match(/duration=([^&]+)/)?.[1],
|
|
||||||
publish_state: this.state.filterArgs.match(/publish_state=([^&]+)/)?.[1],
|
|
||||||
sort_by: this.state.selectedSort,
|
|
||||||
tag: tag,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onSortSelect(sortBy) {
|
|
||||||
this.setState({ selectedSort: sortBy }, () => {
|
|
||||||
this.onFiltersUpdate({
|
|
||||||
media_type: this.state.filterArgs.match(/media_type=([^&]+)/)?.[1],
|
|
||||||
upload_date: this.state.filterArgs.match(/upload_date=([^&]+)/)?.[1],
|
|
||||||
duration: this.state.filterArgs.match(/duration=([^&]+)/)?.[1],
|
|
||||||
publish_state: this.state.filterArgs.match(/publish_state=([^&]+)/)?.[1],
|
|
||||||
sort_by: sortBy,
|
|
||||||
tag: this.state.selectedTag,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onFiltersUpdate(updatedArgs) {
|
|
||||||
const args = {
|
|
||||||
media_type: null,
|
|
||||||
upload_date: null,
|
|
||||||
duration: null,
|
|
||||||
publish_state: null,
|
|
||||||
sort_by: null,
|
|
||||||
ordering: null,
|
|
||||||
t: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
switch (updatedArgs.media_type) {
|
|
||||||
case 'video':
|
|
||||||
case 'audio':
|
|
||||||
case 'image':
|
|
||||||
case 'pdf':
|
|
||||||
args.media_type = updatedArgs.media_type;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (updatedArgs.upload_date) {
|
|
||||||
case 'today':
|
|
||||||
case 'this_week':
|
|
||||||
case 'this_month':
|
|
||||||
case 'this_year':
|
|
||||||
args.upload_date = updatedArgs.upload_date;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle duration filter
|
|
||||||
if (updatedArgs.duration && updatedArgs.duration !== 'all') {
|
|
||||||
args.duration = updatedArgs.duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle publish state filter
|
|
||||||
if (updatedArgs.publish_state && updatedArgs.publish_state !== 'all') {
|
|
||||||
args.publish_state = updatedArgs.publish_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (updatedArgs.sort_by) {
|
|
||||||
case 'date_added_desc':
|
|
||||||
// Default sorting, no need to add parameters
|
|
||||||
break;
|
|
||||||
case 'date_added_asc':
|
|
||||||
args.ordering = 'asc';
|
|
||||||
break;
|
|
||||||
case 'alphabetically_asc':
|
|
||||||
args.sort_by = 'title_asc';
|
|
||||||
break;
|
|
||||||
case 'alphabetically_desc':
|
|
||||||
args.sort_by = 'title_desc';
|
|
||||||
break;
|
|
||||||
case 'plays_least':
|
|
||||||
args.sort_by = 'views_asc';
|
|
||||||
break;
|
|
||||||
case 'plays_most':
|
|
||||||
args.sort_by = 'views_desc';
|
|
||||||
break;
|
|
||||||
case 'likes_least':
|
|
||||||
args.sort_by = 'likes_asc';
|
|
||||||
break;
|
|
||||||
case 'likes_most':
|
|
||||||
args.sort_by = 'likes_desc';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updatedArgs.tag && updatedArgs.tag !== 'all') {
|
|
||||||
args.t = updatedArgs.tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newArgs = [];
|
|
||||||
|
|
||||||
for (let arg in args) {
|
|
||||||
if (null !== args[arg]) {
|
|
||||||
newArgs.push(arg + '=' + args[arg]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState(
|
|
||||||
{
|
|
||||||
filterArgs: newArgs.length ? '&' + newArgs.join('&') : '',
|
|
||||||
},
|
|
||||||
function () {
|
|
||||||
if (!this.state.author) {
|
if (!this.state.author) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let requestUrl;
|
let requestUrl;
|
||||||
|
|
||||||
if (this.state.query) {
|
if (newQuery) {
|
||||||
requestUrl = ApiUrlContext._currentValue.media + '?author=' + this.state.author.id + '&show=shared_with_me&q=' + encodeURIComponent(this.state.query) + this.state.filterArgs;
|
requestUrl =
|
||||||
|
ApiUrlContext._currentValue.media +
|
||||||
|
'?author=' +
|
||||||
|
this.state.author.id +
|
||||||
|
'&show=shared_with_me&q=' +
|
||||||
|
encodeURIComponent(newQuery) +
|
||||||
|
this.state.filterArgs;
|
||||||
} else {
|
} else {
|
||||||
requestUrl = ApiUrlContext._currentValue.media + '?author=' + this.state.author.id + '&show=shared_with_me' + this.state.filterArgs;
|
requestUrl =
|
||||||
|
ApiUrlContext._currentValue.media +
|
||||||
|
'?author=' +
|
||||||
|
this.state.author.id +
|
||||||
|
'&show=shared_with_me' +
|
||||||
|
this.state.filterArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
let title = this.state.title;
|
||||||
|
|
||||||
|
if ('' === newQuery) {
|
||||||
|
title = this.props.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
requestUrl: requestUrl,
|
requestUrl: requestUrl,
|
||||||
|
query: newQuery,
|
||||||
|
title: title,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
onResponseDataLoaded(responseData) {
|
|
||||||
if (responseData && responseData.tags) {
|
|
||||||
const tags = responseData.tags.split(',').map((tag) => tag.trim()).filter((tag) => tag);
|
|
||||||
this.setState({ availableTags: tags });
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pageContent() {
|
onToggleFiltersClick() {
|
||||||
const authorData = ProfilePageStore.get('author-data');
|
this.setState({
|
||||||
|
hiddenFilters: !this.state.hiddenFilters,
|
||||||
|
hiddenTags: true,
|
||||||
|
hiddenSorting: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const isMediaAuthor = authorData && authorData.username === MemberContext._currentValue.username;
|
onToggleTagsClick() {
|
||||||
|
this.setState({
|
||||||
|
hiddenFilters: true,
|
||||||
|
hiddenTags: !this.state.hiddenTags,
|
||||||
|
hiddenSorting: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Check if any filters are active
|
onToggleSortingClick() {
|
||||||
const hasActiveFilters = this.state.filterArgs && (
|
this.setState({
|
||||||
this.state.filterArgs.includes('media_type=') ||
|
hiddenFilters: true,
|
||||||
this.state.filterArgs.includes('upload_date=') ||
|
hiddenTags: true,
|
||||||
this.state.filterArgs.includes('duration=') ||
|
hiddenSorting: !this.state.hiddenSorting,
|
||||||
this.state.filterArgs.includes('publish_state=')
|
});
|
||||||
);
|
}
|
||||||
|
|
||||||
return [
|
onTagSelect(tag) {
|
||||||
this.state.author ? (
|
this.setState({ selectedTag: tag }, () => {
|
||||||
<ProfilePagesHeader
|
this.onFiltersUpdate({
|
||||||
key="ProfilePagesHeader"
|
media_type: this.state.filterArgs.match(/media_type=([^&]+)/)?.[1],
|
||||||
author={this.state.author}
|
upload_date: this.state.filterArgs.match(/upload_date=([^&]+)/)?.[1],
|
||||||
type="shared_with_me"
|
duration: this.state.filterArgs.match(/duration=([^&]+)/)?.[1],
|
||||||
onQueryChange={this.changeRequestQuery}
|
publish_state: this.state.filterArgs.match(/publish_state=([^&]+)/)?.[1],
|
||||||
onToggleFiltersClick={this.onToggleFiltersClick}
|
sort_by: this.state.selectedSort,
|
||||||
onToggleTagsClick={this.onToggleTagsClick}
|
tag: tag,
|
||||||
onToggleSortingClick={this.onToggleSortingClick}
|
});
|
||||||
hasActiveFilters={hasActiveFilters}
|
});
|
||||||
hasActiveTags={this.state.selectedTag !== 'all'}
|
}
|
||||||
hasActiveSort={this.state.selectedSort !== 'date_added_desc'}
|
|
||||||
/>
|
onSortSelect(sortBy) {
|
||||||
) : null,
|
this.setState({ selectedSort: sortBy }, () => {
|
||||||
this.state.author ? (
|
this.onFiltersUpdate({
|
||||||
<ProfilePagesContent key="ProfilePagesContent">
|
media_type: this.state.filterArgs.match(/media_type=([^&]+)/)?.[1],
|
||||||
<MediaListWrapper
|
upload_date: this.state.filterArgs.match(/upload_date=([^&]+)/)?.[1],
|
||||||
title={this.state.title}
|
duration: this.state.filterArgs.match(/duration=([^&]+)/)?.[1],
|
||||||
className="items-list-ver"
|
publish_state: this.state.filterArgs.match(/publish_state=([^&]+)/)?.[1],
|
||||||
>
|
sort_by: sortBy,
|
||||||
<ProfileMediaFilters hidden={this.state.hiddenFilters} tags={this.state.availableTags} onFiltersUpdate={this.onFiltersUpdate} />
|
tag: this.state.selectedTag,
|
||||||
<ProfileMediaTags hidden={this.state.hiddenTags} tags={this.state.availableTags} onTagSelect={this.onTagSelect} />
|
});
|
||||||
<ProfileMediaSorting hidden={this.state.hiddenSorting} onSortSelect={this.onSortSelect} />
|
});
|
||||||
<LazyLoadItemListAsync
|
}
|
||||||
key={this.state.requestUrl}
|
|
||||||
requestUrl={this.state.requestUrl}
|
onFiltersUpdate(updatedArgs) {
|
||||||
hideAuthor={true}
|
const args = {
|
||||||
itemsCountCallback={this.state.requestUrl ? this.getCountFunc : null}
|
media_type: null,
|
||||||
hideViews={!PageStore.get('config-media-item').displayViews}
|
upload_date: null,
|
||||||
hideDate={!PageStore.get('config-media-item').displayPublishDate}
|
duration: null,
|
||||||
canEdit={false}
|
publish_state: null,
|
||||||
onResponseDataLoaded={this.onResponseDataLoaded}
|
sort_by: null,
|
||||||
/>
|
ordering: null,
|
||||||
{isMediaAuthor && 0 === this.state.channelMediaCount && !this.state.query ? (
|
t: null,
|
||||||
<EmptySharedWithMe name={this.state.author.name} />
|
};
|
||||||
) : null}
|
|
||||||
</MediaListWrapper>
|
switch (updatedArgs.media_type) {
|
||||||
</ProfilePagesContent>
|
case 'video':
|
||||||
) : null,
|
case 'audio':
|
||||||
];
|
case 'image':
|
||||||
}
|
case 'pdf':
|
||||||
|
args.media_type = updatedArgs.media_type;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (updatedArgs.upload_date) {
|
||||||
|
case 'today':
|
||||||
|
case 'this_week':
|
||||||
|
case 'this_month':
|
||||||
|
case 'this_year':
|
||||||
|
args.upload_date = updatedArgs.upload_date;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle duration filter
|
||||||
|
if (updatedArgs.duration && updatedArgs.duration !== 'all') {
|
||||||
|
args.duration = updatedArgs.duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle publish state filter
|
||||||
|
if (updatedArgs.publish_state && updatedArgs.publish_state !== 'all') {
|
||||||
|
args.publish_state = updatedArgs.publish_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (updatedArgs.sort_by) {
|
||||||
|
case 'date_added_desc':
|
||||||
|
// Default sorting, no need to add parameters
|
||||||
|
break;
|
||||||
|
case 'date_added_asc':
|
||||||
|
args.ordering = 'asc';
|
||||||
|
break;
|
||||||
|
case 'alphabetically_asc':
|
||||||
|
args.sort_by = 'title_asc';
|
||||||
|
break;
|
||||||
|
case 'alphabetically_desc':
|
||||||
|
args.sort_by = 'title_desc';
|
||||||
|
break;
|
||||||
|
case 'plays_least':
|
||||||
|
args.sort_by = 'views_asc';
|
||||||
|
break;
|
||||||
|
case 'plays_most':
|
||||||
|
args.sort_by = 'views_desc';
|
||||||
|
break;
|
||||||
|
case 'likes_least':
|
||||||
|
args.sort_by = 'likes_asc';
|
||||||
|
break;
|
||||||
|
case 'likes_most':
|
||||||
|
args.sort_by = 'likes_desc';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updatedArgs.tag && updatedArgs.tag !== 'all') {
|
||||||
|
args.t = updatedArgs.tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newArgs = [];
|
||||||
|
|
||||||
|
for (let arg in args) {
|
||||||
|
if (null !== args[arg]) {
|
||||||
|
newArgs.push(arg + '=' + args[arg]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
filterArgs: newArgs.length ? '&' + newArgs.join('&') : '',
|
||||||
|
},
|
||||||
|
function () {
|
||||||
|
if (!this.state.author) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let requestUrl;
|
||||||
|
|
||||||
|
if (this.state.query) {
|
||||||
|
requestUrl =
|
||||||
|
ApiUrlContext._currentValue.media +
|
||||||
|
'?author=' +
|
||||||
|
this.state.author.id +
|
||||||
|
'&show=shared_with_me&q=' +
|
||||||
|
encodeURIComponent(this.state.query) +
|
||||||
|
this.state.filterArgs;
|
||||||
|
} else {
|
||||||
|
requestUrl =
|
||||||
|
ApiUrlContext._currentValue.media +
|
||||||
|
'?author=' +
|
||||||
|
this.state.author.id +
|
||||||
|
'&show=shared_with_me' +
|
||||||
|
this.state.filterArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
requestUrl: requestUrl,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onResponseDataLoaded(responseData) {
|
||||||
|
if (responseData && responseData.tags) {
|
||||||
|
const tags = responseData.tags
|
||||||
|
.split(',')
|
||||||
|
.map((tag) => tag.trim())
|
||||||
|
.filter((tag) => tag);
|
||||||
|
this.setState({ availableTags: tags });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pageContent() {
|
||||||
|
const authorData = ProfilePageStore.get('author-data');
|
||||||
|
|
||||||
|
const isMediaAuthor = authorData && authorData.username === MemberContext._currentValue.username;
|
||||||
|
|
||||||
|
// Check if any filters are active
|
||||||
|
const hasActiveFilters =
|
||||||
|
this.state.filterArgs &&
|
||||||
|
(this.state.filterArgs.includes('media_type=') ||
|
||||||
|
this.state.filterArgs.includes('upload_date=') ||
|
||||||
|
this.state.filterArgs.includes('duration=') ||
|
||||||
|
this.state.filterArgs.includes('publish_state='));
|
||||||
|
|
||||||
|
return [
|
||||||
|
this.state.author ? (
|
||||||
|
<ProfilePagesHeader
|
||||||
|
key="ProfilePagesHeader"
|
||||||
|
author={this.state.author}
|
||||||
|
type="shared_with_me"
|
||||||
|
onQueryChange={this.changeRequestQuery}
|
||||||
|
onToggleFiltersClick={this.onToggleFiltersClick}
|
||||||
|
onToggleTagsClick={this.onToggleTagsClick}
|
||||||
|
onToggleSortingClick={this.onToggleSortingClick}
|
||||||
|
hasActiveFilters={hasActiveFilters}
|
||||||
|
hasActiveTags={this.state.selectedTag !== 'all'}
|
||||||
|
hasActiveSort={this.state.selectedSort !== 'date_added_desc'}
|
||||||
|
hideChannelBanner={inEmbeddedApp()}
|
||||||
|
/>
|
||||||
|
) : null,
|
||||||
|
this.state.author ? (
|
||||||
|
<ProfilePagesContent key="ProfilePagesContent">
|
||||||
|
<MediaListWrapper title={this.state.title} className="items-list-ver">
|
||||||
|
<ProfileMediaFilters
|
||||||
|
hidden={this.state.hiddenFilters}
|
||||||
|
tags={this.state.availableTags}
|
||||||
|
onFiltersUpdate={this.onFiltersUpdate}
|
||||||
|
/>
|
||||||
|
<ProfileMediaTags
|
||||||
|
hidden={this.state.hiddenTags}
|
||||||
|
tags={this.state.availableTags}
|
||||||
|
onTagSelect={this.onTagSelect}
|
||||||
|
/>
|
||||||
|
<ProfileMediaSorting hidden={this.state.hiddenSorting} onSortSelect={this.onSortSelect} />
|
||||||
|
<LazyLoadItemListAsync
|
||||||
|
key={this.state.requestUrl}
|
||||||
|
requestUrl={this.state.requestUrl}
|
||||||
|
hideAuthor={true}
|
||||||
|
itemsCountCallback={this.state.requestUrl ? this.getCountFunc : null}
|
||||||
|
hideViews={!PageStore.get('config-media-item').displayViews}
|
||||||
|
hideDate={!PageStore.get('config-media-item').displayPublishDate}
|
||||||
|
canEdit={false}
|
||||||
|
onResponseDataLoaded={this.onResponseDataLoaded}
|
||||||
|
/>
|
||||||
|
{isMediaAuthor && 0 === this.state.channelMediaCount && !this.state.query ? (
|
||||||
|
<EmptySharedWithMe name={this.state.author.name} />
|
||||||
|
) : null}
|
||||||
|
</MediaListWrapper>
|
||||||
|
</ProfilePagesContent>
|
||||||
|
) : null,
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfileSharedWithMePage.propTypes = {
|
ProfileSharedWithMePage.propTypes = {
|
||||||
title: PropTypes.string.isRequired,
|
title: PropTypes.string.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
ProfileSharedWithMePage.defaultProps = {
|
ProfileSharedWithMePage.defaultProps = {
|
||||||
title: 'Shared with me',
|
title: 'Shared with me',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { PageStore, MediaPageStore } from '../utils/stores/';
|
import { PageStore, MediaPageStore } from '../utils/stores/';
|
||||||
import { MediaPageActions } from '../utils/actions/';
|
import { MediaPageActions } from '../utils/actions/';
|
||||||
|
import { inEmbeddedApp } from '../utils/helpers/';
|
||||||
import ViewerError from '../components/media-page/ViewerError';
|
import ViewerError from '../components/media-page/ViewerError';
|
||||||
import ViewerInfo from '../components/media-page/ViewerInfo';
|
import ViewerInfo from '../components/media-page/ViewerInfo';
|
||||||
import ViewerSidebar from '../components/media-page/ViewerSidebar';
|
import ViewerSidebar from '../components/media-page/ViewerSidebar';
|
||||||
@@ -10,102 +11,102 @@ import '../components/media-page/MediaPage.scss';
|
|||||||
const wideLayoutBreakpoint = 1216;
|
const wideLayoutBreakpoint = 1216;
|
||||||
|
|
||||||
export class _MediaPage extends Page {
|
export class _MediaPage extends Page {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props, 'media');
|
super(props, 'media');
|
||||||
|
|
||||||
const isWideLayout = wideLayoutBreakpoint <= window.innerWidth;
|
const isWideLayout = wideLayoutBreakpoint <= window.innerWidth;
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
mediaLoaded: false,
|
mediaLoaded: false,
|
||||||
mediaLoadFailed: false,
|
mediaLoadFailed: false,
|
||||||
wideLayout: isWideLayout,
|
wideLayout: isWideLayout,
|
||||||
infoAndSidebarViewType: !isWideLayout ? 0 : 1,
|
infoAndSidebarViewType: !isWideLayout ? 0 : 1,
|
||||||
viewerClassname: 'cf viewer-section viewer-wide',
|
viewerClassname: 'cf viewer-section viewer-wide',
|
||||||
viewerNestedClassname: 'viewer-section-nested',
|
viewerNestedClassname: 'viewer-section-nested',
|
||||||
pagePlaylistLoaded: false,
|
pagePlaylistLoaded: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onWindowResize = this.onWindowResize.bind(this);
|
this.onWindowResize = this.onWindowResize.bind(this);
|
||||||
this.onMediaLoad = this.onMediaLoad.bind(this);
|
this.onMediaLoad = this.onMediaLoad.bind(this);
|
||||||
this.onMediaLoadError = this.onMediaLoadError.bind(this);
|
this.onMediaLoadError = this.onMediaLoadError.bind(this);
|
||||||
this.onPagePlaylistLoad = this.onPagePlaylistLoad.bind(this);
|
this.onPagePlaylistLoad = this.onPagePlaylistLoad.bind(this);
|
||||||
|
|
||||||
MediaPageStore.on('loaded_media_data', this.onMediaLoad);
|
MediaPageStore.on('loaded_media_data', this.onMediaLoad);
|
||||||
MediaPageStore.on('loaded_media_error', this.onMediaLoadError);
|
MediaPageStore.on('loaded_media_error', this.onMediaLoadError);
|
||||||
MediaPageStore.on('loaded_page_playlist_data', this.onPagePlaylistLoad);
|
MediaPageStore.on('loaded_page_playlist_data', this.onPagePlaylistLoad);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
MediaPageActions.loadMediaData();
|
MediaPageActions.loadMediaData();
|
||||||
// FIXME: Is not neccessary to check on every window dimension for changes...
|
// FIXME: Is not neccessary to check on every window dimension for changes...
|
||||||
PageStore.on('window_resize', this.onWindowResize);
|
PageStore.on('window_resize', this.onWindowResize);
|
||||||
}
|
}
|
||||||
|
|
||||||
onPagePlaylistLoad() {
|
onPagePlaylistLoad() {
|
||||||
this.setState({
|
this.setState({
|
||||||
pagePlaylistLoaded: true,
|
pagePlaylistLoaded: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onWindowResize() {
|
onWindowResize() {
|
||||||
const isWideLayout = wideLayoutBreakpoint <= window.innerWidth;
|
const isWideLayout = wideLayoutBreakpoint <= window.innerWidth;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
wideLayout: isWideLayout,
|
wideLayout: isWideLayout,
|
||||||
infoAndSidebarViewType: !isWideLayout || (MediaPageStore.isVideo() && this.state.theaterMode) ? 0 : 1,
|
infoAndSidebarViewType: !isWideLayout || (MediaPageStore.isVideo() && this.state.theaterMode) ? 0 : 1,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onMediaLoad() {
|
onMediaLoad() {
|
||||||
this.setState({ mediaLoaded: true });
|
this.setState({ mediaLoaded: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
onMediaLoadError() {
|
onMediaLoadError() {
|
||||||
this.setState({ mediaLoadFailed: true });
|
this.setState({ mediaLoadFailed: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
viewerContainerContent() {
|
viewerContainerContent() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaType() {
|
mediaType() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pageContent() {
|
pageContent() {
|
||||||
return this.state.mediaLoadFailed ? (
|
return this.state.mediaLoadFailed ? (
|
||||||
<div className={this.state.viewerClassname}>
|
<div className={this.state.viewerClassname}>
|
||||||
<ViewerError />
|
<ViewerError />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className={this.state.viewerClassname}>
|
<div className={this.state.viewerClassname}>
|
||||||
<div className="viewer-container" key="viewer-container">
|
<div className="viewer-container" key="viewer-container">
|
||||||
{this.state.mediaLoaded ? this.viewerContainerContent() : null}
|
{this.state.mediaLoaded ? this.viewerContainerContent() : null}
|
||||||
</div>
|
</div>
|
||||||
<div key="viewer-section-nested" className={this.state.viewerNestedClassname}>
|
<div key="viewer-section-nested" className={this.state.viewerNestedClassname}>
|
||||||
{!this.state.infoAndSidebarViewType
|
{!this.state.infoAndSidebarViewType
|
||||||
? [
|
? [
|
||||||
<ViewerInfo key="viewer-info" />,
|
<ViewerInfo key="viewer-info" />,
|
||||||
this.state.pagePlaylistLoaded ? (
|
!inEmbeddedApp() && this.state.pagePlaylistLoaded ? (
|
||||||
<ViewerSidebar
|
<ViewerSidebar
|
||||||
key="viewer-sidebar"
|
key="viewer-sidebar"
|
||||||
mediaId={MediaPageStore.get('media-id')}
|
mediaId={MediaPageStore.get('media-id')}
|
||||||
playlistData={MediaPageStore.get('playlist-data')}
|
playlistData={MediaPageStore.get('playlist-data')}
|
||||||
/>
|
/>
|
||||||
) : null,
|
) : null,
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
this.state.pagePlaylistLoaded ? (
|
!inEmbeddedApp() && this.state.pagePlaylistLoaded ? (
|
||||||
<ViewerSidebar
|
<ViewerSidebar
|
||||||
key="viewer-sidebar"
|
key="viewer-sidebar"
|
||||||
mediaId={MediaPageStore.get('media-id')}
|
mediaId={MediaPageStore.get('media-id')}
|
||||||
playlistData={MediaPageStore.get('playlist-data')}
|
playlistData={MediaPageStore.get('playlist-data')}
|
||||||
/>
|
/>
|
||||||
) : null,
|
) : null,
|
||||||
<ViewerInfo key="viewer-info" />,
|
<ViewerInfo key="viewer-info" />,
|
||||||
]}
|
]}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React from 'react';
|
|||||||
// FIXME: 'VideoViewerStore' is used only in case of video media, but is included in every media page code.
|
// FIXME: 'VideoViewerStore' is used only in case of video media, but is included in every media page code.
|
||||||
import { PageStore, MediaPageStore, VideoViewerStore } from '../utils/stores/';
|
import { PageStore, MediaPageStore, VideoViewerStore } from '../utils/stores/';
|
||||||
import { MediaPageActions } from '../utils/actions/';
|
import { MediaPageActions } from '../utils/actions/';
|
||||||
|
import { inEmbeddedApp } from '../utils/helpers/';
|
||||||
import ViewerInfoVideo from '../components/media-page/ViewerInfoVideo';
|
import ViewerInfoVideo from '../components/media-page/ViewerInfoVideo';
|
||||||
import ViewerError from '../components/media-page/ViewerError';
|
import ViewerError from '../components/media-page/ViewerError';
|
||||||
import ViewerSidebar from '../components/media-page/ViewerSidebar';
|
import ViewerSidebar from '../components/media-page/ViewerSidebar';
|
||||||
@@ -11,118 +12,119 @@ import _MediaPage from './_MediaPage';
|
|||||||
const wideLayoutBreakpoint = 1216;
|
const wideLayoutBreakpoint = 1216;
|
||||||
|
|
||||||
export class _VideoMediaPage extends Page {
|
export class _VideoMediaPage extends Page {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props, 'media');
|
super(props, 'media');
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
wideLayout: wideLayoutBreakpoint <= window.innerWidth,
|
wideLayout: wideLayoutBreakpoint <= window.innerWidth,
|
||||||
mediaLoaded: false,
|
mediaLoaded: false,
|
||||||
mediaLoadFailed: false,
|
mediaLoadFailed: false,
|
||||||
isVideoMedia: false,
|
isVideoMedia: false,
|
||||||
theaterMode: false, // FIXME: Used only in case of video media, but is included in every media page code.
|
theaterMode: false, // FIXME: Used only in case of video media, but is included in every media page code.
|
||||||
pagePlaylistLoaded: false,
|
pagePlaylistLoaded: false,
|
||||||
pagePlaylistData: MediaPageStore.get('playlist-data'),
|
pagePlaylistData: MediaPageStore.get('playlist-data'),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onWindowResize = this.onWindowResize.bind(this);
|
this.onWindowResize = this.onWindowResize.bind(this);
|
||||||
this.onMediaLoad = this.onMediaLoad.bind(this);
|
this.onMediaLoad = this.onMediaLoad.bind(this);
|
||||||
this.onMediaLoadError = this.onMediaLoadError.bind(this);
|
this.onMediaLoadError = this.onMediaLoadError.bind(this);
|
||||||
this.onPagePlaylistLoad = this.onPagePlaylistLoad.bind(this);
|
this.onPagePlaylistLoad = this.onPagePlaylistLoad.bind(this);
|
||||||
|
|
||||||
MediaPageStore.on('loaded_media_data', this.onMediaLoad);
|
MediaPageStore.on('loaded_media_data', this.onMediaLoad);
|
||||||
MediaPageStore.on('loaded_media_error', this.onMediaLoadError);
|
MediaPageStore.on('loaded_media_error', this.onMediaLoadError);
|
||||||
MediaPageStore.on('loaded_page_playlist_data', this.onPagePlaylistLoad);
|
MediaPageStore.on('loaded_page_playlist_data', this.onPagePlaylistLoad);
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
MediaPageActions.loadMediaData();
|
|
||||||
// FIXME: Is not neccessary to check on every window dimension for changes...
|
|
||||||
PageStore.on('window_resize', this.onWindowResize);
|
|
||||||
}
|
|
||||||
|
|
||||||
onWindowResize() {
|
|
||||||
this.setState({
|
|
||||||
wideLayout: wideLayoutBreakpoint <= window.innerWidth,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onPagePlaylistLoad() {
|
|
||||||
this.setState({
|
|
||||||
pagePlaylistLoaded: true,
|
|
||||||
pagePlaylistData: MediaPageStore.get('playlist-data'),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onMediaLoad() {
|
|
||||||
const isVideoMedia = 'video' === MediaPageStore.get('media-type') || 'audio' === MediaPageStore.get('media-type');
|
|
||||||
|
|
||||||
if (isVideoMedia) {
|
|
||||||
this.onViewerModeChange = this.onViewerModeChange.bind(this);
|
|
||||||
|
|
||||||
VideoViewerStore.on('changed_viewer_mode', this.onViewerModeChange);
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
mediaLoaded: true,
|
|
||||||
isVideoMedia: isVideoMedia,
|
|
||||||
theaterMode: VideoViewerStore.get('in-theater-mode'),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
mediaLoaded: true,
|
|
||||||
isVideoMedia: isVideoMedia,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
onViewerModeChange() {
|
componentDidMount() {
|
||||||
this.setState({ theaterMode: VideoViewerStore.get('in-theater-mode') });
|
MediaPageActions.loadMediaData();
|
||||||
}
|
// FIXME: Is not neccessary to check on every window dimension for changes...
|
||||||
|
PageStore.on('window_resize', this.onWindowResize);
|
||||||
|
}
|
||||||
|
|
||||||
onMediaLoadError(a) {
|
onWindowResize() {
|
||||||
this.setState({ mediaLoadFailed: true });
|
this.setState({
|
||||||
}
|
wideLayout: wideLayoutBreakpoint <= window.innerWidth,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pageContent() {
|
onPagePlaylistLoad() {
|
||||||
const viewerClassname = 'cf viewer-section' + (this.state.theaterMode ? ' theater-mode' : ' viewer-wide');
|
this.setState({
|
||||||
const viewerNestedClassname = 'viewer-section-nested' + (this.state.theaterMode ? ' viewer-section' : '');
|
pagePlaylistLoaded: true,
|
||||||
|
pagePlaylistData: MediaPageStore.get('playlist-data'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return this.state.mediaLoadFailed ? (
|
onMediaLoad() {
|
||||||
<div className={viewerClassname}>
|
const isVideoMedia =
|
||||||
<ViewerError />
|
'video' === MediaPageStore.get('media-type') || 'audio' === MediaPageStore.get('media-type');
|
||||||
</div>
|
|
||||||
) : (
|
if (isVideoMedia) {
|
||||||
<div className={viewerClassname}>
|
this.onViewerModeChange = this.onViewerModeChange.bind(this);
|
||||||
{[
|
|
||||||
<div className="viewer-container" key="viewer-container">
|
VideoViewerStore.on('changed_viewer_mode', this.onViewerModeChange);
|
||||||
{this.state.mediaLoaded && this.state.pagePlaylistLoaded
|
|
||||||
? this.viewerContainerContent(MediaPageStore.get('media-data'))
|
this.setState({
|
||||||
: null}
|
mediaLoaded: true,
|
||||||
</div>,
|
isVideoMedia: isVideoMedia,
|
||||||
<div key="viewer-section-nested" className={viewerNestedClassname}>
|
theaterMode: VideoViewerStore.get('in-theater-mode'),
|
||||||
{!this.state.wideLayout || (this.state.isVideoMedia && this.state.theaterMode)
|
});
|
||||||
? [
|
} else {
|
||||||
<ViewerInfoVideo key="viewer-info" />,
|
this.setState({
|
||||||
this.state.pagePlaylistLoaded ? (
|
mediaLoaded: true,
|
||||||
<ViewerSidebar
|
isVideoMedia: isVideoMedia,
|
||||||
key="viewer-sidebar"
|
});
|
||||||
mediaId={MediaPageStore.get('media-id')}
|
}
|
||||||
playlistData={MediaPageStore.get('playlist-data')}
|
}
|
||||||
/>
|
|
||||||
) : null,
|
onViewerModeChange() {
|
||||||
]
|
this.setState({ theaterMode: VideoViewerStore.get('in-theater-mode') });
|
||||||
: [
|
}
|
||||||
this.state.pagePlaylistLoaded ? (
|
|
||||||
<ViewerSidebar
|
onMediaLoadError(a) {
|
||||||
key="viewer-sidebar"
|
this.setState({ mediaLoadFailed: true });
|
||||||
mediaId={MediaPageStore.get('media-id')}
|
}
|
||||||
playlistData={MediaPageStore.get('playlist-data')}
|
|
||||||
/>
|
pageContent() {
|
||||||
) : null,
|
const viewerClassname = 'cf viewer-section' + (this.state.theaterMode ? ' theater-mode' : ' viewer-wide');
|
||||||
<ViewerInfoVideo key="viewer-info" />,
|
const viewerNestedClassname = 'viewer-section-nested' + (this.state.theaterMode ? ' viewer-section' : '');
|
||||||
|
|
||||||
|
return this.state.mediaLoadFailed ? (
|
||||||
|
<div className={viewerClassname}>
|
||||||
|
<ViewerError />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className={viewerClassname}>
|
||||||
|
{[
|
||||||
|
<div className="viewer-container" key="viewer-container">
|
||||||
|
{this.state.mediaLoaded && this.state.pagePlaylistLoaded
|
||||||
|
? this.viewerContainerContent(MediaPageStore.get('media-data'))
|
||||||
|
: null}
|
||||||
|
</div>,
|
||||||
|
<div key="viewer-section-nested" className={viewerNestedClassname}>
|
||||||
|
{!this.state.wideLayout || (this.state.isVideoMedia && this.state.theaterMode)
|
||||||
|
? [
|
||||||
|
<ViewerInfoVideo key="viewer-info" />,
|
||||||
|
!inEmbeddedApp() && this.state.pagePlaylistLoaded ? (
|
||||||
|
<ViewerSidebar
|
||||||
|
key="viewer-sidebar"
|
||||||
|
mediaId={MediaPageStore.get('media-id')}
|
||||||
|
playlistData={MediaPageStore.get('playlist-data')}
|
||||||
|
/>
|
||||||
|
) : null,
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
!inEmbeddedApp() && this.state.pagePlaylistLoaded ? (
|
||||||
|
<ViewerSidebar
|
||||||
|
key="viewer-sidebar"
|
||||||
|
mediaId={MediaPageStore.get('media-id')}
|
||||||
|
playlistData={MediaPageStore.get('playlist-data')}
|
||||||
|
/>
|
||||||
|
) : null,
|
||||||
|
<ViewerInfoVideo key="viewer-info" />,
|
||||||
|
]}
|
||||||
|
</div>,
|
||||||
]}
|
]}
|
||||||
</div>,
|
</div>
|
||||||
]}
|
);
|
||||||
</div>
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,101 +1,103 @@
|
|||||||
import React, { createContext, useContext, useEffect, useState } from 'react';
|
import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
||||||
import { BrowserCache } from '../classes/';
|
import { BrowserCache } from '../classes/';
|
||||||
import { PageStore } from '../stores/';
|
import { PageStore } from '../stores/';
|
||||||
import { addClassname, removeClassname } from '../helpers/';
|
import { addClassname, removeClassname, inEmbeddedApp } from '../helpers/';
|
||||||
import SiteContext from './SiteContext';
|
import SiteContext from './SiteContext';
|
||||||
|
|
||||||
let slidingSidebarTimeout;
|
let slidingSidebarTimeout;
|
||||||
|
|
||||||
function onSidebarVisibilityChange(visibleSidebar) {
|
function onSidebarVisibilityChange(visibleSidebar) {
|
||||||
clearTimeout(slidingSidebarTimeout);
|
clearTimeout(slidingSidebarTimeout);
|
||||||
|
|
||||||
addClassname(document.body, 'sliding-sidebar');
|
addClassname(document.body, 'sliding-sidebar');
|
||||||
|
|
||||||
slidingSidebarTimeout = setTimeout(function () {
|
|
||||||
if ('media' === PageStore.get('current-page')) {
|
|
||||||
if (visibleSidebar) {
|
|
||||||
addClassname(document.body, 'overflow-hidden');
|
|
||||||
} else {
|
|
||||||
removeClassname(document.body, 'overflow-hidden');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!visibleSidebar || 767 < window.innerWidth) {
|
|
||||||
removeClassname(document.body, 'overflow-hidden');
|
|
||||||
} else {
|
|
||||||
addClassname(document.body, 'overflow-hidden');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (visibleSidebar) {
|
|
||||||
addClassname(document.body, 'visible-sidebar');
|
|
||||||
} else {
|
|
||||||
removeClassname(document.body, 'visible-sidebar');
|
|
||||||
}
|
|
||||||
|
|
||||||
slidingSidebarTimeout = setTimeout(function () {
|
slidingSidebarTimeout = setTimeout(function () {
|
||||||
slidingSidebarTimeout = null;
|
if ('media' === PageStore.get('current-page')) {
|
||||||
removeClassname(document.body, 'sliding-sidebar');
|
if (visibleSidebar) {
|
||||||
}, 220);
|
addClassname(document.body, 'overflow-hidden');
|
||||||
}, 20);
|
} else {
|
||||||
|
removeClassname(document.body, 'overflow-hidden');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!visibleSidebar || 767 < window.innerWidth) {
|
||||||
|
removeClassname(document.body, 'overflow-hidden');
|
||||||
|
} else {
|
||||||
|
addClassname(document.body, 'overflow-hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visibleSidebar) {
|
||||||
|
addClassname(document.body, 'visible-sidebar');
|
||||||
|
} else {
|
||||||
|
removeClassname(document.body, 'visible-sidebar');
|
||||||
|
}
|
||||||
|
|
||||||
|
slidingSidebarTimeout = setTimeout(function () {
|
||||||
|
slidingSidebarTimeout = null;
|
||||||
|
removeClassname(document.body, 'sliding-sidebar');
|
||||||
|
}, 220);
|
||||||
|
}, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LayoutContext = createContext();
|
export const LayoutContext = createContext();
|
||||||
|
|
||||||
export const LayoutProvider = ({ children }) => {
|
export const LayoutProvider = ({ children }) => {
|
||||||
const site = useContext(SiteContext);
|
const site = useContext(SiteContext);
|
||||||
const cache = new BrowserCache('MediaCMS[' + site.id + '][layout]', 86400);
|
const cache = new BrowserCache('MediaCMS[' + site.id + '][layout]', 86400);
|
||||||
|
|
||||||
const enabledSidebar = !!(document.getElementById('app-sidebar') || document.querySelector('.page-sidebar'));
|
const isMediaPage = useMemo(() => PageStore.get('current-page') === 'media', []);
|
||||||
|
const isEmbeddedApp = useMemo(() => inEmbeddedApp(), []);
|
||||||
|
|
||||||
const [visibleSidebar, setVisibleSidebar] = useState(cache.get('visible-sidebar'));
|
const enabledSidebar = Boolean(document.getElementById('app-sidebar') || document.querySelector('.page-sidebar'));
|
||||||
const [visibleMobileSearch, setVisibleMobileSearch] = useState(false);
|
|
||||||
|
|
||||||
const toggleMobileSearch = () => {
|
const [visibleSidebar, setVisibleSidebar] = useState(cache.get('visible-sidebar'));
|
||||||
setVisibleMobileSearch(!visibleMobileSearch);
|
const [visibleMobileSearch, setVisibleMobileSearch] = useState(false);
|
||||||
};
|
|
||||||
|
|
||||||
const toggleSidebar = () => {
|
const toggleMobileSearch = () => {
|
||||||
const newval = !visibleSidebar;
|
setVisibleMobileSearch(!visibleMobileSearch);
|
||||||
onSidebarVisibilityChange(newval);
|
};
|
||||||
setVisibleSidebar(newval);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
const toggleSidebar = () => {
|
||||||
if (visibleSidebar) {
|
const newval = !visibleSidebar;
|
||||||
addClassname(document.body, 'visible-sidebar');
|
onSidebarVisibilityChange(newval);
|
||||||
} else {
|
setVisibleSidebar(newval);
|
||||||
removeClassname(document.body, 'visible-sidebar');
|
};
|
||||||
}
|
|
||||||
if ('media' !== PageStore.get('current-page') && 1023 < window.innerWidth) {
|
|
||||||
cache.set('visible-sidebar', visibleSidebar);
|
|
||||||
}
|
|
||||||
}, [visibleSidebar]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
PageStore.once('page_init', () => {
|
if (!isEmbeddedApp && visibleSidebar) {
|
||||||
if ('media' === PageStore.get('current-page')) {
|
addClassname(document.body, 'visible-sidebar');
|
||||||
setVisibleSidebar(false);
|
} else {
|
||||||
removeClassname(document.body, 'visible-sidebar');
|
removeClassname(document.body, 'visible-sidebar');
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
setVisibleSidebar(
|
if (!isEmbeddedApp && !isMediaPage && 1023 < window.innerWidth) {
|
||||||
'media' !== PageStore.get('current-page') &&
|
cache.set('visible-sidebar', visibleSidebar);
|
||||||
1023 < window.innerWidth &&
|
}
|
||||||
(null === visibleSidebar || visibleSidebar)
|
}, [isEmbeddedApp, isMediaPage, visibleSidebar]);
|
||||||
);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const value = {
|
useEffect(() => {
|
||||||
enabledSidebar,
|
PageStore.once('page_init', () => {
|
||||||
visibleSidebar,
|
if (isEmbeddedApp || isMediaPage) {
|
||||||
setVisibleSidebar,
|
setVisibleSidebar(false);
|
||||||
visibleMobileSearch,
|
removeClassname(document.body, 'visible-sidebar');
|
||||||
toggleMobileSearch,
|
}
|
||||||
toggleSidebar,
|
});
|
||||||
};
|
|
||||||
|
|
||||||
return <LayoutContext.Provider value={value}>{children}</LayoutContext.Provider>;
|
setVisibleSidebar(
|
||||||
|
!isEmbeddedApp && !isMediaPage && 1023 < window.innerWidth && (null === visibleSidebar || visibleSidebar)
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const value = {
|
||||||
|
enabledSidebar,
|
||||||
|
visibleSidebar,
|
||||||
|
setVisibleSidebar,
|
||||||
|
visibleMobileSearch,
|
||||||
|
toggleMobileSearch,
|
||||||
|
toggleSidebar,
|
||||||
|
};
|
||||||
|
|
||||||
|
return <LayoutContext.Provider value={value}>{children}</LayoutContext.Provider>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const LayoutConsumer = LayoutContext.Consumer;
|
export const LayoutConsumer = LayoutContext.Consumer;
|
||||||
|
|||||||
4
frontend/src/static/js/utils/helpers/embeddedApp.ts
Normal file
4
frontend/src/static/js/utils/helpers/embeddedApp.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export function inEmbeddedApp() {
|
||||||
|
const url = new URL(globalThis.location.href);
|
||||||
|
return url.searchParams.get('mode') === 'embed_mode';
|
||||||
|
}
|
||||||
@@ -14,3 +14,4 @@ export * from './quickSort';
|
|||||||
export * from './requests';
|
export * from './requests';
|
||||||
export { translateString } from './translate';
|
export { translateString } from './translate';
|
||||||
export { replaceString } from './replacementStrings';
|
export { replaceString } from './replacementStrings';
|
||||||
|
export * from './embeddedApp';
|
||||||
|
|||||||
@@ -3,64 +3,82 @@ import ReactDOM from 'react-dom';
|
|||||||
import { ThemeProvider } from './contexts/ThemeContext';
|
import { ThemeProvider } from './contexts/ThemeContext';
|
||||||
import { LayoutProvider } from './contexts/LayoutContext';
|
import { LayoutProvider } from './contexts/LayoutContext';
|
||||||
import { UserProvider } from './contexts/UserContext';
|
import { UserProvider } from './contexts/UserContext';
|
||||||
|
import { inEmbeddedApp } from './helpers';
|
||||||
|
|
||||||
const AppProviders = ({ children }) => (
|
const AppProviders = ({ children }) => (
|
||||||
<LayoutProvider>
|
<LayoutProvider>
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
<UserProvider>{children}</UserProvider>
|
<UserProvider>{children}</UserProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</LayoutProvider>
|
</LayoutProvider>
|
||||||
);
|
);
|
||||||
|
|
||||||
import { PageHeader, PageSidebar } from '../components/page-layout';
|
import { PageHeader, PageSidebar } from '../components/page-layout';
|
||||||
|
|
||||||
export function renderPage(idSelector, PageComponent) {
|
export function renderPage(idSelector, PageComponent) {
|
||||||
const appHeader = document.getElementById('app-header');
|
const appContent = idSelector ? document.getElementById(idSelector) : undefined;
|
||||||
const appSidebar = document.getElementById('app-sidebar');
|
|
||||||
const appContent = idSelector ? document.getElementById(idSelector) : undefined;
|
|
||||||
|
|
||||||
if (appContent && PageComponent) {
|
if (inEmbeddedApp() && appContent) {
|
||||||
ReactDOM.render(
|
globalThis.document.body.classList.add('embedded-app');
|
||||||
<AppProviders>
|
globalThis.document.body.classList.remove('visible-sidebar');
|
||||||
{appHeader ? ReactDOM.createPortal(<PageHeader />, appHeader) : null}
|
|
||||||
{appSidebar ? ReactDOM.createPortal(<PageSidebar />, appSidebar) : null}
|
if (PageComponent) {
|
||||||
<PageComponent />
|
ReactDOM.render(
|
||||||
</AppProviders>,
|
<AppProviders>
|
||||||
appContent
|
<PageComponent />
|
||||||
);
|
</AppProviders>,
|
||||||
} else if (appHeader && appSidebar) {
|
appContent
|
||||||
ReactDOM.render(
|
);
|
||||||
<AppProviders>
|
}
|
||||||
{ReactDOM.createPortal(<PageHeader />, appHeader)}
|
|
||||||
<PageSidebar />
|
return;
|
||||||
</AppProviders>,
|
}
|
||||||
appSidebar
|
|
||||||
);
|
const appHeader = document.getElementById('app-header');
|
||||||
} else if (appHeader) {
|
const appSidebar = document.getElementById('app-sidebar');
|
||||||
ReactDOM.render(
|
|
||||||
<LayoutProvider>
|
if (appContent && PageComponent) {
|
||||||
<ThemeProvider>
|
ReactDOM.render(
|
||||||
<UserProvider>
|
<AppProviders>
|
||||||
<PageHeader />
|
{appHeader ? ReactDOM.createPortal(<PageHeader />, appHeader) : null}
|
||||||
</UserProvider>
|
{appSidebar ? ReactDOM.createPortal(<PageSidebar />, appSidebar) : null}
|
||||||
</ThemeProvider>
|
<PageComponent />
|
||||||
</LayoutProvider>,
|
</AppProviders>,
|
||||||
appSidebar
|
appContent
|
||||||
);
|
);
|
||||||
} else if (appSidebar) {
|
} else if (appHeader && appSidebar) {
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<AppProviders>
|
<AppProviders>
|
||||||
<PageSidebar />
|
{ReactDOM.createPortal(<PageHeader />, appHeader)}
|
||||||
</AppProviders>,
|
<PageSidebar />
|
||||||
appSidebar
|
</AppProviders>,
|
||||||
);
|
appSidebar
|
||||||
}
|
);
|
||||||
|
} else if (appHeader) {
|
||||||
|
ReactDOM.render(
|
||||||
|
<LayoutProvider>
|
||||||
|
<ThemeProvider>
|
||||||
|
<UserProvider>
|
||||||
|
<PageHeader />
|
||||||
|
</UserProvider>
|
||||||
|
</ThemeProvider>
|
||||||
|
</LayoutProvider>,
|
||||||
|
appSidebar
|
||||||
|
);
|
||||||
|
} else if (appSidebar) {
|
||||||
|
ReactDOM.render(
|
||||||
|
<AppProviders>
|
||||||
|
<PageSidebar />
|
||||||
|
</AppProviders>,
|
||||||
|
appSidebar
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderEmbedPage(idSelector, PageComponent) {
|
export function renderEmbedPage(idSelector, PageComponent) {
|
||||||
const appContent = idSelector ? document.getElementById(idSelector) : undefined;
|
const appContent = idSelector ? document.getElementById(idSelector) : undefined;
|
||||||
|
|
||||||
if (appContent && PageComponent) {
|
if (appContent && PageComponent) {
|
||||||
ReactDOM.render(<PageComponent />, appContent);
|
ReactDOM.render(<PageComponent />, appContent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user