blob: 44bc2e18473f3d722ddf1b51619cfc53a5e188fd [file] [log] [blame]
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:cocoon_service/protos.dart' show Agent;
import 'agent_health_details.dart';
import 'agent_list.dart';
import 'state/agent.dart';
/// A card for showing the information from an [Agent].
///
/// Summarizes [Agent.healthDetails] into a row of icons.
///
/// Offers the ability to view the agent raw health details, re-authorize the
/// agent, and attempt to reserve a task for the agent.
class AgentTile extends StatelessWidget {
const AgentTile({this.fullAgent, this.agentState, Key key}) : super(key: key);
final AgentState agentState;
final FullAgent fullAgent;
@visibleForTesting
static const Duration authorizeAgentSnackbarDuration = Duration(seconds: 5);
@visibleForTesting
static const Duration reserveTaskSnackbarDuration = Duration(seconds: 5);
/// Values to be used in [PopupMenu] to know what action to execute.
static const String _authorizeAgentValue = 'authorize';
static const String _healthDetailsValue = 'details';
static const String _reserveTaskValue = 'reserve';
@override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
final Agent agent = fullAgent.agent;
final AgentHealthDetails healthDetails = fullAgent.healthDetails;
return Card(
child: ListTile(
leading: CircleAvatar(
backgroundColor:
healthDetails.isHealthy ? Colors.green : theme.errorColor,
foregroundColor: Colors.white,
child: _getIconFromId(agent.agentId),
),
title: Text(agent.agentId),
subtitle: AgentHealthDetailsBar(healthDetails),
trailing: PopupMenuButton<String>(
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
const PopupMenuItem<String>(
child: Text('Raw health details'),
value: _healthDetailsValue,
),
const PopupMenuItem<String>(
child: Text('Authorize agent'),
value: _authorizeAgentValue,
),
const PopupMenuItem<String>(
child: Text('Reserve task'),
value: _reserveTaskValue,
),
],
icon: Icon(Icons.more_vert),
onSelected: (String value) {
switch (value) {
case _healthDetailsValue:
_showHealthDetailsDialog(context, agent.healthDetails);
break;
case _authorizeAgentValue:
_authorizeAgent(context, agent);
break;
case _reserveTaskValue:
_reserveTask(context, agent);
break;
default:
throw Exception(
'$value is not a valid operation on AgentTile popup menu');
}
},
),
),
);
}
/// A lookup function for showing the leading icon based on [agentId].
Icon _getIconFromId(String agentId) {
if (agentId.contains('vm')) {
return Icon(Icons.dns);
} else if (agentId.contains('linux')) {
return Icon(Icons.android);
} else if (agentId.contains('mac')) {
return Icon(Icons.phone_iphone);
} else if (agentId.contains('windows')) {
return Icon(Icons.desktop_windows);
}
return Icon(Icons.device_unknown);
}
void _showHealthDetailsDialog(BuildContext context, String rawHealthDetails) {
// TODO(chillers): Add copy button when web has support. https://github.com/flutter/flutter/issues/46020
print(rawHealthDetails);
showDialog<SimpleDialog>(
context: context,
builder: (BuildContext context) => SimpleDialog(
children: <Widget>[
Text(rawHealthDetails),
],
),
);
}
/// Call [authorizeAgent] to Cocoon for [agent] and show the new access token.
///
/// On success, displays a [SnackBar] telling the user the access token can
/// be found in their console.
///
/// If the request fails, [AgentDashboardPage] will handle the error and show
/// a [SnackBar].
Future<void> _authorizeAgent(BuildContext context, Agent agent) async {
final String token = await agentState.authorizeAgent(agent);
if (token != null) {
// TODO(chillers): Copy the token to clipboard when web has support. https://github.com/flutter/flutter/issues/46020
print(token);
Scaffold.of(context).showSnackBar(const SnackBar(
content: Text('Check console for token'),
duration: authorizeAgentSnackbarDuration,
));
}
}
/// Call [reserveTask] to Cocoon for [agent] and show the information for
/// the [Task] that was reserved.
///
/// On success, displays a [SnackBar] telling the user the information can
/// be found in their console. The data is just the ids and names for the
/// task its commit.
///
/// If the request fails, [AgentDashboardPage] will handle the error and show
/// a [SnackBar].
Future<void> _reserveTask(BuildContext context, Agent agent) async {
await agentState.reserveTask(agent);
Scaffold.of(context).showSnackBar(const SnackBar(
content: Text('Check console for reserve task info'),
duration: authorizeAgentSnackbarDuration,
));
}
}