Some updates to the frontend
This commit is contained in:
parent
f9aa2c683d
commit
20b2f7df0a
@ -1,49 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:softplayer_web/models/catalog_entry.dart';
|
|
||||||
|
|
||||||
class CatalogCard extends StatelessWidget {
|
|
||||||
const CatalogCard({
|
|
||||||
super.key,
|
|
||||||
required this.data,
|
|
||||||
});
|
|
||||||
final List<CatalogEntry> data;
|
|
||||||
|
|
||||||
List<Widget> createCards(List<CatalogEntry> data) {
|
|
||||||
List<Widget> createCards = [];
|
|
||||||
for (var app in data) {
|
|
||||||
createCards.add(Card(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
ListTile(
|
|
||||||
//leading: Image.network(app.logoUrl),
|
|
||||||
leading: const Icon(Icons.nfc),
|
|
||||||
title: Text(app.name),
|
|
||||||
subtitle: Text(app.description),
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
children: <Widget>[
|
|
||||||
TextButton(
|
|
||||||
child: const Text('INSTALL'),
|
|
||||||
onPressed: () {
|
|
||||||
print("installing");
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
return createCards;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Column(
|
|
||||||
children: createCards(data),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:softplayer_web/api/grpc/environments.dart';
|
import 'package:softplayer_web/api/grpc/environments.dart';
|
||||||
|
import 'package:softplayer_web/components/environment_preview.dart';
|
||||||
import 'package:softplayer_web/helpers/providers/common.dart';
|
import 'package:softplayer_web/helpers/providers/common.dart';
|
||||||
|
|
||||||
class EnvirnomentCard extends StatefulWidget {
|
class EnvirnomentCard extends StatefulWidget {
|
||||||
@ -48,9 +49,17 @@ class _EnvirnomentCardState extends State<EnvirnomentCard> {
|
|||||||
elevation: elevation,
|
elevation: elevation,
|
||||||
child: SelectionArea(
|
child: SelectionArea(
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () => showBottomSheet(
|
onLongPress: () => showMenu(
|
||||||
|
position: RelativeRect.fromSize(Rect.largest, Size.infinite),
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => Text(widget.env.uuid!),
|
items: [
|
||||||
|
PopupMenuItem(child: Text("test")),
|
||||||
|
PopupMenuItem(child: Text("text")),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () => showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => EnvirnomentPreiview(env: widget.env),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
91
lib/components/environment_preview.dart
Normal file
91
lib/components/environment_preview.dart
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:softplayer_web/api/grpc/environments.dart';
|
||||||
|
import 'package:softplayer_web/helpers/providers/common.dart';
|
||||||
|
|
||||||
|
class EnvirnomentPreiview extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() => _EnvirnomentPreviewState();
|
||||||
|
final EnvironmentLocalData env;
|
||||||
|
|
||||||
|
const EnvirnomentPreiview({
|
||||||
|
super.key,
|
||||||
|
required this.env,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EnvirnomentPreviewState extends State<EnvirnomentPreiview> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
Provider provider = ProviderHelper().getProvider(widget.env.provider);
|
||||||
|
|
||||||
|
String serverType;
|
||||||
|
String serverLocation;
|
||||||
|
try {
|
||||||
|
serverType = ProviderHelper().getServerType(widget.env.serverType);
|
||||||
|
serverLocation = provider.getServerLocation(widget.env.serverLocation);
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text(widget.env.name),
|
||||||
|
content: SizedBox(
|
||||||
|
height: 420,
|
||||||
|
width: 420,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Table(
|
||||||
|
border: const TableBorder(
|
||||||
|
bottom: BorderSide.none,
|
||||||
|
left: BorderSide.none,
|
||||||
|
right: BorderSide.none,
|
||||||
|
top: BorderSide.none,
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
TableRow(children: [
|
||||||
|
const Text("Description"),
|
||||||
|
Text(widget.env.description),
|
||||||
|
]),
|
||||||
|
TableRow(children: [
|
||||||
|
const Text("Provider"),
|
||||||
|
Text(provider.getProviderName()),
|
||||||
|
]),
|
||||||
|
TableRow(children: [
|
||||||
|
const Text("Server Type"),
|
||||||
|
Text(serverType),
|
||||||
|
]),
|
||||||
|
TableRow(children: [
|
||||||
|
const Text("Location"),
|
||||||
|
Text(serverLocation),
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Divider(),
|
||||||
|
Table(
|
||||||
|
border: const TableBorder(
|
||||||
|
bottom: BorderSide.none,
|
||||||
|
left: BorderSide.none,
|
||||||
|
right: BorderSide.none,
|
||||||
|
top: BorderSide.none,
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
TableRow(children: [
|
||||||
|
const Text("Price per hour"),
|
||||||
|
Text("0.52"),
|
||||||
|
]),
|
||||||
|
TableRow(children: [
|
||||||
|
const Text("Current usage"),
|
||||||
|
Text("10.5"),
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(onPressed: () => print("lala"), child: Text("test")),
|
||||||
|
TextButton(onPressed: () => print("lala"), child: Text("test")),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -52,31 +52,35 @@ class _EnvirnomentListState extends State<EnvirnomentList> {
|
|||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
var data = snapshot.requireData;
|
var data = snapshot.requireData;
|
||||||
if (data.isNotEmpty) {
|
if (data.isNotEmpty) {
|
||||||
return Column(children: [
|
return Container(
|
||||||
Flexible(
|
margin: const EdgeInsetsDirectional.fromSTEB(
|
||||||
child: Container(
|
50.0, 20.0, 50.0, 10.0),
|
||||||
margin: const EdgeInsetsDirectional.fromSTEB(
|
child: Column(children: [
|
||||||
50.0, 20.0, 50.0, 10.0),
|
Flexible(
|
||||||
child: const TextField(
|
child: Container(
|
||||||
decoration: InputDecoration(
|
child: const TextField(
|
||||||
fillColor: Colors.white,
|
decoration: InputDecoration(
|
||||||
filled: true,
|
fillColor: Colors.white,
|
||||||
labelText: "Search",
|
filled: true,
|
||||||
prefixIcon: Icon(Icons.search)),
|
labelText: "Search",
|
||||||
|
prefixIcon: Icon(Icons.search)),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Container(
|
||||||
Flexible(
|
child: Flexible(
|
||||||
child: GridView.count(
|
child: GridView.count(
|
||||||
childAspectRatio: (30 / 13),
|
childAspectRatio: (30 / 13),
|
||||||
crossAxisCount: 4,
|
crossAxisCount: 4,
|
||||||
children: snapshot.data!
|
children: snapshot.data!
|
||||||
.map((e) => EnvirnomentCard(
|
.map((e) => EnvirnomentCard(
|
||||||
env: e,
|
env: e,
|
||||||
))
|
))
|
||||||
.toList(),
|
.toList(),
|
||||||
))
|
)),
|
||||||
]);
|
)
|
||||||
|
]),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return Center(
|
return Center(
|
||||||
child: Container(
|
child: Container(
|
||||||
|
@ -1,103 +0,0 @@
|
|||||||
import 'dart:html';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:grpc/grpc_web.dart';
|
|
||||||
import 'package:softplayer_web/api/grpc/accounts.dart';
|
|
||||||
|
|
||||||
class SignInForm extends StatefulWidget {
|
|
||||||
const SignInForm({
|
|
||||||
super.key,
|
|
||||||
required this.accountsGrpc,
|
|
||||||
});
|
|
||||||
|
|
||||||
final AccountsGrpc accountsGrpc;
|
|
||||||
@override
|
|
||||||
State<StatefulWidget> createState() => _SignInFormState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _SignInFormState extends State<SignInForm> {
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
|
||||||
final usernameCtrl = TextEditingController();
|
|
||||||
final passwordCtrl = TextEditingController();
|
|
||||||
static const dialogName = "Sign In";
|
|
||||||
void submitForm() {
|
|
||||||
// Validate returns true if the form is valid, or false otherwise.
|
|
||||||
if (_formKey.currentState!.validate()) {
|
|
||||||
final username = usernameCtrl.text;
|
|
||||||
final password = passwordCtrl.text;
|
|
||||||
widget.accountsGrpc.signIn(username, "", password).then((rs) {
|
|
||||||
window.localStorage["token"] = rs.token;
|
|
||||||
window.localStorage["uuid"] = rs.uuid;
|
|
||||||
Navigator.of(context, rootNavigator: true).pop();
|
|
||||||
}).catchError((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,
|
|
||||||
));
|
|
||||||
passwordCtrl.clear();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) => AlertDialog(
|
|
||||||
title: const Text(dialogName),
|
|
||||||
content: SizedBox(
|
|
||||||
width: 420,
|
|
||||||
height: 140,
|
|
||||||
child: Form(
|
|
||||||
key: _formKey,
|
|
||||||
child: Center(
|
|
||||||
child: Column(children: [
|
|
||||||
TextFormField(
|
|
||||||
controller: usernameCtrl,
|
|
||||||
autofocus: true,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
hintText: "Enter your username or email",
|
|
||||||
icon: Icon(Icons.account_circle),
|
|
||||||
label: Text("Username"),
|
|
||||||
),
|
|
||||||
cursorWidth: 1,
|
|
||||||
cursorHeight: 18,
|
|
||||||
cursorRadius: const Radius.circular(10),
|
|
||||||
),
|
|
||||||
TextFormField(
|
|
||||||
controller: passwordCtrl,
|
|
||||||
obscureText: true,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
hintText: "Enter your password",
|
|
||||||
icon: Icon(Icons.password),
|
|
||||||
label: Text("Password")),
|
|
||||||
cursorWidth: 1,
|
|
||||||
cursorHeight: 18,
|
|
||||||
cursorRadius: const Radius.circular(10),
|
|
||||||
onFieldSubmitted: (v) {
|
|
||||||
if (usernameCtrl.text.isEmpty) {
|
|
||||||
FocusScope.of(context).nextFocus();
|
|
||||||
} else {
|
|
||||||
submitForm();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
])))),
|
|
||||||
actions: <Widget>[
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Navigator.pop(context, 'Cancel'),
|
|
||||||
child: const Text('Cancel'),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: submitForm,
|
|
||||||
child: const Text('OK'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,125 +0,0 @@
|
|||||||
import 'dart:html';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:grpc/grpc_web.dart';
|
|
||||||
import 'package:softplayer_web/api/grpc/accounts.dart';
|
|
||||||
|
|
||||||
class SignUpForm extends StatefulWidget {
|
|
||||||
const SignUpForm({
|
|
||||||
super.key,
|
|
||||||
required this.accountsGrpc,
|
|
||||||
});
|
|
||||||
|
|
||||||
final AccountsGrpc accountsGrpc;
|
|
||||||
@override
|
|
||||||
State<StatefulWidget> createState() => _SignUpFormState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _SignUpFormState extends State<SignUpForm> {
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
|
||||||
|
|
||||||
final usernameCtrl = TextEditingController();
|
|
||||||
final passwordCtrl = TextEditingController();
|
|
||||||
final passwordVerifyCtrl = TextEditingController();
|
|
||||||
final emailCtrl = TextEditingController();
|
|
||||||
|
|
||||||
static const dialogName = "Sign Up";
|
|
||||||
|
|
||||||
void submitForm() {
|
|
||||||
// Validate returns true if the form is valid, or false otherwise.
|
|
||||||
if (_formKey.currentState!.validate()) {
|
|
||||||
final username = usernameCtrl.text;
|
|
||||||
final password = passwordCtrl.text;
|
|
||||||
final email = emailCtrl.text;
|
|
||||||
widget.accountsGrpc.signUp(username, email, password).then((rs) {
|
|
||||||
window.localStorage["token"] = rs.token;
|
|
||||||
window.localStorage["uuid"] = rs.uuid;
|
|
||||||
Navigator.of(context, rootNavigator: true).pop();
|
|
||||||
}).catchError((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,
|
|
||||||
));
|
|
||||||
passwordCtrl.clear();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) => AlertDialog(
|
|
||||||
title: const Text(dialogName),
|
|
||||||
content: SizedBox(
|
|
||||||
width: 420,
|
|
||||||
height: 280,
|
|
||||||
child: Form(
|
|
||||||
key: _formKey,
|
|
||||||
child: Center(
|
|
||||||
child: Column(children: [
|
|
||||||
TextFormField(
|
|
||||||
autofocus: true,
|
|
||||||
controller: usernameCtrl,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
hintText: "Enter your username",
|
|
||||||
icon: Icon(Icons.account_circle),
|
|
||||||
label: Text("Username"),
|
|
||||||
),
|
|
||||||
cursorWidth: 1,
|
|
||||||
cursorHeight: 18,
|
|
||||||
cursorRadius: const Radius.circular(10),
|
|
||||||
),
|
|
||||||
TextFormField(
|
|
||||||
controller: emailCtrl,
|
|
||||||
autofocus: true,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
hintText: "Enter your email",
|
|
||||||
icon: Icon(Icons.email),
|
|
||||||
label: Text("Email"),
|
|
||||||
),
|
|
||||||
cursorWidth: 1,
|
|
||||||
cursorHeight: 18,
|
|
||||||
cursorRadius: const Radius.circular(10),
|
|
||||||
),
|
|
||||||
TextFormField(
|
|
||||||
controller: passwordCtrl,
|
|
||||||
obscureText: true,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
hintText: "Enter your password",
|
|
||||||
icon: Icon(Icons.password),
|
|
||||||
label: Text("Password")),
|
|
||||||
cursorWidth: 1,
|
|
||||||
cursorHeight: 18,
|
|
||||||
cursorRadius: const Radius.circular(10),
|
|
||||||
),
|
|
||||||
TextFormField(
|
|
||||||
controller: passwordVerifyCtrl,
|
|
||||||
obscureText: true,
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
hintText: "Verify your password",
|
|
||||||
icon: Icon(Icons.password),
|
|
||||||
label: Text("Confirm Password")),
|
|
||||||
cursorWidth: 1,
|
|
||||||
cursorHeight: 18,
|
|
||||||
cursorRadius: const Radius.circular(10),
|
|
||||||
),
|
|
||||||
])))),
|
|
||||||
actions: <Widget>[
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Navigator.pop(context, 'Cancel'),
|
|
||||||
child: const Text('Cancel'),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: submitForm,
|
|
||||||
child: const Text('OK'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
@ -91,7 +91,6 @@ class _StateRootWidget extends State<RootWidget> {
|
|||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
title: const Text("Softplayer"),
|
title: const Text("Softplayer"),
|
||||||
bottom: const TabBar(
|
bottom: const TabBar(
|
||||||
|
|
||||||
tabs: <Widget>[
|
tabs: <Widget>[
|
||||||
Tab(
|
Tab(
|
||||||
icon: Icon(Icons.computer),
|
icon: Icon(Icons.computer),
|
||||||
|
Loading…
Reference in New Issue
Block a user