Major Change Inputs & Co
This commit is contained in:
@@ -1,40 +1,41 @@
|
||||
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/core/models/workspace_local.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/models/search.dart';
|
||||
import 'package:oc_front/widgets/forms/sub_keys_forms.dart';
|
||||
|
||||
class Check extends SerializerDeserializer<Check> {
|
||||
bool is_available = false;
|
||||
bool isAvailable = false;
|
||||
|
||||
Check({
|
||||
this.is_available = false,
|
||||
this.isAvailable = false,
|
||||
});
|
||||
|
||||
@override deserialize(dynamic json) {
|
||||
try { json = json as Map<String, dynamic>;
|
||||
} catch (e) { return Check(); }
|
||||
return Check(
|
||||
is_available: json.containsKey("is_available") ? json["is_available"] : false,
|
||||
isAvailable: json.containsKey("is_available") ? json["is_available"] : false,
|
||||
);
|
||||
}
|
||||
@override Map<String, dynamic> serialize() {
|
||||
return {
|
||||
"is_available": is_available,
|
||||
"is_available": isAvailable,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class WorkflowExecutions extends SerializerDeserializer<WorkflowExecutions> {
|
||||
List<WorkflowExecution> executions = [];
|
||||
String? executionData;
|
||||
int? status;
|
||||
String? workflowId;
|
||||
|
||||
|
||||
WorkflowExecutions({
|
||||
this.executions = const [],
|
||||
});
|
||||
@@ -56,7 +57,7 @@ class WorkflowExecutions extends SerializerDeserializer<WorkflowExecutions> {
|
||||
class WorkflowExecution extends SerializerDeserializer<WorkflowExecution> {
|
||||
String? id;
|
||||
String? name;
|
||||
String? executionData;
|
||||
String? startDate;
|
||||
String? endDate;
|
||||
int? status;
|
||||
String? workflowId;
|
||||
@@ -66,7 +67,7 @@ class WorkflowExecution extends SerializerDeserializer<WorkflowExecution> {
|
||||
|
||||
WorkflowExecution({
|
||||
this.id,
|
||||
this.executionData,
|
||||
this.startDate,
|
||||
this.status,
|
||||
this.workflowId,
|
||||
this.name,
|
||||
@@ -79,7 +80,7 @@ class WorkflowExecution extends SerializerDeserializer<WorkflowExecution> {
|
||||
return WorkflowExecution(
|
||||
id: json.containsKey("id") ? json["id"] : "",
|
||||
endDate: json.containsKey("end_date") ? json["end_date"] : "",
|
||||
executionData: json.containsKey("execution_date") ? json["execution_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"] : "",
|
||||
@@ -91,7 +92,7 @@ class WorkflowExecution extends SerializerDeserializer<WorkflowExecution> {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"end_date": endDate,
|
||||
"execution_data": executionData,
|
||||
"execution_data": startDate,
|
||||
"status": status,
|
||||
"workflow_id": workflowId,
|
||||
};
|
||||
@@ -108,8 +109,6 @@ class Workflow extends SerializerDeserializer<Workflow> implements ShallowData
|
||||
List<dynamic> processing;
|
||||
List<dynamic> workflows;
|
||||
Graph? graph;
|
||||
Scheduler? schedule;
|
||||
bool scheduleActive = false;
|
||||
List<dynamic> shared;
|
||||
|
||||
Workflow({
|
||||
@@ -121,14 +120,12 @@ class Workflow extends SerializerDeserializer<Workflow> implements ShallowData
|
||||
this.processing = const [],
|
||||
this.workflows = const [],
|
||||
this.graph,
|
||||
this.schedule,
|
||||
this.scheduleActive = false,
|
||||
this.shared = const [],
|
||||
});
|
||||
|
||||
@override String getID() => id ?? "";
|
||||
@override String getName() => name ?? "";
|
||||
@override String getDescription() => "";
|
||||
String getDescription() => "";
|
||||
|
||||
@override deserialize(dynamic json) {
|
||||
try { json = json as Map<String, dynamic>;
|
||||
@@ -140,11 +137,9 @@ class Workflow extends SerializerDeserializer<Workflow> implements ShallowData
|
||||
processing: json.containsKey("processings") ? json["processings"] : [],
|
||||
compute: json.containsKey("computes") ? json["computes"] : [],
|
||||
data: json.containsKey("datas") ? json["datas"] : [],
|
||||
scheduleActive: json.containsKey("schedule_active") ? json["schedule_active"] : false,
|
||||
storage: json.containsKey("storages") ? json["storages"] : [],
|
||||
shared: json.containsKey("shared") ? json["shared"] : [],
|
||||
graph: json.containsKey("graph") ? Graph().deserialize(json["graph"]) : null,
|
||||
schedule: json.containsKey("schedule") ? Scheduler().deserialize(json["schedule"]) : null,
|
||||
);
|
||||
}
|
||||
@override Map<String, dynamic> serialize() {
|
||||
@@ -152,12 +147,10 @@ class Workflow extends SerializerDeserializer<Workflow> implements ShallowData
|
||||
"id": id,
|
||||
"name": name,
|
||||
"datas": data,
|
||||
"computes" : compute,
|
||||
"storages": storage,
|
||||
"processings": processing,
|
||||
"computes" : compute,
|
||||
"workflows": workflows,
|
||||
"schedule_active": scheduleActive,
|
||||
"schedule": schedule?.serialize(),
|
||||
"processings": processing,
|
||||
};
|
||||
if (graph != null) {
|
||||
obj["graph"] = graph!.serialize();
|
||||
@@ -168,24 +161,17 @@ class Workflow extends SerializerDeserializer<Workflow> implements ShallowData
|
||||
void fromDashboard(Map<String, dynamic> j) {
|
||||
id = j["id"];
|
||||
name = j["name"];
|
||||
scheduleActive = j["schedule_active"];
|
||||
if (j.containsKey("graph")) {
|
||||
graph = Graph();
|
||||
graph!.fromDashboard(j["graph"]);
|
||||
}
|
||||
if (j.containsKey("schedule")) {
|
||||
schedule = Scheduler();
|
||||
schedule!.fromDashboard(j["schedule"]);
|
||||
}
|
||||
}
|
||||
Map<String, dynamic> toDashboard() {
|
||||
return {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"graph": graph?.toDashboard(),
|
||||
"schedule_active": scheduleActive,
|
||||
"schedule": schedule?.toDashboard(),
|
||||
"shared": shared,
|
||||
"graph": graph?.toDashboard(),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -221,7 +207,7 @@ class Scheduler extends SerializerDeserializer<Scheduler> {
|
||||
end = DateTime.parse(j["end"]);
|
||||
}
|
||||
|
||||
} catch (e) {}
|
||||
} catch (e) { /**/ }
|
||||
}
|
||||
Map<String, dynamic> toDashboard() {
|
||||
return {
|
||||
@@ -279,6 +265,159 @@ class Graph extends SerializerDeserializer<Graph> {
|
||||
this.links = const [],
|
||||
});
|
||||
|
||||
Map<String, List<dynamic>> getInfosToUpdate(SubMapFormsType type) {
|
||||
Map<String, List<dynamic>> 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<String, List<dynamic>> getEnvToUpdate() {
|
||||
return getInfosToUpdate(SubMapFormsType.ENV);
|
||||
}
|
||||
|
||||
Map<String, List<dynamic>> getInputToUpdate() {
|
||||
return getInfosToUpdate(SubMapFormsType.INPUT);
|
||||
}
|
||||
|
||||
Map<String, List<dynamic>> getOutputToUpdate() {
|
||||
return getInfosToUpdate(SubMapFormsType.OUTPUT);
|
||||
}
|
||||
|
||||
|
||||
GraphItem getItemByElementID(String id) {
|
||||
return items[id] ?? GraphItem();
|
||||
}
|
||||
Map<String,GraphItem?> getArrowByElementID(String id) {
|
||||
Map<String,GraphItem?> 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<String,int> 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<Param> 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<String, dynamic>;
|
||||
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<Param> params) {
|
||||
for (var e in params) {
|
||||
if (value == e.value) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void fill() {
|
||||
Map<String, int> 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<String, dynamic> j) {
|
||||
items = {};
|
||||
for (var el in (j["elements"] as Map<dynamic, dynamic>).values) {
|
||||
@@ -292,9 +431,11 @@ class Graph extends SerializerDeserializer<Graph> {
|
||||
return d;
|
||||
}).toList();
|
||||
j["zoom"] = zoom;
|
||||
fill();
|
||||
}
|
||||
|
||||
Map<String, dynamic> toDashboard() {
|
||||
fill();
|
||||
List<Map<String, dynamic>> elements = [];
|
||||
List<Map<String, dynamic>> arrows = [];
|
||||
for (var el in items.values) {
|
||||
@@ -313,28 +454,70 @@ class Graph extends SerializerDeserializer<Graph> {
|
||||
@override deserialize(dynamic json) {
|
||||
try { json = json as Map<String, dynamic>;
|
||||
} catch (e) { return Graph(); }
|
||||
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<GraphItem>(json["items"], GraphItem()) : {},
|
||||
);
|
||||
g.fill();
|
||||
return g;
|
||||
}
|
||||
@override Map<String, dynamic> serialize() {
|
||||
fill();
|
||||
return {
|
||||
"zoom": zoom,
|
||||
"items": toMapJson(items),
|
||||
"links": toListJson(links),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class StorageProcessingGraphLink extends SerializerDeserializer<StorageProcessingGraphLink> {
|
||||
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<String, dynamic>;
|
||||
} 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<String, dynamic> serialize() {
|
||||
return {
|
||||
"write": write,
|
||||
"source": source,
|
||||
"destination": destination,
|
||||
"filename": filename,
|
||||
};
|
||||
}
|
||||
@override Map<String, dynamic> serialize() => {
|
||||
"zoom": zoom,
|
||||
"items": toMapJson(items),
|
||||
"links": toListJson(links),
|
||||
};
|
||||
}
|
||||
|
||||
class GraphLink extends SerializerDeserializer<GraphLink> {
|
||||
Position? source;
|
||||
Position? destination;
|
||||
GraphLinkStyle? style;
|
||||
List<StorageProcessingGraphLink> infos = [];
|
||||
List<Param> env = [];
|
||||
|
||||
GraphLink({
|
||||
this.source,
|
||||
this.destination,
|
||||
this.style,
|
||||
this.infos = const [],
|
||||
this.env = const [],
|
||||
});
|
||||
|
||||
void fromDashboard(Map<String, dynamic> j) {
|
||||
@@ -342,6 +525,8 @@ class GraphLink extends SerializerDeserializer<GraphLink> {
|
||||
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<String, dynamic> toDashboard() {
|
||||
@@ -357,6 +542,8 @@ class GraphLink extends SerializerDeserializer<GraphLink> {
|
||||
"y": destination?.y ?? 0,
|
||||
},
|
||||
"params": style?.toDashboard(),
|
||||
"infos": toListJson(infos),
|
||||
"env": env.map( (el) => el.serialize()).toList(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -364,9 +551,11 @@ class GraphLink extends SerializerDeserializer<GraphLink> {
|
||||
try { json = json as Map<String, dynamic>;
|
||||
} catch (e) { return GraphLink(); }
|
||||
return GraphLink(
|
||||
source: json.containsKey("source") ? Position().deserialize(json["source"]) : null,
|
||||
destination: json.containsKey("destination") ? Position().deserialize(json["destination"]) : null,
|
||||
style: json.containsKey("style") ? GraphLinkStyle().deserialize(json["style"]) : null,
|
||||
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<String, dynamic> serialize() {
|
||||
@@ -380,6 +569,8 @@ class GraphLink extends SerializerDeserializer<GraphLink> {
|
||||
if (style != null) {
|
||||
obj["style"] = style!.serialize();
|
||||
}
|
||||
obj["storage_link_infos"] = toListJson(infos);
|
||||
obj["env"] = toListJson(env);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
@@ -521,33 +712,19 @@ class GraphItem extends SerializerDeserializer<GraphItem> {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
void fromDashboard(Map<String, dynamic> j) {
|
||||
id = j["id"];
|
||||
position = Position(x: j["x"], y: j["y"]);
|
||||
width = j["width"];
|
||||
height = j["height"];
|
||||
|
||||
var abs = WorkspaceLocal.getItem(j["element"]?["id"] ?? "", true) as AbstractItem<FlowData>?;
|
||||
if (abs != null) {
|
||||
if (abs.topic == "data") {
|
||||
data = DataItem().deserialize(abs.serialize());
|
||||
data!.model = ResourceModel().deserialize(j["element"]["resource_model"]);
|
||||
} else if (abs.topic == "processing") {
|
||||
processing = ProcessingItem().deserialize(abs.serialize());
|
||||
processing!.model = ResourceModel().deserialize(j["element"]["resource_model"]);
|
||||
if ((j["element"] as Map<String, dynamic>).containsKey("container")) {
|
||||
processing!.container = Containered().deserialize(j["element"]["container"]);
|
||||
processing!.container?.env?.removeWhere((key, value) => key == "" || value == "");
|
||||
processing!.container?.volumes?.removeWhere((key, value) => key == "" || value == "");
|
||||
processing!.expose.removeWhere((element) => element.port == null || element.port == 0 || (element.PAT == 0 && element.path == ""));
|
||||
|
||||
}
|
||||
} else if (abs.topic == "compute") {
|
||||
compute = ComputeItem().deserialize(abs.serialize());
|
||||
} else if (abs.topic == "storage") {
|
||||
storage = StorageItem().deserialize(abs.serialize());
|
||||
} else if (abs.topic == "workflow") {
|
||||
workflow = WorkflowItem().deserialize(abs.serialize());
|
||||
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;
|
||||
@@ -566,7 +743,8 @@ class GraphItem extends SerializerDeserializer<GraphItem> {
|
||||
|
||||
Map<String, dynamic> toDashboard() {
|
||||
Map<String, dynamic> element = {};
|
||||
for(var el in [data, processing, storage, compute, workflow]) {
|
||||
List<AbstractItem?> items = [data, processing, storage, compute, workflow];
|
||||
for(var el in items) {
|
||||
if (el != null && el.getID() != "") {
|
||||
element = el.serialize();
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user