import 'package:flutter/material.dart'; import 'package:flutter_colorpicker/flutter_colorpicker.dart'; import 'package:flutter_flow_chart/flutter_flow_chart.dart'; import 'package:oc_front/models/abstract.dart'; import 'package:oc_front/models/logs.dart'; import 'package:oc_front/models/resources/compute.dart'; import 'package:oc_front/models/resources/data.dart'; import 'package:oc_front/models/resources/processing.dart'; import 'package:oc_front/models/resources/resources.dart'; import 'package:oc_front/models/resources/storage.dart'; import 'package:oc_front/models/resources/workflow.dart'; import 'package:oc_front/models/response.dart'; import 'package:oc_front/widgets/forms/sub_keys_forms.dart'; class Check extends SerializerDeserializer { bool isAvailable = false; Check({ this.isAvailable = false, }); @override deserialize(dynamic json) { try { json = json as Map; } catch (e) { return Check(); } return Check( isAvailable: json.containsKey("is_available") ? json["is_available"] : false, ); } @override Map serialize() { return { "is_available": isAvailable, }; } } class WorkflowExecutions extends SerializerDeserializer { List executions = []; WorkflowExecutions({ this.executions = const [], }); @override deserialize(dynamic json) { try { json = json as List; } catch (e) { return WorkflowExecutions(); } return WorkflowExecutions( executions: fromListJson(json, WorkflowExecution()), ); } @override Map serialize() { return {}; } } class WorkflowExecution extends SerializerDeserializer { String? id; String? name; String? startDate; String? endDate; int? status; String? workflowId; List? logs; WorkflowExecution({ this.id, this.startDate, this.status, this.workflowId, this.name, this.endDate, }); @override deserialize(dynamic json) { try { json = json as Map; } catch (e) { return WorkflowExecution(); } return WorkflowExecution( id: json.containsKey("id") ? json["id"] : "", endDate: json.containsKey("end_date") ? json["end_date"] : "", startDate: json.containsKey("execution_date") ? json["execution_date"] : "", status: json.containsKey("state") ? json["state"] : 1, workflowId: json.containsKey("workflow_id") ? json["workflow_id"] : "", name: json.containsKey("name") ? json["name"] : "", ); } @override Map serialize() { return { "id": id, "name": name, "end_date": endDate, "execution_data": startDate, "status": status, "workflow_id": workflowId, }; } } class Workflow extends SerializerDeserializer implements ShallowData { String? id; String? name; List data; List compute; List storage; List processing; List workflows; Graph? graph; List shared; Workflow({ this.id, this.name = "", this.data = const [], this.compute = const [], this.storage = const [], this.processing = const [], this.workflows = const [], this.graph, this.shared = const [], }); @override String getID() => id ?? ""; @override String getName() => name ?? ""; String getDescription() => ""; @override deserialize(dynamic json) { try { json = json as Map; } catch (e) { return Workflow(); } return Workflow( id: json.containsKey("id") ? json["id"] : "", name: json.containsKey("name") ? json["name"] : "", workflows: json.containsKey("workflows") ? json["workflows"] : [], processing: json.containsKey("processings") ? json["processings"] : [], compute: json.containsKey("computes") ? json["computes"] : [], data: json.containsKey("datas") ? json["datas"] : [], storage: json.containsKey("storages") ? json["storages"] : [], shared: json.containsKey("shared") ? json["shared"] : [], graph: json.containsKey("graph") ? Graph().deserialize(json["graph"]) : null, ); } @override Map serialize() { var obj = { "id": id, "name": name, "datas": data, "storages": storage, "computes" : compute, "workflows": workflows, "processings": processing, }; if (graph != null) { obj["graph"] = graph!.serialize(); } return obj; } void fromDashboard(Map j) { id = j["id"]; name = j["name"]; if (j.containsKey("graph")) { graph = Graph(); graph!.fromDashboard(j["graph"]); } } Map toDashboard() { return { "id": id, "name": name, "shared": shared, "graph": graph?.toDashboard(), }; } } class Scheduler extends SerializerDeserializer { String? id; String? name; String? cron; DateTime? start; DateTime? end; int? mode; Scheduler({ this.id, this.name, this.cron, this.start, this.end, this.mode, }); void fromDashboard(Map j) { id = j["id"]; name = j["name"]; cron = j["cron"]; mode =j["mode"]; try { start = j["start"] != null ? DateTime.parse(j["start"]) : DateTime.now().add( const Duration(minutes: 1)).toUtc(); if (start == DateTime.utc(0)) { start = DateTime.now().add( const Duration(minutes: 1)).toUtc(); } if (j.containsKey("end") && j["end"] != null) { end = DateTime.parse(j["end"]); } } catch (e) { /**/ } } Map toDashboard() { return { "id": id, "name": name, "cron": cron, "mode": mode ?? 1, "start": start?.toIso8601String(), "end": end?.toIso8601String(), }; } @override deserialize(dynamic json) { try { json = json as Map; } catch (e) { return Scheduler(); } return Scheduler( id: json.containsKey("id") ? json["id"] : null, name: json.containsKey("name") ? json["name"] : "", cron: json.containsKey("cron") ? json["cron"] : "", mode: json.containsKey("mode") ? json["mode"] : "", start: json.containsKey("start") && json["start"] != null ? DateTime.parse(json["start"]) : null, end: json.containsKey("end") && json["end"] != null ? DateTime.parse(json["end"]) : null, ); } @override Map serialize() { try { return { "id": id, "name": name, "cron": cron ?? "", "mode": mode ?? 1, "start": start?.toIso8601String(), "end": end?.toIso8601String(), }; } catch (e) { return { "id": id, "name": name, "cron": cron ?? "", "start": start?.toIso8601String(), "end": end?.toIso8601String(), }; } } } class Graph extends SerializerDeserializer { double zoom; Map items = {}; List links = []; Graph({ this.zoom = 1, this.items = const {}, this.links = const [], }); Map> getInfosToUpdate(SubMapFormsType type) { Map> infos = {}; for (var item in items.values) { var inst = item.getElement()?.getSelectedInstance(); if (inst == null) { return infos; } infos[item.id ?? ""] = (type == SubMapFormsType.INPUT ? inst.inputs : ( type == SubMapFormsType.OUTPUT ? inst.outputs : inst.env)).map( (e) => e.serialize()).toList(); } return infos; } Map> getEnvToUpdate() { return getInfosToUpdate(SubMapFormsType.ENV); } Map> getInputToUpdate() { return getInfosToUpdate(SubMapFormsType.INPUT); } Map> getOutputToUpdate() { return getInfosToUpdate(SubMapFormsType.OUTPUT); } GraphItem getItemByElementID(String id) { return items[id] ?? GraphItem(); } Map getArrowByElementID(String id) { Map arr = {}; for (var link in links) { var nested = false; var reverse = false; String? from = link.source?.id; String? to = link.destination?.id; bool isInLink = (from?.contains(id) ?? false) || (to?.contains(id) ?? false); if (isInLink && (["storage", "compute"].contains(getItemByElementID(from ?? "").getElement()?.getType()) || ["storage", "compute"].contains(getItemByElementID(to ?? "").getElement()?.getType()))) { nested = true; reverse = link.source?.id?.contains(id) ?? false; } if (nested || isInLink) { arr[reverse ? (to ?? "") : (from ?? "") ] = getItemByElementID(reverse ? (to ?? "") : (from ?? "") ); } } return arr; } void fillEnv(AbstractItem? mainItem, GraphItem? item, SubMapFormsType type, Map alreadySeen) { if (mainItem == null || item == null) { return; } AbstractItem? el = item.getElement(); if (el?.getSelectedInstance() == null) { return; } var inst = el!.getSelectedInstance()!; var inst2 = mainItem.getSelectedInstance()!; var what = type == SubMapFormsType.INPUT ? inst.inputs : ( type == SubMapFormsType.OUTPUT ? inst.outputs : inst.env); var what2 = type == SubMapFormsType.INPUT ? inst2.inputs : ( type == SubMapFormsType.OUTPUT ? inst2.outputs : inst2.env); for (var e in what2) { if (e.attr != null && e.value == null) { e.value = inst2.serialize()[e.attr!]; } } // should find arrow env info and add it to the env List extParams = []; var arrows = links.where( (e) => (e.source?.id?.contains(item.id ?? "") ?? false) || (e.destination?.id?.contains(item.id ?? "") ?? false)); for (var arrow in arrows) { for (var info in arrow.infos) { var i = info as Map; for (var entry in i.entries) { if (entry.value == null) { continue; } var varName = "LINK_${el.getName().toUpperCase().replaceAll(" ", "_")}_${entry.key.toUpperCase()}"; /*alreadySeen[varName] = (alreadySeen[varName] ?? -1) + 1; if ((alreadySeen[varName] ?? 0) > 1) { varName = "${varName}_${alreadySeen[varName]}"; }*/ if ((entry.value is String) && !isEnvAttr(entry.value, what2)) { extParams.add(Param( name: varName, attr: entry.key, value: entry.value, origin: item.id, readOnly: true)); } } } } for ( var param in what) { if (param.attr == null) { continue; } var varName = param.name != null && (param.name!.contains("LINK_") || param.name!.contains("DATA_") || param.name!.contains("PROCESSING_") || param.name!.contains("STORAGE_") || param.name!.contains("WORKFLOW_") || param.name!.contains("COMPUTE") ) ? param.name : "${el.topic.toUpperCase()}_${el.getName().toUpperCase().replaceAll(" ", "_")}_${param.attr!.toUpperCase()}"; /*alreadySeen[varName] = (alreadySeen[varName] ?? -1) + 1; if ((alreadySeen[varName] ?? 0) > 0) { varName = "${varName}_${alreadySeen[varName]}"; }*/ dynamic env; if (param.value == null) { var s = el.serialize(); s.addAll(el.getSelectedInstance()?.serialize() ?? {}); env = s[param.attr!]; } else { env = param.value; } // bool isSrc = param.origin == null; //if (isSrc) { continue; } if (!isEnvAttr(env, what2)) { extParams.add(Param( name: varName, attr: param.attr, value: env, origin: item.id, readOnly: true)); } } for (var param in extParams) { what2.add(param); } } bool isEnvAttr(String value, List params) { for (var e in params) { if (value == e.value) { return true; } } return false; } void fill() { Map alreadySeen = {}; var its = items.values.toList(); for (var type in [SubMapFormsType.INPUT, SubMapFormsType.OUTPUT, SubMapFormsType.ENV]) { for (var item in its) { var envs = type == SubMapFormsType.INPUT ? item.getElement()?.getSelectedInstance()?.inputs : ( type == SubMapFormsType.OUTPUT ? item.getElement()?.getSelectedInstance()?.outputs : item.getElement()?.getSelectedInstance()?.env); if (envs != null) { envs.removeWhere( (e) => e.readOnly && e.name != null && (e.name!.contains("LINK_") || e.name!.contains("DATA_") || e.name!.contains("PROCESSING_") || e.name!.contains("STORAGE_") || e.name!.contains("WORKFLOW_") || e.name!.contains("COMPUTE") )); } } for (var item in [...its, ...its.reversed]) { var itss = getArrowByElementID(item.id ?? ""); for (var i in itss.values) { fillEnv(item.getElement(), i, type, alreadySeen); } } } } void fromDashboard(Map j) { items = {}; for (var el in (j["elements"] as Map).values) { var d = GraphItem(); d.fromDashboard(el as Map); items[d.id ?? ""] = d; } links = (j["arrows"] as List).map( (el) { var d = GraphLink(); d.fromDashboard(el); return d; }).toList(); j["zoom"] = zoom; fill(); } Map toDashboard() { fill(); List> elements = []; List> arrows = []; for (var el in items.values) { elements.add(el.toDashboard()); } for (var l in links) { arrows.add(l.toDashboard()); } return { "zoom": zoom, "elements": elements, "arrows": arrows, }; } @override deserialize(dynamic json) { try { json = json as Map; } catch (e) { return Graph(); } var g = Graph( zoom: json.containsKey("zoom") ? double.parse(json["zoom"].toString()) : 0, links: json.containsKey("links") ? fromListJson(json["links"], GraphLink()) : [], items: json.containsKey("items") ? fromMapJson(json["items"], GraphItem()) : {}, ); g.fill(); return g; } @override Map serialize() { fill(); return { "zoom": zoom, "items": toMapJson(items), "links": toListJson(links), }; } } class StorageProcessingGraphLink extends SerializerDeserializer { bool write = false; String? source; String? destination; String? filename; StorageProcessingGraphLink({ this.write = false, this.source, this.destination, this.filename, }); @override deserialize(dynamic json) { try { json = json as Map; } catch (e) { return StorageProcessingGraphLink(); } return StorageProcessingGraphLink( write: json.containsKey("write") ? json["write"] : false, source: json.containsKey("source") ? json["source"] : "", destination: json.containsKey("destination") ? json["destination"] : "", filename: json.containsKey("filename") && json["filename"] != null ? json["filename"] : "", ); } @override Map serialize() { return { "write": write, "source": source, "destination": destination, "filename": filename, }; } } class GraphLink extends SerializerDeserializer { Position? source; Position? destination; GraphLinkStyle? style; List infos = []; List env = []; GraphLink({ this.source, this.destination, this.style, this.infos = const [], this.env = const [], }); void fromDashboard(Map j) { source = Position(id: j["from"]["id"], x: j["from"]["x"], y: j["from"]["y"]); destination = Position(id: j["to"]["id"], x: j["to"]["x"], y: j["to"]["y"]); style = GraphLinkStyle(); style!.fromDashboard(j["params"]); infos = fromListJson(j["infos"], StorageProcessingGraphLink()); env = fromListJson(j["env"], Param()); } Map toDashboard() { return { "from": { "id": source?.id ?? "", "x" : source?.x ?? 0, "y": source?.y ?? 0, }, "to": { "id": destination?.id ?? "", "x" : destination?.x ?? 0, "y": destination?.y ?? 0, }, "params": style?.toDashboard(), "infos": toListJson(infos), "env": env.map( (el) => el.serialize()).toList(), }; } @override deserialize(dynamic json) { try { json = json as Map; } catch (e) { return GraphLink(); } return GraphLink( source: json.containsKey("source") && json["source"] != null ? Position().deserialize(json["source"]) : null, destination: json.containsKey("destination") && json["destination"] != null ? Position().deserialize(json["destination"]) : null, style: json.containsKey("style") && json["style"] != null ? GraphLinkStyle().deserialize(json["style"]) : null, infos: json.containsKey("storage_link_infos") && json["storage_link_infos"] != null ? fromListJson(json["storage_link_infos"], StorageProcessingGraphLink()) : [], env: json.containsKey("env") && json["env"] != null ? fromListJson(json["env"], Param()) : [], ); } @override Map serialize() { var obj = {}; if (source != null) { obj["source"] = source!.serialize(); } if (destination != null) { obj["destination"] = destination!.serialize(); } if (style != null) { obj["style"] = style!.serialize(); } obj["storage_link_infos"] = toListJson(infos); obj["env"] = toListJson(env); return obj; } } class GraphLinkStyle extends SerializerDeserializer { Color color = Colors.black; double stroke = 1; double tension = 23; double headRadius = 10; double dashWidth = 0; double dashSpace = 0; double startArrowWidth = 1; double endArrowWidth = 10; Position? startArrow; Position? endArrow; ArrowStyle arrowStyle = ArrowStyle.curve; ArrowDirection arrowDirection = ArrowDirection.forward; GraphLinkStyle({ this.color = Colors.black, this.stroke = 1, this.tension = 23, this.headRadius = 10, this.dashWidth = 0, this.dashSpace = 0, this.startArrowWidth = 10, this.endArrowWidth = 10, this.startArrow, this.endArrow, this.arrowStyle = ArrowStyle.curve, this.arrowDirection = ArrowDirection.forward }); void fromDashboard(Map j) { dashSpace = j["dash_space"]; dashWidth = j["dash_width"]; endArrowWidth = j["backward_arrow_width"]; startArrowWidth = j["forward_arrow_width"]; stroke = j["thickness"]; arrowDirection = ArrowDirection.values.firstWhere((element) => element.index == j["direction"]); headRadius = j["head_radius"]; color = Color(j["color"]); arrowStyle = ArrowStyle.values.firstWhere((element) => element.index == j["arrow_style"]); tension = j["tension"]; startArrow = Position(x: j["start_arrow_position_x"], y: j["start_arrow_position_y"]); endArrow = Position(x: j["end_arrow_position_x"], y: j["end_arrow_position_y"]); } Map toDashboard() { return { "dash_space": dashSpace, "dash_width": dashWidth, "backward_arrow_width": endArrowWidth, "forward_arrow_width": startArrowWidth, "thickness": stroke, "direction": arrowDirection.index, "head_radius": headRadius, "tail_length": 25.0, "color": int.parse(color.toHexString(), radix: 16), "arrow_style" : arrowStyle.index, "tension" : tension, "start_arrow_position_x": startArrow?.x ?? 0, "start_arrow_position_y": startArrow?.y ?? 0, "end_arrow_position_x": endArrow?.x ?? 0, "end_arrow_position_y": endArrow?.y ?? 0, }; } @override deserialize(dynamic json) { try { json = json as Map; } catch (e) { return GraphLinkStyle(); } return GraphLinkStyle( color: json.containsKey("color") ? Color(json["color"] as int) : Colors.black, stroke: json.containsKey("stroke") ? double.parse(json["stroke"].toString()) : 0, tension: json.containsKey("tension") ? double.parse(json["tension"].toString()) : 0, headRadius: json.containsKey("head_radius") ? double.parse(json["head_radius"].toString()) : 0, dashWidth: json.containsKey("dash_width") ? double.parse(json["dash_width"].toString()) : 0, dashSpace: json.containsKey("dash_space") ? double.parse(json["dash_space"].toString()) : 0, startArrow: json.containsKey("start_arrow") ? Position().deserialize(json["start_arrow"]) : null, endArrow: json.containsKey("end_arrow") ? Position().deserialize(json["end_arrow"]) : null, arrowDirection: json.containsKey("arrow_direction") ? ArrowDirection.values.firstWhere((el) => el.index == json["arrow_direction"]) : ArrowDirection.forward, arrowStyle: json.containsKey("arrow_style") ? ArrowStyle.values.firstWhere((el) => el.index == json["arrow_style"]) : ArrowStyle.curve, startArrowWidth: json.containsKey("start_arrow_width") ? double.parse(json["start_arrow_width"].toString()) : 0, endArrowWidth: json.containsKey("end_arrow_width") ? double.parse(json["end_arrow_width"].toString()) : 0, ); } @override Map serialize() { var obj = { "color" : int.parse(color.toHexString(), radix: 16), "stroke" : stroke, "tension" : tension, "head_radius" : headRadius, "dash_width" : dashWidth, "dash_space" : dashSpace, "arrow_direction" : arrowDirection.index, "arrow_style" : arrowStyle.index, "start_arrow_width" : startArrowWidth, "end_arrow_width" : endArrowWidth, }; if (startArrow != null) { obj["start_arrow"] = startArrow!.serialize(); } if (endArrow != null) { obj["end_arrow"] = endArrow!.serialize(); } return obj; } } class GraphItem extends SerializerDeserializer { String? id; double? width; double? height; Position? position; DataItem? data; ProcessingItem? processing; StorageItem? storage; ComputeItem? compute; WorkflowItem? workflow; GraphItem({ this.id, this.width, this.height, this.position, this.data, this.processing, this.storage, this.compute, this.workflow, }); AbstractItem? getElement() { if (data != null) { return data!; } if (processing != null) { return processing!; } if (storage != null) { return storage!; } if (compute != null) { return compute!; } if (workflow != null) { return workflow!; } return null; } void fromDashboard(Map j) { id = j["id"]; position = Position(x: j["x"], y: j["y"]); width = j["width"]; height = j["height"]; if (j["element"] != null) { if (j["element"]["type"] == "data") { data = DataItem().deserialize(j["element"]); } else if (j["element"]["type"] == "processing") { processing = ProcessingItem().deserialize(j["element"]); } else if (j["element"]["type"] == "compute") { compute = ComputeItem().deserialize(j["element"]); } else if (j["element"]["type"] == "storage") { storage = StorageItem().deserialize(j["element"]); } else if (j["element"]["type"] == "workflow") { workflow = WorkflowItem().deserialize(j["element"]); } else { compute = null; data = null; processing = null; storage = null; workflow = null; } } else { compute = null; data = null; processing = null; storage = null; workflow = null; } } Map toDashboard() { Map element = {}; List items = [data, processing, storage, compute, workflow]; for(var el in items) { if (el != null && el.getID() != "") { element = el.serialize(); break; } } return { "id": id, "x": (position?.x ?? 0), "y": (position?.y ?? 0), "width": width ?? 0, "height": height ?? 0, "element": element, }; } @override deserialize(dynamic json) { try { json = json as Map; } catch (e) { return GraphItem(); } return GraphItem( id: json.containsKey("id") ? json["id"] : null, width: json.containsKey("width") ? double.parse(json["width"].toString()) : null, height: json.containsKey("height") ? double.parse(json["height"].toString()) : null, position: json.containsKey("position") ? Position().deserialize(json["position"]) : null, data: json.containsKey("data") ? DataItem().deserialize(json["data"]) : null, processing: json.containsKey("processing") ? ProcessingItem().deserialize(json["processing"]) : null, storage: json.containsKey("storage") ? StorageItem().deserialize(json["storage"]) : null, compute: json.containsKey("compute") ? ComputeItem().deserialize(json["compute"]) : null, workflow: json.containsKey("workflow") ? WorkflowItem().deserialize(json["workflow"]) : null, ); } @override Map serialize() { return { "id": id, "width": width, "height": height, "data": data?.serialize(), "processing": processing?.serialize(), "storage": storage?.serialize(), "compute": compute?.serialize(), "workflow": workflow?.serialize(), "position": position?.serialize(), }; } } class Position extends SerializerDeserializer { String? id; double? x; double? y; Position({ this.id, this.x, this.y, }); @override deserialize(dynamic json) { try { json = json as Map; } catch (e) { return Position(); } return Position( id: json.containsKey("id") ? json["id"] : null, x: json.containsKey("x") ? double.parse(json["x"].toString()) : null, y: json.containsKey("y") ? double.parse(json["y"].toString()) : null, ); } @override Map serialize() => { "id": id, "x": x , "y": y, }; }