add side panel and more build log controls
This commit is contained in:
		@@ -42,8 +42,7 @@ class _APIBuilderState<T extends BaseProvider, K, DTO>
 | 
			
		||||
 | 
			
		||||
    if (widget.interval != null) {
 | 
			
		||||
      timer = Timer.periodic(widget.interval!, (Timer t) {
 | 
			
		||||
        Provider.of<T>(context, listen: false)
 | 
			
		||||
            .refresh(context);
 | 
			
		||||
        Provider.of<T>(context, listen: false).refresh(context);
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -31,11 +31,13 @@ class _BuildOutputState extends State<BuildOutput> {
 | 
			
		||||
        scrollDirection: Axis.vertical, //.horizontal
 | 
			
		||||
        child: Padding(
 | 
			
		||||
          padding: const EdgeInsets.only(left: 30, right: 15),
 | 
			
		||||
          child: Text(
 | 
			
		||||
            output,
 | 
			
		||||
            style: const TextStyle(
 | 
			
		||||
              fontSize: 16.0,
 | 
			
		||||
              color: Colors.white,
 | 
			
		||||
          child: SelectionArea(
 | 
			
		||||
            child: Text(
 | 
			
		||||
              output,
 | 
			
		||||
              style: const TextStyle(
 | 
			
		||||
                fontSize: 16.0,
 | 
			
		||||
                color: Colors.white,
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
          ),
 | 
			
		||||
        ),
 | 
			
		||||
 
 | 
			
		||||
@@ -2,17 +2,18 @@ import 'package:flutter/material.dart';
 | 
			
		||||
 | 
			
		||||
import '../../constants/color_constants.dart';
 | 
			
		||||
 | 
			
		||||
class ChartCard extends StatelessWidget {
 | 
			
		||||
  const ChartCard({
 | 
			
		||||
    Key? key,
 | 
			
		||||
class SideCard extends StatelessWidget {
 | 
			
		||||
  const SideCard({
 | 
			
		||||
    super.key,
 | 
			
		||||
    required this.title,
 | 
			
		||||
    required this.color,
 | 
			
		||||
    this.color,
 | 
			
		||||
    required this.textRight,
 | 
			
		||||
    required this.subtitle,
 | 
			
		||||
  }) : super(key: key);
 | 
			
		||||
    this.subtitle,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  final Color color;
 | 
			
		||||
  final String title, textRight, subtitle;
 | 
			
		||||
  final Color? color;
 | 
			
		||||
  final String title, textRight;
 | 
			
		||||
  final String? subtitle;
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context) {
 | 
			
		||||
@@ -27,12 +28,13 @@ class ChartCard extends StatelessWidget {
 | 
			
		||||
      ),
 | 
			
		||||
      child: Row(
 | 
			
		||||
        children: [
 | 
			
		||||
          SizedBox(
 | 
			
		||||
              height: 20,
 | 
			
		||||
              width: 20,
 | 
			
		||||
              child: Container(
 | 
			
		||||
                color: color,
 | 
			
		||||
              )),
 | 
			
		||||
          if (color != null)
 | 
			
		||||
            SizedBox(
 | 
			
		||||
                height: 20,
 | 
			
		||||
                width: 20,
 | 
			
		||||
                child: Container(
 | 
			
		||||
                  color: color,
 | 
			
		||||
                )),
 | 
			
		||||
          Expanded(
 | 
			
		||||
            child: Padding(
 | 
			
		||||
              padding: const EdgeInsets.symmetric(horizontal: defaultPadding),
 | 
			
		||||
@@ -44,13 +46,14 @@ class ChartCard extends StatelessWidget {
 | 
			
		||||
                    maxLines: 1,
 | 
			
		||||
                    overflow: TextOverflow.ellipsis,
 | 
			
		||||
                  ),
 | 
			
		||||
                  Text(
 | 
			
		||||
                    subtitle,
 | 
			
		||||
                    style: Theme.of(context)
 | 
			
		||||
                        .textTheme
 | 
			
		||||
                        .bodySmall!
 | 
			
		||||
                        .copyWith(color: Colors.white70),
 | 
			
		||||
                  ),
 | 
			
		||||
                  if (subtitle != null)
 | 
			
		||||
                    Text(
 | 
			
		||||
                      subtitle!,
 | 
			
		||||
                      style: Theme.of(context)
 | 
			
		||||
                          .textTheme
 | 
			
		||||
                          .bodySmall!
 | 
			
		||||
                          .copyWith(color: Colors.white70),
 | 
			
		||||
                    ),
 | 
			
		||||
                ],
 | 
			
		||||
              ),
 | 
			
		||||
            ),
 | 
			
		||||
 
 | 
			
		||||
@@ -39,21 +39,21 @@ class SidePanel extends StatelessWidget {
 | 
			
		||||
              nrbuilds: nrbuilds,
 | 
			
		||||
              nrfailedbuilds: nrfailedbuilds,
 | 
			
		||||
              nrActiveBuilds: nrActiveBuilds),
 | 
			
		||||
          ChartCard(
 | 
			
		||||
          SideCard(
 | 
			
		||||
            color: const Color(0xff0a7005),
 | 
			
		||||
            title: "Successful Builds",
 | 
			
		||||
            textRight:
 | 
			
		||||
                "${((nrbuilds - nrfailedbuilds) * 100 / nrbuilds).toStringAsFixed(2)}%",
 | 
			
		||||
            subtitle: (nrbuilds - nrfailedbuilds).toString(),
 | 
			
		||||
          ),
 | 
			
		||||
          ChartCard(
 | 
			
		||||
          SideCard(
 | 
			
		||||
            color: const Color(0xff760707),
 | 
			
		||||
            title: "Failed Builds",
 | 
			
		||||
            textRight:
 | 
			
		||||
                "${(nrfailedbuilds * 100 / nrbuilds).toStringAsFixed(2)}%",
 | 
			
		||||
            subtitle: nrfailedbuilds.toString(),
 | 
			
		||||
          ),
 | 
			
		||||
          ChartCard(
 | 
			
		||||
          SideCard(
 | 
			
		||||
            color: const Color(0xff9d8d00),
 | 
			
		||||
            title: "Active Builds",
 | 
			
		||||
            textRight:
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,10 @@ import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:go_router/go_router.dart';
 | 
			
		||||
import 'package:provider/provider.dart';
 | 
			
		||||
 | 
			
		||||
import '../components/confirm_popup.dart';
 | 
			
		||||
import '../components/dashboard/chart_card.dart';
 | 
			
		||||
import '../components/dashboard/your_packages.dart';
 | 
			
		||||
import '../constants/color_constants.dart';
 | 
			
		||||
 | 
			
		||||
class BuildScreen extends StatefulWidget {
 | 
			
		||||
  const BuildScreen({super.key, required this.buildID});
 | 
			
		||||
@@ -32,50 +35,201 @@ class _BuildScreenState extends State<BuildScreen> {
 | 
			
		||||
            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,
 | 
			
		||||
              return Row(
 | 
			
		||||
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
 | 
			
		||||
                children: [
 | 
			
		||||
                  Row(
 | 
			
		||||
                    mainAxisAlignment: MainAxisAlignment.start,
 | 
			
		||||
                    children: [
 | 
			
		||||
                      const SizedBox(
 | 
			
		||||
                        width: 10,
 | 
			
		||||
                      ),
 | 
			
		||||
                      IconButton(
 | 
			
		||||
                        icon: Icon(
 | 
			
		||||
                          switchSuccessIcon(buildData.status),
 | 
			
		||||
                          color: switchSuccessColor(buildData.status),
 | 
			
		||||
                  Expanded(
 | 
			
		||||
                    child: Column(
 | 
			
		||||
                      crossAxisAlignment: CrossAxisAlignment.start,
 | 
			
		||||
                      mainAxisAlignment: MainAxisAlignment.start,
 | 
			
		||||
                      children: [
 | 
			
		||||
                        _buildTopBar(buildData),
 | 
			
		||||
                        const SizedBox(
 | 
			
		||||
                          height: 15,
 | 
			
		||||
                        ),
 | 
			
		||||
                        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()}")
 | 
			
		||||
                    ],
 | 
			
		||||
                        _buildPage(buildData)
 | 
			
		||||
                      ],
 | 
			
		||||
                    ),
 | 
			
		||||
                  ),
 | 
			
		||||
                  const SizedBox(
 | 
			
		||||
                    height: 15,
 | 
			
		||||
                  ),
 | 
			
		||||
                  _buildPage(buildData)
 | 
			
		||||
                  _buildSideBar(),
 | 
			
		||||
                ],
 | 
			
		||||
              );
 | 
			
		||||
            }),
 | 
			
		||||
      ),
 | 
			
		||||
      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",
 | 
			
		||||
            ),
 | 
			
		||||
          ],
 | 
			
		||||
        ),
 | 
			
		||||
      ),
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user