Some updates
This commit is contained in:
		
							
								
								
									
										
											BIN
										
									
								
								assets/main_background.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/main_background.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 2.2 MiB | 
| @@ -2,13 +2,18 @@ import 'package:softplayer_dart_proto/main.dart'; | ||||
| import 'package:softplayer_web/api/grpc/creds.dart'; | ||||
|  | ||||
| class EnvironmentLocalData { | ||||
|   EnvironmentLocalData({ | ||||
|     required this.uuid, | ||||
|     required this.token, | ||||
|   }); | ||||
|   EnvironmentLocalData( | ||||
|       {required this.serverType, | ||||
|       required this.serverLocation, | ||||
|       required this.provider, | ||||
|       required this.name, | ||||
|       required this.description}); | ||||
|  | ||||
|   String uuid; | ||||
|   String token; | ||||
|   final String name; | ||||
|   final String description; | ||||
|   final String provider; | ||||
|   final String serverType; | ||||
|   final String serverLocation; | ||||
| } | ||||
|  | ||||
| class EnvironmentsGrpc { | ||||
| @@ -19,23 +24,62 @@ class EnvironmentsGrpc { | ||||
|   EnvironmentsGrpc(channel) : envStub = EnvironmentsClient(channel); | ||||
|  | ||||
|   // Get environments from the API | ||||
|   Future<EnvironmentFull> get(String name, SoftplayerCreds creds) async { | ||||
|   Future<EnvironmentLocalData> get(String name, SoftplayerCreds creds) async { | ||||
|     final request = GetOptions( | ||||
|       name: EnvironmentName(name: name), | ||||
|       metadata: EnvironmentMetadata(name: name), | ||||
|       ownerId: OwnerId(uuid: creds.uuid), | ||||
|       token: Token(token: creds.token), | ||||
|     ); | ||||
|  | ||||
|     try { | ||||
|       final response = await envStub.get(request); | ||||
|       return response; | ||||
|       return EnvironmentLocalData( | ||||
|           serverType: response.spec.serverType.toString(), | ||||
|           serverLocation: response.spec.serverLocation.toString(), | ||||
|           provider: response.spec.provider.toString(), | ||||
|           name: response.metadata.name, | ||||
|           description: response.metadata.description); | ||||
|     } catch (e) { | ||||
|       rethrow; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   Stream<List<EnvironmentFull>> list(SoftplayerCreds creds) async* { | ||||
|     List<EnvironmentFull> envs = []; | ||||
|   Future<EnvironmentLocalData> create( | ||||
|       EnvironmentLocalData data, SoftplayerCreds creds) async { | ||||
|       Location.values.forEach((element) => print(element.toString() + " - " + data.serverLocation)); | ||||
|   print(ServerType.values); | ||||
|  | ||||
|     final request = CreateOptions( | ||||
|       metadata: | ||||
|           EnvironmentMetadata(description: data.description, name: data.name), | ||||
|       spec: EnvironmentSpec( | ||||
|         // Currently we do not support other kinds | ||||
|         kubernetes: Kubernetes.KUBERNETES_K3S, | ||||
|         // Currently we do not support other providers | ||||
|         provider: Provider.PROVIDER_HETZNER, | ||||
|         serverLocation: Location.values | ||||
|             .firstWhere((e) => e.toString() == data.serverLocation), | ||||
|         serverType: ServerType.values | ||||
|             .firstWhere((e) => e.toString() == data.serverType), | ||||
|       ), | ||||
|       ownerId: OwnerId(uuid: creds.uuid), | ||||
|       token: Token(token: creds.token), | ||||
|     ); | ||||
|     try { | ||||
|       final response = await envStub.create(request); | ||||
|       return EnvironmentLocalData( | ||||
|           serverType: response.spec.serverType.toString(), | ||||
|           serverLocation: response.spec.serverLocation.toString(), | ||||
|           provider: response.spec.provider.toString(), | ||||
|           name: response.metadata.name, | ||||
|           description: response.metadata.description); | ||||
|     } catch (e) { | ||||
|       rethrow; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   Stream<List<EnvironmentLocalData>> list(SoftplayerCreds creds) async* { | ||||
|     List<EnvironmentLocalData> envs = []; | ||||
|     try { | ||||
|       await for (var feature in envStub.list( | ||||
|         ListOptions( | ||||
| @@ -43,9 +87,12 @@ class EnvironmentsGrpc { | ||||
|           token: Token(token: creds.token), | ||||
|         ), | ||||
|       )) { | ||||
|         envs.add(EnvironmentFull( | ||||
|           data: feature.data, | ||||
|           name: feature.name, | ||||
|         envs.add(EnvironmentLocalData( | ||||
|           serverType: feature.spec.serverType.toString(), | ||||
|           serverLocation: feature.spec.serverLocation.toString(), | ||||
|           provider: feature.spec.provider.toString(), | ||||
|           name: feature.metadata.name, | ||||
|           description: feature.metadata.description, | ||||
|         )); | ||||
|       } | ||||
|     } catch (e) { | ||||
|   | ||||
							
								
								
									
										131
									
								
								lib/components/create_env_form.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								lib/components/create_env_form.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,131 @@ | ||||
| import 'dart:html'; | ||||
| import 'dart:js' as js; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:grpc/grpc_web.dart'; | ||||
| import 'package:softplayer_web/api/grpc/creds.dart'; | ||||
| import 'package:softplayer_web/api/grpc/environments.dart'; | ||||
|  | ||||
| class CreateEnvForm extends StatefulWidget { | ||||
|   CreateEnvForm(GrpcWebClientChannel channel, {super.key}) | ||||
|       : environmentsGrpc = EnvironmentsGrpc(channel); | ||||
|   final EnvironmentsGrpc environmentsGrpc; | ||||
|   @override | ||||
|   State<StatefulWidget> createState() => _CreateEnvFormState(); | ||||
| } | ||||
|  | ||||
| class _CreateEnvFormState extends State<CreateEnvForm> { | ||||
|   final _formKey = GlobalKey<FormState>(); | ||||
|  | ||||
|   final nameCtl = TextEditingController(); | ||||
|   final descriptionCtl = TextEditingController(); | ||||
|   String? serverLocation; | ||||
|   String? serverType; | ||||
|  | ||||
|   void createEnvironment() { | ||||
|     // Validate returns true if the form is valid, or false otherwise. | ||||
|     if (_formKey.currentState!.validate()) { | ||||
|       final name = nameCtl.text; | ||||
|       final description = descriptionCtl.text; | ||||
|       widget.environmentsGrpc | ||||
|           .create( | ||||
|               EnvironmentLocalData( | ||||
|                   serverType: serverType!, | ||||
|                   serverLocation: serverLocation!, | ||||
|                   provider: "", | ||||
|                   name: name, | ||||
|                   description: description), | ||||
|               SoftplayerCredsHelpers().fromLocalStorage()) | ||||
|           .then((rs) { | ||||
|         Navigator.pop(context); | ||||
|       }).catchError((e) { | ||||
|         print(e); | ||||
|         GrpcError error = e; | ||||
|         String msg; | ||||
|         if (error.message != null) { | ||||
|           msg = error.message!; | ||||
|         } else { | ||||
|           msg = error.toString(); | ||||
|         } | ||||
|         ScaffoldMessenger.of(context).showSnackBar(SnackBar( | ||||
|           content: Text(msg), | ||||
|           backgroundColor: Colors.red, | ||||
|           showCloseIcon: true, | ||||
|           behavior: SnackBarBehavior.floating, | ||||
|         )); | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   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", | ||||
|                 ), | ||||
|                 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"), | ||||
|             ) | ||||
|           ])))); | ||||
|   List<Widget> createEnvActions() => [ | ||||
|         TextButton( | ||||
|           onPressed: createEnvironment, | ||||
|           child: const Text('OK'), | ||||
|         ), | ||||
|       ]; | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) => AlertDialog( | ||||
|         title: const Text("Create a new environment"), | ||||
|         content: createEnvForm(), | ||||
|         actions: createEnvActions(), | ||||
|       ); | ||||
| } | ||||
| @@ -1,24 +1,51 @@ | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:softplayer_web/api/grpc/environments.dart'; | ||||
|  | ||||
| class EnvirnomentCard extends StatelessWidget { | ||||
|   final String name; | ||||
|   final EnvironmentLocalData env; | ||||
|  | ||||
|   const EnvirnomentCard({ | ||||
|     super.key, | ||||
|     required this.name, | ||||
|     required this.env, | ||||
|   }); | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Card( | ||||
|       child: SelectionArea( | ||||
|         child: Column( | ||||
|           children: [ | ||||
|           Text(name), | ||||
|           Row( | ||||
|             children: [Text(name)], | ||||
|             Text(env.name), | ||||
|             const Divider(), | ||||
|             Table( | ||||
|               border: const TableBorder( | ||||
|                 bottom: BorderSide.none, | ||||
|                 left: BorderSide.none, | ||||
|                 right: BorderSide.none, | ||||
|                 top: BorderSide.none, | ||||
|               ), | ||||
|               children: [ | ||||
|                 TableRow(children: [ | ||||
|                   Text("Provider"), | ||||
|                   Text(env.provider), | ||||
|                 ]), | ||||
|                 TableRow(children: [ | ||||
|                   Text("Description"), | ||||
|                   Text(env.description), | ||||
|                 ]), | ||||
|                 TableRow(children: [ | ||||
|                   Text("Server Type"), | ||||
|                   Text(env.serverType), | ||||
|                 ]), | ||||
|                 TableRow(children: [ | ||||
|                   Text("Location"), | ||||
|                   Text(env.serverLocation), | ||||
|                 ]), | ||||
|               ], | ||||
|             ) | ||||
|           ], | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -26,7 +26,15 @@ class _EnvirnomentListState extends State<EnvirnomentList> { | ||||
|   @override | ||||
|   Widget build(BuildContext context) { | ||||
|     return Scaffold( | ||||
|         body: SafeArea( | ||||
|         body: Container( | ||||
|             width: double.infinity, | ||||
|             height: double.infinity, | ||||
|             decoration: const BoxDecoration( | ||||
|               image: DecorationImage( | ||||
|                 image: AssetImage("assets/login_background.jpg"), | ||||
|                 fit: BoxFit.cover, | ||||
|               ), | ||||
|             ), | ||||
|             child: StreamBuilder( | ||||
|                 stream: | ||||
|                     envGrpc.list(SoftplayerCredsHelpers().fromLocalStorage()), | ||||
| @@ -37,66 +45,37 @@ class _EnvirnomentListState extends State<EnvirnomentList> { | ||||
|                     if (snapshot.hasError) { | ||||
|                       return const Text('Error!'); | ||||
|                     } else { | ||||
|                       if (snapshot.hasData) { | ||||
|                         var data = snapshot.requireData; | ||||
|                         if (data.isNotEmpty) { | ||||
|                           return GridView.count( | ||||
|                             crossAxisCount: 4, | ||||
|                             children: snapshot.data! | ||||
|                             .map((e) => EnvirnomentCard(name: e.name.name)) | ||||
|                                 .map((e) => EnvirnomentCard( | ||||
|                                       env: e, | ||||
|                                     )) | ||||
|                                 .toList(), | ||||
|                           ); | ||||
|                         } else { | ||||
|                           print("npo data"); | ||||
|                           return Center( | ||||
|                               child: Container( | ||||
|                             height: 300, | ||||
|                             child: Text( | ||||
|                                 "To get strated, use the button in the corner"), | ||||
|                             decoration: BoxDecoration( | ||||
|                               border: Border.all(), | ||||
|                               shape: BoxShape.rectangle, | ||||
|                               borderRadius: | ||||
|                                   BorderRadius.all(Radius.circular(10)), | ||||
|                               color: Color.fromRGBO(100, 150, 80, 20), | ||||
|                             ), | ||||
|                           )); | ||||
|                         } | ||||
|                       } | ||||
|                     } | ||||
|                   } | ||||
|                   return const Text("err"); | ||||
|                 }))); | ||||
|   } | ||||
| } | ||||
|  | ||||
| //class EnvirnomentList extends StatelessWidget { | ||||
| //  EnvirnomentList({ | ||||
| //    super.key, | ||||
| //    required this.channel, | ||||
| //  }); | ||||
| //  final GrpcWebClientChannel channel; | ||||
| //  late List<String> envs; | ||||
| //  late EnvironmentsGrpc envGrpc; | ||||
| //  List<String> getEnvs() { | ||||
| //    List<String> envs = []; | ||||
| //    envGrpc.list().then((value) { | ||||
| //      return value; | ||||
| //    }).catchError((e) { | ||||
| //      return envs; | ||||
| //    }); | ||||
| //    return envs; | ||||
| //  } | ||||
| // | ||||
| //  List<Widget> bootstrapCards(List<String> envs) { | ||||
| //    List<Widget> cards = []; | ||||
| //    envs.forEach((element) { | ||||
| //      cards.add(Center(child: Text(element))); | ||||
| //    }); | ||||
| //    return cards; | ||||
| //  } | ||||
| // | ||||
| // | ||||
| //  @override | ||||
| //  Widget build(BuildContext context) { | ||||
| //    envGrpc = EnvironmentsGrpc(channel: channel); | ||||
| //    envGrpc.init(); | ||||
| //    envs = getEnvs(); | ||||
| //    return GridView.count( | ||||
| //      crossAxisCount: 2, | ||||
| //      children: bootstrapCards(envs), | ||||
| //    ); | ||||
| // // children: List.generate(100, (index) { | ||||
| // //   return Center( | ||||
| // //     child: Text( | ||||
| // //       'Item $index', | ||||
| // //       style: Theme.of(context).textTheme.headlineSmall, | ||||
| // //     ), | ||||
| // //   ); | ||||
| // // }), | ||||
| // // ); | ||||
| //   // return GridView.count( | ||||
| //   //       children: bootstrapCards(getEnvs()), | ||||
| //     //   ); | ||||
| //  } | ||||
| //} | ||||
|   | ||||
							
								
								
									
										4
									
								
								lib/helpers/providers/common.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								lib/helpers/providers/common.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| abstract class Provider { | ||||
|   String getServerType(String serverType); | ||||
|   String rawServerType(String serverType); | ||||
| } | ||||
							
								
								
									
										26
									
								
								lib/helpers/providers/hetzner.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								lib/helpers/providers/hetzner.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| import 'package:softplayer_web/helpers/providers/common.dart'; | ||||
|  | ||||
| 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(); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   String rawServerType(string) { | ||||
|     // TODO: implement rawServerType | ||||
|     throw UnimplementedError(); | ||||
|   } | ||||
| } | ||||
| @@ -1,8 +1,10 @@ | ||||
| import 'dart:html'; | ||||
|  | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:grpc/grpc_web.dart'; | ||||
| import 'package:softplayer_web/api/grpc/accounts.dart'; | ||||
| import 'package:softplayer_web/components/create_env_form.dart'; | ||||
| import 'package:softplayer_web/components/environments.dart'; | ||||
| import 'package:softplayer_web/components/login_form.dart'; | ||||
|  | ||||
| @@ -61,10 +63,12 @@ class _StateRootWidget extends State<RootWidget> { | ||||
|     if (!isSignedIn()) { | ||||
|       return Scaffold( | ||||
|           body: Container( | ||||
|         width: double.infinity, | ||||
|         height: double.infinity, | ||||
|         decoration: const BoxDecoration( | ||||
|           image: DecorationImage( | ||||
|             image: AssetImage("assets/login_background.jpg"), | ||||
|             fit: BoxFit.fill, | ||||
|             fit: BoxFit.cover, | ||||
|           ), | ||||
|         ), | ||||
|         child: LoginForm( | ||||
| @@ -73,8 +77,9 @@ class _StateRootWidget extends State<RootWidget> { | ||||
|         ), | ||||
|       )); | ||||
|     } else { | ||||
|       EnvirnomentList envList = EnvirnomentList(channel: widget.channel); | ||||
|       return Scaffold( | ||||
|         body: EnvirnomentList(channel: widget.channel), | ||||
|         body: envList, | ||||
|         appBar: AppBar( | ||||
|           title: const Text("Softplayer"), | ||||
|           actions: [ | ||||
| @@ -88,7 +93,12 @@ class _StateRootWidget extends State<RootWidget> { | ||||
|           ], | ||||
|         ), | ||||
|         floatingActionButton: FloatingActionButton( | ||||
|           onPressed: () => print("1"), | ||||
|           child: const Icon(Icons.add), | ||||
|           onPressed: () => showDialog( | ||||
|             context: context, | ||||
|             builder: (context) => | ||||
|                 CreateEnvForm(widget.channel), | ||||
|           ), | ||||
|         ), | ||||
|       ); | ||||
|     } | ||||
|   | ||||
| @@ -245,7 +245,7 @@ packages: | ||||
|     description: | ||||
|       path: "." | ||||
|       ref: main | ||||
|       resolved-ref: "6b6325ac4b6c469e41c994d1045af79225a49d38" | ||||
|       resolved-ref: bccaaff90c8ef1e9d23c565a58cab6db841282d3 | ||||
|       url: "https://git.badhouseplants.net/softplayer/softplayer-dart-proto.git" | ||||
|     source: git | ||||
|     version: "1.0.0+1" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user