This commit is contained in:
Markos Gogoulos
2026-02-07 12:51:40 +02:00
parent 9c7cc293ce
commit 6075514ffa
7 changed files with 138 additions and 22 deletions

View File

@@ -1 +1 @@
VERSION = "7.6" VERSION = "7.7"

View File

@@ -374,6 +374,19 @@ class NavMenuInlineTabs extends React.PureComponent {
render() { render() {
const isSelectMediaMode = inSelectMediaEmbedMode(); const isSelectMediaMode = inSelectMediaEmbedMode();
// Append action=select_media to links when in select mode
const mediaLink = isSelectMediaMode
? `${LinksContext._currentValue.profile.media}${LinksContext._currentValue.profile.media.includes('?') ? '&' : '?'}action=select_media`
: LinksContext._currentValue.profile.media;
const sharedByMeLink = isSelectMediaMode
? `${LinksContext._currentValue.profile.shared_by_me}${LinksContext._currentValue.profile.shared_by_me.includes('?') ? '&' : '?'}action=select_media`
: LinksContext._currentValue.profile.shared_by_me;
const sharedWithMeLink = isSelectMediaMode
? `${LinksContext._currentValue.profile.shared_with_me}${LinksContext._currentValue.profile.shared_with_me.includes('?') ? '&' : '?'}action=select_media`
: LinksContext._currentValue.profile.shared_with_me;
return ( return (
<nav ref="tabsNav" className="profile-nav items-list-outer list-inline list-slider"> <nav ref="tabsNav" className="profile-nav items-list-outer list-inline list-slider">
<div className="profile-nav-inner items-list-outer"> <div className="profile-nav-inner items-list-outer">
@@ -392,14 +405,14 @@ class NavMenuInlineTabs extends React.PureComponent {
id="media" id="media"
isActive={'media' === this.props.type} isActive={'media' === this.props.type}
label={translateString(this.userIsAuthor ? 'Media I own' : 'Media')} label={translateString(this.userIsAuthor ? 'Media I own' : 'Media')}
link={LinksContext._currentValue.profile.media} link={mediaLink}
/> />
{this.userIsAuthor ? ( {this.userIsAuthor ? (
<InlineTab <InlineTab
id="shared_by_me" id="shared_by_me"
isActive={'shared_by_me' === this.props.type} isActive={'shared_by_me' === this.props.type}
label={translateString('Shared by me')} label={translateString('Shared by me')}
link={LinksContext._currentValue.profile.shared_by_me} link={sharedByMeLink}
/> />
) : null} ) : null}
{this.userIsAuthor ? ( {this.userIsAuthor ? (
@@ -407,7 +420,7 @@ class NavMenuInlineTabs extends React.PureComponent {
id="shared_with_me" id="shared_with_me"
isActive={'shared_with_me' === this.props.type} isActive={'shared_with_me' === this.props.type}
label={translateString('Shared with me')} label={translateString('Shared with me')}
link={LinksContext._currentValue.profile.shared_with_me} link={sharedWithMeLink}
/> />
) : null} ) : null}

View File

@@ -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 { inEmbeddedApp, translateString } from '../utils/helpers'; import { inEmbeddedApp, inSelectMediaEmbedMode, translateString } from '../utils/helpers';
import { withBulkActions } from '../utils/hoc/withBulkActions'; import { withBulkActions } from '../utils/hoc/withBulkActions';
import { Page } from './_Page'; import { Page } from './_Page';
@@ -51,6 +51,7 @@ class ProfileSharedByMePage extends Page {
availableTags: [], availableTags: [],
selectedTag: 'all', selectedTag: 'all',
selectedSort: 'date_added_desc', selectedSort: 'date_added_desc',
selectedMedia: new Set(), // For select media mode
}; };
this.authorDataLoad = this.authorDataLoad.bind(this); this.authorDataLoad = this.authorDataLoad.bind(this);
@@ -64,6 +65,7 @@ class ProfileSharedByMePage extends Page {
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);
this.handleMediaSelection = this.handleMediaSelection.bind(this);
ProfilePageStore.on('load-author-data', this.authorDataLoad); ProfilePageStore.on('load-author-data', this.authorDataLoad);
} }
@@ -343,10 +345,55 @@ class ProfileSharedByMePage extends Page {
} }
} }
handleMediaSelection(mediaId, isSelected) {
const isSelectMediaMode = inSelectMediaEmbedMode();
this.setState((prevState) => {
const newSelectedMedia = new Set();
// In select media mode, only allow single selection
if (isSelectMediaMode) {
if (isSelected) {
newSelectedMedia.add(mediaId);
console.log('Selected media item:', mediaId);
// Send postMessage to parent window (Moodle TinyMCE plugin)
if (window.parent !== window) {
// Construct the embed URL
const baseUrl = window.location.origin;
const embedUrl = `${baseUrl}/embed?m=${mediaId}`;
// Send message in the format expected by the Moodle plugin
window.parent.postMessage({
type: 'videoSelected',
embedUrl: embedUrl,
videoId: mediaId
}, '*');
console.log('Sent postMessage to parent:', { embedUrl, videoId: mediaId });
}
}
} else {
// Normal mode: should not reach here as bulk actions handle this
newSelectedMedia.clear();
prevState.selectedMedia.forEach((id) => newSelectedMedia.add(id));
if (isSelected) {
newSelectedMedia.add(mediaId);
} else {
newSelectedMedia.delete(mediaId);
}
}
return { selectedMedia: newSelectedMedia };
});
}
pageContent() { pageContent() {
const authorData = ProfilePageStore.get('author-data'); const authorData = ProfilePageStore.get('author-data');
const isMediaAuthor = authorData && authorData.username === MemberContext._currentValue.username; const isMediaAuthor = authorData && authorData.username === MemberContext._currentValue.username;
const isSelectMediaMode = inSelectMediaEmbedMode();
// Check if any filters are active // Check if any filters are active
const hasActiveFilters = const hasActiveFilters =
@@ -375,11 +422,12 @@ class ProfileSharedByMePage extends Page {
this.state.author ? ( this.state.author ? (
<ProfilePagesContent key="ProfilePagesContent"> <ProfilePagesContent key="ProfilePagesContent">
<MediaListWrapper <MediaListWrapper
title={this.state.title} title={isSelectMediaMode ? undefined : this.state.title}
className="items-list-ver" className="items-list-ver"
showBulkActions={isMediaAuthor} style={isSelectMediaMode ? { marginTop: '24px' } : undefined}
selectedCount={this.props.bulkActions.selectedMedia.size} showBulkActions={!isSelectMediaMode && isMediaAuthor}
totalCount={this.props.bulkActions.availableMediaIds.length} selectedCount={isSelectMediaMode ? this.state.selectedMedia.size : this.props.bulkActions.selectedMedia.size}
totalCount={isSelectMediaMode ? 0 : this.props.bulkActions.availableMediaIds.length}
onBulkAction={this.props.bulkActions.handleBulkAction} onBulkAction={this.props.bulkActions.handleBulkAction}
onSelectAll={this.props.bulkActions.handleSelectAll} onSelectAll={this.props.bulkActions.handleSelectAll}
onDeselectAll={this.props.bulkActions.handleDeselectAll} onDeselectAll={this.props.bulkActions.handleDeselectAll}
@@ -396,19 +444,19 @@ class ProfileSharedByMePage extends Page {
/> />
<ProfileMediaSorting hidden={this.state.hiddenSorting} onSortSelect={this.onSortSelect} /> <ProfileMediaSorting hidden={this.state.hiddenSorting} onSortSelect={this.onSortSelect} />
<LazyLoadItemListAsync <LazyLoadItemListAsync
key={`${this.state.requestUrl}-${this.props.bulkActions.listKey}`} key={isSelectMediaMode ? this.state.requestUrl : `${this.state.requestUrl}-${this.props.bulkActions.listKey}`}
requestUrl={this.state.requestUrl} requestUrl={this.state.requestUrl}
hideAuthor={true} hideAuthor={true}
itemsCountCallback={this.state.requestUrl ? this.getCountFunc : null} itemsCountCallback={this.state.requestUrl ? this.getCountFunc : null}
hideViews={!PageStore.get('config-media-item').displayViews} hideViews={!PageStore.get('config-media-item').displayViews}
hideDate={!PageStore.get('config-media-item').displayPublishDate} hideDate={!PageStore.get('config-media-item').displayPublishDate}
canEdit={isMediaAuthor} canEdit={!isSelectMediaMode && isMediaAuthor}
onResponseDataLoaded={this.onResponseDataLoaded} onResponseDataLoaded={this.onResponseDataLoaded}
showSelection={isMediaAuthor} showSelection={isMediaAuthor || isSelectMediaMode}
hasAnySelection={this.props.bulkActions.selectedMedia.size > 0} hasAnySelection={isSelectMediaMode ? this.state.selectedMedia.size > 0 : this.props.bulkActions.selectedMedia.size > 0}
selectedMedia={this.props.bulkActions.selectedMedia} selectedMedia={isSelectMediaMode ? this.state.selectedMedia : this.props.bulkActions.selectedMedia}
onMediaSelection={this.props.bulkActions.handleMediaSelection} onMediaSelection={isSelectMediaMode ? this.handleMediaSelection : this.props.bulkActions.handleMediaSelection}
onItemsUpdate={this.props.bulkActions.handleItemsUpdate} onItemsUpdate={!isSelectMediaMode ? this.props.bulkActions.handleItemsUpdate : undefined}
/> />
{isMediaAuthor && 0 === this.state.channelMediaCount && !this.state.query ? ( {isMediaAuthor && 0 === this.state.channelMediaCount && !this.state.query ? (
<EmptySharedByMe name={this.state.author.name} /> <EmptySharedByMe name={this.state.author.name} />
@@ -416,7 +464,7 @@ class ProfileSharedByMePage extends Page {
</MediaListWrapper> </MediaListWrapper>
</ProfilePagesContent> </ProfilePagesContent>
) : null, ) : null,
this.state.author && isMediaAuthor ? ( this.state.author && isMediaAuthor && !isSelectMediaMode ? (
<BulkActionsModals <BulkActionsModals
key="BulkActionsModals" key="BulkActionsModals"
{...this.props.bulkActions} {...this.props.bulkActions}

View File

@@ -10,7 +10,7 @@ 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 { inEmbeddedApp, translateString } from '../utils/helpers'; import { inEmbeddedApp, inSelectMediaEmbedMode, translateString } from '../utils/helpers';
import { Page } from './_Page'; import { Page } from './_Page';
@@ -49,6 +49,7 @@ export class ProfileSharedWithMePage extends Page {
availableTags: [], availableTags: [],
selectedTag: 'all', selectedTag: 'all',
selectedSort: 'date_added_desc', selectedSort: 'date_added_desc',
selectedMedia: new Set(), // For select media mode
}; };
this.authorDataLoad = this.authorDataLoad.bind(this); this.authorDataLoad = this.authorDataLoad.bind(this);
@@ -62,6 +63,7 @@ export class ProfileSharedWithMePage extends Page {
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);
this.handleMediaSelection = this.handleMediaSelection.bind(this);
ProfilePageStore.on('load-author-data', this.authorDataLoad); ProfilePageStore.on('load-author-data', this.authorDataLoad);
} }
@@ -341,10 +343,55 @@ export class ProfileSharedWithMePage extends Page {
} }
} }
handleMediaSelection(mediaId, isSelected) {
const isSelectMediaMode = inSelectMediaEmbedMode();
this.setState((prevState) => {
const newSelectedMedia = new Set();
// In select media mode, only allow single selection
if (isSelectMediaMode) {
if (isSelected) {
newSelectedMedia.add(mediaId);
console.log('Selected media item:', mediaId);
// Send postMessage to parent window (Moodle TinyMCE plugin)
if (window.parent !== window) {
// Construct the embed URL
const baseUrl = window.location.origin;
const embedUrl = `${baseUrl}/embed?m=${mediaId}`;
// Send message in the format expected by the Moodle plugin
window.parent.postMessage({
type: 'videoSelected',
embedUrl: embedUrl,
videoId: mediaId
}, '*');
console.log('Sent postMessage to parent:', { embedUrl, videoId: mediaId });
}
}
} else {
// Normal mode: no selection UI in this page normally
newSelectedMedia.clear();
prevState.selectedMedia.forEach((id) => newSelectedMedia.add(id));
if (isSelected) {
newSelectedMedia.add(mediaId);
} else {
newSelectedMedia.delete(mediaId);
}
}
return { selectedMedia: newSelectedMedia };
});
}
pageContent() { pageContent() {
const authorData = ProfilePageStore.get('author-data'); const authorData = ProfilePageStore.get('author-data');
const isMediaAuthor = authorData && authorData.username === MemberContext._currentValue.username; const isMediaAuthor = authorData && authorData.username === MemberContext._currentValue.username;
const isSelectMediaMode = inSelectMediaEmbedMode();
// Check if any filters are active // Check if any filters are active
const hasActiveFilters = const hasActiveFilters =
@@ -372,7 +419,11 @@ export class ProfileSharedWithMePage extends Page {
) : null, ) : null,
this.state.author ? ( this.state.author ? (
<ProfilePagesContent key="ProfilePagesContent"> <ProfilePagesContent key="ProfilePagesContent">
<MediaListWrapper title={this.state.title} className="items-list-ver"> <MediaListWrapper
title={isSelectMediaMode ? undefined : this.state.title}
className="items-list-ver"
style={isSelectMediaMode ? { marginTop: '24px' } : undefined}
>
<ProfileMediaFilters <ProfileMediaFilters
hidden={this.state.hiddenFilters} hidden={this.state.hiddenFilters}
tags={this.state.availableTags} tags={this.state.availableTags}
@@ -393,6 +444,10 @@ export class ProfileSharedWithMePage extends Page {
hideDate={!PageStore.get('config-media-item').displayPublishDate} hideDate={!PageStore.get('config-media-item').displayPublishDate}
canEdit={false} canEdit={false}
onResponseDataLoaded={this.onResponseDataLoaded} onResponseDataLoaded={this.onResponseDataLoaded}
showSelection={isSelectMediaMode}
hasAnySelection={this.state.selectedMedia.size > 0}
selectedMedia={this.state.selectedMedia}
onMediaSelection={this.handleMediaSelection}
/> />
{isMediaAuthor && 0 === this.state.channelMediaCount && !this.state.query ? ( {isMediaAuthor && 0 === this.state.channelMediaCount && !this.state.query ? (
<EmptySharedWithMe name={this.state.author.name} /> <EmptySharedWithMe name={this.state.author.name} />

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long