diff --git a/frontend/src/static/js/components/BulkActionsDropdown.tsx b/frontend/src/static/js/components/BulkActionsDropdown.tsx index ac592454..2280810a 100644 --- a/frontend/src/static/js/components/BulkActionsDropdown.tsx +++ b/frontend/src/static/js/components/BulkActionsDropdown.tsx @@ -9,14 +9,15 @@ interface BulkActionsDropdownProps { } const BULK_ACTIONS = [ - { value: 'add-remove-coviewers', label: translateString('Add / Remove Co-Viewers'), enabled: true }, - { value: 'add-remove-coeditors', label: translateString('Add / Remove Co-Editors'), enabled: true }, - { value: 'add-remove-coowners', label: translateString('Add / Remove Co-Owners'), enabled: true }, + { value: 'add-remove-coviewers', label: inEmbeddedApp() ? translateString('Share with Co-Viewers') : translateString('Add / Remove Co-Viewers'), enabled: true }, + { value: 'add-remove-coeditors', label: inEmbeddedApp() ? translateString('Share with Co-Editors') : translateString('Add / Remove Co-Editors'), enabled: true }, + { value: 'add-remove-coowners', label: inEmbeddedApp() ? translateString('Share with Co-Owners') : translateString('Add / Remove Co-Owners'), enabled: true }, { value: 'add-remove-playlist', label: translateString('Add to / Remove from Playlist'), enabled: true }, - { value: 'add-remove-category', label: inEmbeddedApp() ? translateString('Share with Course') : translateString('Add to / Remove from Category'), enabled: true }, + { value: 'add-remove-category', label: inEmbeddedApp() ? translateString('Share with Course Members') : translateString('Add to / Remove from Category'), enabled: true }, { value: 'add-remove-tags', label: translateString('Add / Remove Tags'), enabled: true }, { value: 'enable-comments', label: translateString('Enable Comments'), enabled: true }, { value: 'disable-comments', label: translateString('Disable Comments'), enabled: true }, + { value: 'delete-comments', label: translateString('Delete Comments'), enabled: true }, { value: 'enable-download', label: translateString('Enable Download'), enabled: true }, { value: 'disable-download', label: translateString('Disable Download'), enabled: true }, { value: 'publish-state', label: translateString('Publish State'), enabled: true }, diff --git a/frontend/src/static/js/pages/ProfileAboutPage.js b/frontend/src/static/js/pages/ProfileAboutPage.js index b4495fdf..c9b733c7 100644 --- a/frontend/src/static/js/pages/ProfileAboutPage.js +++ b/frontend/src/static/js/pages/ProfileAboutPage.js @@ -8,7 +8,7 @@ import { PageStore, ProfilePageStore } from '../utils/stores/'; import ProfilePagesHeader from '../components/profile-page/ProfilePagesHeader'; import ProfilePagesContent from '../components/profile-page/ProfilePagesContent'; import { MediaListRow } from '../components/MediaListRow'; -import { ProfileMediaPage } from './ProfileMediaPage'; +import { ProfileMediaPageBase } from './ProfileMediaPage'; class ChannelContactForm extends React.PureComponent { constructor(props) { @@ -149,7 +149,7 @@ class ChannelContactForm extends React.PureComponent { } } -export class ProfileAboutPage extends ProfileMediaPage { +export class ProfileAboutPage extends ProfileMediaPageBase { constructor(props) { super(props, 'author-about'); diff --git a/frontend/src/static/js/pages/ProfileHistoryPage.js b/frontend/src/static/js/pages/ProfileHistoryPage.js index a23f479c..8d56efcd 100755 --- a/frontend/src/static/js/pages/ProfileHistoryPage.js +++ b/frontend/src/static/js/pages/ProfileHistoryPage.js @@ -7,9 +7,9 @@ import { MediaListWrapper } from '../components/MediaListWrapper'; import ProfilePagesHeader from '../components/profile-page/ProfilePagesHeader'; import ProfilePagesContent from '../components/profile-page/ProfilePagesContent'; import { LazyLoadItemListAsync } from '../components/item-list/LazyLoadItemListAsync.jsx'; -import { ProfileMediaPage } from './ProfileMediaPage'; +import { ProfileMediaPageBase } from './ProfileMediaPage'; -export class ProfileHistoryPage extends ProfileMediaPage { +export class ProfileHistoryPage extends ProfileMediaPageBase { constructor(props) { super(props, 'author-history'); diff --git a/frontend/src/static/js/pages/ProfileLikedPage.js b/frontend/src/static/js/pages/ProfileLikedPage.js index 4c390766..e65fa826 100755 --- a/frontend/src/static/js/pages/ProfileLikedPage.js +++ b/frontend/src/static/js/pages/ProfileLikedPage.js @@ -7,9 +7,9 @@ import { MediaListWrapper } from '../components/MediaListWrapper'; import ProfilePagesHeader from '../components/profile-page/ProfilePagesHeader'; import ProfilePagesContent from '../components/profile-page/ProfilePagesContent'; import { LazyLoadItemListAsync } from '../components/item-list/LazyLoadItemListAsync'; -import { ProfileMediaPage } from './ProfileMediaPage'; +import { ProfileMediaPageBase } from './ProfileMediaPage'; -export class ProfileLikedPage extends ProfileMediaPage { +export class ProfileLikedPage extends ProfileMediaPageBase { constructor(props) { super(props, 'author-liked'); diff --git a/frontend/src/static/js/pages/ProfileMediaPage.js b/frontend/src/static/js/pages/ProfileMediaPage.js index 4041c96d..f6901835 100755 --- a/frontend/src/static/js/pages/ProfileMediaPage.js +++ b/frontend/src/static/js/pages/ProfileMediaPage.js @@ -8,22 +8,17 @@ import { MediaListWrapper } from '../components/MediaListWrapper'; import ProfilePagesHeader from '../components/profile-page/ProfilePagesHeader'; import ProfilePagesContent from '../components/profile-page/ProfilePagesContent'; import { LazyLoadItemListAsync } from '../components/item-list/LazyLoadItemListAsync'; -import { BulkActionConfirmModal } from '../components/BulkActionConfirmModal'; -import { BulkActionPermissionModal } from '../components/BulkActionPermissionModal'; -import { BulkActionPlaylistModal } from '../components/BulkActionPlaylistModal'; -import { BulkActionChangeOwnerModal } from '../components/BulkActionChangeOwnerModal'; -import { BulkActionPublishStateModal } from '../components/BulkActionPublishStateModal'; -import { BulkActionCategoryModal } from '../components/BulkActionCategoryModal'; -import { BulkActionTagModal } from '../components/BulkActionTagModal'; +import { BulkActionsModals } from '../components/BulkActionsModals'; import { ProfileMediaFilters } from '../components/search-filters/ProfileMediaFilters'; import { ProfileMediaTags } from '../components/search-filters/ProfileMediaTags'; import { ProfileMediaSorting } from '../components/search-filters/ProfileMediaSorting'; +import { withBulkActions } from '../utils/hoc/withBulkActions'; import { Page } from './_Page'; import '../components/profile-page/ProfilePage.scss'; -export class ProfileMediaPage extends Page { +class ProfileMediaPage extends Page { constructor(props, pageSlug) { super(props, 'string' === typeof pageSlug ? pageSlug : 'author-home'); @@ -36,15 +31,7 @@ export class ProfileMediaPage extends Page { title: this.props.title, query: ProfilePageStore.get('author-query'), requestUrl: null, - selectedMedia: new Set(), - availableMediaIds: [], - showConfirmModal: false, - pendingAction: null, - confirmMessage: '', - listKey: 0, - notificationMessage: '', - showNotification: false, - notificationType: 'success', + selectedMedia: new Set(), // For select media embed mode only hiddenFilters: true, hiddenTags: true, hiddenSorting: true, @@ -52,13 +39,6 @@ export class ProfileMediaPage extends Page { availableTags: [], selectedTag: 'all', selectedSort: 'date_added_desc', - showPermissionModal: false, - permissionType: null, - showPlaylistModal: false, - showChangeOwnerModal: false, - showPublishStateModal: false, - showCategoryModal: false, - showTagModal: false, }; this.authorDataLoad = this.authorDataLoad.bind(this); @@ -66,20 +46,6 @@ export class ProfileMediaPage extends Page { this.getCountFunc = this.getCountFunc.bind(this); this.changeRequestQuery = this.changeRequestQuery.bind(this); this.handleMediaSelection = this.handleMediaSelection.bind(this); - this.handleBulkAction = this.handleBulkAction.bind(this); - this.handleConfirmCancel = this.handleConfirmCancel.bind(this); - this.handleConfirmProceed = this.handleConfirmProceed.bind(this); - this.clearSelectionAndRefresh = this.clearSelectionAndRefresh.bind(this); - this.clearSelection = this.clearSelection.bind(this); - this.executeEnableComments = this.executeEnableComments.bind(this); - this.executeDisableComments = this.executeDisableComments.bind(this); - this.executeEnableDownload = this.executeEnableDownload.bind(this); - this.executeDisableDownload = this.executeDisableDownload.bind(this); - this.executeCopyMedia = this.executeCopyMedia.bind(this); - this.showNotification = this.showNotification.bind(this); - this.handleSelectAll = this.handleSelectAll.bind(this); - this.handleDeselectAll = this.handleDeselectAll.bind(this); - this.handleItemsUpdate = this.handleItemsUpdate.bind(this); this.onToggleFiltersClick = this.onToggleFiltersClick.bind(this); this.onToggleTagsClick = this.onToggleTagsClick.bind(this); this.onToggleSortingClick = this.onToggleSortingClick.bind(this); @@ -87,24 +53,6 @@ export class ProfileMediaPage extends Page { this.onTagSelect = this.onTagSelect.bind(this); this.onSortSelect = this.onSortSelect.bind(this); this.onResponseDataLoaded = this.onResponseDataLoaded.bind(this); - this.handlePermissionModalCancel = this.handlePermissionModalCancel.bind(this); - this.handlePermissionModalSuccess = this.handlePermissionModalSuccess.bind(this); - this.handlePermissionModalError = this.handlePermissionModalError.bind(this); - this.handlePlaylistModalCancel = this.handlePlaylistModalCancel.bind(this); - this.handlePlaylistModalSuccess = this.handlePlaylistModalSuccess.bind(this); - this.handlePlaylistModalError = this.handlePlaylistModalError.bind(this); - this.handleChangeOwnerModalCancel = this.handleChangeOwnerModalCancel.bind(this); - this.handleChangeOwnerModalSuccess = this.handleChangeOwnerModalSuccess.bind(this); - this.handleChangeOwnerModalError = this.handleChangeOwnerModalError.bind(this); - this.handlePublishStateModalCancel = this.handlePublishStateModalCancel.bind(this); - this.handlePublishStateModalSuccess = this.handlePublishStateModalSuccess.bind(this); - this.handlePublishStateModalError = this.handlePublishStateModalError.bind(this); - this.handleCategoryModalCancel = this.handleCategoryModalCancel.bind(this); - this.handleCategoryModalSuccess = this.handleCategoryModalSuccess.bind(this); - this.handleCategoryModalError = this.handleCategoryModalError.bind(this); - this.handleTagModalCancel = this.handleTagModalCancel.bind(this); - this.handleTagModalSuccess = this.handleTagModalSuccess.bind(this); - this.handleTagModalError = this.handleTagModalError.bind(this); ProfilePageStore.on('load-author-data', this.authorDataLoad); } @@ -202,42 +150,22 @@ export class ProfileMediaPage extends Page { } handleMediaSelection(mediaId, isSelected) { - const isSelectMediaMode = inSelectMediaEmbedMode(); - + // Only used in select media embed mode; normal mode is handled by bulkActions 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); + if (isSelected) { + newSelectedMedia.add(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}`; + if (window.parent !== window) { + 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: allow multiple selection - newSelectedMedia.clear(); - prevState.selectedMedia.forEach((id) => newSelectedMedia.add(id)); - - if (isSelected) { - newSelectedMedia.add(mediaId); - } else { - newSelectedMedia.delete(mediaId); + window.parent.postMessage({ + type: 'videoSelected', + embedUrl: embedUrl, + videoId: mediaId + }, '*'); } } @@ -245,386 +173,6 @@ export class ProfileMediaPage extends Page { }); } - handleBulkAction(action) { - const selectedCount = this.state.selectedMedia.size; - - if (selectedCount === 0) { - return; - } - - if (action === 'delete-media') { - this.setState({ - showConfirmModal: true, - pendingAction: action, - confirmMessage: - translateString('You are going to delete') + - ` ${selectedCount} ` + - translateString('media, are you sure?'), - }); - } else if (action === 'enable-comments') { - this.setState({ - showConfirmModal: true, - pendingAction: action, - confirmMessage: - translateString('You are going to enable comments to') + - ` ${selectedCount} ` + - translateString('media, are you sure?'), - }); - } else if (action === 'disable-comments') { - this.setState({ - showConfirmModal: true, - pendingAction: action, - confirmMessage: - translateString('You are going to disable comments to') + - ` ${selectedCount} ` + - translateString('media, are you sure?'), - }); - } else if (action === 'enable-download') { - this.setState({ - showConfirmModal: true, - pendingAction: action, - confirmMessage: - translateString('You are going to enable download for') + - ` ${selectedCount} ` + - translateString('media, are you sure?'), - }); - } else if (action === 'disable-download') { - this.setState({ - showConfirmModal: true, - pendingAction: action, - confirmMessage: - translateString('You are going to disable download for') + - ` ${selectedCount} ` + - translateString('media, are you sure?'), - }); - } else if (action === 'copy-media') { - this.setState({ - showConfirmModal: true, - pendingAction: action, - confirmMessage: - translateString('You are going to copy') + - ` ${selectedCount} ` + - translateString('media, are you sure?'), - }); - } else if (action === 'add-remove-coviewers') { - this.setState({ - showPermissionModal: true, - permissionType: 'viewer', - }); - } else if (action === 'add-remove-coeditors') { - this.setState({ - showPermissionModal: true, - permissionType: 'editor', - }); - } else if (action === 'add-remove-coowners') { - this.setState({ - showPermissionModal: true, - permissionType: 'owner', - }); - } else if (action === 'add-remove-playlist') { - this.setState({ - showPlaylistModal: true, - }); - } else if (action === 'change-owner') { - this.setState({ - showChangeOwnerModal: true, - }); - } else if (action === 'publish-state') { - this.setState({ - showPublishStateModal: true, - }); - } else if (action === 'add-remove-category') { - this.setState({ - showCategoryModal: true, - }); - } else if (action === 'add-remove-tags') { - this.setState({ - showTagModal: true, - }); - } else { - // Other actions can be implemented later - } - } - - handleConfirmCancel() { - this.setState({ - showConfirmModal: false, - pendingAction: null, - confirmMessage: '', - }); - } - - handleConfirmProceed() { - const action = this.state.pendingAction; - this.setState({ - showConfirmModal: false, - pendingAction: null, - confirmMessage: '', - }); - - if (action === 'delete-media') { - this.executeDeleteMedia(); - } else if (action === 'enable-comments') { - this.executeEnableComments(); - } else if (action === 'disable-comments') { - this.executeDisableComments(); - } else if (action === 'enable-download') { - this.executeEnableDownload(); - } else if (action === 'disable-download') { - this.executeDisableDownload(); - } else if (action === 'copy-media') { - this.executeCopyMedia(); - } - } - - executeDeleteMedia() { - const selectedIds = Array.from(this.state.selectedMedia); - const selectedCount = selectedIds.length; - - fetch('/api/v1/media/user/bulk_actions', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': this.getCsrfToken(), - }, - body: JSON.stringify({ - action: 'delete_media', - media_ids: selectedIds, - }), - }) - .then((response) => { - if (!response.ok) { - throw new Error('Failed to delete media'); - } - return response.json(); - }) - .then((data) => { - const message = - selectedCount === 1 - ? translateString('The media was deleted successfully.') - : translateString('Successfully deleted') + ` ${selectedCount} ` + translateString('media.'); - this.showNotification(message); - this.clearSelectionAndRefresh(); - }) - .catch((error) => { - this.showNotification(translateString('Failed to delete media. Please try again.'), 'error'); - this.clearSelectionAndRefresh(); - }); - } - - getCsrfToken() { - const name = 'csrftoken'; - let cookieValue = null; - if (document.cookie && document.cookie !== '') { - const cookies = document.cookie.split(';'); - for (let i = 0; i < cookies.length; i++) { - const cookie = cookies[i].trim(); - if (cookie.substring(0, name.length + 1) === name + '=') { - cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); - break; - } - } - } - return cookieValue; - } - - clearSelectionAndRefresh() { - // Clear selected media and increment listKey to force re-render - this.setState((prevState) => ({ - selectedMedia: new Set(), - listKey: prevState.listKey + 1, - })); - } - - clearSelection() { - // Clear selected media without refreshing - this.setState({ - selectedMedia: new Set(), - }); - } - - executeEnableComments() { - const selectedIds = Array.from(this.state.selectedMedia); - - fetch('/api/v1/media/user/bulk_actions', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': this.getCsrfToken(), - }, - body: JSON.stringify({ - action: 'enable_comments', - media_ids: selectedIds, - }), - }) - .then((response) => { - if (!response.ok) { - throw new Error('Failed to enable comments'); - } - return response.json(); - }) - .then((data) => { - this.showNotification(translateString('Successfully Enabled comments')); - this.clearSelection(); - }) - .catch((error) => { - this.showNotification(translateString('Failed to enable comments.'), 'error'); - this.clearSelection(); - }); - } - - executeDisableComments() { - const selectedIds = Array.from(this.state.selectedMedia); - - fetch('/api/v1/media/user/bulk_actions', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': this.getCsrfToken(), - }, - body: JSON.stringify({ - action: 'disable_comments', - media_ids: selectedIds, - }), - }) - .then((response) => { - if (!response.ok) { - throw new Error('Failed to disable comments'); - } - return response.json(); - }) - .then((data) => { - this.showNotification(translateString('Successfully Disabled comments')); - this.clearSelection(); - }) - .catch((error) => { - this.showNotification(translateString('Failed to disable comments.'), 'error'); - this.clearSelection(); - }); - } - - executeEnableDownload() { - const selectedIds = Array.from(this.state.selectedMedia); - - fetch('/api/v1/media/user/bulk_actions', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': this.getCsrfToken(), - }, - body: JSON.stringify({ - action: 'enable_download', - media_ids: selectedIds, - }), - }) - .then((response) => { - if (!response.ok) { - throw new Error('Failed to enable download'); - } - return response.json(); - }) - .then((data) => { - this.showNotification(translateString('Successfully Enabled Download')); - this.clearSelection(); - }) - .catch((error) => { - this.showNotification(translateString('Failed to enable download.'), 'error'); - this.clearSelection(); - }); - } - - executeDisableDownload() { - const selectedIds = Array.from(this.state.selectedMedia); - - fetch('/api/v1/media/user/bulk_actions', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': this.getCsrfToken(), - }, - body: JSON.stringify({ - action: 'disable_download', - media_ids: selectedIds, - }), - }) - .then((response) => { - if (!response.ok) { - throw new Error('Failed to disable download'); - } - return response.json(); - }) - .then((data) => { - this.showNotification(translateString('Successfully Disabled Download')); - this.clearSelection(); - }) - .catch((error) => { - this.showNotification(translateString('Failed to disable download.'), 'error'); - this.clearSelection(); - }); - } - - executeCopyMedia() { - const selectedIds = Array.from(this.state.selectedMedia); - - fetch('/api/v1/media/user/bulk_actions', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-CSRFToken': this.getCsrfToken(), - }, - body: JSON.stringify({ - action: 'copy_media', - media_ids: selectedIds, - }), - }) - .then((response) => { - if (!response.ok) { - throw new Error('Failed to copy media'); - } - return response.json(); - }) - .then((data) => { - this.showNotification(translateString('Successfully Copied')); - this.clearSelectionAndRefresh(); - }) - .catch((error) => { - this.showNotification(translateString('Failed to copy media.'), 'error'); - this.clearSelection(); - }); - } - - showNotification(message, type = 'success') { - this.setState({ - notificationMessage: message, - showNotification: true, - notificationType: type, - }); - - setTimeout(() => { - this.setState({ showNotification: false }); - }, 5000); - } - - handleItemsUpdate(items) { - // Extract media IDs from loaded items - const mediaIds = items.map((item) => item.friendly_token || item.uid || item.id); - this.setState({ availableMediaIds: mediaIds }); - } - - handleSelectAll() { - // Select all available media - this.setState({ - selectedMedia: new Set(this.state.availableMediaIds), - }); - } - - handleDeselectAll() { - // Clear all selections - this.setState({ - selectedMedia: new Set(), - }); - } - onToggleFiltersClick() { this.setState({ hiddenFilters: !this.state.hiddenFilters, @@ -651,7 +199,6 @@ export class ProfileMediaPage extends Page { onTagSelect(tag) { this.setState({ selectedTag: tag }, () => { - // Apply tag filter this.onFiltersUpdate({ media_type: this.state.filterArgs.includes('media_type') ? this.state.filterArgs.match(/media_type=([^&]*)/)?.[1] @@ -673,7 +220,6 @@ export class ProfileMediaPage extends Page { onSortSelect(sortOption) { this.setState({ selectedSort: sortOption }, () => { - // Apply sort filter this.onFiltersUpdate({ media_type: this.state.filterArgs.includes('media_type') ? this.state.filterArgs.match(/media_type=([^&]*)/)?.[1] @@ -722,19 +268,16 @@ export class ProfileMediaPage extends Page { 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'; @@ -759,7 +302,6 @@ export class ProfileMediaPage extends Page { break; } - // Handle tag filter if (updatedArgs.tag && updatedArgs.tag !== 'all') { args.t = updatedArgs.tag; } @@ -775,10 +317,8 @@ export class ProfileMediaPage extends Page { this.setState( { filterArgs: newArgs.length ? '&' + newArgs.join('&') : '', - selectedMedia: new Set(), // Clear selected items when filter changes }, function () { - // Update the request URL with new filter args if (!this.state.author) { return; } @@ -805,137 +345,7 @@ export class ProfileMediaPage extends Page { ); } - handlePermissionModalCancel() { - this.setState({ - showPermissionModal: false, - permissionType: null, - }); - } - - handlePermissionModalSuccess(message) { - this.showNotification(message); - this.clearSelection(); - this.setState({ - showPermissionModal: false, - permissionType: null, - }); - } - - handlePermissionModalError(message) { - this.showNotification(message, 'error'); - this.setState({ - showPermissionModal: false, - permissionType: null, - }); - } - - handlePlaylistModalCancel() { - this.setState({ - showPlaylistModal: false, - }); - } - - handlePlaylistModalSuccess(message) { - this.showNotification(message); - this.clearSelection(); - this.setState({ - showPlaylistModal: false, - }); - } - - handlePlaylistModalError(message) { - this.showNotification(message, 'error'); - this.setState({ - showPlaylistModal: false, - }); - } - - handleChangeOwnerModalCancel() { - this.setState({ - showChangeOwnerModal: false, - }); - } - - handleChangeOwnerModalSuccess(message) { - this.showNotification(message); - this.clearSelectionAndRefresh(); - this.setState({ - showChangeOwnerModal: false, - }); - } - - handleChangeOwnerModalError(message) { - this.showNotification(message, 'error'); - this.setState({ - showChangeOwnerModal: false, - }); - } - - handlePublishStateModalCancel() { - this.setState({ - showPublishStateModal: false, - }); - } - - handlePublishStateModalSuccess(message) { - this.showNotification(message); - this.clearSelectionAndRefresh(); - this.setState({ - showPublishStateModal: false, - }); - } - - handlePublishStateModalError(message) { - this.showNotification(message, 'error'); - this.setState({ - showPublishStateModal: false, - }); - } - - handleCategoryModalCancel() { - this.setState({ - showCategoryModal: false, - }); - } - - handleCategoryModalSuccess(message) { - this.showNotification(message); - this.clearSelection(); - this.setState({ - showCategoryModal: false, - }); - } - - handleCategoryModalError(message) { - this.showNotification(message, 'error'); - this.setState({ - showCategoryModal: false, - }); - } - - handleTagModalCancel() { - this.setState({ - showTagModal: false, - }); - } - - handleTagModalSuccess(message) { - this.showNotification(message); - this.clearSelection(); - this.setState({ - showTagModal: false, - }); - } - - handleTagModalError(message) { - this.showNotification(message, 'error'); - this.setState({ - showTagModal: false, - }); - } - onResponseDataLoaded(responseData) { - // Extract tags from response if (responseData && responseData.tags) { const tags = responseData.tags .split(',') @@ -951,7 +361,6 @@ export class ProfileMediaPage extends Page { const isMediaAuthor = authorData && authorData.username === MemberContext._currentValue.username; const isSelectMediaMode = inSelectMediaEmbedMode(); - // Check if any filters are active (excluding default sort and tags) const hasActiveFilters = this.state.filterArgs && (this.state.filterArgs.includes('media_type=') || @@ -985,11 +394,11 @@ export class ProfileMediaPage extends Page { className="items-list-ver" style={inEmbeddedApp() ? { marginTop: '24px' } : undefined} showBulkActions={!isSelectMediaMode && isMediaAuthor} - selectedCount={this.state.selectedMedia.size} - totalCount={this.state.availableMediaIds.length} - onBulkAction={this.handleBulkAction} - onSelectAll={this.handleSelectAll} - onDeselectAll={this.handleDeselectAll} + selectedCount={isSelectMediaMode ? this.state.selectedMedia.size : this.props.bulkActions.selectedMedia.size} + totalCount={isSelectMediaMode ? 0 : this.props.bulkActions.availableMediaIds.length} + onBulkAction={this.props.bulkActions.handleBulkAction} + onSelectAll={this.props.bulkActions.handleSelectAll} + onDeselectAll={this.props.bulkActions.handleDeselectAll} showAddMediaButton={!isSelectMediaMode && isMediaAuthor} >