import 'package:flutter/material.dart'; import 'package:flutter_flow_chart/flutter_flow_chart.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:go_router/go_router.dart'; import 'package:oc_front/core/models/workspace_local.dart'; import 'package:oc_front/core/services/perms_service.dart'; import 'package:oc_front/core/services/specialized_services/workflow_service.dart'; import 'package:oc_front/main.dart'; import 'package:oc_front/models/response.dart'; import 'package:oc_front/models/search.dart'; import 'package:oc_front/models/workflow.dart'; import 'package:oc_front/pages/abstract_page.dart'; import 'package:oc_front/pages/shared.dart'; import 'package:oc_front/widgets/dialog/shallow_creation.dart'; import 'package:oc_front/widgets/forms/compute_forms.dart'; import 'package:oc_front/widgets/forms/data_forms.dart'; import 'package:oc_front/widgets/forms/processing_forms.dart'; import 'package:oc_front/widgets/forms/scheduler_forms.dart'; import 'package:oc_front/widgets/forms/storage_forms.dart'; import 'package:oc_front/widgets/items/item_row.dart'; import 'package:oc_front/widgets/inputs/shallow_dropdown_input.dart'; Dashboard dash = Dashboard(name: ""); class WorkflowFactory implements AbstractFactory { @override GlobalKey getKey() { return key; } static GlobalKey key = GlobalKey(); @override bool searchFill() { return false; } @override Widget factory(GoRouterState state, List args) { String? id; try { id = state.pathParameters[args.first]; } catch (e) { } return WorkflowPageWidget(id: id); } @override void search(BuildContext context, bool special) { } } bool getAll = true; class WorkflowPageWidget extends StatefulWidget { String? id; WorkflowPageWidget ({ this.id }) : super(key: WorkflowFactory.key); @override WorkflowPageWidgetState createState() => WorkflowPageWidgetState(); static void search(BuildContext context) { } static Widget factory() { return WorkflowPageWidget(); } } class WorkflowPageWidgetState extends State { final WorflowService _service = WorflowService(); Widget itemBuild(Object item) { var e = item as AbstractItem; return Tooltip( message: item.name ?? "", child: e.logo != null ? Image.network(e.logo ?? "", fit: BoxFit.fill) : Image.network('https://get-picto.com/wp-content/uploads/2024/01/logo-instagram-png.webp', fit: BoxFit.fill)); } Widget itemTooltipBuild(Object item) { var e = item as AbstractItem; return Container(color: Colors.white, child: ItemRowWidget(low: true, contextWidth: 290, item: e)); } List getForms(FlowData? obj, String id) { var objAbs = obj as AbstractItem?; if (objAbs == null) { return []; } List res = []; if ( objAbs.topic == "processing") { res = [ProcessingFormsWidget(item: objAbs as ProcessingItem, dash: dash, elementID: id)]; } else if ( objAbs.topic == "data" ) { res = [DataFormsWidget(item: objAbs as DataItem)]; } else if ( objAbs.topic == "storage" ) { res = [StorageFormsWidget(item: objAbs as StorageItem)]; } else if ( objAbs.topic == "compute" ) { res = [ComputeFormsWidget(item: objAbs as ComputeItem)]; } return [ Wrap( alignment: WrapAlignment.center, children: [ Container( padding: const EdgeInsets.all(10), width: 250, height: 60, decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))), child: const Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text("ELEMENT INFO", style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold), textAlign: TextAlign.center), Text("", style: TextStyle(fontSize: 12), textAlign: TextAlign.center), ])), ...res ]) ]; } Widget? getTopRight(FlowData? obj) { var objAbs = obj as AbstractItem?; if (objAbs == null) { return null; } if (objAbs.topic == "compute" ) { var compute = objAbs as ComputeItem; if (compute.technology == 0) { return Icon(FontAwesomeIcons.docker, size: 18); } else if (compute.technology == 1) { return Icon(FontAwesomeIcons.lifeRing, size: 18); } else if (compute.technology == 2) { return Icon(FontAwesomeIcons.cubes, size: 18); } else if (compute.technology == 3) { return Icon(FontAwesomeIcons.hardDrive, size: 18); } else if (compute.technology == 4) { return Icon(FontAwesomeIcons.v, size: 18); } } return null; } Widget? getBottomLeftBadge(FlowData? obj) { var objAbs = obj as AbstractItem?; if (objAbs == null) { return null; } if (objAbs.topic == "processing" ) { return Icon(FontAwesomeIcons.gear) ; } else if (objAbs.topic == "data" ) { return Icon(FontAwesomeIcons.file); } else if (objAbs.topic == "storage" ) { return Icon(FontAwesomeIcons.database); } else if (objAbs.topic == "compute" ) { return Icon(FontAwesomeIcons.microchip); } else if (objAbs.topic == "workflows" ) { return Icon(FontAwesomeIcons.diagramProject); } return null; } List getDashInfoForms() { return [ SchedulerFormsWidget(item: dash), ]; } Future loadDash(String selected) async { dash.shouldSave = false; dash.name = ""; var name = ""; if (selected.split("~").length > 1) { name = selected.split("~")[1]; dash.id = selected.split("~")[0]; } else { name = selected; } await _service.get(context, dash.id ?? "").then((value) async { if (value.data != null) { await WorkspaceLocal.init(context, false); WorkspaceLocal.changeWorkspaceByName("${value.data?.name ?? ""}_workspace"); dash.clear(); dash.deserialize(value.data!.toDashboard()); Future.delayed(const Duration(seconds: 1), () { dash.name = name; dash.shouldSave = true; dash.selectedMenuKey.currentState?.setState(() { }); }); } }); } Future saveDash(String? id) async { if (id == null || !dash.isOpened || !dash.shouldSave || !PermsService.getPerm(Perms.WORKFLOW_EDIT)) { return; } var datas = WorkspaceLocal.byTopic("data", true).where( (element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) ); var compute = WorkspaceLocal.byTopic("compute", true).where( (element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) ); var storage = WorkspaceLocal.byTopic("storage", true).where( (element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) ); var computing = WorkspaceLocal.byTopic("processing", true).where( (element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) ); var workflows = WorkspaceLocal.byTopic("workflows", true).where( (element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) ); var updateW = Workflow( name: dash.name, graph: Graph(), data: datas.map((e) => e.id).toSet().toList(), compute: compute.map((e) => e.id).toSet().toList(), storage: storage.map((e) => e.id).toSet().toList(), processing: computing.map((e) => e.id).toSet().toList(), workflows: workflows.map((e) => e.id).toSet().toList(), ); updateW.fromDashboard(dash.serialize()); for (var item in (updateW.graph?.items.values ?? [] as List)) { if (item.position == null) { continue; } item.position?.x = (item.position?.x ?? 0) + (item.width! / 2) + 7.5; item.position?.y = (item.position?.y ?? 0) + (item.height! / 2) + 7.5; for (var i in (updateW.graph?.links ?? [] as List).where((element) => id == element.source?.id)) { i.source?.x = (i.source?.x ?? 0) + (item.width! / 2) + 7; i.source?.y = (i.source?.y ?? 0) + (item.width! / 2) + 7; } for (var i in (updateW.graph?.links ?? [] as List).where((element) => id == element.destination?.id)) { i.destination?.x = (i.destination?.x ?? 0) + (item.width! / 2) + 7.5; i.destination?.y = (i.destination?.y ?? 0) + (item.width! / 2) + 7.5; } } updateW.graph?.zoom = dash.getZoomFactor(); dash.addToHistory(); await _service.put(context, id, updateW.serialize(), {}).then( (e) async { if (dash.addChange) { dash.addChange = false; await WorkspaceLocal.init(context, false); WorkspaceLocal.changeWorkspaceByName("${dash.name}_workspace"); dash.selectedLeftMenuKey.currentState?.setState(() { }); } }); } FlowData? transformToData(Map data) { var d = WorkspaceLocal.getItem(data["id"] ?? "", true); if (d == null) { return null; } d.model = ResourceModel().deserialize(data["resource_model"]); if (d.topic == "data") { return d as DataItem; } if (d.topic == "compute") { return d as ComputeItem; } if (d.topic == "storage") { return d as StorageItem; } if (d.topic == "processing") { d = d as ProcessingItem; if (data.containsKey("container")) { d.container = Containered().deserialize(data["container"]); } return d; } if (d.topic == "workflows") { return d as WorkflowItem; } return null; } Widget onDashboardMenu(Dashboard dash) { return Container( padding: EdgeInsets.only(left: 50), decoration: BoxDecoration( border: Border( left: BorderSide( color: Colors.white ))), child: ShallowDropdownInputWidget( filled: lightColor, hintColor: Colors.grey.shade200, color: Colors.white, prefixIcon: Padding( padding: EdgeInsets.only(right: 10), child: Icon(Icons.shopping_cart, color: Colors.grey.shade200)), current: WorkspaceLocal.current, width: 300, all: () async => WorkspaceLocal.getWorkspacesShallow(), type: CollaborativeAreaType.workspace, change: (String? change) { WorkspaceLocal.changeWorkspace(change.toString()); }, canLoad: (p0) => true, load: (p0) async { dash.isInfo = !dash.isInfo; dash.flutterChartKey.currentState?.setState(() { }); }, tooltipLoad: "open workspace manager", iconLoad: dash.isInfo ? Icons.remove_red_eye_outlined : Icons.remove_red_eye, )); } Widget onDashboardAlertOpened(BuildContext context, Dashboard dash) { return ShallowCreationDialogWidget( canClose: () => dash.isOpened, context: context, load: (p0) async { dash.isOpened = true; if (dash.load != null) { WorkspaceLocal.changeWorkspaceByName(p0.split("~")[1]); await dash.load!(p0); } dash.notifyListeners(); }, create: PermsService.getPerm(Perms.WORKFLOW_CREATE) ? (p0) async => await _service.post(context, p0, {}).then( (value) async { dash.clear(); dash.id = value.data?.getID() ?? ""; dash.name = value.data?.getName() ?? ""; dash.notifyListeners(); await WorkspaceLocal.init(context, true); dash.isOpened = true; Future.delayed(const Duration(seconds: 1), () { dash.load!("${dash.id}~${dash.name}"); }); } ) : null, maptoDropdown: (e) => DropdownMenuItem( value: "${e.id}~${e.name}", child: Text(e.name), ), type: CollaborativeAreaType.workflow, all: () async { List res = []; await _service.all(context).then( (e) { if (e.data != null) { res = e.data!.values.map((e) => Shallow(id: e["id"] ?? "", name: e["name"] ?? "")).toList(); } } ); return res; } ); } @override Widget build(BuildContext context) { dash.load = loadDash; dash.save = saveDash; dash.dashColor = lightColor; dash.midDashColor = midColor; dash.transformToData = transformToData; dash.infoItemWidget = getForms; dash.infoWidget = getDashInfoForms; dash.widthOffset = 50; return FlowChart( key: dash.flutterChartKey, itemLeftBottomBadges: getBottomLeftBadge, itemrightTopBadges: getTopRight, onDashboardAlertOpened: onDashboardAlertOpened, dashboard: dash, current: widget.id, itemWidget: itemBuild, menuWidget: onDashboardMenu, categories: const ["processing", "data", "compute", "storage", "workflows"], draggableItemBuilder: (cat) => WorkspaceLocal.byTopic(cat, false), itemWidgetTooltip: itemTooltipBuild, innerMenuWidth: 350, width: getMainWidth(context), height: getMainHeight(context), onNewConnection: (p1, p2) { }, onDashboardTapped: (context, position) { }, onScaleUpdate: (newScale) { }, onDashboardSecondaryTapped: (context, position) { }, onDashboardLongTapped: (context, position) { }, onDashboardSecondaryLongTapped: (context, position) { }, onElementLongPressed: (context, position, element) { }, onElementSecondaryLongTapped: (context, position, element) { }, onElementPressed: (context, position, element) { }, onElementSecondaryTapped: (context, position, element) { }, onHandlerPressed: (context, position, handler, element) { }, onHandlerLongPressed: (context, position, handler, element) { }, onPivotSecondaryPressed: (context, pivot) { }, ); } }