2024-02-17 18:50:15 +00:00
|
|
|
import 'package:aurcache/api/builds.dart';
|
|
|
|
import 'package:aurcache/api/packages.dart';
|
2023-12-30 21:23:42 +00:00
|
|
|
import 'package:aurcache/components/build_output.dart';
|
2023-12-30 15:46:13 +00:00
|
|
|
import 'package:aurcache/models/build.dart';
|
2024-01-01 16:11:05 +00:00
|
|
|
import 'package:aurcache/components/api/APIBuilder.dart';
|
2024-02-16 21:37:35 +00:00
|
|
|
import 'package:aurcache/providers/build_log_provider.dart';
|
2024-01-01 22:07:52 +00:00
|
|
|
import 'package:aurcache/utils/time_formatter.dart';
|
2023-12-30 15:46:13 +00:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:go_router/go_router.dart';
|
2024-01-19 19:00:10 +00:00
|
|
|
import 'package:provider/provider.dart';
|
2023-12-30 15:46:13 +00:00
|
|
|
|
2024-02-17 18:50:15 +00:00
|
|
|
import '../api/API.dart';
|
2024-02-16 16:37:26 +00:00
|
|
|
import '../components/confirm_popup.dart';
|
|
|
|
import '../components/dashboard/chart_card.dart';
|
|
|
|
import '../constants/color_constants.dart';
|
2024-02-16 21:37:35 +00:00
|
|
|
import '../providers/api/build_provider.dart';
|
2024-03-10 19:57:20 +00:00
|
|
|
import '../utils/package_color.dart';
|
2023-12-30 15:46:13 +00:00
|
|
|
|
|
|
|
class BuildScreen extends StatefulWidget {
|
|
|
|
const BuildScreen({super.key, required this.buildID});
|
|
|
|
|
|
|
|
final int buildID;
|
|
|
|
|
|
|
|
@override
|
|
|
|
State<BuildScreen> createState() => _BuildScreenState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _BuildScreenState extends State<BuildScreen> {
|
2024-02-16 21:37:35 +00:00
|
|
|
bool scrollFollowActive = true;
|
|
|
|
|
2023-12-30 15:46:13 +00:00
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return Scaffold(
|
2024-01-19 19:00:10 +00:00
|
|
|
body: MultiProvider(
|
|
|
|
providers: [
|
|
|
|
ChangeNotifierProvider<BuildProvider>(create: (_) => BuildProvider()),
|
2024-02-16 21:37:35 +00:00
|
|
|
ChangeNotifierProvider<BuildLogProvider>(
|
|
|
|
create: (_) => BuildLogProvider()),
|
2024-01-19 19:00:10 +00:00
|
|
|
],
|
2024-02-16 21:37:35 +00:00
|
|
|
builder: (context, child) {
|
|
|
|
return APIBuilder<BuildProvider, Build, BuildDTO>(
|
|
|
|
key: const Key("Build on seperate page"),
|
|
|
|
dto: BuildDTO(buildID: widget.buildID),
|
|
|
|
interval: const Duration(seconds: 10),
|
|
|
|
onLoad: () => const Text("loading"),
|
|
|
|
onData: (buildData) {
|
|
|
|
return Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
|
children: [
|
|
|
|
Expanded(
|
|
|
|
child: Column(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
|
|
children: [
|
|
|
|
_buildTopBar(buildData, context),
|
|
|
|
const SizedBox(
|
|
|
|
height: 15,
|
|
|
|
),
|
|
|
|
_buildPage(buildData)
|
|
|
|
],
|
|
|
|
),
|
2024-02-16 16:37:26 +00:00
|
|
|
),
|
2024-02-17 18:50:15 +00:00
|
|
|
_buildSideBar(buildData),
|
2024-02-16 21:37:35 +00:00
|
|
|
],
|
|
|
|
);
|
|
|
|
});
|
|
|
|
},
|
2024-01-19 19:00:10 +00:00
|
|
|
),
|
2024-02-16 16:37:26 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-02-16 21:37:35 +00:00
|
|
|
Widget _buildTopBar(Build buildData, BuildContext context) {
|
2024-02-16 16:37:26 +00:00
|
|
|
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,
|
|
|
|
),
|
2024-02-24 20:05:50 +00:00
|
|
|
Text("triggered ${buildData.start_time.readableDuration()}")
|
2024-02-16 16:37:26 +00:00
|
|
|
],
|
|
|
|
),
|
|
|
|
Row(
|
|
|
|
children: [
|
|
|
|
IconButton(
|
2024-02-16 21:37:35 +00:00
|
|
|
onPressed: () {
|
|
|
|
setState(() {
|
|
|
|
scrollFollowActive = !scrollFollowActive;
|
|
|
|
Provider.of<BuildLogProvider>(context, listen: false)
|
|
|
|
.followLog = scrollFollowActive;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
isSelected: scrollFollowActive,
|
2024-02-16 16:37:26 +00:00
|
|
|
icon: const Icon(Icons.read_more),
|
2024-02-16 21:37:35 +00:00
|
|
|
selectedIcon: const Icon(Icons.read_more),
|
2024-02-16 16:37:26 +00:00
|
|
|
tooltip: "Follow log",
|
|
|
|
),
|
|
|
|
IconButton(
|
2024-02-16 21:37:35 +00:00
|
|
|
onPressed: () {
|
|
|
|
Provider.of<BuildLogProvider>(context, listen: false)
|
|
|
|
.go_to_top();
|
|
|
|
},
|
2024-02-16 16:37:26 +00:00
|
|
|
icon: const Icon(Icons.vertical_align_top_rounded),
|
|
|
|
tooltip: "Go to Top",
|
|
|
|
),
|
|
|
|
IconButton(
|
2024-02-16 21:37:35 +00:00
|
|
|
onPressed: () {
|
|
|
|
Provider.of<BuildLogProvider>(context, listen: false)
|
|
|
|
.go_to_bottom();
|
|
|
|
},
|
|
|
|
icon: const Icon(Icons.vertical_align_bottom_rounded),
|
2024-02-16 16:37:26 +00:00
|
|
|
tooltip: "Go to Bottom",
|
|
|
|
),
|
|
|
|
const SizedBox(
|
|
|
|
width: 15,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-02-17 18:50:15 +00:00
|
|
|
Widget _buildSideBar(Build buildData) {
|
2024-02-16 16:37:26 +00:00
|
|
|
return SizedBox(
|
|
|
|
width: 300,
|
|
|
|
child: Container(
|
|
|
|
color: secondaryColor,
|
|
|
|
padding: const EdgeInsets.all(defaultPadding),
|
|
|
|
child: Column(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
children: [
|
|
|
|
const SizedBox(
|
|
|
|
height: 45,
|
|
|
|
),
|
2024-02-16 21:58:46 +00:00
|
|
|
const Divider(),
|
|
|
|
const SizedBox(
|
|
|
|
height: 5,
|
|
|
|
),
|
2024-02-16 16:37:26 +00:00
|
|
|
const Text(
|
|
|
|
"Actions:",
|
|
|
|
style: TextStyle(fontSize: 18),
|
|
|
|
textAlign: TextAlign.start,
|
|
|
|
),
|
|
|
|
const SizedBox(
|
2024-02-16 21:58:46 +00:00
|
|
|
height: 20,
|
2024-02-16 16:37:26 +00:00
|
|
|
),
|
|
|
|
Row(
|
2024-03-10 19:57:20 +00:00
|
|
|
children: buildActions(buildData),
|
2024-02-16 16:37:26 +00:00
|
|
|
),
|
|
|
|
const SizedBox(
|
|
|
|
height: 15,
|
|
|
|
),
|
2024-02-16 21:58:46 +00:00
|
|
|
const Divider(),
|
2024-02-16 16:37:26 +00:00
|
|
|
const SizedBox(
|
2024-02-16 21:58:46 +00:00
|
|
|
height: 5,
|
2024-02-16 16:37:26 +00:00
|
|
|
),
|
2024-02-17 18:50:15 +00:00
|
|
|
const Text(
|
2024-02-16 16:37:26 +00:00
|
|
|
"Build Information:",
|
|
|
|
style: TextStyle(fontSize: 18),
|
|
|
|
textAlign: TextAlign.start,
|
|
|
|
),
|
2024-02-17 18:50:15 +00:00
|
|
|
const SizedBox(
|
2024-02-16 16:37:26 +00:00
|
|
|
height: 20,
|
|
|
|
),
|
|
|
|
SideCard(
|
|
|
|
title: "Build Number",
|
2024-02-25 09:58:14 +00:00
|
|
|
textRight: "#${buildData.id}",
|
2024-02-16 16:37:26 +00:00
|
|
|
),
|
|
|
|
SideCard(
|
2024-02-18 13:22:27 +00:00
|
|
|
title: "Version",
|
|
|
|
textRight: buildData.version,
|
2024-02-16 16:37:26 +00:00
|
|
|
),
|
|
|
|
SideCard(
|
2024-02-18 13:22:27 +00:00
|
|
|
title: "Finished",
|
|
|
|
textRight: buildData.end_time == null
|
|
|
|
? "Not yet"
|
2024-02-24 20:05:50 +00:00
|
|
|
: buildData.end_time!.readableDuration(),
|
2024-02-16 16:37:26 +00:00
|
|
|
),
|
|
|
|
SideCard(
|
|
|
|
title: "Duration",
|
2024-02-24 20:05:50 +00:00
|
|
|
textRight: (buildData.end_time ?? DateTime.now())
|
|
|
|
.difference(buildData.start_time)
|
2024-02-17 18:50:15 +00:00
|
|
|
.readableDuration(),
|
2024-02-16 16:37:26 +00:00
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
2023-12-30 15:46:13 +00:00
|
|
|
);
|
|
|
|
}
|
2024-01-02 22:05:03 +00:00
|
|
|
|
2024-03-10 19:57:20 +00:00
|
|
|
List<Widget> buildActions(Build build) {
|
|
|
|
if (build.status == 0) {
|
|
|
|
return [
|
|
|
|
ElevatedButton(
|
|
|
|
onPressed: () async {
|
|
|
|
await showConfirmationDialog(
|
|
|
|
context, "Cancel Build", "Are you sure to cancel this Build?",
|
|
|
|
() {
|
|
|
|
API.cancelBuild(widget.buildID);
|
|
|
|
Provider.of<BuildProvider>(context, listen: false)
|
|
|
|
.refresh(context);
|
|
|
|
}, null);
|
|
|
|
},
|
|
|
|
child: const Text(
|
|
|
|
"Cancel",
|
|
|
|
style: TextStyle(color: Colors.redAccent),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
];
|
|
|
|
} else {
|
|
|
|
return [
|
|
|
|
ElevatedButton(
|
|
|
|
onPressed: () async {
|
|
|
|
await showConfirmationDialog(
|
|
|
|
context, "Delete Build", "Are you sure to delete this Build?",
|
|
|
|
() {
|
|
|
|
API.deleteBuild(widget.buildID);
|
|
|
|
context.pop();
|
|
|
|
}, null);
|
|
|
|
},
|
|
|
|
child: const Text(
|
|
|
|
"Delete",
|
|
|
|
style: TextStyle(color: Colors.redAccent),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
const SizedBox(
|
|
|
|
width: 10,
|
|
|
|
),
|
|
|
|
ElevatedButton(
|
|
|
|
onPressed: () async {
|
|
|
|
final buildid = await API.updatePackage(id: build.pkg_id);
|
|
|
|
context.pushReplacement("/build/$buildid");
|
|
|
|
},
|
|
|
|
child: const Text(
|
|
|
|
"Retry",
|
|
|
|
style: TextStyle(color: Colors.orangeAccent),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-02 22:05:03 +00:00
|
|
|
Widget _buildPage(Build build) {
|
|
|
|
switch (build.status) {
|
|
|
|
case 3:
|
|
|
|
return const Text("in Queue");
|
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
default:
|
|
|
|
return BuildOutput(build: build);
|
|
|
|
}
|
|
|
|
}
|
2023-12-30 15:46:13 +00:00
|
|
|
}
|