This commit is contained in:
Markos Gogoulos
2026-04-20 18:43:35 +03:00
parent 690ffd9409
commit c6f713a885
7 changed files with 106 additions and 25 deletions
@@ -159,6 +159,56 @@
}
}
.shared-selector {
display: flex;
flex-direction: column;
gap: 6px;
&-label {
display: flex;
align-items: center;
gap: 8px;
font-size: 14px;
font-weight: 500;
color: #333;
cursor: pointer;
user-select: none;
input[type='checkbox'] {
width: 16px;
height: 16px;
cursor: pointer;
&:disabled {
cursor: not-allowed;
opacity: 0.5;
}
}
.dark_theme & {
color: #fff;
}
}
&-note {
margin: 0;
font-size: 12px;
color: #777;
&--warn {
color: #b45309;
}
.dark_theme & {
color: #aaa;
&--warn {
color: #f59e0b;
}
}
}
}
.publish-state-modal-footer {
display: flex;
justify-content: flex-end;
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useRef } from 'react';
import './BulkActionPublishStateModal.scss';
import { translateString } from '../utils/helpers/';
@@ -32,14 +32,23 @@ export const BulkActionPublishStateModal: React.FC<BulkActionPublishStateModalPr
const defaultState = availableStates[0].value;
const [selectedState, setSelectedState] = useState(defaultState);
const [shared, setShared] = useState<boolean | null>(null);
const [isProcessing, setIsProcessing] = useState(false);
const sharedRef = useRef<HTMLInputElement>(null);
useEffect(() => {
if (!isOpen) {
setSelectedState(defaultState);
setShared(null);
}
}, [isOpen]);
useEffect(() => {
if (sharedRef.current) {
sharedRef.current.indeterminate = shared === null;
}
}, [shared]);
const handleSubmit = async () => {
if (!selectedState) {
onError(translateString('Please select a publish state'));
@@ -49,17 +58,22 @@ export const BulkActionPublishStateModal: React.FC<BulkActionPublishStateModalPr
setIsProcessing(true);
try {
const body: Record<string, unknown> = {
action: 'set_state',
media_ids: selectedMediaIds,
state: selectedState,
};
if (shared !== null) {
body.shared = shared;
}
const response = await fetch('/api/v1/media/user/bulk_actions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrfToken,
},
body: JSON.stringify({
action: 'set_state',
media_ids: selectedMediaIds,
state: selectedState,
}),
body: JSON.stringify(body),
});
if (!response.ok) {
@@ -79,9 +93,12 @@ export const BulkActionPublishStateModal: React.FC<BulkActionPublishStateModalPr
if (!isOpen) return null;
// Note: We don't check hasStateChanged because the modal doesn't know the actual
// current state of the selected media. Users should be able to set any state.
// If the state is already the same, the backend will handle it gracefully.
const sharedNote =
shared === null
? translateString('Sharing status will not be changed.')
: shared
? translateString('Selected media will be marked as shared.')
: translateString('Sharing will be removed from all selected media.');
return (
<div className="publish-state-modal-overlay">
@@ -109,6 +126,22 @@ export const BulkActionPublishStateModal: React.FC<BulkActionPublishStateModalPr
))}
</select>
</div>
<div className="shared-selector">
<label className="shared-selector-label">
<input
ref={sharedRef}
type="checkbox"
checked={shared === true}
onChange={(e) => setShared(e.target.checked)}
disabled={isProcessing}
/>
{translateString('Shared')}
</label>
<p className={`shared-selector-note${shared === false ? ' shared-selector-note--warn' : ''}`}>
{sharedNote}
</p>
</div>
</div>
<div className="publish-state-modal-footer">