From ee03172f100fa10d75772d36dc98a03b9badc734 Mon Sep 17 00:00:00 2001 From: Arthi-chaud Date: Tue, 8 Feb 2022 11:00:33 +0100 Subject: [PATCH 01/10] Mobile Client: Setup Project to enable localization --- mobile/I10n.yaml | 2 +- mobile/lib/I10n/app_fr.arb | 3 --- mobile/lib/{I10n => l10n}/app_en.arb | 0 mobile/lib/l10n/app_fr.arb | 3 +++ mobile/lib/src/main.dart | 6 ++++-- mobile/lib/src/widgets/aeris_page.dart | 2 +- mobile/pubspec.lock | 10 +++++----- 7 files changed, 14 insertions(+), 12 deletions(-) delete mode 100644 mobile/lib/I10n/app_fr.arb rename mobile/lib/{I10n => l10n}/app_en.arb (100%) create mode 100644 mobile/lib/l10n/app_fr.arb diff --git a/mobile/I10n.yaml b/mobile/I10n.yaml index bb557b3..15338f2 100644 --- a/mobile/I10n.yaml +++ b/mobile/I10n.yaml @@ -1,3 +1,3 @@ arb-dir: lib/l10n template-arb-file: app_en.arb -output-localization-file: app_localizations.dartà \ No newline at end of file +output-localization-file: app_localizations.dart diff --git a/mobile/lib/I10n/app_fr.arb b/mobile/lib/I10n/app_fr.arb deleted file mode 100644 index 6bf8554..0000000 --- a/mobile/lib/I10n/app_fr.arb +++ /dev/null @@ -1,3 +0,0 @@ -{ - "helloWorld": "Bonjour, monde!", -} \ No newline at end of file diff --git a/mobile/lib/I10n/app_en.arb b/mobile/lib/l10n/app_en.arb similarity index 100% rename from mobile/lib/I10n/app_en.arb rename to mobile/lib/l10n/app_en.arb diff --git a/mobile/lib/l10n/app_fr.arb b/mobile/lib/l10n/app_fr.arb new file mode 100644 index 0000000..684fff7 --- /dev/null +++ b/mobile/lib/l10n/app_fr.arb @@ -0,0 +1,3 @@ +{ + "helloWorld": "Salutations au peuple" +} \ No newline at end of file diff --git a/mobile/lib/src/main.dart b/mobile/lib/src/main.dart index d72b680..d617417 100644 --- a/mobile/lib/src/main.dart +++ b/mobile/lib/src/main.dart @@ -12,6 +12,7 @@ import 'package:mobile/src/views/home_page.dart'; import 'package:mobile/src/constants.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; void main() { runApp( @@ -35,14 +36,15 @@ class MyApp extends StatelessWidget { debugShowCheckedModeBanner: false, title: 'Aeris', localizationsDelegates: const [ + AppLocalizations.delegate, GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, FormBuilderLocalizations.delegate ], - supportedLocales: const [Locale('en', ''), Locale('fr', '')], + supportedLocales: const [Locale('fr', ''), Locale('en', '')], theme: ThemeData(colorScheme: aerisScheme), - initialRoute: '/', + initialRoute: '/home', onGenerateRoute: (settings) { Map pageRoutes = { '/': () => const StartupPage(), diff --git a/mobile/lib/src/widgets/aeris_page.dart b/mobile/lib/src/widgets/aeris_page.dart index 25613e0..cbc3005 100644 --- a/mobile/lib/src/widgets/aeris_page.dart +++ b/mobile/lib/src/widgets/aeris_page.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:mobile/src/widgets/background/animated_background.dart'; - +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; /// Application base page, holds scaffold and background class AerisPage extends StatelessWidget { /// Body of the page diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 4560ef7..44edf20 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -571,7 +571,7 @@ packages: name: url_launcher_web url: "https://pub.dartlang.org" source: hosted - version: "2.0.6" + version: "2.0.8" url_launcher_windows: dependency: transitive description: @@ -592,21 +592,21 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.1" + version: "2.1.2" win32: dependency: transitive description: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.3.9" + version: "2.3.11" xdg_directories: dependency: transitive description: name: xdg_directories url: "https://pub.dartlang.org" source: hosted - version: "0.2.0" + version: "0.2.0+1" xml: dependency: transitive description: @@ -623,4 +623,4 @@ packages: version: "3.1.0" sdks: dart: ">=2.16.0-100.0.dev <3.0.0" - flutter: ">=2.5.0" + flutter: ">=2.10.0" From 2074c92aeb54731066793eafc460a7e06a7a80ee Mon Sep 17 00:00:00 2001 From: Arthi-chaud Date: Tue, 8 Feb 2022 11:51:11 +0100 Subject: [PATCH 02/10] Mobile client: Setting up basic translations --- mobile/lib/l10n/app_en.arb | 13 +- mobile/lib/src/main.dart | 57 +++-- mobile/lib/src/models/trigger.dart | 1 + .../lib/src/views/create_pipeline_page.dart | 225 +++++++++--------- mobile/lib/src/views/login_page.dart | 8 +- .../lib/src/views/pipeline_detail_page.dart | 11 +- mobile/lib/src/views/service_page.dart | 69 +++--- mobile/lib/src/views/setup_action_page.dart | 1 + mobile/lib/src/views/startup_page.dart | 3 +- .../src/widgets/action_card_popup_menu.dart | 2 + mobile/lib/src/widgets/home_page_menu.dart | 2 + .../lib/src/widgets/home_page_sort_menu.dart | 1 + 12 files changed, 214 insertions(+), 179 deletions(-) diff --git a/mobile/lib/l10n/app_en.arb b/mobile/lib/l10n/app_en.arb index 4f466e2..533bd3d 100644 --- a/mobile/lib/l10n/app_en.arb +++ b/mobile/lib/l10n/app_en.arb @@ -1,6 +1,13 @@ { "helloWorld": "Hello World!", - "@helloWorld": { - "description": "The conventional newborn programmer greeting" - } + "nameOfThePipeline": "Name of the pipeline", + "addReaction": "Add a Reaction", + "addTrigger": "Add a Trigger", + "usernameOrPasswordIncorrect": "Username or password is incorrect", + "userDoesNotExist": "User does not exist", + "enabled": "Enabled", + "disabled": "Disabled", + "deletePipeline": "Delete Pipeline", + "connected": "Connected", + "available": "Available" } \ No newline at end of file diff --git a/mobile/lib/src/main.dart b/mobile/lib/src/main.dart index d617417..ca2a8db 100644 --- a/mobile/lib/src/main.dart +++ b/mobile/lib/src/main.dart @@ -15,24 +15,21 @@ import 'package:provider/provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; void main() { - runApp( - MultiProvider( - providers: [ - ChangeNotifierProvider(create: (_) => PipelineProvider()), - ChangeNotifierProvider(create: (_) => UserServiceProvider()) - ], - child: const MyApp() - ) - ); + runApp(MultiProvider(providers: [ + ChangeNotifierProvider(create: (_) => PipelineProvider()), + ChangeNotifierProvider(create: (_) => UserServiceProvider()) + ], child: const Aeris())); } -class MyApp extends StatelessWidget { - const MyApp({Key? key}) : super(key: key); +class Aeris extends StatelessWidget { + static GlobalKey materialKey = GlobalKey(); + const Aeris({Key? key}) : super(key: key); ///This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( + navigatorKey: Aeris.materialKey, debugShowCheckedModeBanner: false, title: 'Aeris', localizationsDelegates: const [ @@ -62,23 +59,25 @@ class MyApp extends StatelessWidget { ..addAll(cardRoutes) ..addAll(pageRoutes); return PageRouteBuilder( - opaque: false, - settings: settings, - pageBuilder: (_, __, ___) => routes[settings.name].call(), - transitionDuration: const Duration(milliseconds: 350), - transitionsBuilder: (context, animation, secondaryAnimation, child) => - pageRoutes.containsKey(settings.name) ? ScaleTransition( - child: child, - scale: CurvedAnimation( - parent: animation, - curve: Curves.ease, - ) - ) : SlideTransition( - position: animation.drive(Tween(begin: const Offset(0, 1), end: Offset.zero).chain(CurveTween(curve: Curves.ease))), - child: child, - ) - ); - } - ); + opaque: false, + settings: settings, + pageBuilder: (_, __, ___) => routes[settings.name].call(), + transitionDuration: const Duration(milliseconds: 350), + transitionsBuilder: (context, animation, secondaryAnimation, + child) => + pageRoutes.containsKey(settings.name) + ? ScaleTransition( + child: child, + scale: CurvedAnimation( + parent: animation, + curve: Curves.ease, + )) + : SlideTransition( + position: animation.drive( + Tween(begin: const Offset(0, 1), end: Offset.zero) + .chain(CurveTween(curve: Curves.ease))), + child: child, + )); + }); } } diff --git a/mobile/lib/src/models/trigger.dart b/mobile/lib/src/models/trigger.dart index e25eaaf..ec34c61 100644 --- a/mobile/lib/src/models/trigger.dart +++ b/mobile/lib/src/models/trigger.dart @@ -15,6 +15,7 @@ class Trigger extends aeris_action.Action { : super(service: service, name: name, parameters: parameters); ///TODO Constructor from DB 'Type' field + ///TODO translate String lastToString() { if (last == null) return 'Last: Never'; int elapsedDays = DateTime.now().difference(last!).inDays; diff --git a/mobile/lib/src/views/create_pipeline_page.dart b/mobile/lib/src/views/create_pipeline_page.dart index 5f545b3..b8ef8c2 100644 --- a/mobile/lib/src/views/create_pipeline_page.dart +++ b/mobile/lib/src/views/create_pipeline_page.dart @@ -12,6 +12,7 @@ import 'package:mobile/src/widgets/aeris_card_page.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:mobile/src/widgets/colored_clickable_card.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; /// Page to create a new pipeline class CreatePipelinePage extends StatefulWidget { @@ -22,7 +23,6 @@ class CreatePipelinePage extends StatefulWidget { } class _CreatePipelinePageState extends State { - /// Creates a basic Template the user can modify Trigger trigger = Trigger.template(); @@ -36,113 +36,122 @@ class _CreatePipelinePageState extends State { Widget build(BuildContext context) { final _formKey = GlobalKey(); return Consumer( - builder: (context, provider, _) => - AerisCardPage( - body: ListView(children: [ - const Text("Create a new pipeline", - style: TextStyle( - fontSize: 25, - ) - ), - FormBuilder( - key: _formKey, - child: Padding( - padding: const EdgeInsets.all(20), - child: Column(children: [ - FormBuilderTextField( - name: 'name', - initialValue: name, - decoration: const InputDecoration( - labelText: 'Name of the pipeline', - ), - validator: FormBuilderValidators.compose([ - FormBuilderValidators.required(context), - FormBuilderValidators.minLength(context, 5), + builder: (context, provider, _) => AerisCardPage( + body: ListView(children: [ + const Text("Create a new pipeline", + style: TextStyle( + fontSize: 25, + )), + FormBuilder( + key: _formKey, + child: Padding( + padding: const EdgeInsets.all(20), + child: Column(children: [ + FormBuilderTextField( + name: 'name', + initialValue: name, + decoration: InputDecoration( + labelText: + AppLocalizations.of(context)!.nameOfThePipeline, + ), + validator: FormBuilderValidators.compose([ + FormBuilderValidators.required(context), + FormBuilderValidators.minLength(context, 5), + ]), + onChanged: (value) { + name = value; + }, + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: trigger == Trigger.template() + ? ColoredClickableCard( + color: Theme.of(context) + .colorScheme + .secondaryContainer, + text: AppLocalizations.of(context)!.addTrigger, + onTap: () { + print("add trigger"); // TODO add reaction + Navigator.of(context) + .pushNamed('/pipeline/action/new', + arguments: + SetupActionPageArguments(trigger)) + .then((_) => setState(() {})); + }) + : ActionCard( + leading: trigger.service.getLogo(logoSize: 50), + title: trigger.service.name, + trailing: ActionCardPopupMenu( + deletable: false, + action: trigger, + then: () => setState(() {})), + ), + ), + ...[ + for (Reaction reaction in reactions) + ActionCard( + leading: reaction.service.getLogo(logoSize: 50), + title: reaction.service.name, + trailing: ActionCardPopupMenu( + deletable: reaction != reactions[0], + action: reaction, + then: () => setState(() {})), + ) + ], + Padding( + padding: const EdgeInsets.all(8.0), + child: ColoredClickableCard( + color: Theme.of(context) + .colorScheme + .secondaryContainer, + text: AppLocalizations.of(context)!.addReaction, + onTap: () async { + // TODO add to db + reactions.add(Reaction.template()); + await Navigator.of(context).pushNamed( + '/pipeline/action/new', + arguments: + SetupActionPageArguments(reactions.last)); + setState(() {}); + }), + ), + ElevatedButton( + child: const Text("Save"), + onPressed: () { + _formKey.currentState!.save(); + if (_formKey.currentState!.validate()) { + if (trigger == Trigger.template() || + reactions.isEmpty || + reactions + .where((element) => + element == Reaction.template()) + .isNotEmpty) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + backgroundColor: + Theme.of(context).colorScheme.secondary, + content: const Text( + "You must select at least a trigger and a reaction"))); + } else { + Pipeline newPipeline = Pipeline( + id: 0, + name: _formKey.currentState!.value['name'], + triggerCount: 0, + enabled: true, + parameters: {}, + trigger: trigger, + reactions: reactions); + provider.addPipelineInProvider(newPipeline); + + ///TODO add to db + Navigator.of(context).popAndPushNamed('/pipeline', + arguments: + PipelineDetailPageArguments(newPipeline)); + } + } + }, + ), ]), - onChanged: (value) { - name = value; - }, - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: trigger == Trigger.template() ? ColoredClickableCard( - color: Theme.of(context).colorScheme.secondaryContainer, - text: "Add Trigger", - onTap: () { - print("add trigger"); // TODO add reaction - Navigator.of(context).pushNamed('/pipeline/action/new', - arguments: SetupActionPageArguments(trigger) - ).then((_) => setState(() {})); - } - ) : ActionCard( - leading: trigger.service.getLogo(logoSize: 50), - title: trigger.service.name, - trailing: ActionCardPopupMenu( - deletable: false, - action: trigger, - then: () => setState(() {})), - ), - ), - ...[ - for (Reaction reaction in reactions) - ActionCard( - leading: reaction.service.getLogo(logoSize: 50), - title: reaction.service.name, - trailing: ActionCardPopupMenu( - deletable: reaction != reactions[0], - action: reaction, - then: () => setState(() {})), - ) - ], - Padding( - padding: const EdgeInsets.all(8.0), - child: ColoredClickableCard( - color: Theme.of(context).colorScheme.secondaryContainer, - text: "Add Reaction", - onTap: () async { - // TODO add to db - reactions.add(Reaction.template()); - await Navigator.of(context).pushNamed('/pipeline/action/new', - arguments: SetupActionPageArguments(reactions.last) - ); - setState(() {}); - } - ), - ), - ElevatedButton( - child: const Text("Save"), - onPressed: () { - _formKey.currentState!.save(); - if (_formKey.currentState!.validate()) { - if (trigger == Trigger.template() || reactions.isEmpty || - reactions.where((element) => element == Reaction.template()).isNotEmpty) { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - backgroundColor: Theme.of(context).colorScheme.secondary, - content: const Text("You must select at least a trigger and a reaction")) - ); - } else { - Pipeline newPipeline = Pipeline( - id: 0, - name: _formKey.currentState!.value['name'], - triggerCount: 0, - enabled: true, - parameters: {}, - trigger: trigger, - reactions: reactions - ); - provider.addPipelineInProvider(newPipeline); - ///TODO add to db - Navigator.of(context).popAndPushNamed('/pipeline', - arguments: PipelineDetailPageArguments(newPipeline) - ); - } - } - }, - ), - ]), - )), - ]) - ) - ); + )), + ]))); } } diff --git a/mobile/lib/src/views/login_page.dart b/mobile/lib/src/views/login_page.dart index 411b00e..491ffe9 100644 --- a/mobile/lib/src/views/login_page.dart +++ b/mobile/lib/src/views/login_page.dart @@ -1,6 +1,8 @@ +import 'package:mobile/src/main.dart'; import 'package:mobile/src/widgets/aeris_page.dart'; import 'package:flutter_login/flutter_login.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; const users = { 'dribbble@gmail.com': '12345', @@ -19,10 +21,10 @@ class LoginPage extends StatelessWidget { debugPrint('Name: ${data.name}, Password: ${data.password}'); return Future.delayed(loginDuration).then((_) { if (!users.containsKey(data.name)) { - return 'User does not exists'; + return AppLocalizations.of(Aeris.materialKey.currentContext!)!.usernameOrPasswordIncorrect, } if (users[data.name] != data.password) { - return 'Password does not match'; + return AppLocalizations.of(Aeris.materialKey.currentContext!)!.usernameOrPasswordIncorrect, } return null; }); @@ -41,7 +43,7 @@ class LoginPage extends StatelessWidget { debugPrint('Name: $name'); return Future.delayed(loginDuration).then((_) { if (!users.containsKey(name)) { - return 'User does not exists'; + return AppLocalizations.of(Aeris.materialKey.currentContext!)!.userDoesNotExist; } return null; }); diff --git a/mobile/lib/src/views/pipeline_detail_page.dart b/mobile/lib/src/views/pipeline_detail_page.dart index 594707a..c9adf2a 100644 --- a/mobile/lib/src/views/pipeline_detail_page.dart +++ b/mobile/lib/src/views/pipeline_detail_page.dart @@ -1,3 +1,4 @@ +import 'package:mobile/src/main.dart'; import 'package:mobile/src/providers/pipelines_provider.dart'; import 'package:mobile/src/views/setup_action_page.dart'; import 'package:mobile/src/widgets/action_card_popup_menu.dart'; @@ -10,6 +11,7 @@ import 'package:mobile/src/models/reaction.dart'; import 'package:mobile/src/models/pipeline.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; /// Class to get the pipeline's name in route's arguments class PipelineDetailPageArguments { @@ -86,7 +88,7 @@ class _PipelineDetailPageState extends State { const SizedBox(height: 10), Align( alignment: Alignment.center, - child: Text(pipeline.enabled ? "Enabled" : "Disabed", + child: Text(pipeline.enabled ? AppLocalizations.of(context)!.enabled : AppLocalizations.of(context)!.disabled, style: const TextStyle(fontSize: 13) ), ), @@ -98,7 +100,7 @@ class _PipelineDetailPageState extends State { final Widget addReactionbutton = ColoredClickableCard( color: Theme.of(context).colorScheme.secondaryContainer, - text: "Add a reaction", + text: AppLocalizations.of(context)!.addReaction, onTap: () { Reaction newreaction = Reaction.template(); Navigator.of(context).pushNamed('/pipeline/action/new', @@ -116,10 +118,11 @@ class _PipelineDetailPageState extends State { final Widget deleteButton = ColoredClickableCard( color: Theme.of(context).colorScheme.error, - text: "Delete a Pipeline", + text: AppLocalizations.of(context)!.deletePipeline, onTap: () => showDialog( context: context, builder: (BuildContext context) => WarningDialog( + ///TODO translate message: "You are about to delete a pipeline. This action can not be undone. Are you sure ?", onAccept: () { @@ -127,7 +130,7 @@ class _PipelineDetailPageState extends State { print("Delete pipeline"); /*TODO call api*/ Navigator.of(context).pop(); }, - warnedAction: "Delete" + warnedAction: "Delete" ///TODO translate ) ), ); diff --git a/mobile/lib/src/views/service_page.dart b/mobile/lib/src/views/service_page.dart index 45d460d..4fb4c97 100644 --- a/mobile/lib/src/views/service_page.dart +++ b/mobile/lib/src/views/service_page.dart @@ -5,30 +5,33 @@ import 'package:mobile/src/widgets/action_card.dart'; import 'package:mobile/src/widgets/aeris_card_page.dart'; import 'package:mobile/src/widgets/warning_dialog.dart'; import 'package:provider/provider.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; ///Page listing connected & available services class ServicePage extends StatelessWidget { const ServicePage({Key? key}) : super(key: key); - List getServiceGroup(String groupName, Icon trailingIcon, void Function() onTap, BuildContext context) { - UserServiceProvider uServicesProvider = Provider.of(context); + List getServiceGroup(String groupName, Icon trailingIcon, + void Function() onTap, BuildContext context) { + UserServiceProvider uServicesProvider = + Provider.of(context); return [ - Text("$groupName:", + Text( + "$groupName:", style: const TextStyle(fontWeight: FontWeight.w500), ), const SizedBox(height: 10), for (var service in uServicesProvider.userServices) ActionCard( - leading: service.serviceProvider.getLogo(logoSize: 50), - title: service.serviceProvider.name, - trailing: IconButton( - splashColor: trailingIcon.color!.withAlpha(100), - splashRadius: 20, - icon: trailingIcon, - onPressed: onTap, - ) - ), + leading: service.serviceProvider.getLogo(logoSize: 50), + title: service.serviceProvider.name, + trailing: IconButton( + splashColor: trailingIcon.color!.withAlpha(100), + splashRadius: 20, + icon: trailingIcon, + onPressed: onTap, + )), const SizedBox(height: 30), ]; } @@ -43,7 +46,8 @@ class ServicePage extends StatelessWidget { Service.twitter(), Service.spotify() ]; - UserServiceProvider uServiceProvider = Provider.of(context, listen: false); + UserServiceProvider uServiceProvider = + Provider.of(context, listen: false); for (var service in services) { uServiceProvider.createUserService(service); } @@ -59,29 +63,32 @@ class ServicePage extends StatelessWidget { ...[ const Align( alignment: Alignment.center, - child: Text("Services", - style: TextStyle(fontSize: 25) - ), + child: Text("Services", style: TextStyle(fontSize: 25)), ), const SizedBox(height: 60) ], ...getServiceGroup( - "Connected", - const Icon(Icons.delete, color: Colors.red), - () => showDialog( - context: context, - builder: (BuildContext context) => WarningDialog( - message: "You are about to disconnect to a service. Once disconnected, every related pipeline will be deleted. This action cannot be undone.", - onAccept: () => print("Disconnect") /* TODO Delete service form db + related actions*/, - warnedAction: "Disconnect") - ), - context - ), + AppLocalizations.of(context)!.connected, + const Icon(Icons.delete, color: Colors.red), + () => showDialog( + context: context, + builder: (BuildContext context) => WarningDialog( + + ///TODO translate + message: + "You are about to disconnect to a service. Once disconnected, every related pipeline will be deleted. This action cannot be undone.", + onAccept: () => print( + "Disconnect") /* TODO Delete service form db + related actions*/, + + ///TODO translate + warnedAction: "Disconnect")), + context), ...getServiceGroup( - "Available", - const Icon(Icons.connect_without_contact, color: Colors.green), - () => print("Connected") /* TODO open page to connect service*/, - context), + + AppLocalizations.of(context)!.available, + const Icon(Icons.connect_without_contact, color: Colors.green), + () => print("Connected") /* TODO open page to connect service*/, + context), ], ), ), diff --git a/mobile/lib/src/views/setup_action_page.dart b/mobile/lib/src/views/setup_action_page.dart index eec5f66..435336f 100644 --- a/mobile/lib/src/views/setup_action_page.dart +++ b/mobile/lib/src/views/setup_action_page.dart @@ -81,6 +81,7 @@ class _SetupActionPageState extends State { children: [ Align( alignment: Alignment.centerLeft, + ///TODO translate child: Text( "${availableActions.length} available actions for ", )), diff --git a/mobile/lib/src/views/startup_page.dart b/mobile/lib/src/views/startup_page.dart index 65feea8..961c16a 100644 --- a/mobile/lib/src/views/startup_page.dart +++ b/mobile/lib/src/views/startup_page.dart @@ -31,6 +31,7 @@ class _StartupPageState extends State { const Padding( padding: EdgeInsets.all(20), child: OverlayedText( + ///TODO translate text: "Aeris is the best AREA in Nantes! Control each of your social network with Aeris, your new Action / Reaction app.", overlayedColor: Color.fromRGBO(50, 0, 27, 1), textColor: Color.fromRGBO(198, 93, 151, 1), @@ -49,7 +50,7 @@ class _StartupPageState extends State { Navigator.of(context).pushNamed('/login'); }, child: const Tooltip( - message: 'Connexion', + message: 'Connexion', ///TODO translate child: Text("Se connecter") ), ), diff --git a/mobile/lib/src/widgets/action_card_popup_menu.dart b/mobile/lib/src/widgets/action_card_popup_menu.dart index 7f1d867..5fbc5a6 100644 --- a/mobile/lib/src/widgets/action_card_popup_menu.dart +++ b/mobile/lib/src/widgets/action_card_popup_menu.dart @@ -37,6 +37,7 @@ class ActionCardPopupMenu extends StatelessWidget { AerisPopupMenuItem( context: context, icon: Icons.settings, + ///TODO translate title: "Modify", value: { 'route': "/pipeline/action/mod", @@ -45,6 +46,7 @@ class ActionCardPopupMenu extends StatelessWidget { AerisPopupMenuItem( context: context, icon: Icons.delete, + ///TODO translate title: "Delete", value: "/pipeline/action/del", enabled: deletable, diff --git a/mobile/lib/src/widgets/home_page_menu.dart b/mobile/lib/src/widgets/home_page_menu.dart index 1f4f812..b5edfcf 100644 --- a/mobile/lib/src/widgets/home_page_menu.dart +++ b/mobile/lib/src/widgets/home_page_menu.dart @@ -12,8 +12,10 @@ class HomePageMenu extends StatelessWidget { itemBuilder: (context) => [ AerisPopupMenuItem( context: context, + ///TODO translate icon: Icons.electrical_services, title: "Services", value: "/services"), AerisPopupMenuItem( + ///TODO translate context: context, icon: Icons.logout, title: "Logout", value: "/logout"), ], onSelected: (route) => Navigator.pushNamed(context, route as String), diff --git a/mobile/lib/src/widgets/home_page_sort_menu.dart b/mobile/lib/src/widgets/home_page_sort_menu.dart index dfb2573..5dfcda9 100644 --- a/mobile/lib/src/widgets/home_page_sort_menu.dart +++ b/mobile/lib/src/widgets/home_page_sort_menu.dart @@ -43,6 +43,7 @@ class HomePageSortMenu extends StatelessWidget { context: context, icon: Icons.call_merge, title: collectionProvider.pipelineCollection.sortingSplitDisabled + ///TODO translate ? "Merge disabled pipelines" : "Seperate disabled pipelines", value: "" From fb655e7e7382d0d83507fee5b431d517eadffd91 Mon Sep 17 00:00:00 2001 From: Arthi-chaud Date: Tue, 8 Feb 2022 11:56:03 +0100 Subject: [PATCH 03/10] Mobile client: Setting up basic translations --- mobile/lib/l10n/app_en.arb | 8 ++++- .../lib/src/views/pipeline_detail_page.dart | 5 ++- mobile/lib/src/views/setup_action_page.dart | 4 +-- .../lib/src/widgets/home_page_sort_menu.dart | 32 ++++++++++--------- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/mobile/lib/l10n/app_en.arb b/mobile/lib/l10n/app_en.arb index 533bd3d..18f63a2 100644 --- a/mobile/lib/l10n/app_en.arb +++ b/mobile/lib/l10n/app_en.arb @@ -3,11 +3,17 @@ "nameOfThePipeline": "Name of the pipeline", "addReaction": "Add a Reaction", "addTrigger": "Add a Trigger", + "delete": "Delete", "usernameOrPasswordIncorrect": "Username or password is incorrect", "userDoesNotExist": "User does not exist", "enabled": "Enabled", "disabled": "Disabled", "deletePipeline": "Delete Pipeline", "connected": "Connected", - "available": "Available" + "available": "Available", + "deletePipelineWarningMessage": "You are about to delete a pipeline. This action can not be undone. Are you sure ?", + "avalableActionsFor": "available actions for", + "mergeDisabledPipelines": "Merge disabled pipelines", + "seperateDisabledPipelines": "Seperate disabled pipelines", + } \ No newline at end of file diff --git a/mobile/lib/src/views/pipeline_detail_page.dart b/mobile/lib/src/views/pipeline_detail_page.dart index c9adf2a..7163fb2 100644 --- a/mobile/lib/src/views/pipeline_detail_page.dart +++ b/mobile/lib/src/views/pipeline_detail_page.dart @@ -122,15 +122,14 @@ class _PipelineDetailPageState extends State { onTap: () => showDialog( context: context, builder: (BuildContext context) => WarningDialog( - ///TODO translate message: - "You are about to delete a pipeline. This action can not be undone. Are you sure ?", + AppLocalizations.of(context)!.deletePipelineWarningMessage, onAccept: () { provider.removePipeline(pipeline); print("Delete pipeline"); /*TODO call api*/ Navigator.of(context).pop(); }, - warnedAction: "Delete" ///TODO translate + warnedAction: AppLocalizations.of(context)!.delete ) ), ); diff --git a/mobile/lib/src/views/setup_action_page.dart b/mobile/lib/src/views/setup_action_page.dart index 435336f..27069a1 100644 --- a/mobile/lib/src/views/setup_action_page.dart +++ b/mobile/lib/src/views/setup_action_page.dart @@ -5,6 +5,7 @@ import 'package:mobile/src/models/trigger.dart'; import 'package:mobile/src/widgets/action_form.dart'; import 'package:mobile/src/widgets/aeris_card_page.dart'; import 'package:expandable/expandable.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; /// Class to get the action in route's arguments class SetupActionPageArguments { @@ -81,9 +82,8 @@ class _SetupActionPageState extends State { children: [ Align( alignment: Alignment.centerLeft, - ///TODO translate child: Text( - "${availableActions.length} available actions for ", + "${availableActions.length} ${AppLocalizations.of(context)!.avalableActionsFor} ", )), Align(alignment: Alignment.centerRight, child: serviceDropdown), ], diff --git a/mobile/lib/src/widgets/home_page_sort_menu.dart b/mobile/lib/src/widgets/home_page_sort_menu.dart index 5dfcda9..fc49d45 100644 --- a/mobile/lib/src/widgets/home_page_sort_menu.dart +++ b/mobile/lib/src/widgets/home_page_sort_menu.dart @@ -4,6 +4,7 @@ import 'package:mobile/src/providers/pipelines_provider.dart'; import 'package:mobile/src/widgets/aeris_popup_menu.dart'; import 'package:mobile/src/widgets/aeris_popup_menu_item.dart'; import 'package:recase/recase.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; /// Sorting Menu for the Home Page class HomePageSortMenu extends StatelessWidget { @@ -33,28 +34,29 @@ class HomePageSortMenu extends StatelessWidget { ...[ for (var sortingMethod in PipelineCollectionSort.values) AerisPopupMenuItem( - context: context, - icon: sortMethodGetIcon(sortingMethod), - title: ReCase(sortingMethod.name).titleCase, - value: sortingMethod - ), + context: context, + icon: sortMethodGetIcon(sortingMethod), + title: ReCase(sortingMethod.name).titleCase, + value: sortingMethod), ], AerisPopupMenuItem( - context: context, - icon: Icons.call_merge, - title: collectionProvider.pipelineCollection.sortingSplitDisabled - ///TODO translate - ? "Merge disabled pipelines" - : "Seperate disabled pipelines", - value: "" - ), + context: context, + icon: Icons.call_merge, + title: collectionProvider.pipelineCollection.sortingSplitDisabled + + ///TODO translate + ? AppLocalizations.of(context)!.mergeDisabledPipelines + : AppLocalizations.of(context)!.seperateDisabledPipelines, + value: ""), ], onSelected: (sortingMethod) { /// TODO: not clean if (sortingMethod == "") { - collectionProvider.pipelineCollection.sortingSplitDisabled = !collectionProvider.pipelineCollection.sortingSplitDisabled; + collectionProvider.pipelineCollection.sortingSplitDisabled = + !collectionProvider.pipelineCollection.sortingSplitDisabled; } else { - collectionProvider.pipelineCollection.sortingMethod = sortingMethod as PipelineCollectionSort; + collectionProvider.pipelineCollection.sortingMethod = + sortingMethod as PipelineCollectionSort; } collectionProvider.sortPipelines(); }, From 90ddcef322af44bb2e9997bb82bd334bffbf5953 Mon Sep 17 00:00:00 2001 From: Arthi-chaud Date: Tue, 8 Feb 2022 14:04:42 +0100 Subject: [PATCH 04/10] Mobile client: English traduction --- mobile/lib/l10n/app_en.arb | 8 ++- mobile/lib/src/main.dart | 2 +- .../lib/src/views/create_pipeline_page.dart | 6 +- mobile/lib/src/views/login_page.dart | 41 +++++++------ .../lib/src/views/pipeline_detail_page.dart | 10 ++-- mobile/lib/src/views/service_page.dart | 11 ++-- mobile/lib/src/views/setup_action_page.dart | 2 +- mobile/lib/src/views/startup_page.dart | 19 +++--- .../src/widgets/action_card_popup_menu.dart | 60 +++++++++---------- mobile/lib/src/widgets/home_page_menu.dart | 15 +++-- .../lib/src/widgets/home_page_sort_menu.dart | 6 +- mobile/test/widget_test.dart | 2 +- 12 files changed, 93 insertions(+), 89 deletions(-) diff --git a/mobile/lib/l10n/app_en.arb b/mobile/lib/l10n/app_en.arb index 18f63a2..6caae2a 100644 --- a/mobile/lib/l10n/app_en.arb +++ b/mobile/lib/l10n/app_en.arb @@ -3,17 +3,23 @@ "nameOfThePipeline": "Name of the pipeline", "addReaction": "Add a Reaction", "addTrigger": "Add a Trigger", + "modify": "Modify", "delete": "Delete", + "services": "Services", + "logout": "Logout", "usernameOrPasswordIncorrect": "Username or password is incorrect", "userDoesNotExist": "User does not exist", "enabled": "Enabled", "disabled": "Disabled", + "disconnect": "Disconnect", "deletePipeline": "Delete Pipeline", "connected": "Connected", + "connect": "Connect", "available": "Available", + "disconnectServiceWarningMessage": "You are about to disconnect to a service. Once disconnected, every related pipeline will be deleted. This action cannot be undone.", "deletePipelineWarningMessage": "You are about to delete a pipeline. This action can not be undone. Are you sure ?", "avalableActionsFor": "available actions for", "mergeDisabledPipelines": "Merge disabled pipelines", "seperateDisabledPipelines": "Seperate disabled pipelines", - + "aerisDescription": "Aeris is the best AREA in Nantes! Control each of your social network with Aeris, your new Action / Reaction app." } \ No newline at end of file diff --git a/mobile/lib/src/main.dart b/mobile/lib/src/main.dart index ca2a8db..504d5da 100644 --- a/mobile/lib/src/main.dart +++ b/mobile/lib/src/main.dart @@ -41,7 +41,7 @@ class Aeris extends StatelessWidget { ], supportedLocales: const [Locale('fr', ''), Locale('en', '')], theme: ThemeData(colorScheme: aerisScheme), - initialRoute: '/home', + initialRoute: '/', onGenerateRoute: (settings) { Map pageRoutes = { '/': () => const StartupPage(), diff --git a/mobile/lib/src/views/create_pipeline_page.dart b/mobile/lib/src/views/create_pipeline_page.dart index b8ef8c2..d9d5225 100644 --- a/mobile/lib/src/views/create_pipeline_page.dart +++ b/mobile/lib/src/views/create_pipeline_page.dart @@ -52,7 +52,7 @@ class _CreatePipelinePageState extends State { initialValue: name, decoration: InputDecoration( labelText: - AppLocalizations.of(context)!.nameOfThePipeline, + AppLocalizations.of(context).nameOfThePipeline, ), validator: FormBuilderValidators.compose([ FormBuilderValidators.required(context), @@ -69,7 +69,7 @@ class _CreatePipelinePageState extends State { color: Theme.of(context) .colorScheme .secondaryContainer, - text: AppLocalizations.of(context)!.addTrigger, + text: AppLocalizations.of(context).addTrigger, onTap: () { print("add trigger"); // TODO add reaction Navigator.of(context) @@ -104,7 +104,7 @@ class _CreatePipelinePageState extends State { color: Theme.of(context) .colorScheme .secondaryContainer, - text: AppLocalizations.of(context)!.addReaction, + text: AppLocalizations.of(context).addReaction, onTap: () async { // TODO add to db reactions.add(Reaction.template()); diff --git a/mobile/lib/src/views/login_page.dart b/mobile/lib/src/views/login_page.dart index 491ffe9..221e5b1 100644 --- a/mobile/lib/src/views/login_page.dart +++ b/mobile/lib/src/views/login_page.dart @@ -21,10 +21,12 @@ class LoginPage extends StatelessWidget { debugPrint('Name: ${data.name}, Password: ${data.password}'); return Future.delayed(loginDuration).then((_) { if (!users.containsKey(data.name)) { - return AppLocalizations.of(Aeris.materialKey.currentContext!)!.usernameOrPasswordIncorrect, + return AppLocalizations.of(Aeris.materialKey.currentContext!) + .usernameOrPasswordIncorrect; } if (users[data.name] != data.password) { - return AppLocalizations.of(Aeris.materialKey.currentContext!)!.usernameOrPasswordIncorrect, + return AppLocalizations.of(Aeris.materialKey.currentContext!) + .usernameOrPasswordIncorrect; } return null; }); @@ -43,7 +45,7 @@ class LoginPage extends StatelessWidget { debugPrint('Name: $name'); return Future.delayed(loginDuration).then((_) { if (!users.containsKey(name)) { - return AppLocalizations.of(Aeris.materialKey.currentContext!)!.userDoesNotExist; + return AppLocalizations.of(Aeris.materialKey.currentContext!).userDoesNotExist; } return null; }); @@ -52,23 +54,20 @@ class LoginPage extends StatelessWidget { @override Widget build(BuildContext context) { return AerisPage( - displayAppbar: false, - body: FlutterLogin( - disableCustomPageTransformer: true, - logo: const AssetImage("assets/logo.png"), - onRecoverPassword: _recoverPassword, - theme: LoginTheme( - pageColorLight: Colors.transparent, - pageColorDark: Colors.transparent, - primaryColor: Theme.of(context).colorScheme.primary - ), - onLogin: _authUser, - onSignup: _signupUser, - onSubmitAnimationCompleted: () { - Navigator.of(context).popUntil((route) => route.isFirst); - Navigator.of(context).popAndPushNamed("/home"); - } - ) - ); + displayAppbar: false, + body: FlutterLogin( + disableCustomPageTransformer: true, + logo: const AssetImage("assets/logo.png"), + onRecoverPassword: _recoverPassword, + theme: LoginTheme( + pageColorLight: Colors.transparent, + pageColorDark: Colors.transparent, + primaryColor: Theme.of(context).colorScheme.primary), + onLogin: _authUser, + onSignup: _signupUser, + onSubmitAnimationCompleted: () { + Navigator.of(context).popUntil((route) => route.isFirst); + Navigator.of(context).popAndPushNamed("/home"); + })); } } diff --git a/mobile/lib/src/views/pipeline_detail_page.dart b/mobile/lib/src/views/pipeline_detail_page.dart index 7163fb2..2284a8c 100644 --- a/mobile/lib/src/views/pipeline_detail_page.dart +++ b/mobile/lib/src/views/pipeline_detail_page.dart @@ -88,7 +88,7 @@ class _PipelineDetailPageState extends State { const SizedBox(height: 10), Align( alignment: Alignment.center, - child: Text(pipeline.enabled ? AppLocalizations.of(context)!.enabled : AppLocalizations.of(context)!.disabled, + child: Text(pipeline.enabled ? AppLocalizations.of(context).enabled : AppLocalizations.of(context).disabled, style: const TextStyle(fontSize: 13) ), ), @@ -100,7 +100,7 @@ class _PipelineDetailPageState extends State { final Widget addReactionbutton = ColoredClickableCard( color: Theme.of(context).colorScheme.secondaryContainer, - text: AppLocalizations.of(context)!.addReaction, + text: AppLocalizations.of(context).addReaction, onTap: () { Reaction newreaction = Reaction.template(); Navigator.of(context).pushNamed('/pipeline/action/new', @@ -118,18 +118,18 @@ class _PipelineDetailPageState extends State { final Widget deleteButton = ColoredClickableCard( color: Theme.of(context).colorScheme.error, - text: AppLocalizations.of(context)!.deletePipeline, + text: AppLocalizations.of(context).deletePipeline, onTap: () => showDialog( context: context, builder: (BuildContext context) => WarningDialog( message: - AppLocalizations.of(context)!.deletePipelineWarningMessage, + AppLocalizations.of(context).deletePipelineWarningMessage, onAccept: () { provider.removePipeline(pipeline); print("Delete pipeline"); /*TODO call api*/ Navigator.of(context).pop(); }, - warnedAction: AppLocalizations.of(context)!.delete + warnedAction: AppLocalizations.of(context).delete ) ), ); diff --git a/mobile/lib/src/views/service_page.dart b/mobile/lib/src/views/service_page.dart index 4fb4c97..8962732 100644 --- a/mobile/lib/src/views/service_page.dart +++ b/mobile/lib/src/views/service_page.dart @@ -68,24 +68,21 @@ class ServicePage extends StatelessWidget { const SizedBox(height: 60) ], ...getServiceGroup( - AppLocalizations.of(context)!.connected, + AppLocalizations.of(context).connected, const Icon(Icons.delete, color: Colors.red), () => showDialog( context: context, builder: (BuildContext context) => WarningDialog( - ///TODO translate - message: - "You are about to disconnect to a service. Once disconnected, every related pipeline will be deleted. This action cannot be undone.", + message:AppLocalizations.of(context).disconnectServiceWarningMessage, onAccept: () => print( "Disconnect") /* TODO Delete service form db + related actions*/, - ///TODO translate - warnedAction: "Disconnect")), + warnedAction: AppLocalizations.of(context).disconnect)), context), ...getServiceGroup( - AppLocalizations.of(context)!.available, + AppLocalizations.of(context).available, const Icon(Icons.connect_without_contact, color: Colors.green), () => print("Connected") /* TODO open page to connect service*/, context), diff --git a/mobile/lib/src/views/setup_action_page.dart b/mobile/lib/src/views/setup_action_page.dart index 27069a1..54b5ffd 100644 --- a/mobile/lib/src/views/setup_action_page.dart +++ b/mobile/lib/src/views/setup_action_page.dart @@ -83,7 +83,7 @@ class _SetupActionPageState extends State { Align( alignment: Alignment.centerLeft, child: Text( - "${availableActions.length} ${AppLocalizations.of(context)!.avalableActionsFor} ", + "${availableActions.length} ${AppLocalizations.of(context).avalableActionsFor} ", )), Align(alignment: Alignment.centerRight, child: serviceDropdown), ], diff --git a/mobile/lib/src/views/startup_page.dart b/mobile/lib/src/views/startup_page.dart index 961c16a..8507899 100644 --- a/mobile/lib/src/views/startup_page.dart +++ b/mobile/lib/src/views/startup_page.dart @@ -1,7 +1,7 @@ import 'package:flutter_fadein/flutter_fadein.dart'; import 'package:flutter/material.dart'; import '../widgets/aeris_page.dart'; - +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import '../../aeris.dart'; /// [StatefulWidget] used in order to display StartupPage [Widget] @@ -28,13 +28,12 @@ class _StartupPageState extends State { curve: Curves.easeInOut ) ), - const Padding( - padding: EdgeInsets.all(20), + Padding( + padding: const EdgeInsets.all(20), child: OverlayedText( - ///TODO translate - text: "Aeris is the best AREA in Nantes! Control each of your social network with Aeris, your new Action / Reaction app.", - overlayedColor: Color.fromRGBO(50, 0, 27, 1), - textColor: Color.fromRGBO(198, 93, 151, 1), + text: AppLocalizations.of(context).aerisDescription, + overlayedColor: const Color.fromRGBO(50, 0, 27, 1), + textColor: const Color.fromRGBO(198, 93, 151, 1), fontSize: 20, strokeWidth: 2.15 ) @@ -49,9 +48,9 @@ class _StartupPageState extends State { onPressed: () { Navigator.of(context).pushNamed('/login'); }, - child: const Tooltip( - message: 'Connexion', ///TODO translate - child: Text("Se connecter") + child: Tooltip( + message: 'Connexion', + child: Text(AppLocalizations.of(context).connect) ), ), ) diff --git a/mobile/lib/src/widgets/action_card_popup_menu.dart b/mobile/lib/src/widgets/action_card_popup_menu.dart index 5fbc5a6..8971a08 100644 --- a/mobile/lib/src/widgets/action_card_popup_menu.dart +++ b/mobile/lib/src/widgets/action_card_popup_menu.dart @@ -3,6 +3,7 @@ import 'package:mobile/src/views/setup_action_page.dart'; import 'package:mobile/src/widgets/aeris_popup_menu.dart'; import 'package:mobile/src/widgets/aeris_popup_menu_item.dart'; import 'package:mobile/src/models/action.dart' as aeris; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; /// [StatelessWidget] displayed as a PopupMenu class ActionCardPopupMenu extends StatelessWidget { @@ -25,35 +26,34 @@ class ActionCardPopupMenu extends StatelessWidget { @override Widget build(BuildContext context) { return AerisPopupMenu( - onSelected: (value) { - Map object = value as Map; - Navigator.pushNamed(context, object['route'] as String, arguments: object['params']).then((r) { - then(); - return r; - }); - }, - icon: Icons.more_vert, - itemBuilder: (context) => [ - AerisPopupMenuItem( - context: context, - icon: Icons.settings, - ///TODO translate - title: "Modify", - value: { - 'route': "/pipeline/action/mod", - 'params': SetupActionPageArguments(action), - }), - AerisPopupMenuItem( - context: context, - icon: Icons.delete, - ///TODO translate - title: "Delete", - value: "/pipeline/action/del", - enabled: deletable, - // TODO Delete from parent pipeline - /* TODO Define delete route*/ - ), - ] - ); + onSelected: (value) { + Map object = value as Map; + Navigator.pushNamed(context, object['route'] as String, + arguments: object['params']) + .then((r) { + then(); + return r; + }); + }, + icon: Icons.more_vert, + itemBuilder: (context) => [ + AerisPopupMenuItem( + context: context, + icon: Icons.settings, + title: AppLocalizations.of(context).modify, + value: { + 'route': "/pipeline/action/mod", + 'params': SetupActionPageArguments(action), + }), + AerisPopupMenuItem( + context: context, + icon: Icons.delete, + title: AppLocalizations.of(context).delete, + value: "/pipeline/action/del", + enabled: deletable, + // TODO Delete from parent pipeline + /* TODO Define delete route*/ + ), + ]); } } diff --git a/mobile/lib/src/widgets/home_page_menu.dart b/mobile/lib/src/widgets/home_page_menu.dart index b5edfcf..fc03632 100644 --- a/mobile/lib/src/widgets/home_page_menu.dart +++ b/mobile/lib/src/widgets/home_page_menu.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:mobile/src/widgets/aeris_popup_menu.dart'; import 'package:mobile/src/widgets/aeris_popup_menu_item.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; /// Menu for the Home Page class HomePageMenu extends StatelessWidget { @@ -11,12 +12,16 @@ class HomePageMenu extends StatelessWidget { return AerisPopupMenu( itemBuilder: (context) => [ AerisPopupMenuItem( - context: context, - ///TODO translate - icon: Icons.electrical_services, title: "Services", value: "/services"), + context: context, + icon: Icons.electrical_services, + title: AppLocalizations.of(context).services, + value: "/services"), AerisPopupMenuItem( - ///TODO translate - context: context, icon: Icons.logout, title: "Logout", value: "/logout"), + + context: context, + icon: Icons.logout, + title: AppLocalizations.of(context).logout, + value: "/logout"), ], onSelected: (route) => Navigator.pushNamed(context, route as String), icon: Icons.more_horiz, diff --git a/mobile/lib/src/widgets/home_page_sort_menu.dart b/mobile/lib/src/widgets/home_page_sort_menu.dart index fc49d45..cdc2a17 100644 --- a/mobile/lib/src/widgets/home_page_sort_menu.dart +++ b/mobile/lib/src/widgets/home_page_sort_menu.dart @@ -43,10 +43,8 @@ class HomePageSortMenu extends StatelessWidget { context: context, icon: Icons.call_merge, title: collectionProvider.pipelineCollection.sortingSplitDisabled - - ///TODO translate - ? AppLocalizations.of(context)!.mergeDisabledPipelines - : AppLocalizations.of(context)!.seperateDisabledPipelines, + ? AppLocalizations.of(context).mergeDisabledPipelines + : AppLocalizations.of(context).seperateDisabledPipelines, value: ""), ], onSelected: (sortingMethod) { diff --git a/mobile/test/widget_test.dart b/mobile/test/widget_test.dart index 51b48fe..514db74 100644 --- a/mobile/test/widget_test.dart +++ b/mobile/test/widget_test.dart @@ -12,7 +12,7 @@ import 'package:mobile/src/main.dart'; void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); + await tester.pumpWidget(const Aeris()); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget); From 28685927632892dd6e0266a175a94aac0e0b6c57 Mon Sep 17 00:00:00 2001 From: Arthi-chaud Date: Tue, 8 Feb 2022 14:12:09 +0100 Subject: [PATCH 05/10] Mobile client: french traduction --- mobile/lib/l10n/app_fr.arb | 24 +++++++++++++++++++++++- mobile/lib/src/main.dart | 1 + 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/mobile/lib/l10n/app_fr.arb b/mobile/lib/l10n/app_fr.arb index 684fff7..7f8215a 100644 --- a/mobile/lib/l10n/app_fr.arb +++ b/mobile/lib/l10n/app_fr.arb @@ -1,3 +1,25 @@ { - "helloWorld": "Salutations au peuple" + "helloWorld": "Bonjour le monde!", + "nameOfThePipeline": "Nom de la pipeline", + "addReaction": "Ajouter une Reaction", + "addTrigger": "Ajouter un Déclancheur", + "modify": "Modifier", + "delete": "Supprimer", + "services": "Services", + "logout": "Se Deconnecter", + "usernameOrPasswordIncorrect": "Nom d'utilisateur ou mot de passe incorrect", + "userDoesNotExist": "L'utilisateur n'existe pas", + "enabled": "Activé", + "disabled": "Désactivé", + "disconnect": "Déconnecter", + "deletePipeline": "Supprimer la Pipeline", + "connected": "Connecté", + "connect": "Se Connecter", + "available": "Disponible", + "disconnectServiceWarningMessage": "Vous allez supprimer un service. Une fois fait, toutes les pipelines associées seront supprimées. Cela ne peut pas être annulé.", + "deletePipelineWarningMessage": "Vous allez supprimer une pipeline. Cela ne peut pas être annulé.", + "avalableActionsFor": "Actions disponibles pour", + "mergeDisabledPipelines": "Mélanger les pipelines désactivées", + "seperateDisabledPipelines": "Séparer les pipelines désactivées", + "aerisDescription": "Aeris est le meilleur AREA de Nantes! Prennez le contrôle de vos réseaux sociaux avec Aeris, la nouvelle application de pipeline!" } \ No newline at end of file diff --git a/mobile/lib/src/main.dart b/mobile/lib/src/main.dart index 504d5da..7a343ab 100644 --- a/mobile/lib/src/main.dart +++ b/mobile/lib/src/main.dart @@ -29,6 +29,7 @@ class Aeris extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( + locale: const Locale('fr', ''), navigatorKey: Aeris.materialKey, debugShowCheckedModeBanner: false, title: 'Aeris', From a7467b2fb576b5d2bab5b88da70c1934603a45f2 Mon Sep 17 00:00:00 2001 From: Arthi-chaud Date: Tue, 8 Feb 2022 14:24:28 +0100 Subject: [PATCH 06/10] Mobile client: french traduction --- mobile/Dockerfile | 2 ++ mobile/lib/l10n/app_en.arb | 4 ++++ mobile/lib/l10n/app_fr.arb | 4 ++++ mobile/lib/src/models/trigger.dart | 10 +++++++--- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/mobile/Dockerfile b/mobile/Dockerfile index 5fd4bc0..7bc2bea 100644 --- a/mobile/Dockerfile +++ b/mobile/Dockerfile @@ -11,5 +11,7 @@ COPY pubspec.* ./ RUN flutter pub get COPY . . +# Generate traduction files +RUN fkutter gen-l10n RUN flutter build apk lib/src/main.dart CMD mv ./build/app/outputs/flutter-apk/app-release.apk /dist/aeris_android.apk diff --git a/mobile/lib/l10n/app_en.arb b/mobile/lib/l10n/app_en.arb index 6caae2a..92e5cb3 100644 --- a/mobile/lib/l10n/app_en.arb +++ b/mobile/lib/l10n/app_en.arb @@ -1,5 +1,9 @@ { "helloWorld": "Hello World!", + "lastTrigger": "Last", + "never": "Never", + "nDaysAgo": "n days ago", + "today": "Today", "nameOfThePipeline": "Name of the pipeline", "addReaction": "Add a Reaction", "addTrigger": "Add a Trigger", diff --git a/mobile/lib/l10n/app_fr.arb b/mobile/lib/l10n/app_fr.arb index 7f8215a..6fe4ca0 100644 --- a/mobile/lib/l10n/app_fr.arb +++ b/mobile/lib/l10n/app_fr.arb @@ -1,5 +1,9 @@ { "helloWorld": "Bonjour le monde!", + "lastTrigger": "Dernière", + "never": "Jamais", + "nDaysAgo": " jours", + "today": "Aujourd'hui", "nameOfThePipeline": "Nom de la pipeline", "addReaction": "Ajouter une Reaction", "addTrigger": "Ajouter un Déclancheur", diff --git a/mobile/lib/src/models/trigger.dart b/mobile/lib/src/models/trigger.dart index ec34c61..cfc2835 100644 --- a/mobile/lib/src/models/trigger.dart +++ b/mobile/lib/src/models/trigger.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:mobile/src/main.dart'; import 'package:mobile/src/models/service.dart'; import 'package:mobile/src/models/action.dart' as aeris_action; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; ///Object representation of a pipeline trigger class Trigger extends aeris_action.Action { @@ -17,11 +19,13 @@ class Trigger extends aeris_action.Action { ///TODO Constructor from DB 'Type' field ///TODO translate String lastToString() { - if (last == null) return 'Last: Never'; + var context = AppLocalizations.of(Aeris.materialKey.currentContext!); + String lastStr = context.lastTrigger; + if (last == null) return '$lastStr: ${context.lastTrigger}'; int elapsedDays = DateTime.now().difference(last!).inDays; return elapsedDays == 0 - ? 'Last: Today' - : 'Last: ${elapsedDays.toString()}d ago'; + ? '$lastStr: ${context.today}' + : '$lastStr: $elapsedDays${context.nDaysAgo}'; } /// Template trigger, used as an 'empty' trigger From 8761af1d33739819a2f2a0bdb28442ecc99c6856 Mon Sep 17 00:00:00 2001 From: Arthi-chaud Date: Tue, 8 Feb 2022 16:01:56 +0100 Subject: [PATCH 07/10] Mobile Client: When deleting service, delete related actions + Setup action form :default values --- mobile/lib/src/models/action.dart | 2 +- mobile/lib/src/models/reaction.dart | 2 +- mobile/lib/src/models/trigger.dart | 2 +- mobile/lib/src/views/service_page.dart | 94 +++++++++++++-------- mobile/lib/src/views/setup_action_page.dart | 3 +- mobile/lib/src/widgets/action_form.dart | 5 +- 6 files changed, 67 insertions(+), 41 deletions(-) diff --git a/mobile/lib/src/models/action.dart b/mobile/lib/src/models/action.dart index e1f5efe..4d34a12 100644 --- a/mobile/lib/src/models/action.dart +++ b/mobile/lib/src/models/action.dart @@ -10,7 +10,7 @@ abstract class Action { String name; ///Action's parameters - Map parameters; + Map parameters; Action( {Key? key, required this.service, diff --git a/mobile/lib/src/models/reaction.dart b/mobile/lib/src/models/reaction.dart index 496d911..5dde37d 100644 --- a/mobile/lib/src/models/reaction.dart +++ b/mobile/lib/src/models/reaction.dart @@ -8,7 +8,7 @@ class Reaction extends aeris_action.Action { {Key? key, required Service service, required String name, - Map parameters = const {}}) + Map parameters = const {}}) : super(service: service, name: name, parameters: parameters); /// Template trigger, used as an 'empty' trigger diff --git a/mobile/lib/src/models/trigger.dart b/mobile/lib/src/models/trigger.dart index cfc2835..c07273a 100644 --- a/mobile/lib/src/models/trigger.dart +++ b/mobile/lib/src/models/trigger.dart @@ -12,7 +12,7 @@ class Trigger extends aeris_action.Action { {Key? key, required Service service, required String name, - Map parameters = const {}, + Map parameters = const {}, this.last}) : super(service: service, name: name, parameters: parameters); diff --git a/mobile/lib/src/views/service_page.dart b/mobile/lib/src/views/service_page.dart index 8962732..c8c973e 100644 --- a/mobile/lib/src/views/service_page.dart +++ b/mobile/lib/src/views/service_page.dart @@ -1,5 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:mobile/src/models/pipeline.dart'; +import 'package:mobile/src/models/reaction.dart'; import 'package:mobile/src/models/service.dart'; +import 'package:mobile/src/providers/pipelines_provider.dart'; import 'package:mobile/src/providers/user_services_provider.dart'; import 'package:mobile/src/widgets/action_card.dart'; import 'package:mobile/src/widgets/aeris_card_page.dart'; @@ -12,7 +15,7 @@ class ServicePage extends StatelessWidget { const ServicePage({Key? key}) : super(key: key); List getServiceGroup(String groupName, Icon trailingIcon, - void Function() onTap, BuildContext context) { + void Function(Service) onTap, BuildContext context) { UserServiceProvider uServicesProvider = Provider.of(context); @@ -30,7 +33,7 @@ class ServicePage extends StatelessWidget { splashColor: trailingIcon.color!.withAlpha(100), splashRadius: 20, icon: trailingIcon, - onPressed: onTap, + onPressed: () => onTap(service.serviceProvider), )), const SizedBox(height: 30), ]; @@ -52,41 +55,60 @@ class ServicePage extends StatelessWidget { uServiceProvider.createUserService(service); } - return AerisCardPage( - body: NotificationListener( - onNotification: (overscroll) { - overscroll.disallowIndicator(); - return true; - }, - child: ListView( - children: [ - ...[ - const Align( - alignment: Alignment.center, - child: Text("Services", style: TextStyle(fontSize: 25)), - ), - const SizedBox(height: 60) + return Consumer( + builder: (context, provider, _) => AerisCardPage( + body: NotificationListener( + onNotification: (overscroll) { + overscroll.disallowIndicator(); + return true; + }, + child: ListView( + children: [ + ...[ + const Align( + alignment: Alignment.center, + child: Text("Services", style: TextStyle(fontSize: 25)), + ), + const SizedBox(height: 60) + ], + ...getServiceGroup( + AppLocalizations.of(context).connected, + const Icon(Icons.delete, color: Colors.red), + (Service service) => showDialog( + context: context, + builder: (BuildContext context) => WarningDialog( + message: AppLocalizations.of(context) + .disconnectServiceWarningMessage, + onAccept: () => { + provider.pipelineCollection.pipelines + .removeWhere((Pipeline pipeline) { + if (pipeline.trigger.service == service) { + return true; + } + if (pipeline.reactions + .where((Reaction react) => + react.service == service) + .isNotEmpty) { + return true; + } + return false; + }), + /// TODO Remove service from provider + provider.notifyListeners(), + print("Disconnect") + } /* TODO Delete service form db + related actions*/, + warnedAction: + AppLocalizations.of(context).disconnect)), + context), + ...getServiceGroup( + AppLocalizations.of(context).available, + const Icon(Icons.connect_without_contact, + color: Colors.green), + (Service service) => + print("Connected") /* TODO open page to connect service*/, + context), ], - ...getServiceGroup( - AppLocalizations.of(context).connected, - const Icon(Icons.delete, color: Colors.red), - () => showDialog( - context: context, - builder: (BuildContext context) => WarningDialog( - - message:AppLocalizations.of(context).disconnectServiceWarningMessage, - onAccept: () => print( - "Disconnect") /* TODO Delete service form db + related actions*/, - - warnedAction: AppLocalizations.of(context).disconnect)), - context), - ...getServiceGroup( - - AppLocalizations.of(context).available, - const Icon(Icons.connect_without_contact, color: Colors.green), - () => print("Connected") /* TODO open page to connect service*/, - context), - ], + ), ), ), ); diff --git a/mobile/lib/src/views/setup_action_page.dart b/mobile/lib/src/views/setup_action_page.dart index 54b5ffd..b4a9c5a 100644 --- a/mobile/lib/src/views/setup_action_page.dart +++ b/mobile/lib/src/views/setup_action_page.dart @@ -39,7 +39,7 @@ class _SetupActionPageState extends State { last: DateTime.now(), service: arguments.action.service, name: "action", - parameters: {'key1': 'value1', 'key2': null}) + parameters: {'key1': 'value1', 'key2': 'value2'}) ]; final Widget serviceDropdown = DropdownButton( @@ -105,6 +105,7 @@ class _SetupActionPageState extends State { name: availableAction.name, parametersNames: availableAction.parameters.keys.toList(), + initValues: availableAction.parameters, onValidate: (parameters) { arguments.action.service = serviceState!; arguments.action.parameters = parameters; diff --git a/mobile/lib/src/widgets/action_form.dart b/mobile/lib/src/widgets/action_form.dart index dbbad41..5913fd7 100644 --- a/mobile/lib/src/widgets/action_form.dart +++ b/mobile/lib/src/widgets/action_form.dart @@ -1,3 +1,5 @@ +import 'dart:ffi'; + import 'package:flutter/material.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:form_builder_validators/form_builder_validators.dart'; @@ -9,7 +11,7 @@ class ActionForm extends StatefulWidget { /// Names of the parameters final List parametersNames; /// Initial values of the fields - final Map initValues; + final Map initValues; /// On validate callback final void Function(Map) onValidate; @@ -44,6 +46,7 @@ class _ActionFormState extends State { validator: FormBuilderValidators.compose([ FormBuilderValidators.required(context), ]), + keyboardType: (widget.initValues.containsKey(name)) && widget.initValues[name] is Int ? TextInputType.number : null, )), ...[ ElevatedButton( From ef9773f5bb73acff134a7ecd9394323ffdb5d169 Mon Sep 17 00:00:00 2001 From: Arthi-chaud Date: Tue, 8 Feb 2022 16:32:50 +0100 Subject: [PATCH 08/10] Mobile Client: In forms, get values from previous state + delete action button --- mobile/lib/src/main.dart | 2 +- .../lib/src/views/create_pipeline_page.dart | 18 +- .../lib/src/views/pipeline_detail_page.dart | 212 +++++++++--------- mobile/lib/src/views/setup_action_page.dart | 2 +- .../src/widgets/action_card_popup_menu.dart | 30 ++- 5 files changed, 136 insertions(+), 128 deletions(-) diff --git a/mobile/lib/src/main.dart b/mobile/lib/src/main.dart index 7a343ab..c67c499 100644 --- a/mobile/lib/src/main.dart +++ b/mobile/lib/src/main.dart @@ -42,7 +42,7 @@ class Aeris extends StatelessWidget { ], supportedLocales: const [Locale('fr', ''), Locale('en', '')], theme: ThemeData(colorScheme: aerisScheme), - initialRoute: '/', + initialRoute: '/home', onGenerateRoute: (settings) { Map pageRoutes = { '/': () => const StartupPage(), diff --git a/mobile/lib/src/views/create_pipeline_page.dart b/mobile/lib/src/views/create_pipeline_page.dart index d9d5225..9c67822 100644 --- a/mobile/lib/src/views/create_pipeline_page.dart +++ b/mobile/lib/src/views/create_pipeline_page.dart @@ -90,13 +90,17 @@ class _CreatePipelinePageState extends State { ...[ for (Reaction reaction in reactions) ActionCard( - leading: reaction.service.getLogo(logoSize: 50), - title: reaction.service.name, - trailing: ActionCardPopupMenu( - deletable: reaction != reactions[0], - action: reaction, - then: () => setState(() {})), - ) + leading: reaction.service.getLogo(logoSize: 50), + title: reaction.service.name, + trailing: ActionCardPopupMenu( + deletable: reaction != reactions[0], + action: reaction, + then: () => setState(() {}), + onDelete: () { + setState(() { + reactions.remove(reaction); + }); + })) ], Padding( padding: const EdgeInsets.all(8.0), diff --git a/mobile/lib/src/views/pipeline_detail_page.dart b/mobile/lib/src/views/pipeline_detail_page.dart index 2284a8c..3796d9a 100644 --- a/mobile/lib/src/views/pipeline_detail_page.dart +++ b/mobile/lib/src/views/pipeline_detail_page.dart @@ -35,7 +35,9 @@ class _PipelineDetailPageState extends State { @override Widget build(BuildContext context) => Consumer(builder: (context, provider, _) { - final PipelineDetailPageArguments arguments = ModalRoute.of(context)!.settings.arguments as PipelineDetailPageArguments; + final PipelineDetailPageArguments arguments = ModalRoute.of(context)! + .settings + .arguments as PipelineDetailPageArguments; Pipeline pipeline = arguments.pipeline; final cardHeader = Row( @@ -47,139 +49,129 @@ class _PipelineDetailPageState extends State { Align( alignment: Alignment.centerLeft, child: Text(pipeline.name, - style: const TextStyle( - fontSize: 25, - ) - ), + style: const TextStyle( + fontSize: 25, + )), ), const SizedBox(height: 10), Align( alignment: Alignment.centerLeft, child: Text(pipeline.trigger.lastToString(), - style: const TextStyle( - fontSize: 17, - ) - ), + style: const TextStyle( + fontSize: 17, + )), ), ], ), ), Expanded( - flex: 3, - child: Column( - children: [ - const SizedBox(height: 10), - Align( - alignment: Alignment.center, - child: FlutterSwitch( - activeColor: Colors.green, - width: 60, - value: pipeline.enabled, - onToggle: (value) { - setState(() { - pipeline.enabled = !pipeline.enabled; - provider.sortPipelines(); - provider.notifyListeners(); - // TODO call api - }); - }, + flex: 3, + child: Column( + children: [ + const SizedBox(height: 10), + Align( + alignment: Alignment.center, + child: FlutterSwitch( + activeColor: Colors.green, + width: 60, + value: pipeline.enabled, + onToggle: (value) { + setState(() { + pipeline.enabled = !pipeline.enabled; + provider.sortPipelines(); + provider.notifyListeners(); + // TODO call api + }); + }, + ), ), - ), - const SizedBox(height: 10), - Align( - alignment: Alignment.center, - child: Text(pipeline.enabled ? AppLocalizations.of(context).enabled : AppLocalizations.of(context).disabled, - style: const TextStyle(fontSize: 13) + const SizedBox(height: 10), + Align( + alignment: Alignment.center, + child: Text( + pipeline.enabled + ? AppLocalizations.of(context).enabled + : AppLocalizations.of(context).disabled, + style: const TextStyle(fontSize: 13)), ), - ), - ], - ) - ) + ], + )) ], ); final Widget addReactionbutton = ColoredClickableCard( - color: Theme.of(context).colorScheme.secondaryContainer, - text: AppLocalizations.of(context).addReaction, - onTap: () { - Reaction newreaction = Reaction.template(); - Navigator.of(context).pushNamed('/pipeline/action/new', - arguments: SetupActionPageArguments(newreaction) - ).then((r) { - if (newreaction != Reaction.template()) { - setState(() { - pipeline.reactions.add(newreaction); - }); - } - return r; - }); // TODO add reaction in db - } - ); + color: Theme.of(context).colorScheme.secondaryContainer, + text: AppLocalizations.of(context).addReaction, + onTap: () { + Reaction newreaction = Reaction.template(); + Navigator.of(context) + .pushNamed('/pipeline/action/new', + arguments: SetupActionPageArguments(newreaction)) + .then((r) { + if (newreaction != Reaction.template()) { + setState(() { + pipeline.reactions.add(newreaction); + }); + } + return r; + }); // TODO add reaction in db + }); final Widget deleteButton = ColoredClickableCard( color: Theme.of(context).colorScheme.error, text: AppLocalizations.of(context).deletePipeline, onTap: () => showDialog( - context: context, - builder: (BuildContext context) => WarningDialog( - message: - AppLocalizations.of(context).deletePipelineWarningMessage, - onAccept: () { - provider.removePipeline(pipeline); - print("Delete pipeline"); /*TODO call api*/ - Navigator.of(context).pop(); - }, - warnedAction: AppLocalizations.of(context).delete - ) - ), + context: context, + builder: (BuildContext context) => WarningDialog( + message: + AppLocalizations.of(context).deletePipelineWarningMessage, + onAccept: () { + provider.removePipeline(pipeline); + print("Delete pipeline"); /*TODO call api*/ + Navigator.of(context).pop(); + }, + warnedAction: AppLocalizations.of(context).delete)), ); return AerisCardPage( - body: Padding( - padding: const EdgeInsets.only(top: 10), - child: ListView( - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 40), - child: cardHeader, - ), - const Text("Action", - style: TextStyle(fontWeight: FontWeight.w500) - ), - ActionCard( - leading: pipeline.trigger.service.getLogo(logoSize: 50), - title: pipeline.trigger.name, - trailing: ActionCardPopupMenu( + body: Padding( + padding: const EdgeInsets.only(top: 10), + child: ListView(children: [ + Padding( + padding: const EdgeInsets.only(bottom: 40), + child: cardHeader, + ), + const Text("Action", style: TextStyle(fontWeight: FontWeight.w500)), + ActionCard( + leading: pipeline.trigger.service.getLogo(logoSize: 50), + title: pipeline.trigger.name, + trailing: ActionCardPopupMenu( deletable: false, action: pipeline.trigger, - then: () => setState(() {})) - ), - const SizedBox(height: 25), - const Text("Reactions", - style: TextStyle(fontWeight: FontWeight.w500) - ), - for (var reaction in pipeline.reactions) - ActionCard( - leading: reaction.service.getLogo(logoSize: 50), - title: reaction.name, - trailing: ActionCardPopupMenu( - deletable: reaction != pipeline.reactions.first, - action: reaction, - then: () => setState(() {})) - ), - addReactionbutton, - const Padding( - padding: EdgeInsets.only(top: 30, bottom: 5), - child: Text("Danger Zone", - style: TextStyle(fontWeight: FontWeight.w500) - ) - ), - deleteButton, - const SizedBox(height: 25), - ] - ), - ) - ); - } - ); + then: () => setState(() {}))), + const SizedBox(height: 25), + const Text("Reactions", + style: TextStyle(fontWeight: FontWeight.w500)), + for (var reaction in pipeline.reactions) + ActionCard( + leading: reaction.service.getLogo(logoSize: 50), + title: reaction.name, + trailing: ActionCardPopupMenu( + deletable: reaction != pipeline.reactions.first, + action: reaction, + then: () => setState(() {}), + onDelete: () { + pipeline.reactions.remove(reaction); + }, + )), + addReactionbutton, + const Padding( + padding: EdgeInsets.only(top: 30, bottom: 5), + child: Text("Danger Zone", + style: TextStyle(fontWeight: FontWeight.w500))), + deleteButton, + const SizedBox(height: 25), + ]), + )); + }); } diff --git a/mobile/lib/src/views/setup_action_page.dart b/mobile/lib/src/views/setup_action_page.dart index b4a9c5a..65d2cd4 100644 --- a/mobile/lib/src/views/setup_action_page.dart +++ b/mobile/lib/src/views/setup_action_page.dart @@ -105,7 +105,7 @@ class _SetupActionPageState extends State { name: availableAction.name, parametersNames: availableAction.parameters.keys.toList(), - initValues: availableAction.parameters, + initValues: arguments.action.parameters, onValidate: (parameters) { arguments.action.service = serviceState!; arguments.action.parameters = parameters; diff --git a/mobile/lib/src/widgets/action_card_popup_menu.dart b/mobile/lib/src/widgets/action_card_popup_menu.dart index 8971a08..cc0eafa 100644 --- a/mobile/lib/src/widgets/action_card_popup_menu.dart +++ b/mobile/lib/src/widgets/action_card_popup_menu.dart @@ -7,12 +7,17 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; /// [StatelessWidget] displayed as a PopupMenu class ActionCardPopupMenu extends StatelessWidget { - const ActionCardPopupMenu({ + ActionCardPopupMenu({ Key? key, required this.action, required this.then, required this.deletable, - }) : super(key: key); + this.onDelete, + }) : super(key: key) { + if (deletable) { + assert(onDelete != null); + } + } /// Action to trigger final aeris.Action action; @@ -23,17 +28,24 @@ class ActionCardPopupMenu extends StatelessWidget { /// Deletable characteristic final bool deletable; + final void Function()? onDelete; + @override Widget build(BuildContext context) { return AerisPopupMenu( onSelected: (value) { - Map object = value as Map; - Navigator.pushNamed(context, object['route'] as String, - arguments: object['params']) - .then((r) { - then(); - return r; - }); + if (value == '/pipeline/action/del') { + onDelete!(); + } else { + Map object = value as Map; + Navigator.pushNamed(context, object['route'] as String, + arguments: object['params']) + .then((r) { + then(); + return r; + }); + } + ; }, icon: Icons.more_vert, itemBuilder: (context) => [ From 5839c4c0a120160b992a2e047b949fa4121ec7e9 Mon Sep 17 00:00:00 2001 From: Arthi-chaud Date: Tue, 8 Feb 2022 16:33:10 +0100 Subject: [PATCH 09/10] Mobile Client: In forms, get values from previous state + delete action button --- mobile/lib/src/widgets/action_card_popup_menu.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/mobile/lib/src/widgets/action_card_popup_menu.dart b/mobile/lib/src/widgets/action_card_popup_menu.dart index cc0eafa..e3a4eed 100644 --- a/mobile/lib/src/widgets/action_card_popup_menu.dart +++ b/mobile/lib/src/widgets/action_card_popup_menu.dart @@ -36,6 +36,7 @@ class ActionCardPopupMenu extends StatelessWidget { onSelected: (value) { if (value == '/pipeline/action/del') { onDelete!(); + ///TODO delete from db } else { Map object = value as Map; Navigator.pushNamed(context, object['route'] as String, From f215bf1e8545dd14899cc1fe573d8c28017e3d01 Mon Sep 17 00:00:00 2001 From: Arthi-chaud Date: Tue, 8 Feb 2022 16:50:02 +0100 Subject: [PATCH 10/10] Mobile CLient: reset home page --- mobile/lib/src/main.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mobile/lib/src/main.dart b/mobile/lib/src/main.dart index c67c499..7a343ab 100644 --- a/mobile/lib/src/main.dart +++ b/mobile/lib/src/main.dart @@ -42,7 +42,7 @@ class Aeris extends StatelessWidget { ], supportedLocales: const [Locale('fr', ''), Locale('en', '')], theme: ThemeData(colorScheme: aerisScheme), - initialRoute: '/home', + initialRoute: '/', onGenerateRoute: (settings) { Map pageRoutes = { '/': () => const StartupPage(),