From e68110c81015e302ab2e1dd524a7828513f3e0b3 Mon Sep 17 00:00:00 2001 From: Arthi-chaud Date: Fri, 4 Mar 2022 17:28:22 +0100 Subject: [PATCH 1/3] Mobile Client: about.json: using newly formatted description + label --- mobile/lib/src/models/action.dart | 12 +- mobile/lib/src/models/action_template.dart | 3 +- mobile/lib/src/models/reaction.dart | 6 +- mobile/lib/src/models/trigger.dart | 6 +- .../providers/action_catalogue_provider.dart | 16 +- .../lib/src/views/create_pipeline_page.dart | 299 ++++++++++-------- .../lib/src/views/pipeline_detail_page.dart | 20 +- mobile/lib/src/views/setup_action_page.dart | 117 ++++--- mobile/lib/src/widgets/action_form.dart | 168 +++++----- 9 files changed, 350 insertions(+), 297 deletions(-) diff --git a/mobile/lib/src/models/action.dart b/mobile/lib/src/models/action.dart index 0b90e15..9fa1796 100644 --- a/mobile/lib/src/models/action.dart +++ b/mobile/lib/src/models/action.dart @@ -1,15 +1,16 @@ import 'package:aeris/src/models/action_parameter.dart'; import 'package:flutter/widgets.dart'; import 'package:aeris/src/models/service.dart'; -import 'package:recase/recase.dart'; ///Base class for reactions and trigger abstract class Action { ///Action's service Service service; - ///Name fo the action + ///Identifier of the action type String name; + ///Name odf the action + String displayName; ///Action's parameters List parameters; @@ -21,6 +22,7 @@ abstract class Action { {Key? key, required this.service, required this.name, + required this.displayName, this.description, this.parameters = const []}); @@ -29,10 +31,4 @@ abstract class Action { var service = snake.removeAt(0); return Service.factory(service); } - - String displayName() { - var words = name.split('_'); - words.removeAt(0); - return ReCase(words.join()).titleCase; - } } diff --git a/mobile/lib/src/models/action_template.dart b/mobile/lib/src/models/action_template.dart index 53ce020..f8f00cd 100644 --- a/mobile/lib/src/models/action_template.dart +++ b/mobile/lib/src/models/action_template.dart @@ -13,8 +13,9 @@ class ActionTemplate extends Action { {Key? key, required Service service, required String name, + required String displayName, required String description, this.returnedValues = const [], List parameters = const []}) - : super(service: service, name: name, parameters: parameters, description: description); + : super(service: service, name: name, parameters: parameters, description: description, displayName: displayName); } diff --git a/mobile/lib/src/models/reaction.dart b/mobile/lib/src/models/reaction.dart index 5351609..e81903f 100644 --- a/mobile/lib/src/models/reaction.dart +++ b/mobile/lib/src/models/reaction.dart @@ -11,17 +11,19 @@ class Reaction extends aeris_action.Action { {Key? key, required Service service, required String name, + required String displayName, List parameters = const []}) - : super(service: service, name: name, parameters: parameters); + : super(service: service, name: name, parameters: parameters, displayName: displayName); /// Template trigger, used as an 'empty' trigger Reaction.template() - : super(service: Service.all()[0], name: '', parameters: []); + : super(service: Service.all()[0], name: '', parameters: [],displayName: ''); static Reaction fromJSON(Object reaction) { var reactionJSON = reaction as Map; var service = aeris_action.Action.parseServiceInName(reactionJSON['rType'] as String); return Reaction( + displayName: reactionJSON['label']['en'], ///TODO use locale service: service, name: reactionJSON['rType'] as String, parameters: ActionParameter.fromJSON((reactionJSON['rParams'] as Map))); diff --git a/mobile/lib/src/models/trigger.dart b/mobile/lib/src/models/trigger.dart index 5c2ef16..eb60787 100644 --- a/mobile/lib/src/models/trigger.dart +++ b/mobile/lib/src/models/trigger.dart @@ -15,9 +15,10 @@ class Trigger extends aeris_action.Action { {Key? key, required Service service, required String name, + required String displayName, List parameters = const [], this.last}) - : super(service: service, name: name, parameters: parameters); + : super(service: service, name: name, parameters: parameters, displayName: displayName); /// Unserialize static Trigger fromJSON(Object action) { @@ -30,6 +31,7 @@ class Trigger extends aeris_action.Action { : DateTime.parse(lastTriggerField as String); return Trigger( + displayName: triggerJSON['label']['en'], ///TODO use locale service: service, name: triggerJSON['pType'] as String, last: last, @@ -49,7 +51,7 @@ class Trigger extends aeris_action.Action { /// Template trigger, used as an 'empty' trigger Trigger.template({Key? key, this.last}) - : super(service: Service.all()[0], name: '', parameters: []); + : super(service: Service.all()[0], name: '', parameters: [], displayName: ''); @override // ignore: avoid_renaming_method_parameters diff --git a/mobile/lib/src/providers/action_catalogue_provider.dart b/mobile/lib/src/providers/action_catalogue_provider.dart index 5290d6d..1936ba7 100644 --- a/mobile/lib/src/providers/action_catalogue_provider.dart +++ b/mobile/lib/src/providers/action_catalogue_provider.dart @@ -33,31 +33,35 @@ class ActionCatalogueProvider extends ChangeNotifier { for (var serviceContent in services) { Service service = Service.factory(serviceContent['name']); for (var action in (serviceContent['actions'] as List)) { + print(action); _triggerTemplates[service]!.add( ActionTemplate( name: action['name'], + displayName: action['label']['en'], ///TODO use locale service: service, - description: action['description'], + description: action['description']['en'], ///TODO use locale parameters: (action['params'] as List).map( - (e) => ActionParameter(name: e['name'], description: e['description']) + (e) => ActionParameter(name: e['name'], description: e['description']['en'])///TODO use locale ).toList(), returnedValues: (action['returns'] as List).map( - (e) => ActionParameter(name: e['name'], description: e['description']) + (e) => ActionParameter(name: e['name'], description: e['description']['en']) ///TODO use locale ).toList(), ) ); } for (var reaction in serviceContent['reactions']) { + print(reaction); _reactionTemplates[service]!.add( ActionTemplate( + displayName: reaction['label']['en'], ///TODO use locale name: reaction['name'], service: service, - description: reaction['description'], + description: reaction['description']['en'], ///TODO use locale parameters: (reaction['params'] as List).map( - (e) => ActionParameter(name: e['name'], description: e['description']) + (e) => ActionParameter(name: e['name'], description: e['description']['en']) ///TODO use locale ).toList(), returnedValues: (reaction['returns'] as List).map( - (e) => ActionParameter(name: e['name'], description: e['description']) + (e) => ActionParameter(name: e['name'], description: e['description']['en']) ///TODO use locale ).toList(), ) ); diff --git a/mobile/lib/src/views/create_pipeline_page.dart b/mobile/lib/src/views/create_pipeline_page.dart index a0bae4c..812c811 100644 --- a/mobile/lib/src/views/create_pipeline_page.dart +++ b/mobile/lib/src/views/create_pipeline_page.dart @@ -38,149 +38,170 @@ class _CreatePipelinePageState extends State { final _formKey = GlobalKey(); return Consumer( builder: (context, provider, _) => AerisCardPage( - body: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(AppLocalizations.of(context).createNewPipeline, - style: const TextStyle( - fontSize: 25, - )), - FormBuilder( - key: _formKey, - child: Padding( - padding: const EdgeInsets.all(20), - child: Column(crossAxisAlignment: CrossAxisAlignment.start, 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; - }, - ), - const SizedBox(height: 10), - trigger != Trigger.template() - ? Text(AppLocalizations.of(context).action, - style: const TextStyle(fontWeight: FontWeight.w500)) - : Container(), - Padding( - padding: const EdgeInsets.all(8.0), - child: trigger == Trigger.template() - ? ColoredClickableCard( - color: Theme.of(context) - .colorScheme - .secondaryContainer, - text: AppLocalizations.of(context).addTrigger, - onTap: () { - showAerisCardPage( + body: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(AppLocalizations.of(context).createNewPipeline, + style: const TextStyle( + fontSize: 25, + )), + FormBuilder( + key: _formKey, + child: Padding( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + 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; + }, + ), + const SizedBox(height: 10), + trigger != Trigger.template() + ? Text(AppLocalizations.of(context).action, + style: const TextStyle( + fontWeight: FontWeight.w500)) + : Container(), + Padding( + padding: const EdgeInsets.all(8.0), + child: trigger == Trigger.template() + ? ColoredClickableCard( + color: Theme.of(context) + .colorScheme + .secondaryContainer, + text: AppLocalizations.of(context) + .addTrigger, + onTap: () { + showAerisCardPage( + context, + (_) => SetupActionPage( + action: trigger, + parentReactions: + reactions)) + .then((_) => setState(() {})); + }) + : ActionCard( + leading: trigger.service + .getLogo(logoSize: 50), + title: trigger.displayName, + trailing: ActionCardPopupMenu( + deletable: false, + parentReactions: reactions, + parentTrigger: trigger, + action: trigger, + then: () => setState(() {})), + ), + ), + reactions.isNotEmpty + ? Text(AppLocalizations.of(context).reactions, + style: const TextStyle( + fontWeight: FontWeight.w500)) + : Container(), + Padding( + padding: + const EdgeInsets.only(left: 8, right: 8), + child: ReorderableReactionCardsList( + reactionList: reactions, + onReorder: () {}, + itemBuilder: (reaction) => ActionCard( + key: ValueKey( + reactions.indexOf(reaction)), + leading: reaction.service + .getLogo(logoSize: 50), + title: reaction.displayName, + trailing: ActionCardPopupMenu( + parentTrigger: + trigger == Trigger.template() + ? null + : trigger, + parentReactions: reactions, + deletable: reactions.length > 1, + action: reaction, + then: () => setState(() {}), + onDelete: () { + setState(() { + reactions.remove(reaction); + }); + })), + )), + Padding( + padding: const EdgeInsets.all(8.0), + child: ColoredClickableCard( + color: Theme.of(context) + .colorScheme + .secondaryContainer, + text: AppLocalizations.of(context) + .addReaction, + onTap: () async { + var newreact = Reaction.template(); + showAerisCardPage( context, (_) => SetupActionPage( - action: trigger, - parentReactions: reactions - )) - .then((_) => setState(() {})); - }) - : ActionCard( - leading: trigger.service.getLogo(logoSize: 50), - title: trigger.displayName(), - trailing: ActionCardPopupMenu( - deletable: false, - parentReactions: reactions, - parentTrigger: trigger, - action: trigger, - then: () => setState(() {})), + action: newreact, + parentReactions: reactions, + parentTrigger: trigger == + Trigger.template() + ? null + : trigger, + )).then((_) => setState(() { + if (newreact != + Reaction.template()) { + reactions.add(newreact); + } + })); + }), ), - ), - reactions.isNotEmpty - ? Text(AppLocalizations.of(context).reactions, - style: const TextStyle(fontWeight: FontWeight.w500)) - : Container(), - Padding( - padding: const EdgeInsets.only(left: 8, right: 8), - child: ReorderableReactionCardsList( - reactionList: reactions, - onReorder: () { }, - itemBuilder: (reaction) => ActionCard( - key: ValueKey(reactions.indexOf(reaction)), - leading: reaction.service.getLogo(logoSize: 50), - title: reaction.displayName(), - trailing: ActionCardPopupMenu( - parentTrigger: trigger == Trigger.template() ? null : trigger, - parentReactions: reactions, - deletable: reactions.length > 1, - action: reaction, - then: () => setState(() {}), - onDelete: () { - setState(() { - reactions.remove(reaction); - }); - })), - ) - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: ColoredClickableCard( - color: Theme.of(context) - .colorScheme - .secondaryContainer, - text: AppLocalizations.of(context).addReaction, - onTap: () async { - var newreact = Reaction.template(); - showAerisCardPage( - context, - (_) => SetupActionPage( - action: newreact, - parentReactions: reactions, - parentTrigger: trigger == Trigger.template() ? null : trigger, - )) - .then((_) => setState(() { - if (newreact != Reaction.template()) { - reactions.add(newreact); + Center( + child: ElevatedButton( + child: Text(AppLocalizations.of(context).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, + trigger: trigger, + reactions: reactions); + provider.addPipeline(newPipeline); + Navigator.of(context).pop(); + showAerisCardPage( + context, + (_) => PipelineDetailPage( + pipeline: newPipeline)); } - })); - }), - ), - Center(child: ElevatedButton( - child: Text(AppLocalizations.of(context).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, - trigger: trigger, - reactions: reactions); - provider.addPipeline(newPipeline); - Navigator.of(context).pop(); - showAerisCardPage( - context, - (_) => PipelineDetailPage(pipeline: newPipeline) - ); - } - } - }, + } + }, + )), + ]), )), - ]), - )), - ]))); + ]))); } } diff --git a/mobile/lib/src/views/pipeline_detail_page.dart b/mobile/lib/src/views/pipeline_detail_page.dart index 4c5aeca..b98f833 100644 --- a/mobile/lib/src/views/pipeline_detail_page.dart +++ b/mobile/lib/src/views/pipeline_detail_page.dart @@ -95,13 +95,12 @@ class _PipelineDetailPageState extends State { onTap: () { Reaction newreaction = Reaction.template(); showAerisCardPage( - context, (_) => SetupActionPage( + context, + (_) => SetupActionPage( action: newreaction, parentTrigger: pipeline.trigger, parentReactions: pipeline.reactions, - ) - ) - .then((r) { + )).then((r) { if (newreaction != Reaction.template()) { setState(() { pipeline.reactions.add(newreaction); @@ -140,7 +139,7 @@ class _PipelineDetailPageState extends State { style: const TextStyle(fontWeight: FontWeight.w500)), ActionCard( leading: pipeline.trigger.service.getLogo(logoSize: 50), - title: pipeline.trigger.displayName(), + title: pipeline.trigger.displayName, trailing: ActionCardPopupMenu( deletable: false, parentTrigger: pipeline.trigger, @@ -154,12 +153,12 @@ class _PipelineDetailPageState extends State { Text(AppLocalizations.of(context).reactions, style: const TextStyle(fontWeight: FontWeight.w500)), ReorderableReactionCardsList( - onReorder: () => GetIt.I().editPipeline(pipeline), - reactionList: pipeline.reactions, - itemBuilder: (reaction) => ActionCard( + onReorder: () => GetIt.I().editPipeline(pipeline), + reactionList: pipeline.reactions, + itemBuilder: (reaction) => ActionCard( key: ValueKey(pipeline.reactions.indexOf(reaction)), leading: reaction.service.getLogo(logoSize: 50), - title: reaction.displayName(), + title: reaction.displayName, trailing: ActionCardPopupMenu( parentTrigger: pipeline.trigger, parentReactions: pipeline.reactions, @@ -174,8 +173,7 @@ class _PipelineDetailPageState extends State { setState(() {}); GetIt.I().editPipeline(pipeline); }), - ) - ), + )), addReactionbutton, Padding( padding: const EdgeInsets.only(top: 30, bottom: 5), diff --git a/mobile/lib/src/views/setup_action_page.dart b/mobile/lib/src/views/setup_action_page.dart index 49f006d..1223520 100644 --- a/mobile/lib/src/views/setup_action_page.dart +++ b/mobile/lib/src/views/setup_action_page.dart @@ -15,10 +15,16 @@ import 'package:skeleton_loader/skeleton_loader.dart'; ///Page to setup an action class SetupActionPage extends StatefulWidget { - const SetupActionPage({Key? key, required this.action, required this.parentReactions, this.parentTrigger}) : super(key: key); + const SetupActionPage( + {Key? key, + required this.action, + required this.parentReactions, + this.parentTrigger}) + : super(key: key); /// Action to setup final aeris.Action action; + /// Trigger of Parent of the action to setup final Trigger? parentTrigger; @@ -37,12 +43,12 @@ class _SetupActionPageState extends State { void initState() { super.initState(); serviceState = widget.action.service; - availableActions = GetIt.I().getActionsFor(serviceState!, widget.action); + availableActions = + GetIt.I().getActionsFor(serviceState!, widget.action); } @override Widget build(BuildContext context) { - final Widget serviceDropdown = DropdownButton( value: serviceState, elevation: 8, @@ -50,7 +56,8 @@ class _SetupActionPageState extends State { onChanged: (service) { setState(() { serviceState = service; - availableActions = GetIt.I().getActionsFor(service!, widget.action); + availableActions = + GetIt.I().getActionsFor(service!, widget.action); }); }, items: Service.all().map>((Service service) { @@ -77,9 +84,10 @@ class _SetupActionPageState extends State { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(widget.action is Trigger - ? AppLocalizations.of(context).setupTrigger - : AppLocalizations.of(context).setupReaction, + Text( + widget.action is Trigger + ? AppLocalizations.of(context).setupTrigger + : AppLocalizations.of(context).setupReaction, style: const TextStyle( fontSize: 25, )), @@ -108,49 +116,60 @@ class _SetupActionPageState extends State { const SizedBox(height: 20), if (availableActions == null) SkeletonLoader( - builder: Card(shape: cardShape, child: const SizedBox(height: 40), elevation: 5), + builder: Card( + shape: cardShape, + child: const SizedBox(height: 40), + elevation: 5), items: 15, - highlightColor: Theme.of(context).colorScheme.secondary - ) - else - ...[for (ActionTemplate availableAction in availableActions!) - Card( - elevation: 5, - shape: cardShape, - child: ExpandableNotifier( - child: ScrollOnExpand(child: ExpandablePanel( - header: Padding( - padding: - const EdgeInsets.only(left: 30, top: 20, bottom: 20), - child: Text(availableAction.displayName(), - style: const TextStyle(fontSize: 15))), - collapsed: Container(), - expanded: Padding( - padding: const EdgeInsets.all(20), - child: ActionForm( - reactionsCandidates: widget.parentReactions, - triggerCandidate: widget.parentTrigger, - candidate: widget.action, - key: Key("${availableAction.name}${availableAction.description}${availableAction.service}"), - description: availableAction.description!, - name: availableAction.name, - parameters: availableAction.parameters.map((param) { - if (widget.action.service.name == serviceState!.name && widget.action.name == availableAction.name) { - var previousParams = widget.action.parameters.where((element) => element.name == param.name); - if (previousParams.isNotEmpty) { - param.value = previousParams.first.value; - } - } - return param; - }).toList(), - onValidate: (parameters) { - widget.action.service = serviceState!; - widget.action.parameters = ActionParameter.fromJSON(parameters); - widget.action.name = availableAction.name; - Navigator.of(context).pop(); - }), - )), - ))), + highlightColor: Theme.of(context).colorScheme.secondary) + else ...[ + for (ActionTemplate availableAction in availableActions!) + Card( + elevation: 5, + shape: cardShape, + child: ExpandableNotifier( + child: ScrollOnExpand( + child: ExpandablePanel( + header: Padding( + padding: const EdgeInsets.only( + left: 30, top: 20, bottom: 20), + child: Text(availableAction.displayName, + style: const TextStyle(fontSize: 15))), + collapsed: Container(), + expanded: Padding( + padding: const EdgeInsets.all(20), + child: ActionForm( + reactionsCandidates: widget.parentReactions, + triggerCandidate: widget.parentTrigger, + candidate: widget.action, + key: Key( + "${availableAction.name}${availableAction.description}${availableAction.service}"), + description: availableAction.description!, + name: availableAction.name, + parameters: + availableAction.parameters.map((param) { + if (widget.action.service.name == + serviceState!.name && + widget.action.name == + availableAction.name) { + var previousParams = widget.action.parameters + .where((element) => + element.name == param.name); + if (previousParams.isNotEmpty) { + param.value = previousParams.first.value; + } + } + return param; + }).toList(), + onValidate: (parameters) { + widget.action.service = serviceState!; + widget.action.parameters = + ActionParameter.fromJSON(parameters); + widget.action.name = availableAction.name; + Navigator.of(context).pop(); + }), + )), + ))), const SizedBox(height: 10) ] ], diff --git a/mobile/lib/src/widgets/action_form.dart b/mobile/lib/src/widgets/action_form.dart index 5e7b308..8ecbc0e 100644 --- a/mobile/lib/src/widgets/action_form.dart +++ b/mobile/lib/src/widgets/action_form.dart @@ -13,10 +13,11 @@ import 'package:tuple/tuple.dart'; import 'package:flutter_typeahead/flutter_typeahead.dart'; class Suggestion extends Tuple3 { - Suggestion(int item1, ActionParameter item2, ActionTemplate item3) : super(item1, item2, item3); + Suggestion(int item1, ActionParameter item2, ActionTemplate item3) + : super(item1, item2, item3); // Overriding show method - + @override String toString() { return "${item2.name}@$item1"; @@ -27,32 +28,35 @@ class Suggestion extends Tuple3 { class ActionForm extends StatefulWidget { /// Name of the action final String name; + /// List of parameters, 'values' are used as default values final List parameters; + /// What the action does final String description; /// The Action that will be eventually filled by the form final aeris.Action candidate; + /// The trigger candidate in the parent form page final Trigger? triggerCandidate; + /// The trigger candidate in the parent form page final List reactionsCandidates; /// On validate callback final void Function(Map) onValidate; - const ActionForm( - {Key? key, - required this.name, - required this.description, - required this.parameters, - required this.onValidate, - required this.candidate, - this.triggerCandidate, - required this.reactionsCandidates, - }) - : super(key: key); + const ActionForm({ + Key? key, + required this.name, + required this.description, + required this.parameters, + required this.onValidate, + required this.candidate, + this.triggerCandidate, + required this.reactionsCandidates, + }) : super(key: key); @override State createState() => _ActionFormState(); @@ -61,26 +65,27 @@ class ActionForm extends StatefulWidget { class _ActionFormState extends State { final _formKey = GlobalKey(); - List getSuggestions(String pattern, ActionCatalogueProvider catalogue) { + List getSuggestions( + String pattern, ActionCatalogueProvider catalogue) { List suggestions = []; if (pattern.endsWith("{") == false) return suggestions; if (widget.candidate is Trigger) return suggestions; if (widget.triggerCandidate != null) { Trigger trigger = widget.triggerCandidate!; - var triggerTemplate = catalogue.triggerTemplates[trigger.service]!.firstWhere( - (element) => element.name == trigger.name - ); + var triggerTemplate = catalogue.triggerTemplates[trigger.service]! + .firstWhere((element) => element.name == trigger.name); for (var parameter in triggerTemplate.returnedValues) { suggestions.add(Suggestion(0, parameter, triggerTemplate)); } } int index = 1; - int indexOfCandidate = widget.reactionsCandidates.indexOf(widget.candidate as Reaction); + int indexOfCandidate = + widget.reactionsCandidates.indexOf(widget.candidate as Reaction); for (var reactionCandidate in widget.reactionsCandidates) { if (index == indexOfCandidate + 1) break; - var reactionTemplate = catalogue.reactionTemplates[reactionCandidate.service]!.firstWhere( - (element) => element.name == reactionCandidate.name - ); + var reactionTemplate = catalogue + .reactionTemplates[reactionCandidate.service]! + .firstWhere((element) => element.name == reactionCandidate.name); for (var parameter in reactionTemplate.returnedValues) { suggestions.add(Suggestion(index, parameter, reactionTemplate)); } @@ -94,63 +99,68 @@ class _ActionFormState extends State { @override Widget build(BuildContext context) { return Consumer( - builder: (__, catalogue, _) => Form( - key: _formKey, - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Text(widget.description, textAlign: TextAlign.left, style: TextStyle(color: Theme.of(context).colorScheme.onSurface)), - ...widget.parameters.map((param) { - final textEditingController = TextEditingController(text: values[param.name] ?? param.value?.toString()); - return TypeAheadFormField( - key: Key(param.description), - textFieldConfiguration: TextFieldConfiguration( - autofocus: true, - controller: textEditingController, - enableSuggestions: widget.candidate is Reaction, - decoration: InputDecoration( - labelText: ReCase(param.name).titleCase, - helperText: param.description - ), - ), - onSaved: (value) { - values[param.name] = value!; - }, - suggestionsBoxDecoration: const SuggestionsBoxDecoration( - elevation: 6, - borderRadius: BorderRadius.all(Radius.circular(10)) - ), - validator: FormBuilderValidators.compose([ - FormBuilderValidators.required(context), - ]), - hideOnEmpty: true, - suggestionsCallback: (suggestion) => getSuggestions(suggestion, catalogue), - onSuggestionSelected: (suggestion) { - textEditingController.text += suggestion.toString(); - textEditingController.text += "}"; - values[param.name] = textEditingController.text; - }, - itemBuilder: (context, suggestion) => ListTile( - isThreeLine: true, - dense: true, - leading: suggestion.item3.service.getLogo(logoSize: 30), - title: Text(suggestion.item2.name), - subtitle: Text("${suggestion.item2.description}, from '${suggestion.item3.displayName()}'") - ));}), - ...[ - ElevatedButton( - child: Text(AppLocalizations.of(context).save), - onPressed: () { - if (_formKey.currentState!.validate()) { - _formKey.currentState!.save(); - widget.onValidate(values); - } - }, - ), - const SizedBox(height: 10) - ] - ] - ) - )); + builder: (__, catalogue, _) => Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Text(widget.description, + textAlign: TextAlign.left, + style: TextStyle( + color: Theme.of(context).colorScheme.onSurface)), + ...widget.parameters.map((param) { + final textEditingController = TextEditingController( + text: values[param.name] ?? param.value?.toString()); + return TypeAheadFormField( + key: Key(param.description), + textFieldConfiguration: TextFieldConfiguration( + autofocus: true, + controller: textEditingController, + enableSuggestions: widget.candidate is Reaction, + decoration: InputDecoration( + labelText: ReCase(param.name).titleCase, + helperText: param.description), + ), + onSaved: (value) { + values[param.name] = value!; + }, + suggestionsBoxDecoration: + const SuggestionsBoxDecoration( + elevation: 6, + borderRadius: + BorderRadius.all(Radius.circular(10))), + validator: FormBuilderValidators.compose([ + FormBuilderValidators.required(context), + ]), + hideOnEmpty: true, + suggestionsCallback: (suggestion) => + getSuggestions(suggestion, catalogue), + onSuggestionSelected: (suggestion) { + textEditingController.text += suggestion.toString(); + textEditingController.text += "}"; + values[param.name] = textEditingController.text; + }, + itemBuilder: (context, suggestion) => ListTile( + isThreeLine: true, + dense: true, + leading: + suggestion.item3.service.getLogo(logoSize: 30), + title: Text(suggestion.item2.name), + subtitle: Text( + "${suggestion.item2.description}, from '${suggestion.item3.displayName}'"))); + }), + ...[ + ElevatedButton( + child: Text(AppLocalizations.of(context).save), + onPressed: () { + if (_formKey.currentState!.validate()) { + _formKey.currentState!.save(); + widget.onValidate(values); + } + }, + ), + const SizedBox(height: 10) + ] + ]))); } } From 5e219592360d0847a389627b3d68c7c3972a1cc4 Mon Sep 17 00:00:00 2001 From: Arthi-chaud Date: Fri, 4 Mar 2022 17:28:47 +0100 Subject: [PATCH 2/3] Mobile Client: On pipeline fetch, using about.json to fecth display name/description back --- mobile/lib/src/models/reaction.dart | 15 ++++++++++++--- mobile/lib/src/models/trigger.dart | 12 ++++++++++-- mobile/lib/src/views/setup_action_page.dart | 1 + 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/mobile/lib/src/models/reaction.dart b/mobile/lib/src/models/reaction.dart index e81903f..0399780 100644 --- a/mobile/lib/src/models/reaction.dart +++ b/mobile/lib/src/models/reaction.dart @@ -1,9 +1,13 @@ // ignore_for_file: hash_and_equals +import 'package:aeris/main.dart'; import 'package:aeris/src/models/action.dart' as aeris_action; import 'package:aeris/src/models/action_parameter.dart'; +import 'package:aeris/src/providers/action_catalogue_provider.dart'; import 'package:flutter/widgets.dart'; import 'package:aeris/src/models/service.dart'; +import 'package:get_it/get_it.dart'; +import 'package:provider/provider.dart'; ///Object representation of a reaction class Reaction extends aeris_action.Action { @@ -21,11 +25,16 @@ class Reaction extends aeris_action.Action { static Reaction fromJSON(Object reaction) { var reactionJSON = reaction as Map; - var service = aeris_action.Action.parseServiceInName(reactionJSON['rType'] as String); + String rType = reactionJSON['rType'] as String; + var service = aeris_action.Action.parseServiceInName(rType); return Reaction( - displayName: reactionJSON['label']['en'], ///TODO use locale + displayName: reactionJSON['label']?['en'] + ?? Provider.of(Aeris.materialKey.currentContext!, listen: false) + .reactionTemplates[service]!.firstWhere((template) { + return template.name == rType; + }).displayName, ///TODO use locale service: service, - name: reactionJSON['rType'] as String, + name: rType, parameters: ActionParameter.fromJSON((reactionJSON['rParams'] as Map))); } diff --git a/mobile/lib/src/models/trigger.dart b/mobile/lib/src/models/trigger.dart index eb60787..68fde99 100644 --- a/mobile/lib/src/models/trigger.dart +++ b/mobile/lib/src/models/trigger.dart @@ -1,11 +1,14 @@ // ignore_for_file: hash_and_equals import 'package:aeris/src/models/action_parameter.dart'; +import 'package:aeris/src/providers/action_catalogue_provider.dart'; import 'package:flutter/material.dart'; import 'package:aeris/main.dart'; import 'package:aeris/src/models/service.dart'; import 'package:aeris/src/models/action.dart' as aeris_action; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:get_it/get_it.dart'; +import 'package:provider/provider.dart'; ///Object representation of a pipeline trigger class Trigger extends aeris_action.Action { @@ -29,11 +32,16 @@ class Trigger extends aeris_action.Action { DateTime? last = lastTriggerField == null ? null : DateTime.parse(lastTriggerField as String); + String pType = triggerJSON['pType'] as String; return Trigger( - displayName: triggerJSON['label']['en'], ///TODO use locale + displayName: triggerJSON['label']?['en'] + ?? Provider.of(Aeris.materialKey.currentContext!, listen: false) + .triggerTemplates[service]!.firstWhere((template) { + return template.name == pType; + }).displayName, ///TODO use locale service: service, - name: triggerJSON['pType'] as String, + name: pType, last: last, parameters: ActionParameter.fromJSON((triggerJSON['pParams'] as Map)) ); diff --git a/mobile/lib/src/views/setup_action_page.dart b/mobile/lib/src/views/setup_action_page.dart index 1223520..c76b5a4 100644 --- a/mobile/lib/src/views/setup_action_page.dart +++ b/mobile/lib/src/views/setup_action_page.dart @@ -166,6 +166,7 @@ class _SetupActionPageState extends State { widget.action.parameters = ActionParameter.fromJSON(parameters); widget.action.name = availableAction.name; + widget.action.displayName = availableAction.displayName; Navigator.of(context).pop(); }), )), From d45ce5601da8a85498aa598695b53b0c6f00e7ca Mon Sep 17 00:00:00 2001 From: Arthi-chaud Date: Fri, 4 Mar 2022 17:30:47 +0100 Subject: [PATCH 3/3] Mobile Client: remove print + unused imports --- mobile/lib/src/models/reaction.dart | 1 - mobile/lib/src/models/trigger.dart | 1 - mobile/lib/src/providers/action_catalogue_provider.dart | 2 -- 3 files changed, 4 deletions(-) diff --git a/mobile/lib/src/models/reaction.dart b/mobile/lib/src/models/reaction.dart index 0399780..6f846ca 100644 --- a/mobile/lib/src/models/reaction.dart +++ b/mobile/lib/src/models/reaction.dart @@ -6,7 +6,6 @@ import 'package:aeris/src/models/action_parameter.dart'; import 'package:aeris/src/providers/action_catalogue_provider.dart'; import 'package:flutter/widgets.dart'; import 'package:aeris/src/models/service.dart'; -import 'package:get_it/get_it.dart'; import 'package:provider/provider.dart'; ///Object representation of a reaction diff --git a/mobile/lib/src/models/trigger.dart b/mobile/lib/src/models/trigger.dart index 68fde99..32f8419 100644 --- a/mobile/lib/src/models/trigger.dart +++ b/mobile/lib/src/models/trigger.dart @@ -7,7 +7,6 @@ import 'package:aeris/main.dart'; import 'package:aeris/src/models/service.dart'; import 'package:aeris/src/models/action.dart' as aeris_action; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; -import 'package:get_it/get_it.dart'; import 'package:provider/provider.dart'; ///Object representation of a pipeline trigger diff --git a/mobile/lib/src/providers/action_catalogue_provider.dart b/mobile/lib/src/providers/action_catalogue_provider.dart index 1936ba7..3404ce0 100644 --- a/mobile/lib/src/providers/action_catalogue_provider.dart +++ b/mobile/lib/src/providers/action_catalogue_provider.dart @@ -33,7 +33,6 @@ class ActionCatalogueProvider extends ChangeNotifier { for (var serviceContent in services) { Service service = Service.factory(serviceContent['name']); for (var action in (serviceContent['actions'] as List)) { - print(action); _triggerTemplates[service]!.add( ActionTemplate( name: action['name'], @@ -50,7 +49,6 @@ class ActionCatalogueProvider extends ChangeNotifier { ); } for (var reaction in serviceContent['reactions']) { - print(reaction); _reactionTemplates[service]!.add( ActionTemplate( displayName: reaction['label']['en'], ///TODO use locale