From 8923e79b2957976b3e74d3b803f1c10225a68d11 Mon Sep 17 00:00:00 2001 From: hunteraraujo Date: Mon, 18 Sep 2023 15:08:22 -0700 Subject: [PATCH] Refactor TaskView to Support Combined Data and Test Suite Detail View This commit introduces substantial improvements to the TaskView class to accommodate both tasks and test suites in a unified view. It also integrates the TestSuiteDetailView to display test suite details when a test suite is selected. Key Enhancements: 1. Modified the `initState` method to call `fetchAndCombineData()` from TaskViewModel, thereby populating the combined data source. 2. Replaced the ListView that was rendering tasks with a ListView that can render both tasks and test suites. 3. Introduced conditional rendering for TestSuiteDetailView when a test suite is selected. 4. Updated onTap actions to select and deselect tasks and test suites appropriately. 5. Moved to using a Stack layout to allow overlay of TestSuiteDetailView on top of the existing layout. This refactor enhances the TaskView's capabilities to manage and display both tasks and test suites, offering a more integrated user experience. --- frontend/lib/views/task/task_view.dart | 147 ++++++++++++++++--------- 1 file changed, 94 insertions(+), 53 deletions(-) diff --git a/frontend/lib/views/task/task_view.dart b/frontend/lib/views/task/task_view.dart index 73d64b48..a1d1aa62 100644 --- a/frontend/lib/views/task/task_view.dart +++ b/frontend/lib/views/task/task_view.dart @@ -1,8 +1,12 @@ +import 'package:auto_gpt_flutter_client/models/task.dart'; +import 'package:auto_gpt_flutter_client/models/test_suite.dart'; +import 'package:auto_gpt_flutter_client/viewmodels/api_settings_viewmodel.dart'; import 'package:auto_gpt_flutter_client/views/task/api_base_url_field.dart'; +import 'package:auto_gpt_flutter_client/views/task/test_suite_detail_view.dart'; +import 'package:auto_gpt_flutter_client/views/task/test_suite_list_tile.dart'; import 'package:flutter/material.dart'; import 'package:auto_gpt_flutter_client/viewmodels/task_viewmodel.dart'; import 'package:auto_gpt_flutter_client/viewmodels/chat_viewmodel.dart'; -import 'package:auto_gpt_flutter_client/viewmodels/api_settings_viewmodel.dart'; import 'package:auto_gpt_flutter_client/views/task/new_task_button.dart'; import 'package:auto_gpt_flutter_client/views/task/task_list_tile.dart'; import 'package:provider/provider.dart'; @@ -25,7 +29,7 @@ class _TaskViewState extends State { // Schedule the fetchTasks call for after the initial build WidgetsBinding.instance.addPostFrameCallback((_) { - widget.viewModel.fetchTasks(); + widget.viewModel.fetchAndCombineData(); _baseUrlController.text = Provider.of(context, listen: false).baseURL; }); @@ -33,64 +37,101 @@ class _TaskViewState extends State { @override Widget build(BuildContext context) { + // Combine tasks and test suites into a single list + final items = widget.viewModel.combinedDataSource; return Scaffold( backgroundColor: Colors.white, - body: Column( + body: Stack( children: [ - // Title and New Task button - Padding( - padding: const EdgeInsets.all(8.0), - child: NewTaskButton( - onPressed: () async { - // Update the current task ID and chats in ChatViewModel - final chatViewModel = - Provider.of(context, listen: false); - chatViewModel.clearCurrentTaskAndChats(); - widget.viewModel.deselectTask(); - print( - 'New Task button pressed, cleared current task ID and chats'); - }, - )), - // Task List - Expanded( - child: ListView.builder( - itemCount: widget.viewModel.tasks.length, - itemBuilder: (context, index) { - final task = widget.viewModel.tasks[index]; - return TaskListTile( - task: task, - onTap: () { - // Select the task in TaskViewModel - widget.viewModel.selectTask(task.id); - - // Update the current task ID in ChatViewModel - // TODO: Do we want to have a reference to chat view model in this class? - final chatViewModel = - Provider.of(context, listen: false); - chatViewModel.setCurrentTaskId(task.id); - - print('Task ${task.title} tapped'); - }, - onDelete: () { - // Delete the task in TaskViewModel - widget.viewModel.deleteTask(task.id); - // TODO: Do we want to have a reference to chat view model in this class? - final chatViewModel = - Provider.of(context, listen: false); - if (chatViewModel.currentTaskId == task.id) { + Column( + children: [ + // Title and New Task button + Padding( + padding: const EdgeInsets.all(8.0), + child: NewTaskButton( + onPressed: () async { + // Update the current task ID and chats in ChatViewModel + final chatViewModel = + Provider.of(context, listen: false); chatViewModel.clearCurrentTaskAndChats(); - } + widget.viewModel.deselectTask(); + print( + 'New Task button pressed, cleared current task ID and chats'); + }, + )), + // Task List + Expanded( + child: ListView.builder( + itemCount: items.length, + itemBuilder: (context, index) { + final item = items[index]; - print('Task ${task.title} delete button tapped'); + if (item is Task) { + return TaskListTile( + task: item, + onTap: () { + // Select the task in TaskViewModel + widget.viewModel.selectTask(item.id); + + // Update the current task ID in ChatViewModel + // TODO: Do we want to have a reference to chat view model in this class? + final chatViewModel = Provider.of( + context, + listen: false); + chatViewModel.setCurrentTaskId(item.id); + + print('Task ${item.title} tapped'); + }, + onDelete: () { + // Delete the task in TaskViewModel + widget.viewModel.deleteTask(item.id); + // TODO: Do we want to have a reference to chat view model in this class? + final chatViewModel = Provider.of( + context, + listen: false); + if (chatViewModel.currentTaskId == item.id) { + chatViewModel.clearCurrentTaskAndChats(); + } + + print('Task ${item.title} delete button tapped'); + }, + selected: item.id == widget.viewModel.selectedTask?.id, + ); + } else if (item is TestSuite) { + return TestSuiteListTile( + testSuite: item, + onTap: () { + // Navigate to the new view for this test suite + widget.viewModel.deselectTask(); + widget.viewModel.selectTestSuite(item); + // TODO: Do we want to have a reference to chat view model in this class? + Provider.of(context, listen: false) + .clearCurrentTaskAndChats(); + }, + ); + } else { + return const SizedBox + .shrink(); // return an empty widget if type is unknown + } }, - selected: task.id == widget.viewModel.selectedTask?.id, - ); - }, - ), + ), + ), + const SizedBox(height: 16), + ApiBaseUrlField(controller: _baseUrlController), + const SizedBox(height: 16), + ], ), - const SizedBox(height: 16), - ApiBaseUrlField(controller: _baseUrlController), - const SizedBox(height: 16), + if (widget.viewModel.selectedTestSuite != null) + Positioned( + top: 0, + left: 0, + right: 0, + bottom: 0, + child: TestSuiteDetailView( + testSuite: widget.viewModel.selectedTestSuite!, + viewModel: widget.viewModel, + ), + ), ], ), );