Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Admin UI: Login page #584

Merged
merged 48 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
91c30e4
chore: adapt the header appearance
stamenione Apr 1, 2024
0c83a49
chore: add new design for login box
stamenione Apr 1, 2024
067af12
chore: adapt login position in padding widget via screen size
stamenione Apr 1, 2024
7f79398
chore: logic for displaying the error message for attempted login
stamenione Apr 1, 2024
53277da
chore: remove error message
stamenione Apr 1, 2024
a1f5bd9
chore: add error message
stamenione Apr 1, 2024
3aba8cd
chore: change the button colors and add a text button
stamenione Apr 1, 2024
1aad577
chore: remove Visibility widget
stamenione Apr 1, 2024
9f34d13
chore: add text style for text button
stamenione Apr 1, 2024
8c909a0
chore: change todo comment according to the flutter style
stamenione Apr 1, 2024
4b635e6
Merge branch 'main' into NMSHDB-97-Admin-UI-Login-Page
mergify[bot] Apr 1, 2024
3e366de
Merge branch 'main' into NMSHDB-97-Admin-UI-Login-Page
mergify[bot] Apr 2, 2024
804df5b
Merge branch 'main' into NMSHDB-97-Admin-UI-Login-Page
mergify[bot] Apr 2, 2024
68e24ac
Merge branch 'main' into NMSHDB-97-Admin-UI-Login-Page
mergify[bot] Apr 2, 2024
b7275c0
refactor: extract the app title to be a separate widget
stamenione Apr 2, 2024
36431b5
refactor: extract text field to be reusable
stamenione Apr 2, 2024
5441fb7
chore: use new app title widget
stamenione Apr 2, 2024
d60fc2c
chore: use custom text field
stamenione Apr 2, 2024
b04098d
chore: make the text field fixed height
stamenione Apr 2, 2024
0ff34d7
chore: rename variables and make them private
stamenione Apr 2, 2024
702d11d
chore: update imports
stamenione Apr 2, 2024
63fc066
chore: use extracted app title widget
stamenione Apr 2, 2024
0fffd62
chore: remove unnecessary widgets and center the card
stamenione Apr 2, 2024
0cafd43
chore: add custom colors and move login button to the bottom
stamenione Apr 2, 2024
979defb
chore: remove unused import
stamenione Apr 2, 2024
61d3eac
refactor: rename folder and files appropriately
stamenione Apr 2, 2024
72c4cde
refactor: extract sized box into a separate custom widget
stamenione Apr 2, 2024
befe455
refactor: extract elevated button into a separate custom widget
stamenione Apr 2, 2024
27a6132
chore: make the variable private
stamenione Apr 2, 2024
0fb491d
chore: local variable should not start with underscore
stamenione Apr 2, 2024
a7d67c9
chore: add DI for baseUrl
stamenione Apr 2, 2024
48afead
fix: untangle coding
jkoenig134 Apr 2, 2024
ffa9788
fix: imports
jkoenig134 Apr 2, 2024
60cd19b
fix: make CustomColors easier accessible
jkoenig134 Apr 2, 2024
f234bcd
fix: make prettier
jkoenig134 Apr 2, 2024
7156477
feat: add gaps
jkoenig134 Apr 2, 2024
9bfbc2a
fix: rename file
jkoenig134 Apr 2, 2024
d83ba82
refactor: remove CustomX, make whole logic with one variable
jkoenig134 Apr 2, 2024
38c35af
fix: bool logic
jkoenig134 Apr 3, 2024
8a98917
ci: add jkoenig134 as codeowner
tnotheis Apr 3, 2024
ad2497e
chore: remove accidentally committet code
jkoenig134 Apr 3, 2024
665e072
fix: undo change
jkoenig134 Apr 3, 2024
cda655a
refactor: simplify login screen
jkoenig134 Apr 3, 2024
900b5a9
refactor: simplify app title
jkoenig134 Apr 3, 2024
7bbba1a
refactor: PR comments
jkoenig134 Apr 3, 2024
dde4624
chore: inline svg picture
jkoenig134 Apr 3, 2024
7b17855
chore: make multi line params last
jkoenig134 Apr 3, 2024
d924d1d
Merge branches 'NMSHDB-97-Admin-UI-Login-Page' and 'NMSHDB-97-Admin-U…
tnotheis Apr 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions AdminUi/apps/admin_ui/lib/core/app_config.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AppConfig {
final String baseUrl;

AppConfig({required this.baseUrl});
}
19 changes: 19 additions & 0 deletions AdminUi/apps/admin_ui/lib/core/constants.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:flutter/widgets.dart';

class Gaps {
Gaps._();

static const SizedBox h4 = SizedBox(height: 4);
static const SizedBox h8 = SizedBox(height: 8);
static const SizedBox h16 = SizedBox(height: 16);
static const SizedBox h24 = SizedBox(height: 24);
static const SizedBox h32 = SizedBox(height: 32);
static const SizedBox h40 = SizedBox(height: 40);

static const SizedBox w4 = SizedBox(width: 4);
static const SizedBox w8 = SizedBox(width: 8);
static const SizedBox w16 = SizedBox(width: 16);
static const SizedBox w24 = SizedBox(width: 24);
static const SizedBox w32 = SizedBox(width: 32);
static const SizedBox w40 = SizedBox(width: 40);
}
4 changes: 4 additions & 0 deletions AdminUi/apps/admin_ui/lib/core/core.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export 'app_config.dart';
export 'constants.dart';
export 'extensions.dart';
export 'widgets/widgets.dart';
16 changes: 16 additions & 0 deletions AdminUi/apps/admin_ui/lib/core/extensions.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';

import 'theme/theme.dart';

extension UnregisterIfRegistered on GetIt {
Future<void> unregisterIfRegistered<T extends Object>() async {
if (!isRegistered<T>()) return;

await unregister<T>();
}
}

extension GetCustomColors on BuildContext {
CustomColors get customColors => Theme.of(this).extension<CustomColors>()!;
}
2 changes: 2 additions & 0 deletions AdminUi/apps/admin_ui/lib/core/theme/theme.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export 'color_schemes.dart';
export 'custom_colors.dart';
44 changes: 44 additions & 0 deletions AdminUi/apps/admin_ui/lib/core/widgets/app_title.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';

import '../constants.dart';

class AppTitle extends StatelessWidget {
const AppTitle({super.key});

@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
SvgPicture.asset(
'assets/logo.svg',
width: 30,
height: 30,
),
Gaps.w8,
RichText(
jkoenig134 marked this conversation as resolved.
Show resolved Hide resolved
text: TextSpan(
children: [
TextSpan(
text: 'enmeshed',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.scrim,
fontSize: 25,
),
),
TextSpan(
text: ' Admin UI',
style: TextStyle(
color: Theme.of(context).colorScheme.scrim,
fontSize: 25,
),
jkoenig134 marked this conversation as resolved.
Show resolved Hide resolved
),
],
),
),
],
);
}
}
1 change: 1 addition & 0 deletions AdminUi/apps/admin_ui/lib/core/widgets/widgets.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'app_title.dart';
9 changes: 3 additions & 6 deletions AdminUi/apps/admin_ui/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import 'package:admin_ui/theme/colors/color_schemes.dart';
import 'package:admin_ui/theme/colors/custom_colors.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

import 'core/theme/theme.dart';
import 'home/home.dart';
import 'pages/pages.dart';
import 'screens/screens.dart';
import 'setup/setup_desktop.dart' if (dart.library.html) 'setup/setup_web.dart';

void main() async {
WidgetsFlutterBinding.ensureInitialized();

await setup();

runApp(
const AdminUiApp(),
);
runApp(const AdminUiApp());
}

final _rootNavigatorKey = GlobalKey<NavigatorState>();
Expand Down
97 changes: 0 additions & 97 deletions AdminUi/apps/admin_ui/lib/pages/login_page.dart
jkoenig134 marked this conversation as resolved.
Outdated
Show resolved Hide resolved

This file was deleted.

3 changes: 0 additions & 3 deletions AdminUi/apps/admin_ui/lib/pages/pages.dart

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import 'package:admin_api_sdk/admin_api_sdk.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get_it/get_it.dart';
import 'package:go_router/go_router.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '/core/core.dart';

class HomeScreen extends StatefulWidget {
final Widget child;
final String location;
Expand All @@ -21,14 +23,7 @@ class _HomeScreenState extends State<HomeScreen> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Row(
mainAxisSize: MainAxisSize.min,
children: [
SvgPicture.asset('assets/logo.svg', width: 30, height: 30),
const SizedBox(width: 10),
const Text('Enmeshed Admin UI'),
],
),
title: const AppTitle(),
leading: IconButton(
icon: const Icon(Icons.menu),
onPressed: () {
Expand All @@ -39,7 +34,7 @@ class _HomeScreenState extends State<HomeScreen> {
),
actions: [
IconButton(icon: const Icon(Icons.logout), onPressed: _logout),
const SizedBox(width: 10),
Gaps.w8,
],
),
body: Row(
Expand Down Expand Up @@ -85,7 +80,8 @@ class _HomeScreenState extends State<HomeScreen> {
Future<void> _logout() async {
final sp = await SharedPreferences.getInstance();
await sp.remove('api_key');
await GetIt.I.reset();
await GetIt.I.unregisterIfRegistered<AdminApiClient>();

if (mounted) context.go('/login');
}
}
113 changes: 113 additions & 0 deletions AdminUi/apps/admin_ui/lib/screens/login_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import 'package:admin_api_sdk/admin_api_sdk.dart';
import 'package:flutter/material.dart';
import 'package:get_it/get_it.dart';
import 'package:go_router/go_router.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '/core/core.dart';

class LoginScreen extends StatefulWidget {
const LoginScreen({super.key});

@override
State<LoginScreen> createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
final _apiKeyController = TextEditingController();
final _apiKeyFocusNode = FocusNode();

bool? _isApiKeyValid;

@override
void initState() {
super.initState();

_apiKeyFocusNode.requestFocus();
}

@override
void dispose() {
_apiKeyController.dispose();
_apiKeyFocusNode.dispose();

super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const AppTitle(),
leading: const SizedBox(
width: 40,
),
jkoenig134 marked this conversation as resolved.
Show resolved Hide resolved
),
body: Center(
child: SizedBox(
width: 400,
child: Card(
child: Padding(
padding: const EdgeInsets.all(25),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
height: 100,
child: TextField(
controller: _apiKeyController,
focusNode: _apiKeyFocusNode,
decoration: InputDecoration(
labelText: 'API Key',
border: const OutlineInputBorder(),
errorText: (_isApiKeyValid == false) ? 'Invalid API Key' : null,
),
obscureText: true,
onChanged: (text) {
if (_isApiKeyValid != null) return;

setState(() {
_isApiKeyValid = null;
});
},
onSubmitted: (_) => _login(),
),
),
Gaps.h16,
SizedBox(
height: 40,
width: double.infinity,
child: FilledButton(
onPressed: _apiKeyController.text.isNotEmpty ? _login : null,
child: const Text('Login'),
),
),
],
),
),
),
),
),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
);
}

Future<void> _login() async {
final apiKey = _apiKeyController.text.trim();
if (apiKey.isEmpty) return;

final baseUrl = GetIt.I<AppConfig>().baseUrl;
final isApiKeyValid = await AdminApiClient.validateApiKey(baseUrl: baseUrl, apiKey: apiKey);

if (!mounted) return;

if (!isApiKeyValid) return setState(() => _isApiKeyValid = false);
jkoenig134 marked this conversation as resolved.
Show resolved Hide resolved

final sp = await SharedPreferences.getInstance();
await sp.setString('api_key', apiKey);

await GetIt.I.unregisterIfRegistered<AdminApiClient>();
GetIt.I.registerSingleton(await AdminApiClient.create(baseUrl: baseUrl, apiKey: apiKey));
if (mounted) context.go('/dashboard');
}
}
3 changes: 3 additions & 0 deletions AdminUi/apps/admin_ui/lib/screens/screens.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export 'home_screen.dart';
export 'login_screen.dart';
export 'splash_screen.dart';
Loading