Added date filtering logs

This commit is contained in:
Juan Gilsanz Polo 2022-10-02 03:58:02 +02:00
parent 84df416011
commit f6b747f729
12 changed files with 432 additions and 72 deletions

View file

@ -1,14 +1,31 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:adguard_home_manager/screens/logs/logs_filters_modal.dart';
class LogsAppBar extends StatelessWidget with PreferredSizeWidget {
const LogsAppBar({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
void openFilersModal() {
showModalBottomSheet(
context: context,
builder: (context) => const LogsFiltersModal(),
backgroundColor: Colors.transparent,
isScrollControlled: true
);
}
return AppBar(
title: Text(AppLocalizations.of(context)!.logs),
centerTitle: true,
actions: [
IconButton(
onPressed: openFilersModal,
icon: const Icon(Icons.filter_list_rounded)
),
const SizedBox(width: 5),
],
);
}

View file

@ -143,7 +143,7 @@ class LogDetailsModal extends StatelessWidget {
LogListTile(
icon: Icons.schedule,
title: AppLocalizations.of(context)!.time,
subtitle: formatTimestamp(log.time, 'HH:mm:ss')
subtitle: formatTimestampUTC(log.time, 'HH:mm:ss')
),
Padding(
padding: const EdgeInsets.all(20),

View file

@ -200,7 +200,7 @@ class LogTile extends StatelessWidget {
],
),
Text(
formatTimestamp(log.time, 'HH:mm:ss')
formatTimestampUTC(log.time, 'HH:mm:ss')
),
],
),

View file

@ -6,6 +6,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:adguard_home_manager/screens/logs/log_tile.dart';
import 'package:adguard_home_manager/providers/logs_provider.dart';
import 'package:adguard_home_manager/models/filtering_status.dart';
import 'package:adguard_home_manager/models/app_log.dart';
import 'package:adguard_home_manager/providers/app_config_provider.dart';
@ -21,25 +22,26 @@ class Logs extends StatelessWidget {
Widget build(BuildContext context) {
final serversProvider = Provider.of<ServersProvider>(context);
final appConfigProvider = Provider.of<AppConfigProvider>(context);
final logsProvider = Provider.of<LogsProvider>(context);
return LogsWidget(
server: serversProvider.selectedServer!,
createLog: appConfigProvider.addLog,
setFilteringStatus: serversProvider.setFilteringStatus,
serversProvider: serversProvider,
appConfigProvider: appConfigProvider,
logsProvider: logsProvider,
);
}
}
class LogsWidget extends StatefulWidget {
final Server server;
final void Function(AppLog) createLog;
final void Function(FilteringStatus) setFilteringStatus;
final ServersProvider serversProvider;
final AppConfigProvider appConfigProvider;
final LogsProvider logsProvider;
const LogsWidget({
Key? key,
required this.server,
required this.createLog,
required this.setFilteringStatus,
required this.serversProvider,
required this.appConfigProvider,
required this.logsProvider,
}) : super(key: key);
@override
@ -47,14 +49,6 @@ class LogsWidget extends StatefulWidget {
}
class _LogsWidgetState extends State<LogsWidget> {
LogsList logsList = LogsList(
loadStatus: 0,
logsData: null
);
int itemsPerLoad = 100;
int offset = 0;
late ScrollController scrollController;
bool isLoadingMore = false;
@ -63,42 +57,44 @@ class _LogsWidgetState extends State<LogsWidget> {
int? inOffset,
bool? loadingMore
}) async {
int offst = inOffset ?? offset;
int offst = inOffset ?? widget.logsProvider.offset;
if (loadingMore != null && loadingMore == true) {
setState(() => isLoadingMore = true);
}
final result = await getLogs(server: widget.server, count: itemsPerLoad, offset: offst);
final result = await getLogs(
server: widget.serversProvider.selectedServer!,
count: widget.logsProvider.logsQuantity,
offset: offst
);
if (loadingMore != null && loadingMore == true) {
setState(() => isLoadingMore = false);
}
if (result['result'] == 'success') {
setState(() {
offset = inOffset != null ? inOffset+itemsPerLoad : offset+itemsPerLoad;
if (loadingMore != null && loadingMore == true) {
logsList.logsData!.data = [...logsList.logsData!.data, ...result['data'].data];
}
else {
logsList.logsData = result['data'];
}
logsList.loadStatus = 1;
});
widget.logsProvider.setOffset(inOffset != null ? inOffset+widget.logsProvider.logsQuantity : widget.logsProvider.offset+widget.logsProvider.logsQuantity);
if (loadingMore != null && loadingMore == true && widget.logsProvider.logsData != null) {
LogsData newLogsData = result['data'];
newLogsData.data = [...widget.logsProvider.logsData!.data, ...result['data'].data];
widget.logsProvider.setLogsData(newLogsData);
}
else {
widget.logsProvider.setLogsData(result['data']);
}
widget.logsProvider.setLoadStatus(1);
}
else {
setState(() {
logsList.loadStatus = 2;
});
widget.createLog(result['log']);
widget.logsProvider.setLoadStatus(2);
widget.appConfigProvider.addLog(result['log']);
}
}
void fetchFilteringRules() async {
final result = await getFilteringRules(server: widget.server);
final result = await getFilteringRules(server: widget.serversProvider.selectedServer!);
if (result['result'] == 'success') {
widget.setFilteringStatus(result['data']);
widget.serversProvider.setFilteringStatus(result['data']);
}
else {
ScaffoldMessenger.of(context).showSnackBar(
@ -126,7 +122,9 @@ class _LogsWidgetState extends State<LogsWidget> {
@override
Widget build(BuildContext context) {
switch (logsList.loadStatus) {
final logsProvider = Provider.of<LogsProvider>(context);
switch (logsProvider.loadStatus) {
case 0:
return SizedBox(
width: double.maxFinite,
@ -153,30 +151,60 @@ class _LogsWidgetState extends State<LogsWidget> {
onRefresh: () async {
await fetchLogs(inOffset: 0);
},
child: ListView.builder(
controller: scrollController,
padding: const EdgeInsets.only(top: 0),
itemCount: isLoadingMore == true
? logsList.logsData!.data.length+1
: logsList.logsData!.data.length,
itemBuilder: (context, index) {
if (isLoadingMore == true && index == logsList.logsData!.data.length) {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 20),
child: Center(
child: CircularProgressIndicator(),
),
);
}
else {
return LogTile(
log: logsList.logsData!.data[index],
index: index,
length: logsList.logsData!.data.length,
);
}
}
),
child: logsProvider.logsData!.data.isNotEmpty
? ListView.builder(
controller: scrollController,
padding: const EdgeInsets.only(top: 0),
itemCount: isLoadingMore == true
? logsProvider.logsData!.data.length+1
: logsProvider.logsData!.data.length,
itemBuilder: (context, index) {
if (isLoadingMore == true && index == logsProvider.logsData!.data.length) {
return const Padding(
padding: EdgeInsets.symmetric(vertical: 20),
child: Center(
child: CircularProgressIndicator(),
),
);
}
else {
return LogTile(
log: logsProvider.logsData!.data[index],
index: index,
length: logsProvider.logsData!.data.length,
);
}
}
)
: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
AppLocalizations.of(context)!.noLogsDisplay,
style: const TextStyle(
fontSize: 24,
color: Colors.grey
),
),
if (logsProvider.logsOlderThan != null) Padding(
padding: const EdgeInsets.only(
top: 30,
left: 20,
right: 20
),
child: Text(
AppLocalizations.of(context)!.noLogsThatOld,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 16,
color: Colors.grey
),
),
),
]
),
)
);
case 2:

View file

@ -0,0 +1,224 @@
// ignore_for_file: use_build_context_synchronously
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:adguard_home_manager/providers/app_config_provider.dart';
import 'package:adguard_home_manager/providers/servers_provider.dart';
import 'package:adguard_home_manager/services/http_requests.dart';
import 'package:adguard_home_manager/functions/format_time.dart';
import 'package:adguard_home_manager/providers/logs_provider.dart';
class LogsFiltersModal extends StatelessWidget {
const LogsFiltersModal({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final logsProvider = Provider.of<LogsProvider>(context);
final serversProvider = Provider.of<ServersProvider>(context);
final appConfigProvider = Provider.of<AppConfigProvider>(context);
void selectTime() async {
DateTime now = DateTime.now();
DateTime? dateValue = await showDatePicker(
context: context,
initialDate: now,
firstDate: DateTime(now.year, now.month-1, now.day),
lastDate: now
);
if (dateValue != null) {
TimeOfDay? timeValue = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
helpText: AppLocalizations.of(context)!.selectTime,
);
if (timeValue != null) {
DateTime value = DateTime(
dateValue.year,
dateValue.month,
dateValue.day,
timeValue.hour,
timeValue.minute,
dateValue.second
).toUtc();
logsProvider.setLogsOlderThan(value);
logsProvider.setLoadStatus(0);
logsProvider.setOffset(0);
final result = await getLogs(
server: serversProvider.selectedServer!,
count: logsProvider.logsQuantity,
olderThan: logsProvider.logsOlderThan
);
if (result['result'] == 'success') {
logsProvider.setLogsData(result['data']);
logsProvider.setLoadStatus(1);
}
else {
appConfigProvider.addLog(result['log']);
logsProvider.setLoadStatus(2);
}
}
}
}
void resetFilters() async {
logsProvider.setLoadStatus(0);
logsProvider.resetFilters();
final result = await getLogs(
server: serversProvider.selectedServer!,
count: logsProvider.logsQuantity
);
if (result['result'] == 'success') {
logsProvider.setLogsData(result['data']);
logsProvider.setLoadStatus(1);
}
else {
appConfigProvider.addLog(result['log']);
logsProvider.setLoadStatus(2);
}
}
return Container(
height: 350,
decoration: BoxDecoration(
color: Theme.of(context).dialogBackgroundColor,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(28),
topRight: Radius.circular(28)
)
),
child: Column(
children: [
const Padding(
padding: EdgeInsets.only(
top: 24,
bottom: 20,
),
child: Icon(
Icons.filter_list_rounded,
size: 26,
),
),
Text(
AppLocalizations.of(context)!.filters,
style: const TextStyle(
fontSize: 24
),
),
const SizedBox(height: 20),
Expanded(
child: ListView(
physics: const NeverScrollableScrollPhysics(),
children: [
Material(
color: Colors.transparent,
child: InkWell(
onTap: selectTime,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Row(
children: [
const Icon(
Icons.schedule,
size: 24,
color: Colors.grey,
),
const SizedBox(width: 20),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
AppLocalizations.of(context)!.logsOlderThan,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500
),
),
const SizedBox(height: 5),
Text(
logsProvider.logsOlderThan != null
? formatTimestampUTC(logsProvider.logsOlderThan!, 'HH:mm - dd/MM/yyyy')
: AppLocalizations.of(context)!.notSelected,
style: const TextStyle(
fontSize: 14,
color: Colors.grey
),
)
],
)
],
),
),
),
),
Material(
color: Colors.transparent,
child: InkWell(
onTap: () => {},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Row(
children: [
const Icon(
Icons.shield_rounded,
size: 24,
color: Colors.grey,
),
const SizedBox(width: 20),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
AppLocalizations.of(context)!.responseStatus,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500
),
),
const SizedBox(height: 5),
const Text(
"12/12/2000",
style: TextStyle(
fontSize: 14,
color: Colors.grey
),
)
],
)
],
),
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
TextButton(
onPressed: resetFilters,
child: Text(AppLocalizations.of(context)!.resetFilters)
),
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(AppLocalizations.of(context)!.close)
),
],
),
)
],
),
);
}
}