add side panel and more build log controls
This commit is contained in:
parent
96c2876c97
commit
7ea241112c
@ -42,8 +42,7 @@ class _APIBuilderState<T extends BaseProvider, K, DTO>
|
|||||||
|
|
||||||
if (widget.interval != null) {
|
if (widget.interval != null) {
|
||||||
timer = Timer.periodic(widget.interval!, (Timer t) {
|
timer = Timer.periodic(widget.interval!, (Timer t) {
|
||||||
Provider.of<T>(context, listen: false)
|
Provider.of<T>(context, listen: false).refresh(context);
|
||||||
.refresh(context);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,13 @@ class _BuildOutputState extends State<BuildOutput> {
|
|||||||
scrollDirection: Axis.vertical, //.horizontal
|
scrollDirection: Axis.vertical, //.horizontal
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(left: 30, right: 15),
|
padding: const EdgeInsets.only(left: 30, right: 15),
|
||||||
child: Text(
|
child: SelectionArea(
|
||||||
output,
|
child: Text(
|
||||||
style: const TextStyle(
|
output,
|
||||||
fontSize: 16.0,
|
style: const TextStyle(
|
||||||
color: Colors.white,
|
fontSize: 16.0,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -2,17 +2,18 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
import '../../constants/color_constants.dart';
|
import '../../constants/color_constants.dart';
|
||||||
|
|
||||||
class ChartCard extends StatelessWidget {
|
class SideCard extends StatelessWidget {
|
||||||
const ChartCard({
|
const SideCard({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.color,
|
this.color,
|
||||||
required this.textRight,
|
required this.textRight,
|
||||||
required this.subtitle,
|
this.subtitle,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final Color color;
|
final Color? color;
|
||||||
final String title, textRight, subtitle;
|
final String title, textRight;
|
||||||
|
final String? subtitle;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -27,12 +28,13 @@ class ChartCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
if (color != null)
|
||||||
height: 20,
|
SizedBox(
|
||||||
width: 20,
|
height: 20,
|
||||||
child: Container(
|
width: 20,
|
||||||
color: color,
|
child: Container(
|
||||||
)),
|
color: color,
|
||||||
|
)),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: defaultPadding),
|
padding: const EdgeInsets.symmetric(horizontal: defaultPadding),
|
||||||
@ -44,13 +46,14 @@ class ChartCard extends StatelessWidget {
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
Text(
|
if (subtitle != null)
|
||||||
subtitle,
|
Text(
|
||||||
style: Theme.of(context)
|
subtitle!,
|
||||||
.textTheme
|
style: Theme.of(context)
|
||||||
.bodySmall!
|
.textTheme
|
||||||
.copyWith(color: Colors.white70),
|
.bodySmall!
|
||||||
),
|
.copyWith(color: Colors.white70),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -39,21 +39,21 @@ class SidePanel extends StatelessWidget {
|
|||||||
nrbuilds: nrbuilds,
|
nrbuilds: nrbuilds,
|
||||||
nrfailedbuilds: nrfailedbuilds,
|
nrfailedbuilds: nrfailedbuilds,
|
||||||
nrActiveBuilds: nrActiveBuilds),
|
nrActiveBuilds: nrActiveBuilds),
|
||||||
ChartCard(
|
SideCard(
|
||||||
color: const Color(0xff0a7005),
|
color: const Color(0xff0a7005),
|
||||||
title: "Successful Builds",
|
title: "Successful Builds",
|
||||||
textRight:
|
textRight:
|
||||||
"${((nrbuilds - nrfailedbuilds) * 100 / nrbuilds).toStringAsFixed(2)}%",
|
"${((nrbuilds - nrfailedbuilds) * 100 / nrbuilds).toStringAsFixed(2)}%",
|
||||||
subtitle: (nrbuilds - nrfailedbuilds).toString(),
|
subtitle: (nrbuilds - nrfailedbuilds).toString(),
|
||||||
),
|
),
|
||||||
ChartCard(
|
SideCard(
|
||||||
color: const Color(0xff760707),
|
color: const Color(0xff760707),
|
||||||
title: "Failed Builds",
|
title: "Failed Builds",
|
||||||
textRight:
|
textRight:
|
||||||
"${(nrfailedbuilds * 100 / nrbuilds).toStringAsFixed(2)}%",
|
"${(nrfailedbuilds * 100 / nrbuilds).toStringAsFixed(2)}%",
|
||||||
subtitle: nrfailedbuilds.toString(),
|
subtitle: nrfailedbuilds.toString(),
|
||||||
),
|
),
|
||||||
ChartCard(
|
SideCard(
|
||||||
color: const Color(0xff9d8d00),
|
color: const Color(0xff9d8d00),
|
||||||
title: "Active Builds",
|
title: "Active Builds",
|
||||||
textRight:
|
textRight:
|
||||||
|
@ -7,7 +7,10 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../components/confirm_popup.dart';
|
||||||
|
import '../components/dashboard/chart_card.dart';
|
||||||
import '../components/dashboard/your_packages.dart';
|
import '../components/dashboard/your_packages.dart';
|
||||||
|
import '../constants/color_constants.dart';
|
||||||
|
|
||||||
class BuildScreen extends StatefulWidget {
|
class BuildScreen extends StatefulWidget {
|
||||||
const BuildScreen({super.key, required this.buildID});
|
const BuildScreen({super.key, required this.buildID});
|
||||||
@ -32,50 +35,201 @@ class _BuildScreenState extends State<BuildScreen> {
|
|||||||
interval: const Duration(seconds: 10),
|
interval: const Duration(seconds: 10),
|
||||||
onLoad: () => const Text("loading"),
|
onLoad: () => const Text("loading"),
|
||||||
onData: (buildData) {
|
onData: (buildData) {
|
||||||
final start_time = DateTime.fromMillisecondsSinceEpoch(
|
return Row(
|
||||||
(buildData.start_time ?? 0) * 1000);
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
|
||||||
return Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Expanded(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
child: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
const SizedBox(
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
width: 10,
|
children: [
|
||||||
),
|
_buildTopBar(buildData),
|
||||||
IconButton(
|
const SizedBox(
|
||||||
icon: Icon(
|
height: 15,
|
||||||
switchSuccessIcon(buildData.status),
|
|
||||||
color: switchSuccessColor(buildData.status),
|
|
||||||
),
|
),
|
||||||
onPressed: () {
|
_buildPage(buildData)
|
||||||
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(
|
_buildSideBar(),
|
||||||
height: 15,
|
|
||||||
),
|
|
||||||
_buildPage(buildData)
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
appBar: AppBar(),
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildTopBar(Build buildData) {
|
||||||
|
final start_time =
|
||||||
|
DateTime.fromMillisecondsSinceEpoch((buildData.start_time ?? 0) * 1000);
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
color: secondaryColor,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 10, bottom: 10),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
width: 10,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.arrow_back,
|
||||||
|
size: 28,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
context.pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 10,
|
||||||
|
),
|
||||||
|
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()}")
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: const Icon(Icons.read_more),
|
||||||
|
tooltip: "Follow log",
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: const Icon(Icons.vertical_align_top_rounded),
|
||||||
|
tooltip: "Go to Top",
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: Icon(Icons.vertical_align_bottom_rounded),
|
||||||
|
tooltip: "Go to Bottom",
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 15,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildSideBar() {
|
||||||
|
return SizedBox(
|
||||||
|
width: 300,
|
||||||
|
child: Container(
|
||||||
|
color: secondaryColor,
|
||||||
|
padding: const EdgeInsets.all(defaultPadding),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 45,
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
const Text(
|
||||||
|
"Actions:",
|
||||||
|
style: TextStyle(fontSize: 18),
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 15,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final confirmResult = await showConfirmationDialog(
|
||||||
|
context,
|
||||||
|
"Delete Build",
|
||||||
|
"Are you sure to delete this Package?",
|
||||||
|
() async {},
|
||||||
|
() {},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text(
|
||||||
|
"Delete",
|
||||||
|
style: TextStyle(color: Colors.redAccent),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 10,
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final confirmResult = await showConfirmationDialog(
|
||||||
|
context,
|
||||||
|
"Delete Build",
|
||||||
|
"Are you sure to delete this Package?",
|
||||||
|
() async {},
|
||||||
|
() {},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text(
|
||||||
|
"Retry",
|
||||||
|
style: TextStyle(color: Colors.orangeAccent),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 15,
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
const SizedBox(
|
||||||
|
height: 15,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"Build Information:",
|
||||||
|
style: TextStyle(fontSize: 18),
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
SideCard(
|
||||||
|
title: "Build Number",
|
||||||
|
textRight: "7",
|
||||||
|
),
|
||||||
|
SideCard(
|
||||||
|
title: "Finished",
|
||||||
|
textRight: "7",
|
||||||
|
),
|
||||||
|
SideCard(
|
||||||
|
title: "Queued",
|
||||||
|
textRight: "7",
|
||||||
|
),
|
||||||
|
SideCard(
|
||||||
|
title: "Duration",
|
||||||
|
textRight: "7",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user