Added edit client

This commit is contained in:
Juan Gilsanz Polo 2022-10-07 17:08:23 +02:00
parent 89e3add4c7
commit e78dbb232f
7 changed files with 219 additions and 60 deletions

View file

@ -193,5 +193,7 @@
"serverAddress": "Server address",
"noUpstreamServers": "No upstream servers.",
"willBeUsedGeneralServers": "General upstream servers will be used.",
"added": "Added"
"added": "Added",
"clientUpdatedSuccessfully": "Client updated successfully",
"clientNotUpdated": "Client could not be updated"
}

View file

@ -193,5 +193,7 @@
"serverAddress": "Dirección del servidor",
"noUpstreamServers": "No hay servidores de salida.",
"willBeUsedGeneralServers": "Se usarán los servidores de salida generales.",
"added": "Añadidos"
"added": "Añadidos",
"clientUpdatedSuccessfully": "Cliente actualizado correctamente",
"clientNotUpdated": "El cliente no pudo ser actualizado"
}

View file

@ -17,7 +17,7 @@ ClientsData clientsFromJson(String str) => ClientsData.fromJson(json.decode(str)
String clientsToJson(ClientsData data) => json.encode(data.toJson());
class ClientsData {
final List<Client> clients;
List<Client> clients;
final List<AutoClient> autoClientsData;
final List<String> supportedTags;
ClientsAllowedBlocked? clientsAllowedBlocked;
@ -80,7 +80,7 @@ class WhoisInfo {
class Client {
final String name;
final dynamic blockedServices;
final List<String> blockedServices;
final List<String> ids;
final List<String> tags;
final List<dynamic> upstreams;
@ -107,7 +107,7 @@ class Client {
factory Client.fromJson(Map<String, dynamic> json) => Client(
name: json["name"],
blockedServices: json["blocked_services"],
blockedServices: List<String>.from(json["blocked_services"]),
ids: List<String>.from(json["ids"].map((x) => x)),
tags: List<String>.from(json["tags"].map((x) => x)),
upstreams: List<dynamic>.from(json["upstreams"].map((x) => x)),

View file

@ -5,7 +5,10 @@ import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:adguard_home_manager/screens/clients/fab.dart';
import 'package:adguard_home_manager/screens/clients/client_modal.dart';
import 'package:adguard_home_manager/classes/process_modal.dart';
import 'package:adguard_home_manager/services/http_requests.dart';
import 'package:adguard_home_manager/models/clients.dart';
import 'package:adguard_home_manager/providers/app_config_provider.dart';
import 'package:adguard_home_manager/providers/servers_provider.dart';
@ -25,6 +28,58 @@ class AddedList extends StatelessWidget {
final serversProvider = Provider.of<ServersProvider>(context);
final appConfigProvider = Provider.of<AppConfigProvider>(context);
void confirmEditClient(Client client) async {
ProcessModal processModal = ProcessModal(context: context);
processModal.open(AppLocalizations.of(context)!.addingClient);
final result = await postUpdateClient(server: serversProvider.selectedServer!, data: {
'name': client.name,
'data': client.toJson()
});
processModal.close();
if (result['result'] == 'success') {
ClientsData clientsData = serversProvider.clients.data!;
clientsData.clients = clientsData.clients.map((e) {
if (e.name == client.name) {
return client;
}
else {
return e;
}
}).toList();
serversProvider.setClientsData(clientsData);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(AppLocalizations.of(context)!.clientUpdatedSuccessfully),
backgroundColor: Colors.green,
)
);
}
else {
appConfigProvider.addLog(result['log']);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(AppLocalizations.of(context)!.clientNotUpdated),
backgroundColor: Colors.red,
)
);
}
}
void openClientModal(Client client) {
showModalBottomSheet(
context: context,
builder: (ctx) => ClientModal(
client: client,
onConfirm: confirmEditClient
),
isScrollControlled: true,
backgroundColor: Colors.transparent
);
}
return Stack(
children: [
if (data.isNotEmpty) RefreshIndicator(
@ -34,7 +89,7 @@ class AddedList extends StatelessWidget {
itemCount: data.length,
itemBuilder: (context, index) => ListTile(
isThreeLine: true,
onTap: () => {},
onTap: () => openClientModal(data[index]),
title: Padding(
padding: const EdgeInsets.only(bottom: 5),
child: Text(data[index].name),

View file

@ -9,20 +9,23 @@ import 'package:adguard_home_manager/screens/clients/tags_modal.dart';
import 'package:adguard_home_manager/providers/servers_provider.dart';
import 'package:adguard_home_manager/models/clients.dart';
class AddClientModal extends StatefulWidget {
class ClientModal extends StatefulWidget {
final Client? client;
final void Function(Client) onConfirm;
const AddClientModal({
const ClientModal({
Key? key,
this.client,
required this.onConfirm
}) : super(key: key);
@override
State<AddClientModal> createState() => _AddClientModalState();
State<ClientModal> createState() => _ClientModalState();
}
class _AddClientModalState extends State<AddClientModal> {
class _ClientModalState extends State<ClientModal> {
final Uuid uuid = const Uuid();
bool editMode = true;
TextEditingController nameController = TextEditingController();
@ -59,6 +62,28 @@ class _AddClientModalState extends State<AddClientModal> {
return false;
}
}
@override
void initState() {
if (widget.client != null) {
editMode = false;
nameController.text = widget.client!.name;
selectedTags = widget.client!.tags;
identifiersControllers = widget.client!.ids.map((e) => {
'id': uuid.v4(),
'controller': TextEditingController(text: e)
}).toList();
useGlobalSettingsFiltering = widget.client!.useGlobalSettings;
enableFiltering = widget.client!.filteringEnabled;
enableParentalControl = widget.client!.parentalEnabled;
enableSafeBrowsing = widget.client!.safebrowsingEnabled;
enableSafeSearch = widget.client!.safesearchEnabled;
useGlobalSettingsServices = widget.client!.useGlobalBlockedServices;
blockedServices = widget.client!.blockedServices;
}
super.initState();
}
@override
Widget build(BuildContext context) {
@ -159,12 +184,14 @@ class _AddClientModalState extends State<AddClientModal> {
Widget settignsTile({
required String label,
required bool? value,
required void Function(bool) onChange
void Function(bool)? onChange
}) {
return Material(
color: Colors.transparent,
child: InkWell(
onTap: value != null ? () => onChange(!value) : null,
onTap: onChange != null
? value != null ? () => onChange(!value) : null
: null,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30,
@ -179,9 +206,9 @@ class _AddClientModalState extends State<AddClientModal> {
fontSize: 15
),
),
value != null
useGlobalSettingsFiltering == false
? Switch(
value: value,
value: value!,
onChanged: onChange,
activeColor: Theme.of(context).primaryColor,
)
@ -238,6 +265,7 @@ class _AddClientModalState extends State<AddClientModal> {
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: TextFormField(
enabled: widget.client != null ? false : true,
controller: nameController,
onChanged: (_) => checkValidValues(),
decoration: InputDecoration(
@ -255,7 +283,7 @@ class _AddClientModalState extends State<AddClientModal> {
Material(
color: Colors.transparent,
child: InkWell(
onTap: openTagsModal,
onTap: editMode == true ? () => openTagsModal() : null,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 10, horizontal: 20
@ -296,7 +324,7 @@ class _AddClientModalState extends State<AddClientModal> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
sectionLabel(AppLocalizations.of(context)!.identifiers),
Padding(
if (editMode == true) Padding(
padding: const EdgeInsets.only(right: 20),
child: IconButton(
onPressed: () => setState(() => identifiersControllers.add({
@ -316,8 +344,11 @@ class _AddClientModalState extends State<AddClientModal> {
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
width: MediaQuery.of(context).size.width - 108,
width: editMode == true
? MediaQuery.of(context).size.width - 108
: MediaQuery.of(context).size.width - 40,
child: TextFormField(
enabled: editMode,
controller: controller['controller'],
onChanged: (_) => checkValidValues(),
decoration: InputDecoration(
@ -332,16 +363,18 @@ class _AddClientModalState extends State<AddClientModal> {
),
),
),
const SizedBox(width: 20),
Padding(
padding: const EdgeInsets.only(bottom: 25),
child: IconButton(
onPressed: () => setState(
() => identifiersControllers = identifiersControllers.where((e) => e['id'] != controller['id']).toList()
),
icon: const Icon(Icons.remove_circle_outline_outlined)
),
)
if (editMode == true) ...[
const SizedBox(width: 20),
Padding(
padding: const EdgeInsets.only(bottom: 25),
child: IconButton(
onPressed: () => setState(
() => identifiersControllers = identifiersControllers.where((e) => e['id'] != controller['id']).toList()
),
icon: const Icon(Icons.remove_circle_outline_outlined)
),
)
]
],
),
),
@ -364,7 +397,9 @@ class _AddClientModalState extends State<AddClientModal> {
color: Theme.of(context).primaryColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(28),
child: InkWell(
onTap: enableDisableGlobalSettingsFiltering,
onTap: editMode
? () => enableDisableGlobalSettingsFiltering()
: null,
borderRadius: BorderRadius.circular(28),
child: Padding(
padding: const EdgeInsets.symmetric(
@ -382,7 +417,9 @@ class _AddClientModalState extends State<AddClientModal> {
),
Switch(
value: useGlobalSettingsFiltering,
onChanged: (value) => enableDisableGlobalSettingsFiltering(),
onChanged: editMode == true
? (value) => enableDisableGlobalSettingsFiltering()
: null,
activeColor: Theme.of(context).primaryColor,
)
],
@ -395,22 +432,30 @@ class _AddClientModalState extends State<AddClientModal> {
settignsTile(
label: AppLocalizations.of(context)!.enableFiltering,
value: enableFiltering,
onChange: (value) => setState(() => enableFiltering = value)
onChange: editMode == true
? (value) => setState(() => enableFiltering = value)
: null
),
settignsTile(
label: AppLocalizations.of(context)!.enableSafeBrowsing,
value: enableSafeBrowsing,
onChange: (value) => setState(() => enableSafeBrowsing = value)
onChange: editMode == true
? (value) => setState(() => enableSafeBrowsing = value)
: null
),
settignsTile(
label: AppLocalizations.of(context)!.enableParentalControl,
value: enableParentalControl,
onChange: (value) => setState(() => enableParentalControl = value)
onChange: editMode == true
? (value) => setState(() => enableParentalControl = value)
: null
),
settignsTile(
label: AppLocalizations.of(context)!.enableSafeSearch,
value: enableSafeSearch,
onChange: (value) => setState(() => enableSafeSearch = value)
onChange: editMode == true
? (value) => setState(() => enableSafeSearch = value)
: null
),
sectionLabel(AppLocalizations.of(context)!.blockedServices),
Padding(
@ -419,7 +464,9 @@ class _AddClientModalState extends State<AddClientModal> {
color: Theme.of(context).primaryColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(28),
child: InkWell(
onTap: () => updateServicesGlobalSettings(!useGlobalSettingsServices),
onTap: editMode == true
? () => updateServicesGlobalSettings(!useGlobalSettingsServices)
: null,
borderRadius: BorderRadius.circular(28),
child: Padding(
padding: const EdgeInsets.symmetric(
@ -437,7 +484,9 @@ class _AddClientModalState extends State<AddClientModal> {
),
Switch(
value: useGlobalSettingsServices,
onChanged: updateServicesGlobalSettings,
onChanged: editMode == true
? (value) => updateServicesGlobalSettings(value)
: null,
activeColor: Theme.of(context).primaryColor,
)
],
@ -450,8 +499,10 @@ class _AddClientModalState extends State<AddClientModal> {
Material(
color: Colors.transparent,
child: InkWell(
onTap: useGlobalSettingsServices == false
? openServicesModal
onTap: editMode == true
? useGlobalSettingsServices == false
? openServicesModal
: null
: null,
child: Padding(
padding: const EdgeInsets.symmetric(
@ -498,7 +549,7 @@ class _AddClientModalState extends State<AddClientModal> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
sectionLabel(AppLocalizations.of(context)!.upstreamServers),
Padding(
if (editMode == true) Padding(
padding: const EdgeInsets.only(right: 20),
child: IconButton(
onPressed: () => setState(() => upstreamServers.add({
@ -520,6 +571,7 @@ class _AddClientModalState extends State<AddClientModal> {
SizedBox(
width: MediaQuery.of(context).size.width - 108,
child: TextFormField(
enabled: editMode,
controller: controller['controller'],
onChanged: (_) => checkValidValues(),
decoration: InputDecoration(
@ -574,29 +626,43 @@ class _AddClientModalState extends State<AddClientModal> {
Padding(
padding: const EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisAlignment: widget.client == null || (widget.client != null && editMode == true)
? MainAxisAlignment.end
: MainAxisAlignment.spaceBetween,
children: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(AppLocalizations.of(context)!.cancel)
if (widget.client != null && editMode == false) TextButton(
onPressed: () => setState(() => editMode = true),
child: Text(AppLocalizations.of(context)!.edit)
),
const SizedBox(width: 20),
TextButton(
onPressed: checkValidValues() == true
? () {
createClient();
Navigator.pop(context);
}
: null,
child: Text(
AppLocalizations.of(context)!.confirm,
style: TextStyle(
color: checkValidValues() == true
? Theme.of(context).primaryColor
: Colors.grey
Row(
children: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(AppLocalizations.of(context)!.cancel)
),
)
),
if (widget.client == null || (widget.client != null && editMode == true)) ...[
const SizedBox(width: 20),
TextButton(
onPressed: checkValidValues() == true
? () {
createClient();
Navigator.pop(context);
}
: null,
child: Text(
widget.client != null && editMode == true
? AppLocalizations.of(context)!.save
: AppLocalizations.of(context)!.confirm,
style: TextStyle(
color: checkValidValues() == true
? Theme.of(context).primaryColor
: Colors.grey
),
)
),
]
],
)
],
),
),

View file

@ -5,7 +5,7 @@ import 'package:provider/provider.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:adguard_home_manager/screens/clients/block_client_modal.dart';
import 'package:adguard_home_manager/screens/clients/add_client_modal.dart';
import 'package:adguard_home_manager/screens/clients/client_modal.dart';
import 'package:adguard_home_manager/models/clients.dart';
import 'package:adguard_home_manager/services/http_requests.dart';
@ -118,7 +118,7 @@ class ClientsFab extends StatelessWidget {
void openAddClient() {
showModalBottomSheet(
context: context,
builder: (ctx) => AddClientModal(
builder: (ctx) => ClientModal(
onConfirm: confirmAddClient
),
isScrollControlled: true,

View file

@ -635,4 +635,38 @@ Future postAddClient({
else {
return result;
}
}
Future postUpdateClient({
required Server server,
required Map<String, dynamic> data,
}) async {
final result = await apiRequest(
urlPath: '/clients/update',
method: 'post',
server: server,
body: data,
type: 'update_client'
);
if (result['hasResponse'] == true) {
if (result['statusCode'] == 200) {
return {'result': 'success'};
}
else {
return {
'result': 'error',
'log': AppLog(
type: 'update_client',
dateTime: DateTime.now(),
message: 'error_code_not_expected',
statusCode: result['statusCode'].toString(),
resBody: result['body']
)
};
}
}
else {
return result;
}
}