Skip to content

Commit

Permalink
few stability changes
Browse files Browse the repository at this point in the history
  • Loading branch information
birdup000 committed Dec 28, 2024
1 parent a28106e commit c4aab54
Show file tree
Hide file tree
Showing 14 changed files with 170 additions and 141 deletions.
1 change: 0 additions & 1 deletion app/components/AIEnhancedRichTextEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import isHotkey from 'is-hotkey';
import { initializeAGiXT } from '../utils/agixt';
import { FormatButton } from './FormatButton';
import { toggleMark } from './editorUtils';
import AGiXT from 'agixt';

interface AIEnhancedRichTextEditorProps {
placeholder?: string;
Expand Down
75 changes: 47 additions & 28 deletions app/components/ModernTaskPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";

import React, { useState } from 'react';
import Modal from './ui/Modal';
import { DragDropContext, DropResult } from '@hello-pangea/dnd';
import { Task } from '../types/task';
import TaskPriorityMatrix from './TaskPriorityMatrix';
Expand All @@ -17,6 +18,7 @@ import { useKeyboardShortcuts } from '../hooks/useKeyboardShortcuts';
import LayoutSettingsPanel from './LayoutSettingsPanel';
import GroupingSettingsPanel from './GroupingSettingsPanel';
import GeminiConfig from './GeminiConfig';
import useLocalStorage from '../hooks/useLocalStorage';

interface ModernTaskPanelProps {
tasks: Task[];
Expand Down Expand Up @@ -54,12 +56,13 @@ const ModernTaskPanel: React.FC<ModernTaskPanelProps> = ({
lists,
}) => {
// State management
const [selectedTask, setSelectedTask] = useState<Task | null>(null);
const [selectedTask, setSelectedTask] = useState<Task | null | undefined>(undefined);
const [isEditorOpen, setIsEditorOpen] = useState(false);
const [isAGiXTConfigOpen, setIsAGiXTConfigOpen] = useState(false);
const [agixtConfig, setAgixtConfig] = useState({ backendUrl: '', authToken: '' });
const [agixtConfig, setAgixtConfig] = useLocalStorage<{ backendUrl: string; authToken: string }>('agixtConfig', { backendUrl: '', authToken: '' });
const [geminiConfig, setGeminiConfig] = useState({ apiKey: '', model: 'gemini-pro' });
const [isGeminiConfigOpen, setIsGeminiConfigOpen] = useState(false);
const [isNotesOpen, setIsNotesOpen] = useState(false);
const [currentView, setCurrentView] = useState<'board' | 'matrix'>('board');
const [layoutSettings, setLayoutSettings] = useState<LayoutSettings>({
selectedLayout: 'board',
Expand Down Expand Up @@ -112,18 +115,7 @@ const ModernTaskPanel: React.FC<ModernTaskPanelProps> = ({

if (source.droppableId === destination.droppableId) {
// Reorder within same status
const statusTasks = tasks.filter(t => t.status === source.droppableId);
const [movedTask] = statusTasks.splice(source.index, 1);
statusTasks.splice(destination.index, 0, movedTask);

const updatedTasks = tasks.map(t => {
if (t.status === source.droppableId) {
const reorderedTask = statusTasks.find(rt => rt.id === t.id);
return reorderedTask || t;
}
return t;
});

const updatedTasks = reorderTasksWithinStatus(tasks, source, destination);
onReorderTasks(updatedTasks);
} else {
// Move to different status
Expand All @@ -134,6 +126,20 @@ const ModernTaskPanel: React.FC<ModernTaskPanelProps> = ({
}
};

const reorderTasksWithinStatus = (tasks: Task[], source: any, destination: any): Task[] => {
const statusTasks = [...tasks.filter(t => t.status === source.droppableId)];
const [movedTask] = statusTasks.splice(source.index, 1);
statusTasks.splice(destination.index, 0, movedTask);

return tasks.map(t => {
if (t.status === source.droppableId) {
const reorderedTask = statusTasks.find(rt => rt.id === t.id);
return reorderedTask || t;
}
return t;
});
};

// Helper function to get grouped tasks
const getGroupedTasks = (status: 'todo' | 'in-progress' | 'done') => {
const filteredTasks = filteredAndSortedTasks().filter(task => task.status === status);
Expand Down Expand Up @@ -268,6 +274,7 @@ const ModernTaskPanel: React.FC<ModernTaskPanelProps> = ({
onDeleteTask={onDeleteTask}
onReorderTasks={onReorderTasks}
listId="default"
agixtConfig={agixtConfig}
/>
</div>
</div>
Expand All @@ -294,6 +301,7 @@ const ModernTaskPanel: React.FC<ModernTaskPanelProps> = ({
onDeleteTask={onDeleteTask}
onReorderTasks={onReorderTasks}
listId="default"
agixtConfig={agixtConfig}
/>
</div>
</div>
Expand All @@ -320,6 +328,7 @@ const ModernTaskPanel: React.FC<ModernTaskPanelProps> = ({
onDeleteTask={onDeleteTask}
onReorderTasks={onReorderTasks}
listId="default"
agixtConfig={agixtConfig}
/>
</div>
</div>
Expand All @@ -341,7 +350,7 @@ const ModernTaskPanel: React.FC<ModernTaskPanelProps> = ({
onTaskUpdate={onUpdateTask}
onNewTask={onAddTask}
geminiApiKey={geminiConfig.apiKey}
selectedTask={selectedTask}
selectedTask={selectedTask ?? undefined}
agixtConfig={agixtConfig}
/>
)}
Expand All @@ -351,7 +360,7 @@ const ModernTaskPanel: React.FC<ModernTaskPanelProps> = ({
authToken={agixtConfig.authToken}
onTaskSuggestion={(suggestion) => {
const newTask: Task = {
id: Date.now().toString(),
id: crypto.randomUUID(),
title: suggestion.title || '',
description: suggestion.description || '',
priority: suggestion.priority || 'medium',
Expand All @@ -365,7 +374,14 @@ const ModernTaskPanel: React.FC<ModernTaskPanelProps> = ({
comments: [],
version: 1,
listId: lists[0]?.id || 'default',
dueDate: suggestion.dueDate,
tags: suggestion.tags,
};

if (lists && lists.length > 0) {
newTask.listId = lists[0].id;
}

onAddTask(newTask);
}}
onTaskOptimization={(taskIds) => {
Expand All @@ -375,7 +391,7 @@ const ModernTaskPanel: React.FC<ModernTaskPanelProps> = ({
onReorderTasks(optimizedTasks);
}}
tasks={tasks}
selectedTask={selectedTask}
selectedTask={selectedTask ?? null}
/>
)}
</div>
Expand All @@ -384,7 +400,7 @@ const ModernTaskPanel: React.FC<ModernTaskPanelProps> = ({

{/* Modals */}
{isLayoutSettingsOpen && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
<Modal onClose={() => setIsLayoutSettingsOpen(false)}>
<LayoutSettingsPanel
layoutSettings={layoutSettings}
onSave={(newSettings: LayoutSettings) => {
Expand All @@ -393,11 +409,11 @@ const ModernTaskPanel: React.FC<ModernTaskPanelProps> = ({
}}
onClose={() => setIsLayoutSettingsOpen(false)}
/>
</div>
</Modal>
)}

{isGroupingSettingsOpen && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
<Modal onClose={() => setIsGroupingSettingsOpen(false)}>
<GroupingSettingsPanel
groupingSettings={groupingSettings}
onSave={(newSettings: GroupingSettings) => {
Expand All @@ -406,35 +422,35 @@ const ModernTaskPanel: React.FC<ModernTaskPanelProps> = ({
}}
onClose={() => setIsGroupingSettingsOpen(false)}
/>
</div>
</Modal>
)}

{isAGiXTConfigOpen && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
<Modal onClose={() => setIsAGiXTConfigOpen(false)}>
<AGiXTConfig
onClose={() => setIsAGiXTConfigOpen(false)}
onSave={(config) => {
onSave={(config: { backendUrl: string; authToken: string }) => {
setAgixtConfig(config);
setIsAGiXTConfigOpen(false);
}}
/>
</div>
</Modal>
)}

{isGeminiConfigOpen && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
<Modal onClose={() => setIsGeminiConfigOpen(false)}>
<GeminiConfig
onClose={() => setIsGeminiConfigOpen(false)}
onSave={(config) => {
setGeminiConfig(config);
setIsGeminiConfigOpen(false);
}}
/>
</div>
</Modal>
)}

{isEditorOpen && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center">
<Modal onClose={() => setIsEditorOpen(false)}>
<TaskForm
onSubmit={(task) => {
onAddTask(task);
Expand All @@ -443,7 +459,7 @@ const ModernTaskPanel: React.FC<ModernTaskPanelProps> = ({
onCancel={() => setIsEditorOpen(false)}
lists={lists}
/>
</div>
</Modal>
)}

{selectedTask && (
Expand All @@ -453,6 +469,9 @@ const ModernTaskPanel: React.FC<ModernTaskPanelProps> = ({
onUpdateTask={onUpdateTask}
allTasks={tasks}
className="fixed inset-y-0 right-0 w-[32rem] shadow-xl"
geminiConfig={geminiConfig}
agixtConfig={agixtConfig}
onAddTask={onAddTask}
/>
)}
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/components/RichTextEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import React, { useMemo, useCallback } from 'react';
import { createEditor, Descendant, Editor, Element as SlateElement, Text, Node as SlateNode } from 'slate';
import { Slate, Editable, withReact, RenderElementProps, RenderLeafProps } from 'slate-react';
import { CustomEditor, initialValue as defaultInitialValue, HOTKEYS } from './EditorConfig';
import { CustomEditor, HOTKEYS } from './EditorConfig';
import isHotkey from 'is-hotkey';

interface RichTextEditorProps {
Expand Down
21 changes: 12 additions & 9 deletions app/components/TaskCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ export interface TaskCardProps {
onClick?: () => void;
onDelete?: () => void;
onUpdateTask?: (task: Task) => void;
agixtConfig?: { backendUrl: string; authToken: string };
}

export const TaskCard: React.FC<TaskCardProps> = ({ task, index = 0, onClick, onDelete, onUpdateTask }) => {
export const TaskCard: React.FC<TaskCardProps> = ({ task, index = 0, onClick, onDelete, onUpdateTask, agixtConfig }) => {
const [agixtError, setAgixtError] = useState<string | null>(null);

if (!task) {
Expand Down Expand Up @@ -64,15 +65,17 @@ export const TaskCard: React.FC<TaskCardProps> = ({ task, index = 0, onClick, on

const handleGenerateSubtasksClick = async (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
const agixtApiUri = localStorage.getItem('agixtapi') || '';
const agixtApiKey = localStorage.getItem('agixtkey') || '';
const selectedAgent = localStorage.getItem('selectedAgent') || 'OpenAI';
if (agixtApiUri && agixtApiKey && selectedAgent && task) {
const updatedTask = await handleGenerateSubtasks(task, selectedAgent, agixtApiUri, agixtApiKey);
if (updatedTask) {
onUpdateTask?.(updatedTask);
if (task && onUpdateTask && agixtConfig && agixtConfig.backendUrl && agixtConfig.authToken) {
const selectedAgent = localStorage.getItem('selectedAgent') || 'OpenAI';
if (selectedAgent) {
const updatedTask = await handleGenerateSubtasks(task, selectedAgent, agixtConfig.backendUrl, agixtConfig.authToken);
if (updatedTask) {
onUpdateTask(updatedTask);
}
} else {
setAgixtError("AGiXT API URI, API Key, or agent not set.");
}
} else {
} else if (task && onUpdateTask) {
setAgixtError("AGiXT API URI, API Key, or agent not set.");
}
};
Expand Down
59 changes: 9 additions & 50 deletions app/components/TaskDetailsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import React from 'react';
import { Task } from '../types/task';
import NotesEditor from './NotesEditor';
import TaskProgress from './TaskProgress';
import TaskComments from './TaskComments';
import TaskAttachments from './TaskAttachments';
import TaskTimer from './TaskTimer';
Expand All @@ -19,9 +18,11 @@ interface TaskDetailsPanelProps {
task: Task | null;
onClose: () => void;
onUpdateTask: (task: Task) => void;
onAddTask?: (task: Task) => void;
onAddTask: (task: Task) => void;
allTasks: Task[];
className?: string;
geminiConfig: { apiKey: string; model: string };
agixtConfig: { backendUrl: string; authToken: string };
}

const TaskDetailsPanel: React.FC<TaskDetailsPanelProps> = ({
Expand All @@ -30,6 +31,9 @@ const TaskDetailsPanel: React.FC<TaskDetailsPanelProps> = ({
onUpdateTask,
allTasks,
className = '',
geminiConfig,
agixtConfig,
onAddTask,
}) => {
if (!task) return null;

Expand Down Expand Up @@ -386,57 +390,12 @@ const TaskDetailsPanel: React.FC<TaskDetailsPanelProps> = ({
<VoiceTaskAssistant
onTaskUpdate={onUpdateTask}
selectedTask={task}
geminiApiKey={geminiConfig.apiKey}
agixtConfig={agixtConfig}
onNewTask={onAddTask}
/>
</div>

<div className="border-t border-gray-700 pt-4">
<h4 className="text-sm font-medium text-gray-300 mb-4 flex items-center gap-2">
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
</svg>
Notes
</h4>
<div className="space-y-4">
<NotesEditor
initialNotes={task.notes || []}
tasks={allTasks}
onLinkTask={(noteId, taskId) => {
const updatedNotes = task.notes?.map(note =>
note.id === noteId
? { ...note, linkedTaskIds: [...(note.linkedTaskIds || []), taskId] }
: note
);
onUpdateTask({
...task,
notes: updatedNotes,
activityLog: [
...task.activityLog,
{
id: Date.now().toString(),
taskId: task.id,
userId: 'current-user',
action: 'linked_note',
timestamp: new Date(),
},
],
});
}}
/>
<AIEnhancedRichTextEditor
initialContent={task.description}
onChange={(content) => onUpdateTask({
...task,
description: content,
updatedAt: new Date(),
})}
onCreateTask={(title, description) => {
// Handle task creation from AI suggestions
// This would typically be handled by the parent component
console.log('AI suggested new task:', { title, description });
}}
/>
</div>
</div>
</div>
</div>
);
Expand Down
5 changes: 4 additions & 1 deletion app/components/TaskList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface TaskListProps {
onDeleteTask: (task: Task) => void;
onReorderTasks: (tasks: Task[]) => void;
listId: string;
agixtConfig?: { backendUrl: string; authToken: string };
}

export const TaskList: React.FC<TaskListProps> = ({
Expand All @@ -23,7 +24,8 @@ export const TaskList: React.FC<TaskListProps> = ({
onTaskClick,
onDeleteTask,
onReorderTasks,
listId
listId,
agixtConfig
}) => {
return (
<div>
Expand All @@ -42,6 +44,7 @@ export const TaskList: React.FC<TaskListProps> = ({
onUpdateTask={onUpdateTask}
onClick={() => onTaskClick(task)}
onDelete={() => onDeleteTask(task)}
agixtConfig={agixtConfig ? agixtConfig : undefined}
/>
))}
{provided.placeholder}
Expand Down
Loading

0 comments on commit c4aab54

Please sign in to comment.