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:softplayer_web/api/grpc/environments.dart';
|
||||
import 'package:softplayer_web/components/environment_preview.dart';
|
||||
import 'package:softplayer_web/helpers/providers/common.dart';
|
||||
|
||||
class EnvirnomentCard extends StatefulWidget {
|
||||
@ -48,9 +49,17 @@ class _EnvirnomentCardState extends State<EnvirnomentCard> {
|
||||
elevation: elevation,
|
||||
child: SelectionArea(
|
||||
child: InkWell(
|
||||
onTap: () => showBottomSheet(
|
||||
onLongPress: () => showMenu(
|
||||
position: RelativeRect.fromSize(Rect.largest, Size.infinite),
|
||||
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(
|
||||
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) {
|
||||
var data = snapshot.requireData;
|
||||
if (data.isNotEmpty) {
|
||||
return Column(children: [
|
||||
Flexible(
|
||||
child: Container(
|
||||
margin: const EdgeInsetsDirectional.fromSTEB(
|
||||
50.0, 20.0, 50.0, 10.0),
|
||||
child: const TextField(
|
||||
decoration: InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
filled: true,
|
||||
labelText: "Search",
|
||||
prefixIcon: Icon(Icons.search)),
|
||||
return Container(
|
||||
margin: const EdgeInsetsDirectional.fromSTEB(
|
||||
50.0, 20.0, 50.0, 10.0),
|
||||
child: Column(children: [
|
||||
Flexible(
|
||||
child: Container(
|
||||
child: const TextField(
|
||||
decoration: InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
filled: true,
|
||||
labelText: "Search",
|
||||
prefixIcon: Icon(Icons.search)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: GridView.count(
|
||||
childAspectRatio: (30 / 13),
|
||||
crossAxisCount: 4,
|
||||
children: snapshot.data!
|
||||
.map((e) => EnvirnomentCard(
|
||||
env: e,
|
||||
))
|
||||
.toList(),
|
||||
))
|
||||
]);
|
||||
Container(
|
||||
child: Flexible(
|
||||
child: GridView.count(
|
||||
childAspectRatio: (30 / 13),
|
||||
crossAxisCount: 4,
|
||||
children: snapshot.data!
|
||||
.map((e) => EnvirnomentCard(
|
||||
env: e,
|
||||
))
|
||||
.toList(),
|
||||
)),
|
||||
)
|
||||
]),
|
||||
);
|
||||
} else {
|
||||
return Center(
|
||||
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,
|
||||
title: const Text("Softplayer"),
|
||||
bottom: const TabBar(
|
||||
|
||||
tabs: <Widget>[
|
||||
Tab(
|
||||
icon: Icon(Icons.computer),
|
||||
|
Loading…
Reference in New Issue
Block a user