Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f234ebc48 | |||
| 305743d752 |
@@ -1,3 +1,4 @@
|
||||
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { SyncStrategy, RegexReplacement, SyncState, ScheduleSettings, ScheduleMode } from '../types';
|
||||
import {
|
||||
@@ -61,6 +62,25 @@ const STRATEGIES: StrategyOption[] = [
|
||||
|
||||
const WEEK_DAYS = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
|
||||
|
||||
// Helper to determine the actual mode and settings that would be saved based on the current UI state
|
||||
const deriveEffectiveSchedule = (schedule: ScheduleSettings, tab: ScheduleMode): ScheduleSettings => {
|
||||
const derived = { ...schedule };
|
||||
|
||||
if (tab === ScheduleMode.CRON) {
|
||||
derived.mode = derived.cronExpression.trim() !== '' ? ScheduleMode.CRON : ScheduleMode.DISABLED;
|
||||
} else {
|
||||
// For Daily/Weekly
|
||||
// If the mode matches the tab, we keep it (Enabled).
|
||||
// If the mode doesn't match (e.g. it was CRON or DISABLED), then in the context of this tab, it is effectively Disabled until the user checks the box.
|
||||
if (derived.mode === tab) {
|
||||
derived.mode = tab;
|
||||
} else {
|
||||
derived.mode = ScheduleMode.DISABLED;
|
||||
}
|
||||
}
|
||||
return derived;
|
||||
};
|
||||
|
||||
interface StrategySelectorProps {
|
||||
currentStrategy: SyncStrategy;
|
||||
onSelect: (strategy: SyncStrategy, label: string) => void;
|
||||
@@ -123,10 +143,13 @@ const StrategySelector: React.FC<StrategySelectorProps> = ({
|
||||
setIsRegexDirty(isDifferent);
|
||||
}, [localReplacements, savedRegexReplacements]);
|
||||
|
||||
// Check dirty state for Schedule (including Active Tab changes)
|
||||
useEffect(() => {
|
||||
const isDifferent = JSON.stringify(localSchedule) !== JSON.stringify(savedSchedule);
|
||||
// We calculate what the "effective" schedule would be if we saved right now.
|
||||
const effectiveLocal = deriveEffectiveSchedule(localSchedule, activeTab);
|
||||
const isDifferent = JSON.stringify(effectiveLocal) !== JSON.stringify(savedSchedule);
|
||||
setIsScheduleDirty(isDifferent);
|
||||
}, [localSchedule, savedSchedule]);
|
||||
}, [localSchedule, savedSchedule, activeTab]);
|
||||
|
||||
const selectedOption = STRATEGIES.find(s => s.value === currentStrategy) || STRATEGIES[0];
|
||||
|
||||
@@ -140,6 +163,11 @@ const StrategySelector: React.FC<StrategySelectorProps> = ({
|
||||
return () => document.removeEventListener('mousedown', handleClickOutside);
|
||||
}, []);
|
||||
|
||||
// Determine if tabs have changed from the saved state
|
||||
const initialTab = savedSchedule.mode === ScheduleMode.DISABLED ? ScheduleMode.CRON : savedSchedule.mode;
|
||||
const hasTabChanged = activeTab !== initialTab;
|
||||
const isScheduleActionable = isScheduleDirty || hasTabChanged;
|
||||
|
||||
const handleSelect = (strategy: StrategyOption) => {
|
||||
if (isLocked) return;
|
||||
onSelect(strategy.value, strategy.label);
|
||||
@@ -196,37 +224,23 @@ const StrategySelector: React.FC<StrategySelectorProps> = ({
|
||||
setLocalSchedule(JSON.parse(JSON.stringify(savedSchedule)));
|
||||
if (savedSchedule.mode !== ScheduleMode.DISABLED) {
|
||||
setActiveTab(savedSchedule.mode);
|
||||
} else {
|
||||
setActiveTab(ScheduleMode.CRON);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSaveScheduleClick = async () => {
|
||||
if (isLocked) return;
|
||||
|
||||
let settingsToSave = { ...localSchedule };
|
||||
|
||||
// Logic to determine mode based on active Tab and checkbox state
|
||||
if (activeTab === ScheduleMode.CRON) {
|
||||
if (settingsToSave.cronExpression.trim() !== '') {
|
||||
settingsToSave.mode = ScheduleMode.CRON;
|
||||
} else {
|
||||
// Empty cron -> disabled
|
||||
settingsToSave.mode = ScheduleMode.DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
// For Daily/Weekly, enforce: Save commits what is seen in the active tab.
|
||||
if (activeTab !== ScheduleMode.CRON) {
|
||||
// If the mode matches the active tab, it's enabled. Otherwise disabled.
|
||||
if (localSchedule.mode !== activeTab) {
|
||||
settingsToSave.mode = ScheduleMode.DISABLED;
|
||||
}
|
||||
}
|
||||
// Determine the effective settings based on the current view (tab) and inputs
|
||||
const settingsToSave = deriveEffectiveSchedule(localSchedule, activeTab);
|
||||
|
||||
// Call API
|
||||
const success = await onSaveSchedule(settingsToSave);
|
||||
if (success) {
|
||||
setLocalSchedule(settingsToSave);
|
||||
setIsScheduleDirty(false);
|
||||
// Dirty state is cleared by the useEffect prop update, or we can clear it optimistically here if needed,
|
||||
// but useEffect [savedSchedule] handles it correctly.
|
||||
}
|
||||
};
|
||||
|
||||
@@ -554,9 +568,9 @@ const StrategySelector: React.FC<StrategySelectorProps> = ({
|
||||
<div className="flex items-center gap-2 justify-end pt-3 border-t border-white/5">
|
||||
<button
|
||||
onClick={handleResetSchedule}
|
||||
disabled={!isScheduleDirty}
|
||||
disabled={!isScheduleActionable}
|
||||
className={`flex items-center justify-center space-x-1.5 px-3 py-1.5 rounded-md text-xs font-medium border transition-all
|
||||
${isScheduleDirty
|
||||
${isScheduleActionable
|
||||
? 'bg-gray-800 border-gray-600 text-gray-300 hover:bg-gray-700 hover:text-white'
|
||||
: 'bg-transparent border-transparent text-gray-700 cursor-not-allowed'}`}
|
||||
>
|
||||
@@ -565,9 +579,9 @@ const StrategySelector: React.FC<StrategySelectorProps> = ({
|
||||
</button>
|
||||
<button
|
||||
onClick={handleSaveScheduleClick}
|
||||
disabled={!isScheduleDirty}
|
||||
disabled={!isScheduleActionable}
|
||||
className={`flex items-center justify-center space-x-1.5 px-3 py-1.5 rounded-md text-xs font-bold border transition-all
|
||||
${isScheduleDirty
|
||||
${isScheduleActionable
|
||||
? 'bg-plex-orange border-plex-orange text-gray-900 hover:bg-yellow-500 shadow-lg shadow-plex-orange/10'
|
||||
: 'bg-gray-800/30 border-gray-800/50 text-gray-600 cursor-not-allowed'}`}
|
||||
>
|
||||
@@ -614,4 +628,4 @@ const StrategySelector: React.FC<StrategySelectorProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default StrategySelector;
|
||||
export default StrategySelector;
|
||||
|
||||
Reference in New Issue
Block a user