Files
flutter_thingsboard_app/lib/modules/alarm/alarms_base.dart
2022-08-12 15:13:53 +03:00

323 lines
13 KiB
Dart

import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:thingsboard_app/core/context/tb_context.dart';
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
import 'package:thingsboard_app/core/entity/entities_base.dart';
import 'package:thingsboard_app/generated/l10n.dart';
import 'package:thingsboard_app/utils/utils.dart';
import 'package:thingsboard_client/thingsboard_client.dart';
const Map<AlarmSeverity, Color> alarmSeverityColors = {
AlarmSeverity.CRITICAL: Color(0xFFFF0000),
AlarmSeverity.MAJOR: Color(0xFFFFA500),
AlarmSeverity.MINOR: Color(0xFFFFCA3D),
AlarmSeverity.WARNING: Color(0xFFABAB00),
AlarmSeverity.INDETERMINATE: Color(0xFF00FF00),
};
const Map<AlarmSeverity, String> alarmSeverityTranslations = {
AlarmSeverity.CRITICAL: 'Critical',
AlarmSeverity.MAJOR: 'Major',
AlarmSeverity.MINOR: 'Minor',
AlarmSeverity.WARNING: 'Warning',
AlarmSeverity.INDETERMINATE: 'Indeterminate',
};
const Map<AlarmStatus, String> alarmStatusTranslations = {
AlarmStatus.ACTIVE_ACK: 'Active Acknowledged',
AlarmStatus.ACTIVE_UNACK: 'Active Unacknowledged',
AlarmStatus.CLEARED_ACK: 'Cleared Acknowledged',
AlarmStatus.CLEARED_UNACK: 'Cleared Unacknowledged',
};
mixin AlarmsBase on EntitiesBase<AlarmInfo, AlarmQuery> {
@override
String get title => 'Alarms';
@override
String get noItemsFoundText => 'No alarms found';
@override
Future<PageData<AlarmInfo>> fetchEntities(AlarmQuery query) {
return tbClient.getAlarmService().getAllAlarms(query);
}
@override
void onEntityTap(AlarmInfo alarm) {
String? dashboardId = alarm.details?['dashboardId'];
if (dashboardId != null) {
var state = Utils.createDashboardEntityState(alarm.originator,
entityName: alarm.originatorName);
navigateToDashboard(dashboardId,
dashboardTitle: alarm.originatorName, state: state);
} else {
if (tbClient.isTenantAdmin()) {
showWarnNotification(
'Mobile dashboard should be configured in device profile alarm rules!');
}
}
}
@override
Widget buildEntityListCard(BuildContext context, AlarmInfo alarm) {
return _buildEntityListCard(context, alarm);
}
Widget _buildEntityListCard(BuildContext context, AlarmInfo alarm) {
return AlarmCard(tbContext, alarm: alarm);
}
}
class AlarmQueryController extends PageKeyController<AlarmQuery> {
AlarmQueryController({int pageSize = 20, String? searchText})
: super(AlarmQuery(
TimePageLink(pageSize, 0, searchText,
SortOrder('createdTime', Direction.DESC)),
fetchOriginator: true));
@override
AlarmQuery nextPageKey(AlarmQuery pageKey) {
return AlarmQuery(pageKey.pageLink.nextPageLink());
}
onSearchText(String searchText) {
var query = value.pageKey;
query.pageLink.page = 0;
query.pageLink.textSearch = searchText;
notifyListeners();
}
}
class AlarmCard extends TbContextWidget {
final AlarmInfo alarm;
AlarmCard(TbContext tbContext, {required this.alarm}) : super(tbContext);
@override
_AlarmCardState createState() => _AlarmCardState(alarm);
}
class _AlarmCardState extends TbContextState<AlarmCard> {
bool loading = false;
AlarmInfo alarm;
final entityDateFormat = DateFormat('yyyy-MM-dd');
_AlarmCardState(this.alarm) : super();
@override
void initState() {
super.initState();
}
@override
void didUpdateWidget(AlarmCard oldWidget) {
super.didUpdateWidget(oldWidget);
this.loading = false;
this.alarm = widget.alarm;
}
@override
Widget build(BuildContext context) {
if (this.loading) {
return Container(
height: 134,
alignment: Alignment.center,
child: RefreshProgressIndicator());
} else {
bool hasDashboard = alarm.details?['dashboardId'] != null;
return Stack(
children: [
Positioned.fill(
child: Container(
alignment: Alignment.centerLeft,
child: Container(
width: 4,
decoration: BoxDecoration(
color: alarmSeverityColors[alarm.severity]!,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(4),
bottomLeft: Radius.circular(4))),
))),
Row(mainAxisSize: MainAxisSize.max, children: [
SizedBox(width: 4),
Flexible(
fit: FlexFit.tight,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(width: 16),
Flexible(
fit: FlexFit.tight,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 12),
Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Flexible(
fit: FlexFit.tight,
child: AutoSizeText(alarm.type,
maxLines: 2,
minFontSize: 8,
overflow:
TextOverflow.ellipsis,
style: TextStyle(
color: Color(0xFF282828),
fontWeight:
FontWeight.w500,
fontSize: 14,
height: 20 / 14))),
Text(
entityDateFormat.format(DateTime
.fromMillisecondsSinceEpoch(
alarm.createdTime!)),
style: TextStyle(
color: Color(0xFFAFAFAF),
fontWeight: FontWeight.normal,
fontSize: 12,
height: 16 / 12))
]),
SizedBox(height: 4),
Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Flexible(
fit: FlexFit.tight,
child: Text(
alarm.originatorName != null
? alarm.originatorName!
: '',
style: TextStyle(
color: Color(0xFFAFAFAF),
fontWeight:
FontWeight.normal,
fontSize: 12,
height: 16 / 12))),
Text(
alarmSeverityTranslations[
alarm.severity]!,
style: TextStyle(
color: alarmSeverityColors[
alarm.severity]!,
fontWeight: FontWeight.w500,
fontSize: 12,
height: 16 / 12))
]),
SizedBox(height: 12)
],
)),
SizedBox(width: 16),
if (hasDashboard)
Icon(Icons.chevron_right,
color: Color(0xFFACACAC)),
if (hasDashboard) SizedBox(width: 16),
]),
Divider(height: 1),
SizedBox(height: 8),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(width: 16),
Flexible(
fit: FlexFit.tight,
child: Text(
alarmStatusTranslations[alarm.status]!,
style: TextStyle(
color: Color(0xFF282828),
fontWeight: FontWeight.normal,
fontSize: 14,
height: 20 / 14))),
SizedBox(height: 32),
Row(
children: [
if ([
AlarmStatus.CLEARED_UNACK,
AlarmStatus.ACTIVE_UNACK
].contains(alarm.status))
CircleAvatar(
radius: 16,
backgroundColor: Color(0xffF0F4F9),
child: IconButton(
icon: Icon(Icons.done, size: 18),
padding: EdgeInsets.all(7.0),
onPressed: () =>
_ackAlarm(alarm, context))),
if ([
AlarmStatus.ACTIVE_UNACK,
AlarmStatus.ACTIVE_ACK
].contains(alarm.status))
Row(children: [
SizedBox(width: 4),
CircleAvatar(
radius: 16,
backgroundColor: Color(0xffF0F4F9),
child: IconButton(
icon: Icon(Icons.clear, size: 18),
padding: EdgeInsets.all(7.0),
onPressed: () =>
_clearAlarm(alarm, context)))
])
],
),
SizedBox(width: 8)
],
),
SizedBox(height: 8)
]))
])
],
);
}
}
_clearAlarm(AlarmInfo alarm, BuildContext context) async {
var res = await confirm(
title: '${S.of(context).alarmClearTitle}',
message: '${S.of(context).alarmClearText}',
cancel: '${S.of(context).No}',
ok: '${S.of(context).Yes}');
if (res != null && res) {
setState(() {
loading = true;
});
await tbClient.getAlarmService().clearAlarm(alarm.id!.id!);
var newAlarm =
await tbClient.getAlarmService().getAlarmInfo(alarm.id!.id!);
setState(() {
loading = false;
this.alarm = newAlarm!;
});
}
}
_ackAlarm(AlarmInfo alarm, BuildContext context) async {
var res = await confirm(
title: '${S.of(context).alarmAcknowledgeTitle}',
message: '${S.of(context).alarmAcknowledgeText}',
cancel: '${S.of(context).No}',
ok: '${S.of(context).Yes}');
if (res != null && res) {
setState(() {
loading = true;
});
await tbClient.getAlarmService().ackAlarm(alarm.id!.id!);
var newAlarm =
await tbClient.getAlarmService().getAlarmInfo(alarm.id!.id!);
setState(() {
loading = false;
this.alarm = newAlarm!;
});
}
}
}