From bb34e56be02a89888634f9b86958a9e81a1ba501 Mon Sep 17 00:00:00 2001 From: lukas-heiligenbrunner Date: Fri, 19 Jan 2024 20:00:10 +0100 Subject: [PATCH] add providers per page show only 10 packages new page for all packages --- frontend/lib/api/packages.dart | 5 +- frontend/lib/components/api/APIBuilder.dart | 37 +--- .../components/dashboard/recent_builds.dart | 7 - .../components/dashboard/your_packages.dart | 122 ++---------- frontend/lib/components/packages_table.dart | 111 +++++++++++ frontend/lib/components/routing/router.dart | 5 + frontend/lib/main.dart | 42 ++--- frontend/lib/providers/packages_provider.dart | 11 +- frontend/lib/screens/build_screen.dart | 98 +++++----- frontend/lib/screens/builds_screen.dart | 59 +++--- frontend/lib/screens/dashboard_screen.dart | 118 ++++++------ frontend/lib/screens/package_screen.dart | 175 +++++++++--------- frontend/lib/screens/packages_screen.dart | 56 ++++++ 13 files changed, 462 insertions(+), 384 deletions(-) create mode 100644 frontend/lib/components/packages_table.dart create mode 100644 frontend/lib/screens/packages_screen.dart diff --git a/frontend/lib/api/packages.dart b/frontend/lib/api/packages.dart index 04c01ad..5d9010d 100644 --- a/frontend/lib/api/packages.dart +++ b/frontend/lib/api/packages.dart @@ -2,8 +2,9 @@ import '../models/package.dart'; import 'api_client.dart'; extension PackagesAPI on ApiClient { - Future> listPackages() async { - final resp = await getRawClient().get("/packages/list"); + Future> listPackages({int? limit}) async { + final resp = await getRawClient() + .get("/packages/list", queryParameters: {'limit': limit}); final responseObject = resp.data as List; final List packages = diff --git a/frontend/lib/components/api/APIBuilder.dart b/frontend/lib/components/api/APIBuilder.dart index 7841135..f605122 100644 --- a/frontend/lib/components/api/APIBuilder.dart +++ b/frontend/lib/components/api/APIBuilder.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:visibility_detector/visibility_detector.dart'; import '../../providers/BaseProvider.dart'; @@ -26,7 +25,6 @@ class APIBuilder extends StatefulWidget { class _APIBuilderState extends State> { Timer? timer; - bool visible = true; @override void initState() { @@ -35,10 +33,8 @@ class _APIBuilderState if (widget.interval != null) { timer = Timer.periodic(widget.interval!, (Timer t) { - if (visible) { - Provider.of(context, listen: false) - .refresh(context, dto: widget.dto); - } + Provider.of(context, listen: false) + .refresh(context, dto: widget.dto); }); } } @@ -53,30 +49,15 @@ class _APIBuilderState Widget build(BuildContext context) { final Future fut = Provider.of(context).data as Future; - return VisibilityDetector( - key: widget.key ?? const Key("APIBuilder"), - onVisibilityChanged: (visibilityInfo) { - var visiblePercentage = visibilityInfo.visibleFraction * 100; - - if (mounted) { - setState(() { - visible = visiblePercentage != 0; - }); + return FutureBuilder( + future: fut, + builder: (context, snapshot) { + if (snapshot.hasData) { + return widget.onData(snapshot.data!); + } else { + return widget.onLoad(); } - - debugPrint( - 'Widget ${visibilityInfo.key} is ${visiblePercentage}% visible'); }, - child: FutureBuilder( - future: fut, - builder: (context, snapshot) { - if (snapshot.hasData) { - return widget.onData(snapshot.data!); - } else { - return widget.onLoad(); - } - }, - ), ); } } diff --git a/frontend/lib/components/dashboard/recent_builds.dart b/frontend/lib/components/dashboard/recent_builds.dart index fbd55a0..07dc1ef 100644 --- a/frontend/lib/components/dashboard/recent_builds.dart +++ b/frontend/lib/components/dashboard/recent_builds.dart @@ -1,16 +1,9 @@ -import 'dart:async'; - -import 'package:aurcache/api/builds.dart'; import 'package:aurcache/components/builds_table.dart'; import 'package:aurcache/models/build.dart'; -import 'package:aurcache/components/dashboard/your_packages.dart'; import 'package:aurcache/components/api/APIBuilder.dart'; import 'package:aurcache/providers/builds_provider.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import 'package:provider/provider.dart'; - -import '../../api/API.dart'; import '../../constants/color_constants.dart'; class RecentBuilds extends StatefulWidget { diff --git a/frontend/lib/components/dashboard/your_packages.dart b/frontend/lib/components/dashboard/your_packages.dart index 3c610c6..6dd0251 100644 --- a/frontend/lib/components/dashboard/your_packages.dart +++ b/frontend/lib/components/dashboard/your_packages.dart @@ -1,18 +1,10 @@ -import 'dart:async'; - -import 'package:aurcache/api/packages.dart'; import 'package:aurcache/components/api/APIBuilder.dart'; +import 'package:aurcache/components/packages_table.dart'; import 'package:aurcache/providers/packages_provider.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import 'package:provider/provider.dart'; - -import '../../api/API.dart'; import '../../constants/color_constants.dart'; import '../../models/package.dart'; -import '../../providers/builds_provider.dart'; -import '../../providers/stats_provider.dart'; -import '../confirm_popup.dart'; class YourPackages extends StatefulWidget { const YourPackages({ @@ -39,113 +31,33 @@ class _YourPackagesState extends State { "Your Packages", style: Theme.of(context).textTheme.subtitle1, ), - SingleChildScrollView( - //scrollDirection: Axis.horizontal, - child: SizedBox( + Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + SizedBox( width: double.infinity, - child: APIBuilder, Object>( - key: Key("Packages on dashboard"), + child: APIBuilder, PackagesDTO>( + key: const Key("Packages on dashboard"), interval: const Duration(seconds: 10), + dto: PackagesDTO(limit: 10), onData: (data) { - return DataTable( - horizontalMargin: 0, - columnSpacing: defaultPadding, - columns: const [ - DataColumn( - label: Text("Package ID"), - ), - DataColumn( - label: Text("Package Name"), - ), - DataColumn( - label: Text("Version"), - ), - DataColumn( - label: Text("Up-To-Date"), - ), - DataColumn( - label: Text("Status"), - ), - DataColumn( - label: Text("Action"), - ), - ], - rows: data - .map((e) => buildDataRow(e)) - .toList(growable: false)); + return PackagesTable(data: data); }, onLoad: () => const Text("No data"), ), ), - ), + ElevatedButton( + onPressed: () { + context.push("/packages"); + }, + child: Text( + "List all Packages", + style: TextStyle(color: Colors.white.withOpacity(0.8)), + ), + ) + ]), ], ), ); } - - DataRow buildDataRow(Package package) { - return DataRow( - cells: [ - DataCell(Text(package.id.toString())), - DataCell(Text(package.name)), - DataCell(Text(package.latest_version.toString())), - DataCell(IconButton( - icon: Icon( - package.outofdate ? Icons.update : Icons.verified, - color: package.outofdate ? Color(0xFF6B43A4) : Color(0xFF0A6900), - ), - onPressed: package.outofdate - ? () { - // todo open build info with logs - } - : null, - )), - DataCell(IconButton( - icon: Icon( - switchSuccessIcon(package.status), - color: switchSuccessColor(package.status), - ), - onPressed: () { - //context.push("/build/${package.latest_version_id}"); - }, - )), - DataCell( - Row( - children: [ - TextButton( - child: const Text('View', style: TextStyle(color: greenColor)), - onPressed: () { - context.push("/package/${package.id}"); - }, - ), - const SizedBox( - width: 6, - ), - TextButton( - child: const Text("Delete", - style: TextStyle(color: Colors.redAccent)), - onPressed: () async { - final confirmResult = - await showDeleteConfirmationDialog(context); - if (!confirmResult) return; - - final succ = await API.deletePackage(package.id); - if (succ) { - Provider.of(context, listen: false) - .refresh(context); - Provider.of(context, listen: false) - .refresh(context); - Provider.of(context, listen: false) - .refresh(context); - } - }, - ), - ], - ), - ), - ], - ); - } } IconData switchSuccessIcon(int status) { diff --git a/frontend/lib/components/packages_table.dart b/frontend/lib/components/packages_table.dart new file mode 100644 index 0000000..0e36ebb --- /dev/null +++ b/frontend/lib/components/packages_table.dart @@ -0,0 +1,111 @@ +import 'package:aurcache/api/packages.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:provider/provider.dart'; + +import '../api/API.dart'; +import '../constants/color_constants.dart'; +import '../models/package.dart'; +import '../providers/builds_provider.dart'; +import '../providers/packages_provider.dart'; +import '../providers/stats_provider.dart'; +import 'confirm_popup.dart'; +import 'dashboard/your_packages.dart'; + +class PackagesTable extends StatelessWidget { + const PackagesTable({super.key, required this.data}); + final List data; + + @override + Widget build(BuildContext context) { + return DataTable( + horizontalMargin: 0, + columnSpacing: defaultPadding, + columns: const [ + DataColumn( + label: Text("Package ID"), + ), + DataColumn( + label: Text("Package Name"), + ), + DataColumn( + label: Text("Version"), + ), + DataColumn( + label: Text("Up-To-Date"), + ), + DataColumn( + label: Text("Status"), + ), + DataColumn( + label: Text("Action"), + ), + ], + rows: + data.map((e) => buildDataRow(e, context)).toList(growable: false)); + } + + DataRow buildDataRow(Package package, BuildContext context) { + return DataRow( + cells: [ + DataCell(Text(package.id.toString())), + DataCell(Text(package.name)), + DataCell(Text(package.latest_version.toString())), + DataCell(IconButton( + icon: Icon( + package.outofdate ? Icons.update : Icons.verified, + color: package.outofdate ? Color(0xFF6B43A4) : Color(0xFF0A6900), + ), + onPressed: package.outofdate + ? () { + // todo open build info with logs + } + : null, + )), + DataCell(IconButton( + icon: Icon( + switchSuccessIcon(package.status), + color: switchSuccessColor(package.status), + ), + onPressed: () { + //context.push("/build/${package.latest_version_id}"); + }, + )), + DataCell( + Row( + children: [ + TextButton( + child: const Text('View', style: TextStyle(color: greenColor)), + onPressed: () { + context.push("/package/${package.id}"); + }, + ), + const SizedBox( + width: 6, + ), + TextButton( + child: const Text("Delete", + style: TextStyle(color: Colors.redAccent)), + onPressed: () async { + final confirmResult = + await showDeleteConfirmationDialog(context); + if (!confirmResult) return; + + final succ = await API.deletePackage(package.id); + if (succ) { + Provider.of(context, listen: false) + .refresh(context); + Provider.of(context, listen: false) + .refresh(context); + Provider.of(context, listen: false) + .refresh(context); + } + }, + ), + ], + ), + ), + ], + ); + } +} diff --git a/frontend/lib/components/routing/router.dart b/frontend/lib/components/routing/router.dart index 752b534..7fcb72d 100644 --- a/frontend/lib/components/routing/router.dart +++ b/frontend/lib/components/routing/router.dart @@ -3,6 +3,7 @@ import 'package:aurcache/screens/builds_screen.dart'; import 'package:aurcache/screens/dashboard_screen.dart'; import 'package:aurcache/components/routing/menu_shell.dart'; import 'package:aurcache/screens/package_screen.dart'; +import 'package:aurcache/screens/packages_screen.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; @@ -35,6 +36,10 @@ final appRouter = GoRouter( path: '/builds', builder: (context, state) => const BuildsScreen(), ), + GoRoute( + path: '/packages', + builder: (context, state) => const PackagesScreen(), + ), GoRoute( path: '/package/:id', builder: (context, state) { diff --git a/frontend/lib/main.dart b/frontend/lib/main.dart index 57ef57e..8d16635 100644 --- a/frontend/lib/main.dart +++ b/frontend/lib/main.dart @@ -1,13 +1,7 @@ import 'package:aurcache/components/routing/router.dart'; -import 'package:aurcache/providers/build_provider.dart'; -import 'package:aurcache/providers/builds_provider.dart'; -import 'package:aurcache/providers/package_provider.dart'; -import 'package:aurcache/providers/packages_provider.dart'; -import 'package:aurcache/providers/stats_provider.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:provider/provider.dart'; import 'constants/color_constants.dart'; void main() { @@ -20,30 +14,18 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - return MultiProvider( - providers: [ - ChangeNotifierProvider(create: (_) => StatsProvider()), - ChangeNotifierProvider( - create: (_) => PackagesProvider()), - ChangeNotifierProvider(create: (_) => BuildsProvider()), - ChangeNotifierProvider( - create: (_) => PackageProvider()), - ChangeNotifierProvider(create: (_) => BuildProvider()), - ], - child: MaterialApp.router( - routerConfig: appRouter, - debugShowCheckedModeBanner: false, - title: 'AURCache', - theme: ThemeData.dark().copyWith( - appBarTheme: - const AppBarTheme(backgroundColor: bgColor, elevation: 0), - scaffoldBackgroundColor: bgColor, - primaryColor: greenColor, - dialogBackgroundColor: secondaryColor, - textTheme: GoogleFonts.openSansTextTheme(Theme.of(context).textTheme) - .apply(bodyColor: Colors.white), - canvasColor: secondaryColor, - ), + return MaterialApp.router( + routerConfig: appRouter, + debugShowCheckedModeBanner: false, + title: 'AURCache', + theme: ThemeData.dark().copyWith( + appBarTheme: const AppBarTheme(backgroundColor: bgColor, elevation: 0), + scaffoldBackgroundColor: bgColor, + primaryColor: greenColor, + dialogBackgroundColor: secondaryColor, + textTheme: GoogleFonts.openSansTextTheme(Theme.of(context).textTheme) + .apply(bodyColor: Colors.white), + canvasColor: secondaryColor, ), ); } diff --git a/frontend/lib/providers/packages_provider.dart b/frontend/lib/providers/packages_provider.dart index a7b3cb4..de9b171 100644 --- a/frontend/lib/providers/packages_provider.dart +++ b/frontend/lib/providers/packages_provider.dart @@ -2,10 +2,17 @@ import 'package:aurcache/api/packages.dart'; import 'package:aurcache/providers/BaseProvider.dart'; import '../api/API.dart'; +import '../models/package.dart'; -class PackagesProvider extends BaseProvider { +class PackagesDTO { + final int limit; + + PackagesDTO({required this.limit}); +} + +class PackagesProvider extends BaseProvider, PackagesDTO> { @override loadFuture(context, {dto}) { - data = API.listPackages(); + data = API.listPackages(limit: dto?.limit); } } diff --git a/frontend/lib/screens/build_screen.dart b/frontend/lib/screens/build_screen.dart index 47e58d8..f23008f 100644 --- a/frontend/lib/screens/build_screen.dart +++ b/frontend/lib/screens/build_screen.dart @@ -5,6 +5,7 @@ import 'package:aurcache/providers/build_provider.dart'; import 'package:aurcache/utils/time_formatter.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:provider/provider.dart'; import '../components/dashboard/your_packages.dart'; @@ -21,54 +22,59 @@ class _BuildScreenState extends State { @override Widget build(BuildContext context) { return Scaffold( - body: APIBuilder( - key: const Key("Build on seperate page"), - dto: BuildDTO(buildID: widget.buildID), - interval: const Duration(seconds: 10), - onLoad: () => const Text("loading"), - onData: (buildData) { - final start_time = DateTime.fromMillisecondsSinceEpoch( - (buildData.start_time ?? 0) * 1000); + body: MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => BuildProvider()), + ], + child: APIBuilder( + key: const Key("Build on seperate page"), + dto: BuildDTO(buildID: widget.buildID), + interval: const Duration(seconds: 10), + onLoad: () => const Text("loading"), + onData: (buildData) { + final start_time = DateTime.fromMillisecondsSinceEpoch( + (buildData.start_time ?? 0) * 1000); - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - const SizedBox( - width: 10, - ), - IconButton( - icon: Icon( - switchSuccessIcon(buildData.status), - color: switchSuccessColor(buildData.status), + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const SizedBox( + width: 10, ), - onPressed: () { - context.replace("/build/${buildData.id}"); - }, - ), - const SizedBox( - width: 10, - ), - Text( - buildData.pkg_name, - style: const TextStyle(fontWeight: FontWeight.bold), - ), - const SizedBox( - width: 10, - ), - Text("triggered ${start_time.readableDuration()}") - ], - ), - const SizedBox( - height: 15, - ), - _buildPage(buildData) - ], - ); - }), + IconButton( + icon: Icon( + switchSuccessIcon(buildData.status), + color: switchSuccessColor(buildData.status), + ), + onPressed: () { + context.replace("/build/${buildData.id}"); + }, + ), + const SizedBox( + width: 10, + ), + Text( + buildData.pkg_name, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox( + width: 10, + ), + Text("triggered ${start_time.readableDuration()}") + ], + ), + const SizedBox( + height: 15, + ), + _buildPage(buildData) + ], + ); + }), + ), appBar: AppBar(), ); } diff --git a/frontend/lib/screens/builds_screen.dart b/frontend/lib/screens/builds_screen.dart index 471791e..7231e31 100644 --- a/frontend/lib/screens/builds_screen.dart +++ b/frontend/lib/screens/builds_screen.dart @@ -2,6 +2,7 @@ import 'package:aurcache/components/builds_table.dart'; import 'package:aurcache/components/api/APIBuilder.dart'; import 'package:aurcache/providers/builds_provider.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import '../constants/color_constants.dart'; import '../models/build.dart'; @@ -12,33 +13,39 @@ class BuildsScreen extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), - body: Padding( - padding: const EdgeInsets.all(defaultPadding), - child: Container( + body: MultiProvider( + providers: [ + ChangeNotifierProvider( + create: (_) => BuildsProvider()), + ], + child: Padding( padding: const EdgeInsets.all(defaultPadding), - decoration: const BoxDecoration( - color: secondaryColor, - borderRadius: BorderRadius.all(Radius.circular(10)), - ), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "All Builds", - style: Theme.of(context).textTheme.subtitle1, - ), - SizedBox( - width: double.infinity, - child: APIBuilder, Object>( - key: const Key("Builds on seperate screen"), - interval: const Duration(seconds: 10), - onLoad: () => const Text("no data"), - onData: (data) { - return BuildsTable(data: data); - }), - ) - ], + child: Container( + padding: const EdgeInsets.all(defaultPadding), + decoration: const BoxDecoration( + color: secondaryColor, + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "All Builds", + style: Theme.of(context).textTheme.subtitle1, + ), + SizedBox( + width: double.infinity, + child: APIBuilder, Object>( + key: const Key("Builds on seperate screen"), + interval: const Duration(seconds: 10), + onLoad: () => const Text("no data"), + onData: (data) { + return BuildsTable(data: data); + }), + ) + ], + ), ), ), ), diff --git a/frontend/lib/screens/dashboard_screen.dart b/frontend/lib/screens/dashboard_screen.dart index f0e7213..246003b 100644 --- a/frontend/lib/screens/dashboard_screen.dart +++ b/frontend/lib/screens/dashboard_screen.dart @@ -1,12 +1,12 @@ -import 'package:aurcache/api/statistics.dart'; import 'package:aurcache/components/api/APIBuilder.dart'; import 'package:aurcache/providers/stats_provider.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import '../api/API.dart'; import '../components/dashboard/header.dart'; import '../constants/color_constants.dart'; +import '../providers/builds_provider.dart'; +import '../providers/packages_provider.dart'; import '../utils/responsive.dart'; import '../models/stats.dart'; import '../components/dashboard/quick_info_banner.dart'; @@ -22,63 +22,71 @@ class DashboardScreen extends StatefulWidget { class _DashboardScreenState extends State { @override Widget build(BuildContext context) { - return APIBuilder( - interval: const Duration(seconds: 10), - onData: (stats) { - return SafeArea( - child: SingleChildScrollView( - child: Container( - padding: const EdgeInsets.all(defaultPadding), - child: Column( - children: [ - const Header(), - const SizedBox(height: defaultPadding), - QuickInfoBanner( - stats: stats, - ), - const SizedBox(height: defaultPadding), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - flex: 5, - child: Column( - children: [ - const YourPackages(), - const SizedBox(height: defaultPadding), - const RecentBuilds(), - if (Responsive.isMobile(context)) - const SizedBox(height: defaultPadding), - if (Responsive.isMobile(context)) - SidePanel( - nrbuilds: stats.total_builds, - nrfailedbuilds: stats.failed_builds, - nrActiveBuilds: stats.active_builds), - ], - ), - ), - if (!Responsive.isMobile(context)) - const SizedBox(width: defaultPadding), - // On Mobile means if the screen is less than 850 we dont want to show it - if (!Responsive.isMobile(context)) + return MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => StatsProvider()), + ChangeNotifierProvider( + create: (_) => PackagesProvider()), + ChangeNotifierProvider(create: (_) => BuildsProvider()), + ], + child: APIBuilder( + interval: const Duration(seconds: 10), + onData: (stats) { + return SafeArea( + child: SingleChildScrollView( + child: Container( + padding: const EdgeInsets.all(defaultPadding), + child: Column( + children: [ + const Header(), + const SizedBox(height: defaultPadding), + QuickInfoBanner( + stats: stats, + ), + const SizedBox(height: defaultPadding), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ Expanded( - flex: 2, - child: SidePanel( - nrbuilds: stats.total_builds, - nrfailedbuilds: stats.failed_builds, - nrActiveBuilds: stats.active_builds), + flex: 5, + child: Column( + children: [ + const YourPackages(), + const SizedBox(height: defaultPadding), + const RecentBuilds(), + if (Responsive.isMobile(context)) + const SizedBox(height: defaultPadding), + if (Responsive.isMobile(context)) + SidePanel( + nrbuilds: stats.total_builds, + nrfailedbuilds: stats.failed_builds, + nrActiveBuilds: stats.active_builds), + ], + ), ), - ], - ) - ], + if (!Responsive.isMobile(context)) + const SizedBox(width: defaultPadding), + // On Mobile means if the screen is less than 850 we dont want to show it + if (!Responsive.isMobile(context)) + Expanded( + flex: 2, + child: SidePanel( + nrbuilds: stats.total_builds, + nrfailedbuilds: stats.failed_builds, + nrActiveBuilds: stats.active_builds), + ), + ], + ) + ], + ), ), ), - ), - ); - }, - onLoad: () { - return Text("loading"); - }, + ); + }, + onLoad: () { + return Text("loading"); + }, + ), ); } } diff --git a/frontend/lib/screens/package_screen.dart b/frontend/lib/screens/package_screen.dart index f4b186d..11877d1 100644 --- a/frontend/lib/screens/package_screen.dart +++ b/frontend/lib/screens/package_screen.dart @@ -29,94 +29,103 @@ class _PackageScreenState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), - body: APIBuilder( - dto: PackageDTO(pkgID: widget.pkgID), - onLoad: () => const Text("loading"), - onData: (pkg) { - return Padding( - padding: const EdgeInsets.all(defaultPadding), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Container( - margin: const EdgeInsets.only(left: 15), - child: Text( - pkg.name, - style: const TextStyle(fontSize: 32), - ), - ), - Container( - margin: const EdgeInsets.only(right: 15), - child: ElevatedButton( - onPressed: () async { - final confirmResult = - await showDeleteConfirmationDialog(context); - if (!confirmResult) return; - - final succ = await API.deletePackage(pkg.id); - if (succ) { - context.pop(); - - Provider.of(context, - listen: false) - .refresh(context); - Provider.of(context, - listen: false) - .refresh(context); - Provider.of(context, listen: false) - .refresh(context); - } - }, - child: const Text( - "Delete", - style: TextStyle(color: Colors.redAccent), + body: MultiProvider( + providers: [ + ChangeNotifierProvider( + create: (_) => BuildsProvider()), + ChangeNotifierProvider( + create: (_) => PackageProvider()), + ], + child: APIBuilder( + dto: PackageDTO(pkgID: widget.pkgID), + onLoad: () => const Text("loading"), + onData: (pkg) { + return Padding( + padding: const EdgeInsets.all(defaultPadding), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + margin: const EdgeInsets.only(left: 15), + child: Text( + pkg.name, + style: const TextStyle(fontSize: 32), ), ), - ) - ], - ), - const SizedBox( - height: 25, - ), - Container( - padding: const EdgeInsets.all(defaultPadding), - decoration: const BoxDecoration( - color: secondaryColor, - borderRadius: BorderRadius.all(Radius.circular(10)), - ), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Builds of ${pkg.name}", - style: Theme.of(context).textTheme.subtitle1, - ), - SizedBox( - width: double.infinity, - child: APIBuilder, - BuildsDTO>( - key: const Key("Builds on Package info"), - dto: BuildsDTO(pkgID: pkg.id), - interval: const Duration(seconds: 5), - onData: (data) { - return BuildsTable(data: data); - }, - onLoad: () => const Text("no data"), + Container( + margin: const EdgeInsets.only(right: 15), + child: ElevatedButton( + onPressed: () async { + final confirmResult = + await showDeleteConfirmationDialog(context); + if (!confirmResult) return; + + final succ = await API.deletePackage(pkg.id); + if (succ) { + context.pop(); + + Provider.of(context, + listen: false) + .refresh(context); + Provider.of(context, + listen: false) + .refresh(context); + Provider.of(context, + listen: false) + .refresh(context); + } + }, + child: const Text( + "Delete", + style: TextStyle(color: Colors.redAccent), ), ), - ], - ), + ) + ], ), - ) - ], - ), - ); - }), + const SizedBox( + height: 25, + ), + Container( + padding: const EdgeInsets.all(defaultPadding), + decoration: const BoxDecoration( + color: secondaryColor, + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Builds of ${pkg.name}", + style: Theme.of(context).textTheme.subtitle1, + ), + SizedBox( + width: double.infinity, + child: APIBuilder, + BuildsDTO>( + key: const Key("Builds on Package info"), + dto: BuildsDTO(pkgID: pkg.id), + interval: const Duration(seconds: 5), + onData: (data) { + return BuildsTable(data: data); + }, + onLoad: () => const Text("no data"), + ), + ), + ], + ), + ), + ) + ], + ), + ); + }), + ), ); } } diff --git a/frontend/lib/screens/packages_screen.dart b/frontend/lib/screens/packages_screen.dart new file mode 100644 index 0000000..1c41ea0 --- /dev/null +++ b/frontend/lib/screens/packages_screen.dart @@ -0,0 +1,56 @@ +import 'package:aurcache/components/packages_table.dart'; +import 'package:aurcache/providers/packages_provider.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../components/api/APIBuilder.dart'; +import '../constants/color_constants.dart'; +import '../models/package.dart'; + +class PackagesScreen extends StatelessWidget { + const PackagesScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(), + body: MultiProvider( + providers: [ + ChangeNotifierProvider( + create: (_) => PackagesProvider()), + ], + child: Padding( + padding: const EdgeInsets.all(defaultPadding), + child: Container( + padding: const EdgeInsets.all(defaultPadding), + decoration: const BoxDecoration( + color: secondaryColor, + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "All Packages", + style: Theme.of(context).textTheme.subtitle1, + ), + SizedBox( + width: double.infinity, + child: APIBuilder, Object>( + key: const Key("Builds on seperate screen"), + interval: const Duration(seconds: 10), + onLoad: () => const Text("no data"), + onData: (data) { + return PackagesTable(data: data); + }), + ) + ], + ), + ), + ), + ), + ), + ); + } +}