Create management portal in Flutter #39

This commit is contained in:
Scott E. Graves 2025-03-06 10:03:35 -06:00
parent c1e5bd6b0b
commit 72a2567c83
5 changed files with 65 additions and 23 deletions

View File

@ -25,3 +25,5 @@ String initialCaps(String txt) {
return txt[0].toUpperCase() + txt.substring(1).toLowerCase(); return txt[0].toUpperCase() + txt.substring(1).toLowerCase();
} }
Map<String, dynamic> createDefaultSettings() => {'EventLevel': 'info'};

View File

@ -7,7 +7,11 @@ import 'package:repertory/types/mount_config.dart';
class Mount with ChangeNotifier { class Mount with ChangeNotifier {
final MountConfig mountConfig; final MountConfig mountConfig;
Mount(this.mountConfig) { Mount(this.mountConfig, {isAdd = false}) {
if (isAdd) {
mountConfig.updateSettings({'EventLevel': 'info'});
return;
}
refresh(); refresh();
} }

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:repertory/constants.dart'; import 'package:repertory/constants.dart';
import 'package:repertory/helpers.dart';
import 'package:repertory/models/mount.dart'; import 'package:repertory/models/mount.dart';
import 'package:repertory/types/mount_config.dart'; import 'package:repertory/types/mount_config.dart';
import 'package:repertory/widgets/mount_settings.dart'; import 'package:repertory/widgets/mount_settings.dart';
@ -15,10 +16,10 @@ class AddMountScreen extends StatefulWidget {
class _AddMountScreenState extends State<AddMountScreen> { class _AddMountScreenState extends State<AddMountScreen> {
static const _padding = 15.0; static const _padding = 15.0;
final TextEditingController _mountNameController = TextEditingController();
Mount? _mount; Mount? _mount;
final _mountNameController = TextEditingController();
String _mountType = ""; String _mountType = "";
var _settings = createDefaultSettings();
bool _showAdvanced = false; bool _showAdvanced = false;
@override @override
@ -42,10 +43,15 @@ class _AddMountScreenState extends State<AddMountScreen> {
body: Padding( body: Padding(
padding: const EdgeInsets.all(_padding), padding: const EdgeInsets.all(_padding),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Card( Card(
margin: EdgeInsets.all(_padding),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
const Text('Provider Type'), const Text('Provider Type'),
@ -55,7 +61,6 @@ class _AddMountScreenState extends State<AddMountScreen> {
onChanged: (newValue) { onChanged: (newValue) {
setState(() { setState(() {
_mountType = newValue ?? ""; _mountType = newValue ?? "";
if (_mountType.isNotEmpty) {}
}); });
}, },
items: items:
@ -72,7 +77,10 @@ class _AddMountScreenState extends State<AddMountScreen> {
if (_mountType.isNotEmpty) const SizedBox(height: _padding), if (_mountType.isNotEmpty) const SizedBox(height: _padding),
if (_mountType.isNotEmpty) if (_mountType.isNotEmpty)
Card( Card(
margin: EdgeInsets.all(_padding),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
const Text('Configuration Name'), const Text('Configuration Name'),
@ -89,8 +97,10 @@ class _AddMountScreenState extends State<AddMountScreen> {
: Mount( : Mount(
MountConfig( MountConfig(
name: _mountNameController.text, name: _mountNameController.text,
settings: _settings,
type: _mountType, type: _mountType,
), ),
isAdd: true,
); );
}); });
}, },
@ -99,7 +109,15 @@ class _AddMountScreenState extends State<AddMountScreen> {
), ),
), ),
if (_mount != null) if (_mount != null)
MountSettingsWidget(mount: _mount!, showAdvanced: _showAdvanced), Card(
margin: EdgeInsets.all(_padding),
child: MountSettingsWidget(
isAdd: true,
mount: _mount!,
onChanged: (settings) => _settings = settings,
showAdvanced: _showAdvanced,
),
),
], ],
), ),
), ),

View File

@ -7,7 +7,13 @@ class MountConfig {
Map<String, dynamic> _settings = {}; Map<String, dynamic> _settings = {};
IconData _state = Icons.toggle_off; IconData _state = Icons.toggle_off;
final String _type; final String _type;
MountConfig({required name, required type}) : _name = name, _type = type; MountConfig({required name, required type, Map<String, dynamic>? settings})
: _name = name,
_type = type {
if (settings != null) {
_settings = settings;
}
}
String get name => _name; String get name => _name;
String get path => _path; String get path => _path;

View File

@ -8,11 +8,15 @@ import 'package:repertory/models/mount.dart';
import 'package:settings_ui/settings_ui.dart'; import 'package:settings_ui/settings_ui.dart';
class MountSettingsWidget extends StatefulWidget { class MountSettingsWidget extends StatefulWidget {
final bool isAdd;
final bool showAdvanced; final bool showAdvanced;
final Mount mount; final Mount mount;
final Function? onChanged;
const MountSettingsWidget({ const MountSettingsWidget({
super.key, super.key,
this.isAdd = false,
required this.mount, required this.mount,
this.onChanged,
required this.showAdvanced, required this.showAdvanced,
}); });
@ -33,11 +37,13 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
onPressed: (_) { onPressed: (_) {
setState(() { setState(() {
root[key] = !value; root[key] = !value;
widget.onChanged?.call(_settings);
}); });
}, },
onToggle: (bool nextValue) { onToggle: (bool nextValue) {
setState(() { setState(() {
root[key] = nextValue; root[key] = nextValue;
widget.onChanged?.call(_settings);
}); });
}, },
), ),
@ -70,6 +76,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
onPressed: () { onPressed: () {
setState(() { setState(() {
root[key] = int.parse(updatedValue); root[key] = int.parse(updatedValue);
widget.onChanged?.call(_settings);
}); });
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
@ -114,6 +121,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
onChanged: (newValue) { onChanged: (newValue) {
setState(() { setState(() {
root[key] = int.parse(newValue ?? defaultValue.toString()); root[key] = int.parse(newValue ?? defaultValue.toString());
widget.onChanged?.call(_settings);
}); });
}, },
items: items:
@ -148,6 +156,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
onChanged: (newValue) { onChanged: (newValue) {
setState(() { setState(() {
root[key] = newValue; root[key] = newValue;
widget.onChanged?.call(_settings);
}); });
}, },
items: items:
@ -200,6 +209,7 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
onPressed: () { onPressed: () {
setState(() { setState(() {
root[key] = updatedValue; root[key] = updatedValue;
widget.onChanged?.call(_settings);
}); });
Navigator.of(context).pop(); Navigator.of(context).pop();
}, },
@ -629,24 +639,26 @@ class _MountSettingsWidgetState extends State<MountSettingsWidget> {
@override @override
void dispose() { void dispose() {
var settings = widget.mount.mountConfig.settings; if (!widget.isAdd) {
if (!DeepCollectionEquality().equals(_settings, settings)) { var settings = widget.mount.mountConfig.settings;
_settings.forEach((key, value) { if (!DeepCollectionEquality().equals(_settings, settings)) {
if (!DeepCollectionEquality().equals(settings[key], value)) { _settings.forEach((key, value) {
if (value is Map<String, dynamic>) { if (!DeepCollectionEquality().equals(settings[key], value)) {
value.forEach((subKey, subValue) { if (value is Map<String, dynamic>) {
if (!DeepCollectionEquality().equals( value.forEach((subKey, subValue) {
settings[key][subKey], if (!DeepCollectionEquality().equals(
subValue, settings[key][subKey],
)) { subValue,
widget.mount.setValue('$key.$subKey', subValue.toString()); )) {
} widget.mount.setValue('$key.$subKey', subValue.toString());
}); }
} else { });
widget.mount.setValue(key, value.toString()); } else {
widget.mount.setValue(key, value.toString());
}
} }
} });
}); }
} }
super.dispose(); super.dispose();
} }