Files
flutter_thingsboard_app/lib/modules/alarm/alarms_base.dart
2021-08-18 21:07:19 +03:00

303 lines
12 KiB
Dart

import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.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/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))
),
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))
)
]
)
],
),
SizedBox(width: 8)
],
),
SizedBox(height: 8)
]
)
)
]
)
],
);
}
}
_clearAlarm(AlarmInfo alarm) async {
var res = await confirm(title: 'Clear Alarm', message: 'Are you sure you want to clear Alarm?', cancel: 'No', ok: '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) async {
var res = await confirm(title: 'Acknowledge Alarm', message: 'Are you sure you want to acknowledge Alarm?', cancel: 'No', ok: '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!;
});
}
}
}