invoice/lib/ui/app/dialogs/health_check_dialog.dart

213 lines
6.6 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:invoiceninja_flutter/data/models/health_check_model.dart';
import 'package:invoiceninja_flutter/data/models/serializers.dart';
import 'package:invoiceninja_flutter/data/web_client.dart';
import 'package:invoiceninja_flutter/redux/app/app_actions.dart';
import 'package:invoiceninja_flutter/redux/app/app_state.dart';
import 'package:invoiceninja_flutter/ui/app/dialogs/error_dialog.dart';
import 'package:invoiceninja_flutter/utils/localization.dart';
class HealthCheckDialog extends StatefulWidget {
@override
_HealthCheckDialogState createState() => _HealthCheckDialogState();
}
class _HealthCheckDialogState extends State<HealthCheckDialog> {
HealthCheckResponse _response;
@override
void didChangeDependencies() {
if (_response == null) {
runCheck();
}
super.didChangeDependencies();
}
void runCheck() {
setState(() {
_response = null;
});
final webClient = WebClient();
final state = StoreProvider.of<AppState>(context).state;
final credentials = state.credentials;
final url = '${credentials.url}/health_check';
webClient.get(url, credentials.token).then((dynamic response) {
setState(() {
_response = serializers.deserializeWith(
HealthCheckResponse.serializer, response);
});
}).catchError((dynamic error) {
showDialog<ErrorDialog>(
context: context,
builder: (BuildContext context) {
return ErrorDialog(error);
});
});
}
void clearCache() {
setState(() {
_response = null;
});
final webClient = WebClient();
final store = StoreProvider.of<AppState>(context);
final state = store.state;
final credentials = state.credentials;
final url = '${credentials.url}/ping?clear_cache=true';
webClient.get(url, credentials.token).then((dynamic response) {
store.dispatch(RefreshData(
completer: Completer<Null>()
..future.then((value) {
runCheck();
})));
}).catchError((dynamic error) {
showDialog<ErrorDialog>(
context: context,
builder: (BuildContext context) {
return ErrorDialog(error);
});
});
}
String _parseVersion(String version) =>
RegExp(r'(\d+\.\d+.\d+)').stringMatch(version);
@override
Widget build(BuildContext context) {
final localization = AppLocalization.of(context);
final webPhpVersion =
_parseVersion(_response?.phpVersion?.currentPHPVersion ?? '');
final cliPhpVersion =
_parseVersion(_response?.phpVersion?.currentPHPCLIVersion ?? '');
return AlertDialog(
content: _response == null
? Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: LinearProgressIndicator(),
),
Text('${localization.loading}...'),
],
)
: Column(
mainAxisSize: MainAxisSize.min,
children: [
_HealthListTile(
title: 'System Health',
isValid: _response.systemHealth,
),
_HealthListTile(
title: 'Database Check',
isValid: _response.dbCheck,
),
_HealthListTile(
title: 'PHP Version',
isValid: _response.phpVersion.isOkay,
subtitle: webPhpVersion == cliPhpVersion
? 'v$webPhpVersion'
: 'Web: v$webPhpVersion\nCLI: v$cliPhpVersion}',
),
if (!_response.execEnabled)
_HealthListTile(
title: 'PHP Exec',
isValid: false,
subtitle: 'Not enabled',
),
if (!_response.openBasedir)
_HealthListTile(
title: 'Open Basedir',
isValid: false,
subtitle: 'Not enabled',
),
if (!_response.envWritable)
_HealthListTile(
title: '.env Writable',
isValid: _response.envWritable,
),
if (!_response.cacheEnabled)
_HealthListTile(
title: 'Config Cached',
isValid: _response.cacheEnabled ? true : null,
),
if (_response.phantomEnabled)
_HealthListTile(
title: 'Using PhantomJS',
subtitle: 'Use node to generate PDFs locally',
)
else ...[
_HealthListTile(
title: 'Node Version',
isValid: _response.nodeStatus.isNotEmpty,
subtitle: _response.nodeStatus,
),
_HealthListTile(
title: 'NPM Version',
isValid: _response.npmStatus.isNotEmpty,
subtitle: 'v' + _response.npmStatus,
),
]
],
),
actions: _response == null
? []
: [
FlatButton(
child: Text(localization.clearCache.toUpperCase()),
onPressed: () => clearCache(),
),
FlatButton(
child: Text(localization.refresh.toUpperCase()),
onPressed: () => runCheck(),
),
FlatButton(
child: Text(localization.close.toUpperCase()),
onPressed: () => Navigator.of(context).pop(),
)
],
);
}
}
class _HealthListTile extends StatelessWidget {
const _HealthListTile({
@required this.title,
this.isValid,
this.subtitle,
});
final String title;
final bool isValid;
final String subtitle;
@override
Widget build(BuildContext context) {
return ListTile(
title: Text(title),
subtitle: Text(subtitle != null
? subtitle
: (isValid == null ? 'Warning' : (isValid ? 'Passed' : 'Failed'))),
trailing: Icon(
isValid == null
? Icons.warning
: (isValid ? Icons.check_circle_outline : Icons.error_outline),
color: isValid == null
? Colors.orange
: (isValid ? Colors.green : Colors.red),
),
);
}
}