diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6fcb9cb..9adbc24 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,13 +5,13 @@ rust-latest: stage: build image: rust:latest script: - - cargo build -r --mainifest-path=lib/Cargo.toml - - cargo test -r --mainifest-path=lib/Cargo.toml + - cargo build -r --manifest-path=lib/Cargo.toml + - cargo test -r --manifest-path=lib/Cargo.toml rust-nightly: stage: build image: rustlang/rust:nightly script: - - cargo build -r --mainifest-path=lib/Cargo.toml - - cargo test -r --mainifest-path=lib/Cargo.toml - allow_failure: true \ No newline at end of file + - cargo build -r --manifest-path=lib/Cargo.toml + - cargo test -r --manifest-path=lib/Cargo.toml + allow_failure: true diff --git a/app/lib/api/request.dart b/app/lib/api/request.dart new file mode 100644 index 0000000..768d3a5 --- /dev/null +++ b/app/lib/api/request.dart @@ -0,0 +1,12 @@ +import 'dart:convert'; + +import 'package:flutter/foundation.dart'; +import 'package:http/http.dart' as http; + +Future> getJson(String uri) async { + if (!kIsWeb) { + uri = "http://127.0.0.1:8000$uri"; + } + final resp = await http.get(Uri.parse(uri)); + return jsonDecode(resp.body); +} diff --git a/app/lib/disk_page.dart b/app/lib/disk_page.dart new file mode 100644 index 0000000..e069fa9 --- /dev/null +++ b/app/lib/disk_page.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:raid_manager/api/request.dart'; +import 'package:raid_manager/types/disk.dart'; +import 'package:raid_manager/utils/file_formatter.dart'; + +class DiskPage extends StatefulWidget { + const DiskPage({Key? key}) : super(key: key); + + @override + State createState() => _DiskPageState(); +} + +class _DiskPageState extends State { + Future> fetchDisks() async { + return (await getJson('/api/disks') as List) + .map((e) => Disk.fromJson(e)) + .toList(growable: false); + } + + late final myFetch = fetchDisks(); + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: myFetch, + builder: (context, snapshot) { + if (snapshot.hasData) { + final data = snapshot.data!; + return ListView.builder( + itemCount: data.length, + itemBuilder: (context, idx) { + return ListTile( + title: Text( + data[idx].name, + style: Theme.of(context).textTheme.headlineMedium, + ), + subtitle: Text( + data[idx].size.readableFileSize(), + style: Theme.of(context).textTheme.labelMedium, + ), + onTap: () {}, + ); + }, + ); + } else if (snapshot.hasError) { + return const Text("errored"); + } else { + return const Text("loading..."); + } + }, + ); + } +} diff --git a/app/lib/main.dart b/app/lib/main.dart index 5edda06..a715020 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:raid_manager/disk_page.dart'; import 'package:raid_manager/raid_page.dart'; import 'package:sidebarx/sidebarx.dart'; @@ -21,22 +22,20 @@ class SidebarXExampleApp extends StatelessWidget { canvasColor: canvasColor, scaffoldBackgroundColor: scaffoldBackgroundColor, textTheme: const TextTheme( - headlineSmall: TextStyle( - color: Colors.white, - fontSize: 12, - fontWeight: FontWeight.w800, - ), - headlineMedium: TextStyle( - color: Colors.white, - fontSize: 17, - fontWeight: FontWeight.w500, - ), - labelMedium: TextStyle( - color: Colors.white, - fontSize: 14, - fontWeight: FontWeight.w200 - ) - ), + headlineSmall: TextStyle( + color: Colors.white, + fontSize: 12, + fontWeight: FontWeight.w800, + ), + headlineMedium: TextStyle( + color: Colors.white, + fontSize: 17, + fontWeight: FontWeight.w500, + ), + labelMedium: TextStyle( + color: Colors.white, + fontSize: 14, + fontWeight: FontWeight.w200)), ), home: Builder( builder: (context) { @@ -45,18 +44,18 @@ class SidebarXExampleApp extends StatelessWidget { key: _key, appBar: isSmallScreen ? AppBar( - backgroundColor: canvasColor, - title: Text(_getTitleByIndex(_controller.selectedIndex)), - leading: IconButton( - onPressed: () { - // if (!Platform.isAndroid && !Platform.isIOS) { - // _controller.setExtended(true); - // } - _key.currentState?.openDrawer(); - }, - icon: const Icon(Icons.menu), - ), - ) + backgroundColor: canvasColor, + title: Text(_getTitleByIndex(_controller.selectedIndex)), + leading: IconButton( + onPressed: () { + // if (!Platform.isAndroid && !Platform.isIOS) { + // _controller.setExtended(true); + // } + _key.currentState?.openDrawer(); + }, + icon: const Icon(Icons.menu), + ), + ) : null, drawer: ExampleSidebarX(controller: _controller), body: Row( @@ -138,9 +137,7 @@ class ExampleSidebarX extends StatelessWidget { ), footerDivider: divider, headerBuilder: (context, extended) { - return const SizedBox( - height: 20 - ); + return const SizedBox(height: 20); }, items: const [ SidebarXItem( @@ -175,19 +172,7 @@ class _ScreensExample extends StatelessWidget { case 0: return const RaidPage(); case 1: - return ListView.builder( - padding: const EdgeInsets.only(top: 10), - itemBuilder: (context, index) => Container( - height: 100, - width: double.infinity, - margin: const EdgeInsets.only(bottom: 10, right: 10, left: 10), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(20), - color: Theme.of(context).canvasColor, - boxShadow: const [BoxShadow()], - ), - ), - ); + return const DiskPage(); default: return Text( pageTitle, diff --git a/app/lib/raid_page.dart b/app/lib/raid_page.dart index 6e0d9ae..f821bd8 100644 --- a/app/lib/raid_page.dart +++ b/app/lib/raid_page.dart @@ -1,9 +1,7 @@ -import 'dart:convert'; - import 'package:flutter/material.dart'; +import 'package:raid_manager/api/request.dart'; import 'package:raid_manager/raid_info_page.dart'; import 'package:raid_manager/types/md_raid_system.dart'; -import 'package:http/http.dart' as http; class RaidPage extends StatefulWidget { const RaidPage({Key? key}) : super(key: key); @@ -14,9 +12,7 @@ class RaidPage extends StatefulWidget { class _RaidPageState extends State { Future fetchRaids() async { - final resp = - await http.get(Uri.parse('http://127.0.0.1:8000/api/raiddevices')); - return MdRaidSystem.fromJson(jsonDecode(resp.body)); + return MdRaidSystem.fromJson(await getJson('/api/raiddevices')); } late final myFetch = fetchRaids(); diff --git a/app/lib/types/disk.dart b/app/lib/types/disk.dart new file mode 100644 index 0000000..a52d234 --- /dev/null +++ b/app/lib/types/disk.dart @@ -0,0 +1,13 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'disk.g.dart'; + +@JsonSerializable() +class Disk { + String name; + int size; + + Disk(this.name, this.size); + factory Disk.fromJson(Map json) => _$DiskFromJson(json); + Map toJson() => _$DiskToJson(this); +} diff --git a/app/lib/types/disk.g.dart b/app/lib/types/disk.g.dart new file mode 100644 index 0000000..40c5a42 --- /dev/null +++ b/app/lib/types/disk.g.dart @@ -0,0 +1,17 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'disk.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Disk _$DiskFromJson(Map json) => Disk( + json['name'] as String, + json['size'] as int, + ); + +Map _$DiskToJson(Disk instance) => { + 'name': instance.name, + 'size': instance.size, + }; diff --git a/app/lib/utils/file_formatter.dart b/app/lib/utils/file_formatter.dart new file mode 100644 index 0000000..61d90b2 --- /dev/null +++ b/app/lib/utils/file_formatter.dart @@ -0,0 +1,15 @@ +import 'dart:math'; + +double _log10(num x) => log(x) / ln10; + +extension FileFormatter on num { + String readableFileSize({bool base1024 = true}) { + if (this <= 0) return "0"; + final base = base1024 ? 1024 : 1000; + final units = base1024 + ? ["Bi", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"] + : ["B", "KB", "MB", "GB", "TB", "PB", "EB"]; + final digitGroups = (_log10(this) / _log10(base)).floor(); + return "${(this / pow(base, digitGroups)).toStringAsFixed(2)} ${units[digitGroups]}"; + } +}