From 6f32e1ff3856b6c49e021cbced84968fc08a27c2 Mon Sep 17 00:00:00 2001 From: Benimautner Date: Sat, 22 Jul 2023 22:55:25 +0200 Subject: [PATCH] renamed namespaces to projects, added basic project views --- lib/pages/home.dart | 6 +- lib/pages/list/list.dart | 2 +- lib/pages/project/overview.dart | 149 ++++++++++++++++++++++++++++++++ lib/pages/project/project.dart | 23 +++++ 4 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 lib/pages/project/overview.dart create mode 100644 lib/pages/project/project.dart diff --git a/lib/pages/home.dart b/lib/pages/home.dart index 181fd97..ba456b9 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -7,12 +7,14 @@ import 'package:provider/provider.dart'; import 'package:vikunja_app/components/AddDialog.dart'; import 'package:vikunja_app/components/ErrorDialog.dart'; +import 'package:vikunja_app/models/project.dart'; import 'package:vikunja_app/pages/namespace/namespace.dart'; import 'package:vikunja_app/pages/namespace/namespace_edit.dart'; import 'package:vikunja_app/pages/landing_page.dart'; import 'package:vikunja_app/global.dart'; import 'package:vikunja_app/models/namespace.dart'; import 'package:vikunja_app/pages/namespace/overview.dart'; +import 'package:vikunja_app/pages/project/overview.dart'; import 'package:vikunja_app/pages/settings.dart'; import 'package:vikunja_app/stores/list_store.dart'; @@ -31,13 +33,13 @@ class HomePageState extends State { create: (_) => new ListProvider(), child: LandingPage(), ), - NamespaceOverviewPage(), + ProjectOverviewPage(), SettingsPage() ]; List navbarItems = [ BottomNavigationBarItem(icon: Icon(Icons.home), label: "Home"), - BottomNavigationBarItem(icon: Icon(Icons.list), label: "Namespaces"), + BottomNavigationBarItem(icon: Icon(Icons.list), label: "Projects"), BottomNavigationBarItem(icon: Icon(Icons.settings), label: "Settings"), ]; diff --git a/lib/pages/list/list.dart b/lib/pages/list/list.dart index 06acc27..70c5f46 100644 --- a/lib/pages/list/list.dart +++ b/lib/pages/list/list.dart @@ -314,7 +314,7 @@ class _ListPageState extends State { createdBy: currentUser, done: false, bucketId: bucket?.id, - listId: _list.id, + projectId: _list.id, ); setState(() => _loadingTasks.add(newTask)); return Provider.of(context, listen: false) diff --git a/lib/pages/project/overview.dart b/lib/pages/project/overview.dart new file mode 100644 index 0000000..2bc6c6b --- /dev/null +++ b/lib/pages/project/overview.dart @@ -0,0 +1,149 @@ +import 'package:after_layout/after_layout.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:vikunja_app/pages/project/project.dart'; + +import '../../components/AddDialog.dart'; +import '../../components/ErrorDialog.dart'; +import '../../global.dart'; +import '../../models/project.dart'; + +class ProjectOverviewPage extends StatefulWidget { + @override + _ProjectOverviewPageState createState() => + new _ProjectOverviewPageState(); +} + +class _ProjectOverviewPageState extends State + with AfterLayoutMixin { + List _projects = []; + int _selectedDrawerIndex = -2, _previousDrawerIndex = -2; + bool _loading = true; + + Project? get _currentProject => + _selectedDrawerIndex >= -1 && _selectedDrawerIndex < _projects.length + ? _projects[_selectedDrawerIndex] + : null; + + @override + void afterFirstLayout(BuildContext context) { + _loadProjects(); + } + + Widget createProjectTile(Project project, int level){ + List children = addProjectChildren(project, level); + EdgeInsets insets = EdgeInsets.fromLTRB(level * 20 + 10, 0, 0, 0); + if(children.length == 0) { + return new ListTile( + leading: const Icon(Icons.folder), + title: new Text(project.title), + contentPadding: insets, + ); + } else { + return new ExpansionTile( + leading: const Icon(Icons.folder), + title: new Text(project.title), + children: children, + tilePadding: insets + //onTap: () => _onSelectItem(i), + ); + } + } + + List addProjectChildren(Project project, level) { + Iterable children = _projects.where((element) => element.parentProjectId == project.id); + List widgets = []; + children.forEach((element) {widgets.add(createProjectTile(element, level + 1));}); + return widgets; + } + + @override + Widget build(BuildContext context) { + List projectList = []; + _projects + .asMap() + .forEach((i, project) { + if(project.parentProjectId != 0) + return; + projectList.add(createProjectTile(project, 0)); + }); + + if(_selectedDrawerIndex > -1) { + return new WillPopScope( + child: ProjectPage(project: _projects[_selectedDrawerIndex]), + onWillPop: () async {setState(() { + _selectedDrawerIndex = -2; + }); + return false;}); + + } + + return Scaffold( + body: + this._loading + ? Center(child: CircularProgressIndicator()) + : + RefreshIndicator( + child: ListView( + padding: EdgeInsets.zero, + children: ListTile.divideTiles( + context: context, tiles: projectList) + .toList()), + onRefresh: _loadProjects, + ), + floatingActionButton: Builder( + builder: (context) => FloatingActionButton( + onPressed: () => _addProjectDialog(context), + child: const Icon(Icons.add))), + appBar: AppBar( + title: Text("Projects"), + ), + ); + } + + Future _loadProjects() { + return VikunjaGlobal.of(context).projectService.getAll().then((result) { + setState(() { + _loading = false; + if (result != null) _projects = result; + }); + }); + } + + _onSelectItem(int index) { + Navigator.push(context, + MaterialPageRoute( + builder: (buildContext) => ProjectPage( + project: _projects[index], + ),)); + //setState(() => _selectedDrawerIndex = index); + } + + _addProjectDialog(BuildContext context) { + showDialog( + context: context, + builder: (_) => AddDialog( + onAdd: (name) => _addProject(name, context), + decoration: new InputDecoration( + labelText: 'Project', hintText: 'eg. Personal Project'), + )); + } + + _addProject(String name, BuildContext context) { + final currentUser = VikunjaGlobal.of(context).currentUser; + if (currentUser == null) { + return; + } + + VikunjaGlobal.of(context) + .projectService + .create(Project(title: name, owner: currentUser)) + .then((_) { + _loadProjects(); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text('The project was created successfully!'), + )); + }).catchError((error) => showDialog( + context: context, builder: (context) => ErrorDialog(error: error))); + } +} diff --git a/lib/pages/project/project.dart b/lib/pages/project/project.dart new file mode 100644 index 0000000..ed2a624 --- /dev/null +++ b/lib/pages/project/project.dart @@ -0,0 +1,23 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import '../../models/project.dart'; + +class ProjectPage extends StatefulWidget { + final Project project; + + ProjectPage({required this.project}) + : super(key: Key(project.id.toString())); + + @override + _ProjectPageState createState() => new _ProjectPageState(); +} + +class _ProjectPageState extends State { + @override + Widget build(BuildContext context) { + // TODO: implement build + return Scaffold(); + } + +} \ No newline at end of file