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();
}
Map<String, dynamic> createDefaultSettings() => {'EventLevel': 'info'};

View File

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

View File

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

View File

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