Skip to content

Commit

Permalink
feat(workflow): handle the creation of workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
sambrus authored and mathieu-brl committed Dec 10, 2024
1 parent 18a059a commit 459bf8f
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 25 deletions.
5 changes: 4 additions & 1 deletion client_mobile/lib/data/action.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ class WorkflowActionReaction {
final String description;
final List<Parameter> parameters;
String? serviceName;
int? serviceId;

WorkflowActionReaction({
required this.id,
required this.name,
required this.description,
required this.parameters,
this.serviceName,
this.serviceId
});

factory WorkflowActionReaction.fromJson(Map<String, dynamic> json) {
Expand All @@ -28,10 +30,11 @@ class WorkflowActionReaction {
);
}

Map<String, dynamic> toJson() {
Map<String, dynamic> toJson(String type) {
return {
'id': id,
'name': name,
'type': type,
'description': description,
'parameters': parameters.map((p) => p.toJson()).toList(),
};
Expand Down
2 changes: 1 addition & 1 deletion client_mobile/lib/data/parameter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class Parameter {
Map<String, dynamic> toJson() {
return {
'name': name,
'description': description,
'type': type,
'value': value
};
}
}
4 changes: 2 additions & 2 deletions client_mobile/lib/data/service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ class WorkflowService {
return {
'id': id,
'name': name,
'actions': actions.map((a) => a.toJson()).toList(),
'reactions': reactions.map((r) => r.toJson()).toList(),
'actions': actions.map((a) => a.toJson("action")).toList(),
'reactions': reactions.map((r) => r.toJson("reaction")).toList(),
};
}
}
38 changes: 38 additions & 0 deletions client_mobile/lib/data/workflow.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import 'package:client_mobile/data/action.dart';
import 'package:flutter/gestures.dart';

class WorkflowEvent
{
final WorkflowActionReaction action;
final String type;

WorkflowEvent({
required this.action,
required this.type
});
}


class Workflow {
final String name;
final String description;
final List<int> servicesId;
final List<WorkflowEvent> events;

Workflow({
required this.name,
required this.description,
required this.servicesId,
required this.events,
});


Map<String, dynamic> toJson() {
return {
'name': name,
'description': description,
'services': servicesId,
'events': events.map((a) => a.action.toJson(a.type)).toList(),
};
}
}
9 changes: 5 additions & 4 deletions client_mobile/lib/pages/dashboard/action_selection_page.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import 'package:client_mobile/data/action.dart';
import 'package:client_mobile/data/parameter.dart';
import 'package:client_mobile/data/service.dart';
import 'package:flutter/material.dart';

class ActionSelectionPage extends StatelessWidget {
final String serviceName;
final Function(WorkflowActionReaction, String) onActionSelected;
final WorkflowService service;
final Function(WorkflowActionReaction, WorkflowService) onActionSelected;
final List<WorkflowActionReaction> actions;

const ActionSelectionPage(
{super.key,
required this.serviceName,
required this.service,
required this.onActionSelected,
required this.actions});

Expand All @@ -30,7 +31,7 @@ class ActionSelectionPage extends StatelessWidget {
await _showParameterDialog(context, param);
param.value = updatedValue;
}
onActionSelected(actions[index], serviceName);
onActionSelected(actions[index], service);
Navigator.popUntil(context, (route) => route.isFirst);
},
);
Expand Down
2 changes: 0 additions & 2 deletions client_mobile/lib/pages/dashboard/service_connection.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import 'dart:io';

import 'package:client_mobile/services/microsoft/microsoft_auth_service.dart';
import 'package:client_mobile/widgets/sign_in_button.dart';
import 'package:flutter/material.dart';
Expand Down
4 changes: 2 additions & 2 deletions client_mobile/lib/pages/dashboard/service_selection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'package:flutter/material.dart';

// Page principale avec FutureBuilder
class ServiceSelectionPage extends StatelessWidget {
final Function(WorkflowActionReaction, String) onActionSelected;
final Function(WorkflowActionReaction, WorkflowService) onActionSelected;
final bool isAction;

const ServiceSelectionPage({
Expand Down Expand Up @@ -58,7 +58,7 @@ class ServiceSelectionPage extends StatelessWidget {
context,
MaterialPageRoute(
builder: (context) => ActionSelectionPage(
serviceName: services[index].name,
service: services[index],
onActionSelected: onActionSelected,
actions: isAction
? services[index].actions
Expand Down
120 changes: 109 additions & 11 deletions client_mobile/lib/pages/dashboard/workflow.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import 'package:client_mobile/data/action.dart';
import 'package:client_mobile/data/service.dart';
import 'package:client_mobile/data/workflow.dart';
import 'package:client_mobile/services/login/auth_service.dart';
import 'package:client_mobile/services/workflow/workflow_service.dart';
import 'package:client_mobile/widgets/action_button.dart';
import 'package:client_mobile/widgets/reaction_button.dart';
import 'package:flutter/material.dart';
Expand All @@ -16,20 +19,74 @@ class _WorkflowPageState extends State<WorkflowPage> {
WorkflowActionReaction? action;
WorkflowActionReaction? reaction;

void onActionSelected(WorkflowActionReaction selected, String serviceName) {
void onActionSelected(
WorkflowActionReaction selected, WorkflowService service) {
setState(() {
action = selected;
action!.serviceName = serviceName;
action!.serviceName = service.name;
action!.serviceId = service.id;
});
}

void onReactionSelected(WorkflowActionReaction selected, String serviceName) {
void onReactionSelected(
WorkflowActionReaction selected, WorkflowService service) {
setState(() {
reaction = selected;
reaction!.serviceName = serviceName;
reaction!.serviceName = service.name;
reaction!.serviceId = service.id;
});
}

Future<Map<String, String>?> _showWorkflowDetailsDialog(
BuildContext context) async {
final TextEditingController nameController = TextEditingController();
final TextEditingController descriptionController = TextEditingController();

return showDialog<Map<String, String>>(
context: context,
builder: (context) {
return AlertDialog(
title: const Text("Workflow Details"),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
controller: nameController,
decoration: const InputDecoration(
labelText: "Name",
),
),
const SizedBox(height: 20),
TextField(
controller: descriptionController,
decoration: const InputDecoration(
labelText: "Description",
),
),
],
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop(null);
},
child: const Text("Cancel"),
),
ElevatedButton(
onPressed: () {
Navigator.of(context).pop({
"name": nameController.text,
"description": descriptionController.text,
}); // Retourne les données
},
child: const Text("Save"),
),
],
);
},
);
}

@override
Widget build(BuildContext context) {
return Scaffold(
Expand All @@ -44,14 +101,55 @@ class _WorkflowPageState extends State<WorkflowPage> {
ElevatedButton(
onPressed: () async {
if (action == null || reaction == null) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Please refer an action and a reaction"),
backgroundColor: Colors.red,
),
);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Please refer an action and a reaction"),
backgroundColor: Colors.red,
),
);
} else {
print("create workflow");
final workflowDetails =
await _showWorkflowDetailsDialog(context);
if (workflowDetails != null) {
final name = workflowDetails["name"];
final description = workflowDetails["description"];
print("Creating workflow with:");
print("Name: $name");
print("Description: $description");
List<int> servicesId = [];
servicesId.add(action!.serviceId!);
if (action!.serviceId! != reaction!.serviceId!)
servicesId.add(reaction!.serviceId!);

bool hasCreatedWorkflow =
await CreateWorkflowService.createWorkflow(
Workflow(
name: name!,
description: description!,
servicesId: servicesId,
events: [
WorkflowEvent(action: action!, type: "action"),
WorkflowEvent(action: reaction!, type: "reaction")
],
),
);

if (hasCreatedWorkflow) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Workflow successfully created !"),
backgroundColor: Colors.black,
),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("Workflow failed to be created."),
backgroundColor: Colors.red,
),
);
}
}
}
},
child: const Text("Create"))
Expand Down
26 changes: 26 additions & 0 deletions client_mobile/lib/services/workflow/workflow_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'dart:convert';
import 'package:client_mobile/data/workflow.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:http/http.dart' as http;

class CreateWorkflowService {
static const FlutterSecureStorage secureStorage = FlutterSecureStorage();

static String baseUrl =
dotenv.env["BACKEND_BASE_URL"] ?? "http://127.0.0.1:8080";

static Future<bool> createWorkflow(Workflow workflow) async {
final String? token = await secureStorage.read(key: 'bearer_token');

print("bearer token : $token");
final response = await http.post(Uri.parse('$baseUrl/workflow/create'),
headers: {
'Authorization': 'Bearer $token',
'Content-Type': 'application/json'
},
body: jsonEncode(workflow.toJson()));

return (response.statusCode == 200);
}
}
3 changes: 2 additions & 1 deletion client_mobile/lib/widgets/action_button.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import 'package:client_mobile/data/action.dart';
import 'package:client_mobile/data/service.dart';
import 'package:client_mobile/data/service_metadata.dart';
import 'package:client_mobile/pages/dashboard/service_selection.dart';
import 'package:flutter/material.dart';

class ActionButton extends StatefulWidget {
const ActionButton({super.key, required this.onActionSelected, this.action});

final Function(WorkflowActionReaction, String) onActionSelected;
final Function(WorkflowActionReaction, WorkflowService) onActionSelected;
final WorkflowActionReaction? action;

@override
Expand Down
3 changes: 2 additions & 1 deletion client_mobile/lib/widgets/reaction_button.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:client_mobile/data/action.dart';
import 'package:client_mobile/data/service.dart';
import 'package:client_mobile/data/service_metadata.dart';
import 'package:client_mobile/pages/dashboard/service_selection.dart';
import 'package:flutter/material.dart';
Expand All @@ -7,7 +8,7 @@ class ReactionButton extends StatefulWidget {
const ReactionButton(
{super.key, required this.onActionSelected, this.reaction});

final Function(WorkflowActionReaction, String) onActionSelected;
final Function(WorkflowActionReaction, WorkflowService) onActionSelected;
final WorkflowActionReaction? reaction;

@override
Expand Down

0 comments on commit 459bf8f

Please sign in to comment.