chore: remove locked dimension UI residue
Remove padlock button from dimensions pane, priority-toggle behaviour from node dimension tags, and all supporting state/functions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
75c4c58ec7
commit
41f8498d4a
@@ -14,16 +14,6 @@ import { useDimensionIcons } from '@/context/DimensionIconsContext';
|
|||||||
import ConfirmDialog from '../common/ConfirmDialog';
|
import ConfirmDialog from '../common/ConfirmDialog';
|
||||||
import { SourceReader } from './source';
|
import { SourceReader } from './source';
|
||||||
|
|
||||||
interface PopularDimension {
|
|
||||||
dimension: string;
|
|
||||||
count: number;
|
|
||||||
isPriority: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DimensionsResponse {
|
|
||||||
success: boolean;
|
|
||||||
data: PopularDimension[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface NodeSearchResult {
|
interface NodeSearchResult {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -58,7 +48,6 @@ export default function FocusPanel({ openTabs, activeTab, onTabSelect, onNodeCli
|
|||||||
const [savingField, setSavingField] = useState<string | null>(null);
|
const [savingField, setSavingField] = useState<string | null>(null);
|
||||||
const [embeddingNode, setEmbeddingNode] = useState<number | null>(null);
|
const [embeddingNode, setEmbeddingNode] = useState<number | null>(null);
|
||||||
const [showReembedPrompt, setShowReembedPrompt] = useState<number | null>(null);
|
const [showReembedPrompt, setShowReembedPrompt] = useState<number | null>(null);
|
||||||
const [priorityDimensions, setPriorityDimensions] = useState<string[]>([]);
|
|
||||||
|
|
||||||
const activeNodeId = activeTab;
|
const activeNodeId = activeTab;
|
||||||
const currentNode = activeNodeId !== null ? nodesData[activeNodeId] : undefined;
|
const currentNode = activeNodeId !== null ? nodesData[activeNodeId] : undefined;
|
||||||
@@ -172,10 +161,6 @@ export default function FocusPanel({ openTabs, activeTab, onTabSelect, onNodeCli
|
|||||||
return { type: 'inferred', label: 'will be inferred' };
|
return { type: 'inferred', label: 'will be inferred' };
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fetch priority dimensions on mount
|
|
||||||
useEffect(() => {
|
|
||||||
fetchPriorityDimensions();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// Generate node search suggestions
|
// Generate node search suggestions
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -254,19 +239,6 @@ export default function FocusPanel({ openTabs, activeTab, onTabSelect, onNodeCli
|
|||||||
setSourceEditValue('');
|
setSourceEditValue('');
|
||||||
}, [activeTab]);
|
}, [activeTab]);
|
||||||
|
|
||||||
const fetchPriorityDimensions = async () => {
|
|
||||||
try {
|
|
||||||
const response = await fetch('/api/dimensions/popular');
|
|
||||||
const payload = (await response.json()) as DimensionsResponse;
|
|
||||||
if (payload?.success && Array.isArray(payload.data)) {
|
|
||||||
const priority = payload.data.filter((d) => d.isPriority).map((d) => d.dimension);
|
|
||||||
setPriorityDimensions(priority);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching priority dimensions:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchNodeData = async (id: number) => {
|
const fetchNodeData = async (id: number) => {
|
||||||
setLoadingNodes(prev => new Set(prev).add(id));
|
setLoadingNodes(prev => new Set(prev).add(id));
|
||||||
// First try to fetch as a node
|
// First try to fetch as a node
|
||||||
@@ -2074,7 +2046,6 @@ export default function FocusPanel({ openTabs, activeTab, onTabSelect, onNodeCli
|
|||||||
}}>
|
}}>
|
||||||
<DimensionTags
|
<DimensionTags
|
||||||
dimensions={nodesData[activeTab].dimensions || []}
|
dimensions={nodesData[activeTab].dimensions || []}
|
||||||
priorityDimensions={priorityDimensions}
|
|
||||||
onUpdate={async (newDimensions) => {
|
onUpdate={async (newDimensions) => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/api/nodes/${activeTab}`, {
|
const response = await fetch(`/api/nodes/${activeTab}`, {
|
||||||
@@ -2098,28 +2069,6 @@ export default function FocusPanel({ openTabs, activeTab, onTabSelect, onNodeCli
|
|||||||
alert('Failed to save dimensions. Please try again.');
|
alert('Failed to save dimensions. Please try again.');
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onPriorityToggle={async (dimension) => {
|
|
||||||
try {
|
|
||||||
const response = await fetch('/api/dimensions/popular', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ dimension }),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('Failed to toggle priority');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresh priority dimensions list
|
|
||||||
await fetchPriorityDimensions();
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error toggling priority:', error);
|
|
||||||
alert('Failed to toggle priority. Please try again.');
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
disabled={false}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ import DimensionSearchModal from './DimensionSearchModal';
|
|||||||
|
|
||||||
interface DimensionTagsProps {
|
interface DimensionTagsProps {
|
||||||
dimensions: string[];
|
dimensions: string[];
|
||||||
priorityDimensions?: string[];
|
|
||||||
onUpdate: (dimensions: string[]) => Promise<void>;
|
onUpdate: (dimensions: string[]) => Promise<void>;
|
||||||
onPriorityToggle?: (dimension: string) => Promise<void>;
|
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,12 +14,10 @@ interface DimensionSuggestion {
|
|||||||
count: number;
|
count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function DimensionTags({
|
export default function DimensionTags({
|
||||||
dimensions,
|
dimensions,
|
||||||
priorityDimensions = [],
|
onUpdate,
|
||||||
onUpdate,
|
disabled = false
|
||||||
onPriorityToggle,
|
|
||||||
disabled = false
|
|
||||||
}: DimensionTagsProps) {
|
}: DimensionTagsProps) {
|
||||||
const [isAdding, setIsAdding] = useState(false);
|
const [isAdding, setIsAdding] = useState(false);
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
@@ -32,14 +28,7 @@ export default function DimensionTags({
|
|||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
// Sort dimensions with priority ones first
|
const sortedDimensions = [...dimensions];
|
||||||
const sortedDimensions = [...dimensions].sort((a, b) => {
|
|
||||||
const aPriority = priorityDimensions.includes(a);
|
|
||||||
const bPriority = priorityDimensions.includes(b);
|
|
||||||
if (aPriority && !bPriority) return -1;
|
|
||||||
if (!aPriority && bPriority) return 1;
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isAdding && inputRef.current) {
|
if (isAdding && inputRef.current) {
|
||||||
@@ -169,12 +158,6 @@ export default function DimensionTags({
|
|||||||
await onUpdate(newDimensions);
|
await onUpdate(newDimensions);
|
||||||
};
|
};
|
||||||
|
|
||||||
const togglePriority = async (dimension: string) => {
|
|
||||||
if (onPriorityToggle) {
|
|
||||||
await onPriorityToggle(dimension);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check if dimensions overflow 2 lines (approximate)
|
// Check if dimensions overflow 2 lines (approximate)
|
||||||
const shouldShowExpandButton = sortedDimensions.length > 6; // Rough estimate for 2 lines
|
const shouldShowExpandButton = sortedDimensions.length > 6; // Rough estimate for 2 lines
|
||||||
const displayedDimensions = (!isExpanded && shouldShowExpandButton)
|
const displayedDimensions = (!isExpanded && shouldShowExpandButton)
|
||||||
@@ -216,8 +199,6 @@ export default function DimensionTags({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{displayedDimensions.map((dimension, index) => {
|
{displayedDimensions.map((dimension, index) => {
|
||||||
const isPriority = priorityDimensions.includes(dimension);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={`${dimension}-${index}`}
|
key={`${dimension}-${index}`}
|
||||||
@@ -225,35 +206,28 @@ export default function DimensionTags({
|
|||||||
onDragStart={() => handleDragStart(index)}
|
onDragStart={() => handleDragStart(index)}
|
||||||
onDragOver={(e) => handleDragOver(e, index)}
|
onDragOver={(e) => handleDragOver(e, index)}
|
||||||
onDragEnd={handleDragEnd}
|
onDragEnd={handleDragEnd}
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
if (!disabled && onPriorityToggle) {
|
|
||||||
togglePriority(dimension);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
style={{
|
style={{
|
||||||
display: 'inline-flex',
|
display: 'inline-flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: '3px',
|
gap: '3px',
|
||||||
fontSize: '10px',
|
fontSize: '10px',
|
||||||
color: isPriority ? '#22c55e' : '#d1d5db', /* Changed from gold to green */
|
color: '#d1d5db',
|
||||||
background: isPriority ? '#0f2417' : '#1a1a1a', /* Green-tinted background */
|
background: '#1a1a1a',
|
||||||
border: isPriority ? '1px solid #166534' : '1px solid #333', /* Green border */
|
border: '1px solid #333',
|
||||||
borderRadius: '8px',
|
borderRadius: '8px',
|
||||||
padding: '2px 6px',
|
padding: '2px 6px',
|
||||||
cursor: disabled ? 'default' : (onPriorityToggle ? 'pointer' : 'grab'),
|
cursor: disabled ? 'default' : 'grab',
|
||||||
opacity: draggedIndex === index ? 0.5 : 1,
|
opacity: draggedIndex === index ? 0.5 : 1,
|
||||||
transition: 'all 0.2s'
|
transition: 'all 0.2s'
|
||||||
}}
|
}}
|
||||||
onMouseEnter={(e) => {
|
onMouseEnter={(e) => {
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
e.currentTarget.style.borderColor = isPriority ? '#22c55e' : '#555'; /* Green hover */
|
e.currentTarget.style.borderColor = '#555';
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onMouseLeave={(e) => {
|
onMouseLeave={(e) => {
|
||||||
e.currentTarget.style.borderColor = isPriority ? '#166534' : '#333'; /* Green default */
|
e.currentTarget.style.borderColor = '#333';
|
||||||
}}
|
}}
|
||||||
title={isPriority ? 'Priority dimension (click to unpin)' : 'Click to pin as priority dimension'}
|
|
||||||
>
|
>
|
||||||
<span>{dimension}</span>
|
<span>{dimension}</span>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useEffect, useMemo, useState, useRef, type DragEvent } from 'react';
|
import { useEffect, useMemo, useState, useRef, type DragEvent } from 'react';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import { Check, X, ArrowLeft, Plus, Trash2, Edit2, Lock } from 'lucide-react';
|
import { X, ArrowLeft, Plus, Trash2, Edit2 } from 'lucide-react';
|
||||||
import type { Node } from '@/types/database';
|
import type { Node } from '@/types/database';
|
||||||
import ConfirmDialog from '../common/ConfirmDialog';
|
import ConfirmDialog from '../common/ConfirmDialog';
|
||||||
import InputDialog from '../common/InputDialog';
|
import InputDialog from '../common/InputDialog';
|
||||||
@@ -237,24 +237,6 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleToggleLock = async (dimension: string) => {
|
|
||||||
try {
|
|
||||||
const response = await fetch('/api/dimensions/popular', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({ dimension })
|
|
||||||
});
|
|
||||||
const data = await response.json();
|
|
||||||
if (!response.ok || !data.success) {
|
|
||||||
throw new Error(data.error || 'Failed to toggle dimension');
|
|
||||||
}
|
|
||||||
await fetchDimensions();
|
|
||||||
onDataChanged?.();
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error toggling lock:', error);
|
|
||||||
alert('Failed to update lock state.');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDeleteDimension = async (dimension: string) => {
|
const handleDeleteDimension = async (dimension: string) => {
|
||||||
setDeletingDimension(dimension);
|
setDeletingDimension(dimension);
|
||||||
@@ -616,7 +598,6 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{sortedDimensions.map((dimension) => {
|
{sortedDimensions.map((dimension) => {
|
||||||
const isLocked = dimension.isPriority;
|
|
||||||
const isDragTarget = dragHoverDimension === dimension.dimension;
|
const isDragTarget = dragHoverDimension === dimension.dimension;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -637,7 +618,7 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
|
|||||||
onDrop={(event) => handleNodeDropOnDimension(event, dimension.dimension)}
|
onDrop={(event) => handleNodeDropOnDimension(event, dimension.dimension)}
|
||||||
style={{
|
style={{
|
||||||
background: isDragTarget ? 'rgba(34, 197, 94, 0.05)' : 'transparent',
|
background: isDragTarget ? 'rgba(34, 197, 94, 0.05)' : 'transparent',
|
||||||
borderLeft: isLocked ? '2px solid #22c55e' : '2px solid transparent',
|
borderLeft: '2px solid transparent',
|
||||||
borderRadius: '6px',
|
borderRadius: '6px',
|
||||||
padding: '12px 14px',
|
padding: '12px 14px',
|
||||||
textAlign: 'left',
|
textAlign: 'left',
|
||||||
@@ -664,7 +645,7 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
|
|||||||
width: '28px',
|
width: '28px',
|
||||||
height: '28px',
|
height: '28px',
|
||||||
borderRadius: '6px',
|
borderRadius: '6px',
|
||||||
background: isLocked ? 'rgba(34, 197, 94, 0.08)' : 'rgba(255, 255, 255, 0.03)',
|
background: 'rgba(255, 255, 255, 0.03)',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
@@ -673,7 +654,7 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
|
|||||||
<DynamicIcon
|
<DynamicIcon
|
||||||
name={dimensionIcons[dimension.dimension] || 'Folder'}
|
name={dimensionIcons[dimension.dimension] || 'Folder'}
|
||||||
size={14}
|
size={14}
|
||||||
style={{ color: isLocked ? '#22c55e' : '#555' }}
|
style={{ color: '#555' }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -682,7 +663,7 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
|
|||||||
<div style={{
|
<div style={{
|
||||||
fontSize: '13px',
|
fontSize: '13px',
|
||||||
fontWeight: 500,
|
fontWeight: 500,
|
||||||
color: isLocked ? '#f0f0f0' : '#999',
|
color: '#999',
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
textOverflow: 'ellipsis',
|
textOverflow: 'ellipsis',
|
||||||
@@ -708,7 +689,7 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
|
|||||||
<span style={{
|
<span style={{
|
||||||
fontSize: '11px',
|
fontSize: '11px',
|
||||||
fontWeight: 500,
|
fontWeight: 500,
|
||||||
color: isLocked ? '#22c55e' : '#444',
|
color: '#444',
|
||||||
fontFamily: 'monospace',
|
fontFamily: 'monospace',
|
||||||
flexShrink: 0
|
flexShrink: 0
|
||||||
}}>
|
}}>
|
||||||
@@ -744,30 +725,6 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
|
|||||||
>
|
>
|
||||||
<Edit2 size={12} />
|
<Edit2 size={12} />
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
handleToggleLock(dimension.dimension);
|
|
||||||
}}
|
|
||||||
title={isLocked ? 'Unlock' : 'Lock'}
|
|
||||||
style={{
|
|
||||||
background: 'transparent',
|
|
||||||
border: 'none',
|
|
||||||
borderRadius: '4px',
|
|
||||||
width: '22px',
|
|
||||||
height: '22px',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
cursor: 'pointer',
|
|
||||||
color: isLocked ? '#22c55e' : '#666',
|
|
||||||
transition: 'color 0.1s ease'
|
|
||||||
}}
|
|
||||||
onMouseEnter={(e) => { if (!isLocked) e.currentTarget.style.color = '#22c55e'; }}
|
|
||||||
onMouseLeave={(e) => { if (!isLocked) e.currentTarget.style.color = '#666'; }}
|
|
||||||
>
|
|
||||||
{isLocked ? <Check size={12} /> : <Lock size={12} />}
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@@ -1740,7 +1697,7 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
|
|||||||
width: '32px',
|
width: '32px',
|
||||||
height: '32px',
|
height: '32px',
|
||||||
borderRadius: '8px',
|
borderRadius: '8px',
|
||||||
background: editingDimensionModal.isPriority ? 'rgba(34, 197, 94, 0.1)' : '#111',
|
background: '#111',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center'
|
justifyContent: 'center'
|
||||||
@@ -1748,7 +1705,7 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
|
|||||||
<DynamicIcon
|
<DynamicIcon
|
||||||
name={editModalIcon}
|
name={editModalIcon}
|
||||||
size={16}
|
size={16}
|
||||||
style={{ color: editingDimensionModal.isPriority ? '#22c55e' : '#888' }}
|
style={{ color: '#888' }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -1761,7 +1718,7 @@ export default function FolderViewOverlay({ onClose, onNodeOpen, refreshToken, o
|
|||||||
</div>
|
</div>
|
||||||
<div style={{
|
<div style={{
|
||||||
fontSize: '13px',
|
fontSize: '13px',
|
||||||
color: editingDimensionModal.isPriority ? '#22c55e' : '#888'
|
color: '#888'
|
||||||
}}>
|
}}>
|
||||||
{editingDimensionModal.dimension}
|
{editingDimensionModal.dimension}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user