missing files
This commit is contained in:
		@@ -1,147 +0,0 @@
 | 
				
			|||||||
import 'package:flutter/material.dart';
 | 
					 | 
				
			||||||
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/core/services/perms_service.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/main.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/models/search.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/models/workflow.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/pages/workflow.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/widgets/forms/sub_keys_forms.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/widgets/forms/sub_expose_forms.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/widgets/forms/sub_map_forms.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/widgets/inputs/sub_text_input.dart';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Map<String, Map<String, AbstractItem>> proxyWfItem = {};
 | 
					 | 
				
			||||||
// ADD EXPOSE
 | 
					 | 
				
			||||||
class ProcessingFormsWidget extends StatefulWidget {
 | 
					 | 
				
			||||||
  String elementID;
 | 
					 | 
				
			||||||
  ProcessingItem item;
 | 
					 | 
				
			||||||
  Dashboard dash;
 | 
					 | 
				
			||||||
  ProcessingFormsWidget ({ super.key, required this.item, required this.dash, required this.elementID });
 | 
					 | 
				
			||||||
  @override ProcessingFormsWidgetState createState() => ProcessingFormsWidgetState();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
class ProcessingFormsWidgetState extends State<ProcessingFormsWidget> {
 | 
					 | 
				
			||||||
  Widget getInputAndOutputVariableForms(bool readOnly) {
 | 
					 | 
				
			||||||
    var inList = widget.dash.GetArrowByElementID(widget.elementID, true);
 | 
					 | 
				
			||||||
    var outList = widget.dash.GetArrowByElementID(widget.elementID, false);
 | 
					 | 
				
			||||||
    List<Widget> res = [];
 | 
					 | 
				
			||||||
    List<GraphItem> inItems = [];
 | 
					 | 
				
			||||||
    List<GraphItem> outItems = [];
 | 
					 | 
				
			||||||
    for (var inItem in inList) {
 | 
					 | 
				
			||||||
      var element = widget.dash.getElement(inItem.fromID.substring(0,36));
 | 
					 | 
				
			||||||
      if (element == null) { continue; }
 | 
					 | 
				
			||||||
      var g = GraphItem();
 | 
					 | 
				
			||||||
      g.fromDashboard(element.serialize());
 | 
					 | 
				
			||||||
      inItems.add(g);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    for (var outItem in outList) {
 | 
					 | 
				
			||||||
      var element = widget.dash.getElement(outItem.toID.substring(0,36));
 | 
					 | 
				
			||||||
      if (element == null) { continue; }
 | 
					 | 
				
			||||||
      var g = GraphItem();
 | 
					 | 
				
			||||||
      g.fromDashboard(element.serialize());
 | 
					 | 
				
			||||||
      outItems.add(g);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (inItems.isNotEmpty) {
 | 
					 | 
				
			||||||
      res.add(SubKeysMapFormsWidget(dash: widget.dash, isInput: true, item: widget.item, elementID: widget.elementID, 
 | 
					 | 
				
			||||||
        categoryKey: "container", varKey: "env", graphItems: inItems, readOnly: readOnly));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (outItems.isNotEmpty) {
 | 
					 | 
				
			||||||
      res.add(SubKeysMapFormsWidget(dash: widget.dash, isInput: false, item: widget.item, elementID: widget.elementID, 
 | 
					 | 
				
			||||||
        categoryKey: "container", varKey: "env", graphItems: outItems, readOnly: readOnly));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return Column( children: res );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @override Widget build(BuildContext context) {
 | 
					 | 
				
			||||||
    bool readOnly = !PermsService.getPerm(Perms.WORKFLOW_EDIT);
 | 
					 | 
				
			||||||
    List<Widget> categories = [];
 | 
					 | 
				
			||||||
    var l = widget.item.model?.model?.keys ?? [];
 | 
					 | 
				
			||||||
    for (var child in l) {
 | 
					 | 
				
			||||||
      var sub = widget.item.model!.model![child]!;
 | 
					 | 
				
			||||||
      List<Widget> children = [];
 | 
					 | 
				
			||||||
      for (var st in sub.keys) {  
 | 
					 | 
				
			||||||
        if (sub[st]!.type?.contains("map") ?? false) {
 | 
					 | 
				
			||||||
          children.add(
 | 
					 | 
				
			||||||
            SubMapFormsWidget(dash: dash, empty: children.isEmpty, item: widget.item, 
 | 
					 | 
				
			||||||
                          readOnly: readOnly,
 | 
					 | 
				
			||||||
                          elementID: widget.elementID, categoryKey: child, varKey: st)
 | 
					 | 
				
			||||||
          );
 | 
					 | 
				
			||||||
        } else if (sub[st]!.type == "string") {
 | 
					 | 
				
			||||||
          children.add(SubTextInputWidget(subkey: st, 
 | 
					 | 
				
			||||||
            readOnly: readOnly,
 | 
					 | 
				
			||||||
            initialValue: widget.item.getVariable([child, st], widget.item.serialize()), 
 | 
					 | 
				
			||||||
            width: 180, empty: children.isEmpty, change: (value) { 
 | 
					 | 
				
			||||||
              widget.item.model ?? Model();
 | 
					 | 
				
			||||||
              Future.delayed(const Duration(seconds: 2), () {
 | 
					 | 
				
			||||||
                if (widget.item.getVariable([child, st], widget.item.serialize()) == value) {
 | 
					 | 
				
			||||||
                  dash.saveDash(dash.id);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
              });
 | 
					 | 
				
			||||||
              var el = dash.getElement(widget.elementID);
 | 
					 | 
				
			||||||
              widget.item = widget.item.deserialize(widget.item.setVariable([child, st], value, widget.item.serialize())) as dynamic;
 | 
					 | 
				
			||||||
              el!.element = widget.item as dynamic;
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
          );
 | 
					 | 
				
			||||||
        }  
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      categories.add(Container(
 | 
					 | 
				
			||||||
          padding: const EdgeInsets.symmetric(vertical: 10),
 | 
					 | 
				
			||||||
          width: 180,
 | 
					 | 
				
			||||||
          child: Column( 
 | 
					 | 
				
			||||||
            mainAxisAlignment: MainAxisAlignment.center,
 | 
					 | 
				
			||||||
            children: [
 | 
					 | 
				
			||||||
              Text("<${child.toUpperCase()}>", style: const TextStyle(fontSize: 13, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
 | 
					 | 
				
			||||||
              Padding(padding: const EdgeInsets.only(bottom: 10), child: SubTextInputWidget(subkey: "image", width: 180, empty: false, change: (value) {}, 
 | 
					 | 
				
			||||||
                initialValue: widget.item.container?.image, readOnly: true,)),
 | 
					 | 
				
			||||||
              ...children,
 | 
					 | 
				
			||||||
              getInputAndOutputVariableForms(readOnly),
 | 
					 | 
				
			||||||
            ],)
 | 
					 | 
				
			||||||
        ));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    // EXPOSE 
 | 
					 | 
				
			||||||
    categories.add(Container(
 | 
					 | 
				
			||||||
          padding: const EdgeInsets.symmetric(vertical: 10),
 | 
					 | 
				
			||||||
          width: 180,
 | 
					 | 
				
			||||||
          child: Column( 
 | 
					 | 
				
			||||||
            mainAxisAlignment: MainAxisAlignment.center,
 | 
					 | 
				
			||||||
            children: [
 | 
					 | 
				
			||||||
              const Padding(padding: EdgeInsets.only(bottom: 5), child: Text("<EXPOSE>", 
 | 
					 | 
				
			||||||
                style: TextStyle(fontSize: 13, fontWeight: FontWeight.bold), textAlign: TextAlign.center)),
 | 
					 | 
				
			||||||
              readOnly ? Container() : Row( children: [
 | 
					 | 
				
			||||||
                InkWell( onTap: () {
 | 
					 | 
				
			||||||
                    widget.item.expose.add(Expose());
 | 
					 | 
				
			||||||
                    var el = dash.getElement(widget.elementID);
 | 
					 | 
				
			||||||
                    el!.element = widget.item as dynamic;
 | 
					 | 
				
			||||||
                    setState(() {});
 | 
					 | 
				
			||||||
                  }, child:
 | 
					 | 
				
			||||||
                  Container( margin: const EdgeInsets.only(top: 5),
 | 
					 | 
				
			||||||
                    decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.grey, width: 1)),
 | 
					 | 
				
			||||||
                    width: 125, height: 30,
 | 
					 | 
				
			||||||
                    child: const Row( mainAxisAlignment: MainAxisAlignment.center,
 | 
					 | 
				
			||||||
                      children: [ Padding( padding: EdgeInsets.only(right: 5), child: Icon(Icons.add)), Text("add expose")]),
 | 
					 | 
				
			||||||
                  )
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
                InkWell( onTap: () {
 | 
					 | 
				
			||||||
                  if (widget.item.expose.isEmpty) { return; }
 | 
					 | 
				
			||||||
                    widget.item.expose = widget.item.expose.sublist(0, widget.item.expose.length - 1);
 | 
					 | 
				
			||||||
                    var el = dash.getElement(widget.elementID);
 | 
					 | 
				
			||||||
                    el!.element = widget.item as dynamic;
 | 
					 | 
				
			||||||
                    setState(() {});
 | 
					 | 
				
			||||||
                  }, child:
 | 
					 | 
				
			||||||
                  Container( margin: const EdgeInsets.only(left: 5, top: 5),
 | 
					 | 
				
			||||||
                    decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.grey, width: 1)),
 | 
					 | 
				
			||||||
                    width: 45, height: 30,
 | 
					 | 
				
			||||||
                    child: const Row( mainAxisAlignment: MainAxisAlignment.center,
 | 
					 | 
				
			||||||
                      children: [ Icon(Icons.delete, color: Colors.black) ]),
 | 
					 | 
				
			||||||
                  )
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
              ]),
 | 
					 | 
				
			||||||
            ],)
 | 
					 | 
				
			||||||
        ));
 | 
					 | 
				
			||||||
    for (var expose in widget.item.expose) {
 | 
					 | 
				
			||||||
      categories.add(SubExposeFormsWidget( readOnly: readOnly, width: 180, dash: dash, empty: categories.isEmpty, 
 | 
					 | 
				
			||||||
      item: expose, elementID: widget.elementID));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return SizedBox( height: getHeight(context) - 330, child: SingleChildScrollView( child: Column( 
 | 
					 | 
				
			||||||
      children: categories )) );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										91
									
								
								lib/widgets/forms/resource_forms.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								lib/widgets/forms/resource_forms.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
				
			|||||||
 | 
					import 'package:oc_front/main.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/models/workflow.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/models/resources/resources.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/core/services/perms_service.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/widgets/forms/sub_keys_forms.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_flow_chart/flutter_flow_chart.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/widgets/inputs/sub_text_input.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/widgets/forms/container_forms.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/widgets/inputs/sub_dropdown_input%20.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ignore: must_be_immutable
 | 
				
			||||||
 | 
					class ResourceFormsWidget extends StatefulWidget {
 | 
				
			||||||
 | 
					  int instanceID = 0;
 | 
				
			||||||
 | 
					  AbstractItem item;
 | 
				
			||||||
 | 
					  Dashboard dash;
 | 
				
			||||||
 | 
					  String elementID;
 | 
				
			||||||
 | 
					  ResourceFormsWidget ({ super.key, required this.item, required this.dash, required this.elementID });
 | 
				
			||||||
 | 
					  @override ResourceFormsWidgetState createState() => ResourceFormsWidgetState();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ResourceFormsWidgetState extends State<ResourceFormsWidget> {
 | 
				
			||||||
 | 
					  List<Widget> getWidgets(Map<String, dynamic> infos) {
 | 
				
			||||||
 | 
					    List<Widget> widgets = [];
 | 
				
			||||||
 | 
					    for (var key in infos.keys) {
 | 
				
			||||||
 | 
					      if (infos[key] == null && infos[key] != 0) { continue; }
 | 
				
			||||||
 | 
					      if (infos[key] is Map) { widgets.addAll(getWidgets(infos[key]));
 | 
				
			||||||
 | 
					      } if (infos[key] is List) {
 | 
				
			||||||
 | 
					        if (infos[key].isEmpty) { continue; }
 | 
				
			||||||
 | 
					        widgets.add(SubTextInputWidget(subkey: key.replaceAll("_", " "), width: 180, empty: false, readOnly: true,
 | 
				
			||||||
 | 
					              change: (value) {}, initialValue: (infos[key] as List<dynamic>).join(",") ));
 | 
				
			||||||
 | 
					      } else if (infos[key] is Map) {
 | 
				
			||||||
 | 
					          widgets.addAll(getWidgets(infos[key] as Map<String, dynamic>));
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        widgets.add(SubTextInputWidget(subkey: key.replaceAll("_", " "), width: 180, empty: false, readOnly: true,
 | 
				
			||||||
 | 
					          change: (value) {}, initialValue: infos[key] is List ? infos[key].join(",") : "${infos[key]}" ));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (widgets.isNotEmpty) {
 | 
				
			||||||
 | 
					      widgets.add(SizedBox( width: 200, height: 15) );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return widgets;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Widget getInputAndOutputVariableForms(bool readOnly) {
 | 
				
			||||||
 | 
					    List<Widget> res = [];
 | 
				
			||||||
 | 
					    res.add(SubKeysMapFormsWidget(dash: widget.dash, type: SubMapFormsType.INPUT, item: widget.item, elementID: widget.elementID, 
 | 
				
			||||||
 | 
					      readOnly: readOnly));
 | 
				
			||||||
 | 
					    res.add(SubKeysMapFormsWidget(dash: widget.dash, type: SubMapFormsType.OUTPUT, item: widget.item, elementID: widget.elementID, 
 | 
				
			||||||
 | 
					      readOnly: readOnly));
 | 
				
			||||||
 | 
					    res.add(SubKeysMapFormsWidget(dash: widget.dash, type: SubMapFormsType.ENV, item: widget.item, elementID: widget.elementID, 
 | 
				
			||||||
 | 
					        readOnly: readOnly));
 | 
				
			||||||
 | 
					    return Column( children: res );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    List<Widget> instancesCat = [];
 | 
				
			||||||
 | 
					    List<Widget> childrenReadOnly = getWidgets(widget.item.infos());
 | 
				
			||||||
 | 
					    List<DropdownMenuItem<String>> dpItems = [];
 | 
				
			||||||
 | 
					    for (var (i, instance) in widget.item.instances.indexed) {
 | 
				
			||||||
 | 
					      dpItems.add(DropdownMenuItem(value: '$i', child: Text('${instance.name}', overflow: TextOverflow.ellipsis,)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (dpItems.isNotEmpty) {
 | 
				
			||||||
 | 
					      childrenReadOnly.add(Padding( padding: EdgeInsets.only(top: 20),
 | 
				
			||||||
 | 
					        child : Container(
 | 
				
			||||||
 | 
					          width: 200, decoration: BoxDecoration( border: Border(bottom: BorderSide(color: Colors.grey))),
 | 
				
			||||||
 | 
					        )));
 | 
				
			||||||
 | 
					      childrenReadOnly.add(Padding(padding: EdgeInsets.only(bottom: 15), child: 
 | 
				
			||||||
 | 
					        SubDropdownInputWidget( dropdownMenuEntries: dpItems, subkey: "", width: 180, empty: false, 
 | 
				
			||||||
 | 
					          initialValue: "${widget.instanceID}", change: (value) {
 | 
				
			||||||
 | 
					            if (value != null) { setState(() { widget.instanceID = int.parse(value); }); }
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					        ))
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      if (widget.item.instances.length > widget.instanceID) {
 | 
				
			||||||
 | 
					        childrenReadOnly.addAll(getWidgets(widget.item.instances[widget.instanceID].infos()));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    instancesCat.add(ContainerFormsWidget(dash: widget.dash, item: widget.item, elementID: widget.elementID));
 | 
				
			||||||
 | 
					    if (instancesCat.isNotEmpty) {
 | 
				
			||||||
 | 
					      instancesCat.add(Container(
 | 
				
			||||||
 | 
					          width: 200, decoration: BoxDecoration( border: Border(bottom: BorderSide(color: Colors.grey))),
 | 
				
			||||||
 | 
					        ));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    bool readOnly = !PermsService.getPerm(Perms.WORKFLOW_EDIT);
 | 
				
			||||||
 | 
					    // missing env input and output variables
 | 
				
			||||||
 | 
					    return SizedBox( height: getHeight(context) - 330, child: SingleChildScrollView( child:  Column( 
 | 
				
			||||||
 | 
					      children: [ getInputAndOutputVariableForms(readOnly), ...childrenReadOnly,  ...instancesCat,  ])));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,72 +1,117 @@
 | 
				
			|||||||
import 'package:alert_banner/exports.dart';
 | 
					
 | 
				
			||||||
import 'package:cron/cron.dart';
 | 
					import 'package:cron/cron.dart';
 | 
				
			||||||
import 'package:intl/intl.dart' as intl;
 | 
					import 'package:oc_front/core/services/specialized_services/workflow_execution_service.dart';
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					 | 
				
			||||||
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
 | 
					 | 
				
			||||||
import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/core/models/shared_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/core/services/specialized_services/check_service.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/main.dart';
 | 
					import 'package:oc_front/main.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:intl/intl.dart' as intl;
 | 
				
			||||||
 | 
					import 'package:alert_banner/exports.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/models/resources/compute.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/models/resources/processing.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/models/workflow.dart';
 | 
				
			||||||
import 'package:oc_front/pages/shared.dart';
 | 
					import 'package:oc_front/pages/shared.dart';
 | 
				
			||||||
import 'package:oc_front/pages/workflow.dart';
 | 
					import 'package:oc_front/pages/workflow.dart';
 | 
				
			||||||
import 'package:oc_front/widgets/dialog/alert.dart';
 | 
					import 'package:oc_front/widgets/dialog/alert.dart';
 | 
				
			||||||
import 'package:oc_front/widgets/dialog/confirm_box.dart';
 | 
					import 'package:oc_front/widgets/dialog/confirm_box.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/core/services/perms_service.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_flow_chart/flutter_flow_chart.dart';
 | 
				
			||||||
import 'package:oc_front/widgets/inputs/shallow_text_input.dart';
 | 
					import 'package:oc_front/widgets/inputs/shallow_text_input.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/core/models/shared_workspace_local.dart';
 | 
				
			||||||
 | 
					import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/core/services/specialized_services/check_service.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/core/services/specialized_services/workflow_service.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ignore: must_be_immutable
 | 
				
			||||||
class SchedulerFormsWidget extends StatefulWidget {
 | 
					class SchedulerFormsWidget extends StatefulWidget {
 | 
				
			||||||
 | 
					  Scheduler schedule = Scheduler();
 | 
				
			||||||
  Dashboard item;
 | 
					  Dashboard item;
 | 
				
			||||||
  String purpose = ""; 
 | 
					 | 
				
			||||||
  bool? booking;
 | 
					  bool? booking;
 | 
				
			||||||
 | 
					  bool valid = false;
 | 
				
			||||||
 | 
					  bool shouldSearch = true;
 | 
				
			||||||
 | 
					  int scheduleFutureCount = 0;
 | 
				
			||||||
 | 
					  int scheduleBeforeCount = 0;
 | 
				
			||||||
  String? error;
 | 
					  String? error;
 | 
				
			||||||
  String? errorEndDate;
 | 
					  String? errorEndDate;
 | 
				
			||||||
  String? errorCron;
 | 
					  String? errorCron;
 | 
				
			||||||
  Function validate = () {};
 | 
					  Function validate = () {};
 | 
				
			||||||
 | 
					  final WorkflowExecutionService _service = WorkflowExecutionService();
 | 
				
			||||||
  SchedulerFormsWidget ({ super.key, required this.item, });
 | 
					  SchedulerFormsWidget ({ super.key, required this.item, });
 | 
				
			||||||
  @override SchedulerFormsWidgetState createState() => SchedulerFormsWidgetState();
 | 
					  @override SchedulerFormsWidgetState createState() => SchedulerFormsWidgetState();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
 | 
					class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
 | 
				
			||||||
  CheckService check = CheckService();
 | 
					  CheckService check = CheckService();
 | 
				
			||||||
  void save(List<GlobalKey<FormFieldState>> formKeys) {
 | 
					  void save(List<GlobalKey<FormFieldState>> formKeys) {
 | 
				
			||||||
    dash.scheduleActive = !dash.scheduleActive;
 | 
					 | 
				
			||||||
    widget.error = null;
 | 
					    widget.error = null;
 | 
				
			||||||
    widget.errorEndDate = null;
 | 
					    widget.errorEndDate = null;
 | 
				
			||||||
    widget.errorCron = null;
 | 
					    widget.errorCron = null;
 | 
				
			||||||
 | 
					    if (dash.elements.isEmpty || dash.elements.where((element) => element.element is ProcessingItem).isEmpty) {
 | 
				
			||||||
 | 
					      dash.error = "You need at least one processing element";
 | 
				
			||||||
 | 
					    } 
 | 
				
			||||||
 | 
					    var processings = dash.elements.where((element) => element.element is ProcessingItem);
 | 
				
			||||||
 | 
					    var computes = dash.elements.where((element) => element.element is ComputeItem);
 | 
				
			||||||
 | 
					    for (var p in processings) {
 | 
				
			||||||
 | 
					      var links =  dash.arrows.where((element) => element.fromID.contains(p.id) || element.toID.contains(p.id));
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        List<ComputeItem> c = [];
 | 
				
			||||||
 | 
					        for (var link in links) {
 | 
				
			||||||
 | 
					          c.addAll(computes.where( (e) => link.toID.contains(e.id) || link.fromID.contains(e.id)).map( (e) => e.element as ComputeItem));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (c.isEmpty) { throw Exception("no compute element linked"); }
 | 
				
			||||||
 | 
					      } catch (e) {
 | 
				
			||||||
 | 
					        dash.error = "You need to link each processing element to a compute element";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (dash.error != null) {
 | 
				
			||||||
 | 
					      showAlertBanner( context, () {}, AlertAlertBannerChild(text: dash.error.toString()),// <-- Put any widget here you want!
 | 
				
			||||||
 | 
					                       alertBannerLocation:  AlertBannerLocation.bottom,);
 | 
				
			||||||
 | 
					      setState(() {});
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    for (var k in formKeys) {
 | 
					    for (var k in formKeys) {
 | 
				
			||||||
      if (k.currentState != null) {
 | 
					      if (k.currentState != null) {
 | 
				
			||||||
        if (!k.currentState!.validate() && dash.scheduleActive) {
 | 
					        if (!k.currentState!.validate()) {
 | 
				
			||||||
          dash.scheduleActive = !dash.scheduleActive;
 | 
					 | 
				
			||||||
          return;
 | 
					          return;
 | 
				
			||||||
        } else { k.currentState!.save();}
 | 
					        } else { k.currentState!.save();}
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    DateTime now = DateTime.now().add(const Duration(minutes: 1));
 | 
					    DateTime now = DateTime.now().add(const Duration(minutes: 1));
 | 
				
			||||||
    if (dash.scheduler["start"] == null || DateTime.parse(dash.scheduler["start"]!).isBefore(now)) {
 | 
					    if (widget.schedule.start == null || widget.schedule.start!.isBefore(now)) {
 | 
				
			||||||
      dash.scheduler["start"] = now.toUtc().toIso8601String();
 | 
					      widget.schedule.start = now.toUtc();
 | 
				
			||||||
      if (dash.scheduler["end"] != null) {
 | 
					      if (widget.schedule.end != null) {
 | 
				
			||||||
        dash.scheduler["end"] = now.add(const Duration(minutes: 1)).toUtc().toIso8601String();
 | 
					        widget.schedule.end = now.add(const Duration(minutes: 1)).toUtc();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    widget.item.saveDash(widget.item.id);
 | 
					    Duration durationBefore = widget.schedule.start!.difference(DateTime.now().toUtc()) + Duration(seconds: 5);
 | 
				
			||||||
 | 
					    widget._service.schedule(context, widget.item.id ?? "", widget.schedule.serialize(), {}).then((value) {
 | 
				
			||||||
 | 
					      setState(() { widget.valid = true; });
 | 
				
			||||||
 | 
					      Future.delayed(durationBefore, () {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					          setState(() {});
 | 
				
			||||||
 | 
					        } catch (e) { /* */ }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      Future.delayed(const Duration(seconds: 10), () {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					          setState(() { widget.valid = false; });
 | 
				
			||||||
 | 
					        } catch (e) { /* */ }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  void checkBooking(List<GlobalKey<FormFieldState>> formKeys, void Function(List<GlobalKey<FormFieldState>> )? f){
 | 
					  void checkBooking(List<GlobalKey<FormFieldState>> formKeys, void Function(List<GlobalKey<FormFieldState>> )? f){
 | 
				
			||||||
    if (widget.item.scheduler["start"] == null) {
 | 
					    if (widget.schedule.start == null) {
 | 
				
			||||||
      DateTime now = DateTime.now().add(const Duration(minutes: 5));
 | 
					      DateTime now = DateTime.now().add(const Duration(minutes: 5));
 | 
				
			||||||
      widget.item.scheduler["start"] = now.toUtc().toIso8601String();
 | 
					      widget.schedule.start = now.toUtc();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    var s = DateTime.parse(widget.item.scheduler["start"]).toUtc().toIso8601String();
 | 
					    var s = widget.schedule.start!.toUtc().toIso8601String();
 | 
				
			||||||
    var e = "";
 | 
					    var e = "";
 | 
				
			||||||
    if (widget.item.scheduler["end"] == null) {
 | 
					    if (widget.schedule.end == null) {
 | 
				
			||||||
      e = DateTime.parse(widget.item.scheduler["start"]).add(const Duration(seconds: 5)).toUtc().toIso8601String();
 | 
					      e = widget.schedule.start!.add(const Duration(seconds: 5)).toUtc().toIso8601String();
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      e = DateTime.parse(widget.item.scheduler["end"]).toUtc().toIso8601String();
 | 
					      e = widget.schedule.end!.toUtc().toIso8601String();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    check.search(context, [widget.item.id ?? "", s.substring(0, 19), e.substring(0, 19)], {}).then(
 | 
					    check.search(context, [widget.item.id ?? "", s.substring(0, 19), e.substring(0, 19)], {}).then(
 | 
				
			||||||
      (v) {
 | 
					      (v) {
 | 
				
			||||||
        if (v.data == null) { return; }
 | 
					        if (v.data == null) { return; }
 | 
				
			||||||
        widget.booking = v.data!.is_available;
 | 
					        widget.booking = v.data!.isAvailable;
 | 
				
			||||||
        if (v.data!.is_available) {
 | 
					        if (v.data!.isAvailable) {
 | 
				
			||||||
          if (f != null) { f(formKeys); 
 | 
					          if (f != null) { f(formKeys); 
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            showAlertBanner( context, () {}, 
 | 
					            showAlertBanner( context, () {}, 
 | 
				
			||||||
@@ -84,6 +129,31 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override Widget build(BuildContext context) {
 | 
					  @override Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    if (widget.shouldSearch && widget.item.name != "") {
 | 
				
			||||||
 | 
					      widget.shouldSearch = false;
 | 
				
			||||||
 | 
					      widget._service.search(null, [widget.item.name], {}).then((value) {
 | 
				
			||||||
 | 
					        if (value.data != null) {
 | 
				
			||||||
 | 
					          try {
 | 
				
			||||||
 | 
					            setState(() {  
 | 
				
			||||||
 | 
					            widget.scheduleFutureCount = 0;
 | 
				
			||||||
 | 
					            widget.scheduleBeforeCount = 0;
 | 
				
			||||||
 | 
					            for (var exec in value.data!.executions) {
 | 
				
			||||||
 | 
					              if (exec.startDate != null && DateTime.parse(exec.startDate!).isAfter(DateTime.now().toUtc())) {
 | 
				
			||||||
 | 
					                widget.scheduleFutureCount++;
 | 
				
			||||||
 | 
					              } else {
 | 
				
			||||||
 | 
					                widget.scheduleBeforeCount++;
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					          } catch (e) { /* */ }
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      Future.delayed(const Duration(milliseconds: 100), () {
 | 
				
			||||||
 | 
					        widget.shouldSearch = true;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    bool isService = true;
 | 
					    bool isService = true;
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      widget.item.elements.firstWhere((element) => (element.element?.serialize()["is_service"] ?? false) == true);
 | 
					      widget.item.elements.firstWhere((element) => (element.element?.serialize()["is_service"] ?? false) == true);
 | 
				
			||||||
@@ -95,22 +165,22 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
 | 
				
			|||||||
    DateTime? end;
 | 
					    DateTime? end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Duration delayed = const Duration(minutes: 5);
 | 
					    Duration delayed = const Duration(minutes: 5);
 | 
				
			||||||
    if (widget.item.scheduler["start"] != null) {
 | 
					    if (widget.schedule.start != null) {
 | 
				
			||||||
      start = DateTime.parse(widget.item.scheduler["start"]!);
 | 
					      start = widget.schedule.start!;
 | 
				
			||||||
      if (start.isBefore(DateTime.now()) && !dash.scheduleActive) {
 | 
					      if (start.isBefore(DateTime.now())) {
 | 
				
			||||||
        start = DateTime.now().add(const Duration(minutes: 5));
 | 
					        start = DateTime.now().add(const Duration(minutes: 5));
 | 
				
			||||||
        widget.item.scheduler["start"] = start.toUtc().toIso8601String();
 | 
					        widget.schedule.start = start.toUtc();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (start.isBefore(DateTime.now())) {
 | 
					      if (start.isBefore(DateTime.now())) {
 | 
				
			||||||
        // get difference between now and start
 | 
					        // get difference between now and start
 | 
				
			||||||
        delayed = start.difference(DateTime.now());
 | 
					        delayed = start.difference(DateTime.now());
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (widget.item.scheduler["end"] != null) {
 | 
					    if (widget.schedule.end != null) {
 | 
				
			||||||
      end = DateTime.parse(widget.item.scheduler["end"]!);
 | 
					      end = widget.schedule.end!;
 | 
				
			||||||
      if (end.isBefore(DateTime.now()) && !dash.scheduleActive) {
 | 
					      if (end.isBefore(DateTime.now())) {
 | 
				
			||||||
        end = DateTime.now().add(const Duration(minutes: 5));
 | 
					        end = DateTime.now().add(const Duration(minutes: 5));
 | 
				
			||||||
        widget.item.scheduler["end"] = end.toUtc().toIso8601String();
 | 
					        widget.schedule.end = end.toUtc();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (end.isBefore(DateTime.now())) {
 | 
					      if (end.isBefore(DateTime.now())) {
 | 
				
			||||||
        // get difference between now and start
 | 
					        // get difference between now and start
 | 
				
			||||||
@@ -164,51 +234,11 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
 | 
				
			|||||||
        child: shallow ),
 | 
					        child: shallow ),
 | 
				
			||||||
      const SizedBox(height: 20, width: 200 ),
 | 
					      const SizedBox(height: 20, width: 200 ),
 | 
				
			||||||
      isService ? Text("Warning a processing is a service, if no end execution it will run forever.") : Container(),
 | 
					      isService ? Text("Warning a processing is a service, if no end execution it will run forever.") : Container(),
 | 
				
			||||||
      Tooltip( message: "executions name",
 | 
					 | 
				
			||||||
        child: Container( height: 40, margin: const EdgeInsets.only(top: 5),
 | 
					 | 
				
			||||||
                              padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
 | 
					 | 
				
			||||||
                              child: TextFormField( key: formKeys[0], readOnly: readOnly,
 | 
					 | 
				
			||||||
                              initialValue: "${widget.item.scheduler["name"] ?? "${widget.item.name}_executions"}",
 | 
					 | 
				
			||||||
                              enabled: !dash.scheduleActive && !readOnly,
 | 
					 | 
				
			||||||
                              onChanged: (value) { 
 | 
					 | 
				
			||||||
                                Future.delayed(const Duration(seconds: 100), () {
 | 
					 | 
				
			||||||
                                  if (widget.item.scheduler["name"] == value) { 
 | 
					 | 
				
			||||||
                                    widget.item.saveDash(widget.item.id);  
 | 
					 | 
				
			||||||
                                  }
 | 
					 | 
				
			||||||
                                });
 | 
					 | 
				
			||||||
                                widget.item.scheduler["name"] = value;
 | 
					 | 
				
			||||||
                              },
 | 
					 | 
				
			||||||
                              onSaved: (value) { 
 | 
					 | 
				
			||||||
                                widget.item.scheduler["name"] = value ?? "${widget.item.scheduler["name"] ?? "${widget.item.name}_executions"}";
 | 
					 | 
				
			||||||
                              },
 | 
					 | 
				
			||||||
                              validator: (value) {
 | 
					 | 
				
			||||||
                                if (value == null || value.isEmpty) {
 | 
					 | 
				
			||||||
                                  setState(() { widget.error = 'missing name';  });   
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
                                return value == null || value.isEmpty ? "not empty" :  null;
 | 
					 | 
				
			||||||
                              },
 | 
					 | 
				
			||||||
                              style: const TextStyle(fontSize: 12),
 | 
					 | 
				
			||||||
                              decoration: InputDecoration(
 | 
					 | 
				
			||||||
                                floatingLabelBehavior: FloatingLabelBehavior.always,
 | 
					 | 
				
			||||||
                                fillColor: Colors.white,
 | 
					 | 
				
			||||||
                                filled: true,
 | 
					 | 
				
			||||||
                                hintText: "enter executions name...",
 | 
					 | 
				
			||||||
                                labelText: "executions name*",
 | 
					 | 
				
			||||||
                                hintStyle: TextStyle(fontSize: 10),
 | 
					 | 
				
			||||||
                                labelStyle: TextStyle(fontSize: 10),
 | 
					 | 
				
			||||||
                                focusedErrorBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.item.error != null || widget.error != null ? Colors.red : Colors.black)),
 | 
					 | 
				
			||||||
                                errorBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.item.error != null || widget.error != null ? Colors.red : Colors.black)),
 | 
					 | 
				
			||||||
                                focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.item.error != null || widget.error != null ? Colors.red : Colors.black)),
 | 
					 | 
				
			||||||
                                enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.item.error != null || widget.error != null ? Colors.red : Colors.grey)),
 | 
					 | 
				
			||||||
                                border: OutlineInputBorder(borderSide: BorderSide(color: widget.item.error != null || widget.error != null ? Colors.red : Colors.grey)),
 | 
					 | 
				
			||||||
                                contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
 | 
					 | 
				
			||||||
                              ),
 | 
					 | 
				
			||||||
                          ))),
 | 
					 | 
				
			||||||
      Tooltip( message: "start executions",
 | 
					      Tooltip( message: "start executions",
 | 
				
			||||||
        child: Container( height: 40, margin: const EdgeInsets.only(top: 5),
 | 
					        child: Container( height: 40, margin: const EdgeInsets.only(top: 5),
 | 
				
			||||||
                              padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
 | 
					                              padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
 | 
				
			||||||
                              child: DateTimeField( key: formKeys[1],
 | 
					                              child: DateTimeField( key: formKeys[1],
 | 
				
			||||||
                                enabled: !dash.scheduleActive && !readOnly,
 | 
					                                enabled: !readOnly,
 | 
				
			||||||
                                resetIcon: null,
 | 
					                                resetIcon: null,
 | 
				
			||||||
                                onShowPicker: (context, currentValue) async { 
 | 
					                                onShowPicker: (context, currentValue) async { 
 | 
				
			||||||
                                  var date = await showDatePicker(                                    
 | 
					                                  var date = await showDatePicker(                                    
 | 
				
			||||||
@@ -228,7 +258,7 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
 | 
				
			|||||||
                                      return w;
 | 
					                                      return w;
 | 
				
			||||||
                                    },
 | 
					                                    },
 | 
				
			||||||
                                    context: context,
 | 
					                                    context: context,
 | 
				
			||||||
                                    firstDate: dash.scheduleActive ? DateTime(1900) : DateTime.now().add(const Duration(minutes: 5)),
 | 
					                                    firstDate: DateTime.now().add(const Duration(minutes: 5)),
 | 
				
			||||||
                                    initialDate: DateTime.parse( start?.toLocal().toIso8601String() 
 | 
					                                    initialDate: DateTime.parse( start?.toLocal().toIso8601String() 
 | 
				
			||||||
                                      ?? currentValue?.toIso8601String() 
 | 
					                                      ?? currentValue?.toIso8601String() 
 | 
				
			||||||
                                      ?? DateTime.now().add(const Duration(minutes: 5)).toUtc().toIso8601String()).toLocal(),
 | 
					                                      ?? DateTime.now().add(const Duration(minutes: 5)).toUtc().toIso8601String()).toLocal(),
 | 
				
			||||||
@@ -265,9 +295,9 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
 | 
				
			|||||||
                                      if (time == null) { return DateTime.now().add( const Duration(minutes: 1)); }
 | 
					                                      if (time == null) { return DateTime.now().add( const Duration(minutes: 1)); }
 | 
				
			||||||
                                      count++;
 | 
					                                      count++;
 | 
				
			||||||
                                      date = DateTime(date.year, date.month, date.day, time.hour, time.minute);
 | 
					                                      date = DateTime(date.year, date.month, date.day, time.hour, time.minute);
 | 
				
			||||||
                                      widget.item.scheduler["start"] = date.toUtc().toIso8601String();  
 | 
					                                      widget.schedule.start = date.toUtc();  
 | 
				
			||||||
                                    }
 | 
					                                    }
 | 
				
			||||||
                                    widget.item.saveDash(widget.item.id);   
 | 
					                                    widget.item.saveDash(widget.item.id, context);   
 | 
				
			||||||
                                  }
 | 
					                                  }
 | 
				
			||||||
                                  return date;
 | 
					                                  return date;
 | 
				
			||||||
                                },
 | 
					                                },
 | 
				
			||||||
@@ -296,18 +326,18 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
 | 
				
			|||||||
        child: Container( height: 40, margin: const EdgeInsets.only(top: 5), 
 | 
					        child: Container( height: 40, margin: const EdgeInsets.only(top: 5), 
 | 
				
			||||||
                              padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
 | 
					                              padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
 | 
				
			||||||
                              child: DateTimeField( key: formKeys[2],
 | 
					                              child: DateTimeField( key: formKeys[2],
 | 
				
			||||||
                                enabled: !dash.scheduleActive && !readOnly,
 | 
					                                enabled: !readOnly,
 | 
				
			||||||
                                validator: (value) {
 | 
					                                validator: (value) {
 | 
				
			||||||
                                  if (value == null && widget.item.scheduler["cron"] != null && widget.item.scheduler["cron"].isNotEmpty) {
 | 
					                                  if (value == null && widget.schedule.cron != null && widget.schedule.cron!.isNotEmpty) {
 | 
				
			||||||
                                    setState(() {
 | 
					                                    setState(() {
 | 
				
			||||||
                                      widget.errorEndDate = 'missing start date';
 | 
					                                      widget.errorEndDate = 'missing start date';
 | 
				
			||||||
                                    });   
 | 
					                                    });   
 | 
				
			||||||
                                  }
 | 
					                                  }
 | 
				
			||||||
                                  return value == null && widget.item.scheduler["cron"] != null && widget.item.scheduler["cron"].isNotEmpty ? "not empty" :  null;
 | 
					                                  return value == null && widget.schedule.cron != null && widget.schedule.cron!.isNotEmpty ? "not empty" :  null;
 | 
				
			||||||
                                },
 | 
					                                },
 | 
				
			||||||
                                onChanged: (value) { 
 | 
					                                onChanged: (value) { 
 | 
				
			||||||
                                  if (value == null) {
 | 
					                                  if (value == null) {
 | 
				
			||||||
                                    widget.item.scheduler.remove("end");
 | 
					                                    widget.schedule.end = null;
 | 
				
			||||||
                                  }
 | 
					                                  }
 | 
				
			||||||
                                },
 | 
					                                },
 | 
				
			||||||
                                resetIcon: const Icon(Icons.close, size: 15),
 | 
					                                resetIcon: const Icon(Icons.close, size: 15),
 | 
				
			||||||
@@ -329,7 +359,7 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
 | 
				
			|||||||
                                      return w;
 | 
					                                      return w;
 | 
				
			||||||
                                    },
 | 
					                                    },
 | 
				
			||||||
                                    context: context,
 | 
					                                    context: context,
 | 
				
			||||||
                                    firstDate: dash.scheduleActive ? DateTime(1900) : DateTime.now().add(const Duration(minutes: 5)),
 | 
					                                    firstDate: DateTime.now().add(const Duration(minutes: 5)),
 | 
				
			||||||
                                    initialDate: DateTime.parse( end?.toLocal().toIso8601String() 
 | 
					                                    initialDate: DateTime.parse( end?.toLocal().toIso8601String() 
 | 
				
			||||||
                                      ?? currentValue?.toIso8601String() 
 | 
					                                      ?? currentValue?.toIso8601String() 
 | 
				
			||||||
                                      ?? DateTime.now().add(const Duration(minutes: 5)).toUtc().toIso8601String()).toLocal(),
 | 
					                                      ?? DateTime.now().add(const Duration(minutes: 5)).toUtc().toIso8601String()).toLocal(),
 | 
				
			||||||
@@ -342,7 +372,7 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
 | 
				
			|||||||
                                    var count = 0;
 | 
					                                    var count = 0;
 | 
				
			||||||
                                    while(date!.microsecondsSinceEpoch <= (DateTime.now().microsecondsSinceEpoch) 
 | 
					                                    while(date!.microsecondsSinceEpoch <= (DateTime.now().microsecondsSinceEpoch) 
 | 
				
			||||||
                                      || time == null
 | 
					                                      || time == null
 | 
				
			||||||
                                      || (date.microsecondsSinceEpoch) <= (DateTime.parse(widget.item.scheduler["start"] ?? DateTime.now().toIso8601String()).microsecondsSinceEpoch)) {
 | 
					                                      || (date.microsecondsSinceEpoch) <= (widget.schedule.start  ?? DateTime.now()).microsecondsSinceEpoch) {
 | 
				
			||||||
                                      if (count > 0) { 
 | 
					                                      if (count > 0) { 
 | 
				
			||||||
                                        showAlertBanner( context, () {},  // ignore: use_build_context_synchronously
 | 
					                                        showAlertBanner( context, () {},  // ignore: use_build_context_synchronously
 | 
				
			||||||
                                        const AlertAlertBannerChild(text: "must be at least 1 minute from now to let system check info && upper starting date"),// <-- Put any widget here you want!
 | 
					                                        const AlertAlertBannerChild(text: "must be at least 1 minute from now to let system check info && upper starting date"),// <-- Put any widget here you want!
 | 
				
			||||||
@@ -370,9 +400,9 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
 | 
				
			|||||||
                                      if (time == null) { return null; }
 | 
					                                      if (time == null) { return null; }
 | 
				
			||||||
                                      count++;
 | 
					                                      count++;
 | 
				
			||||||
                                      date = DateTime(date.year, date.month, date.day, time.hour, time.minute);
 | 
					                                      date = DateTime(date.year, date.month, date.day, time.hour, time.minute);
 | 
				
			||||||
                                      widget.item.scheduler["end"] = date.toUtc().toIso8601String();   
 | 
					                                      widget.schedule.end = date.toUtc();   
 | 
				
			||||||
                                    }
 | 
					                                    }
 | 
				
			||||||
                                    widget.item.saveDash(widget.item.id);                          
 | 
					                                    widget.item.saveDash(widget.item.id, context);                          
 | 
				
			||||||
                                  }
 | 
					                                  }
 | 
				
			||||||
                                  return date;
 | 
					                                  return date;
 | 
				
			||||||
                                },
 | 
					                                },
 | 
				
			||||||
@@ -400,19 +430,19 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
 | 
				
			|||||||
        child: Container( height: 40, margin: const EdgeInsets.only(top: 5),
 | 
					        child: Container( height: 40, margin: const EdgeInsets.only(top: 5),
 | 
				
			||||||
                              padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
 | 
					                              padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
 | 
				
			||||||
                              child: TextFormField( key: formKeys[3],
 | 
					                              child: TextFormField( key: formKeys[3],
 | 
				
			||||||
                              enabled: !dash.scheduleActive && !readOnly,
 | 
					                              enabled: !readOnly,
 | 
				
			||||||
                              initialValue: widget.item.scheduler["cron"],
 | 
					                              initialValue: widget.schedule.cron,
 | 
				
			||||||
                              onChanged: (value) { 
 | 
					                              onChanged: (value) { 
 | 
				
			||||||
                                Future.delayed(const Duration(seconds: 100), () {
 | 
					                                Future.delayed(const Duration(seconds: 100), () {
 | 
				
			||||||
                                  if (widget.item.scheduler["cron"] == value) { 
 | 
					                                  if (widget.schedule.cron  == value) { 
 | 
				
			||||||
                                    widget.item.saveDash(widget.item.id);  
 | 
					                                    widget.item.saveDash(widget.item.id, context);  
 | 
				
			||||||
                                  }
 | 
					                                  }
 | 
				
			||||||
                                });
 | 
					                                });
 | 
				
			||||||
                                widget.item.scheduler["cron"] = value;
 | 
					                                widget.schedule.cron = value;
 | 
				
			||||||
                              },
 | 
					                              },
 | 
				
			||||||
                              onSaved: (value) { 
 | 
					                              onSaved: (value) { 
 | 
				
			||||||
                                if (value != null) {
 | 
					                                if (value != null) {
 | 
				
			||||||
                                  widget.item.scheduler["cron"] = value;
 | 
					                                  widget.schedule.cron = value;
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                              },
 | 
					                              },
 | 
				
			||||||
                              validator: (value) { 
 | 
					                              validator: (value) { 
 | 
				
			||||||
@@ -456,49 +486,58 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
 | 
				
			|||||||
        width: 200,
 | 
					        width: 200,
 | 
				
			||||||
        height: 10,
 | 
					        height: 10,
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
      Tooltip( message: "check booking",
 | 
					      Tooltip( message: "check booking", child: InkWell( mouseCursor: SystemMouseCursors.click, 
 | 
				
			||||||
                              child: InkWell( mouseCursor: SystemMouseCursors.click, 
 | 
					        onTap: () { PermsService.getPerm(Perms.WORKFLOW_BOOKING) ? checkBooking(formKeys, null) : null;
 | 
				
			||||||
                              onTap: () {
 | 
					        }, child: Container( margin: const EdgeInsets.only(bottom: 5, left: 10, right: 10),
 | 
				
			||||||
                                PermsService.getPerm(Perms.WORKFLOW_BOOKING) ? checkBooking(formKeys, null) : null;
 | 
					                              decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), 
 | 
				
			||||||
                              }, child: Container( margin: const EdgeInsets.only(bottom: 5, left: 10, right: 10),
 | 
					                                  border: Border.all(color: widget.booking == null ? (
 | 
				
			||||||
                                decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), 
 | 
					 | 
				
			||||||
                                  border: Border.all(color: widget.booking == null && !dash.scheduleActive ? (
 | 
					 | 
				
			||||||
                                    PermsService.getPerm(Perms.WORKFLOW_BOOKING) && PermsService.getPerm(Perms.WORKFLOW_EDIT) ? Colors.black : Colors.grey) : (
 | 
					                                    PermsService.getPerm(Perms.WORKFLOW_BOOKING) && PermsService.getPerm(Perms.WORKFLOW_EDIT) ? Colors.black : Colors.grey) : (
 | 
				
			||||||
                                      widget.booking == true || dash.scheduleActive  ? Colors.green : redColor), width: 1)),
 | 
					                                      widget.booking == true  ? Colors.green : redColor), width: 1)),
 | 
				
			||||||
                                width: 200, height: 30,
 | 
					                                width: 200, height: 30,
 | 
				
			||||||
                                child: Icon(
 | 
					                                child: Icon( Icons.verified_outlined, 
 | 
				
			||||||
                                  Icons.verified_outlined, 
 | 
					                                  color: widget.booking == null ? Colors.black :  (widget.booking == true ? Colors.green : redColor)),
 | 
				
			||||||
                                  color: widget.booking == null && !dash.scheduleActive ? Colors.black :  (widget.booking == true || dash.scheduleActive ? Colors.green : redColor)),
 | 
					 | 
				
			||||||
                              ))
 | 
					                              ))
 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
      Tooltip( message: dash.scheduleActive ? "unbook" : "book",
 | 
					      Tooltip( message: "book", child: InkWell( mouseCursor: SystemMouseCursors.click, 
 | 
				
			||||||
                              child: InkWell( mouseCursor: SystemMouseCursors.click, 
 | 
					 | 
				
			||||||
                              onTap: () {
 | 
					                              onTap: () {
 | 
				
			||||||
                                PermsService.getPerm(Perms.WORKFLOW_BOOKING) && PermsService.getPerm(Perms.WORKFLOW_EDIT) ? (dash.scheduleActive ? setState(() {  save(formKeys); }) : checkBooking(formKeys,  save)) : null;
 | 
					                                PermsService.getPerm(Perms.WORKFLOW_BOOKING) && PermsService.getPerm(Perms.WORKFLOW_EDIT) ? setState(() {  save(formKeys); }) : null;
 | 
				
			||||||
                              }, child: Container( margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
 | 
					                              }, child: Container( margin: const EdgeInsets.only(top: 5, bottom: 10, left: 10, right: 10),
 | 
				
			||||||
                                decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), 
 | 
					                                decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), 
 | 
				
			||||||
                                  border: Border.all(color: dash.scheduleActive ? Colors.green : ( PermsService.getPerm(Perms.WORKFLOW_BOOKING) ?Colors.black : Colors.grey ))),
 | 
					                                  border: Border.all(color: dash.error != null ? Colors.red : ( PermsService.getPerm(Perms.WORKFLOW_BOOKING) ?(widget.valid ? Colors.green : Colors.black) : Colors.grey ))),
 | 
				
			||||||
                                width: 200, height: 30,
 | 
					                                width: 200, height: 30,
 | 
				
			||||||
                                child: Icon(
 | 
					                                child: Icon(Icons.schedule_send, color: dash.error != null ? Colors.red : (widget.valid ? Colors.green : Colors.black)),
 | 
				
			||||||
                                  dash.scheduleActive ? Icons.cancel_schedule_send : Icons.schedule_send, color: dash.scheduleActive ? Colors.green : Colors.black),
 | 
					 | 
				
			||||||
                              ))
 | 
					                              ))
 | 
				
			||||||
                            ),
 | 
					                            ),
 | 
				
			||||||
 | 
					      Column( children: [
 | 
				
			||||||
 | 
					        Container(
 | 
				
			||||||
 | 
					          height: 15, width: 200,
 | 
				
			||||||
 | 
					          decoration: const BoxDecoration(border: Border(top: BorderSide(color: Colors.grey))),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 10),
 | 
				
			||||||
 | 
					          child:Text( textAlign: TextAlign.center, overflow: TextOverflow.ellipsis,
 | 
				
			||||||
 | 
					            style: const TextStyle(fontSize: 13, color: Colors.grey ),
 | 
				
			||||||
 | 
					            "Was booked ${widget.scheduleBeforeCount} times.")),
 | 
				
			||||||
 | 
					        Container( alignment: Alignment.center, padding: const EdgeInsets.only(left: 10, right: 10, bottom: 15),
 | 
				
			||||||
 | 
					          child:Text( textAlign: TextAlign.center, overflow: TextOverflow.ellipsis,
 | 
				
			||||||
 | 
					            style: const TextStyle(fontSize: 13, color: Colors.grey ),
 | 
				
			||||||
 | 
					            "Is booked ${widget.scheduleFutureCount} times.")),
 | 
				
			||||||
 | 
					      ]),
 | 
				
			||||||
      widget.item.info["shared"] != null && (widget.item.info["shared"] as List<dynamic>).isNotEmpty ? Column( children: [
 | 
					      widget.item.info["shared"] != null && (widget.item.info["shared"] as List<dynamic>).isNotEmpty ? Column( children: [
 | 
				
			||||||
        Container(
 | 
					        Container(
 | 
				
			||||||
          height: 30,
 | 
					          height: 30,
 | 
				
			||||||
          width: 200,
 | 
					          width: 200,
 | 
				
			||||||
          decoration: const BoxDecoration(border: Border(top: BorderSide(color: Colors.grey))),
 | 
					          decoration: const BoxDecoration(border: Border(top: BorderSide(color: Colors.grey))),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
        Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 10),
 | 
					        Container( alignment: Alignment.center,
 | 
				
			||||||
          child:Text( textAlign: TextAlign.center, overflow: TextOverflow.ellipsis,
 | 
					          child:Text( overflow: TextOverflow.ellipsis,
 | 
				
			||||||
            style: const TextStyle(fontSize: 14, color: Colors.black, fontWeight: FontWeight.bold),
 | 
					            style: const TextStyle(fontSize: 14, color: Colors.black, fontWeight: FontWeight.bold),
 | 
				
			||||||
            "Workflow is shared in ${(widget.item.info["shared"] as List<dynamic>).length} workspace(s)")),
 | 
					            "Is shared ${(widget.item.info["shared"] as List<dynamic>).length} time(s).")),
 | 
				
			||||||
        ...(widget.item.info["shared"] as List<dynamic>).where( (e) => CollaborativeAreaLocal.getCollaborativeArea(e) != null 
 | 
					        ...(widget.item.info["shared"] as List<dynamic>).where( (e) => CollaborativeAreaLocal.getCollaborativeArea(e) != null 
 | 
				
			||||||
        ).map((e) {
 | 
					        ).map((e) {
 | 
				
			||||||
          var sw = CollaborativeAreaLocal.getCollaborativeArea(e);
 | 
					          var sw = CollaborativeAreaLocal.getCollaborativeArea(e);
 | 
				
			||||||
          return Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
 | 
					          return Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
 | 
				
			||||||
            child: Row(  children: [ 
 | 
					            child: Row(  children: [ 
 | 
				
			||||||
              const Padding(padding: EdgeInsets.only(right: 10), child: Icon(Icons.work, color: Colors.grey, size: 15)),
 | 
					              const Padding(padding: EdgeInsets.only( left: 10, right: 10), child: Icon(Icons.work, color: Colors.grey, size: 15)),
 | 
				
			||||||
              Text(style: const TextStyle(fontSize: 12, color: Colors.grey),
 | 
					              Text(style: const TextStyle(fontSize: 12, color: Colors.grey),
 | 
				
			||||||
              "Workspace: ${sw != null && sw.name != null ? 
 | 
					              "Workspace: ${sw != null && sw.name != null ? 
 | 
				
			||||||
              "${sw.name!.substring(0, sw.name!.length > 15 ? 12 : sw.name!.length)}${sw.name!.length > 15 ? "..." : ""}" : ""}") ]));
 | 
					              "${sw.name!.substring(0, sw.name!.length > 15 ? 12 : sw.name!.length)}${sw.name!.length > 15 ? "..." : ""}" : ""}") ]));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,18 +0,0 @@
 | 
				
			|||||||
import 'package:flutter/material.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/models/search.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/widgets/forms/web_reference_forms.dart';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class StorageFormsWidget extends StatefulWidget {
 | 
					 | 
				
			||||||
  StorageItem item;
 | 
					 | 
				
			||||||
  String purpose = ""; 
 | 
					 | 
				
			||||||
  Function validate = () {};
 | 
					 | 
				
			||||||
  StorageFormsWidget ({ super.key, required this.item });
 | 
					 | 
				
			||||||
  @override StorageFormsWidgetState createState() => StorageFormsWidgetState();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
class StorageFormsWidgetState extends State<StorageFormsWidget> {
 | 
					 | 
				
			||||||
  @override Widget build(BuildContext context) {
 | 
					 | 
				
			||||||
    return Column( children: [
 | 
					 | 
				
			||||||
      WebReferenceFormsWidget(item: widget.item),
 | 
					 | 
				
			||||||
    ]);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										154
									
								
								lib/widgets/forms/storage_processing_link_forms.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								lib/widgets/forms/storage_processing_link_forms.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,154 @@
 | 
				
			|||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_advanced_switch/flutter_advanced_switch.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/main.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/models/resources/resources.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_flow_chart/flutter_flow_chart.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/models/workflow.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/widgets/inputs/sub_text_input.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ignore: must_be_immutable
 | 
				
			||||||
 | 
					class StorageProcessingLinkFormsWidget extends StatefulWidget {
 | 
				
			||||||
 | 
					  Dashboard dash;
 | 
				
			||||||
 | 
					  ArrowPainter item;
 | 
				
			||||||
 | 
					  bool readOnly = false;
 | 
				
			||||||
 | 
					  StorageProcessingLinkFormsWidget ({ super.key, required this.dash, required this.item, this.readOnly = false });
 | 
				
			||||||
 | 
					  @override StorageProcessingLinkFormsWidgetState createState() => StorageProcessingLinkFormsWidgetState();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class StorageProcessingLinkFormsWidgetState extends State<StorageProcessingLinkFormsWidget> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  List<Param> getParams(String fromID, String toID) {
 | 
				
			||||||
 | 
					    List<Param> arr = [];
 | 
				
			||||||
 | 
					    var els = widget.dash.elements.where( (e) => fromID.contains(e.id) || toID.contains(e.id));
 | 
				
			||||||
 | 
					    for (var element in els) {
 | 
				
			||||||
 | 
					      var g = GraphItem();
 | 
				
			||||||
 | 
					      g.fromDashboard(element.serialize());
 | 
				
			||||||
 | 
					      var e = g.getElement();
 | 
				
			||||||
 | 
					      if (e == null) { continue; }
 | 
				
			||||||
 | 
					      if (e.getSelectedInstance() != null) {
 | 
				
			||||||
 | 
					        for (var env in e.getSelectedInstance()!.env) {
 | 
				
			||||||
 | 
					          if (env.name?.contains("LINK") ?? true) { continue; }
 | 
				
			||||||
 | 
					          arr.add(env);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return arr.where( (e) => e.name != null && e.value != null).toList();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    List<Widget> children = [
 | 
				
			||||||
 | 
					      Padding( padding: const EdgeInsets.only(top: 10),
 | 
				
			||||||
 | 
					          child: Text("<ENV VARIABLES>", 
 | 
				
			||||||
 | 
					            style: const TextStyle(fontSize: 13, fontWeight: FontWeight.bold), textAlign: TextAlign.center)),
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					    var params = getParams(widget.item.fromID, widget.item.toID);
 | 
				
			||||||
 | 
					    widget.item.env = params.map( (e) => e.serialize()).toList();
 | 
				
			||||||
 | 
					    for (var param in params) {
 | 
				
			||||||
 | 
					      children.add(SubTextInputWidget(subkey: param.name ?? "", width: 180, empty: false, readOnly: true,
 | 
				
			||||||
 | 
					          change: (value) {}, initialValue: param.value ?? "", copyLabel: true));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    children.add(Container(width: 200, padding: const EdgeInsets.only(top: 10, bottom: 10),
 | 
				
			||||||
 | 
					          decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1)))));
 | 
				
			||||||
 | 
					    List<Widget> inf = [];
 | 
				
			||||||
 | 
					    int count = 0;
 | 
				
			||||||
 | 
					    for(var info in widget.item.infos) {
 | 
				
			||||||
 | 
					      count++;
 | 
				
			||||||
 | 
					      inf.add(Padding( padding: EdgeInsets.only(top: 10, bottom: 5), 
 | 
				
			||||||
 | 
					        child : Row( crossAxisAlignment: CrossAxisAlignment.center, children: [
 | 
				
			||||||
 | 
					            Padding(padding: EdgeInsets.only(left: 10, right: 10), child: Text("N°$count")),
 | 
				
			||||||
 | 
					            Container(width: 140, decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))))
 | 
				
			||||||
 | 
					          ])));
 | 
				
			||||||
 | 
					      for (var key in (info as Map<String, dynamic>).keys) {
 | 
				
			||||||
 | 
					          if (info[key] is bool) {
 | 
				
			||||||
 | 
					            inf.add(AdvancedSwitch(
 | 
				
			||||||
 | 
					              width: 150.0,
 | 
				
			||||||
 | 
					              height: 25.0,
 | 
				
			||||||
 | 
					              initialValue: info[key] as bool? ?? false,
 | 
				
			||||||
 | 
					              enabled: !widget.readOnly,
 | 
				
			||||||
 | 
					              activeChild: Text(key, style: const TextStyle(color: Colors.white)),
 | 
				
			||||||
 | 
					              inactiveChild: Text(key == "write" ? "read" : "no $key", style: const TextStyle(color: Colors.white)),
 | 
				
			||||||
 | 
					              activeColor: Colors.green,
 | 
				
			||||||
 | 
					              inactiveColor: redColor,
 | 
				
			||||||
 | 
					              onChanged: (v) {
 | 
				
			||||||
 | 
					                try { 
 | 
				
			||||||
 | 
					                  info[key] = v;
 | 
				
			||||||
 | 
					                  Future.delayed(const Duration(seconds: 1), () {
 | 
				
			||||||
 | 
					                    for (var a in widget.dash.arrows) {
 | 
				
			||||||
 | 
					                      if (a.fromID == widget.item.fromID && a.toID == widget.item.toID) {
 | 
				
			||||||
 | 
					                        a.infos = widget.item.infos;
 | 
				
			||||||
 | 
					                      }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    widget.dash.saveDash(widget.dash.id, context);
 | 
				
			||||||
 | 
					                  });
 | 
				
			||||||
 | 
					                } catch (e) { /* */ }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					            ));
 | 
				
			||||||
 | 
					          } else if (info[key] is String?) {
 | 
				
			||||||
 | 
					            inf.add(SubTextInputWidget(subkey: key, width: 180, empty: false, change: (v) {
 | 
				
			||||||
 | 
					              try {
 | 
				
			||||||
 | 
					                info[key] = v;
 | 
				
			||||||
 | 
					                Future.delayed(const Duration(seconds: 1), () {
 | 
				
			||||||
 | 
					                  if (info[key] != v) { return; }
 | 
				
			||||||
 | 
					                  for (var a in widget.dash.arrows) {
 | 
				
			||||||
 | 
					                    if (a.fromID == widget.item.fromID && a.toID == widget.item.toID) {
 | 
				
			||||||
 | 
					                      a.infos = widget.item.infos;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                  widget.dash.saveDash(widget.dash.id, context);
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					              } catch (e) {
 | 
				
			||||||
 | 
					                print(e);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					            }, initialValue: "${info[key] ?? ""}", readOnly: false, noLabel: false));
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return SizedBox( height: getHeight(context) - 230, child: SingleChildScrollView( child: Column(children: [
 | 
				
			||||||
 | 
					      ...children,
 | 
				
			||||||
 | 
					      Row( mainAxisAlignment: MainAxisAlignment.center, children: [
 | 
				
			||||||
 | 
					              InkWell( onTap: () {
 | 
				
			||||||
 | 
					                  widget.item.infos.add({
 | 
				
			||||||
 | 
					                            "write": false,
 | 
				
			||||||
 | 
					                            "source": null,
 | 
				
			||||||
 | 
					                            "destination": null,
 | 
				
			||||||
 | 
					                            "filename": null,
 | 
				
			||||||
 | 
					                  });
 | 
				
			||||||
 | 
					                  setState(() {
 | 
				
			||||||
 | 
					                    widget.dash.saveDash(widget.dash.id, context);
 | 
				
			||||||
 | 
					                  });
 | 
				
			||||||
 | 
					                }, child: Container( margin: const EdgeInsets.only(top: 10),
 | 
				
			||||||
 | 
					                    decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), 
 | 
				
			||||||
 | 
					                    border: Border.all(color: Colors.grey, width: 1)),
 | 
				
			||||||
 | 
					                    width: 125, height: 30,
 | 
				
			||||||
 | 
					                    child: Row( mainAxisAlignment: MainAxisAlignment.center,
 | 
				
			||||||
 | 
					                      children: [ Padding( padding: EdgeInsets.only(right: 5), child: Icon(Icons.add, color: Colors.black,)), 
 | 
				
			||||||
 | 
					                      Text("link infos",
 | 
				
			||||||
 | 
					                        style: TextStyle( color: Colors.black))]),
 | 
				
			||||||
 | 
					                  ),  
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              InkWell( onTap: () {
 | 
				
			||||||
 | 
					                      if (widget.item.infos.isEmpty) { return; }
 | 
				
			||||||
 | 
					                      setState(() { 
 | 
				
			||||||
 | 
					                        widget.item.infos.removeLast();
 | 
				
			||||||
 | 
					                        widget.dash.saveDash(widget.dash.id, context); 
 | 
				
			||||||
 | 
					                      });
 | 
				
			||||||
 | 
					                    }, child:
 | 
				
			||||||
 | 
					                    Container( margin: const EdgeInsets.only(left: 5, top: 10),
 | 
				
			||||||
 | 
					                      decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), 
 | 
				
			||||||
 | 
					                        border: Border.all(color: widget.item.infos.isEmpty ? Colors.grey : Colors.black , width: 1)),
 | 
				
			||||||
 | 
					                      width: 50, height: 30,
 | 
				
			||||||
 | 
					                      child: Row( mainAxisAlignment: MainAxisAlignment.center,
 | 
				
			||||||
 | 
					                        children: [ Icon( Icons.delete, size: 18,
 | 
				
			||||||
 | 
					                          color: widget.item.infos.isEmpty ? Colors.grey : Colors.black ) ]),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                  ), 
 | 
				
			||||||
 | 
					            ]),
 | 
				
			||||||
 | 
					          ...inf
 | 
				
			||||||
 | 
					        ] ) ));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										174
									
								
								lib/widgets/forms/sub_add_forms.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								lib/widgets/forms/sub_add_forms.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,174 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_flow_chart/flutter_flow_chart.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/models/resources/resources.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/widgets/forms/sub_keys_forms.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/widgets/inputs/sub_text_input.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ignore: must_be_immutable
 | 
				
			||||||
 | 
					class SubAddFormsWidget extends StatefulWidget {
 | 
				
			||||||
 | 
					  bool readOnly;
 | 
				
			||||||
 | 
					  SubMapFormsType type;
 | 
				
			||||||
 | 
					  String elementID = "";
 | 
				
			||||||
 | 
					  AbstractItem item;
 | 
				
			||||||
 | 
					  Dashboard dash; 
 | 
				
			||||||
 | 
					  bool empty = false;
 | 
				
			||||||
 | 
					  List<Param> forms = [];
 | 
				
			||||||
 | 
					  SubAddFormsWidget ({ super.key, required this.dash, this.readOnly = false,
 | 
				
			||||||
 | 
					    this.empty = false, required this.item, required this.elementID,
 | 
				
			||||||
 | 
					    required this.type });
 | 
				
			||||||
 | 
					  @override SubAddFormsWidgetState createState() => SubAddFormsWidgetState();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					class SubAddFormsWidgetState extends State<SubAddFormsWidget> {
 | 
				
			||||||
 | 
					  Param? addedparam;
 | 
				
			||||||
 | 
					  @override Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    AbstractInstance instance = widget.item.getSelectedInstance()!;
 | 
				
			||||||
 | 
					    var f = (widget.type == SubMapFormsType.INPUT ? instance.inputs : ( 
 | 
				
			||||||
 | 
					      widget.type == SubMapFormsType.OUTPUT ? instance.outputs : instance.env)).where( (e) => !e.readOnly).toList();
 | 
				
			||||||
 | 
					    widget.forms = f;
 | 
				
			||||||
 | 
					    if (addedparam != null) {
 | 
				
			||||||
 | 
					      widget.forms.add(addedparam!);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    List<Widget> children = [];
 | 
				
			||||||
 | 
					    for (var param in widget.forms) {
 | 
				
			||||||
 | 
					      children.add(Row( mainAxisAlignment: MainAxisAlignment.center, children: [
 | 
				
			||||||
 | 
					        SubTextInputWidget(subkey: "key", readOnly: widget.readOnly,
 | 
				
			||||||
 | 
					          initialValue: param.name, width: 81, empty: widget.empty, 
 | 
				
			||||||
 | 
					          change: (value) { 
 | 
				
			||||||
 | 
					            setState(() {
 | 
				
			||||||
 | 
					              param.name = value;
 | 
				
			||||||
 | 
					              param.attr = value;
 | 
				
			||||||
 | 
					              if (addedparam?.value != null && addedparam?.name != null) {
 | 
				
			||||||
 | 
					                addedparam = null;
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              var sel = widget.item.getSelectedInstance();
 | 
				
			||||||
 | 
					              if (sel != null) {
 | 
				
			||||||
 | 
					                if (widget.type == SubMapFormsType.INPUT) { sel.inputs = [ 
 | 
				
			||||||
 | 
					                    ...sel.inputs.where( (e) => e.readOnly),
 | 
				
			||||||
 | 
					                    ...widget.forms.where((e) => e.name != null && e.value != null)
 | 
				
			||||||
 | 
					                  ];
 | 
				
			||||||
 | 
					                } else if (widget.type == SubMapFormsType.OUTPUT) {  
 | 
				
			||||||
 | 
					                  sel.outputs = [
 | 
				
			||||||
 | 
					                    ...sel.outputs.where( (e) => e.readOnly),
 | 
				
			||||||
 | 
					                    ...widget.forms.where((e) => e.name != null && e.value != null)
 | 
				
			||||||
 | 
					                  ];
 | 
				
			||||||
 | 
					                } else { 
 | 
				
			||||||
 | 
					                  sel.env = [
 | 
				
			||||||
 | 
					                    ...sel.env.where( (e) => e.readOnly),
 | 
				
			||||||
 | 
					                    ...widget.forms.where((e) => e.name != null && e.value != null)
 | 
				
			||||||
 | 
					                  ]; 
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Future.delayed(const Duration(milliseconds: 100), () {
 | 
				
			||||||
 | 
					              if (param.name == value) {
 | 
				
			||||||
 | 
					                widget.dash.saveDash(widget.dash.id, context);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            var el = widget.dash.getElement(widget.elementID);
 | 
				
			||||||
 | 
					            el!.element = widget.item as dynamic;
 | 
				
			||||||
 | 
					            setState(() {});
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        }),
 | 
				
			||||||
 | 
					        const Padding(padding: EdgeInsets.only(left: 5, right: 5, top: 15), child: Text("=", textAlign: TextAlign.center,)),
 | 
				
			||||||
 | 
					        SubTextInputWidget(subkey: "value", initialValue: param.value, width: 81, empty: widget.empty, 
 | 
				
			||||||
 | 
					          readOnly: widget.readOnly, change: (value) { 
 | 
				
			||||||
 | 
					            param.value = value;
 | 
				
			||||||
 | 
					            if (addedparam?.value != null && addedparam?.name != null) {
 | 
				
			||||||
 | 
					              addedparam = null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            var sel = widget.item.getSelectedInstance();
 | 
				
			||||||
 | 
					            if (sel != null) {
 | 
				
			||||||
 | 
					                if (widget.type == SubMapFormsType.INPUT) { sel.inputs = [ 
 | 
				
			||||||
 | 
					                    ...sel.inputs.where( (e) => e.readOnly),
 | 
				
			||||||
 | 
					                    ...widget.forms.where((e) => e.name != null && e.value != null)
 | 
				
			||||||
 | 
					                  ];
 | 
				
			||||||
 | 
					                } else if (widget.type == SubMapFormsType.OUTPUT) {  
 | 
				
			||||||
 | 
					                  sel.outputs = [
 | 
				
			||||||
 | 
					                    ...sel.outputs.where( (e) => e.readOnly),
 | 
				
			||||||
 | 
					                    ...widget.forms.where((e) => e.name != null && e.value != null)
 | 
				
			||||||
 | 
					                  ];
 | 
				
			||||||
 | 
					                } else { 
 | 
				
			||||||
 | 
					                  sel.env = [
 | 
				
			||||||
 | 
					                    ...sel.env.where( (e) => e.readOnly ),
 | 
				
			||||||
 | 
					                    ...widget.forms.where((e) => e.name != null && e.value != null)
 | 
				
			||||||
 | 
					                  ]; 
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            var el = widget.dash.getElement(widget.elementID);
 | 
				
			||||||
 | 
					            el!.element = widget.item as dynamic;
 | 
				
			||||||
 | 
					            setState(() {});
 | 
				
			||||||
 | 
					            Future.delayed(const Duration(milliseconds: 100), () {
 | 
				
			||||||
 | 
					              if (param.value == value) {
 | 
				
			||||||
 | 
					                widget.dash.saveDash(widget.dash.id, context);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }),     
 | 
				
			||||||
 | 
					      ]));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return Column( crossAxisAlignment: CrossAxisAlignment.center, children : [
 | 
				
			||||||
 | 
					      widget.readOnly ? Container() : Row( mainAxisAlignment: MainAxisAlignment.center, children: [
 | 
				
			||||||
 | 
					              InkWell( onTap: () {
 | 
				
			||||||
 | 
					                  if (widget.forms.isNotEmpty && (widget.forms[widget.forms.length - 1].name == null
 | 
				
			||||||
 | 
					                  || widget.forms[widget.forms.length - 1].value == null)) { return;}
 | 
				
			||||||
 | 
					                  widget.forms.add(Param(readOnly: false));
 | 
				
			||||||
 | 
					                  addedparam = widget.forms.last;
 | 
				
			||||||
 | 
					                  var el = widget.dash.getElement(widget.elementID);
 | 
				
			||||||
 | 
					                  el!.element = widget.item as dynamic;
 | 
				
			||||||
 | 
					                  setState(() {});
 | 
				
			||||||
 | 
					                }, child: Container( margin: const EdgeInsets.only(top: 10),
 | 
				
			||||||
 | 
					                    decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), 
 | 
				
			||||||
 | 
					                    border: Border.all(color: widget.forms.isNotEmpty && (widget.forms[widget.forms.length - 1].name == null
 | 
				
			||||||
 | 
					                  || widget.forms[widget.forms.length - 1].value == null) ? Colors.grey : Colors.grey, width: 1)),
 | 
				
			||||||
 | 
					                    width: 125, height: 30,
 | 
				
			||||||
 | 
					                    child: Row( mainAxisAlignment: MainAxisAlignment.center,
 | 
				
			||||||
 | 
					                      children: [ Padding( padding: EdgeInsets.only(right: 5), child: Icon(Icons.add, color: widget.forms.isNotEmpty && (widget.forms[widget.forms.length - 1].name == null
 | 
				
			||||||
 | 
					                  || widget.forms[widget.forms.length - 1].value == null) ? Colors.grey : Colors.black,)), 
 | 
				
			||||||
 | 
					                      Text(widget.type == SubMapFormsType.ENV ? "env" : (widget.type == SubMapFormsType.INPUT ? "input" : "output"),
 | 
				
			||||||
 | 
					                        style: TextStyle( color: widget.forms.isNotEmpty && (widget.forms[widget.forms.length - 1].name == null
 | 
				
			||||||
 | 
					                  || widget.forms[widget.forms.length - 1].value == null) ? Colors.grey : Colors.black))]),
 | 
				
			||||||
 | 
					                  ),  
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              InkWell( onTap: () {
 | 
				
			||||||
 | 
					                      if (addedparam != null) {
 | 
				
			||||||
 | 
					                        addedparam = null;
 | 
				
			||||||
 | 
					                        return setState(() {});
 | 
				
			||||||
 | 
					                      }
 | 
				
			||||||
 | 
					                      if (widget.forms.isEmpty) { return; }
 | 
				
			||||||
 | 
					                      widget.forms.sublist(0, widget.forms.length - 1);
 | 
				
			||||||
 | 
					                      var el = widget.dash.getElement(widget.elementID);
 | 
				
			||||||
 | 
					                      var sel = widget.item.getSelectedInstance();
 | 
				
			||||||
 | 
					                      if (sel != null) {
 | 
				
			||||||
 | 
					                          widget.forms.removeLast();
 | 
				
			||||||
 | 
					                          if (widget.type == SubMapFormsType.INPUT) { sel.inputs = [ 
 | 
				
			||||||
 | 
					                              ...sel.inputs.where( (e) => e.readOnly),
 | 
				
			||||||
 | 
					                              ...widget.forms.where((e) => e.name != null && e.value != null)
 | 
				
			||||||
 | 
					                            ];
 | 
				
			||||||
 | 
					                          } else if (widget.type == SubMapFormsType.OUTPUT) {  
 | 
				
			||||||
 | 
					                            sel.outputs = [
 | 
				
			||||||
 | 
					                              ...sel.outputs.where( (e) => e.readOnly),
 | 
				
			||||||
 | 
					                              ...widget.forms.where((e) => e.name != null && e.value != null)
 | 
				
			||||||
 | 
					                            ];
 | 
				
			||||||
 | 
					                          } else { 
 | 
				
			||||||
 | 
					                            sel.env = [
 | 
				
			||||||
 | 
					                              ...sel.env.where( (e) => e.readOnly),
 | 
				
			||||||
 | 
					                              ...widget.forms.where((e) => e.name != null && e.value != null)
 | 
				
			||||||
 | 
					                            ]; 
 | 
				
			||||||
 | 
					                          }
 | 
				
			||||||
 | 
					                      }
 | 
				
			||||||
 | 
					                      el!.element = widget.item as dynamic;
 | 
				
			||||||
 | 
					                      setState(() { widget.dash.saveDash(widget.dash.id, context); });
 | 
				
			||||||
 | 
					                    }, child:
 | 
				
			||||||
 | 
					                    Container( margin: const EdgeInsets.only(left: 5, top: 10),
 | 
				
			||||||
 | 
					                      decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), 
 | 
				
			||||||
 | 
					                        border: Border.all(color: widget.forms.isEmpty ? Colors.grey : Colors.black , width: 1)),
 | 
				
			||||||
 | 
					                      width: 50, height: 30,
 | 
				
			||||||
 | 
					                      child: Row( mainAxisAlignment: MainAxisAlignment.center,
 | 
				
			||||||
 | 
					                        children: [ Icon( Icons.delete, size: 18,
 | 
				
			||||||
 | 
					                          color: widget.forms.isEmpty ? Colors.grey : Colors.black ) ]),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                  ), 
 | 
				
			||||||
 | 
					            ]),
 | 
				
			||||||
 | 
					      ...children
 | 
				
			||||||
 | 
					    ]); 
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,9 +1,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/models/resources/processing.dart';
 | 
				
			||||||
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
 | 
					import 'package:flutter_flow_chart/flutter_flow_chart.dart';
 | 
				
			||||||
import 'package:oc_front/models/search.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/widgets/inputs/sub_text_input.dart';
 | 
					import 'package:oc_front/widgets/inputs/sub_text_input.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ignore: must_be_immutable
 | 
				
			||||||
class SubExposeFormsWidget extends StatefulWidget {
 | 
					class SubExposeFormsWidget extends StatefulWidget {
 | 
				
			||||||
  bool readOnly;
 | 
					  bool readOnly;
 | 
				
			||||||
  Expose item;
 | 
					  Expose item;
 | 
				
			||||||
@@ -29,7 +30,7 @@ class SubExposeFormsWidgetState extends State<SubExposeFormsWidget> {
 | 
				
			|||||||
                    widget.item.port = int.parse(value);
 | 
					                    widget.item.port = int.parse(value);
 | 
				
			||||||
                    Future.delayed(const Duration(seconds: 2), () {
 | 
					                    Future.delayed(const Duration(seconds: 2), () {
 | 
				
			||||||
                      if (widget.item.port == int.parse(value) && int.parse(value) != 0) {
 | 
					                      if (widget.item.port == int.parse(value) && int.parse(value) != 0) {
 | 
				
			||||||
                        widget.dash.saveDash(widget.dash.id);
 | 
					                        widget.dash.saveDash(widget.dash.id, context);
 | 
				
			||||||
                      }
 | 
					                      }
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                  } catch (e) {  widget.item.port = null; }
 | 
					                  } catch (e) {  widget.item.port = null; }
 | 
				
			||||||
@@ -44,7 +45,7 @@ class SubExposeFormsWidgetState extends State<SubExposeFormsWidget> {
 | 
				
			|||||||
                    widget.item.PAT = int.parse(value);
 | 
					                    widget.item.PAT = int.parse(value);
 | 
				
			||||||
                    Future.delayed(const Duration(seconds: 2), () {
 | 
					                    Future.delayed(const Duration(seconds: 2), () {
 | 
				
			||||||
                      if (widget.item.PAT == int.parse(value) && int.parse(value) != 0) {
 | 
					                      if (widget.item.PAT == int.parse(value) && int.parse(value) != 0) {
 | 
				
			||||||
                        widget.dash.saveDash(widget.dash.id);
 | 
					                        widget.dash.saveDash(widget.dash.id, context);
 | 
				
			||||||
                      }
 | 
					                      }
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                  } catch (e) { widget.item.PAT = null;  }
 | 
					                  } catch (e) { widget.item.PAT = null;  }
 | 
				
			||||||
@@ -57,7 +58,7 @@ class SubExposeFormsWidgetState extends State<SubExposeFormsWidget> {
 | 
				
			|||||||
                  try {
 | 
					                  try {
 | 
				
			||||||
                    widget.item.path = value;
 | 
					                    widget.item.path = value;
 | 
				
			||||||
                    Future.delayed(const Duration(seconds: 2), () {
 | 
					                    Future.delayed(const Duration(seconds: 2), () {
 | 
				
			||||||
                      if (widget.item.path == value) {  widget.dash.saveDash(widget.dash.id); }
 | 
					                      if (widget.item.path == value) {  widget.dash.saveDash(widget.dash.id, context); }
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                  } catch (e) { widget.item.path = null;  }
 | 
					                  } catch (e) { widget.item.path = null;  }
 | 
				
			||||||
                  var el = widget.dash.getElement(widget.elementID);
 | 
					                  var el = widget.dash.getElement(widget.elementID);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,62 +1,97 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_advanced_switch/flutter_advanced_switch.dart';
 | 
				
			||||||
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
 | 
					import 'package:flutter_flow_chart/flutter_flow_chart.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/main.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/models/resources/resources.dart';
 | 
				
			||||||
import 'package:oc_front/models/workflow.dart';
 | 
					import 'package:oc_front/models/workflow.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/widgets/forms/sub_add_forms.dart';
 | 
				
			||||||
import 'package:oc_front/widgets/inputs/sub_text_input.dart';
 | 
					import 'package:oc_front/widgets/inputs/sub_text_input.dart';
 | 
				
			||||||
 | 
					enum SubMapFormsType { 
 | 
				
			||||||
 | 
					  ENV, 
 | 
				
			||||||
 | 
					  INPUT,
 | 
				
			||||||
 | 
					  OUTPUT 
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// ignore: must_be_immutable
 | 
				
			||||||
class SubKeysMapFormsWidget extends StatefulWidget {
 | 
					class SubKeysMapFormsWidget extends StatefulWidget {
 | 
				
			||||||
  bool readOnly = false;
 | 
					  bool readOnly = false;
 | 
				
			||||||
  FlowData item;
 | 
					  AbstractItem item;
 | 
				
			||||||
  Dashboard dash; 
 | 
					  Dashboard dash; 
 | 
				
			||||||
  String varKey = "";
 | 
					 | 
				
			||||||
  bool empty = false;
 | 
					  bool empty = false;
 | 
				
			||||||
  bool isInput = true;
 | 
					  SubMapFormsType type;
 | 
				
			||||||
  String elementID = "";
 | 
					  String elementID = "";
 | 
				
			||||||
  String categoryKey = "";
 | 
					  SubKeysMapFormsWidget({ super.key, required this.dash, required this.type, this.readOnly = false,
 | 
				
			||||||
  List<GraphItem> graphItems = [];
 | 
					    this.empty = false, required this.item, required this.elementID });
 | 
				
			||||||
  SubKeysMapFormsWidget({ super.key, required this.dash, required this.isInput, this.readOnly = false,
 | 
					 | 
				
			||||||
    this.empty = false, required this.item, required this.elementID, required this.graphItems,
 | 
					 | 
				
			||||||
    required this.categoryKey, required this.varKey });
 | 
					 | 
				
			||||||
  @override SubKeysMapFormsWidgetState createState() => SubKeysMapFormsWidgetState();
 | 
					  @override SubKeysMapFormsWidgetState createState() => SubKeysMapFormsWidgetState();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
class SubKeysMapFormsWidgetState extends State<SubKeysMapFormsWidget> {
 | 
					class SubKeysMapFormsWidgetState extends State<SubKeysMapFormsWidget> {
 | 
				
			||||||
 | 
					  bool _save = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  List<Param> getParams(String fromID, String toID) {
 | 
				
			||||||
 | 
					    List<Param> arr = [];
 | 
				
			||||||
 | 
					    var els = widget.dash.elements.where( (e) => fromID.contains(e.id) || toID.contains(e.id));
 | 
				
			||||||
 | 
					    for (var element in els) {
 | 
				
			||||||
 | 
					      var g = GraphItem();
 | 
				
			||||||
 | 
					      g.fromDashboard(element.serialize());
 | 
				
			||||||
 | 
					      var e = g.getElement();
 | 
				
			||||||
 | 
					      if (e != null && e.getSelectedInstance() != null) {
 | 
				
			||||||
 | 
					        arr = [...arr, ...e.getSelectedInstance()!.env];
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return arr;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  List<Widget> getInstanceInOutput(AbstractItem? item, SubMapFormsType type) {
 | 
				
			||||||
 | 
					    List<Widget> children = [];
 | 
				
			||||||
 | 
					    if (item == null || item.getSelectedInstance() == null) {
 | 
				
			||||||
 | 
					      return [];
 | 
				
			||||||
 | 
					    } 
 | 
				
			||||||
 | 
					    AbstractInstance instance = item.getSelectedInstance()!;
 | 
				
			||||||
 | 
					    List<Param> params = widget.type == SubMapFormsType.INPUT ? instance.inputs : ( widget.type == SubMapFormsType.OUTPUT ? instance.outputs : instance.env);
 | 
				
			||||||
 | 
					    for ( var param in params) {
 | 
				
			||||||
 | 
					      if (!param.readOnly) { continue; }
 | 
				
			||||||
 | 
					      dynamic env;
 | 
				
			||||||
 | 
					      if (param.value == null && param.attr != null) { 
 | 
				
			||||||
 | 
					        var s = item.serialize();
 | 
				
			||||||
 | 
					        s.addAll(item.getSelectedInstance()?.serialize() ?? {});
 | 
				
			||||||
 | 
					        env = s[param.attr!];
 | 
				
			||||||
 | 
					      } else {  env = param.value; }
 | 
				
			||||||
 | 
					      _save = true;
 | 
				
			||||||
 | 
					      if (env is bool) {
 | 
				
			||||||
 | 
					        var ctrl = ValueNotifier<bool>(env);
 | 
				
			||||||
 | 
					        children.add(AdvancedSwitch(
 | 
				
			||||||
 | 
					              width: 150.0,
 | 
				
			||||||
 | 
					              height: 25.0,
 | 
				
			||||||
 | 
					              controller: ctrl,
 | 
				
			||||||
 | 
					              enabled: false,
 | 
				
			||||||
 | 
					              activeChild: Text(param.name!, style: const TextStyle(color: Colors.white)),
 | 
				
			||||||
 | 
					              inactiveChild: Text("no ${param.name!}", style: const TextStyle(color: Colors.white)),
 | 
				
			||||||
 | 
					              activeColor: Colors.green,
 | 
				
			||||||
 | 
					              inactiveColor: redColor,
 | 
				
			||||||
 | 
					              onChanged: (value) {},
 | 
				
			||||||
 | 
					        ));
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        children.add(SubTextInputWidget( subkey: param.name!, width: 180, empty: false, change: (value) { }, 
 | 
				
			||||||
 | 
					                     initialValue: env, readOnly: true, noLabel: false, copyLabel: true ));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return children;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override Widget build(BuildContext context) {
 | 
					  @override Widget build(BuildContext context) {
 | 
				
			||||||
    List<Widget> children = [];
 | 
					    List<Widget> children = [];
 | 
				
			||||||
 | 
					    var newwidget = getInstanceInOutput(widget.item, widget.type);
 | 
				
			||||||
    bool save = false;
 | 
					    children.add(Column( children : [
 | 
				
			||||||
    for (var graphItem in widget.graphItems) {
 | 
					        Padding( padding: const EdgeInsets.only(top: 10),
 | 
				
			||||||
      int count = 0;
 | 
					          child: Text("<${widget.type == SubMapFormsType.INPUT ? "INPUT" : (widget.type == SubMapFormsType.OUTPUT ? "OUTPUT" : "")} ENV VARIABLES>", 
 | 
				
			||||||
      var el = graphItem.getElement();
 | 
					            style: const TextStyle(fontSize: 13, fontWeight: FontWeight.bold), textAlign: TextAlign.center)),
 | 
				
			||||||
      if (el == null || el.model == null) { continue; }
 | 
					        ...newwidget,
 | 
				
			||||||
      for ( var r in el.model!.refs.keys) {
 | 
					        SubAddFormsWidget(dash: widget.dash, item: widget.item, elementID: widget.elementID, type: widget.type),
 | 
				
			||||||
        var env = widget.item.getVariable(["container", "env"], widget.item.serialize());
 | 
					        Container(width: 200, padding: const EdgeInsets.only(top: 10, bottom: 10),
 | 
				
			||||||
        if (env == null || env is Map<String, dynamic>) { continue; }
 | 
					          decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1)))),
 | 
				
			||||||
        var n = "${el.topic.toUpperCase()}_${el.getName().toUpperCase().replaceAll(" ", "_")}_${r.toUpperCase()}_$count";
 | 
					    ]));
 | 
				
			||||||
        if (env[n] == null) {
 | 
					    if (_save) {
 | 
				
			||||||
          save = true;
 | 
					      widget.dash.saveDash(widget.dash.id, context);
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        env[n]= "{{ ${ widget.isInput ? "in" : "out" }_${graphItem.id}_$r }}";
 | 
					 | 
				
			||||||
        widget.item.setVariable(["container", "env"], env, el.serialize());
 | 
					 | 
				
			||||||
        children.add( Padding(padding: const EdgeInsets.only(bottom: 10), 
 | 
					 | 
				
			||||||
          child: SubTextInputWidget(subkey: n, width: 180, empty: false, change: (value) {}, 
 | 
					 | 
				
			||||||
          initialValue: n, readOnly: true, noLabel: true)));
 | 
					 | 
				
			||||||
        count++;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (save) {
 | 
					    return Column( children : children ); 
 | 
				
			||||||
      widget.dash.saveDash(widget.dash.id);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (children.isEmpty) {
 | 
					 | 
				
			||||||
      return Container();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return Column( children : [
 | 
					 | 
				
			||||||
      Container(width: 200, padding: const EdgeInsets.only(top: 10, bottom: 10),
 | 
					 | 
				
			||||||
        decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1)))),
 | 
					 | 
				
			||||||
      Padding( padding: const EdgeInsets.only(top: 10),
 | 
					 | 
				
			||||||
        child: Text("<${widget.isInput ? "INPUT ENV VARIABLE" : "OUTPUT ENV VARIABLE"}>", style: const TextStyle(fontSize: 13, fontWeight: FontWeight.bold), 
 | 
					 | 
				
			||||||
                    textAlign: TextAlign.center)),
 | 
					 | 
				
			||||||
      Column( children: children),
 | 
					 | 
				
			||||||
    ]); 
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,115 +0,0 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					 | 
				
			||||||
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/widgets/inputs/sub_text_input.dart';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class MapForm {
 | 
					 | 
				
			||||||
  String key = "";
 | 
					 | 
				
			||||||
  String value = "";
 | 
					 | 
				
			||||||
  MapForm({ required this.key, required this.value });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class SubMapFormsWidget extends StatefulWidget {
 | 
					 | 
				
			||||||
  bool readOnly;
 | 
					 | 
				
			||||||
  String categoryKey = "";
 | 
					 | 
				
			||||||
  String varKey = "";
 | 
					 | 
				
			||||||
  String elementID = "";
 | 
					 | 
				
			||||||
  FlowData item;
 | 
					 | 
				
			||||||
  Dashboard dash; 
 | 
					 | 
				
			||||||
  bool empty = false;
 | 
					 | 
				
			||||||
  List<MapForm> forms = [];
 | 
					 | 
				
			||||||
  SubMapFormsWidget ({ super.key, required this.dash, this.readOnly = false,
 | 
					 | 
				
			||||||
    this.empty = false, required this.item, required this.elementID,
 | 
					 | 
				
			||||||
    required this.categoryKey, required this.varKey });
 | 
					 | 
				
			||||||
  @override SubMapFormsWidgetState createState() => SubMapFormsWidgetState();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
class SubMapFormsWidgetState extends State<SubMapFormsWidget> {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  Map<String, dynamic> toMap() {
 | 
					 | 
				
			||||||
    Map<String, dynamic> m = {};
 | 
					 | 
				
			||||||
    for (var form in widget.forms) {
 | 
					 | 
				
			||||||
      m[form.key] = form.value;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return m;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @override Widget build(BuildContext context) {
 | 
					 | 
				
			||||||
    Map<String, dynamic>? m = widget.item.getVariable([widget.categoryKey, widget.varKey], widget.item.serialize());
 | 
					 | 
				
			||||||
    var l = [widget.categoryKey, widget.varKey];
 | 
					 | 
				
			||||||
    List<Widget> children = [];
 | 
					 | 
				
			||||||
    List<String> empty = [];
 | 
					 | 
				
			||||||
    widget.forms = [];
 | 
					 | 
				
			||||||
    var i = 0;
 | 
					 | 
				
			||||||
    for (var key in (m?.keys.toList() ?? empty)) {
 | 
					 | 
				
			||||||
      if (((m![key] as String?)?.contains('{{') ?? false)) {
 | 
					 | 
				
			||||||
        continue;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      widget.forms.add(MapForm(key: key, value: m[key]));
 | 
					 | 
				
			||||||
      children.add(Row( children: [
 | 
					 | 
				
			||||||
        SubTextInputWidget(subkey: "key", readOnly: widget.readOnly,
 | 
					 | 
				
			||||||
          initialValue: key, width: 77.5, empty: widget.empty, 
 | 
					 | 
				
			||||||
          change: (value) { 
 | 
					 | 
				
			||||||
            setState(() {
 | 
					 | 
				
			||||||
              widget.forms[i].key = value;
 | 
					 | 
				
			||||||
              Future.delayed(const Duration(seconds: 2), () {
 | 
					 | 
				
			||||||
                widget.dash.saveDash(widget.dash.id);
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
            var el = widget.dash.getElement(widget.elementID);
 | 
					 | 
				
			||||||
            widget.item = widget.item.deserialize(widget.item.setVariable(l, toMap(), widget.item.serialize())) as dynamic;
 | 
					 | 
				
			||||||
            el!.element = widget.item as dynamic;
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
        }),
 | 
					 | 
				
			||||||
        const Padding(padding: EdgeInsets.only(left: 5, right: 5, top: 15), child: Text("=", textAlign: TextAlign.center,)),
 | 
					 | 
				
			||||||
        SubTextInputWidget(subkey: "value", initialValue: widget.forms[i].value, width: 77.5, empty: widget.empty, 
 | 
					 | 
				
			||||||
          readOnly: widget.readOnly, change: (value) { 
 | 
					 | 
				
			||||||
            Future.delayed(const Duration(seconds: 2), () {
 | 
					 | 
				
			||||||
                widget.dash.saveDash(widget.dash.id);
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
            widget.forms[i].value = value;
 | 
					 | 
				
			||||||
            var el = widget.dash.getElement(widget.elementID);
 | 
					 | 
				
			||||||
            widget.item = widget.item.deserialize(
 | 
					 | 
				
			||||||
              widget.item.setVariable(l, toMap(), widget.item.serialize())) as dynamic;
 | 
					 | 
				
			||||||
            el!.element = widget.item as dynamic;
 | 
					 | 
				
			||||||
        }),     
 | 
					 | 
				
			||||||
      ]));
 | 
					 | 
				
			||||||
      i++;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return Column( children : [
 | 
					 | 
				
			||||||
      Container(width: 200, padding: const EdgeInsets.only(top: 10),
 | 
					 | 
				
			||||||
        decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),),
 | 
					 | 
				
			||||||
      widget.readOnly ? Container() : Row( children: [
 | 
					 | 
				
			||||||
              InkWell( onTap: () {
 | 
					 | 
				
			||||||
                  widget.forms.add(MapForm(key: "", value: ""));
 | 
					 | 
				
			||||||
                  var el = widget.dash.getElement(widget.elementID);
 | 
					 | 
				
			||||||
                  widget.item = widget.item.deserialize(
 | 
					 | 
				
			||||||
                    widget.item.setVariable(l, toMap(), widget.item.serialize())) as dynamic;
 | 
					 | 
				
			||||||
                  el!.element = widget.item as dynamic;
 | 
					 | 
				
			||||||
                  setState(() {});
 | 
					 | 
				
			||||||
                }, child: Container( margin: const EdgeInsets.only(top: 10),
 | 
					 | 
				
			||||||
                    decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.grey, width: 1)),
 | 
					 | 
				
			||||||
                    width: 125, height: 30,
 | 
					 | 
				
			||||||
                    child: Row( mainAxisAlignment: MainAxisAlignment.center,
 | 
					 | 
				
			||||||
                      children: [ const Padding( padding: EdgeInsets.only(right: 5), child: Icon(Icons.add)), Text("add ${widget.varKey} vars")]),
 | 
					 | 
				
			||||||
                  ),  
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
              InkWell( onTap: () {
 | 
					 | 
				
			||||||
                      if (widget.forms.isEmpty) { return;}
 | 
					 | 
				
			||||||
                      widget.forms.sublist(0, widget.forms.length - 1);
 | 
					 | 
				
			||||||
                      widget.item = widget.item.deserialize(
 | 
					 | 
				
			||||||
                        widget.item.setVariable(l, toMap(), widget.item.serialize())) as dynamic;
 | 
					 | 
				
			||||||
                      var el = widget.dash.getElement(widget.elementID);
 | 
					 | 
				
			||||||
                      el!.element = widget.item as dynamic;
 | 
					 | 
				
			||||||
                      setState(() { widget.dash.saveDash(widget.dash.id); });
 | 
					 | 
				
			||||||
                    }, child:
 | 
					 | 
				
			||||||
                    Container( margin: const EdgeInsets.only(left: 5, top: 10),
 | 
					 | 
				
			||||||
                      decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.grey, width: 1)),
 | 
					 | 
				
			||||||
                      width: 45, height: 30,
 | 
					 | 
				
			||||||
                      child: const Row( mainAxisAlignment: MainAxisAlignment.center,
 | 
					 | 
				
			||||||
                        children: [ Icon( Icons.delete, color: Colors.black ) ]),
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                  ), 
 | 
					 | 
				
			||||||
            ]),
 | 
					 | 
				
			||||||
      ...children
 | 
					 | 
				
			||||||
    ]); 
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,23 +0,0 @@
 | 
				
			|||||||
import 'package:flutter/material.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/widgets/inputs/sub_text_input.dart';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class WebReferenceFormsWidget extends StatefulWidget {
 | 
					 | 
				
			||||||
  dynamic item;
 | 
					 | 
				
			||||||
  WebReferenceFormsWidget ({ super.key, required this.item });
 | 
					 | 
				
			||||||
  @override WebReferenceFormsWidgetState createState() => WebReferenceFormsWidgetState();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
class WebReferenceFormsWidgetState extends State<WebReferenceFormsWidget> {
 | 
					 | 
				
			||||||
  @override Widget build(BuildContext context) {
 | 
					 | 
				
			||||||
    return Column( children: [
 | 
					 | 
				
			||||||
      SubTextInputWidget(subkey: "path", width: 180, empty: false, change: (value) { 
 | 
					 | 
				
			||||||
        widget.item.path = value.split(",");
 | 
					 | 
				
			||||||
      }, initialValue: widget.item.path, readOnly: true,),
 | 
					 | 
				
			||||||
      SubTextInputWidget(subkey: "protocol", width: 180, empty: false, change: (value) { 
 | 
					 | 
				
			||||||
        widget.item.protocol = value.split(",");
 | 
					 | 
				
			||||||
      }, initialValue: widget.item.protocol, readOnly: true,),
 | 
					 | 
				
			||||||
      SubTextInputWidget(subkey: "type", width: 180, empty: false, change: (value) { 
 | 
					 | 
				
			||||||
        widget.item.type = value.split(",");
 | 
					 | 
				
			||||||
      }, initialValue: widget.item.type, readOnly: true,),
 | 
					 | 
				
			||||||
    ]);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -94,7 +94,9 @@ class ShallowDropdownInputWidgetState extends State<ShallowDropdownInputWidget>
 | 
				
			|||||||
            child:InkWell( 
 | 
					            child:InkWell( 
 | 
				
			||||||
            mouseCursor: SystemMouseCursors.click,
 | 
					            mouseCursor: SystemMouseCursors.click,
 | 
				
			||||||
            onTap: () async {
 | 
					            onTap: () async {
 | 
				
			||||||
              if (widget.canLoad == null || !widget.canLoad!(widget.current) || widget.load == null || widget.current == null) {
 | 
					              print("load ${widget.current}");
 | 
				
			||||||
 | 
					              if (widget.canLoad == null || !widget.canLoad!(widget.current) 
 | 
				
			||||||
 | 
					              || widget.load == null || widget.current == null) {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
              await widget.load!(widget.current!);
 | 
					              await widget.load!(widget.current!);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,6 +54,8 @@ class ShallowTextInputWidget extends StatefulWidget {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
class ShallowTextInputWidgetState extends State<ShallowTextInputWidget> {
 | 
					class ShallowTextInputWidgetState extends State<ShallowTextInputWidget> {
 | 
				
			||||||
 | 
					  TextEditingController ctrl = TextEditingController();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool validForms() {
 | 
					  bool validForms() {
 | 
				
			||||||
    for (var form in widget.forms) {
 | 
					    for (var form in widget.forms) {
 | 
				
			||||||
      if (!form.validate()) {
 | 
					      if (!form.validate()) {
 | 
				
			||||||
@@ -65,6 +67,7 @@ class ShallowTextInputWidgetState extends State<ShallowTextInputWidget> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  @override Widget build(BuildContext context) {
 | 
					  @override Widget build(BuildContext context) {
 | 
				
			||||||
    var t = widget.type == CollaborativeAreaType.workspace ? "workspace" : (widget.type == CollaborativeAreaType.workflow ? "workflow" : "peer");
 | 
					    var t = widget.type == CollaborativeAreaType.workspace ? "workspace" : (widget.type == CollaborativeAreaType.workflow ? "workflow" : "peer");
 | 
				
			||||||
 | 
					    ctrl.text = widget.current ?? "";
 | 
				
			||||||
    return Row( mainAxisAlignment: widget.alignment, children: [
 | 
					    return Row( mainAxisAlignment: widget.alignment, children: [
 | 
				
			||||||
          Tooltip( message: widget.hint ?? "current $t", child:
 | 
					          Tooltip( message: widget.hint ?? "current $t", child:
 | 
				
			||||||
          Theme(
 | 
					          Theme(
 | 
				
			||||||
@@ -83,7 +86,7 @@ class ShallowTextInputWidgetState extends State<ShallowTextInputWidget> {
 | 
				
			|||||||
                          }
 | 
					                          }
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                      },
 | 
					                      },
 | 
				
			||||||
                      initialValue: widget.current,
 | 
					                      controller: ctrl,
 | 
				
			||||||
                      style: TextStyle(color: widget.color ?? Colors.black, fontSize: 15),
 | 
					                      style: TextStyle(color: widget.color ?? Colors.black, fontSize: 15),
 | 
				
			||||||
                      decoration: InputDecoration( 
 | 
					                      decoration: InputDecoration( 
 | 
				
			||||||
                        filled: true,
 | 
					                        filled: true,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,10 +4,11 @@ class SubDropdownInputWidget extends StatefulWidget {
 | 
				
			|||||||
  String subkey;
 | 
					  String subkey;
 | 
				
			||||||
  double width;
 | 
					  double width;
 | 
				
			||||||
  bool empty;
 | 
					  bool empty;
 | 
				
			||||||
 | 
					  String? initialValue;
 | 
				
			||||||
  List<DropdownMenuItem<String>> dropdownMenuEntries = [];
 | 
					  List<DropdownMenuItem<String>> dropdownMenuEntries = [];
 | 
				
			||||||
  void Function(String?)? change = (value) {};
 | 
					  void Function(String?)? change = (value) {};
 | 
				
			||||||
  SubDropdownInputWidget ({ Key? key, required this.dropdownMenuEntries,
 | 
					  SubDropdownInputWidget ({ super.key, required this.dropdownMenuEntries, this.initialValue,
 | 
				
			||||||
  required this.subkey, required this.width, required this.empty, required this.change }): super(key: key);
 | 
					  required this.subkey, required this.width, required this.empty, required this.change });
 | 
				
			||||||
  @override SubDropdownInputWidgetState createState() => SubDropdownInputWidgetState();
 | 
					  @override SubDropdownInputWidgetState createState() => SubDropdownInputWidgetState();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
class SubDropdownInputWidgetState extends State<SubDropdownInputWidget> {
 | 
					class SubDropdownInputWidgetState extends State<SubDropdownInputWidget> {
 | 
				
			||||||
@@ -17,9 +18,11 @@ class SubDropdownInputWidgetState extends State<SubDropdownInputWidget> {
 | 
				
			|||||||
              child: Container( margin: EdgeInsets.only(top: widget.empty ? 0 : 15),
 | 
					              child: Container( margin: EdgeInsets.only(top: widget.empty ? 0 : 15),
 | 
				
			||||||
                width: widget.width, height: 30,
 | 
					                width: widget.width, height: 30,
 | 
				
			||||||
                child: DropdownButtonFormField( 
 | 
					                child: DropdownButtonFormField( 
 | 
				
			||||||
 | 
					                  isExpanded: true,
 | 
				
			||||||
                  items: widget.dropdownMenuEntries,
 | 
					                  items: widget.dropdownMenuEntries,
 | 
				
			||||||
 | 
					                  value: widget.initialValue,
 | 
				
			||||||
                  onChanged: widget.change,
 | 
					                  onChanged: widget.change,
 | 
				
			||||||
                  style: const TextStyle(fontSize: 12),
 | 
					                  style: const TextStyle(fontSize: 12,color: Colors.black, overflow: TextOverflow.ellipsis),
 | 
				
			||||||
                  decoration: InputDecoration(
 | 
					                  decoration: InputDecoration(
 | 
				
			||||||
                    hintText: "select ${widget.subkey}...",
 | 
					                    hintText: "select ${widget.subkey}...",
 | 
				
			||||||
                    fillColor: Colors.white,
 | 
					                    fillColor: Colors.white,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,9 +10,10 @@ class SubTextInputWidget extends StatefulWidget {
 | 
				
			|||||||
  bool empty;
 | 
					  bool empty;
 | 
				
			||||||
  bool noLabel;
 | 
					  bool noLabel;
 | 
				
			||||||
  bool readOnly = false;
 | 
					  bool readOnly = false;
 | 
				
			||||||
 | 
					  bool copyLabel = false;
 | 
				
			||||||
  void Function(String) change = (value) {};
 | 
					  void Function(String) change = (value) {};
 | 
				
			||||||
  SubTextInputWidget ({ Key? key, 
 | 
					  SubTextInputWidget ({ Key? key, 
 | 
				
			||||||
  required this.subkey, this.readOnly = false, this.noLabel = false,
 | 
					  required this.subkey, this.readOnly = false, this.noLabel = false, this.copyLabel = false,
 | 
				
			||||||
   this.initialValue, required this.width, required this.empty, required this.change }): 
 | 
					   this.initialValue, required this.width, required this.empty, required this.change }): 
 | 
				
			||||||
    super(key: key);
 | 
					    super(key: key);
 | 
				
			||||||
  @override SubTextInputWidgetState createState() => SubTextInputWidgetState();
 | 
					  @override SubTextInputWidgetState createState() => SubTextInputWidgetState();
 | 
				
			||||||
@@ -47,7 +48,7 @@ class SubTextInputWidgetState extends State<SubTextInputWidget> {
 | 
				
			|||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                ))),
 | 
					                ))),
 | 
				
			||||||
      widget.readOnly ? InkWell( onTap: () {
 | 
					      widget.readOnly ? InkWell( onTap: () {
 | 
				
			||||||
                    Clipboard.setData(ClipboardData(text: widget.initialValue!));
 | 
					                    Clipboard.setData(ClipboardData(text: widget.copyLabel ? "\$${widget.subkey}" : widget.initialValue!));
 | 
				
			||||||
                    showAlertBanner(context, () {}, const InfoAlertBannerChild(text: "successfully add to clipboard"), // <-- Put any widget here you want!
 | 
					                    showAlertBanner(context, () {}, const InfoAlertBannerChild(text: "successfully add to clipboard"), // <-- Put any widget here you want!
 | 
				
			||||||
                      alertBannerLocation:  AlertBannerLocation.bottom,);
 | 
					                      alertBannerLocation:  AlertBannerLocation.bottom,);
 | 
				
			||||||
                  }, child: Container( margin: EdgeInsets.only(left: 5, top: widget.empty ? 0 : 15),
 | 
					                  }, child: Container( margin: EdgeInsets.only(left: 5, top: widget.empty ? 0 : 15),
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								lib/widgets/items/infos.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								lib/widgets/items/infos.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/models/resources/resources.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ignore: must_be_immutable
 | 
				
			||||||
 | 
					class InfosWidget extends StatefulWidget {
 | 
				
			||||||
 | 
					  AbstractItem item;
 | 
				
			||||||
 | 
					  InfosWidget ({ super.key, required this.item });
 | 
				
			||||||
 | 
					  @override InfosWidgetState createState() => InfosWidgetState();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					class InfosWidgetState extends State<InfosWidget> {
 | 
				
			||||||
 | 
					  @override Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    List<Widget> children = [];
 | 
				
			||||||
 | 
					    var obj = widget.item.infos();
 | 
				
			||||||
 | 
					    for (var key in obj.keys) {
 | 
				
			||||||
 | 
					      children.add(
 | 
				
			||||||
 | 
					        Padding(padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 100),
 | 
				
			||||||
 | 
					          child: Text("$key : ${obj[key] ?? "no $key"}", 
 | 
				
			||||||
 | 
					          style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600))),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return Wrap( children: children);
 | 
				
			||||||
 | 
					  } 
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,9 +1,8 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/main.dart';
 | 
					import 'package:oc_front/main.dart';
 | 
				
			||||||
import 'package:oc_front/models/search.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:oc_front/widgets/items/items_details/data_item.dart';
 | 
					import 'package:oc_front/models/resources/resources.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ignore: must_be_immutable
 | 
				
			||||||
class ItemWidget extends StatefulWidget {
 | 
					class ItemWidget extends StatefulWidget {
 | 
				
			||||||
  AbstractItem item;
 | 
					  AbstractItem item;
 | 
				
			||||||
  ItemWidget ({ super.key, required this.item });
 | 
					  ItemWidget ({ super.key, required this.item });
 | 
				
			||||||
@@ -12,15 +11,10 @@ class ItemWidget extends StatefulWidget {
 | 
				
			|||||||
class ItemWidgetState extends State<ItemWidget> {
 | 
					class ItemWidgetState extends State<ItemWidget> {
 | 
				
			||||||
  @override Widget build(BuildContext context) {
 | 
					  @override Widget build(BuildContext context) {
 | 
				
			||||||
    Widget w = Container();
 | 
					    Widget w = Container();
 | 
				
			||||||
    /*  if (isData(widget.item.topic)) { w = DataItemWidget(item: widget.item as DataItem); }
 | 
					    return SizedBox(
 | 
				
			||||||
    else if (isComputing(widget.item.topic)) { w = DataItemWidget(item: widget.item as DataItem); }
 | 
					 | 
				
			||||||
    else if (isCompute(widget.item.topic)) { w = DataItemWidget(item: widget.item as DataItem); }
 | 
					 | 
				
			||||||
    else if (isStorage(widget.item.topic)) { w = DataItemWidget(item: widget.item as DataItem); } */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return Container(
 | 
					 | 
				
			||||||
            height: getHeight(context) - 300,
 | 
					            height: getHeight(context) - 300,
 | 
				
			||||||
            child: SingleChildScrollView(
 | 
					            child: SingleChildScrollView(
 | 
				
			||||||
              child: Column( children: [
 | 
					              child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [
 | 
				
			||||||
              widget.item.description == null ? Container() : Container(
 | 
					              widget.item.description == null ? Container() : Container(
 | 
				
			||||||
                width: getMainWidth(context),
 | 
					                width: getMainWidth(context),
 | 
				
			||||||
                alignment: Alignment.center,
 | 
					                alignment: Alignment.center,
 | 
				
			||||||
@@ -29,10 +23,8 @@ class ItemWidgetState extends State<ItemWidget> {
 | 
				
			|||||||
                child: Text(widget.item.description!, 
 | 
					                child: Text(widget.item.description!, 
 | 
				
			||||||
                style: TextStyle(fontSize: 15, color: Colors.grey, fontWeight: FontWeight.w500))), 
 | 
					                style: TextStyle(fontSize: 15, color: Colors.grey, fontWeight: FontWeight.w500))), 
 | 
				
			||||||
              Container(padding: const EdgeInsets.all(30),
 | 
					              Container(padding: const EdgeInsets.all(30),
 | 
				
			||||||
                  color: midColor,
 | 
					                alignment: Alignment.topLeft,
 | 
				
			||||||
                  width: getMainWidth(context) / 2,
 | 
					                color: midColor, width: getMainWidth(context) / 2,  child: w)
 | 
				
			||||||
                  child: w
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
          ]
 | 
					          ]
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,8 @@
 | 
				
			|||||||
import 'dart:convert';
 | 
					 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/main.dart';
 | 
					import 'package:oc_front/main.dart';
 | 
				
			||||||
import 'package:oc_front/models/search.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:oc_front/core/models/workspace_local.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/core/services/router.dart';
 | 
					import 'package:oc_front/core/services/router.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/models/resources/resources.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/core/models/workspace_local.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const List<GlobalKey<State>> _empty = [];
 | 
					const List<GlobalKey<State>> _empty = [];
 | 
				
			||||||
// ignore: must_be_immutable
 | 
					// ignore: must_be_immutable
 | 
				
			||||||
@@ -38,7 +37,7 @@ class ItemRowWidgetState extends State<ItemRowWidget> {
 | 
				
			|||||||
            constraints: BoxConstraints(maxWidth: imageSize, minWidth: imageSize),
 | 
					            constraints: BoxConstraints(maxWidth: imageSize, minWidth: imageSize),
 | 
				
			||||||
            child: image ?? Image.network('https://get-picto.com/wp-content/uploads/2024/01/logo-instagram-png.webp', 
 | 
					            child: image ?? Image.network('https://get-picto.com/wp-content/uploads/2024/01/logo-instagram-png.webp', 
 | 
				
			||||||
              height: imageSize, width: imageSize)),
 | 
					              height: imageSize, width: imageSize)),
 | 
				
			||||||
          Container(
 | 
					          SizedBox(
 | 
				
			||||||
            width: widget.low ? widget.contextWidth - 20 :  widget.contextWidth - (imageSize + 20) - endWidth,
 | 
					            width: widget.low ? widget.contextWidth - 20 :  widget.contextWidth - (imageSize + 20) - endWidth,
 | 
				
			||||||
            child: Padding(padding: widget.contextWidth != getMainWidth(context) ? 
 | 
					            child: Padding(padding: widget.contextWidth != getMainWidth(context) ? 
 | 
				
			||||||
            const EdgeInsets.symmetric(horizontal: 10) : const EdgeInsets.symmetric(horizontal: 20),
 | 
					            const EdgeInsets.symmetric(horizontal: 10) : const EdgeInsets.symmetric(horizontal: 20),
 | 
				
			||||||
@@ -48,10 +47,7 @@ class ItemRowWidgetState extends State<ItemRowWidget> {
 | 
				
			|||||||
                  widget.low ? Container() : Container(padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
 | 
					                  widget.low ? Container() : Container(padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
 | 
				
			||||||
                    margin: const EdgeInsets.only(right: 20),
 | 
					                    margin: const EdgeInsets.only(right: 20),
 | 
				
			||||||
                    decoration: BoxDecoration(
 | 
					                    decoration: BoxDecoration(
 | 
				
			||||||
                      color: isData(widget.item.topic) ? Colors.blue : 
 | 
					                      color: getColor(widget.item.topic),
 | 
				
			||||||
                      isComputing(widget.item.topic) ? Colors.green : 
 | 
					 | 
				
			||||||
                      isCompute(widget.item.topic) ? Colors.orange : 
 | 
					 | 
				
			||||||
                      isStorage(widget.item.topic) ? redColor : Colors.grey,
 | 
					 | 
				
			||||||
                      borderRadius: BorderRadius.circular(4),
 | 
					                      borderRadius: BorderRadius.circular(4),
 | 
				
			||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
                    child: Text( getMainWidth(context) < 600 ? "" : widget.item.topic.toString(), 
 | 
					                    child: Text( getMainWidth(context) < 600 ? "" : widget.item.topic.toString(), 
 | 
				
			||||||
@@ -61,13 +57,13 @@ class ItemRowWidgetState extends State<ItemRowWidget> {
 | 
				
			|||||||
                    style: TextStyle(fontSize: widget.low ? 14 : 20, overflow: TextOverflow.ellipsis, fontWeight: FontWeight.w600, color: Color(0xFFF67C0B9))),
 | 
					                    style: TextStyle(fontSize: widget.low ? 14 : 20, overflow: TextOverflow.ellipsis, fontWeight: FontWeight.w600, color: Color(0xFFF67C0B9))),
 | 
				
			||||||
                  )
 | 
					                  )
 | 
				
			||||||
                ]),
 | 
					                ]),
 | 
				
			||||||
                Text( "From ${widget.item.owner ?? "unknown owner"}", 
 | 
					                widget.item.owners.isEmpty ? Container() : Text( "From ${widget.item.owners.map( (e) => e.name).join(", ")}", 
 | 
				
			||||||
                  style: const TextStyle(fontSize: 14, color: Colors.grey, overflow: TextOverflow.ellipsis)),
 | 
					                  style: const TextStyle(fontSize: 14, color: Colors.grey, overflow: TextOverflow.ellipsis)),
 | 
				
			||||||
                Text(widget.item.shortDescription ?? "", style: const TextStyle(fontSize: 12, overflow: TextOverflow.ellipsis)),
 | 
					                Text(widget.item.shortDescription ?? "", style: const TextStyle(fontSize: 12, overflow: TextOverflow.ellipsis)),
 | 
				
			||||||
              ],)
 | 
					              ],)
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
          widget.low ? Container() : Container(
 | 
					          widget.low ? Container() : SizedBox(
 | 
				
			||||||
            width: endWidth,
 | 
					            width: endWidth,
 | 
				
			||||||
            child: Row( 
 | 
					            child: Row( 
 | 
				
			||||||
              mainAxisAlignment: MainAxisAlignment.center,
 | 
					              mainAxisAlignment: MainAxisAlignment.center,
 | 
				
			||||||
@@ -91,7 +87,8 @@ class ItemRowWidgetState extends State<ItemRowWidget> {
 | 
				
			|||||||
                    borderRadius: BorderRadius.circular(4),
 | 
					                    borderRadius: BorderRadius.circular(4),
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
                  child: Icon(WorkspaceLocal.hasItem(widget.item) ? Icons.remove_shopping_cart : Icons.add_shopping_cart, 
 | 
					                  child: Icon(WorkspaceLocal.hasItem(widget.item) ? Icons.remove_shopping_cart : Icons.add_shopping_cart, 
 | 
				
			||||||
                    color: Colors.white, size: 20 )) 
 | 
					                    color: Colors.white, size: 20 )
 | 
				
			||||||
 | 
					                ) 
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            ...(ratio > 1 ? [Padding( padding: const EdgeInsets.only(left: 20), 
 | 
					            ...(ratio > 1 ? [Padding( padding: const EdgeInsets.only(left: 20), 
 | 
				
			||||||
              child: InkWell( 
 | 
					              child: InkWell( 
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,24 +0,0 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/models/search.dart';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class DataItemWidget extends StatefulWidget {
 | 
					 | 
				
			||||||
  DataItem item;
 | 
					 | 
				
			||||||
  DataItemWidget ({ super.key, required this.item });
 | 
					 | 
				
			||||||
  @override DataItemWidgetState createState() => DataItemWidgetState();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
class DataItemWidgetState extends State<DataItemWidget> {
 | 
					 | 
				
			||||||
  @override Widget build(BuildContext context) {
 | 
					 | 
				
			||||||
    return Wrap( children: [
 | 
					 | 
				
			||||||
      Padding(padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 100),
 | 
					 | 
				
			||||||
        child: Text("type : ${widget.item.type ?? "unknown type"}", 
 | 
					 | 
				
			||||||
          style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600))),
 | 
					 | 
				
			||||||
      Padding(padding: const EdgeInsets.symmetric(horizontal: 100, vertical: 20), 
 | 
					 | 
				
			||||||
        child: Text("protocol : ${widget.item.protocols.isEmpty ? "no protocol founded" : widget.item.protocols.join(",")}", 
 | 
					 | 
				
			||||||
          style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600))),
 | 
					 | 
				
			||||||
      Padding(padding: const EdgeInsets.symmetric(horizontal: 100, vertical: 20), 
 | 
					 | 
				
			||||||
        child: Text("ex : ${widget.item.exemple ?? "no example"}", 
 | 
					 | 
				
			||||||
          style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600))),
 | 
					 | 
				
			||||||
    ]);
 | 
					 | 
				
			||||||
  } 
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,14 +1,14 @@
 | 
				
			|||||||
import 'package:flutter/material.dart';
 | 
					 | 
				
			||||||
import 'package:flutter_box_transform/flutter_box_transform.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/core/services/specialized_services/abstract_service.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/core/services/specialized_services/booking_service.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/main.dart';
 | 
					import 'package:oc_front/main.dart';
 | 
				
			||||||
import 'package:oc_front/models/workflow.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:oc_front/widgets/logs.dart';
 | 
					import 'package:oc_front/widgets/logs.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/models/workflow.dart';
 | 
				
			||||||
import 'package:flutter_spinkit/flutter_spinkit.dart';
 | 
					import 'package:flutter_spinkit/flutter_spinkit.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_box_transform/flutter_box_transform.dart';
 | 
				
			||||||
import 'package:oc_front/widgets/lib/tranformablebox.dart' as fork;
 | 
					import 'package:oc_front/widgets/lib/tranformablebox.dart' as fork;
 | 
				
			||||||
import 'package:oc_front/widgets/sheduler_items/scheduler_calendar.dart';
 | 
					 | 
				
			||||||
import 'package:oc_front/widgets/sheduler_items/scheduler_item.dart';
 | 
					import 'package:oc_front/widgets/sheduler_items/scheduler_item.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/widgets/sheduler_items/scheduler_calendar.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/core/services/specialized_services/abstract_service.dart';
 | 
				
			||||||
 | 
					import 'package:oc_front/core/services/specialized_services/workflow_execution_service.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
double menuSize = 300;
 | 
					double menuSize = 300;
 | 
				
			||||||
// ignore: must_be_immutable
 | 
					// ignore: must_be_immutable
 | 
				
			||||||
@@ -19,8 +19,8 @@ class ScheduleWidget extends StatefulWidget {
 | 
				
			|||||||
  bool loading = true;
 | 
					  bool loading = true;
 | 
				
			||||||
  bool isList = true;
 | 
					  bool isList = true;
 | 
				
			||||||
  bool isBox = true;
 | 
					  bool isBox = true;
 | 
				
			||||||
  AbstractService<WorkflowExecutions> service;
 | 
					  AbstractService<WorkflowExecutions> service = WorkflowExecutionService();
 | 
				
			||||||
  ScheduleWidget ({ super.key, required this.start, required this.end, required this.service,
 | 
					  ScheduleWidget ({ super.key, required this.start, required this.end,
 | 
				
			||||||
    this.isBox =true, this.isList = true, this.loading = false});
 | 
					    this.isBox =true, this.isList = true, this.loading = false});
 | 
				
			||||||
  @override ScheduleWidgetState createState() => ScheduleWidgetState();
 | 
					  @override ScheduleWidgetState createState() => ScheduleWidgetState();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -43,19 +43,16 @@ class ScheduleWidgetState extends State<ScheduleWidget> {
 | 
				
			|||||||
        "${widget.start.year}-${widget.start.month > 9 ? widget.start.month : "0${widget.start.month}"}-${widget.start.day > 9 ? widget.start.day : "0${widget.start.day}"}", 
 | 
					        "${widget.start.year}-${widget.start.month > 9 ? widget.start.month : "0${widget.start.month}"}-${widget.start.day > 9 ? widget.start.day : "0${widget.start.day}"}", 
 | 
				
			||||||
        "${widget.end.year}-${widget.end.month > 9 ? widget.end.month : "0${widget.end.month}"}-${widget.end.day > 9 ? widget.end.day : "0${widget.end.day}"}"], {}),
 | 
					        "${widget.end.year}-${widget.end.month > 9 ? widget.end.month : "0${widget.end.month}"}-${widget.end.day > 9 ? widget.end.day : "0${widget.end.day}"}"], {}),
 | 
				
			||||||
      builder: (ctx, as) { 
 | 
					      builder: (ctx, as) { 
 | 
				
			||||||
        Future.delayed(const Duration(minutes: 1), () {
 | 
					 | 
				
			||||||
          setState(() {});
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        Map<String, List<WorkflowExecution>> data = {};
 | 
					        Map<String, List<WorkflowExecution>> data = {};
 | 
				
			||||||
        if (as.hasData && as.data!.data != null) {
 | 
					        if (as.hasData && as.data!.data != null) {
 | 
				
			||||||
          for (var element in as.data!.data!.executions) {
 | 
					          for (var element in as.data!.data!.executions) {
 | 
				
			||||||
            if (element.executionData == null) { continue; }
 | 
					            if (element.startDate == null) { continue; }
 | 
				
			||||||
            DateTime dateTime = DateTime.parse(element.executionData!);
 | 
					            DateTime dateTime = DateTime.parse(element.startDate!);
 | 
				
			||||||
            DateTime date = DateTime(dateTime.year, dateTime.month, dateTime.day);
 | 
					            DateTime date = DateTime(dateTime.year, dateTime.month, dateTime.day);
 | 
				
			||||||
            var str = "${date.toIso8601String()}Z";
 | 
					            var str = "${date.toIso8601String()}Z";
 | 
				
			||||||
            if (data[str] == null) { data[str] = []; }
 | 
					            if (data[str] == null) { data[str] = []; }
 | 
				
			||||||
            data[str]!.add(element);
 | 
					            data[str]!.add(element);
 | 
				
			||||||
            data[str]!.sort((a, b) => DateTime.parse(a.executionData!).compareTo(DateTime.parse(b.executionData!)));
 | 
					            data[str]!.sort((a, b) => DateTime.parse(a.startDate!).compareTo(DateTime.parse(b.startDate!)));
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        bool isInfo = getMainWidth(context) <= 600 && selected != null && widget.isBox;
 | 
					        bool isInfo = getMainWidth(context) <= 600 && selected != null && widget.isBox;
 | 
				
			||||||
@@ -63,12 +60,12 @@ class ScheduleWidgetState extends State<ScheduleWidget> {
 | 
				
			|||||||
        List<Widget> children = [];
 | 
					        List<Widget> children = [];
 | 
				
			||||||
        if (selected != null) {
 | 
					        if (selected != null) {
 | 
				
			||||||
          for (var wf in data[selected!] ?? (<WorkflowExecution>[])) {
 | 
					          for (var wf in data[selected!] ?? (<WorkflowExecution>[])) {
 | 
				
			||||||
            DateTime d2 = DateTime.parse(wf.executionData!).toLocal();
 | 
					            DateTime d2 = DateTime.parse(wf.startDate!).toLocal();
 | 
				
			||||||
            children.add( InkWell(
 | 
					            children.add( InkWell(
 | 
				
			||||||
              onTap: () => setState(() { selectedReal = wf.executionData; }),
 | 
					              onTap: () => setState(() { selectedReal = wf.startDate; }),
 | 
				
			||||||
              child: Container( margin: const EdgeInsets.all(10),
 | 
					              child: Container( margin: const EdgeInsets.all(10),
 | 
				
			||||||
              decoration: BoxDecoration( 
 | 
					              decoration: BoxDecoration( 
 | 
				
			||||||
                border: Border.all(color: selectedReal != null && selectedReal == wf.executionData ? lightColor : Colors.transparent, width: 2),
 | 
					                border: Border.all(color: selectedReal != null && selectedReal == wf.startDate ? lightColor : Colors.transparent, width: 2),
 | 
				
			||||||
                borderRadius: BorderRadius.circular(4), color: Colors.white
 | 
					                borderRadius: BorderRadius.circular(4), color: Colors.white
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              child: Container(
 | 
					              child: Container(
 | 
				
			||||||
@@ -96,13 +93,12 @@ class ScheduleWidgetState extends State<ScheduleWidget> {
 | 
				
			|||||||
                  ))
 | 
					                  ))
 | 
				
			||||||
            ));
 | 
					            ));
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        String? selectedID;
 | 
					        String? selectedID;
 | 
				
			||||||
        WorkflowExecution? sel;
 | 
					        WorkflowExecution? sel;
 | 
				
			||||||
        if (selectedReal != null) {
 | 
					        if (selectedReal != null) {
 | 
				
			||||||
          try {
 | 
					          try {
 | 
				
			||||||
            sel = data[selected!]!.firstWhere((element) => element.executionData == selectedReal);
 | 
					            sel = data[selected!]!.firstWhere((element) => element.startDate == selectedReal);
 | 
				
			||||||
            selectedID = sel.id;
 | 
					            selectedID = sel.id;
 | 
				
			||||||
          } catch(e) { /* */ }
 | 
					          } catch(e) { /* */ }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -70,7 +70,7 @@ class SchedulerCalendarWidgetState extends State<SchedulerCalendarWidget> {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                children.add(InkWell( onTap: () => widget.parent!.setState(() {
 | 
					                children.add(InkWell( onTap: () => widget.parent!.setState(() {
 | 
				
			||||||
                  selected = day.toIso8601String();
 | 
					                  selected = day.toIso8601String();
 | 
				
			||||||
                  selectedReal = ev.executionData;
 | 
					                  selectedReal = ev.startDate;
 | 
				
			||||||
                  if (selectedReal  == null) {
 | 
					                  if (selectedReal  == null) {
 | 
				
			||||||
                    widget.parent!.widget.isDayPlanner = true;
 | 
					                    widget.parent!.widget.isDayPlanner = true;
 | 
				
			||||||
                  }
 | 
					                  }
 | 
				
			||||||
@@ -158,9 +158,9 @@ class SchedulerCalendarWidgetState extends State<SchedulerCalendarWidget> {
 | 
				
			|||||||
          shouldFillViewport: true,
 | 
					          shouldFillViewport: true,
 | 
				
			||||||
          eventLoader: (day) {
 | 
					          eventLoader: (day) {
 | 
				
			||||||
            return widget.data[day.toIso8601String()] != null ? widget.data[day.toIso8601String()]!.map((e) {
 | 
					            return widget.data[day.toIso8601String()] != null ? widget.data[day.toIso8601String()]!.map((e) {
 | 
				
			||||||
              DateTime dateTime = DateTime.parse(e.executionData!);
 | 
					              DateTime dateTime = DateTime.parse(e.startDate!);
 | 
				
			||||||
              return Event("[${dateTime.hour > 9 ? dateTime.hour : "0${dateTime.hour}"}:${dateTime.minute > 9 ? dateTime.minute : "0${dateTime.minute}"}:${dateTime.second > 9 ? dateTime.second : "0${dateTime.second}"}] ${e.name}", 
 | 
					              return Event("[${dateTime.hour > 9 ? dateTime.hour : "0${dateTime.hour}"}:${dateTime.minute > 9 ? dateTime.minute : "0${dateTime.minute}"}:${dateTime.second > 9 ? dateTime.second : "0${dateTime.second}"}] ${e.name}", 
 | 
				
			||||||
                 colors[(e.status ?? 1) - 1], e.executionData );
 | 
					                 colors[(e.status ?? 1) - 1], e.startDate );
 | 
				
			||||||
            }).toList() : [];
 | 
					            }).toList() : [];
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
        ));
 | 
					        ));
 | 
				
			||||||
@@ -169,10 +169,10 @@ class SchedulerCalendarWidgetState extends State<SchedulerCalendarWidget> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class Event {
 | 
					class Event {
 | 
				
			||||||
  final String title;
 | 
					  final String title;
 | 
				
			||||||
  String? executionData;
 | 
					  String? startDate;
 | 
				
			||||||
  Color color;
 | 
					  Color color;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Event(this.title, this.color, this.executionData);
 | 
					  Event(this.title, this.color, this.startDate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  String toString() => title;
 | 
					  String toString() => title;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,23 +26,23 @@ class SchedulerItemWidgetState extends State<SchedulerItemWidget> {
 | 
				
			|||||||
          for (var element in widget.data.keys.toList()..sort((a, b) => DateTime.parse(a).compareTo(DateTime.parse(b)))) {
 | 
					          for (var element in widget.data.keys.toList()..sort((a, b) => DateTime.parse(a).compareTo(DateTime.parse(b)))) {
 | 
				
			||||||
            List<Widget> widgets = [];
 | 
					            List<Widget> widgets = [];
 | 
				
			||||||
            for (var ev in widget.data[element] ?? ([] as List<WorkflowExecution>)) {
 | 
					            for (var ev in widget.data[element] ?? ([] as List<WorkflowExecution>)) {
 | 
				
			||||||
              widget.keys[ev.executionData!] = GlobalKey();
 | 
					              widget.keys[ev.startDate!] = GlobalKey();
 | 
				
			||||||
              var d2 = DateTime.parse(ev.executionData!).toLocal();
 | 
					              var d2 = DateTime.parse(ev.startDate!).toLocal();
 | 
				
			||||||
              DateTime? d3;
 | 
					              DateTime? d3;
 | 
				
			||||||
              try { d3 = DateTime.parse(ev.endDate!).toLocal();
 | 
					              try { d3 = DateTime.parse(ev.endDate!).toLocal();
 | 
				
			||||||
              } catch (e) { /* */ }
 | 
					              } catch (e) { /* */ }
 | 
				
			||||||
              widgets.add(InkWell(
 | 
					              widgets.add(InkWell(
 | 
				
			||||||
                onTap: () => widget.parent?.setState(() { 
 | 
					                onTap: () => widget.parent?.setState(() { 
 | 
				
			||||||
                  selected = selected != element || ev.executionData != selectedReal  ? element : null;  
 | 
					                  selected = selected != element || ev.startDate != selectedReal  ? element : null;  
 | 
				
			||||||
                  selectedReal = selected == null ? null : ev.executionData; 
 | 
					                  selectedReal = selected == null ? null : ev.startDate; 
 | 
				
			||||||
                  if (selectedReal  == null) {
 | 
					                  if (selectedReal  == null) {
 | 
				
			||||||
                    widget.parent!.widget.isDayPlanner = true;
 | 
					                    widget.parent!.widget.isDayPlanner = true;
 | 
				
			||||||
                  }
 | 
					                  }
 | 
				
			||||||
                }),  
 | 
					                }),  
 | 
				
			||||||
                child: Container( key: widget.keys[ev.executionData!],
 | 
					                child: Container( key: widget.keys[ev.startDate!],
 | 
				
			||||||
                padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 50),
 | 
					                padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 50),
 | 
				
			||||||
                decoration: BoxDecoration( 
 | 
					                decoration: BoxDecoration( 
 | 
				
			||||||
                  border: selectedReal == ev.executionData ? 
 | 
					                  border: selectedReal == ev.startDate ? 
 | 
				
			||||||
                    Border.all(color: lightColor, width: 2) : Border(top: BorderSide(color: midColor)),
 | 
					                    Border.all(color: lightColor, width: 2) : Border(top: BorderSide(color: midColor)),
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
                child: Row(children: [
 | 
					                child: Row(children: [
 | 
				
			||||||
@@ -59,7 +59,7 @@ class SchedulerItemWidgetState extends State<SchedulerItemWidget> {
 | 
				
			|||||||
                  SizedBox( width: (widget.width - 330) / 2,
 | 
					                  SizedBox( width: (widget.width - 330) / 2,
 | 
				
			||||||
                    child: Padding( 
 | 
					                    child: Padding( 
 | 
				
			||||||
                      padding: const EdgeInsets.only(left: 20), 
 | 
					                      padding: const EdgeInsets.only(left: 20), 
 | 
				
			||||||
                      child: Text(ev.name?.toUpperCase() ?? "", overflow: TextOverflow.ellipsis,
 | 
					                      child: Text("${ev.name?.toUpperCase().split("EXECUTION")[0].replaceAll("_", "") ?? ""} EXECUTION", overflow: TextOverflow.ellipsis,
 | 
				
			||||||
                      style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w500)),
 | 
					                      style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w500)),
 | 
				
			||||||
                    )),
 | 
					                    )),
 | 
				
			||||||
                  SizedBox( width: (widget.width - 340) / 2,
 | 
					                  SizedBox( width: (widget.width - 340) / 2,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1 @@
 | 
				
			|||||||
3.19.6
 | 
					3.24.3
 | 
				
			||||||
@@ -5,5 +5,5 @@ export 'src/dashboard.dart';
 | 
				
			|||||||
export 'src/elements/connection_params.dart';
 | 
					export 'src/elements/connection_params.dart';
 | 
				
			||||||
export 'src/elements/flow_element.dart';
 | 
					export 'src/elements/flow_element.dart';
 | 
				
			||||||
export 'src/flow_chart.dart';
 | 
					export 'src/flow_chart.dart';
 | 
				
			||||||
export 'src/ui/draw_arrow.dart' show ArrowParams, ArrowStyle, ArrowDirection;
 | 
					export 'src/ui/draw_arrow.dart' show ArrowParams, ArrowStyle, ArrowDirection, ArrowPainter;
 | 
				
			||||||
export 'src/ui/grid_background.dart' show GridBackgroundParams;
 | 
					export 'src/ui/grid_background.dart' show GridBackgroundParams;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,13 +28,11 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
  GlobalKey<FlowChartMenuState> chartMenuKey = GlobalKey<FlowChartMenuState>();
 | 
					  GlobalKey<FlowChartMenuState> chartMenuKey = GlobalKey<FlowChartMenuState>();
 | 
				
			||||||
  GlobalKey<ChartWidgetState> chartKey = GlobalKey<ChartWidgetState>();
 | 
					  GlobalKey<ChartWidgetState> chartKey = GlobalKey<ChartWidgetState>();
 | 
				
			||||||
  GlobalKey<FlowChartState> flutterChartKey = GlobalKey<FlowChartState>();
 | 
					  GlobalKey<FlowChartState> flutterChartKey = GlobalKey<FlowChartState>();
 | 
				
			||||||
 | 
					  bool inDialog = false;
 | 
				
			||||||
  List<Map<String, dynamic>> tempHistory = [];
 | 
					  List<Map<String, dynamic>> tempHistory = [];
 | 
				
			||||||
  List<Map<String, dynamic>> history = [];
 | 
					  List<Map<String, dynamic>> history = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Map<String, dynamic> scheduler = {};
 | 
					 | 
				
			||||||
  Map<String, dynamic> info = {};
 | 
					  Map<String, dynamic> info = {};
 | 
				
			||||||
  bool scheduleActive = false;
 | 
					 | 
				
			||||||
  String? id;
 | 
					  String? id;
 | 
				
			||||||
  String name = "";
 | 
					  String name = "";
 | 
				
			||||||
  bool isMenu = true;
 | 
					  bool isMenu = true;
 | 
				
			||||||
@@ -47,8 +45,9 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
  double defaultDashWidth = 0;
 | 
					  double defaultDashWidth = 0;
 | 
				
			||||||
  double defaultBackWidth = 10;
 | 
					  double defaultBackWidth = 10;
 | 
				
			||||||
  double defaultForwardWidth = 10;
 | 
					  double defaultForwardWidth = 10;
 | 
				
			||||||
  Future<void> Function(String? id)? save;
 | 
					  Future<void> Function(String? id, BuildContext? context)? save;
 | 
				
			||||||
  List<Widget> Function(FlowData? obj, String id)? infoItemWidget;
 | 
					  List<Widget> Function(FlowData? obj, String id)? infoItemWidget;
 | 
				
			||||||
 | 
					  Widget Function(ArrowPainter item)? infoLinkWidget;
 | 
				
			||||||
  List<Widget> Function()? infoWidget;
 | 
					  List<Widget> Function()? infoWidget;
 | 
				
			||||||
  FlowData? Function(Map<String, dynamic> json)? transformToData;
 | 
					  FlowData? Function(Map<String, dynamic> json)? transformToData;
 | 
				
			||||||
  bool addChange = false;
 | 
					  bool addChange = false;
 | 
				
			||||||
@@ -74,7 +73,6 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
    this.save,
 | 
					    this.save,
 | 
				
			||||||
    this.dashColor = Colors.grey,
 | 
					    this.dashColor = Colors.grey,
 | 
				
			||||||
    this.midDashColor = Colors.blueGrey,
 | 
					    this.midDashColor = Colors.blueGrey,
 | 
				
			||||||
    this.scheduler = const {},
 | 
					 | 
				
			||||||
    Offset? handlerFeedbackOffset,
 | 
					    Offset? handlerFeedbackOffset,
 | 
				
			||||||
    this.isMenu = true,
 | 
					    this.isMenu = true,
 | 
				
			||||||
    this.defaultDashSpace = 0,
 | 
					    this.defaultDashSpace = 0,
 | 
				
			||||||
@@ -93,7 +91,7 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
    // This is a workaround to set the handlerFeedbackOffset
 | 
					    // This is a workaround to set the handlerFeedbackOffset
 | 
				
			||||||
    // to improve the user experience on devices with touch screens
 | 
					    // to improve the user experience on devices with touch screens
 | 
				
			||||||
    // This will prevent the handler being covered by user's finger
 | 
					    // This will prevent the handler being covered by user's finger
 | 
				
			||||||
    if (loadedGraph != null) { deserialize(loadedGraph!); }
 | 
					    if (loadedGraph != null) { deserialize(loadedGraph!, false); }
 | 
				
			||||||
    if (handlerFeedbackOffset != null) {
 | 
					    if (handlerFeedbackOffset != null) {
 | 
				
			||||||
      this.handlerFeedbackOffset = handlerFeedbackOffset;
 | 
					      this.handlerFeedbackOffset = handlerFeedbackOffset;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@@ -110,18 +108,15 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
    tempHistory = [];
 | 
					    tempHistory = [];
 | 
				
			||||||
    history = [];
 | 
					    history = [];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  Future<void> saveDash(String? id) async {
 | 
					  Future<void> saveDash(String? id, BuildContext? context) async {
 | 
				
			||||||
    shouldSave = true;
 | 
					 | 
				
			||||||
    for (var element in saveRules) {
 | 
					    for (var element in saveRules) {
 | 
				
			||||||
      if (element(this)) {
 | 
					      if (!element(this)) {
 | 
				
			||||||
        shouldSave = true;
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        shouldSave = false;
 | 
					        shouldSave = false;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (save != null && shouldSave) {
 | 
					    if (save != null && shouldSave) {
 | 
				
			||||||
      save!(id);
 | 
					      save!(id, context);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  Future<void> Function(String cat)? load;
 | 
					  Future<void> Function(String cat)? load;
 | 
				
			||||||
@@ -131,14 +126,12 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
    final d = Dashboard(
 | 
					    final d = Dashboard(
 | 
				
			||||||
      name: map['name'] as String,
 | 
					      name: map['name'] as String,
 | 
				
			||||||
      isMenu: map['isMenu'] as bool,
 | 
					      isMenu: map['isMenu'] as bool,
 | 
				
			||||||
      scheduler: map['schedule'] as Map<String, String>? ?? {},
 | 
					 | 
				
			||||||
      defaultDashSpace: map['defaultDashSpace'] as double? ?? 0,
 | 
					      defaultDashSpace: map['defaultDashSpace'] as double? ?? 0,
 | 
				
			||||||
      defaultDashWidth: map['defaultDashWidth'] as double? ?? 0,
 | 
					      defaultDashWidth: map['defaultDashWidth'] as double? ?? 0,
 | 
				
			||||||
      defaultArrowDirection: ArrowDirection.values[
 | 
					      defaultArrowDirection: ArrowDirection.values[
 | 
				
			||||||
          map['defaultArrowDirection'] as int? ?? 0],
 | 
					          map['defaultArrowDirection'] as int? ?? 0],
 | 
				
			||||||
      defaultArrowStyle: ArrowStyle.values[map['arrowStyle'] as int? ?? 0],
 | 
					      defaultArrowStyle: ArrowStyle.values[map['arrowStyle'] as int? ?? 0],
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    d..scheduleActive = map['schedule_active'] as bool? ?? false;
 | 
					 | 
				
			||||||
    d..arrows = List<ArrowPainter>.from(
 | 
					    d..arrows = List<ArrowPainter>.from(
 | 
				
			||||||
        (map['arrows'] as List<dynamic>).map<ArrowPainter>(
 | 
					        (map['arrows'] as List<dynamic>).map<ArrowPainter>(
 | 
				
			||||||
          (x) => ArrowPainter.fromMap(x as Map<String, dynamic>),
 | 
					          (x) => ArrowPainter.fromMap(x as Map<String, dynamic>),
 | 
				
			||||||
@@ -170,15 +163,14 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void copyFromMap(Map<String, dynamic> map) {
 | 
					  void copyFromMap(Map<String, dynamic> map) {
 | 
				
			||||||
    scheduleActive = map['schedule_active'] as bool? ?? false;
 | 
					    debugPrintStack(stackTrace: StackTrace.current, label: 'my_label', maxFrames: 5);
 | 
				
			||||||
    scheduler = map['schedule'] as Map<String, String>? ?? {};
 | 
					 | 
				
			||||||
    defaultArrowStyle = ArrowStyle.values[map['arrowStyle'] as int? ?? 0];
 | 
					    defaultArrowStyle = ArrowStyle.values[map['arrowStyle'] as int? ?? 0];
 | 
				
			||||||
    defaultDashSpace = map['defaultDashSpace'] as double? ?? 0;
 | 
					    defaultDashSpace = map['defaultDashSpace'] as double? ?? 0;
 | 
				
			||||||
    defaultDashWidth = map['defaultDashWidth'] as double? ?? 0;
 | 
					    defaultDashWidth = map['defaultDashWidth'] as double? ?? 0;
 | 
				
			||||||
    defaultArrowDirection = ArrowDirection.values[
 | 
					    defaultArrowDirection = ArrowDirection.values[
 | 
				
			||||||
          map['defaultArrowDirection'] as int? ?? 0];
 | 
					          map['defaultArrowDirection'] as int? ?? 0];
 | 
				
			||||||
    arrows = List<ArrowPainter>.from(
 | 
					    arrows = List<ArrowPainter>.from(
 | 
				
			||||||
        (map['arrows'] as List<dynamic>).map<ArrowPainter>(
 | 
					          (map['arrows'] as List<dynamic>).map<ArrowPainter>(
 | 
				
			||||||
          (x) => ArrowPainter.fromMap(x as Map<String, dynamic>),
 | 
					          (x) => ArrowPainter.fromMap(x as Map<String, dynamic>),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
@@ -257,26 +249,25 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
    d["id"]=id;
 | 
					    d["id"]=id;
 | 
				
			||||||
    d["name"]=name;
 | 
					    d["name"]=name;
 | 
				
			||||||
    d["graph"]=graph;
 | 
					    d["graph"]=graph;
 | 
				
			||||||
    d["schedule"]=scheduler;
 | 
					 | 
				
			||||||
    d["schedule_active"]=scheduleActive;
 | 
					 | 
				
			||||||
    return d;
 | 
					    return d;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void deserialize(Map<String, dynamic> graph) {
 | 
					  void deserialize(Map<String, dynamic> graph, bool noHistory) {
 | 
				
			||||||
    elements = [];
 | 
					    elements = [];
 | 
				
			||||||
    arrows = [];
 | 
					    arrows = [];
 | 
				
			||||||
    info["shared"] = graph["shared"] ?? [];
 | 
					    info["shared"] = graph["shared"] ?? [];
 | 
				
			||||||
    scheduler = graph['schedule'] ?? {};
 | 
					 | 
				
			||||||
    scheduleActive = graph['schedule_active'] ?? false;
 | 
					 | 
				
			||||||
    setZoomFactor(graph["graph"]?["zoom"] ?? 1.0);
 | 
					    setZoomFactor(graph["graph"]?["zoom"] ?? 1.0);
 | 
				
			||||||
    for(var el in graph['graph']?['elements'] ?? []) {
 | 
					    for(var el in graph['graph']?['elements'] ?? []) {
 | 
				
			||||||
      List<ConnectionParams> nexts = [];
 | 
					      List<ConnectionParams> nexts = [];
 | 
				
			||||||
      var flow = FlowElement.deserialize(this, el);
 | 
					      var flow = FlowElement.deserialize(this, el);
 | 
				
			||||||
      for(var ar in graph['graph']['arrows']) {
 | 
					      for(var ar in graph['graph']['arrows']) {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        if (ar['from']['id'] != flow.id) { continue; }
 | 
					        if (ar['from']['id'] != flow.id) { continue; }
 | 
				
			||||||
        nexts.add(ConnectionParams(
 | 
					        nexts.add(ConnectionParams(
 | 
				
			||||||
          srcElementId: ar['from']['id'],
 | 
					          srcElementId: ar['from']['id'],
 | 
				
			||||||
          destElementId: ar['to']['id'],
 | 
					          destElementId: ar['to']['id'],
 | 
				
			||||||
 | 
					          infos: ar['infos'],
 | 
				
			||||||
 | 
					          env: ar['env'],
 | 
				
			||||||
          arrowParams: ArrowParams.fromMap(ar["params"]),
 | 
					          arrowParams: ArrowParams.fromMap(ar["params"]),
 | 
				
			||||||
          pivots: [
 | 
					          pivots: [
 | 
				
			||||||
            Pivot(Offset(ar['from']['x'], (ar['from']['y']))), 
 | 
					            Pivot(Offset(ar['from']['x'], (ar['from']['y']))), 
 | 
				
			||||||
@@ -291,16 +282,35 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
          arr.add(build);
 | 
					          arr.add(build);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      try {
 | 
					      if (flow.element != null) {
 | 
				
			||||||
        FlowData data = arr.firstWhere((element) => element.getID() == flow.element?.getID());
 | 
					 | 
				
			||||||
        flow.kind = ElementKind.widget;
 | 
					        flow.kind = ElementKind.widget;
 | 
				
			||||||
        flow.widget = chartKey.currentState?.widget.flowChart.widget.itemWidget(data);
 | 
					        flow.widget = chartKey.currentState?.widget.flowChart.widget.itemWidget(flow.element!);
 | 
				
			||||||
      } catch (e) { print(e); }
 | 
					      }
 | 
				
			||||||
      elements.add(flow);
 | 
					      elements.add(flow);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    selectedMenuKey.currentState?.setState(() { });
 | 
					    selectedMenuKey.currentState?.setState(() { });
 | 
				
			||||||
    chartMenuKey.currentState?.setState(() { });
 | 
					    chartMenuKey.currentState?.setState(() { });
 | 
				
			||||||
    addToHistory();
 | 
					    if (!noHistory) {
 | 
				
			||||||
 | 
					      addToHistory();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void applyInfos(Map<String, List<dynamic>> elInfos, Map<String, dynamic> graph) {
 | 
				
			||||||
 | 
					    for(var id in elInfos.keys) {
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        var element = elements.firstWhere((element) => element.id == id);
 | 
				
			||||||
 | 
					        element.element?.addEnv(elInfos[id] ?? []);
 | 
				
			||||||
 | 
					      } catch (e) { print("THERE ??? ${id} ${e}"); }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    for(var ar in graph['graph']['arrows']) {
 | 
				
			||||||
 | 
					        var arr = arrows.where((a) => a.fromID == ar['from']['id'] && a.toID == ar['to']['id']).toList();
 | 
				
			||||||
 | 
					        for (var a in arr) {
 | 
				
			||||||
 | 
					          a.infos = ar['infos'];
 | 
				
			||||||
 | 
					          a.env = ar['env'];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    selectedLeftMenuKey.currentState?.setState(() { });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// add listener called when a new connection is created
 | 
					  /// add listener called when a new connection is created
 | 
				
			||||||
@@ -325,30 +335,31 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
    handlerFeedbackOffset = offset;
 | 
					    handlerFeedbackOffset = offset;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  List<ArrowPainter> GetArrowByElementID(String id, bool isinput) {
 | 
					  List<ArrowPainter> getArrowByElementID(String id, bool isinput) {
 | 
				
			||||||
    return arrows.where((element) => (isinput && element.toID.contains(id)) || (!isinput && element.fromID.contains(id))).toList();
 | 
					    return arrows.where((element) => 
 | 
				
			||||||
 | 
					      (isinput && element.toID.contains(id)) || (!isinput && element.fromID.contains(id))).toList();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void addArrows(ArrowPainter f) {
 | 
					  void addArrows(ArrowPainter f, BuildContext? context) {
 | 
				
			||||||
    arrows.add(f);
 | 
					    arrows.add(f);
 | 
				
			||||||
    for (var f in arrowStyleRules) {
 | 
					    for (var f in arrowStyleRules) {
 | 
				
			||||||
      arrows = f(this);
 | 
					      arrows = f(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    addChange = true;
 | 
					    addChange = true;
 | 
				
			||||||
    saveDash(id);
 | 
					    saveDash(id, context);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void removeArrows(bool Function(ArrowPainter) f) {
 | 
					  void removeArrows(bool Function(ArrowPainter) f, BuildContext? context) {
 | 
				
			||||||
    arrows.removeWhere((element) => f(element));
 | 
					    arrows.removeWhere((element) => f(element));
 | 
				
			||||||
    for (var f in arrowStyleRules) {
 | 
					    for (var f in arrowStyleRules) {
 | 
				
			||||||
      arrows = f(this);
 | 
					      arrows = f(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    saveDash(id);
 | 
					    saveDash(id, context);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void removeElements(bool Function(FlowElement<FlowData>) f) {
 | 
					  void removeElements(bool Function(FlowElement<FlowData>) f, BuildContext? context) {
 | 
				
			||||||
    elements.removeWhere((element) => f(element));
 | 
					    elements.removeWhere((element) => f(element));
 | 
				
			||||||
    saveDash(id);
 | 
					    saveDash(id, context);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void clear() {
 | 
					  void clear() {
 | 
				
			||||||
@@ -356,9 +367,7 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
    arrows.clear();
 | 
					    arrows.clear();
 | 
				
			||||||
    tempHistory = [];
 | 
					    tempHistory = [];
 | 
				
			||||||
    history = [];
 | 
					    history = [];
 | 
				
			||||||
    scheduler = {};
 | 
					 | 
				
			||||||
    info = {};
 | 
					    info = {};
 | 
				
			||||||
    scheduleActive = false;
 | 
					 | 
				
			||||||
    notifyListeners();
 | 
					    notifyListeners();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  bool noHistory = false;
 | 
					  bool noHistory = false;
 | 
				
			||||||
@@ -375,14 +384,13 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
    Future.delayed(Duration(seconds: 1), () {
 | 
					    Future.delayed(Duration(seconds: 1), () {
 | 
				
			||||||
      chartMenuKey.currentState?.setState(() { });
 | 
					      chartMenuKey.currentState?.setState(() { });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    ;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  bool isBack = false;
 | 
					  bool isBack = false;
 | 
				
			||||||
  void back() { 
 | 
					  void back() { 
 | 
				
			||||||
    if (canBack()) {
 | 
					    if (canBack()) {
 | 
				
			||||||
      noHistory = true;
 | 
					      noHistory = true;
 | 
				
			||||||
      tempHistory.removeLast(); 
 | 
					      tempHistory.removeLast(); 
 | 
				
			||||||
      if (tempHistory.length > 0) {
 | 
					      if (tempHistory.isNotEmpty) {
 | 
				
			||||||
        copyFromMap(tempHistory.last);
 | 
					        copyFromMap(tempHistory.last);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      chartKey.currentState?.setState(() { });
 | 
					      chartKey.currentState?.setState(() { });
 | 
				
			||||||
@@ -413,28 +421,29 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
    FlowElement element,
 | 
					    FlowElement element,
 | 
				
			||||||
    bool resizable, {
 | 
					    bool resizable, {
 | 
				
			||||||
    bool notify = true,
 | 
					    bool notify = true,
 | 
				
			||||||
 | 
					    BuildContext? context
 | 
				
			||||||
  }) {
 | 
					  }) {
 | 
				
			||||||
    element.isResizing = resizable;
 | 
					    element.isResizing = resizable;
 | 
				
			||||||
    saveDash(id);
 | 
					    saveDash(id, context);
 | 
				
			||||||
    if (notify) notifyListeners();
 | 
					    if (notify) notifyListeners();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  FlowElement? getElement(String id, {bool notify = true}) {
 | 
					  FlowElement? getElement(String id, {bool notify = true}) {
 | 
				
			||||||
    try { return elements.firstWhere((element) {
 | 
					    try { return elements.firstWhere((element) {
 | 
				
			||||||
      return element.id == id;
 | 
					      return id.contains(element.id);
 | 
				
			||||||
    }); }
 | 
					    }); }
 | 
				
			||||||
    catch (e) { return null; }
 | 
					    catch (e) { return null; }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// add a [FlowElement] to the dashboard
 | 
					  /// add a [FlowElement] to the dashboard
 | 
				
			||||||
  void addElement(FlowElement element, {bool notify = true}) {
 | 
					  void addElement(FlowElement element, BuildContext? context, {bool notify = true}) {
 | 
				
			||||||
    if (element.id.isEmpty) {
 | 
					    if (element.id.isEmpty) {
 | 
				
			||||||
      element.id = const Uuid().v4();
 | 
					      element.id = const Uuid().v4();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    element.setScale(1, gridBackgroundParams.scale);
 | 
					    element.setScale(1, gridBackgroundParams.scale);
 | 
				
			||||||
    elements.add(element);
 | 
					    elements.add(element);
 | 
				
			||||||
    addChange = true;
 | 
					    addChange = true;
 | 
				
			||||||
    saveDash(id);
 | 
					    saveDash(id, context);
 | 
				
			||||||
    if (notify) {
 | 
					    if (notify) {
 | 
				
			||||||
      notifyListeners();
 | 
					      notifyListeners();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -554,16 +563,16 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// remove all elements
 | 
					  /// remove all elements
 | 
				
			||||||
  void removeAllElements({bool notify = true}) {
 | 
					  void removeAllElements(BuildContext? context, {bool notify = true}) {
 | 
				
			||||||
    elements.clear();
 | 
					    elements.clear();
 | 
				
			||||||
    if (notify) notifyListeners();
 | 
					    if (notify) notifyListeners();
 | 
				
			||||||
    saveDash(id);
 | 
					    saveDash(id, context);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// remove the [handler] connection of [element]
 | 
					  /// remove the [handler] connection of [element]
 | 
				
			||||||
  void removeElementConnection(
 | 
					  void removeElementConnection(
 | 
				
			||||||
    FlowElement element,
 | 
					    FlowElement element,
 | 
				
			||||||
    Handler handler, {
 | 
					    Handler handler, BuildContext? context, {
 | 
				
			||||||
    bool notify = true,
 | 
					    bool notify = true,
 | 
				
			||||||
  }) {
 | 
					  }) {
 | 
				
			||||||
    Alignment alignment;
 | 
					    Alignment alignment;
 | 
				
			||||||
@@ -600,7 +609,7 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (notify) notifyListeners();
 | 
					    if (notify) notifyListeners();
 | 
				
			||||||
    saveDash(id);
 | 
					    saveDash(id, context);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// dissect an element connection
 | 
					  /// dissect an element connection
 | 
				
			||||||
@@ -690,14 +699,14 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// remove all the connection from the [element]
 | 
					  /// remove all the connection from the [element]
 | 
				
			||||||
  void removeElementConnections(FlowElement element, {bool notify = true}) {
 | 
					  void removeElementConnections(FlowElement element, BuildContext? context, {bool notify = true}) {
 | 
				
			||||||
    element.next.clear();
 | 
					    element.next.clear();
 | 
				
			||||||
    if (notify) notifyListeners();
 | 
					    if (notify) notifyListeners();
 | 
				
			||||||
    saveDash(id);
 | 
					    saveDash(id, context);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// remove all the elements with [id] from the dashboard
 | 
					  /// remove all the elements with [id] from the dashboard
 | 
				
			||||||
  void removeElementById(String id, {bool notify = true}) {
 | 
					  void removeElementById(String id, BuildContext? context, {bool notify = true}) {
 | 
				
			||||||
    // remove the element
 | 
					    // remove the element
 | 
				
			||||||
    var elementId = '';
 | 
					    var elementId = '';
 | 
				
			||||||
    elements.removeWhere((element) {
 | 
					    elements.removeWhere((element) {
 | 
				
			||||||
@@ -714,12 +723,12 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
      });
 | 
					      });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (notify) notifyListeners();
 | 
					    if (notify) notifyListeners();
 | 
				
			||||||
    saveDash(id);
 | 
					    saveDash(id, context);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// remove element
 | 
					  /// remove element
 | 
				
			||||||
  /// return true if it has been removed
 | 
					  /// return true if it has been removed
 | 
				
			||||||
  bool removeElement(FlowElement element, {bool notify = true}) {
 | 
					  bool removeElement(FlowElement element, BuildContext? context, {bool notify = true}) {
 | 
				
			||||||
    // remove the element
 | 
					    // remove the element
 | 
				
			||||||
    var found = false;
 | 
					    var found = false;
 | 
				
			||||||
    final elementId = element.id;
 | 
					    final elementId = element.id;
 | 
				
			||||||
@@ -735,7 +744,7 @@ class Dashboard extends ChangeNotifier {
 | 
				
			|||||||
      );
 | 
					      );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (notify) notifyListeners();
 | 
					    if (notify) notifyListeners();
 | 
				
			||||||
    saveDash(id);
 | 
					    saveDash(id, context);
 | 
				
			||||||
    return found;
 | 
					    return found;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,14 +11,19 @@ class ConnectionParams {
 | 
				
			|||||||
    required this.srcElementId,
 | 
					    required this.srcElementId,
 | 
				
			||||||
    required this.destElementId,
 | 
					    required this.destElementId,
 | 
				
			||||||
    required this.arrowParams,
 | 
					    required this.arrowParams,
 | 
				
			||||||
 | 
					    this.env = const [],
 | 
				
			||||||
 | 
					    this.infos = const [],
 | 
				
			||||||
    List<Pivot>? pivots,
 | 
					    List<Pivot>? pivots,
 | 
				
			||||||
  }) : pivots = pivots ?? [];
 | 
					  }) : pivots = pivots ?? [];
 | 
				
			||||||
 | 
					  List<dynamic> env = [];
 | 
				
			||||||
 | 
					  List<dynamic> infos = [];
 | 
				
			||||||
  ///
 | 
					  ///
 | 
				
			||||||
  factory ConnectionParams.fromMap(Map<String, dynamic> map) {
 | 
					  factory ConnectionParams.fromMap(Map<String, dynamic> map) {
 | 
				
			||||||
    return ConnectionParams(
 | 
					    return ConnectionParams(
 | 
				
			||||||
      srcElementId: map['srcElementId'] as String,
 | 
					      srcElementId: map['srcElementId'] as String,
 | 
				
			||||||
      destElementId: map['destElementId'] as String,
 | 
					      destElementId: map['destElementId'] as String,
 | 
				
			||||||
 | 
					      infos: map['infos'] as List<dynamic>? ?? [],
 | 
				
			||||||
 | 
					      env: map['env'] as List<dynamic>? ?? [],
 | 
				
			||||||
      arrowParams: ArrowParams.fromMap(map['arrowParams'] as Map<String, dynamic>),
 | 
					      arrowParams: ArrowParams.fromMap(map['arrowParams'] as Map<String, dynamic>),
 | 
				
			||||||
      pivots: (map['pivots'] as List?)
 | 
					      pivots: (map['pivots'] as List?)
 | 
				
			||||||
              ?.map<Pivot>(
 | 
					              ?.map<Pivot>(
 | 
				
			||||||
@@ -37,7 +42,6 @@ class ConnectionParams {
 | 
				
			|||||||
  final String destElementId;
 | 
					  final String destElementId;
 | 
				
			||||||
  final String srcElementId;
 | 
					  final String srcElementId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
  /// Arrow parameters.
 | 
					  /// Arrow parameters.
 | 
				
			||||||
  final ArrowParams arrowParams;
 | 
					  final ArrowParams arrowParams;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -374,6 +374,7 @@ class FlowElement<T extends FlowData> extends ChangeNotifier {
 | 
				
			|||||||
    graphElement['width'] = size.width;
 | 
					    graphElement['width'] = size.width;
 | 
				
			||||||
    graphElement['height'] = size.height;
 | 
					    graphElement['height'] = size.height;
 | 
				
			||||||
    graphElement['element']=element?.serialize();
 | 
					    graphElement['element']=element?.serialize();
 | 
				
			||||||
 | 
					    graphElement['next'] = next.map((x) => x.toMap()).toList();
 | 
				
			||||||
    return graphElement;
 | 
					    return graphElement;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -385,6 +386,13 @@ class FlowElement<T extends FlowData> extends ChangeNotifier {
 | 
				
			|||||||
        position: Offset(double.parse("${map['x']}"), double.parse("${map['y']}")),
 | 
					        position: Offset(double.parse("${map['x']}"), double.parse("${map['y']}")),
 | 
				
			||||||
        size: Size(double.parse("${map['width']}"), double.parse("${map['height']}")),
 | 
					        size: Size(double.parse("${map['width']}"), double.parse("${map['height']}")),
 | 
				
			||||||
        element: (dashboard.transformToData != null ? dashboard.transformToData!(map['element'] ?? {}) : null) as T?,
 | 
					        element: (dashboard.transformToData != null ? dashboard.transformToData!(map['element'] ?? {}) : null) as T?,
 | 
				
			||||||
 | 
					        /*next: map['next'] != null && (map['next'] as List).isNotEmpty
 | 
				
			||||||
 | 
					          ? List<ConnectionParams>.from(
 | 
				
			||||||
 | 
					              (map['next'] as List<dynamic>).map<dynamic>(
 | 
				
			||||||
 | 
					                (x) => ConnectionParams.fromMap(x as Map<String, dynamic>),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					          : []*/
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,29 +1,27 @@
 | 
				
			|||||||
// ignore: directives_ordering
 | 
					// ignore: directives_ordering
 | 
				
			||||||
import 'dart:developer';
 | 
					import 'package:uuid/uuid.dart';
 | 
				
			||||||
 | 
					 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:flutter/services.dart';
 | 
					import 'package:flutter/services.dart';
 | 
				
			||||||
import 'package:flutter/foundation.dart';
 | 
					import 'package:flutter/foundation.dart';
 | 
				
			||||||
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
 | 
					 | 
				
			||||||
import 'package:flutter_flow_chart/src/flow_chart_left_menu.dart';
 | 
					 | 
				
			||||||
import 'package:flutter_flow_chart/src/flow_chart_menu.dart';
 | 
					 | 
				
			||||||
import 'package:flutter_flow_chart/src/flow_chart_selected_menu.dart';
 | 
					 | 
				
			||||||
import 'package:flutter_flow_chart/src/ui/draw_arrow.dart';
 | 
					import 'package:flutter_flow_chart/src/ui/draw_arrow.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_flow_chart/flutter_flow_chart.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_flow_chart/src/flow_chart_menu.dart';
 | 
				
			||||||
import 'package:flutter_flow_chart/src/ui/element_widget.dart';
 | 
					import 'package:flutter_flow_chart/src/ui/element_widget.dart';
 | 
				
			||||||
import 'package:flutter_flow_chart/src/ui/grid_background.dart';
 | 
					import 'package:flutter_flow_chart/src/ui/grid_background.dart';
 | 
				
			||||||
import 'package:flutter_flow_chart/src/ui/segment_handler.dart';
 | 
					import 'package:flutter_flow_chart/src/ui/segment_handler.dart';
 | 
				
			||||||
import 'package:uuid/uuid.dart';
 | 
					import 'package:flutter_flow_chart/src/flow_chart_left_menu.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_flow_chart/src/flow_chart_selected_menu.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Main flow chart Widget.
 | 
					/// Main flow chart Widget.
 | 
				
			||||||
/// It displays the background grid, all the elements and connection lines
 | 
					/// It displays the background grid, all the elements and connection lines
 | 
				
			||||||
abstract class FlowData {
 | 
					abstract class FlowData {
 | 
				
			||||||
  String getID();
 | 
					  String getID();
 | 
				
			||||||
  String getName();
 | 
					  String getName();
 | 
				
			||||||
 | 
					  String getType();
 | 
				
			||||||
  double? getWidth();
 | 
					  double? getWidth();
 | 
				
			||||||
  double? getHeight();
 | 
					  double? getHeight();
 | 
				
			||||||
 | 
					  void addEnv(List<dynamic> infos);
 | 
				
			||||||
  Map<String, dynamic> setVariable(List<String> keys, dynamic value, Map<String, dynamic> map);
 | 
					 | 
				
			||||||
  dynamic getVariable(List<String> keys, Map<String, dynamic> map);
 | 
					 | 
				
			||||||
  Map<String, dynamic> serialize();
 | 
					  Map<String, dynamic> serialize();
 | 
				
			||||||
  FlowData deserialize(Map<String, dynamic> data);
 | 
					  FlowData deserialize(Map<String, dynamic> data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -321,17 +319,21 @@ class FlowChartState<T extends FlowData> extends State<FlowChart> {
 | 
				
			|||||||
        Future.delayed(Duration(milliseconds: 100), () => widget.dashboard.load!(widget.dashboard.id!) );    
 | 
					        Future.delayed(Duration(milliseconds: 100), () => widget.dashboard.load!(widget.dashboard.id!) );    
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        Future.delayed(Duration(milliseconds: 100), () {
 | 
					        Future.delayed(Duration(milliseconds: 100), () {
 | 
				
			||||||
          showDialog(
 | 
					          if (!widget.dashboard.inDialog) {
 | 
				
			||||||
          barrierDismissible: false,
 | 
					            widget.dashboard.inDialog = true;
 | 
				
			||||||
          context: context, builder: (context) {
 | 
					            showDialog(
 | 
				
			||||||
          return AlertDialog(
 | 
					              barrierDismissible: false,
 | 
				
			||||||
            titlePadding: EdgeInsets.zero,
 | 
					              context: context, builder: (context) {
 | 
				
			||||||
            insetPadding: EdgeInsets.zero,
 | 
					              return AlertDialog(
 | 
				
			||||||
            backgroundColor: Colors.white,
 | 
					                titlePadding: EdgeInsets.zero,
 | 
				
			||||||
            shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0)),
 | 
					                insetPadding: EdgeInsets.zero,
 | 
				
			||||||
            title: widget.onDashboardAlertOpened!(context, widget.dashboard));
 | 
					                backgroundColor: Colors.white,
 | 
				
			||||||
          
 | 
					                shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0)),
 | 
				
			||||||
        }); });
 | 
					                title: widget.onDashboardAlertOpened!(context, widget.dashboard));
 | 
				
			||||||
 | 
					              
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      widget.dashboard.isOpened  = true;
 | 
					      widget.dashboard.isOpened  = true;
 | 
				
			||||||
@@ -357,14 +359,14 @@ class FlowChartState<T extends FlowData> extends State<FlowChart> {
 | 
				
			|||||||
      onKeyEvent: (event) {
 | 
					      onKeyEvent: (event) {
 | 
				
			||||||
        bool change = false;
 | 
					        bool change = false;
 | 
				
			||||||
        if (event.logicalKey == LogicalKeyboardKey.controlLeft) {
 | 
					        if (event.logicalKey == LogicalKeyboardKey.controlLeft) {
 | 
				
			||||||
          isCtrl = event is KeyDownEvent ||   event is KeyRepeatEvent;
 | 
					          isCtrl = event is KeyDownEvent || event is KeyRepeatEvent;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (event is KeyDownEvent || event.logicalKey == LogicalKeyboardKey.keyZ && isCtrl) {
 | 
					        /*if ((event is KeyDownEvent || event.logicalKey == LogicalKeyboardKey.keyZ) && isCtrl) {
 | 
				
			||||||
          widget.dashboard.back();
 | 
					          widget.dashboard.back();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (event is KeyDownEvent || event.logicalKey == LogicalKeyboardKey.keyY && isCtrl) {
 | 
					        if ((event is KeyDownEvent || event.logicalKey == LogicalKeyboardKey.keyY) && isCtrl) {
 | 
				
			||||||
          widget.dashboard.forward();
 | 
					          widget.dashboard.forward();
 | 
				
			||||||
        }
 | 
					        }*/
 | 
				
			||||||
        if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.add) {
 | 
					        if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.add) {
 | 
				
			||||||
          change = true;
 | 
					          change = true;
 | 
				
			||||||
          for (var el in widget.dashboard.elementSelected) {
 | 
					          for (var el in widget.dashboard.elementSelected) {
 | 
				
			||||||
@@ -379,18 +381,18 @@ class FlowChartState<T extends FlowData> extends State<FlowChart> {
 | 
				
			|||||||
                kind: el.kind,
 | 
					                kind: el.kind,
 | 
				
			||||||
                handlers: el.handlers,
 | 
					                handlers: el.handlers,
 | 
				
			||||||
                handlerSize: el.handlerSize,
 | 
					                handlerSize: el.handlerSize,
 | 
				
			||||||
              ));
 | 
					              ), context);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.delete) {
 | 
					        if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.delete) {
 | 
				
			||||||
          change = true;
 | 
					          change = true;
 | 
				
			||||||
          widget.dashboard.removeElements( (el) => el.isSelected );
 | 
					          widget.dashboard.removeElements( (el) => el.isSelected, context );
 | 
				
			||||||
          for (var arrow in widget.dashboard.arrowsSelected) {
 | 
					          for (var arrow in widget.dashboard.arrowsSelected) {
 | 
				
			||||||
              for (var el in widget.dashboard.elements.where((element) => element.id == arrow.fromID.split("_")[0])) {
 | 
					              for (var el in widget.dashboard.elements.where((element) => element.id == arrow.fromID.split("_")[0])) {
 | 
				
			||||||
                el.next.removeAt(int.parse(arrow.fromID.split("_")[1]));
 | 
					                el.next.removeAt(int.parse(arrow.fromID.split("_")[1]));
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          widget.dashboard.removeArrows( (el) => el.isSelected );
 | 
					          widget.dashboard.removeArrows( (el) => el.isSelected, context );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (change) {
 | 
					        if (change) {
 | 
				
			||||||
          DrawingArrow.instance.notifyListeners();
 | 
					          DrawingArrow.instance.notifyListeners();
 | 
				
			||||||
@@ -459,7 +461,7 @@ class FlowChartState<T extends FlowData> extends State<FlowChart> {
 | 
				
			|||||||
                      Handler.rightCenter,
 | 
					                      Handler.rightCenter,
 | 
				
			||||||
                    ],
 | 
					                    ],
 | 
				
			||||||
                  );
 | 
					                  );
 | 
				
			||||||
              widget.dashboard.addElement(el);
 | 
					              widget.dashboard.addElement(el, context);
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
          ))]
 | 
					          ))]
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
@@ -495,8 +497,8 @@ class FlowChartState<T extends FlowData> extends State<FlowChart> {
 | 
				
			|||||||
        onDragEnd: (d) => node.requestFocus(),
 | 
					        onDragEnd: (d) => node.requestFocus(),
 | 
				
			||||||
        childWhenDragging: Opacity(opacity: .5, 
 | 
					        childWhenDragging: Opacity(opacity: .5, 
 | 
				
			||||||
        child: Padding( padding: const EdgeInsets.all(10), 
 | 
					        child: Padding( padding: const EdgeInsets.all(10), 
 | 
				
			||||||
          child: Container( child: widget.itemWidget(e), alignment: Alignment.center,
 | 
					          child: Container( alignment: Alignment.center,
 | 
				
			||||||
            constraints: BoxConstraints(maxHeight: realSize - 10, maxWidth: realSize - 10), ))),
 | 
					            constraints: BoxConstraints(maxHeight: realSize - 10, maxWidth: realSize - 10), child: widget.itemWidget(e), ))),
 | 
				
			||||||
        feedback: Container( alignment: Alignment.center, constraints: BoxConstraints(maxHeight: realSize, maxWidth: realSize),
 | 
					        feedback: Container( alignment: Alignment.center, constraints: BoxConstraints(maxHeight: realSize, maxWidth: realSize),
 | 
				
			||||||
          child: widget.itemWidget(e) ),
 | 
					          child: widget.itemWidget(e) ),
 | 
				
			||||||
        child: InkWell( mouseCursor: SystemMouseCursors.grab, child: Padding( padding: const EdgeInsets.all(10), 
 | 
					        child: InkWell( mouseCursor: SystemMouseCursors.grab, child: Padding( padding: const EdgeInsets.all(10), 
 | 
				
			||||||
@@ -548,6 +550,8 @@ class _DrawingArrowWidgetState extends State<DrawingArrowWidget> {
 | 
				
			|||||||
      painter: ArrowPainter(
 | 
					      painter: ArrowPainter(
 | 
				
			||||||
        fromID: DrawingArrow.instance.fromID,
 | 
					        fromID: DrawingArrow.instance.fromID,
 | 
				
			||||||
        toID: "",
 | 
					        toID: "",
 | 
				
			||||||
 | 
					        env: DrawingArrow.instance.env,
 | 
				
			||||||
 | 
					        infos: DrawingArrow.instance.infos,
 | 
				
			||||||
        params: DrawingArrow.instance.params,
 | 
					        params: DrawingArrow.instance.params,
 | 
				
			||||||
        from: DrawingArrow.instance.from,
 | 
					        from: DrawingArrow.instance.from,
 | 
				
			||||||
        to: DrawingArrow.instance.to,
 | 
					        to: DrawingArrow.instance.to,
 | 
				
			||||||
@@ -878,9 +882,7 @@ class ChartWidgetState<T extends FlowData> extends State<ChartWidget> {
 | 
				
			|||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
                  // Draw arrows        
 | 
					                  // Draw arrows        
 | 
				
			||||||
                  for (int i = 0; i < widget.dashboard.elements.length; i++)
 | 
					                  for (int i = 0; i < widget.dashboard.elements.length; i++)
 | 
				
			||||||
                    
 | 
					 | 
				
			||||||
                    for (int n = 0; n < widget.dashboard.elements[i].next.length; n++) 
 | 
					                    for (int n = 0; n < widget.dashboard.elements[i].next.length; n++) 
 | 
				
			||||||
                      
 | 
					 | 
				
			||||||
                      DrawArrow(
 | 
					                      DrawArrow(
 | 
				
			||||||
                        flow: this,
 | 
					                        flow: this,
 | 
				
			||||||
                        key: UniqueKey(),
 | 
					                        key: UniqueKey(),
 | 
				
			||||||
@@ -889,6 +891,8 @@ class ChartWidgetState<T extends FlowData> extends State<ChartWidget> {
 | 
				
			|||||||
                        destElement: widget.dashboard.elements[widget.dashboard.findElementIndexById(
 | 
					                        destElement: widget.dashboard.elements[widget.dashboard.findElementIndexById(
 | 
				
			||||||
                          widget.dashboard.elements[i].next[n].destElementId,
 | 
					                          widget.dashboard.elements[i].next[n].destElementId,
 | 
				
			||||||
                        )],
 | 
					                        )],
 | 
				
			||||||
 | 
					                        env: widget.dashboard.elements[i].next[n].env,
 | 
				
			||||||
 | 
					                        infos: widget.dashboard.elements[i].next[n].infos,
 | 
				
			||||||
                        arrowParams: widget.dashboard.elements[i].next[n].arrowParams,
 | 
					                        arrowParams: widget.dashboard.elements[i].next[n].arrowParams,
 | 
				
			||||||
                        pivots: widget.dashboard.elements[i].next[n].pivots,
 | 
					                        pivots: widget.dashboard.elements[i].next[n].pivots,
 | 
				
			||||||
                      ),
 | 
					                      ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,17 +37,20 @@ class FlowChartMenuState extends State<FlowChartMenu> {
 | 
				
			|||||||
                              onTap: () {
 | 
					                              onTap: () {
 | 
				
			||||||
                                widget.dashboard.name = "graph_${DateTime.now().toString().replaceAll(" ", "_").substring(0, DateTime.now().toString().length - 7)}";
 | 
					                                widget.dashboard.name = "graph_${DateTime.now().toString().replaceAll(" ", "_").substring(0, DateTime.now().toString().length - 7)}";
 | 
				
			||||||
                                widget.dashboard.isOpened = true;
 | 
					                                widget.dashboard.isOpened = true;
 | 
				
			||||||
                                showDialog(
 | 
					                                if (!widget.dashboard.inDialog) {
 | 
				
			||||||
                                    barrierDismissible: false,
 | 
					                                  widget.dashboard.inDialog = true;
 | 
				
			||||||
                                    context: context, builder: (context) {
 | 
					                                  showDialog(
 | 
				
			||||||
                                    return AlertDialog(
 | 
					                                      barrierDismissible: false,
 | 
				
			||||||
                                      titlePadding: EdgeInsets.zero,
 | 
					                                      context: context, builder: (context) {
 | 
				
			||||||
                                      insetPadding: EdgeInsets.zero,
 | 
					                                      return AlertDialog(
 | 
				
			||||||
                                      backgroundColor: Colors.white,
 | 
					                                        titlePadding: EdgeInsets.zero,
 | 
				
			||||||
                                      shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0)),
 | 
					                                        insetPadding: EdgeInsets.zero,
 | 
				
			||||||
                                      title: widget.chart.widget.flowChart.widget.onDashboardAlertOpened!(
 | 
					                                        backgroundColor: Colors.white,
 | 
				
			||||||
                                        context, widget.dashboard));
 | 
					                                        shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0)),
 | 
				
			||||||
                                  });
 | 
					                                        title: widget.chart.widget.flowChart.widget.onDashboardAlertOpened!(
 | 
				
			||||||
 | 
					                                          context, widget.dashboard));
 | 
				
			||||||
 | 
					                                    });
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
                              }, 
 | 
					                              }, 
 | 
				
			||||||
                              child: Icon(Icons.folder, color: Colors.white))))),
 | 
					                              child: Icon(Icons.folder, color: Colors.white))))),
 | 
				
			||||||
                        ])),
 | 
					                        ])),
 | 
				
			||||||
@@ -57,8 +60,6 @@ class FlowChartMenuState extends State<FlowChartMenu> {
 | 
				
			|||||||
                        ),
 | 
					                        ),
 | 
				
			||||||
                        child: Padding( padding: EdgeInsets.symmetric(horizontal: 10), 
 | 
					                        child: Padding( padding: EdgeInsets.symmetric(horizontal: 10), 
 | 
				
			||||||
                          child: PopupMenuButton<DisplayEnum>(
 | 
					                          child: PopupMenuButton<DisplayEnum>(
 | 
				
			||||||
                            child: 
 | 
					 | 
				
			||||||
                            Row( children: [ Icon(Icons.fullscreen, color: Colors.white), Icon(Icons.arrow_drop_down, size: 10, color: Colors.white) ]),
 | 
					 | 
				
			||||||
                            initialValue: null,
 | 
					                            initialValue: null,
 | 
				
			||||||
                            onSelected: (DisplayEnum value) {
 | 
					                            onSelected: (DisplayEnum value) {
 | 
				
			||||||
                              if (value == DisplayEnum.MENU) {  widget.dashboard.isMenu = !widget.dashboard.isMenu; }
 | 
					                              if (value == DisplayEnum.MENU) {  widget.dashboard.isMenu = !widget.dashboard.isMenu; }
 | 
				
			||||||
@@ -83,7 +84,9 @@ class FlowChartMenuState extends State<FlowChartMenu> {
 | 
				
			|||||||
                                      child: Text(widget.dashboard.isInfo ? 'hide info' : 'show info', textAlign: TextAlign.center,))
 | 
					                                      child: Text(widget.dashboard.isInfo ? 'hide info' : 'show info', textAlign: TextAlign.center,))
 | 
				
			||||||
                                ]),
 | 
					                                ]),
 | 
				
			||||||
                              ),
 | 
					                              ),
 | 
				
			||||||
                            ]
 | 
					                            ],
 | 
				
			||||||
 | 
					                            child: 
 | 
				
			||||||
 | 
					                            Row( children: [ Icon(Icons.fullscreen, color: Colors.white), Icon(Icons.arrow_drop_down, size: 10, color: Colors.white) ])
 | 
				
			||||||
                            ),)
 | 
					                            ),)
 | 
				
			||||||
                        )
 | 
					                        )
 | 
				
			||||||
                      ),
 | 
					                      ),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,10 +36,10 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
 | 
				
			|||||||
                                    widget.dashboard.elements[element.elementIndex!].next.removeAt(element.connIndex!);
 | 
					                                    widget.dashboard.elements[element.elementIndex!].next.removeAt(element.connIndex!);
 | 
				
			||||||
                                  }
 | 
					                                  }
 | 
				
			||||||
                                  return element.isSelected;
 | 
					                                  return element.isSelected;
 | 
				
			||||||
                                }); 
 | 
					                                }, context); 
 | 
				
			||||||
                                widget.dashboard.removeElements((element) => element.isSelected); 
 | 
					                                widget.dashboard.removeElements((element) => element.isSelected, context); 
 | 
				
			||||||
                                Future.delayed(Duration(milliseconds: 100), () {
 | 
					                                Future.delayed(Duration(milliseconds: 100), () {
 | 
				
			||||||
                                  widget.dashboard.chartKey.currentState?.setState(() { });
 | 
					                                  widget.dashboard.flutterChartKey.currentState?.setState(() { });
 | 
				
			||||||
                                });
 | 
					                                });
 | 
				
			||||||
                              }, child: Container( margin: EdgeInsets.all(10),
 | 
					                              }, child: Container( margin: EdgeInsets.all(10),
 | 
				
			||||||
                                decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.black, width: 1)),
 | 
					                                decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.black, width: 1)),
 | 
				
			||||||
@@ -51,7 +51,7 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
 | 
				
			|||||||
                              child: InkWell( mouseCursor: SystemMouseCursors.click, 
 | 
					                              child: InkWell( mouseCursor: SystemMouseCursors.click, 
 | 
				
			||||||
                              onTap: () {
 | 
					                              onTap: () {
 | 
				
			||||||
                                for (var sel in widget.dashboard.elementSelected) {
 | 
					                                for (var sel in widget.dashboard.elementSelected) {
 | 
				
			||||||
                                  widget.dashboard.addElement(FlowElement.fromMap(widget.dashboard, sel.toMap()));
 | 
					                                  widget.dashboard.addElement(FlowElement.fromMap(widget.dashboard, sel.toMap()), context);
 | 
				
			||||||
                                  widget.dashboard.elements.last.position += Offset(50, 50);
 | 
					                                  widget.dashboard.elements.last.position += Offset(50, 50);
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                                Future.delayed(Duration(milliseconds: 100), () {
 | 
					                                Future.delayed(Duration(milliseconds: 100), () {
 | 
				
			||||||
@@ -67,6 +67,42 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
 | 
				
			|||||||
                        ) : Container()
 | 
					                        ) : Container()
 | 
				
			||||||
        ])
 | 
					        ])
 | 
				
			||||||
      ));
 | 
					      ));
 | 
				
			||||||
 | 
					    } else if (widget.isDashboardInfo && widget.dashboard.arrowsSelected.length == 1) {
 | 
				
			||||||
 | 
					      w = Container(
 | 
				
			||||||
 | 
					        width: 200,
 | 
				
			||||||
 | 
					        height: widget.height,
 | 
				
			||||||
 | 
					        color: widget.dashboard.midDashColor,
 | 
				
			||||||
 | 
					        child: SingleChildScrollView( child: Column( children: [ 
 | 
				
			||||||
 | 
					          widget.dashboard.infoItemWidget != null ?
 | 
				
			||||||
 | 
					          widget.dashboard.infoLinkWidget!(widget.dashboard.arrowsSelected.first) : Container(),
 | 
				
			||||||
 | 
					          widget.dashboard.arrowsSelected.isNotEmpty || widget.dashboard.elementSelected.isNotEmpty ? Container( 
 | 
				
			||||||
 | 
					                          width: 200,
 | 
				
			||||||
 | 
					                          margin: EdgeInsets.only(top: 15),
 | 
				
			||||||
 | 
					                          decoration: BoxDecoration(border: Border(
 | 
				
			||||||
 | 
					                            top: BorderSide(color: Colors.grey, width: 1))),
 | 
				
			||||||
 | 
					                          child: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
 | 
				
			||||||
 | 
					                            Tooltip( message: "remove",
 | 
				
			||||||
 | 
					                              child: InkWell( mouseCursor: SystemMouseCursors.click, 
 | 
				
			||||||
 | 
					                              onTap: () {
 | 
				
			||||||
 | 
					                                widget.dashboard.removeArrows((element) { 
 | 
				
			||||||
 | 
					                                  if (element.isSelected && element.elementIndex != null && element.connIndex != null) {
 | 
				
			||||||
 | 
					                                    widget.dashboard.elements[element.elementIndex!].next.removeAt(element.connIndex!);
 | 
				
			||||||
 | 
					                                  }
 | 
				
			||||||
 | 
					                                  return element.isSelected;
 | 
				
			||||||
 | 
					                                }, context); 
 | 
				
			||||||
 | 
					                                Future.delayed(Duration(milliseconds: 100), () {
 | 
				
			||||||
 | 
					                                  widget.dashboard.flutterChartKey.currentState?.setState(() { });
 | 
				
			||||||
 | 
					                                });
 | 
				
			||||||
 | 
					                              }, child: Container( margin: EdgeInsets.all(10),
 | 
				
			||||||
 | 
					                                decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.black, width: 1)),
 | 
				
			||||||
 | 
					                                width: 200, height: 30,
 | 
				
			||||||
 | 
					                                child: Icon(Icons.delete_outline, color: Colors.black),
 | 
				
			||||||
 | 
					                              ))
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                          ])
 | 
				
			||||||
 | 
					                        ) : Container()
 | 
				
			||||||
 | 
					        ])
 | 
				
			||||||
 | 
					      ));
 | 
				
			||||||
    } else if (widget.isDashboardInfo && widget.dashboard.infoWidget != null) {
 | 
					    } else if (widget.isDashboardInfo && widget.dashboard.infoWidget != null) {
 | 
				
			||||||
       w = Container(
 | 
					       w = Container(
 | 
				
			||||||
        width: 200,
 | 
					        width: 200,
 | 
				
			||||||
@@ -520,10 +556,10 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
 | 
				
			|||||||
                                    widget.dashboard.elements[element.elementIndex!].next.removeAt(element.connIndex!);
 | 
					                                    widget.dashboard.elements[element.elementIndex!].next.removeAt(element.connIndex!);
 | 
				
			||||||
                                  }
 | 
					                                  }
 | 
				
			||||||
                                  return element.isSelected;
 | 
					                                  return element.isSelected;
 | 
				
			||||||
                                }); 
 | 
					                                }, context); 
 | 
				
			||||||
                                widget.dashboard.removeElements((element) => element.isSelected); 
 | 
					                                widget.dashboard.removeElements((element) => element.isSelected, context); 
 | 
				
			||||||
                                Future.delayed(Duration(milliseconds: 100), () {
 | 
					                                Future.delayed(Duration(milliseconds: 100), () {
 | 
				
			||||||
                                  widget.dashboard.chartKey.currentState?.setState(() { });
 | 
					                                  widget.dashboard.flutterChartKey.currentState?.setState(() { });
 | 
				
			||||||
                                });
 | 
					                                });
 | 
				
			||||||
                              }, child: Container( margin: EdgeInsets.all(10),
 | 
					                              }, child: Container( margin: EdgeInsets.all(10),
 | 
				
			||||||
                                decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.black, width: 1)),
 | 
					                                decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.black, width: 1)),
 | 
				
			||||||
@@ -535,7 +571,7 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
 | 
				
			|||||||
                              child: InkWell( mouseCursor: SystemMouseCursors.click, 
 | 
					                              child: InkWell( mouseCursor: SystemMouseCursors.click, 
 | 
				
			||||||
                              onTap: () {
 | 
					                              onTap: () {
 | 
				
			||||||
                                for (var sel in widget.dashboard.elementSelected) {
 | 
					                                for (var sel in widget.dashboard.elementSelected) {
 | 
				
			||||||
                                  widget.dashboard.addElement(FlowElement.fromMap(widget.dashboard, sel.toMap()));
 | 
					                                  widget.dashboard.addElement(FlowElement.fromMap(widget.dashboard, sel.toMap()), context);
 | 
				
			||||||
                                  widget.dashboard.elements.last.position += Offset(50, 50);
 | 
					                                  widget.dashboard.elements.last.position += Offset(50, 50);
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                                Future.delayed(Duration(milliseconds: 100), () {
 | 
					                                Future.delayed(Duration(milliseconds: 100), () {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -211,6 +211,8 @@ class DrawingArrow extends ChangeNotifier {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  /// Arrow parameters.
 | 
					  /// Arrow parameters.
 | 
				
			||||||
  ArrowParams params = ArrowParams();
 | 
					  ArrowParams params = ArrowParams();
 | 
				
			||||||
 | 
					  List<dynamic> env = [];
 | 
				
			||||||
 | 
					  List<dynamic> infos = [];
 | 
				
			||||||
  String fromID = "";
 | 
					  String fromID = "";
 | 
				
			||||||
  String toID = "";
 | 
					  String toID = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -264,13 +266,16 @@ class DrawArrow extends StatefulWidget {
 | 
				
			|||||||
    required this.srcElement,
 | 
					    required this.srcElement,
 | 
				
			||||||
    required this.destElement,
 | 
					    required this.destElement,
 | 
				
			||||||
    required List<Pivot> pivots,
 | 
					    required List<Pivot> pivots,
 | 
				
			||||||
 | 
					    this.infos = const [],
 | 
				
			||||||
 | 
					    this.env = const [],
 | 
				
			||||||
    super.key,
 | 
					    super.key,
 | 
				
			||||||
    ArrowParams? arrowParams,
 | 
					    ArrowParams? arrowParams,
 | 
				
			||||||
  })  : arrowParams = arrowParams ?? ArrowParams(),
 | 
					  })  : arrowParams = arrowParams ?? ArrowParams(),
 | 
				
			||||||
        pivots = PivotsNotifier(pivots);
 | 
					        pivots = PivotsNotifier(pivots);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  final int index;
 | 
					  final int index;
 | 
				
			||||||
 | 
					   List<dynamic> env = [];
 | 
				
			||||||
 | 
					  List<dynamic> infos = [];
 | 
				
			||||||
  ///
 | 
					  ///
 | 
				
			||||||
  final ArrowParams arrowParams;
 | 
					  final ArrowParams arrowParams;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -340,6 +345,8 @@ class DrawArrowState extends State<DrawArrow> {
 | 
				
			|||||||
          builder: (context) {
 | 
					          builder: (context) {
 | 
				
			||||||
            var painter = ArrowPainter(
 | 
					            var painter = ArrowPainter(
 | 
				
			||||||
                connIndex: widget.index,
 | 
					                connIndex: widget.index,
 | 
				
			||||||
 | 
					                infos: widget.infos,
 | 
				
			||||||
 | 
					                env: widget.env,
 | 
				
			||||||
                elementIndex: widget.flow.widget.dashboard.elements.indexOf(widget.srcElement),
 | 
					                elementIndex: widget.flow.widget.dashboard.elements.indexOf(widget.srcElement),
 | 
				
			||||||
                fromID: "${widget.srcElement.id}_${widget.index}",
 | 
					                fromID: "${widget.srcElement.id}_${widget.index}",
 | 
				
			||||||
                toID: "${widget.destElement.id}_${widget.index}",
 | 
					                toID: "${widget.destElement.id}_${widget.index}",
 | 
				
			||||||
@@ -351,8 +358,8 @@ class DrawArrowState extends State<DrawArrow> {
 | 
				
			|||||||
              );
 | 
					              );
 | 
				
			||||||
            if ( widget.flow.widget.dashboard.arrows.where(
 | 
					            if ( widget.flow.widget.dashboard.arrows.where(
 | 
				
			||||||
                  (element) => element.fromID == "${widget.srcElement.id}_${widget.index}").isEmpty) {
 | 
					                  (element) => element.fromID == "${widget.srcElement.id}_${widget.index}").isEmpty) {
 | 
				
			||||||
                widget.flow.widget.dashboard.addArrows(painter); 
 | 
					                widget.flow.widget.dashboard.addArrows(painter, context); 
 | 
				
			||||||
                widget.flow.widget.dashboard.saveDash(widget.flow.widget.dashboard.id);
 | 
					                widget.flow.widget.dashboard.saveDash(widget.flow.widget.dashboard.id, context);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
              var i = widget.flow.widget.dashboard.arrows.indexWhere(
 | 
					              var i = widget.flow.widget.dashboard.arrows.indexWhere(
 | 
				
			||||||
                  (element) => element.fromID == "${widget.srcElement.id}_${widget.index}");
 | 
					                  (element) => element.fromID == "${widget.srcElement.id}_${widget.index}");
 | 
				
			||||||
@@ -390,7 +397,7 @@ class GraphParamsWidgetState extends State<GraphParamsWidget> {
 | 
				
			|||||||
      child: Row(children: [
 | 
					      child: Row(children: [
 | 
				
			||||||
        IconButton(onPressed: () {
 | 
					        IconButton(onPressed: () {
 | 
				
			||||||
          widget.comp.setState(() {
 | 
					          widget.comp.setState(() {
 | 
				
			||||||
            widget.comp.widget.dashboard.removeArrows((el) => el.fromID == "${widget.element.id}${widget.index}");
 | 
					            widget.comp.widget.dashboard.removeArrows((el) => el.fromID == "${widget.element.id}${widget.index}", context);
 | 
				
			||||||
            widget.element.next.removeAt(widget.index);
 | 
					            widget.element.next.removeAt(widget.index);
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
        }, icon: Icon(Icons.delete))
 | 
					        }, icon: Icon(Icons.delete))
 | 
				
			||||||
@@ -421,13 +428,13 @@ class ArrowInfoWidgetState extends State<ArrowInfoWidget> {
 | 
				
			|||||||
/// [ArrowParams.startArrowPosition] and
 | 
					/// [ArrowParams.startArrowPosition] and
 | 
				
			||||||
/// [ArrowParams.endArrowPosition] alignment.
 | 
					/// [ArrowParams.endArrowPosition] alignment.
 | 
				
			||||||
class ArrowPainter extends CustomPainter {
 | 
					class ArrowPainter extends CustomPainter {
 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  ///
 | 
					 | 
				
			||||||
  ArrowPainter({
 | 
					  ArrowPainter({
 | 
				
			||||||
    this.elementIndex,
 | 
					    this.elementIndex,
 | 
				
			||||||
    this.connIndex,
 | 
					    this.connIndex,
 | 
				
			||||||
    this.toID = "",
 | 
					    this.toID = "",
 | 
				
			||||||
    this.fromID = "",
 | 
					    this.fromID = "",
 | 
				
			||||||
 | 
					    this.infos = const [],
 | 
				
			||||||
 | 
					    this.env  = const [],
 | 
				
			||||||
    this.isSelected = false,
 | 
					    this.isSelected = false,
 | 
				
			||||||
    required this.params,
 | 
					    required this.params,
 | 
				
			||||||
    this.from = Offset.zero,
 | 
					    this.from = Offset.zero,
 | 
				
			||||||
@@ -435,9 +442,9 @@ class ArrowPainter extends CustomPainter {
 | 
				
			|||||||
    List<Pivot>? pivots, 
 | 
					    List<Pivot>? pivots, 
 | 
				
			||||||
  }) : pivots = pivots ?? [];
 | 
					  }) : pivots = pivots ?? [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ///
 | 
					  List<dynamic> env;
 | 
				
			||||||
 | 
					  List<dynamic> infos;
 | 
				
			||||||
  ArrowParams params;
 | 
					  ArrowParams params;
 | 
				
			||||||
  ///
 | 
					 | 
				
			||||||
  String toID;
 | 
					  String toID;
 | 
				
			||||||
  String fromID;
 | 
					  String fromID;
 | 
				
			||||||
  Offset to;
 | 
					  Offset to;
 | 
				
			||||||
@@ -462,6 +469,8 @@ class ArrowPainter extends CustomPainter {
 | 
				
			|||||||
  final arrowAngle=  25 * math.pi / 180;
 | 
					  final arrowAngle=  25 * math.pi / 180;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ArrowPainter deserialize(Map<String, dynamic> map) {
 | 
					  ArrowPainter deserialize(Map<String, dynamic> map) {
 | 
				
			||||||
 | 
					    infos = map['infos'];
 | 
				
			||||||
 | 
					    env = map['env'];
 | 
				
			||||||
    params = ArrowParams.fromMap(map['params']);
 | 
					    params = ArrowParams.fromMap(map['params']);
 | 
				
			||||||
    fromID = map['from']['id'];
 | 
					    fromID = map['from']['id'];
 | 
				
			||||||
    toID = map['to']['id'];
 | 
					    toID = map['to']['id'];
 | 
				
			||||||
@@ -469,9 +478,10 @@ class ArrowPainter extends CustomPainter {
 | 
				
			|||||||
    to = Offset(map['to']['x'], map['to']['y']);
 | 
					    to = Offset(map['to']['x'], map['to']['y']);
 | 
				
			||||||
    return this;
 | 
					    return this;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  Map<String, dynamic> serialize() {
 | 
					  Map<String, dynamic> serialize() {
 | 
				
			||||||
    Map<String, dynamic> graphElement = {};
 | 
					    Map<String, dynamic> graphElement = {};
 | 
				
			||||||
 | 
					    graphElement['infos'] = infos;
 | 
				
			||||||
 | 
					    graphElement['env'] = env;
 | 
				
			||||||
    graphElement['from'] = { "id" : fromID.split("_")[0], "x" : from.dx, "y" : from.dy };
 | 
					    graphElement['from'] = { "id" : fromID.split("_")[0], "x" : from.dx, "y" : from.dy };
 | 
				
			||||||
    graphElement['to'] = { "id" : toID.split("_")[0], "x" : to.dx, "y" : to.dy };
 | 
					    graphElement['to'] = { "id" : toID.split("_")[0], "x" : to.dx, "y" : to.dy };
 | 
				
			||||||
    graphElement['params'] = params.toMap();
 | 
					    graphElement['params'] = params.toMap();
 | 
				
			||||||
@@ -484,6 +494,8 @@ class ArrowPainter extends CustomPainter {
 | 
				
			|||||||
      elementIndex: map['elementIndex'] as int,
 | 
					      elementIndex: map['elementIndex'] as int,
 | 
				
			||||||
      toID: map['toID'] != null ? map['toID'] as String : "",
 | 
					      toID: map['toID'] != null ? map['toID'] as String : "",
 | 
				
			||||||
      fromID: map['fromID'] as String,
 | 
					      fromID: map['fromID'] as String,
 | 
				
			||||||
 | 
					      infos: map['infos'] as List,
 | 
				
			||||||
 | 
					      env: map['env'] as List,
 | 
				
			||||||
      isSelected: map['isSelected'] != null ? map['isSelected'] as bool : false,
 | 
					      isSelected: map['isSelected'] != null ? map['isSelected'] as bool : false,
 | 
				
			||||||
      params: ArrowParams.fromMap(map['params']),
 | 
					      params: ArrowParams.fromMap(map['params']),
 | 
				
			||||||
      from: Offset(
 | 
					      from: Offset(
 | 
				
			||||||
@@ -511,6 +523,8 @@ class ArrowPainter extends CustomPainter {
 | 
				
			|||||||
        "fromDy" : from.dy,
 | 
					        "fromDy" : from.dy,
 | 
				
			||||||
        "toDx" : to.dx,
 | 
					        "toDx" : to.dx,
 | 
				
			||||||
        "toDy" : to.dy,
 | 
					        "toDy" : to.dy,
 | 
				
			||||||
 | 
					        "infos" : infos,
 | 
				
			||||||
 | 
					        "env" : env,
 | 
				
			||||||
        'pivots': pivots.map((e) => e.toMap()).toList(),
 | 
					        'pivots': pivots.map((e) => e.toMap()).toList(),
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -151,12 +151,15 @@ class ElementWidgetState<T extends FlowData>  extends State<ElementWidget> {
 | 
				
			|||||||
              for (var element in widget.dashboard.elements) { 
 | 
					              for (var element in widget.dashboard.elements) { 
 | 
				
			||||||
                element.isSelected = false; 
 | 
					                element.isSelected = false; 
 | 
				
			||||||
                element.dashboard.chartKey.currentState?. setState(() { });
 | 
					                element.dashboard.chartKey.currentState?. setState(() { });
 | 
				
			||||||
 | 
					                widget.dashboard.selectedMenuKey.currentState?. setState(() { });
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            widget.element.isSelected = !widget.element.isSelected; 
 | 
					            Future.delayed(Duration(milliseconds: 100), () { 
 | 
				
			||||||
            for (var sel in widget.dashboard.arrows) { sel.isSelected = false; }
 | 
					              DrawingArrow.instance.notifyListeners(); 
 | 
				
			||||||
            widget.dashboard.selectedMenuKey.currentState?. setState(() { });
 | 
					              widget.element.isSelected = !widget.element.isSelected; 
 | 
				
			||||||
            Future.delayed(Duration(seconds: 1), () { DrawingArrow.instance.notifyListeners(); });
 | 
					              for (var sel in widget.dashboard.arrows) { sel.isSelected = false; }
 | 
				
			||||||
 | 
					              widget.dashboard.selectedMenuKey.currentState?. setState(() { });
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
          widget.onElementPressed?.call(context, tapLocation);
 | 
					          widget.onElementPressed?.call(context, tapLocation);
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
@@ -234,7 +237,7 @@ class ElementWidgetState<T extends FlowData>  extends State<ElementWidget> {
 | 
				
			|||||||
                  sel.changePosition(sel.position + diff);
 | 
					                  sel.changePosition(sel.position + diff);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
              widget.dashboard.save!(widget.dashboard.id);
 | 
					              widget.dashboard.saveDash(widget.dashboard.id, context);
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
@@ -263,7 +266,7 @@ class ElementWidgetState<T extends FlowData>  extends State<ElementWidget> {
 | 
				
			|||||||
            child: Row( mainAxisAlignment: MainAxisAlignment.center, 
 | 
					            child: Row( mainAxisAlignment: MainAxisAlignment.center, 
 | 
				
			||||||
              children: (!widget.isHovered ? [] : [
 | 
					              children: (!widget.isHovered ? [] : [
 | 
				
			||||||
              IconButton(tooltip: "remove element", onPressed: () {
 | 
					              IconButton(tooltip: "remove element", onPressed: () {
 | 
				
			||||||
                widget.dashboard.removeElement(widget.element);
 | 
					                widget.dashboard.removeElement(widget.element, context);
 | 
				
			||||||
              }, icon: Icon(Icons.delete_outline)),
 | 
					              }, icon: Icon(Icons.delete_outline)),
 | 
				
			||||||
              IconButton(tooltip: "copy element", onPressed: () {
 | 
					              IconButton(tooltip: "copy element", onPressed: () {
 | 
				
			||||||
                FlowElement<T> newElement = FlowElement<T>(
 | 
					                FlowElement<T> newElement = FlowElement<T>(
 | 
				
			||||||
@@ -274,7 +277,7 @@ class ElementWidgetState<T extends FlowData>  extends State<ElementWidget> {
 | 
				
			|||||||
                  size: widget.element.size,
 | 
					                  size: widget.element.size,
 | 
				
			||||||
                  widget: widget.element.widget,
 | 
					                  widget: widget.element.widget,
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
                widget.dashboard.addElement(newElement);
 | 
					                widget.dashboard.addElement(newElement, context);
 | 
				
			||||||
              }, icon: Icon(Icons.copy, size: 20)),
 | 
					              }, icon: Icon(Icons.copy, size: 20)),
 | 
				
			||||||
            ]))
 | 
					            ]))
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user