2
0
mirror of https://github.com/inventree/inventree-app.git synced 2025-04-28 05:26:47 +00:00

Add progress indicators to a bunch o' stuff

This commit is contained in:
Oliver Walters 2021-02-11 21:38:48 +11:00
parent dba45c7600
commit b1b85a33f8
8 changed files with 172 additions and 96 deletions

View File

@ -2,6 +2,7 @@
import 'package:InvenTree/api.dart'; import 'package:InvenTree/api.dart';
import 'package:InvenTree/inventree/part.dart'; import 'package:InvenTree/inventree/part.dart';
import 'package:InvenTree/preferences.dart'; import 'package:InvenTree/preferences.dart';
import 'package:InvenTree/widget/progress.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
@ -155,13 +156,16 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> {
child: Column( child: Column(
children: <Widget>[ children: <Widget>[
ListTile( ListTile(
title: Text("${category.name}"), title: Text("${category.name}",
style: TextStyle(fontWeight: FontWeight.bold)
),
subtitle: Text("${category.description}"), subtitle: Text("${category.description}"),
), ),
Divider(),
ListTile( ListTile(
title: Text(I18N.of(context).parentCategory), title: Text(I18N.of(context).parentCategory),
subtitle: Text("${category.parentpathstring}"), subtitle: Text("${category.parentpathstring}"),
leading: FaIcon(FontAwesomeIcons.sitemap), leading: FaIcon(FontAwesomeIcons.levelUpAlt),
onTap: () { onTap: () {
if (category.parentId < 0) { if (category.parentId < 0) {
Navigator.push(context, MaterialPageRoute(builder: (context) => CategoryDisplayWidget(null))); Navigator.push(context, MaterialPageRoute(builder: (context) => CategoryDisplayWidget(null)));
@ -204,37 +208,64 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> {
} }
List<Widget> detailTiles() { List<Widget> detailTiles() {
return <Widget>[ List<Widget> tiles = <Widget>[
getCategoryDescriptionCard(), getCategoryDescriptionCard(),
Divider(),
ListTile( ListTile(
title: Text( title: Text(
I18N.of(context).subcategories, I18N.of(context).subcategories,
style: TextStyle(fontWeight: FontWeight.bold) style: TextStyle(fontWeight: FontWeight.bold)
) )
), ),
SubcategoryList(_subcategories),
]; ];
if (loading) {
tiles.add(progressIndicator());
} else if (_subcategories.length == 0) {
tiles.add(ListTile(
title: Text("No Subcategories"),
subtitle: Text("No subcategories available")
));
} else {
tiles.add(SubcategoryList(_subcategories));
}
return tiles;
} }
List<Widget> partTiles() { List<Widget> partTiles() {
return <Widget>[ List<Widget> tiles = <Widget>[
getCategoryDescriptionCard(), getCategoryDescriptionCard(),
Divider(),
ListTile( ListTile(
title: Text( title: Text(
I18N.of(context).parts, I18N.of(context).parts,
style: TextStyle(fontWeight: FontWeight.bold) style: TextStyle(fontWeight: FontWeight.bold)
) )
), ),
PartList(_parts)
]; ];
if (loading) {
tiles.add(progressIndicator());
} else if (_parts.length == 0) {
tiles.add(ListTile(
title: Text("No Parts"),
subtitle: Text("No parts available in this category")
));
} else {
tiles.add(PartList(_parts));
}
return tiles;
} }
List<Widget> actionTiles() { List<Widget> actionTiles() {
List<Widget> tiles = [ List<Widget> tiles = [
getCategoryDescriptionCard() getCategoryDescriptionCard(),
ListTile(
title: Text(I18N.of(context).actions,
style: TextStyle(fontWeight: FontWeight.bold)
)
)
]; ];
// TODO - Actions! // TODO - Actions!

View File

@ -1,6 +1,7 @@
import 'package:InvenTree/api.dart'; import 'package:InvenTree/api.dart';
import 'package:InvenTree/inventree/stock.dart'; import 'package:InvenTree/inventree/stock.dart';
import 'package:InvenTree/preferences.dart'; import 'package:InvenTree/preferences.dart';
import 'package:InvenTree/widget/progress.dart';
import 'package:InvenTree/widget/refreshable_state.dart'; import 'package:InvenTree/widget/refreshable_state.dart';
import 'package:InvenTree/widget/fields.dart'; import 'package:InvenTree/widget/fields.dart';
@ -235,16 +236,25 @@ class _LocationDisplayState extends RefreshableState<LocationDisplayWidget> {
List<Widget> detailTiles() { List<Widget> detailTiles() {
List<Widget> tiles = [ List<Widget> tiles = [
locationDescriptionCard(), locationDescriptionCard(),
Divider(),
ListTile( ListTile(
title: Text( title: Text(
I18N.of(context).sublocations, I18N.of(context).sublocations,
style: TextStyle(fontWeight: FontWeight.bold) style: TextStyle(fontWeight: FontWeight.bold)
), ),
), ),
SublocationList(_sublocations)
]; ];
if (loading) {
tiles.add(progressIndicator());
} else if (_sublocations.length > 0) {
tiles.add(SublocationList(_sublocations));
} else {
tiles.add(ListTile(
title: Text("No Sublocations"),
subtitle: Text("No sublocations available")
));
}
return tiles; return tiles;
} }
@ -252,16 +262,25 @@ List<Widget> detailTiles() {
List<Widget> stockTiles() { List<Widget> stockTiles() {
List<Widget> tiles = [ List<Widget> tiles = [
locationDescriptionCard(), locationDescriptionCard(),
Divider(),
ListTile( ListTile(
title: Text( title: Text(
I18N.of(context).stockItems, I18N.of(context).stockItems,
style: TextStyle(fontWeight: FontWeight.bold) style: TextStyle(fontWeight: FontWeight.bold)
) )
), )
StockList(_items),
]; ];
if (loading) {
tiles.add(progressIndicator());
} else if (_items.length > 0) {
tiles.add(StockList(_items));
} else {
tiles.add(ListTile(
title: Text("No Stock Items"),
subtitle: Text("No stock items available in this location")
));
}
return tiles; return tiles;
} }

View File

@ -1,5 +1,6 @@
import 'dart:io'; import 'dart:io';
import 'package:InvenTree/widget/progress.dart';
import 'package:InvenTree/widget/snacks.dart'; import 'package:InvenTree/widget/snacks.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
@ -172,6 +173,11 @@ class _PartDisplayState extends RefreshableState<PartDetailWidget> {
headerTile() headerTile()
); );
if (loading) {
tiles.add(progressIndicator());
return tiles;
}
// Category information // Category information
if (part.categoryName != null && part.categoryName.isNotEmpty) { if (part.categoryName != null && part.categoryName.isNotEmpty) {
tiles.add( tiles.add(

13
lib/widget/progress.dart Normal file
View File

@ -0,0 +1,13 @@
import 'package:flutter/material.dart';
/*
* Construct a circular progress indicator
*/
Widget progressIndicator() {
return Center(
child: CircularProgressIndicator()
);
}

View File

@ -16,6 +16,11 @@ abstract class RefreshableState<T extends StatefulWidget> extends State<T> {
// Current tab index (used for widgets which display bottom tabs) // Current tab index (used for widgets which display bottom tabs)
int tabIndex = 0; int tabIndex = 0;
// Bool indicator
bool loading = false;
bool get loaded => !loading;
// Update current tab selection // Update current tab selection
void onTabSelectionChanged(int index) { void onTabSelectionChanged(int index) {
setState(() { setState(() {
@ -45,8 +50,16 @@ abstract class RefreshableState<T extends StatefulWidget> extends State<T> {
} }
Future<void> refresh() async { Future<void> refresh() async {
setState(() {
loading = true;
});
await request(context); await request(context);
setState(() {});
setState(() {
loading = false;
});
} }
// Function to construct an appbar (override if needed) // Function to construct an appbar (override if needed)

View File

@ -8,6 +8,7 @@ import 'package:InvenTree/widget/dialogs.dart';
import 'package:InvenTree/widget/fields.dart'; import 'package:InvenTree/widget/fields.dart';
import 'package:InvenTree/widget/location_display.dart'; import 'package:InvenTree/widget/location_display.dart';
import 'package:InvenTree/widget/part_detail.dart'; import 'package:InvenTree/widget/part_detail.dart';
import 'package:InvenTree/widget/progress.dart';
import 'package:InvenTree/widget/refreshable_state.dart'; import 'package:InvenTree/widget/refreshable_state.dart';
import 'package:InvenTree/widget/snacks.dart'; import 'package:InvenTree/widget/snacks.dart';
import 'package:InvenTree/widget/stock_item_test_results.dart'; import 'package:InvenTree/widget/stock_item_test_results.dart';
@ -314,6 +315,15 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
color: item.statusColor color: item.statusColor
) )
), ),
onTap: () {
if (item.partId > 0) {
InvenTreePart().get(context, item.partId).then((var part) {
if (part is InvenTreePart) {
Navigator.push(context, MaterialPageRoute(builder: (context) => PartDetailWidget(part)));
}
});
}
},
//trailing: Text(item.serialOrQuantityDisplay()), //trailing: Text(item.serialOrQuantityDisplay()),
) )
); );
@ -329,22 +339,29 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
// Image / name / description // Image / name / description
tiles.add(headerTile()); tiles.add(headerTile());
tiles.add( if (loading) {
ListTile( tiles.add(progressIndicator());
title: Text(I18N.of(context).part), return tiles;
subtitle: Text("${item.partName}"), }
leading: FaIcon(FontAwesomeIcons.shapes),
onTap: () { // Quantity information
if (item.partId > 0) { if (item.isSerialized()) {
InvenTreePart().get(context, item.partId).then((var part) { tiles.add(
if (part is InvenTreePart) { ListTile(
Navigator.push(context, MaterialPageRoute(builder: (context) => PartDetailWidget(part))); title: Text(I18N.of(context).serialNumber),
} leading: FaIcon(FontAwesomeIcons.hashtag),
}); trailing: Text("${item.serialNumber}"),
} )
}, );
) } else {
); tiles.add(
ListTile(
title: Text(I18N.of(context).quantity),
leading: FaIcon(FontAwesomeIcons.cubes),
trailing: Text("${item.quantityString}"),
)
);
}
// Location information // Location information
if ((item.locationId > 0) && (item.locationName != null) && (item.locationName.isNotEmpty)) { if ((item.locationId > 0) && (item.locationName != null) && (item.locationName.isNotEmpty)) {
@ -373,24 +390,7 @@ class _StockItemDisplayState extends RefreshableState<StockDetailWidget> {
); );
} }
// Quantity information
if (item.isSerialized()) {
tiles.add(
ListTile(
title: Text(I18N.of(context).serialNumber),
leading: FaIcon(FontAwesomeIcons.hashtag),
trailing: Text("${item.serialNumber}"),
)
);
} else {
tiles.add(
ListTile(
title: Text(I18N.of(context).quantity),
leading: FaIcon(FontAwesomeIcons.cubes),
trailing: Text("${item.quantityString}"),
)
);
}
// Supplier part? // Supplier part?
// TODO: Display supplier part info page? // TODO: Display supplier part info page?

View File

@ -4,6 +4,7 @@ import 'package:InvenTree/inventree/model.dart';
import 'package:InvenTree/api.dart'; import 'package:InvenTree/api.dart';
import 'package:InvenTree/widget/dialogs.dart'; import 'package:InvenTree/widget/dialogs.dart';
import 'package:InvenTree/widget/fields.dart'; import 'package:InvenTree/widget/fields.dart';
import 'package:InvenTree/widget/progress.dart';
import 'package:InvenTree/widget/snacks.dart'; import 'package:InvenTree/widget/snacks.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
@ -166,8 +167,40 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes
List<Widget> resultsList() { List<Widget> resultsList() {
List<Widget> tiles = []; List<Widget> tiles = [];
tiles.add(
Card(
child: ListTile(
title: Text(item.partName),
subtitle: Text(item.partDescription),
leading: InvenTreeAPI().getImage(item.partImage),
)
)
);
tiles.add(
ListTile(
title: Text("Test Results",
style: TextStyle(fontWeight: FontWeight.bold)
)
)
);
if (loading) {
tiles.add(progressIndicator());
return tiles;
}
var results = getTestResults(); var results = getTestResults();
if (results.length == 0) {
tiles.add(ListTile(
title: Text("No Results"),
subtitle: Text("No test results available"),
));
return tiles;
}
for (var item in results) { for (var item in results) {
bool _required = false; bool _required = false;
@ -231,6 +264,7 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes
@override @override
Widget getBody(BuildContext context) { Widget getBody(BuildContext context) {
return ListView( return ListView(
children: ListTile.divideTiles( children: ListTile.divideTiles(
context: context, context: context,
@ -239,6 +273,7 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes
); );
} }
/*
List<SpeedDialChild> actionButtons() { List<SpeedDialChild> actionButtons() {
var buttons = List<SpeedDialChild>(); var buttons = List<SpeedDialChild>();
@ -253,14 +288,15 @@ class _StockItemTestResultDisplayState extends RefreshableState<StockItemTestRes
return buttons; return buttons;
} }
*/
@override @override
Widget getFab(BuildContext context) { Widget getFab(BuildContext context) {
return SpeedDial( return FloatingActionButton(
visible: true, child: Icon(FontAwesomeIcons.plus),
animatedIcon: AnimatedIcons.menu_close, onPressed: () {
heroTag: 'stock-item-results-tab', addTestResult();
children: actionButtons(), },
); );
} }
} }

View File

@ -434,48 +434,6 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.4" version: "4.0.4"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.12+4"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.2+4"
shared_preferences_macos:
dependency: transitive
description:
name: shared_preferences_macos
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.1+11"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.2+7"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.2+3"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter