From 60f4934e605f5df3388ad6d63f5b4970272d1cef Mon Sep 17 00:00:00 2001 From: Nikolai Rodionov Date: Thu, 2 May 2024 19:09:44 +0200 Subject: [PATCH] Some updates to the frontent --- lib/api/grpc/environments.dart | 15 ++- lib/components/create_env_form.dart | 157 ++++++++++++++++----------- lib/components/environment_card.dart | 24 +++- lib/components/environments.dart | 28 +++-- lib/helpers/providers/common.dart | 54 ++++++++- lib/helpers/providers/hetzner.dart | 66 +++++++---- lib/main.dart | 2 +- pubspec.lock | 2 +- 8 files changed, 240 insertions(+), 108 deletions(-) diff --git a/lib/api/grpc/environments.dart b/lib/api/grpc/environments.dart index ff91708..136d911 100644 --- a/lib/api/grpc/environments.dart +++ b/lib/api/grpc/environments.dart @@ -7,13 +7,15 @@ class EnvironmentLocalData { required this.serverLocation, required this.provider, required this.name, - required this.description}); + required this.description, + this.uuid}); final String name; final String description; final String provider; final String serverType; final String serverLocation; + String? uuid; } class EnvironmentsGrpc { @@ -24,9 +26,9 @@ class EnvironmentsGrpc { EnvironmentsGrpc(channel) : envStub = EnvironmentsClient(channel); // Get environments from the API - Future get(String name, SoftplayerCreds creds) async { + Future get(String uuid, SoftplayerCreds creds) async { final request = GetOptions( - metadata: EnvironmentMetadata(name: name), + id: EnvironmentId(uuid: uuid), ownerId: OwnerId(uuid: creds.uuid), token: Token(token: creds.token), ); @@ -34,6 +36,7 @@ class EnvironmentsGrpc { try { final response = await envStub.get(request); return EnvironmentLocalData( + uuid: uuid, serverType: response.spec.serverType.toString(), serverLocation: response.spec.serverLocation.toString(), provider: response.spec.provider.toString(), @@ -46,9 +49,7 @@ class EnvironmentsGrpc { Future create( EnvironmentLocalData data, SoftplayerCreds creds) async { - Location.values.forEach((element) => print(element.toString() + " - " + data.serverLocation)); - print(ServerType.values); - + print(data); final request = CreateOptions( metadata: EnvironmentMetadata(description: data.description, name: data.name), @@ -68,6 +69,7 @@ class EnvironmentsGrpc { try { final response = await envStub.create(request); return EnvironmentLocalData( + uuid: response.id.uuid, serverType: response.spec.serverType.toString(), serverLocation: response.spec.serverLocation.toString(), provider: response.spec.provider.toString(), @@ -88,6 +90,7 @@ class EnvironmentsGrpc { ), )) { envs.add(EnvironmentLocalData( + uuid: feature.id.uuid, serverType: feature.spec.serverType.toString(), serverLocation: feature.spec.serverLocation.toString(), provider: feature.spec.provider.toString(), diff --git a/lib/components/create_env_form.dart b/lib/components/create_env_form.dart index f9b5c26..326d22e 100644 --- a/lib/components/create_env_form.dart +++ b/lib/components/create_env_form.dart @@ -2,24 +2,30 @@ import 'dart:html'; import 'dart:js' as js; import 'package:flutter/material.dart'; import 'package:grpc/grpc_web.dart'; +import 'package:softplayer_dart_proto/main.dart'; import 'package:softplayer_web/api/grpc/creds.dart'; import 'package:softplayer_web/api/grpc/environments.dart'; +import 'package:softplayer_web/helpers/providers/common.dart' as helper; class CreateEnvForm extends StatefulWidget { CreateEnvForm(GrpcWebClientChannel channel, {super.key}) : environmentsGrpc = EnvironmentsGrpc(channel); final EnvironmentsGrpc environmentsGrpc; + @override State createState() => _CreateEnvFormState(); } class _CreateEnvFormState extends State { final _formKey = GlobalKey(); - + final String defaultProvider = Provider.PROVIDER_HETZNER.toString(); + late helper.Provider provider = + helper.ProviderHelper().getProvider(defaultProvider); + late String defaultLocation = provider.defaultLocation(); final nameCtl = TextEditingController(); final descriptionCtl = TextEditingController(); - String? serverLocation; - String? serverType; + late String? serverLocation = defaultLocation; + late String? serverType = ServerType.SERVER_TYPE_REGULAR.toString(); void createEnvironment() { // Validate returns true if the form is valid, or false otherwise. @@ -31,14 +37,13 @@ class _CreateEnvFormState extends State { EnvironmentLocalData( serverType: serverType!, serverLocation: serverLocation!, - provider: "", + provider: defaultProvider, name: name, description: description), SoftplayerCredsHelpers().fromLocalStorage()) .then((rs) { Navigator.pop(context); }).catchError((e) { - print(e); GrpcError error = e; String msg; if (error.message != null) { @@ -56,65 +61,91 @@ class _CreateEnvFormState extends State { } } - Widget createEnvForm() => SizedBox( - width: 420, - child: Form( - key: _formKey, - child: Center( - child: Column(children: [ - Divider(), - Text("Provider the environment metadata"), - TextFormField( - autofocus: true, - controller: nameCtl, - decoration: const InputDecoration( - hintText: "Enter the environment name", - icon: Icon(Icons.computer), - label: Text("Name"), - ), - cursorWidth: 1, - cursorHeight: 18, - cursorRadius: const Radius.circular(10), - ), - TextFormField( - autofocus: true, - controller: descriptionCtl, - decoration: const InputDecoration( - hintText: "Enter the environment description", - icon: Icon(Icons.description), - label: Text("Description"), - ), - maxLength: 360, - cursorWidth: 1, - cursorHeight: 18, - cursorRadius: const Radius.circular(10), - ), - Divider(), - DropdownButtonFormField( - decoration: const InputDecoration( - hintText: "Enter the environment description", - icon: Icon(Icons.computer), - label: Text("Type of the server"), - ), - value: null, - isDense: true, - items: [ - DropdownMenuItem( - child: Text("lala1"), - value: "test1", + String defaultServerType = "Regular"; + Widget createEnvForm() => SingleChildScrollView( + child: SizedBox( + width: 420, + child: Form( + key: _formKey, + child: Center( + child: Column(children: [ + TextFormField( + autofocus: true, + controller: nameCtl, + decoration: const InputDecoration( + hintText: "Enter the environment name", + icon: Icon(Icons.computer), + label: Text("Name"), + ), + cursorWidth: 1, + cursorHeight: 18, + cursorRadius: const Radius.circular(10), ), - DropdownMenuItem(child: Text("lala2"), value: "test2"), - DropdownMenuItem(child: Text("lala3"), value: "test3"), - DropdownMenuItem(child: Text("lala4"), value: "test4"), - ], - onChanged: (value) => print(value), - ), - TextButton( - onPressed: () => js.context.callMethod( - 'open', ['https://stackoverflow.com/questions/ask']), - child: Text("Read more about environment types here"), - ) - ])))); + TextFormField( + autofocus: false, + controller: descriptionCtl, + decoration: const InputDecoration( + hintText: "Enter the environment description", + icon: Icon(Icons.description), + label: Text("Description"), + ), + maxLength: 360, + cursorWidth: 1, + cursorHeight: 18, + cursorRadius: const Radius.circular(10), + ), + DropdownButtonFormField( + decoration: const InputDecoration( + hintText: "Enter the environment description", + icon: Icon(Icons.computer), + label: Text("Type of the server"), + ), + value: ServerType.SERVER_TYPE_REGULAR.toString(), + isDense: true, + items: ServerType.values + .where((element) => + element != ServerType.SERVER_TYPE_CUSTOM && + element != ServerType.SERVER_TYPE_UNSPECIFIED) + .map((serverType) { + return DropdownMenuItem( + value: serverType.toString(), + child: Text(helper.ProviderHelper() + .getServerType(serverType.toString())), + ); + }).toList(), + onChanged: (value) => setState(() { + serverType = value; + }), + ), + TextButton( + onPressed: () => js.context.callMethod( + 'open', ['https://stackoverflow.com/questions/ask']), + child: Text("Read more about environment types here"), + ), + DropdownButtonFormField( + decoration: const InputDecoration( + hintText: "Enter the environment location", + icon: Icon(Icons.location_on), + label: Text("Location of the server"), + ), + value: defaultLocation, + isDense: true, + items: Location.values + .where((element) => element + .toString() + .contains(provider.getProviderName().toUpperCase())) + .map((serverType) { + return DropdownMenuItem( + value: serverType.toString(), + child: Text( + provider.getServerLocation(serverType.toString())), + ); + }).toList(), + onChanged: (value) => setState(() { + serverLocation = value; + }), + ), + ]))))); List createEnvActions() => [ TextButton( onPressed: createEnvironment, diff --git a/lib/components/environment_card.dart b/lib/components/environment_card.dart index 49c41f3..6869dda 100644 --- a/lib/components/environment_card.dart +++ b/lib/components/environment_card.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:softplayer_web/api/grpc/environments.dart'; +import 'package:softplayer_web/helpers/providers/common.dart'; class EnvirnomentCard extends StatelessWidget { final EnvironmentLocalData env; @@ -11,6 +12,17 @@ class EnvirnomentCard extends StatelessWidget { @override Widget build(BuildContext context) { + Provider provider = ProviderHelper().getProvider(env.provider); + + String serverType; + String serverLocation; + try { + serverType = ProviderHelper().getServerType(env.serverType); + serverLocation = provider.getServerLocation(env.serverLocation); + } catch (e) { + rethrow; + } + return Card( child: SelectionArea( child: Column( @@ -25,21 +37,21 @@ class EnvirnomentCard extends StatelessWidget { top: BorderSide.none, ), children: [ - TableRow(children: [ - Text("Provider"), - Text(env.provider), - ]), TableRow(children: [ Text("Description"), Text(env.description), ]), + TableRow(children: [ + Text("Provider"), + Text(provider.getProviderName()), + ]), TableRow(children: [ Text("Server Type"), - Text(env.serverType), + Text(serverType), ]), TableRow(children: [ Text("Location"), - Text(env.serverLocation), + Text(serverLocation), ]), ], ) diff --git a/lib/components/environments.dart b/lib/components/environments.dart index 60bcb02..2c53655 100644 --- a/lib/components/environments.dart +++ b/lib/components/environments.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:grpc/grpc_web.dart'; import 'package:softplayer_web/api/grpc/creds.dart'; import 'package:softplayer_web/api/grpc/environments.dart'; @@ -48,16 +49,25 @@ class _EnvirnomentListState extends State { if (snapshot.hasData) { var data = snapshot.requireData; if (data.isNotEmpty) { - return GridView.count( - crossAxisCount: 4, - children: snapshot.data! - .map((e) => EnvirnomentCard( - env: e, - )) - .toList(), - ); + return Column(children: [ + Flexible( + child: TextField( + decoration: InputDecoration( + icon: Icon(Icons.search), + ), + ), + ), + Flexible( + child: GridView.count( + crossAxisCount: 4, + children: snapshot.data! + .map((e) => EnvirnomentCard( + env: e, + )) + .toList(), + )) + ]); } else { - print("npo data"); return Center( child: Container( height: 300, diff --git a/lib/helpers/providers/common.dart b/lib/helpers/providers/common.dart index 0fc9805..7973c47 100644 --- a/lib/helpers/providers/common.dart +++ b/lib/helpers/providers/common.dart @@ -1,4 +1,52 @@ +import 'package:softplayer_dart_proto/environments/environments_v1.pbenum.dart'; +import 'package:softplayer_web/helpers/providers/hetzner.dart'; + abstract class Provider { - String getServerType(String serverType); - String rawServerType(String serverType); -} \ No newline at end of file + String getServerLocation(String serverLocation); + String rawServerLocation(String serverLocation); + String defaultLocation(); + + String getProviderName(); + String rawProviderName(); +} + +class ProviderHelper { + String getServerType(String serverType) { + if (serverType == ServerType.SERVER_TYPE_STARTER.toString()) { + return "Starter"; + } else if (serverType == ServerType.SERVER_TYPE_REGULAR.toString()) { + return "Regular"; + } else if (serverType == ServerType.SERVER_TYPE_PLUS.toString()) { + return "Plus"; + } else if (serverType == ServerType.SERVER_TYPE_PRO.toString()) { + return "Pro"; + } else if (serverType == ServerType.SERVER_TYPE_CUSTOM.toString()) { + throw 'Custom server type is not yet supported'; + } else { + throw 'Unknown server type'; + } + } + + String rawServerType(String serverType) { + if (serverType == "Starter") { + return ServerType.SERVER_TYPE_STARTER.toString(); + } else if (serverType == "Regular") { + return ServerType.SERVER_TYPE_REGULAR.toString(); + } else if (serverType == "Plus") { + return ServerType.SERVER_TYPE_PLUS.toString(); + } else if (serverType == "Pro") { + return ServerType.SERVER_TYPE_PRO.toString(); + } else { + throw 'Unknown server type'; + } + } + + Hetzner getProvider(String provider) { + switch (provider) { + case "hetzner" || "PROVIDER_HETZNER": + return Hetzner(); + default: + throw "unknown prodiver"; + } + } +} diff --git a/lib/helpers/providers/hetzner.dart b/lib/helpers/providers/hetzner.dart index 9dc9c31..5a6e50d 100644 --- a/lib/helpers/providers/hetzner.dart +++ b/lib/helpers/providers/hetzner.dart @@ -1,26 +1,54 @@ -import 'package:softplayer_web/helpers/providers/common.dart'; +import 'package:softplayer_dart_proto/environments/environments_v1.pbgrpc.dart'; +import 'package:softplayer_web/helpers/providers/common.dart' as helper; + +class Hetzner implements helper.Provider { -class Hetzner implements Provider { @override - String getServerType(String serverType) { - switch (serverType) { - case "SERVER_TYPE_STARTER": - return "starter"; - case "SERVER_TYPE_S": - return "starter"; - case "SERVER_TYPE_STARTER": - return "starter"; - case "SERVER_TYPE_STARTER": - return "starter"; - - default: - } - throw UnimplementedError(); + String getProviderName() { + return "Hetzner"; } @override - String rawServerType(string) { - // TODO: implement rawServerType - throw UnimplementedError(); + String rawProviderName() { + return Provider.PROVIDER_HETZNER.toString(); + } + + @override + String getServerLocation(String serverType) { + if (serverType == Location.LOCATION_HETZNER_ASHBURN.toString()) { + return "Ashburn, USA"; + } else if (serverType == Location.LOCATION_HETZNER_FALKENSTEIN.toString()) { + return "Falkenstein, Germany"; + } else if (serverType == Location.LOCATION_HETZNER_HELSINKI.toString()) { + return "Helsinki, Finland"; + } else if (serverType == Location.LOCATION_HETZNER_HILLSBORO.toString()) { + return "Hillsboro, USA"; + } else if (serverType == Location.LOCATION_HETZNER_NUREMBERG.toString()) { + return "Nuremberg, Germany"; + } else { + throw 'Unknown server type'; + } + } + + @override + String rawServerLocation(String serverLocation) { + if (serverLocation == "Ashburn, USA") { + return Location.LOCATION_HETZNER_ASHBURN.toString(); + } else if (serverLocation == "Falkenstein, Germany") { + return Location.LOCATION_HETZNER_FALKENSTEIN.toString(); + } else if (serverLocation == "Helsinki, Finland") { + return Location.LOCATION_HETZNER_HELSINKI.toString(); + } else if (serverLocation == "Hillsboro, USA") { + return Location.LOCATION_HETZNER_HILLSBORO.toString(); + } else if (serverLocation == "Nuremberg, Germany") { + return Location.LOCATION_HETZNER_NUREMBERG.toString(); + } else { + throw 'Unknown server type'; + } + } + + @override + String defaultLocation() { + return Location.LOCATION_HETZNER_NUREMBERG.toString(); } } diff --git a/lib/main.dart b/lib/main.dart index 845be2a..661267a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -80,7 +80,7 @@ class _StateRootWidget extends State { EnvirnomentList envList = EnvirnomentList(channel: widget.channel); return Scaffold( body: envList, - appBar: AppBar( + appBar: AppBar( title: const Text("Softplayer"), actions: [ TextButton( diff --git a/pubspec.lock b/pubspec.lock index b16bbdb..96f3714 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -245,7 +245,7 @@ packages: description: path: "." ref: main - resolved-ref: bccaaff90c8ef1e9d23c565a58cab6db841282d3 + resolved-ref: "3bf6e1bef80350848f0f0407685e4eaf868d4c7e" url: "https://git.badhouseplants.net/softplayer/softplayer-dart-proto.git" source: git version: "1.0.0+1"