intermediate
This commit is contained in:
parent
593f03648b
commit
ceeebfc964
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
["/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/libflutter_linux_gtk.so","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/icudtl.dat","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_dart_project.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_texture.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_event_channel.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_message_codec.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_json_message_codec.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_binary_codec.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_plugin_registry.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_json_method_codec.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_string_codec.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_codec.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_pixel_buffer_texture.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_texture_gl.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/flutter_linux.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_value.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_view.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_channel.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_engine.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_binary_messenger.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_standard_message_codec.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_standard_method_codec.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_texture_registrar.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_response.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_plugin_registrar.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_basic_message_channel.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_call.h","/home/mr/Documents/OC/oc-front/build/flutter_assets/kernel_blob.bin","/home/mr/Documents/OC/oc-front/build/flutter_assets/assets/images/logo.svg","/home/mr/Documents/OC/oc-front/build/flutter_assets/assets/images/icon.svg","/home/mr/Documents/OC/oc-front/build/flutter_assets/packages/cupertino_icons/assets/CupertinoIcons.ttf","/home/mr/Documents/OC/oc-front/build/flutter_assets/packages/flutter_map/lib/assets/flutter_map_logo.png","/home/mr/Documents/OC/oc-front/build/flutter_assets/fonts/MaterialIcons-Regular.otf","/home/mr/Documents/OC/oc-front/build/flutter_assets/shaders/ink_sparkle.frag","/home/mr/Documents/OC/oc-front/build/flutter_assets/AssetManifest.json","/home/mr/Documents/OC/oc-front/build/flutter_assets/AssetManifest.bin","/home/mr/Documents/OC/oc-front/build/flutter_assets/FontManifest.json","/home/mr/Documents/OC/oc-front/build/flutter_assets/NOTICES.Z","/home/mr/Documents/OC/oc-front/build/flutter_assets/version.json"]
|
["/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/libflutter_linux_gtk.so","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/icudtl.dat","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_dart_project.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_texture.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_event_channel.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_message_codec.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_json_message_codec.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_binary_codec.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_plugin_registry.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_json_method_codec.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_string_codec.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_codec.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_pixel_buffer_texture.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_texture_gl.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/flutter_linux.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_value.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_view.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_channel.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_engine.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_binary_messenger.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_standard_message_codec.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_standard_method_codec.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_texture_registrar.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_response.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_plugin_registrar.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_basic_message_channel.h","/home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_call.h","/home/mr/Documents/OC/oc-front/build/flutter_assets/kernel_blob.bin","/home/mr/Documents/OC/oc-front/build/flutter_assets/assets/images/logo.svg","/home/mr/Documents/OC/oc-front/build/flutter_assets/assets/images/icon.svg","/home/mr/Documents/OC/oc-front/build/flutter_assets/packages/cupertino_icons/assets/CupertinoIcons.ttf","/home/mr/Documents/OC/oc-front/build/flutter_assets/packages/flutter_map/lib/assets/flutter_map_logo.png","/home/mr/Documents/OC/oc-front/build/flutter_assets/packages/timezone/data/latest_all.tzf","/home/mr/Documents/OC/oc-front/build/flutter_assets/fonts/MaterialIcons-Regular.otf","/home/mr/Documents/OC/oc-front/build/flutter_assets/shaders/ink_sparkle.frag","/home/mr/Documents/OC/oc-front/build/flutter_assets/AssetManifest.json","/home/mr/Documents/OC/oc-front/build/flutter_assets/AssetManifest.bin","/home/mr/Documents/OC/oc-front/build/flutter_assets/FontManifest.json","/home/mr/Documents/OC/oc-front/build/flutter_assets/NOTICES.Z","/home/mr/Documents/OC/oc-front/build/flutter_assets/version.json"]
|
@ -8,8 +8,10 @@
|
|||||||
import 'dart:io'; // flutter_ignore: dart_io_import.
|
import 'dart:io'; // flutter_ignore: dart_io_import.
|
||||||
import 'package:path_provider_android/path_provider_android.dart';
|
import 'package:path_provider_android/path_provider_android.dart';
|
||||||
import 'package:shared_preferences_android/shared_preferences_android.dart';
|
import 'package:shared_preferences_android/shared_preferences_android.dart';
|
||||||
|
import 'package:webview_flutter_android/webview_flutter_android.dart';
|
||||||
import 'package:path_provider_foundation/path_provider_foundation.dart';
|
import 'package:path_provider_foundation/path_provider_foundation.dart';
|
||||||
import 'package:shared_preferences_foundation/shared_preferences_foundation.dart';
|
import 'package:shared_preferences_foundation/shared_preferences_foundation.dart';
|
||||||
|
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:path_provider_linux/path_provider_linux.dart';
|
import 'package:path_provider_linux/path_provider_linux.dart';
|
||||||
import 'package:shared_preferences_linux/shared_preferences_linux.dart';
|
import 'package:shared_preferences_linux/shared_preferences_linux.dart';
|
||||||
@ -43,6 +45,15 @@ class _PluginRegistrant {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
AndroidWebViewPlatform.registerWith();
|
||||||
|
} catch (err) {
|
||||||
|
print(
|
||||||
|
'`webview_flutter_android` threw an error: $err. '
|
||||||
|
'The app may not function as expected until you remove this plugin from pubspec.yaml'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
} else if (Platform.isIOS) {
|
} else if (Platform.isIOS) {
|
||||||
try {
|
try {
|
||||||
PathProviderFoundation.registerWith();
|
PathProviderFoundation.registerWith();
|
||||||
@ -62,6 +73,15 @@ class _PluginRegistrant {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
WebKitWebViewPlatform.registerWith();
|
||||||
|
} catch (err) {
|
||||||
|
print(
|
||||||
|
'`webview_flutter_wkwebview` threw an error: $err. '
|
||||||
|
'The app may not function as expected until you remove this plugin from pubspec.yaml'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
} else if (Platform.isLinux) {
|
} else if (Platform.isLinux) {
|
||||||
try {
|
try {
|
||||||
DeviceInfoPlusLinuxPlugin.registerWith();
|
DeviceInfoPlusLinuxPlugin.registerWith();
|
||||||
|
@ -61,6 +61,12 @@
|
|||||||
"packageUri": "lib/",
|
"packageUri": "lib/",
|
||||||
"languageVersion": "2.18"
|
"languageVersion": "2.18"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "cron",
|
||||||
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/cron-0.6.1",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.12"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "crypto",
|
"name": "crypto",
|
||||||
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/crypto-3.0.3",
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/crypto-3.0.3",
|
||||||
@ -85,6 +91,12 @@
|
|||||||
"packageUri": "lib/",
|
"packageUri": "lib/",
|
||||||
"languageVersion": "2.19"
|
"languageVersion": "2.19"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "datetime_picker_formfield",
|
||||||
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/datetime_picker_formfield-2.0.1",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.12"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "desktop_window",
|
"name": "desktop_window",
|
||||||
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/desktop_window-0.4.0",
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/desktop_window-0.4.0",
|
||||||
@ -157,6 +169,12 @@
|
|||||||
"packageUri": "lib/",
|
"packageUri": "lib/",
|
||||||
"languageVersion": "3.2"
|
"languageVersion": "3.2"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "flutter_advanced_switch",
|
||||||
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/flutter_advanced_switch-3.1.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.12"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "flutter_box_transform",
|
"name": "flutter_box_transform",
|
||||||
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/flutter_box_transform-0.4.4",
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/flutter_box_transform-0.4.4",
|
||||||
@ -169,6 +187,12 @@
|
|||||||
"packageUri": "lib/",
|
"packageUri": "lib/",
|
||||||
"languageVersion": "2.14"
|
"languageVersion": "2.14"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "flutter_event_calendar",
|
||||||
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/flutter_event_calendar-1.0.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.12"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "flutter_flow_chart",
|
"name": "flutter_flow_chart",
|
||||||
"rootUri": "../library/flutter_flow_chart",
|
"rootUri": "../library/flutter_flow_chart",
|
||||||
@ -259,6 +283,18 @@
|
|||||||
"packageUri": "lib/",
|
"packageUri": "lib/",
|
||||||
"languageVersion": "3.0"
|
"languageVersion": "3.0"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "json_string",
|
||||||
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/json_string-3.0.1",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "json_util",
|
||||||
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/json_util-2.0.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.12"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "latlong2",
|
"name": "latlong2",
|
||||||
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/latlong2-0.9.1",
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/latlong2-0.9.1",
|
||||||
@ -421,6 +457,18 @@
|
|||||||
"packageUri": "lib/",
|
"packageUri": "lib/",
|
||||||
"languageVersion": "2.12"
|
"languageVersion": "2.12"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "scoped_model",
|
||||||
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/scoped_model-2.0.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shamsi_date",
|
||||||
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/shamsi_date-0.15.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.12"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "shared_preferences",
|
"name": "shared_preferences",
|
||||||
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences-2.2.3",
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences-2.2.3",
|
||||||
@ -529,6 +577,24 @@
|
|||||||
"packageUri": "lib/",
|
"packageUri": "lib/",
|
||||||
"languageVersion": "3.3"
|
"languageVersion": "3.3"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "syncfusion_flutter_calendar",
|
||||||
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_calendar-26.2.7",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.17"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "syncfusion_flutter_core",
|
||||||
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_core-26.2.7",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.17"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "syncfusion_flutter_datepicker",
|
||||||
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_datepicker-26.2.7",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.17"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "table_calendar",
|
"name": "table_calendar",
|
||||||
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/table_calendar-3.1.2",
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/table_calendar-3.1.2",
|
||||||
@ -547,6 +613,12 @@
|
|||||||
"packageUri": "lib/",
|
"packageUri": "lib/",
|
||||||
"languageVersion": "3.0"
|
"languageVersion": "3.0"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "timezone",
|
||||||
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/timezone-0.9.3",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "2.19"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "typed_data",
|
"name": "typed_data",
|
||||||
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/typed_data-1.3.2",
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/typed_data-1.3.2",
|
||||||
@ -601,6 +673,30 @@
|
|||||||
"packageUri": "lib/",
|
"packageUri": "lib/",
|
||||||
"languageVersion": "3.3"
|
"languageVersion": "3.3"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "webview_flutter",
|
||||||
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/webview_flutter-4.8.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "webview_flutter_android",
|
||||||
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/webview_flutter_android-3.16.3",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "webview_flutter_platform_interface",
|
||||||
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/webview_flutter_platform_interface-2.10.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "webview_flutter_wkwebview",
|
||||||
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/webview_flutter_wkwebview-3.14.0",
|
||||||
|
"packageUri": "lib/",
|
||||||
|
"languageVersion": "3.2"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "win32",
|
"name": "win32",
|
||||||
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/win32-5.5.0",
|
"rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/win32-5.5.0",
|
||||||
@ -638,7 +734,7 @@
|
|||||||
"languageVersion": "3.3"
|
"languageVersion": "3.3"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"generated": "2024-07-17T08:10:14.640895Z",
|
"generated": "2024-08-07T09:57:10.081261Z",
|
||||||
"generator": "pub",
|
"generator": "pub",
|
||||||
"generatorVersion": "3.3.4"
|
"generatorVersion": "3.3.4"
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,10 @@ convert
|
|||||||
2.18
|
2.18
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/convert-3.1.1/
|
file:///home/mr/.pub-cache/hosted/pub.dev/convert-3.1.1/
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/convert-3.1.1/lib/
|
file:///home/mr/.pub-cache/hosted/pub.dev/convert-3.1.1/lib/
|
||||||
|
cron
|
||||||
|
2.12
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/cron-0.6.1/
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/cron-0.6.1/lib/
|
||||||
crypto
|
crypto
|
||||||
2.19
|
2.19
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/crypto-3.0.3/
|
file:///home/mr/.pub-cache/hosted/pub.dev/crypto-3.0.3/
|
||||||
@ -54,6 +58,10 @@ dashed_path
|
|||||||
2.19
|
2.19
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/dashed_path-1.0.1/
|
file:///home/mr/.pub-cache/hosted/pub.dev/dashed_path-1.0.1/
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/dashed_path-1.0.1/lib/
|
file:///home/mr/.pub-cache/hosted/pub.dev/dashed_path-1.0.1/lib/
|
||||||
|
datetime_picker_formfield
|
||||||
|
2.12
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/datetime_picker_formfield-2.0.1/
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/datetime_picker_formfield-2.0.1/lib/
|
||||||
desktop_window
|
desktop_window
|
||||||
2.12
|
2.12
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/desktop_window-0.4.0/
|
file:///home/mr/.pub-cache/hosted/pub.dev/desktop_window-0.4.0/
|
||||||
@ -98,6 +106,10 @@ fixnum
|
|||||||
2.19
|
2.19
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/fixnum-1.1.0/
|
file:///home/mr/.pub-cache/hosted/pub.dev/fixnum-1.1.0/
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/fixnum-1.1.0/lib/
|
file:///home/mr/.pub-cache/hosted/pub.dev/fixnum-1.1.0/lib/
|
||||||
|
flutter_advanced_switch
|
||||||
|
2.12
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/flutter_advanced_switch-3.1.0/
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/flutter_advanced_switch-3.1.0/lib/
|
||||||
flutter_box_transform
|
flutter_box_transform
|
||||||
3.0
|
3.0
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/flutter_box_transform-0.4.4/
|
file:///home/mr/.pub-cache/hosted/pub.dev/flutter_box_transform-0.4.4/
|
||||||
@ -106,6 +118,10 @@ flutter_colorpicker
|
|||||||
2.14
|
2.14
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/flutter_colorpicker-1.1.0/
|
file:///home/mr/.pub-cache/hosted/pub.dev/flutter_colorpicker-1.1.0/
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/flutter_colorpicker-1.1.0/lib/
|
file:///home/mr/.pub-cache/hosted/pub.dev/flutter_colorpicker-1.1.0/lib/
|
||||||
|
flutter_event_calendar
|
||||||
|
2.12
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/flutter_event_calendar-1.0.0/
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/flutter_event_calendar-1.0.0/lib/
|
||||||
flutter_lints
|
flutter_lints
|
||||||
3.1
|
3.1
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/flutter_lints-3.0.2/
|
file:///home/mr/.pub-cache/hosted/pub.dev/flutter_lints-3.0.2/
|
||||||
@ -154,6 +170,14 @@ irondash_message_channel
|
|||||||
3.0
|
3.0
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/irondash_message_channel-0.7.0/
|
file:///home/mr/.pub-cache/hosted/pub.dev/irondash_message_channel-0.7.0/
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/irondash_message_channel-0.7.0/lib/
|
file:///home/mr/.pub-cache/hosted/pub.dev/irondash_message_channel-0.7.0/lib/
|
||||||
|
json_string
|
||||||
|
2.12
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/json_string-3.0.1/
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/json_string-3.0.1/lib/
|
||||||
|
json_util
|
||||||
|
2.12
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/json_util-2.0.0/
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/json_util-2.0.0/lib/
|
||||||
latlong2
|
latlong2
|
||||||
3.0
|
3.0
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/latlong2-0.9.1/
|
file:///home/mr/.pub-cache/hosted/pub.dev/latlong2-0.9.1/
|
||||||
@ -262,6 +286,14 @@ proj4dart
|
|||||||
2.12
|
2.12
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/proj4dart-2.1.0/
|
file:///home/mr/.pub-cache/hosted/pub.dev/proj4dart-2.1.0/
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/proj4dart-2.1.0/lib/
|
file:///home/mr/.pub-cache/hosted/pub.dev/proj4dart-2.1.0/lib/
|
||||||
|
scoped_model
|
||||||
|
2.12
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/scoped_model-2.0.0/
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/scoped_model-2.0.0/lib/
|
||||||
|
shamsi_date
|
||||||
|
2.12
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/shamsi_date-0.15.0/
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/shamsi_date-0.15.0/lib/
|
||||||
shared_preferences
|
shared_preferences
|
||||||
3.1
|
3.1
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences-2.2.3/
|
file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences-2.2.3/
|
||||||
@ -330,6 +362,18 @@ super_native_extensions
|
|||||||
3.3
|
3.3
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.17/
|
file:///home/mr/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.17/
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.17/lib/
|
file:///home/mr/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.17/lib/
|
||||||
|
syncfusion_flutter_calendar
|
||||||
|
2.17
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_calendar-26.2.7/
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_calendar-26.2.7/lib/
|
||||||
|
syncfusion_flutter_core
|
||||||
|
2.17
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_core-26.2.7/
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_core-26.2.7/lib/
|
||||||
|
syncfusion_flutter_datepicker
|
||||||
|
2.17
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_datepicker-26.2.7/
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_datepicker-26.2.7/lib/
|
||||||
table_calendar
|
table_calendar
|
||||||
3.0
|
3.0
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/table_calendar-3.1.2/
|
file:///home/mr/.pub-cache/hosted/pub.dev/table_calendar-3.1.2/
|
||||||
@ -342,6 +386,10 @@ test_api
|
|||||||
3.0
|
3.0
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/test_api-0.6.1/
|
file:///home/mr/.pub-cache/hosted/pub.dev/test_api-0.6.1/
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/test_api-0.6.1/lib/
|
file:///home/mr/.pub-cache/hosted/pub.dev/test_api-0.6.1/lib/
|
||||||
|
timezone
|
||||||
|
2.19
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/timezone-0.9.3/
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/timezone-0.9.3/lib/
|
||||||
typed_data
|
typed_data
|
||||||
2.17
|
2.17
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/typed_data-1.3.2/
|
file:///home/mr/.pub-cache/hosted/pub.dev/typed_data-1.3.2/
|
||||||
@ -378,6 +426,22 @@ web
|
|||||||
3.3
|
3.3
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/web-0.5.1/
|
file:///home/mr/.pub-cache/hosted/pub.dev/web-0.5.1/
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/web-0.5.1/lib/
|
file:///home/mr/.pub-cache/hosted/pub.dev/web-0.5.1/lib/
|
||||||
|
webview_flutter
|
||||||
|
3.2
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/webview_flutter-4.8.0/
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/webview_flutter-4.8.0/lib/
|
||||||
|
webview_flutter_android
|
||||||
|
3.2
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/webview_flutter_android-3.16.3/
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/webview_flutter_android-3.16.3/lib/
|
||||||
|
webview_flutter_platform_interface
|
||||||
|
3.0
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/webview_flutter_platform_interface-2.10.0/
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/webview_flutter_platform_interface-2.10.0/lib/
|
||||||
|
webview_flutter_wkwebview
|
||||||
|
3.2
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/webview_flutter_wkwebview-3.14.0/
|
||||||
|
file:///home/mr/.pub-cache/hosted/pub.dev/webview_flutter_wkwebview-3.14.0/lib/
|
||||||
win32
|
win32
|
||||||
3.3
|
3.3
|
||||||
file:///home/mr/.pub-cache/hosted/pub.dev/win32-5.5.0/
|
file:///home/mr/.pub-cache/hosted/pub.dev/win32-5.5.0/
|
||||||
|
@ -14,3 +14,6 @@ shared_preferences_linux=/home/mr/.pub-cache/hosted/pub.dev/shared_preferences_l
|
|||||||
shared_preferences_web=/home/mr/.pub-cache/hosted/pub.dev/shared_preferences_web-2.3.0/
|
shared_preferences_web=/home/mr/.pub-cache/hosted/pub.dev/shared_preferences_web-2.3.0/
|
||||||
shared_preferences_windows=/home/mr/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.3.2/
|
shared_preferences_windows=/home/mr/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.3.2/
|
||||||
super_native_extensions=/home/mr/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.17/
|
super_native_extensions=/home/mr/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.17/
|
||||||
|
webview_flutter=/home/mr/.pub-cache/hosted/pub.dev/webview_flutter-4.8.0/
|
||||||
|
webview_flutter_android=/home/mr/.pub-cache/hosted/pub.dev/webview_flutter_android-3.16.3/
|
||||||
|
webview_flutter_wkwebview=/home/mr/.pub-cache/hosted/pub.dev/webview_flutter_wkwebview-3.14.0/
|
||||||
|
File diff suppressed because one or more lines are too long
@ -5,10 +5,10 @@ FROM debian:latest AS build-env
|
|||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
RUN apt-get install -y curl git unzip
|
RUN apt-get install -y curl git unzip
|
||||||
|
|
||||||
ARG WORKSPACE_HOST="https://localhost:49618"
|
ARG WORKSPACE_HOST="https://localhost:8089"
|
||||||
ARG WORKFLOW_HOST="https://localhost:49618"
|
ARG WORKFLOW_HOST="https://localhost:8088"
|
||||||
ARG SEARCH_HOST="https://localhost:49618"
|
ARG SEARCH_HOST="https://localhost:49618"
|
||||||
ARG ITEM_HOST="https://localhost:49618"
|
ARG ITEM_HOST="https://localhost:8087"
|
||||||
|
|
||||||
# define variables
|
# define variables
|
||||||
ARG FLUTTER_SDK=/usr/local/flutter
|
ARG FLUTTER_SDK=/usr/local/flutter
|
||||||
|
Binary file not shown.
@ -1 +1 @@
|
|||||||
assets/images/icon.svg
assetassets/images/icon.svgassets/images/logo.svg
assetassets/images/logo.svg2packages/cupertino_icons/assets/CupertinoIcons.ttf
asset2packages/cupertino_icons/assets/CupertinoIcons.ttf4packages/flutter_map/lib/assets/flutter_map_logo.png
asset4packages/flutter_map/lib/assets/flutter_map_logo.png
|
assets/images/icon.svg
assetassets/images/icon.svgassets/images/logo.svg
assetassets/images/logo.svg2packages/cupertino_icons/assets/CupertinoIcons.ttf
asset2packages/cupertino_icons/assets/CupertinoIcons.ttf4packages/flutter_map/lib/assets/flutter_map_logo.png
asset4packages/flutter_map/lib/assets/flutter_map_logo.png%packages/timezone/data/latest_all.tzf
asset%packages/timezone/data/latest_all.tzf
|
@ -1 +1 @@
|
|||||||
{"assets/images/icon.svg":["assets/images/icon.svg"],"assets/images/logo.svg":["assets/images/logo.svg"],"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"],"packages/flutter_map/lib/assets/flutter_map_logo.png":["packages/flutter_map/lib/assets/flutter_map_logo.png"]}
|
{"assets/images/icon.svg":["assets/images/icon.svg"],"assets/images/logo.svg":["assets/images/logo.svg"],"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"],"packages/flutter_map/lib/assets/flutter_map_logo.png":["packages/flutter_map/lib/assets/flutter_map_logo.png"],"packages/timezone/data/latest_all.tzf":["packages/timezone/data/latest_all.tzf"]}
|
Binary file not shown.
Binary file not shown.
BIN
build/flutter_assets/packages/timezone/data/latest_all.tzf
Normal file
BIN
build/flutter_assets/packages/timezone/data/latest_all.tzf
Normal file
Binary file not shown.
Binary file not shown.
@ -1,65 +1,123 @@
|
|||||||
# ninja log v5
|
# ninja log v5
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_call.h df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_channel.h df34b103123784f1
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_plugin_registry.h df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_codec.h df34b103123784f1
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_string_codec.h df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_basic_message_channel.h df34b103123784f1
|
||||||
4 320 1721230626649119048 plugins/super_native_extensions/_phony_ 74762aee97d0d662
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_engine.h df34b103123784f1
|
||||||
5895 6038 1720171596542283915 plugins/desktop_window/libdesktop_window_plugin.so 26c8f2b838605d38
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_dart_project.h df34b103123784f1
|
||||||
3 5644 0 flutter/_phony_ df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_binary_messenger.h df34b103123784f1
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_json_method_codec.h df34b103123784f1
|
19318 20273 0 CMakeFiles/install.util 558f353ee1373233
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_channel.h df34b103123784f1
|
43 412 1723042867477311806 plugins/super_native_extensions/libsuper_native_extensions.so 74762aee97d0d662
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_engine.h df34b103123784f1
|
18891 19318 1723042886400968232 intermediates_do_not_run/oc_front 4e630cc1de7b670a
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_dart_project.h df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_value.h df34b103123784f1
|
||||||
13608 16421 1720171474184250688 plugins/desktop_window/CMakeFiles/desktop_window_plugin.dir/desktop_window_plugin.cc.o 259dba9caad978aa
|
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_binary_messenger.h df34b103123784f1
|
|
||||||
6240 6392 0 CMakeFiles/install.util 558f353ee1373233
|
|
||||||
7221 7661 1720190160103160034 CMakeFiles/oc_front.dir/main.cc.o b1d36a8b3fb9d7f7
|
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_response.h df34b103123784f1
|
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/libflutter_linux_gtk.so df34b103123784f1
|
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_json_message_codec.h df34b103123784f1
|
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/flutter_linux.h df34b103123784f1
|
|
||||||
5644 6116 1721230632457031904 CMakeFiles/oc_front.dir/my_application.cc.o 3fd042b328f87769
|
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_basic_message_channel.h df34b103123784f1
|
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_codec.h df34b103123784f1
|
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_standard_method_codec.h df34b103123784f1
|
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_view.h df34b103123784f1
|
|
||||||
4 320 1721230626649119048 plugins/super_native_extensions/libsuper_native_extensions.so 74762aee97d0d662
|
|
||||||
6116 6240 1721230632585029984 intermediates_do_not_run/oc_front 4e630cc1de7b670a
|
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_binary_codec.h df34b103123784f1
|
|
||||||
7223 7702 1720190160147159452 plugins/super_native_extensions/CMakeFiles/super_native_extensions_plugin.dir/super_native_extensions_plugin.cc.o e4e228e87b2f98cc
|
|
||||||
5645 6080 1721230632425032384 CMakeFiles/oc_front.dir/flutter/generated_plugin_registrant.cc.o 79b3e2ad61c9feb4
|
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_message_codec.h df34b103123784f1
|
|
||||||
6105 7479 1720190159919162468 plugins/irondash_engine_context/CMakeFiles/irondash_engine_context_plugin.dir/irondash_engine_context_plugin.cc.o 439d26d301366f5a
|
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_standard_message_codec.h df34b103123784f1
|
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_plugin_registrar.h df34b103123784f1
|
|
||||||
7479 7597 1720190160043160828 plugins/irondash_engine_context/libirondash_engine_context_plugin.so a89d3772b0fb0935
|
7479 7597 1720190160043160828 plugins/irondash_engine_context/libirondash_engine_context_plugin.so a89d3772b0fb0935
|
||||||
3 5644 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_value.h df34b103123784f1
|
43 7102 0 flutter/_phony_ df34b103123784f1
|
||||||
5645 5781 1721230632125036886 plugins/super_native_extensions/libsuper_native_extensions_plugin.so 87d9259f3dbf9022
|
13608 16421 1720171474184250688 plugins/desktop_window/CMakeFiles/desktop_window_plugin.dir/desktop_window_plugin.cc.o 259dba9caad978aa
|
||||||
3 326 1721231108669887541 plugins/super_native_extensions/libsuper_native_extensions.so 74762aee97d0d662
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_plugin_registry.h df34b103123784f1
|
||||||
3 326 1721231108669887541 plugins/super_native_extensions/_phony_ 74762aee97d0d662
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_call.h df34b103123784f1
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/libflutter_linux_gtk.so df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_plugin_registrar.h df34b103123784f1
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_basic_message_channel.h df34b103123784f1
|
6105 7479 1720190159919162468 plugins/irondash_engine_context/CMakeFiles/irondash_engine_context_plugin.dir/irondash_engine_context_plugin.cc.o 439d26d301366f5a
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_binary_codec.h df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_standard_message_codec.h df34b103123784f1
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_binary_messenger.h df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/libflutter_linux_gtk.so df34b103123784f1
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_dart_project.h df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_json_message_codec.h df34b103123784f1
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_engine.h df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/flutter_linux.h df34b103123784f1
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_json_message_codec.h df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_string_codec.h df34b103123784f1
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_json_method_codec.h df34b103123784f1
|
5895 6038 1720171596542283915 plugins/desktop_window/libdesktop_window_plugin.so 26c8f2b838605d38
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_message_codec.h df34b103123784f1
|
43 412 1723042867477311806 plugins/super_native_extensions/_phony_ 74762aee97d0d662
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_call.h df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_response.h df34b103123784f1
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_channel.h df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_binary_codec.h df34b103123784f1
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_codec.h df34b103123784f1
|
7223 7702 1720190160147159452 plugins/super_native_extensions/CMakeFiles/super_native_extensions_plugin.dir/super_native_extensions_plugin.cc.o e4e228e87b2f98cc
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_response.h df34b103123784f1
|
7117 18885 1723042885952976327 CMakeFiles/oc_front.dir/flutter/generated_plugin_registrant.cc.o 79b3e2ad61c9feb4
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_plugin_registrar.h df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_message_codec.h df34b103123784f1
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_plugin_registry.h df34b103123784f1
|
7117 16523 1723042883325023855 plugins/super_native_extensions/libsuper_native_extensions_plugin.so 87d9259f3dbf9022
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_standard_message_codec.h df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_json_method_codec.h df34b103123784f1
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_standard_method_codec.h df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_view.h df34b103123784f1
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_string_codec.h df34b103123784f1
|
43 7102 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_standard_method_codec.h df34b103123784f1
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_value.h df34b103123784f1
|
7221 7661 1720190160103160034 CMakeFiles/oc_front.dir/main.cc.o b1d36a8b3fb9d7f7
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_view.h df34b103123784f1
|
7116 18891 1723042885956976255 CMakeFiles/oc_front.dir/my_application.cc.o 3fd042b328f87769
|
||||||
3 5916 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/flutter_linux.h df34b103123784f1
|
58 466 1723042916288432161 plugins/super_native_extensions/libsuper_native_extensions.so 74762aee97d0d662
|
||||||
3 5916 0 flutter/_phony_ df34b103123784f1
|
58 466 1723042916288432161 plugins/super_native_extensions/_phony_ 74762aee97d0d662
|
||||||
5919 6044 1721231114401801556 plugins/super_native_extensions/libsuper_native_extensions_plugin.so 87d9259f3dbf9022
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/libflutter_linux_gtk.so df34b103123784f1
|
||||||
5918 6335 1721231114689797236 CMakeFiles/oc_front.dir/flutter/generated_plugin_registrant.cc.o 79b3e2ad61c9feb4
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_basic_message_channel.h df34b103123784f1
|
||||||
5917 6380 1721231114733796575 CMakeFiles/oc_front.dir/my_application.cc.o 3fd042b328f87769
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_binary_codec.h df34b103123784f1
|
||||||
6380 6517 1721231114873794475 intermediates_do_not_run/oc_front 4e630cc1de7b670a
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_binary_messenger.h df34b103123784f1
|
||||||
6517 6648 0 CMakeFiles/install.util 558f353ee1373233
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_dart_project.h df34b103123784f1
|
||||||
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_engine.h df34b103123784f1
|
||||||
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_json_message_codec.h df34b103123784f1
|
||||||
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_json_method_codec.h df34b103123784f1
|
||||||
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_message_codec.h df34b103123784f1
|
||||||
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_call.h df34b103123784f1
|
||||||
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_channel.h df34b103123784f1
|
||||||
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_codec.h df34b103123784f1
|
||||||
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_response.h df34b103123784f1
|
||||||
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_plugin_registrar.h df34b103123784f1
|
||||||
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_plugin_registry.h df34b103123784f1
|
||||||
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_standard_message_codec.h df34b103123784f1
|
||||||
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_standard_method_codec.h df34b103123784f1
|
||||||
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_string_codec.h df34b103123784f1
|
||||||
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_value.h df34b103123784f1
|
||||||
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_view.h df34b103123784f1
|
||||||
|
57 12620 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/flutter_linux.h df34b103123784f1
|
||||||
|
57 12620 0 flutter/_phony_ df34b103123784f1
|
||||||
|
12638 21600 1723042936588072438 plugins/super_native_extensions/libsuper_native_extensions_plugin.so 87d9259f3dbf9022
|
||||||
|
12638 24688 1723042940476003931 CMakeFiles/oc_front.dir/flutter/generated_plugin_registrant.cc.o 79b3e2ad61c9feb4
|
||||||
|
12638 24698 1723042940524003086 CMakeFiles/oc_front.dir/my_application.cc.o 3fd042b328f87769
|
||||||
|
24698 25496 1723042941331988865 intermediates_do_not_run/oc_front 4e630cc1de7b670a
|
||||||
|
25496 27380 0 CMakeFiles/install.util 558f353ee1373233
|
||||||
|
93 17067 1723043023530568429 plugins/super_native_extensions/libsuper_native_extensions.so 74762aee97d0d662
|
||||||
|
93 17067 1723043023530568429 plugins/super_native_extensions/_phony_ 74762aee97d0d662
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/libflutter_linux_gtk.so df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_basic_message_channel.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_binary_codec.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_binary_messenger.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_dart_project.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_engine.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_json_message_codec.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_json_method_codec.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_message_codec.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_call.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_channel.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_codec.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_response.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_plugin_registrar.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_plugin_registry.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_standard_message_codec.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_standard_method_codec.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_string_codec.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_value.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_view.h df34b103123784f1
|
||||||
|
91 25502 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/flutter_linux.h df34b103123784f1
|
||||||
|
91 25502 0 flutter/_phony_ df34b103123784f1
|
||||||
|
25503 26894 1723043048582145188 plugins/super_native_extensions/libsuper_native_extensions_plugin.so 87d9259f3dbf9022
|
||||||
|
25503 28785 1723043050470113462 CMakeFiles/oc_front.dir/flutter/generated_plugin_registrant.cc.o 79b3e2ad61c9feb4
|
||||||
|
25502 28787 1723043050470113462 CMakeFiles/oc_front.dir/my_application.cc.o 3fd042b328f87769
|
||||||
|
28787 28990 1723043050674110035 intermediates_do_not_run/oc_front 4e630cc1de7b670a
|
||||||
|
28990 29315 0 CMakeFiles/install.util 558f353ee1373233
|
||||||
|
26 384 1723043130512788850 plugins/super_native_extensions/libsuper_native_extensions.so 74762aee97d0d662
|
||||||
|
26 384 1723043130512788850 plugins/super_native_extensions/_phony_ 74762aee97d0d662
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/libflutter_linux_gtk.so df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_basic_message_channel.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_binary_codec.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_binary_messenger.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_dart_project.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_engine.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_json_message_codec.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_json_method_codec.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_message_codec.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_call.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_channel.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_codec.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_method_response.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_plugin_registrar.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_plugin_registry.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_standard_message_codec.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_standard_method_codec.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_string_codec.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_value.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/fl_view.h df34b103123784f1
|
||||||
|
26 6081 0 /home/mr/Documents/OC/oc-front/linux/flutter/ephemeral/flutter_linux/flutter_linux.h df34b103123784f1
|
||||||
|
26 6081 0 flutter/_phony_ df34b103123784f1
|
||||||
|
6084 6259 1723043136404692840 plugins/super_native_extensions/libsuper_native_extensions_plugin.so 87d9259f3dbf9022
|
||||||
|
6083 6556 1723043136700688022 CMakeFiles/oc_front.dir/flutter/generated_plugin_registrant.cc.o 79b3e2ad61c9feb4
|
||||||
|
6082 6587 1723043136728687566 CMakeFiles/oc_front.dir/my_application.cc.o 3fd042b328f87769
|
||||||
|
6587 6802 1723043136948683986 intermediates_do_not_run/oc_front 4e630cc1de7b670a
|
||||||
|
6802 6962 0 CMakeFiles/install.util 558f353ee1373233
|
||||||
|
@ -1 +1 @@
|
|||||||
assets/images/icon.svg
assetassets/images/icon.svgassets/images/logo.svg
assetassets/images/logo.svg2packages/cupertino_icons/assets/CupertinoIcons.ttf
asset2packages/cupertino_icons/assets/CupertinoIcons.ttf4packages/flutter_map/lib/assets/flutter_map_logo.png
asset4packages/flutter_map/lib/assets/flutter_map_logo.png
|
assets/images/icon.svg
assetassets/images/icon.svgassets/images/logo.svg
assetassets/images/logo.svg2packages/cupertino_icons/assets/CupertinoIcons.ttf
asset2packages/cupertino_icons/assets/CupertinoIcons.ttf4packages/flutter_map/lib/assets/flutter_map_logo.png
asset4packages/flutter_map/lib/assets/flutter_map_logo.png%packages/timezone/data/latest_all.tzf
asset%packages/timezone/data/latest_all.tzf
|
@ -1 +1 @@
|
|||||||
{"assets/images/icon.svg":["assets/images/icon.svg"],"assets/images/logo.svg":["assets/images/logo.svg"],"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"],"packages/flutter_map/lib/assets/flutter_map_logo.png":["packages/flutter_map/lib/assets/flutter_map_logo.png"]}
|
{"assets/images/icon.svg":["assets/images/icon.svg"],"assets/images/logo.svg":["assets/images/logo.svg"],"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"],"packages/flutter_map/lib/assets/flutter_map_logo.png":["packages/flutter_map/lib/assets/flutter_map_logo.png"],"packages/timezone/data/latest_all.tzf":["packages/timezone/data/latest_all.tzf"]}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -14,6 +14,7 @@
|
|||||||
/home/mr/Documents/OC/oc-front/build/linux/x64/debug/bundle/data/flutter_assets/NOTICES.Z
|
/home/mr/Documents/OC/oc-front/build/linux/x64/debug/bundle/data/flutter_assets/NOTICES.Z
|
||||||
/home/mr/Documents/OC/oc-front/build/linux/x64/debug/bundle/data/flutter_assets/packages/cupertino_icons/assets/CupertinoIcons.ttf
|
/home/mr/Documents/OC/oc-front/build/linux/x64/debug/bundle/data/flutter_assets/packages/cupertino_icons/assets/CupertinoIcons.ttf
|
||||||
/home/mr/Documents/OC/oc-front/build/linux/x64/debug/bundle/data/flutter_assets/packages/flutter_map/lib/assets/flutter_map_logo.png
|
/home/mr/Documents/OC/oc-front/build/linux/x64/debug/bundle/data/flutter_assets/packages/flutter_map/lib/assets/flutter_map_logo.png
|
||||||
|
/home/mr/Documents/OC/oc-front/build/linux/x64/debug/bundle/data/flutter_assets/packages/timezone/data/latest_all.tzf
|
||||||
/home/mr/Documents/OC/oc-front/build/linux/x64/debug/bundle/data/flutter_assets/version.json
|
/home/mr/Documents/OC/oc-front/build/linux/x64/debug/bundle/data/flutter_assets/version.json
|
||||||
/home/mr/Documents/OC/oc-front/build/linux/x64/debug/bundle/data/flutter_assets/FontManifest.json
|
/home/mr/Documents/OC/oc-front/build/linux/x64/debug/bundle/data/flutter_assets/FontManifest.json
|
||||||
/home/mr/Documents/OC/oc-front/build/linux/x64/debug/bundle/data/flutter_assets/AssetManifest.bin
|
/home/mr/Documents/OC/oc-front/build/linux/x64/debug/bundle/data/flutter_assets/AssetManifest.bin
|
@ -1,29 +0,0 @@
|
|||||||
import 'package:oc_front/models/search.dart';
|
|
||||||
|
|
||||||
class Graphs {
|
|
||||||
static const Map<String, Graph> graphs = {};
|
|
||||||
|
|
||||||
static Graph getGraph(String id) {
|
|
||||||
return graphs[id]!;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void addGraph(String id, Graph graph) {
|
|
||||||
graphs[id] = graph;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void removeGraph(String id) {
|
|
||||||
graphs.remove(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clear() {
|
|
||||||
graphs.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Graph {
|
|
||||||
String id;
|
|
||||||
List<AbstractItem> items = [];
|
|
||||||
|
|
||||||
Graph({ required this.id, required this.items }) {
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,84 +1,177 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
|
||||||
|
import 'package:oc_front/core/sections/end_drawer.dart';
|
||||||
import 'package:oc_front/models/search.dart';
|
import 'package:oc_front/models/search.dart';
|
||||||
import 'package:oc_front/models/workspace.dart';
|
import 'package:oc_front/models/workspace.dart';
|
||||||
import 'package:oc_front/core/services/specialized_services/item_service.dart';
|
|
||||||
import 'package:oc_front/core/services/specialized_services/workspace_service.dart';
|
import 'package:oc_front/core/services/specialized_services/workspace_service.dart';
|
||||||
|
import 'package:oc_front/pages/catalog.dart';
|
||||||
|
import 'package:oc_front/pages/catalog_item.dart';
|
||||||
|
import 'package:oc_front/pages/workflow.dart';
|
||||||
|
|
||||||
|
class WorkSpaceItem {
|
||||||
|
String? id;
|
||||||
|
String? name;
|
||||||
|
WorkSpaceItem({this.id, this.name});
|
||||||
|
}
|
||||||
|
|
||||||
class WorkspaceLocal {
|
class WorkspaceLocal {
|
||||||
static Workspace? workspace;
|
static String? current;
|
||||||
|
static Map<String, Workspace> workspaces = {};
|
||||||
static final WorkspaceService _service = WorkspaceService();
|
static final WorkspaceService _service = WorkspaceService();
|
||||||
static List<AbstractItem> items = [];
|
static List<AbstractItem> items = [];
|
||||||
static void init(BuildContext context) {
|
|
||||||
|
static void init(BuildContext context, bool changeCurrent) {
|
||||||
_service.all(context).then((value) {
|
_service.all(context).then((value) {
|
||||||
workspace = value.data;
|
if (value.data != null && value.data!.values.isNotEmpty ) {
|
||||||
if (workspace != null) {
|
var vals = value.data!.values;
|
||||||
if (workspace!.data.isNotEmpty) {
|
for (var element in vals) {
|
||||||
ItemService<DataItem, DataItem> dataService = ItemService<DataItem, DataItem>();
|
var ws = Workspace().deserialize(element);
|
||||||
for (var element in workspace!.data) {
|
if (ws.id == null) { continue; }
|
||||||
if (WorkspaceLocal.hasItemByID(element)) { continue; }
|
workspaces[ws.id!] = ws;
|
||||||
dataService.get(context, element).then(
|
if (current == null) {
|
||||||
(value) { if (value.data != null) { items.add(value.data!); } }
|
current ??= ws.id;
|
||||||
);
|
workspaces[current!] = ws;
|
||||||
|
_service.put(context, ws.id!, { "active" : true }, {});
|
||||||
}
|
}
|
||||||
|
if (ws.active == true && changeCurrent) {
|
||||||
|
current = ws.id;
|
||||||
}
|
}
|
||||||
if (workspace!.computing.isNotEmpty) {
|
fill();
|
||||||
ItemService<ComputingItem, ComputingItem> computingService = ItemService<ComputingItem, ComputingItem>();
|
|
||||||
for (var element in workspace!.computing) {
|
|
||||||
if (WorkspaceLocal.hasItemByID(element)) { continue; }
|
|
||||||
computingService.get(context, element).then(
|
|
||||||
(value) { if (value.data != null) { items.add(value.data!); } }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (workspace!.datacenter.isNotEmpty) {
|
|
||||||
ItemService<DataCenterItem, DataCenterItem> dataCenterService = ItemService<DataCenterItem, DataCenterItem>();
|
|
||||||
for (var element in workspace!.datacenter) {
|
|
||||||
if (WorkspaceLocal.hasItemByID(element)) { continue; }
|
|
||||||
dataCenterService.get(context, element).then(
|
|
||||||
(value) { if (value.data != null) { items.add(value.data!); } }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (workspace!.storage.isNotEmpty) {
|
|
||||||
ItemService<StorageItem, StorageItem> storageService = ItemService<StorageItem, StorageItem>();
|
|
||||||
for (var element in workspace!.storage) {
|
|
||||||
if (WorkspaceLocal.hasItemByID(element)) { continue; }
|
|
||||||
storageService.get(context, element).then(
|
|
||||||
(value) { if (value.data != null) { items.add(value.data!); } }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
WorkspaceLocal.createWorkspace("main", context);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
static List<AbstractItem> byTopic(String topic) {
|
|
||||||
|
static void fill() {
|
||||||
|
items = [];
|
||||||
|
if (workspaces[current] != null) {
|
||||||
|
for (var element in workspaces[current]!.datas) {
|
||||||
|
if (WorkspaceLocal.hasItemByID(element.getID())) { continue; }
|
||||||
|
items.add(element);
|
||||||
|
}
|
||||||
|
for (var element in workspaces[current]!.processings) {
|
||||||
|
if (WorkspaceLocal.hasItemByID(element.getID())) { continue; }
|
||||||
|
items.add(element); }
|
||||||
|
for (var element in workspaces[current]!.datacenters) {
|
||||||
|
if (WorkspaceLocal.hasItemByID(element.getID())) { continue; }
|
||||||
|
items.add(element);
|
||||||
|
}
|
||||||
|
for (var element in workspaces[current]!.storages) {
|
||||||
|
if (WorkspaceLocal.hasItemByID(element.getID())) { continue; }
|
||||||
|
items.add(element);
|
||||||
|
}
|
||||||
|
for (var element in workspaces[current]!.workflows) {
|
||||||
|
if (WorkspaceLocal.hasItemByID(element.getID())) { continue; }
|
||||||
|
items.add(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Workspace? getCurrentWorkspace() {
|
||||||
|
return workspaces[current];
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> deleteWorkspace(String id) async {
|
||||||
|
if (workspaces.containsKey(id) && workspaces.length == 1) { return; }
|
||||||
|
workspaces.remove(id);
|
||||||
|
await _service.delete(null, id, {});
|
||||||
|
current = workspaces.keys.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> createWorkspace(String name, BuildContext? context) async {
|
||||||
|
Workspace n = Workspace(name: name);
|
||||||
|
await _service.post(context, n.serialize(), {}).then((value) {
|
||||||
|
if (value.data != null) {
|
||||||
|
workspaces[value.data!.id!] = value.data!;
|
||||||
|
current = value.data!.id;
|
||||||
|
fill();
|
||||||
|
endDrawerKey.currentState?.setState(() {});
|
||||||
|
CatalogFactory.key.currentState?.setState(() {});
|
||||||
|
CatalogItemFactory.key.currentState?.setState(() {});
|
||||||
|
WorkflowFactory.key.currentState?.setState(() {});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void changeWorkspace(String id) {
|
||||||
|
current = id;
|
||||||
|
fill();
|
||||||
|
endDrawerKey.currentState?.setState(() {});
|
||||||
|
CatalogFactory.key.currentState?.setState(() {});
|
||||||
|
CatalogItemFactory.key.currentState?.setState(() {});
|
||||||
|
WorkflowFactory.key.currentState?.setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<WorkSpaceItem> getWorkspacesIDS() {
|
||||||
|
List<WorkSpaceItem> res = [];
|
||||||
|
for (var element in workspaces.entries) {
|
||||||
|
res.add(WorkSpaceItem(id: element.key, name: element.value.name));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<AbstractItem> byTopic(String topic, bool all) {
|
||||||
|
if (all) {
|
||||||
|
List<AbstractItem<FlowData>> d = [];
|
||||||
|
for (var w in workspaces.values) {
|
||||||
|
d = [ ...d, ...w.datas.where((element) => !d.map( (d2) => d2.id).contains(element.id)) ];
|
||||||
|
d = [ ...d, ...w.datacenters.where((element) => !d.map( (d2) => d2.id).contains(element.id)) ];
|
||||||
|
d = [ ...d, ...w.processings.where((element) => !d.map( (d2) => d2.id).contains(element.id)) ];
|
||||||
|
d = [ ...d, ...w.storages.where((element) => !d.map( (d2) => d2.id).contains(element.id)) ];
|
||||||
|
d = [ ...d, ...w.workflows.where((element) => !d.map( (d2) => d2.id).contains(element.id)) ];
|
||||||
|
}
|
||||||
|
return d.where((element) => element.topic.toString() == topic).toList();
|
||||||
|
}
|
||||||
return WorkspaceLocal.items.where((element) => element.topic.toString() == topic).toList();
|
return WorkspaceLocal.items.where((element) => element.topic.toString() == topic).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
static AbstractItem? getItem(String id) {
|
static AbstractItem? getItem(String id, bool all) {
|
||||||
|
if (all) {
|
||||||
|
List<AbstractItem<FlowData>> d = [];
|
||||||
|
for (var w in workspaces.values) {
|
||||||
|
d = [ ...d, ...w.datas.where((element) => element.id.toString() == id).where((element) => !d.map( (d2) => d2.id).contains(element.id)) ];
|
||||||
|
d = [ ...d, ...w.datacenters.where((element) => element.id.toString() == id).where((element) => !d.map( (d2) => d2.id).contains(element.id)) ];
|
||||||
|
d = [ ...d, ...w.processings.where((element) => element.id.toString() == id).where((element) => !d.map( (d2) => d2.id).contains(element.id)) ];
|
||||||
|
d = [ ...d, ...w.storages.where((element) => element.id.toString() == id).where((element) => !d.map( (d2) => d2.id).contains(element.id)) ];
|
||||||
|
d = [ ...d, ...w.workflows.where((element) => element.id.toString() == id).where((element) => !d.map( (d2) => d2.id).contains(element.id)) ];
|
||||||
|
}
|
||||||
|
return d.isEmpty ? null : d.first;
|
||||||
|
}
|
||||||
var found = WorkspaceLocal.items.where((element) => element.id.toString() == id);
|
var found = WorkspaceLocal.items.where((element) => element.id.toString() == id);
|
||||||
return found.isEmpty ? null : found.first;
|
return found.isEmpty ? null : found.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addItem(AbstractItem item) {
|
static void addItem(AbstractItem item) {
|
||||||
if (!WorkspaceLocal.hasItem(item)) {
|
if (!WorkspaceLocal.hasItem(item) && workspaces[current] != null && workspaces[current]!.id != null) {
|
||||||
items.add(item);
|
items.add(item);
|
||||||
try {
|
if (item.topic == "data") { workspaces[current]!.datas.add(item as DataItem); }
|
||||||
_service.post(null, {}, { "id" : item.id.toString(), "rtype" : item.type.toString() });
|
if (item.topic == "processing") { workspaces[current]!.processings.add(item as ProcessingItem); }
|
||||||
|
if (item.topic == "datacenter") { workspaces[current]!.datacenters.add(item as DataCenterItem); }
|
||||||
|
if (item.topic == "storage") { workspaces[current]!.storages.add(item as StorageItem); }
|
||||||
|
if (item.topic == "workflow") { workspaces[current]!.workflows.add(item as WorkflowItem); }
|
||||||
|
try { _service.put(null, workspaces[current]!.id!, workspaces[current]!.serialize(), {});
|
||||||
} catch (e) { /* */ }
|
} catch (e) { /* */ }
|
||||||
|
_service.put(null, item.id ?? "", workspaces[current]!.serialize(), {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void removeItem(AbstractItem item) {
|
static void removeItem(AbstractItem item) {
|
||||||
items = items.where((element) => element.name != item.name).toList();
|
items = items.where((element) => element.name != item.name).toList();
|
||||||
try { _service.delete(null, { "id" : item.id.toString(), "rtype" : item.type.toString() });
|
if (item.topic == "data") { workspaces[current]!.datas.removeWhere( (e) => e.id == item.id); }
|
||||||
|
if (item.topic == "processing") { workspaces[current]!.processings.removeWhere( (e) => e.id == item.id); }
|
||||||
|
if (item.topic == "datacenter") { workspaces[current]!.datacenters.removeWhere( (e) => e.id == item.id); }
|
||||||
|
if (item.topic == "storage") { workspaces[current]!.storages.removeWhere( (e) => e.id == item.id); }
|
||||||
|
if (item.topic == "workflow") { workspaces[current]!.workflows.removeWhere( (e) => e.id == item.id); }
|
||||||
|
try { _service.put(null, workspaces[current]!.id!, workspaces[current]!.serialize(), {});
|
||||||
} catch (e) { /* */ }
|
} catch (e) { /* */ }
|
||||||
|
_service.put(null, item.id ?? "", workspaces[current]!.serialize(), {});
|
||||||
}
|
}
|
||||||
static bool hasItemByID(String id) {
|
static bool hasItemByID(String id) {
|
||||||
return items.where((element) => element.id == id).isNotEmpty;
|
return items.where((element) => element.id == id).isNotEmpty;
|
||||||
}
|
}
|
||||||
static bool hasItem(AbstractItem item) {
|
static bool hasItem(AbstractItem item) {
|
||||||
return items.where((element) => element.name == item.name).isNotEmpty;
|
return items.where((element) => element.id == item.id).isNotEmpty;
|
||||||
}
|
}
|
||||||
static void clear() => items.clear();
|
static void clear() => items.clear();
|
||||||
}
|
}
|
@ -3,6 +3,7 @@ import 'package:oc_front/models/search.dart';
|
|||||||
import 'package:oc_front/pages/catalog.dart';
|
import 'package:oc_front/pages/catalog.dart';
|
||||||
import 'package:oc_front/core/models/workspace_local.dart';
|
import 'package:oc_front/core/models/workspace_local.dart';
|
||||||
import 'package:oc_front/widgets/items/item_row.dart';
|
import 'package:oc_front/widgets/items/item_row.dart';
|
||||||
|
import 'package:oc_front/widgets/menu_clipper/workspace_menu.dart';
|
||||||
|
|
||||||
GlobalKey<EndDrawerWidgetState> endDrawerKey = GlobalKey<EndDrawerWidgetState>();
|
GlobalKey<EndDrawerWidgetState> endDrawerKey = GlobalKey<EndDrawerWidgetState>();
|
||||||
class EndDrawerWidget extends StatefulWidget {
|
class EndDrawerWidget extends StatefulWidget {
|
||||||
@ -33,7 +34,8 @@ class EndDrawerWidgetState extends State<EndDrawerWidget> {
|
|||||||
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
itemRows.isEmpty ? Container( height: MediaQuery.of(context).size.height - 50,
|
MenuWorkspaceWidget(simpliest: true, width: 400),
|
||||||
|
itemRows.isEmpty ? Container( height: MediaQuery.of(context).size.height - 100,
|
||||||
color: Colors.grey.shade300,
|
color: Colors.grey.shade300,
|
||||||
child: const Center(child: Text("WORKSPACE IS EMPTY",
|
child: const Center(child: Text("WORKSPACE IS EMPTY",
|
||||||
style: TextStyle(fontSize: 25, fontWeight: FontWeight.w600, color: Colors.white))))
|
style: TextStyle(fontSize: 25, fontWeight: FontWeight.w600, color: Colors.white))))
|
||||||
|
@ -61,7 +61,7 @@ class SearchWidgetState extends State<SearchWidget> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
width: MediaQuery.of(context).size.width - 300 - 100,
|
width: MediaQuery.of(context).size.width - 400 > 0 ? MediaQuery.of(context).size.width - 300 - 100 : MediaQuery.of(context).size.width,
|
||||||
height: 50,
|
height: 50,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
|
@ -82,18 +82,17 @@ class APIService<T extends SerializerDeserializer> {
|
|||||||
_dio.options.headers["authorization"] = auth;
|
_dio.options.headers["authorization"] = auth;
|
||||||
_dio.interceptors.clear();
|
_dio.interceptors.clear();
|
||||||
var response = await _request(url, method, body, options);
|
var response = await _request(url, method, body, options);
|
||||||
|
print(response);
|
||||||
if (response.statusCode != null && response.statusCode! < 400) {
|
if (response.statusCode != null && response.statusCode! < 400) {
|
||||||
if (method == "delete") { cache.remove(url); return APIResponse<T>(); }
|
if (method == "delete") { cache.remove(url); return APIResponse<T>(); }
|
||||||
APIResponse<T> resp = APIResponse<T>().deserialize(response.data);
|
APIResponse<T> resp = APIResponse<T>().deserialize(response.data);
|
||||||
if (resp.error == "") {
|
if (resp.error == "") {
|
||||||
if (method == "get") { cache[url]=resp; }
|
|
||||||
if (context != null && succeed != "") {
|
if (context != null && succeed != "") {
|
||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
showAlertBanner(context, () {}, InfoAlertBannerChild(text: succeed), // <-- Put any widget here you want!
|
showAlertBanner(context, () {}, InfoAlertBannerChild(text: succeed), // <-- Put any widget here you want!
|
||||||
alertBannerLocation: AlertBannerLocation.bottom,);
|
alertBannerLocation: AlertBannerLocation.bottom,);
|
||||||
}
|
}
|
||||||
try { return cache[url] as APIResponse<T>;
|
return resp;
|
||||||
} catch (e) { return APIResponse(); }
|
|
||||||
}
|
}
|
||||||
err = resp.error ?? "internal error";
|
err = resp.error ?? "internal error";
|
||||||
}
|
}
|
||||||
|
@ -52,9 +52,10 @@ class AppRouter {
|
|||||||
description: "View to select & create new workflow.", help: "Workflow only access to your workspace datas. If a an element of your flow is missing, perhaps means it's missing in workspace.",
|
description: "View to select & create new workflow.", help: "Workflow only access to your workspace datas. If a an element of your flow is missing, perhaps means it's missing in workspace.",
|
||||||
factory: WorkflowFactory());
|
factory: WorkflowFactory());
|
||||||
static final RouterItem catalogItem = RouterItem(description: "", help: "", route: "catalog/:id", factory: CatalogItemFactory(), args: ["id"]);
|
static final RouterItem catalogItem = RouterItem(description: "", help: "", route: "catalog/:id", factory: CatalogItemFactory(), args: ["id"]);
|
||||||
|
static final RouterItem catalog= RouterItem(icon: Icons.book_outlined, label: "catalog searcher", route: home, factory: CatalogFactory());
|
||||||
|
|
||||||
static List<RouterItem> zones = [
|
static List<RouterItem> zones = [
|
||||||
RouterItem(icon: Icons.book_outlined, label: "catalog searcher", route: home, factory: CatalogFactory()),
|
catalog,
|
||||||
workflowItem,
|
workflowItem,
|
||||||
RouterItem(icon: Icons.schedule, label: "scheduled tasks", route: "scheduler", factory: SchedulerFactory()),
|
RouterItem(icon: Icons.schedule, label: "scheduled tasks", route: "scheduler", factory: SchedulerFactory()),
|
||||||
RouterItem(icon: Icons.dns_outlined, label: "my datacenter", route: "datacenter",
|
RouterItem(icon: Icons.dns_outlined, label: "my datacenter", route: "datacenter",
|
||||||
|
@ -7,9 +7,21 @@ abstract class AbstractService<T extends SerializerDeserializer> {
|
|||||||
abstract APIService<T> service;
|
abstract APIService<T> service;
|
||||||
abstract String subPath;
|
abstract String subPath;
|
||||||
|
|
||||||
Future<APIResponse<T>> all(BuildContext? context) { throw UnimplementedError(); }
|
Future<APIResponse<T>> search(BuildContext? context, List<String> words, Map<String, dynamic> params) { throw UnimplementedError(); }
|
||||||
Future<APIResponse<T>> get(BuildContext? context, String id);
|
Future<APIResponse<RawData>> all(BuildContext? context) {
|
||||||
Future<APIResponse<T>> post(BuildContext? context, Map<String, dynamic> body, Map<String, String> params);
|
return service.raw(subPath, null, "get");
|
||||||
Future<APIResponse<T>> put(BuildContext? context, String id, Map<String, dynamic> body, Map<String, String> params) { throw UnimplementedError(); }
|
|
||||||
Future<APIResponse<T>> delete(BuildContext? context, Map<String, String> params) { throw UnimplementedError(); }
|
|
||||||
}
|
}
|
||||||
|
Future<APIResponse<T>> get(BuildContext? context, String id) {
|
||||||
|
return service.get("$subPath$id", true, context);
|
||||||
|
}
|
||||||
|
Future<APIResponse<T>> post(BuildContext? context, Map<String, dynamic> body, Map<String, String> params) {
|
||||||
|
return service.post(subPath, body, context);
|
||||||
|
}
|
||||||
|
Future<APIResponse<T>> put(BuildContext? context, String id, Map<String, dynamic> body, Map<String, String> params) {
|
||||||
|
return service.put("$subPath$id", body, context);
|
||||||
|
}
|
||||||
|
Future<APIResponse<T>> delete(BuildContext? context, String id, Map<String, String> params) {
|
||||||
|
return service.delete("$subPath$id", context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,24 +1,11 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:oc_front/core/services/api_service.dart';
|
import 'package:oc_front/core/services/api_service.dart';
|
||||||
import 'package:oc_front/core/services/specialized_services/abstract_service.dart';
|
import 'package:oc_front/core/services/specialized_services/abstract_service.dart';
|
||||||
import 'package:oc_front/models/abstract.dart';
|
import 'package:oc_front/models/abstract.dart';
|
||||||
import 'package:oc_front/models/response.dart';
|
|
||||||
import 'package:oc_front/models/search.dart';
|
import 'package:oc_front/models/search.dart';
|
||||||
|
|
||||||
class ItemService<S extends AbstractItem, T extends SerializerDeserializer<S>> extends AbstractService<T> {
|
class ItemService<S extends AbstractItem, T extends SerializerDeserializer<S>> extends AbstractService<T> {
|
||||||
@override APIService<T> service = APIService<T>(
|
@override APIService<T> service = APIService<T>(
|
||||||
baseURL: const String.fromEnvironment('ITEM_HOST', defaultValue: 'http://localhost:49618')
|
baseURL: const String.fromEnvironment('ITEM_HOST', defaultValue: 'http://localhost:8087')
|
||||||
);
|
);
|
||||||
@override String subPath = "/v1/${getTopic(S)}";
|
@override String subPath = "/oc/${getTopic(S)}/";
|
||||||
|
|
||||||
@override Future<APIResponse<T>> all(BuildContext? context) { throw UnimplementedError(); }
|
|
||||||
@override Future<APIResponse<T>> get(BuildContext? context, String id) {
|
|
||||||
if (id.contains(",")) { return service.get("$subPath/multi/$id", true, context); }
|
|
||||||
return service.get("$subPath/$id", true, context);
|
|
||||||
}
|
|
||||||
@override Future<APIResponse<T>> post(BuildContext? context, Map<String, dynamic> body, Map<String, String> params) {
|
|
||||||
return service.post("$subPath/", body, context);
|
|
||||||
}
|
|
||||||
@override Future<APIResponse<T>> put(BuildContext? context, String id, Map<String, dynamic> body, Map<String, String> params) { throw UnimplementedError(); }
|
|
||||||
@override Future<APIResponse<T>> delete(BuildContext? context, Map<String, String> params) { throw UnimplementedError(); }
|
|
||||||
}
|
}
|
34
lib/core/services/specialized_services/logs_service.dart
Normal file
34
lib/core/services/specialized_services/logs_service.dart
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:oc_front/core/services/api_service.dart';
|
||||||
|
import 'package:oc_front/core/services/specialized_services/abstract_service.dart';
|
||||||
|
import 'package:oc_front/models/logs.dart';
|
||||||
|
import 'package:oc_front/models/response.dart';
|
||||||
|
|
||||||
|
class LogsService extends AbstractService<LogResults> {
|
||||||
|
@override APIService<LogResults> service = APIService<LogResults>(
|
||||||
|
baseURL: const String.fromEnvironment('SCHEDULER_HOST', defaultValue: 'http://localhost:3100')
|
||||||
|
);
|
||||||
|
@override String subPath = "/loki/api/v1/";
|
||||||
|
|
||||||
|
@override Future<APIResponse<LogResults>> search(BuildContext? context, List<String> words, Map<String, dynamic> params) {
|
||||||
|
List<String> v = [];
|
||||||
|
for (var p in params.keys) {
|
||||||
|
if (p == "start" || p == "end") { continue; }
|
||||||
|
v.add("$p=\"${params[p]}\"");
|
||||||
|
}
|
||||||
|
return service.get("${subPath}query_range?query={${v.join(", ")}}&start=${params["start"]}&end=${params["end"]}", false, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override Future<APIResponse<LogResults>> get(BuildContext? context, String id) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
@override Future<APIResponse<LogResults>> post(BuildContext? context, Map<String, dynamic> body, Map<String, String> params) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
@override Future<APIResponse<LogResults>> put(BuildContext? context, String id, Map<String, dynamic> body, Map<String, String> params) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
@override Future<APIResponse<LogResults>> delete(BuildContext? context, String id, Map<String, String> params) {
|
||||||
|
throw UnimplementedError();
|
||||||
|
}
|
||||||
|
}
|
23
lib/core/services/specialized_services/resource_service.dart
Normal file
23
lib/core/services/specialized_services/resource_service.dart
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:oc_front/core/services/api_service.dart';
|
||||||
|
import 'package:oc_front/core/services/specialized_services/abstract_service.dart';
|
||||||
|
import 'package:oc_front/models/response.dart';
|
||||||
|
import 'package:oc_front/models/search.dart';
|
||||||
|
|
||||||
|
class ResourceService extends AbstractService<Resource> {
|
||||||
|
@override APIService<Resource> service = APIService<Resource>(
|
||||||
|
baseURL: const String.fromEnvironment('ITEM_HOST', defaultValue: 'http://localhost:8087')
|
||||||
|
);
|
||||||
|
@override String subPath = "/oc/resource/";
|
||||||
|
|
||||||
|
@override Future<APIResponse<Resource>> search(BuildContext? context, List<String> words, Map<String, dynamic> params) {
|
||||||
|
return service.get("${subPath}search/${words.join("/")}", false, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override Future<APIResponse<Resource>> post(BuildContext? context, Map<String, dynamic> body, Map<String, String> params) {
|
||||||
|
return throw UnimplementedError();
|
||||||
|
}
|
||||||
|
@override Future<APIResponse<Resource>> put(BuildContext? context, String id, Map<String, dynamic> body, Map<String, String> params) {
|
||||||
|
return throw UnimplementedError();
|
||||||
|
}
|
||||||
|
}
|
@ -1,19 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:oc_front/core/services/api_service.dart';
|
|
||||||
import 'package:oc_front/core/services/specialized_services/abstract_service.dart';
|
|
||||||
import 'package:oc_front/models/response.dart';
|
|
||||||
import 'package:oc_front/models/search.dart';
|
|
||||||
|
|
||||||
class SearchService extends AbstractService<Search> {
|
|
||||||
@override APIService<Search> service = APIService<Search>(
|
|
||||||
baseURL: const String.fromEnvironment('SEARCH_HOST', defaultValue: 'http://localhost:49618')
|
|
||||||
);
|
|
||||||
@override String subPath = "/v1/search";
|
|
||||||
@override Future<APIResponse<Search>> all(BuildContext? context) { throw UnimplementedError(); }
|
|
||||||
@override Future<APIResponse<Search>> get(BuildContext? context, String id) {
|
|
||||||
return service.get("$subPath/byWord?word=$id", true, context);
|
|
||||||
}
|
|
||||||
@override Future<APIResponse<Search>> post(BuildContext? context, Map<String, dynamic> body, Map<String, String> params) { throw UnimplementedError(); }
|
|
||||||
@override Future<APIResponse<Search>> put(BuildContext? context, String id, Map<String, dynamic> body, Map<String, String> params) { throw UnimplementedError(); }
|
|
||||||
@override Future<APIResponse<Search>> delete(BuildContext? context, Map<String, String> params) { throw UnimplementedError(); }
|
|
||||||
}
|
|
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:oc_front/core/services/api_service.dart';
|
||||||
|
import 'package:oc_front/core/services/specialized_services/abstract_service.dart';
|
||||||
|
import 'package:oc_front/models/response.dart';
|
||||||
|
import 'package:oc_front/models/workflow.dart';
|
||||||
|
|
||||||
|
class WorkflowExecutionService extends AbstractService<WorkflowExecutions> {
|
||||||
|
@override APIService<WorkflowExecutions> service = APIService<WorkflowExecutions>(
|
||||||
|
baseURL: const String.fromEnvironment('SCHEDULER_HOST', defaultValue: 'http://localhost:8090')
|
||||||
|
);
|
||||||
|
@override String subPath = "/oc/workflow_execution/";
|
||||||
|
|
||||||
|
@override Future<APIResponse<WorkflowExecutions>> search(BuildContext? context, List<String> words, Map<String, dynamic> params) {
|
||||||
|
return service.get("${subPath}search/${words.join("/")}", false, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override Future<APIResponse<WorkflowExecutions>> post(BuildContext? context, Map<String, dynamic> body, Map<String, String> params) {
|
||||||
|
return throw UnimplementedError();
|
||||||
|
}
|
||||||
|
@override Future<APIResponse<WorkflowExecutions>> put(BuildContext? context, String id, Map<String, dynamic> body, Map<String, String> params) {
|
||||||
|
return throw UnimplementedError();
|
||||||
|
}
|
||||||
|
}
|
@ -1,26 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:oc_front/core/services/api_service.dart';
|
import 'package:oc_front/core/services/api_service.dart';
|
||||||
import 'package:oc_front/core/services/specialized_services/abstract_service.dart';
|
import 'package:oc_front/core/services/specialized_services/abstract_service.dart';
|
||||||
import 'package:oc_front/models/response.dart';
|
import 'package:oc_front/models/workflow.dart';
|
||||||
|
|
||||||
class WorflowService extends AbstractService<RawData> {
|
class WorflowService extends AbstractService<Workflow> {
|
||||||
@override APIService<RawData> service = APIService<RawData>(
|
@override APIService<Workflow> service = APIService<Workflow>(
|
||||||
baseURL: const String.fromEnvironment('WORKFLOW_HOST', defaultValue: 'http://localhost:49618')
|
baseURL: const String.fromEnvironment('WORKFLOW_HOST', defaultValue: 'http://localhost:8088')
|
||||||
);
|
);
|
||||||
@override String subPath = "/v1/workflow/";
|
@override String subPath = "/oc/workflow/";
|
||||||
@override Future<APIResponse<RawData>> all(BuildContext? context) {
|
|
||||||
return service.get(subPath, true, context);
|
|
||||||
}
|
|
||||||
@override Future<APIResponse<RawData>> get(BuildContext? context, String id) { throw UnimplementedError(); }
|
|
||||||
@override Future<APIResponse<RawData>> post(BuildContext? context, Map<String, dynamic> body, Map<String, String> params) {
|
|
||||||
String path = "?";
|
|
||||||
for (var key in params.keys) { path += "$key=${params[key]}&"; }
|
|
||||||
return service.post("$subPath$path", body, context);
|
|
||||||
}
|
|
||||||
@override Future<APIResponse<RawData>> put(BuildContext? context, String id, Map<String, dynamic> body, Map<String, String> params) {
|
|
||||||
throw UnimplementedError();
|
|
||||||
}
|
|
||||||
@override Future<APIResponse<RawData>> delete(BuildContext? context, Map<String, String> params) {
|
|
||||||
throw UnimplementedError();
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,30 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:oc_front/core/services/api_service.dart';
|
import 'package:oc_front/core/services/api_service.dart';
|
||||||
import 'package:oc_front/core/services/specialized_services/abstract_service.dart';
|
import 'package:oc_front/core/services/specialized_services/abstract_service.dart';
|
||||||
import 'package:oc_front/models/response.dart';
|
|
||||||
import 'package:oc_front/models/workspace.dart';
|
import 'package:oc_front/models/workspace.dart';
|
||||||
|
|
||||||
class WorkspaceService extends AbstractService<Workspace> {
|
class WorkspaceService extends AbstractService<Workspace> {
|
||||||
@override APIService<Workspace> service = APIService<Workspace>(
|
@override APIService<Workspace> service = APIService<Workspace>(
|
||||||
baseURL: const String.fromEnvironment('WORKSPACE_HOST', defaultValue: 'http://localhost:49618')
|
baseURL: const String.fromEnvironment('WORKSPACE_HOST', defaultValue: 'http://localhost:8089')
|
||||||
);
|
);
|
||||||
@override String subPath = "/v1/workspace/";
|
@override String subPath = "/oc/workspace/";
|
||||||
|
|
||||||
@override Future<APIResponse<Workspace>> all(BuildContext? context) {
|
|
||||||
return service.get("$subPath/list", true, context);
|
|
||||||
}
|
|
||||||
@override Future<APIResponse<Workspace>> get(BuildContext? context, String id) { throw UnimplementedError(); }
|
|
||||||
@override Future<APIResponse<Workspace>> post(BuildContext? context, Map<String, dynamic> body, Map<String, String> params) {
|
|
||||||
String path = "?";
|
|
||||||
for (var key in params.keys) { path += "$key=${params[key]}&"; }
|
|
||||||
return service.post("$subPath$path", body, context);
|
|
||||||
}
|
|
||||||
@override Future<APIResponse<Workspace>> put(BuildContext? context, String id, Map<String, dynamic> body, Map<String, String> params) {
|
|
||||||
throw UnimplementedError();
|
|
||||||
}
|
|
||||||
@override Future<APIResponse<Workspace>> delete(BuildContext? context, Map<String, String> params) {
|
|
||||||
String path = "?";
|
|
||||||
for (var key in params.keys) { path += "$key=${params[key]}&"; }
|
|
||||||
return service.delete("$subPath$path", context);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -50,7 +50,7 @@ class _MainPageState extends State<MainPage> {
|
|||||||
// The Flutter framework has been optimized to make rerunning build methods
|
// The Flutter framework has been optimized to make rerunning build methods
|
||||||
// fast, so that you can just rebuild anything that needs updating rather
|
// fast, so that you can just rebuild anything that needs updating rather
|
||||||
// than having to individually change instances of widgets.
|
// than having to individually change instances of widgets.
|
||||||
WorkspaceLocal.init(context);
|
WorkspaceLocal.init(context, false);
|
||||||
scaffoldKey = GlobalKey<ScaffoldState>();
|
scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
key: scaffoldKey,
|
key: scaffoldKey,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:developer' as developer;
|
|
||||||
|
|
||||||
abstract class SerializerDeserializer<T> {
|
abstract class SerializerDeserializer<T> {
|
||||||
T deserialize(dynamic json);
|
T deserialize(dynamic json);
|
||||||
|
116
lib/models/logs.dart
Normal file
116
lib/models/logs.dart
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import 'package:oc_front/models/abstract.dart';
|
||||||
|
import 'package:json_string/json_string.dart';
|
||||||
|
|
||||||
|
class LogResults extends SerializerDeserializer<LogResults> {
|
||||||
|
String? status;
|
||||||
|
LogsResult? data;
|
||||||
|
|
||||||
|
LogResults({
|
||||||
|
this.status,
|
||||||
|
this.data,
|
||||||
|
});
|
||||||
|
|
||||||
|
String getID() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override deserialize(dynamic json) {
|
||||||
|
try { json = json as Map<String, dynamic>;
|
||||||
|
} catch (e) { return LogResults(); }
|
||||||
|
return LogResults(
|
||||||
|
status: json.containsKey("status") ? json["status"] : "",
|
||||||
|
data: json.containsKey("data") ? LogsResult().deserialize(json["data"]) : null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override Map<String, dynamic> serialize() {
|
||||||
|
return { };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LogsResult extends SerializerDeserializer<LogsResult> {
|
||||||
|
List<Logs> result;
|
||||||
|
LogsResult({
|
||||||
|
this.result = const [],
|
||||||
|
});
|
||||||
|
|
||||||
|
String getID() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override deserialize(dynamic json) {
|
||||||
|
try { json = json as Map<String, dynamic>;
|
||||||
|
} catch (e) { return LogsResult(); }
|
||||||
|
return LogsResult(
|
||||||
|
result: json.containsKey("result") ? fromListJson(json["result"], Logs()) : [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override Map<String, dynamic> serialize() {
|
||||||
|
return { };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Logs extends SerializerDeserializer<Logs> {
|
||||||
|
String? level;
|
||||||
|
List<Log> logs = [];
|
||||||
|
Logs({
|
||||||
|
this.level,
|
||||||
|
});
|
||||||
|
|
||||||
|
String getID() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override deserialize(dynamic json) {
|
||||||
|
try { json = json as Map<String, dynamic>;
|
||||||
|
} catch (e) { return Logs(); }
|
||||||
|
return Logs(
|
||||||
|
level: json.containsKey("stream") && (json["stream"] as Map<String, dynamic>).containsKey("level") ? json["stream"]["level"] : "",
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override Map<String, dynamic> serialize() {
|
||||||
|
return { };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Log extends SerializerDeserializer<Log> {
|
||||||
|
DateTime? timestamp;
|
||||||
|
String? message;
|
||||||
|
|
||||||
|
String? level;
|
||||||
|
Map<String, dynamic> map = {};
|
||||||
|
Log({
|
||||||
|
this.timestamp,
|
||||||
|
this.message,
|
||||||
|
this.level
|
||||||
|
});
|
||||||
|
|
||||||
|
String getID() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
String getMessage(String mess) {
|
||||||
|
var jsonString = mess;
|
||||||
|
try {
|
||||||
|
var j = JsonString(mess.replaceAll("\\", "")).decodedValue as Map<String, dynamic>;
|
||||||
|
map = j;
|
||||||
|
if (j["Status"] == "Pending") {
|
||||||
|
jsonString = "${j["Name"]} : [${j["Namespace"]}] Status: ${j["Status"]}... \nCreated at ${j["Created"].toString().replaceAllMapped(RegExp(r'\(\w+\)'), (match) { return ''; }).replaceAllMapped(RegExp(r'\+\w+'), (match) { return ''; })}";
|
||||||
|
} else {
|
||||||
|
jsonString = "${j["Name"]} : [${j["Namespace"]}] ${j["Status"]} ${j["Progress"]} (${j["Duration"].toString().replaceAll("seconds", "s")})\nStarted at ${j["Created"].toString().replaceAllMapped(RegExp(r'\(\w+\)'), (match) { return ''; }).replaceAllMapped(RegExp(r'\+\w+'), (match) { return ''; })}";
|
||||||
|
}
|
||||||
|
} on JsonFormatException catch (e) { /* */ }
|
||||||
|
message = jsonString;
|
||||||
|
return jsonString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override deserialize(dynamic json) {
|
||||||
|
try { json = json as List<dynamic>;
|
||||||
|
} catch (e) { return Log(); }
|
||||||
|
return Log(
|
||||||
|
timestamp: json.isNotEmpty ? DateTime.parse(json[0]) : null,
|
||||||
|
message: json.length > 1 ? getMessage(json[1].toString()) : null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override Map<String, dynamic> serialize() { return { }; }
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
import 'package:oc_front/models/abstract.dart';
|
import 'package:oc_front/models/abstract.dart';
|
||||||
|
import 'package:oc_front/models/logs.dart';
|
||||||
import 'package:oc_front/models/search.dart';
|
import 'package:oc_front/models/search.dart';
|
||||||
|
import 'package:oc_front/models/workflow.dart';
|
||||||
import 'package:oc_front/models/workspace.dart';
|
import 'package:oc_front/models/workspace.dart';
|
||||||
|
|
||||||
Map<Type, SerializerDeserializer> refs = <Type, SerializerDeserializer> {
|
Map<Type, SerializerDeserializer> refs = <Type, SerializerDeserializer> {
|
||||||
@ -9,15 +11,21 @@ Map<Type, SerializerDeserializer> refs = <Type, SerializerDeserializer> {
|
|||||||
DataItem: DataItem(),
|
DataItem: DataItem(),
|
||||||
DataCenterItem: DataCenterItem(),
|
DataCenterItem: DataCenterItem(),
|
||||||
StorageItem: StorageItem(),
|
StorageItem: StorageItem(),
|
||||||
ComputingItem: ComputingItem(),
|
ProcessingItem: ProcessingItem(),
|
||||||
|
Workflow: Workflow(),
|
||||||
|
Resource: Resource(),
|
||||||
|
WorkflowExecutions: WorkflowExecutions(),
|
||||||
|
LogResults: LogResults(),
|
||||||
};
|
};
|
||||||
|
|
||||||
class APIResponse<T extends SerializerDeserializer> {
|
class APIResponse<T extends SerializerDeserializer> {
|
||||||
APIResponse({
|
APIResponse({
|
||||||
this.data,
|
this.data,
|
||||||
|
this.code = 200,
|
||||||
this.error = "",
|
this.error = "",
|
||||||
this.offset = 0,
|
this.offset = 0,
|
||||||
});
|
});
|
||||||
|
int code = 200;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
T? data ;
|
T? data ;
|
||||||
String? error = "";
|
String? error = "";
|
||||||
@ -28,18 +36,22 @@ class APIResponse<T extends SerializerDeserializer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
APIResponse<T> deserialize(dynamic j) {
|
APIResponse<T> deserialize(dynamic j) {
|
||||||
|
dynamic data;
|
||||||
|
try { data = j["data"];
|
||||||
|
} catch (e) { data = j; }
|
||||||
try {
|
try {
|
||||||
return APIResponse<T>(
|
return APIResponse<T>(
|
||||||
data: refs[T]!.deserialize(j),
|
data: refs[T]!.deserialize(data),
|
||||||
|
code: j.containsKey("code") && j["code"] != null ? j["code"] : 200,
|
||||||
error: j.containsKey("error") && j["error"] != null ? j["error"] : "",
|
error: j.containsKey("error") && j["error"] != null ? j["error"] : "",
|
||||||
);
|
);
|
||||||
} catch (e) { return APIResponse<T>( data: refs[T]!.deserialize(j), ); }
|
} catch (e) { return APIResponse<T>( data: refs[T]!.deserialize(data), ); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class RawData extends SerializerDeserializer<RawData> {
|
class RawData extends SerializerDeserializer<RawData> {
|
||||||
RawData({ this.values = const []});
|
RawData({ this.values = const []});
|
||||||
dynamic values;
|
List<dynamic> values = [];
|
||||||
@override deserialize(dynamic json) { return RawData(values: json); }
|
@override deserialize(dynamic json) { return RawData(values: json ?? []); }
|
||||||
@override Map<String, dynamic> serialize() => { };
|
@override Map<String, dynamic> serialize() => { };
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
|
||||||
import 'package:oc_front/models/abstract.dart';
|
import 'package:oc_front/models/abstract.dart';
|
||||||
|
|
||||||
const List<ComputingItem> _emptyComputing = [];
|
const List<ProcessingItem> _emptyComputing = [];
|
||||||
const List<DataItem> _emptyData = [];
|
const List<DataItem> _emptyData = [];
|
||||||
const List<DataCenterItem> _emptyDataCenter = [];
|
const List<DataCenterItem> _emptyDataCenter = [];
|
||||||
const List<StorageItem> _emptyStorage = [];
|
const List<StorageItem> _emptyStorage = [];
|
||||||
@ -11,248 +12,539 @@ class Search extends SerializerDeserializer<Search> {
|
|||||||
this.data = _emptyData,
|
this.data = _emptyData,
|
||||||
this.storage = _emptyStorage,
|
this.storage = _emptyStorage,
|
||||||
});
|
});
|
||||||
List<ComputingItem> computing;
|
List<ProcessingItem> computing;
|
||||||
List<DataCenterItem> datacenter;
|
List<DataCenterItem> datacenter;
|
||||||
List<DataItem> data;
|
List<DataItem> data;
|
||||||
List<StorageItem> storage;
|
List<StorageItem> storage;
|
||||||
@override deserialize(dynamic json) {
|
@override deserialize(dynamic json) {
|
||||||
json = json as Map<String, dynamic>;
|
json = json as Map<String, dynamic>;
|
||||||
return Search(
|
return Search(
|
||||||
computing: json.containsKey("computing") ? fromListJson(json["computing"], ComputingItem()) : [],
|
computing: json.containsKey("processing") ? fromListJson(json["processing"], ProcessingItem()) : [],
|
||||||
datacenter: json.containsKey("datacenter") ? fromListJson(json["datacenter"], DataCenterItem()) : [],
|
datacenter: json.containsKey("datacenter") ? fromListJson(json["datacenter"], DataCenterItem()) : [],
|
||||||
data: json.containsKey("data") ? fromListJson(json["data"], DataItem()) : [],
|
data: json.containsKey("data") ? fromListJson(json["data"], DataItem()) : [],
|
||||||
storage: json.containsKey("storage") ? fromListJson(json["storage"], StorageItem()) : [],
|
storage: json.containsKey("storage") ? fromListJson(json["storage"], StorageItem()) : [],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@override Map<String, dynamic> serialize() => {};
|
@override Map<String, dynamic> serialize() => {
|
||||||
|
"processing": toListJson<ProcessingItem>(computing),
|
||||||
|
"datacenter": toListJson<DataCenterItem>(datacenter),
|
||||||
|
"data": toListJson<DataItem>(data),
|
||||||
|
"storage": toListJson<StorageItem>(storage),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
const List<String> _empty = [];
|
const List<String> _empty = [];
|
||||||
abstract class AbstractItem {
|
|
||||||
|
class Resource implements SerializerDeserializer<Resource> {
|
||||||
|
List<DataItem> datas = [];
|
||||||
|
List<ProcessingItem> processings = [];
|
||||||
|
List<StorageItem> storages = [];
|
||||||
|
List<DataCenterItem> datacenters = [];
|
||||||
|
List<WorkflowItem> workflows = [];
|
||||||
|
|
||||||
|
Resource({
|
||||||
|
this.datas = const [],
|
||||||
|
this.processings = const [],
|
||||||
|
this.storages = const [],
|
||||||
|
this.datacenters = const [],
|
||||||
|
this.workflows = const [],
|
||||||
|
});
|
||||||
|
|
||||||
|
@override Resource deserialize(json) {
|
||||||
|
try { json = json as Map<String, dynamic>;
|
||||||
|
} catch (e) { return Resource(); }
|
||||||
|
return Resource(
|
||||||
|
datacenters: json.containsKey("datacenter_resource") ? fromListJson(json["datacenter_resource"], DataCenterItem()) : [],
|
||||||
|
datas: json.containsKey("data_resource") ? fromListJson(json["data_resource"], DataItem()) : [],
|
||||||
|
processings: json.containsKey("processing_resource") ? fromListJson(json["processing_resource"], ProcessingItem()) : [],
|
||||||
|
storages: json.containsKey("storage_resource") ? fromListJson(json["storage_resource"], StorageItem()) : [],
|
||||||
|
workflows: json.containsKey("workflow_resource") ? fromListJson(json["workflow_resource"], WorkflowItem()) : [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override Map<String, dynamic> serialize() {
|
||||||
|
return {
|
||||||
|
"datacenter_resource": toListJson<DataCenterItem>(datacenters),
|
||||||
|
"data_resource": toListJson<DataItem>(datas),
|
||||||
|
"processing_resource": toListJson<ProcessingItem>(processings),
|
||||||
|
"storage_resource": toListJson<StorageItem>(storages),
|
||||||
|
"workflow_resource": toListJson<WorkflowItem>(workflows),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AbstractItem<T extends FlowData> extends FlowData implements SerializerDeserializer<T> {
|
||||||
String? id;
|
String? id;
|
||||||
String? name;
|
String? name;
|
||||||
String? logo;
|
String? logo;
|
||||||
String? type;
|
|
||||||
String? owner;
|
String? owner;
|
||||||
|
String? ownerLogo;
|
||||||
|
String? source;
|
||||||
String? description;
|
String? description;
|
||||||
String? shortDescription;
|
String? shortDescription;
|
||||||
|
double? price;
|
||||||
|
String? licence;
|
||||||
|
List<dynamic> inputs = [];
|
||||||
|
List<dynamic> outputs = [];
|
||||||
|
ResourceModel? model;
|
||||||
String topic = "";
|
String topic = "";
|
||||||
|
|
||||||
|
AbstractItem({
|
||||||
|
this.id,
|
||||||
|
this.name,
|
||||||
|
this.logo,
|
||||||
|
this.owner,
|
||||||
|
this.ownerLogo,
|
||||||
|
this.price,
|
||||||
|
this.source,
|
||||||
|
this.licence,
|
||||||
|
this.description,
|
||||||
|
this.model,
|
||||||
|
this.shortDescription,
|
||||||
|
this.inputs = const [],
|
||||||
|
this.outputs = const [],
|
||||||
|
});
|
||||||
|
|
||||||
|
@override String getID() {
|
||||||
|
return id ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override String getName() {
|
||||||
|
return name ?? "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Model extends SerializerDeserializer<Model> {
|
||||||
|
dynamic value;
|
||||||
|
String? type;
|
||||||
|
bool readonly = false;
|
||||||
|
|
||||||
|
Model({
|
||||||
|
this.value,
|
||||||
|
this.type,
|
||||||
|
this.readonly = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override deserialize(dynamic json) {
|
||||||
|
try { json = json as Map<String, dynamic>;
|
||||||
|
} catch (e) { return Model(); }
|
||||||
|
return Model(
|
||||||
|
value: json.containsKey("value") ? json["value"] : null,
|
||||||
|
type: json.containsKey("type") ? json["type"] : null,
|
||||||
|
readonly: json.containsKey("readonly") ? json["readonly"] : false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override Map<String, dynamic> serialize() => {
|
||||||
|
"value": value,
|
||||||
|
"type": type,
|
||||||
|
"readonly": readonly,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class ResourceModel extends SerializerDeserializer<ResourceModel> {
|
||||||
|
String? id;
|
||||||
|
String? type;
|
||||||
|
Map<String, Model>? model;
|
||||||
|
|
||||||
|
ResourceModel({
|
||||||
|
this.id,
|
||||||
|
this.type,
|
||||||
|
this.model,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override deserialize(dynamic json) {
|
||||||
|
try { json = json as Map<String, dynamic>;
|
||||||
|
} catch (e) { return ResourceModel(); }
|
||||||
|
return ResourceModel(
|
||||||
|
id: json.containsKey("id") ? json["id"] : null,
|
||||||
|
type: json.containsKey("type") ? json["type"] : null,
|
||||||
|
model: json.containsKey("model") ? fromMapJson(json["model"], Model()) : {},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override Map<String, dynamic> serialize() => {
|
||||||
|
"id": id,
|
||||||
|
"type": type,
|
||||||
|
"model": toMapJson<Model>(model ?? {}),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Type? getTopicType(String topic) {
|
Type? getTopicType(String topic) {
|
||||||
if (topic == "computing") { return ComputingItem; }
|
if (topic == "processing") { return ProcessingItem; }
|
||||||
else if (topic == "data") { return DataItem; }
|
else if (topic == "data") { return DataItem; }
|
||||||
else if (topic == "datacenter") { return DataCenterItem; }
|
else if (topic == "datacenter") { return DataCenterItem; }
|
||||||
else if (topic == "storage") { return StorageItem; }
|
else if (topic == "storage") { return StorageItem; }
|
||||||
|
else if (topic == "workflow") { return WorkflowItem; }
|
||||||
else { return null; }
|
else { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
String getTopic(Type type) {
|
String getTopic(Type type) {
|
||||||
if (type == ComputingItem) { return "computing"; }
|
if (type == AbstractItem) { return "resource"; }
|
||||||
|
if (type == ProcessingItem) { return "processing"; }
|
||||||
if (type == DataItem) { return "data"; }
|
if (type == DataItem) { return "data"; }
|
||||||
if (type == DataCenterItem) { return "datacenter"; }
|
if (type == DataCenterItem) { return "datacenter"; }
|
||||||
if (type == StorageItem) { return "storage"; }
|
if (type == StorageItem) { return "storage"; }
|
||||||
|
if (type == WorkflowItem) { return "workflow"; }
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isComputing(String topic) => topic == "computing";
|
bool isComputing(String topic) => topic == "processing";
|
||||||
bool isData(String topic) => topic == "data";
|
bool isData(String topic) => topic == "data";
|
||||||
bool isDataCenter(String topic) => topic == "datacenter";
|
bool isDataCenter(String topic) => topic == "datacenter";
|
||||||
bool isStorage(String topic) => topic == "storage";
|
bool isStorage(String topic) => topic == "storage";
|
||||||
|
bool isWorkflow(String topic) => topic == "workflow";
|
||||||
|
|
||||||
class ComputingItem extends SerializerDeserializer<ComputingItem> implements AbstractItem {
|
class ProcessingItem extends SerializerDeserializer<ProcessingItem> implements AbstractItem<ProcessingItem> {
|
||||||
ComputingItem({
|
ProcessingItem({
|
||||||
this.id,
|
this.id,
|
||||||
this.name,
|
this.name,
|
||||||
this.logo,
|
this.logo,
|
||||||
this.type,
|
|
||||||
this.owner,
|
this.owner,
|
||||||
|
this.ownerLogo,
|
||||||
this.price,
|
this.price,
|
||||||
this.image,
|
this.source,
|
||||||
this.command,
|
|
||||||
this.licence,
|
this.licence,
|
||||||
this.description,
|
this.description,
|
||||||
this.requirements,
|
|
||||||
this.ports = _empty,
|
|
||||||
this.shortDescription,
|
this.shortDescription,
|
||||||
this.dinputs = _empty,
|
this.inputs = _empty,
|
||||||
this.doutputs = _empty,
|
this.outputs = _empty,
|
||||||
this.arguments = _empty,
|
|
||||||
this.environment = _empty,
|
this.cpus = const [],
|
||||||
|
this.gpus = const [],
|
||||||
|
this.ram,
|
||||||
|
this.storage,
|
||||||
|
this.parrallel = false,
|
||||||
|
this.scallingModel,
|
||||||
|
this.diskIO,
|
||||||
|
|
||||||
|
this.model,
|
||||||
});
|
});
|
||||||
|
@override ResourceModel? model;
|
||||||
@override String? id;
|
@override String? id;
|
||||||
@override String? name;
|
@override String? name;
|
||||||
@override String? logo;
|
@override String? logo;
|
||||||
@override String? type;
|
@override String? source;
|
||||||
|
@override String? ownerLogo;
|
||||||
@override String? owner;
|
@override String? owner;
|
||||||
@override String topic = "computing";
|
@override String topic = "processing";
|
||||||
double? price;
|
@override double? price;
|
||||||
String? image;
|
@override String? licence;
|
||||||
String? command;
|
@override List<dynamic> inputs;
|
||||||
String? licence;
|
@override List<dynamic> outputs;
|
||||||
List<dynamic> ports;
|
|
||||||
List<dynamic> dinputs;
|
|
||||||
List<dynamic> doutputs;
|
|
||||||
List<dynamic> arguments;
|
|
||||||
@override String? description;
|
@override String? description;
|
||||||
@override String? shortDescription;
|
@override String? shortDescription;
|
||||||
List<dynamic> environment;
|
|
||||||
ExecRequirements? requirements;
|
|
||||||
|
|
||||||
|
// Special Attributes
|
||||||
|
List<CPU> cpus = [];
|
||||||
|
List<GPU> gpus = [];
|
||||||
|
RAM? ram;
|
||||||
|
int? storage;
|
||||||
|
bool parrallel = false;
|
||||||
|
int? scallingModel;
|
||||||
|
String? diskIO;
|
||||||
|
|
||||||
|
@override String getID() {
|
||||||
|
return id ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override String getName() {
|
||||||
|
return name ?? "";
|
||||||
|
}
|
||||||
@override deserialize(dynamic json) {
|
@override deserialize(dynamic json) {
|
||||||
try { json = json as Map<String, dynamic>;
|
try { json = json as Map<String, dynamic>;
|
||||||
} catch (e) { return ComputingItem(); }
|
} catch (e) { return ProcessingItem(); }
|
||||||
return ComputingItem(
|
return ProcessingItem(
|
||||||
id: json.containsKey("ID") ? json["ID"] : null,
|
id: json.containsKey("id") ? json["id"] : null,
|
||||||
name: json.containsKey("name") ? json["name"] : null,
|
name: json.containsKey("name") ? json["name"] : null,
|
||||||
logo: json.containsKey("logo") ? json["logo"] : null,
|
logo: json.containsKey("logo") ? json["logo"] : null,
|
||||||
type: json.containsKey("type") ? json["type"] : null,
|
|
||||||
owner: json.containsKey("owner") ? json["owner"] : null,
|
owner: json.containsKey("owner") ? json["owner"] : null,
|
||||||
|
ownerLogo: json.containsKey("owner_logo") ? json["owner_logo"] : null,
|
||||||
price: json.containsKey("price") ? json["price"]?.toDouble() : null,
|
price: json.containsKey("price") ? json["price"]?.toDouble() : null,
|
||||||
image: json.containsKey("image") ? json["image"] : null,
|
|
||||||
command: json.containsKey("command") ? json["command"] : null,
|
|
||||||
licence: json.containsKey("licence") ? json["licence"] : null,
|
licence: json.containsKey("licence") ? json["licence"] : null,
|
||||||
description: json.containsKey("description") ? json["description"] : null,
|
description: json.containsKey("description") ? json["description"] : null,
|
||||||
ports: json["ports"] ?? [],
|
|
||||||
shortDescription: json.containsKey("short_description") ? json["short_description"] : null,
|
shortDescription: json.containsKey("short_description") ? json["short_description"] : null,
|
||||||
dinputs: json["dinputs"] ?? [],
|
inputs: json["inputs"] ?? [],
|
||||||
doutputs: json["doutputs"] ?? [],
|
outputs: json["outputs"] ?? [],
|
||||||
arguments: json["arguments"] ?? [],
|
source: json.containsKey("source") ? json["source"] : null,
|
||||||
environment: json["environment"] ?? [],
|
|
||||||
requirements: json.containsKey("requirements") ? ExecRequirements().deserialize(json["execution_requirements"]) : null,
|
model: json.containsKey("resource_model") ? ResourceModel().deserialize(json["resource_model"]) : null,
|
||||||
|
cpus: json.containsKey("cpus") ? fromListJson(json["cpus"], CPU()) : [],
|
||||||
|
gpus: json.containsKey("gpus") ? fromListJson(json["gpus"], GPU()) : [],
|
||||||
|
ram: json.containsKey("ram") ? RAM().deserialize(json["ram"]) : null,
|
||||||
|
storage: json.containsKey("storage") ? json["storage"] : null,
|
||||||
|
parrallel: json.containsKey("parrallel") ? json["parrallel"] : false,
|
||||||
|
scallingModel: json.containsKey("scalling_model") ? json["scalling_model"] : null,
|
||||||
|
diskIO: json.containsKey("disk_io") ? json["disk_io"] : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@override Map<String, dynamic> serialize() => {};
|
@override Map<String, dynamic> serialize() => {
|
||||||
|
"id": id,
|
||||||
|
"name": name,
|
||||||
|
"logo": logo,
|
||||||
|
"owner": owner,
|
||||||
|
"owner_logo": ownerLogo,
|
||||||
|
"price": price,
|
||||||
|
"licence": licence,
|
||||||
|
"description": description,
|
||||||
|
"short_description": shortDescription,
|
||||||
|
"inputs": inputs,
|
||||||
|
"outputs": outputs,
|
||||||
|
"source": source,
|
||||||
|
"resource_model": model?.serialize(),
|
||||||
|
"cpus": toListJson<CPU>(cpus),
|
||||||
|
"gpus": toListJson<GPU>(gpus),
|
||||||
|
"ram": ram?.serialize(),
|
||||||
|
"storage": storage,
|
||||||
|
"parrallel": parrallel,
|
||||||
|
"scalling_model": scallingModel,
|
||||||
|
"disk_io": diskIO,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExecRequirements extends SerializerDeserializer<ExecRequirements> {
|
class WorkflowItem extends SerializerDeserializer<WorkflowItem> implements AbstractItem<WorkflowItem> {
|
||||||
ExecRequirements({
|
WorkflowItem({
|
||||||
this.ram,
|
this.id,
|
||||||
this.cpus,
|
this.name,
|
||||||
this.gpus,
|
this.logo,
|
||||||
this.diskIO,
|
this.owner,
|
||||||
this.scallingModel,
|
this.ownerLogo,
|
||||||
this.parallel = false,
|
this.price,
|
||||||
|
this.source,
|
||||||
|
this.licence,
|
||||||
|
this.description,
|
||||||
|
this.shortDescription,
|
||||||
|
this.inputs = _empty,
|
||||||
|
this.outputs = _empty,
|
||||||
|
this.model,
|
||||||
|
this.workflowID,
|
||||||
});
|
});
|
||||||
double? ram;
|
@override ResourceModel? model;
|
||||||
double? cpus;
|
@override String? id;
|
||||||
double? gpus;
|
@override String? name;
|
||||||
String? diskIO;
|
@override String? logo;
|
||||||
bool parallel = false;
|
@override String? source;
|
||||||
double? scallingModel;
|
@override String? ownerLogo;
|
||||||
|
@override String? owner;
|
||||||
|
@override String topic = "workflow";
|
||||||
|
@override double? price;
|
||||||
|
@override String? licence;
|
||||||
|
@override List<dynamic> inputs;
|
||||||
|
@override List<dynamic> outputs;
|
||||||
|
@override String? description;
|
||||||
|
@override String? shortDescription;
|
||||||
|
|
||||||
|
String? workflowID;
|
||||||
|
@override String getID() {
|
||||||
|
return id ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override String getName() {
|
||||||
|
return name ?? "";
|
||||||
|
}
|
||||||
@override deserialize(dynamic json) {
|
@override deserialize(dynamic json) {
|
||||||
try { json = json as Map<String, dynamic>;
|
try { json = json as Map<String, dynamic>;
|
||||||
} catch (e) { return ExecRequirements(); }
|
} catch (e) { return WorkflowItem(); }
|
||||||
return ExecRequirements(
|
return WorkflowItem(
|
||||||
ram: json.containsKey("ram") ? json["ram"]?.toDouble() : null,
|
id: json.containsKey("id") ? json["id"] : null,
|
||||||
cpus: json.containsKey("cpus") ? json["cpus"]?.toDouble() : null,
|
name: json.containsKey("name") ? json["name"] : null,
|
||||||
gpus: json.containsKey("gpus") ? json["gpus"]?.toDouble() : null,
|
logo: json.containsKey("logo") ? json["logo"] : null,
|
||||||
diskIO: json.containsKey("disk_io") ? json["disk_io"] : null,
|
owner: json.containsKey("owner") ? json["owner"] : null,
|
||||||
scallingModel: json.containsKey("scaling_model") ? json["scaling_model"]?.toDouble() : null,
|
ownerLogo: json.containsKey("owner_logo") ? json["owner_logo"] : null,
|
||||||
parallel: json.containsKey("parallel") ? json["parallel"] : false,
|
price: json.containsKey("price") ? json["price"]?.toDouble() : null,
|
||||||
|
licence: json.containsKey("licence") ? json["licence"] : null,
|
||||||
|
description: json.containsKey("description") ? json["description"] : null,
|
||||||
|
shortDescription: json.containsKey("short_description") ? json["short_description"] : null,
|
||||||
|
inputs: json["inputs"] ?? [],
|
||||||
|
outputs: json["outputs"] ?? [],
|
||||||
|
source: json.containsKey("source") ? json["source"] : null,
|
||||||
|
model: json.containsKey("resource_model") ? ResourceModel().deserialize(json["resource_model"]) : null,
|
||||||
|
workflowID: json.containsKey("workflow_id") ? json["workflow_id"] : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@override Map<String, dynamic> serialize() => {};
|
@override Map<String, dynamic> serialize() => {
|
||||||
|
"id": id,
|
||||||
|
"name": name,
|
||||||
|
"logo": logo,
|
||||||
|
"owner": owner,
|
||||||
|
"owner_logo": ownerLogo,
|
||||||
|
"price": price,
|
||||||
|
"licence": licence,
|
||||||
|
"description": description,
|
||||||
|
"short_description": shortDescription,
|
||||||
|
"inputs": inputs,
|
||||||
|
"outputs": outputs,
|
||||||
|
"source": source,
|
||||||
|
"resource_model": model?.serialize(),
|
||||||
|
"workflow_id": workflowID,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class DataItem extends SerializerDeserializer<DataItem> implements AbstractItem {
|
class DataItem extends SerializerDeserializer<DataItem> implements AbstractItem<DataItem> {
|
||||||
DataItem({
|
DataItem({
|
||||||
this.id,
|
this.id,
|
||||||
this.name,
|
this.name,
|
||||||
this.logo,
|
this.logo,
|
||||||
this.type,
|
|
||||||
this.dtype,
|
|
||||||
this.owner,
|
this.owner,
|
||||||
this.example,
|
this.ownerLogo,
|
||||||
this.location,
|
this.price,
|
||||||
|
this.source,
|
||||||
|
this.licence,
|
||||||
this.description,
|
this.description,
|
||||||
this.protocol = _empty,
|
|
||||||
this.shortDescription,
|
this.shortDescription,
|
||||||
|
this.inputs = _empty,
|
||||||
|
this.outputs = _empty,
|
||||||
|
this.model,
|
||||||
|
this.protocols = const [],
|
||||||
|
this.dataType,
|
||||||
|
this.exemple,
|
||||||
});
|
});
|
||||||
@override String? id;
|
@override String? id;
|
||||||
@override String? name;
|
@override String? name;
|
||||||
@override String? logo;
|
@override String? logo;
|
||||||
@override String? type;
|
@override String? source;
|
||||||
@override String topic = "data";
|
@override String? ownerLogo;
|
||||||
String? dtype;
|
|
||||||
String? example;
|
|
||||||
String? location;
|
|
||||||
@override String? description;
|
|
||||||
List<dynamic> protocol;
|
|
||||||
@override String? shortDescription;
|
|
||||||
@override String? owner;
|
@override String? owner;
|
||||||
|
@override String topic = "data";
|
||||||
|
@override double? price;
|
||||||
|
@override String? licence;
|
||||||
|
@override List<dynamic> inputs;
|
||||||
|
@override List<dynamic> outputs;
|
||||||
|
@override String? description;
|
||||||
|
@override String? shortDescription;
|
||||||
|
@override ResourceModel? model;
|
||||||
|
// Special Attributes
|
||||||
|
List<String> protocols = [];
|
||||||
|
String? dataType;
|
||||||
|
String? exemple;
|
||||||
|
@override String getName() {
|
||||||
|
return name ?? "";
|
||||||
|
}
|
||||||
|
@override String getID() {
|
||||||
|
return id ?? "";
|
||||||
|
}
|
||||||
@override deserialize(dynamic json) {
|
@override deserialize(dynamic json) {
|
||||||
try { json = json as Map<String, dynamic>;
|
try { json = json as Map<String, dynamic>;
|
||||||
} catch (e) { return DataItem(); }
|
} catch (e) { return DataItem(); }
|
||||||
return DataItem(
|
return DataItem(
|
||||||
id: json.containsKey("ID") ? json["ID"] : null,
|
id: json.containsKey("id") ? json["id"] : null,
|
||||||
name: json.containsKey("name") ? json["name"] : null,
|
name: json.containsKey("name") ? json["name"] : null,
|
||||||
logo: json.containsKey("logo") ? json["logo"] : null,
|
logo: json.containsKey("logo") ? json["logo"] : null,
|
||||||
type: json.containsKey("type") ? json["type"] : null,
|
|
||||||
owner: json.containsKey("owner") ? json["owner"] : null,
|
owner: json.containsKey("owner") ? json["owner"] : null,
|
||||||
dtype: json.containsKey("dtype") ? json["dtype"] : null,
|
ownerLogo: json.containsKey("owner_logo") ? json["owner_logo"] : null,
|
||||||
example: json.containsKey("example") ? json["example"] : null,
|
price: json.containsKey("price") ? json["price"]?.toDouble() : null,
|
||||||
location: json.containsKey("location") ? json["location"] : null,
|
licence: json.containsKey("licence") ? json["licence"] : null,
|
||||||
description: json.containsKey("description") ? json["description"] : null,
|
description: json.containsKey("description") ? json["description"] : null,
|
||||||
protocol: json["protocol"] ?? [],
|
shortDescription: json.containsKey("short_description") ? json["short_description"] : null,
|
||||||
shortDescription: json.containsKey("short_description") ? json["short_description"] : null
|
inputs: json["inputs"] ?? [],
|
||||||
|
outputs: json["outputs"] ?? [],
|
||||||
|
source: json.containsKey("source") ? json["source"] : null,
|
||||||
|
model: json.containsKey("resource_model") ? ResourceModel().deserialize(json["resource_model"]) : null,
|
||||||
|
protocols: json.containsKey("protocols") ? json["protocols"] : [],
|
||||||
|
dataType: json.containsKey("data_type") ? json["data_type"] : null,
|
||||||
|
exemple: json.containsKey("exemple") ? json["exemple"] : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@override Map<String, dynamic> serialize() => {};
|
@override Map<String, dynamic> serialize() => {
|
||||||
|
"id": id,
|
||||||
|
"name": name,
|
||||||
|
"logo": logo,
|
||||||
|
"owner": owner,
|
||||||
|
"owner_logo": ownerLogo,
|
||||||
|
"price": price,
|
||||||
|
"licence": licence,
|
||||||
|
"description": description,
|
||||||
|
"short_description": shortDescription,
|
||||||
|
"inputs": inputs,
|
||||||
|
"outputs": outputs,
|
||||||
|
"source": source,
|
||||||
|
"resource_model": model?.serialize(),
|
||||||
|
"protocols": protocols,
|
||||||
|
"data_type": dataType,
|
||||||
|
"exemple": exemple,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
const List<GPU> _emptyGPU = [];
|
|
||||||
class DataCenterItem extends SerializerDeserializer<DataCenterItem> implements AbstractItem {
|
class DataCenterItem extends SerializerDeserializer<DataCenterItem> implements AbstractItem<DataCenterItem> {
|
||||||
DataCenterItem({
|
DataCenterItem({
|
||||||
this.id,
|
this.id,
|
||||||
this.cpu,
|
|
||||||
this.ram,
|
|
||||||
this.name,
|
this.name,
|
||||||
this.logo,
|
this.logo,
|
||||||
this.type,
|
|
||||||
this.owner,
|
this.owner,
|
||||||
this.acronym,
|
this.ownerLogo,
|
||||||
this.bookingPrice,
|
this.price,
|
||||||
|
this.source,
|
||||||
|
this.licence,
|
||||||
this.description,
|
this.description,
|
||||||
this.hosts = _empty,
|
|
||||||
this.gpus = _emptyGPU,
|
|
||||||
this.shortDescription,
|
this.shortDescription,
|
||||||
|
this.inputs = _empty,
|
||||||
|
this.outputs = _empty,
|
||||||
|
this.model,
|
||||||
|
this.cpus = const [],
|
||||||
|
this.gpus = const [],
|
||||||
|
this.ram,
|
||||||
});
|
});
|
||||||
CPU? cpu;
|
|
||||||
RAM? ram;
|
|
||||||
@override String? id;
|
@override String? id;
|
||||||
@override String? name;
|
@override String? name;
|
||||||
@override String? logo;
|
@override String? logo;
|
||||||
@override String? type;
|
@override String? source;
|
||||||
|
@override String? ownerLogo;
|
||||||
@override String? owner;
|
@override String? owner;
|
||||||
@override String topic = "datacenter";
|
@override String topic = "datacenter";
|
||||||
String? acronym;
|
@override double? price;
|
||||||
List<GPU> gpus = [];
|
@override String? licence;
|
||||||
|
@override List<dynamic> inputs;
|
||||||
|
@override List<dynamic> outputs;
|
||||||
@override String? description;
|
@override String? description;
|
||||||
List<dynamic> hosts;
|
|
||||||
double? bookingPrice;
|
|
||||||
@override String? shortDescription;
|
@override String? shortDescription;
|
||||||
|
@override ResourceModel? model;
|
||||||
|
// Special Attributes
|
||||||
|
List<CPU> cpus = [];
|
||||||
|
List<GPU> gpus = [];
|
||||||
|
RAM? ram;
|
||||||
|
@override String getID() {
|
||||||
|
return id ?? "";
|
||||||
|
}
|
||||||
|
@override String getName() {
|
||||||
|
return name ?? "";
|
||||||
|
}
|
||||||
@override deserialize(dynamic json) {
|
@override deserialize(dynamic json) {
|
||||||
try { json = json as Map<String, dynamic>;
|
try { json = json as Map<String, dynamic>;
|
||||||
} catch (e) { return DataCenterItem(); }
|
} catch (e) { return DataCenterItem(); }
|
||||||
return DataCenterItem(
|
return DataCenterItem(
|
||||||
id: json.containsKey("ID") ? json["ID"] : null,
|
id: json.containsKey("id") ? json["id"] : null,
|
||||||
ram: json.containsKey("ram") ? RAM().deserialize(json["ram"]) : null,
|
|
||||||
cpu: json.containsKey("cpu") ? CPU().deserialize(json["cpu"]) : null,
|
|
||||||
acronym: json.containsKey("acronym") ? json["acronym"] : null,
|
|
||||||
name: json.containsKey("name") ? json["name"] : null,
|
name: json.containsKey("name") ? json["name"] : null,
|
||||||
logo: json.containsKey("logo") ? json["logo"] : null,
|
logo: json.containsKey("logo") ? json["logo"] : null,
|
||||||
type: json.containsKey("type") ? json["type"] : null,
|
|
||||||
owner: json.containsKey("owner") ? json["owner"] : null,
|
owner: json.containsKey("owner") ? json["owner"] : null,
|
||||||
bookingPrice: json.containsKey("bookingPrice") ? json["bookingPrice"]?.toDouble() : null,
|
ownerLogo: json.containsKey("owner_logo") ? json["owner_logo"] : null,
|
||||||
|
price: json.containsKey("price") ? json["price"]?.toDouble() : null,
|
||||||
|
licence: json.containsKey("licence") ? json["licence"] : null,
|
||||||
description: json.containsKey("description") ? json["description"] : null,
|
description: json.containsKey("description") ? json["description"] : null,
|
||||||
hosts: json["hosts"] ?? [],
|
|
||||||
shortDescription: json.containsKey("short_description") ? json["short_description"] : null,
|
shortDescription: json.containsKey("short_description") ? json["short_description"] : null,
|
||||||
gpus: json.containsKey("gpus") ? fromListJson(json["gpus"] ?? [], GPU()) : [],
|
inputs: json["inputs"] ?? [],
|
||||||
|
outputs: json["outputs"] ?? [],
|
||||||
|
source: json.containsKey("source") ? json["source"] : null,
|
||||||
|
model: json.containsKey("resource_model") ? ResourceModel().deserialize(json["resource_model"]) : null,
|
||||||
|
cpus: json.containsKey("cpus") ? fromListJson(json["cpus"], CPU()) : [],
|
||||||
|
gpus: json.containsKey("gpus") ? fromListJson(json["gpus"], GPU()) : [],
|
||||||
|
ram: json.containsKey("ram") ? RAM().deserialize(json["ram"]) : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@override Map<String, dynamic> serialize() => {};
|
@override Map<String, dynamic> serialize() => {
|
||||||
|
"id": id,
|
||||||
|
"name": name,
|
||||||
|
"logo": logo,
|
||||||
|
"owner": owner,
|
||||||
|
"owner_logo": ownerLogo,
|
||||||
|
"price": price,
|
||||||
|
"licence": licence,
|
||||||
|
"description": description,
|
||||||
|
"short_description": shortDescription,
|
||||||
|
"inputs": inputs,
|
||||||
|
"outputs": outputs,
|
||||||
|
"source": source,
|
||||||
|
"resource_model": model?.serialize(),
|
||||||
|
"cpus": toListJson<CPU>(cpus),
|
||||||
|
"gpus": toListJson<GPU>(gpus),
|
||||||
|
"ram": ram?.serialize(),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
class CPU extends SerializerDeserializer<CPU> {
|
class CPU extends SerializerDeserializer<CPU> {
|
||||||
CPU({
|
CPU({
|
||||||
@ -279,7 +571,13 @@ class CPU extends SerializerDeserializer<CPU> {
|
|||||||
shared: json.containsKey("shared") ? json["shared"] : false,
|
shared: json.containsKey("shared") ? json["shared"] : false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@override Map<String, dynamic> serialize() => {};
|
@override Map<String, dynamic> serialize() => {
|
||||||
|
"cores": cores,
|
||||||
|
"platform": platform,
|
||||||
|
"architecture": architecture,
|
||||||
|
"minimumMemory": minimumMemory,
|
||||||
|
"shared": shared,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
class GPU extends SerializerDeserializer<GPU> {
|
class GPU extends SerializerDeserializer<GPU> {
|
||||||
GPU({
|
GPU({
|
||||||
@ -303,7 +601,12 @@ class GPU extends SerializerDeserializer<GPU> {
|
|||||||
tensorCores: json.containsKey("tensor_cores") ? json["tensor_cores"]?.toDouble() : null,
|
tensorCores: json.containsKey("tensor_cores") ? json["tensor_cores"]?.toDouble() : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@override Map<String, dynamic> serialize() => {};
|
@override Map<String, dynamic> serialize() => {
|
||||||
|
"cuda_cores": cudaCores,
|
||||||
|
"memory": memory,
|
||||||
|
"model": model,
|
||||||
|
"tensor_cores": tensorCores,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
class RAM extends SerializerDeserializer<RAM> {
|
class RAM extends SerializerDeserializer<RAM> {
|
||||||
RAM({
|
RAM({
|
||||||
@ -321,61 +624,108 @@ class RAM extends SerializerDeserializer<RAM> {
|
|||||||
size: json.containsKey("size") ? json["size"]?.toDouble() : null,
|
size: json.containsKey("size") ? json["size"]?.toDouble() : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@override Map<String, dynamic> serialize() => {};
|
@override Map<String, dynamic> serialize() => {
|
||||||
|
"ecc": ecc,
|
||||||
|
"size": size,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
class StorageItem extends SerializerDeserializer<StorageItem> implements AbstractItem {
|
class StorageItem extends SerializerDeserializer<StorageItem> implements AbstractItem<StorageItem> {
|
||||||
StorageItem({
|
StorageItem({
|
||||||
this.id,
|
this.id,
|
||||||
this.url,
|
|
||||||
this.size,
|
|
||||||
this.name,
|
this.name,
|
||||||
this.logo,
|
this.logo,
|
||||||
this.type,
|
|
||||||
this.owner,
|
this.owner,
|
||||||
this.acronym,
|
this.ownerLogo,
|
||||||
this.throughput,
|
this.price,
|
||||||
this.redundancy,
|
this.source,
|
||||||
|
this.licence,
|
||||||
this.description,
|
this.description,
|
||||||
this.bookingPrice,
|
|
||||||
this.shortDescription,
|
this.shortDescription,
|
||||||
|
this.inputs = _empty,
|
||||||
|
this.outputs = _empty,
|
||||||
|
this.acronym,
|
||||||
|
this.type,
|
||||||
|
this.size,
|
||||||
|
this.url,
|
||||||
this.encryption = false,
|
this.encryption = false,
|
||||||
|
this.redundancy,
|
||||||
|
this.throughput,
|
||||||
|
this.model,
|
||||||
});
|
});
|
||||||
@override String? id;
|
@override String? id;
|
||||||
String? url;
|
|
||||||
@override String? name;
|
@override String? name;
|
||||||
@override String? logo;
|
@override String? logo;
|
||||||
@override String? type;
|
@override String? source;
|
||||||
@override String topic = "storage";
|
@override String? ownerLogo;
|
||||||
double? size;
|
|
||||||
@override String? owner;
|
@override String? owner;
|
||||||
|
@override String topic = "storage";
|
||||||
|
@override double? price;
|
||||||
|
@override String? licence;
|
||||||
|
@override List<dynamic> inputs;
|
||||||
|
@override List<dynamic> outputs;
|
||||||
|
@override String? description;
|
||||||
|
@override String? shortDescription;
|
||||||
|
@override ResourceModel? model;
|
||||||
|
// special attributes
|
||||||
String? acronym;
|
String? acronym;
|
||||||
|
String? type;
|
||||||
|
int? size;
|
||||||
|
String? url;
|
||||||
|
bool encryption = false;
|
||||||
String? redundancy;
|
String? redundancy;
|
||||||
String? throughput;
|
String? throughput;
|
||||||
@override String? description;
|
@override String getName() {
|
||||||
double? bookingPrice;
|
return name ?? "";
|
||||||
bool encryption = false;
|
}
|
||||||
@override String? shortDescription;
|
@override String getID() {
|
||||||
|
return id ?? "";
|
||||||
|
}
|
||||||
@override deserialize(dynamic json) {
|
@override deserialize(dynamic json) {
|
||||||
try { json = json as Map<String, dynamic>;
|
try { json = json as Map<String, dynamic>;
|
||||||
} catch (e) { return StorageItem(); }
|
} catch (e) { return StorageItem(); }
|
||||||
return StorageItem(
|
return StorageItem(
|
||||||
id: json.containsKey("ID") ? json["ID"] : null,
|
id: json.containsKey("id") ? json["id"] : null,
|
||||||
url: json.containsKey("URL") ? json["URL"] : null,
|
|
||||||
size: json.containsKey("size") ? json["size"]?.toDouble() : null,
|
|
||||||
name: json.containsKey("name") ? json["name"] : null,
|
name: json.containsKey("name") ? json["name"] : null,
|
||||||
logo: json.containsKey("logo") ? json["logo"] : null,
|
logo: json.containsKey("logo") ? json["logo"] : null,
|
||||||
type: json.containsKey("type") ? json["type"] : null,
|
|
||||||
owner: json.containsKey("owner") ? json["owner"] : null,
|
owner: json.containsKey("owner") ? json["owner"] : null,
|
||||||
acronym: json.containsKey("DCacronym") ? json["DCacronym"] : null,
|
ownerLogo: json.containsKey("owner_logo") ? json["owner_logo"] : null,
|
||||||
bookingPrice: json.containsKey("bookingPrice") ? json["bookingPrice"]?.toDouble() : null,
|
price: json.containsKey("price") ? json["price"]?.toDouble() : null,
|
||||||
|
licence: json.containsKey("licence") ? json["licence"] : null,
|
||||||
description: json.containsKey("description") ? json["description"] : null,
|
description: json.containsKey("description") ? json["description"] : null,
|
||||||
throughput: json.containsKey("throughput") ? json["throughput"] : [],
|
|
||||||
shortDescription: json.containsKey("short_description") ? json["short_description"] : null,
|
shortDescription: json.containsKey("short_description") ? json["short_description"] : null,
|
||||||
redundancy: json.containsKey("redundancy") ? json["redundancy"] : [],
|
inputs: json["inputs"] ?? [],
|
||||||
|
outputs: json["outputs"] ?? [],
|
||||||
|
source: json.containsKey("source") ? json["source"] : null,
|
||||||
|
model: json.containsKey("resource_model") ? ResourceModel().deserialize(json["resource_model"]) : null,
|
||||||
|
acronym: json.containsKey("acronym") ? json["acronym"] : null,
|
||||||
|
type: json.containsKey("type") ? json["type"] : null,
|
||||||
|
size: json.containsKey("size") ? json["size"] : null,
|
||||||
|
url: json.containsKey("url") ? json["url"] : null,
|
||||||
encryption: json.containsKey("encryption") ? json["encryption"] : false,
|
encryption: json.containsKey("encryption") ? json["encryption"] : false,
|
||||||
|
redundancy: json.containsKey("redundancy") ? json["redundancy"] : null,
|
||||||
|
throughput: json.containsKey("throughput") ? json["throughput"] : null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@override Map<String, dynamic> serialize() => {};
|
@override Map<String, dynamic> serialize() => {
|
||||||
|
"id": id,
|
||||||
|
"name": name,
|
||||||
|
"logo": logo,
|
||||||
|
"owner": owner,
|
||||||
|
"owner_logo": ownerLogo,
|
||||||
|
"price": price,
|
||||||
|
"licence": licence,
|
||||||
|
"description": description,
|
||||||
|
"short_description": shortDescription,
|
||||||
|
"inputs": inputs,
|
||||||
|
"outputs": outputs,
|
||||||
|
"source": source,
|
||||||
|
"resource_model": model?.serialize(),
|
||||||
|
"acronym": acronym,
|
||||||
|
"type": type,
|
||||||
|
"size": size,
|
||||||
|
"url": url,
|
||||||
|
"encryption": encryption,
|
||||||
|
"redundancy": redundancy,
|
||||||
|
"throughput": throughput,
|
||||||
|
};
|
||||||
}
|
}
|
559
lib/models/workflow.dart
Normal file
559
lib/models/workflow.dart
Normal file
@ -0,0 +1,559 @@
|
|||||||
|
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/search.dart';
|
||||||
|
|
||||||
|
class WorkflowExecutions extends SerializerDeserializer<WorkflowExecutions> {
|
||||||
|
List<WorkflowExecution> executions = [];
|
||||||
|
String? executionData;
|
||||||
|
int? status;
|
||||||
|
String? workflowId;
|
||||||
|
|
||||||
|
WorkflowExecutions({
|
||||||
|
this.executions = const [],
|
||||||
|
});
|
||||||
|
|
||||||
|
@override deserialize(dynamic json) {
|
||||||
|
try { json = json as List<dynamic>;
|
||||||
|
} catch (e) { return WorkflowExecutions(); }
|
||||||
|
return WorkflowExecutions(
|
||||||
|
executions: fromListJson(json, WorkflowExecution()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override Map<String, dynamic> serialize() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class WorkflowExecution extends SerializerDeserializer<WorkflowExecution> {
|
||||||
|
String? id;
|
||||||
|
String? name;
|
||||||
|
String? executionData;
|
||||||
|
String? endDate;
|
||||||
|
int? status;
|
||||||
|
String? workflowId;
|
||||||
|
|
||||||
|
|
||||||
|
WorkflowExecution({
|
||||||
|
this.id,
|
||||||
|
this.executionData,
|
||||||
|
this.status,
|
||||||
|
this.workflowId,
|
||||||
|
this.name,
|
||||||
|
this.endDate,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override deserialize(dynamic json) {
|
||||||
|
try { json = json as Map<String, dynamic>;
|
||||||
|
} catch (e) { return 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"] : "",
|
||||||
|
status: json.containsKey("status") ? json["status"] : 1,
|
||||||
|
workflowId: json.containsKey("workflow_id") ? json["workflow_id"] : "",
|
||||||
|
name: json.containsKey("name") ? json["name"] : "",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override Map<String, dynamic> serialize() {
|
||||||
|
return {
|
||||||
|
"id": id,
|
||||||
|
"name": name,
|
||||||
|
"end_date": endDate,
|
||||||
|
"execution_data": executionData,
|
||||||
|
"status": status,
|
||||||
|
"workflow_id": workflowId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Workflow extends SerializerDeserializer<Workflow> {
|
||||||
|
String? id;
|
||||||
|
String? name;
|
||||||
|
List<dynamic> data;
|
||||||
|
List<dynamic> datacenter;
|
||||||
|
List<dynamic> storage;
|
||||||
|
List<dynamic> processing;
|
||||||
|
List<dynamic> workflows;
|
||||||
|
Graph? graph;
|
||||||
|
Scheduler? schedule;
|
||||||
|
|
||||||
|
Workflow({
|
||||||
|
this.id,
|
||||||
|
this.name = "",
|
||||||
|
this.data = const [],
|
||||||
|
this.datacenter = const [],
|
||||||
|
this.storage = const [],
|
||||||
|
this.processing = const [],
|
||||||
|
this.workflows = const [],
|
||||||
|
this.graph,
|
||||||
|
this.schedule,
|
||||||
|
});
|
||||||
|
|
||||||
|
String getID() {
|
||||||
|
return id ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override deserialize(dynamic json) {
|
||||||
|
try { json = json as Map<String, dynamic>;
|
||||||
|
} 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"] : [],
|
||||||
|
datacenter: json.containsKey("datacenters") ? json["datacenters"] : [],
|
||||||
|
data: json.containsKey("datas") ? json["datas"] : [],
|
||||||
|
storage: json.containsKey("storages") ? json["storages"] : [],
|
||||||
|
graph: json.containsKey("graph") ? Graph().deserialize(json["graph"]) : null,
|
||||||
|
schedule: json.containsKey("schedule") ? Scheduler().deserialize(json["schedule"]) : null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override Map<String, dynamic> serialize() {
|
||||||
|
var obj = {
|
||||||
|
"id": id,
|
||||||
|
"name": name,
|
||||||
|
"datas": data,
|
||||||
|
"datacenters" : datacenter,
|
||||||
|
"storages": storage,
|
||||||
|
"processings": processing,
|
||||||
|
"workflows": workflows,
|
||||||
|
"schedule": schedule?.serialize(),
|
||||||
|
};
|
||||||
|
if (graph != null) {
|
||||||
|
obj["graph"] = graph!.serialize();
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fromDashboard(Map<String, dynamic> j) {
|
||||||
|
id = j["id"];
|
||||||
|
name = j["name"];
|
||||||
|
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": schedule?.toDashboard(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Scheduler extends SerializerDeserializer<Scheduler> {
|
||||||
|
String? id;
|
||||||
|
String? name;
|
||||||
|
String? cron;
|
||||||
|
DateTime? start;
|
||||||
|
DateTime? end;
|
||||||
|
|
||||||
|
Scheduler({
|
||||||
|
this.id,
|
||||||
|
this.name,
|
||||||
|
this.cron,
|
||||||
|
this.start,
|
||||||
|
this.end
|
||||||
|
});
|
||||||
|
|
||||||
|
void fromDashboard(Map<String, dynamic> j) {
|
||||||
|
id = j["id"];
|
||||||
|
name = j["name"];
|
||||||
|
cron = j["cron"];
|
||||||
|
start = DateTime.parse(j["start"]);
|
||||||
|
if (j.containsKey("end") && j["end"] != null) {
|
||||||
|
end = DateTime.parse(j["end"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Map<String, dynamic> toDashboard() {
|
||||||
|
return {
|
||||||
|
"id": id,
|
||||||
|
"name": name,
|
||||||
|
"cron": cron,
|
||||||
|
"start": start?.toIso8601String(),
|
||||||
|
"end": end?.toIso8601String(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@override deserialize(dynamic json) {
|
||||||
|
try { json = json as Map<String, dynamic>;
|
||||||
|
} 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"] : "",
|
||||||
|
start: json.containsKey("start") ? DateTime.parse(json["start"]) : null,
|
||||||
|
end: json.containsKey("end") ? DateTime.parse(json["end"]) : null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override Map<String, dynamic> serialize() => {
|
||||||
|
"id": id,
|
||||||
|
"name": name,
|
||||||
|
"cron": cron ?? "",
|
||||||
|
"start": start?.toIso8601String(),
|
||||||
|
"end": end?.toIso8601String(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
class Graph extends SerializerDeserializer<Graph> {
|
||||||
|
double zoom;
|
||||||
|
Map<String, GraphItem> items = {};
|
||||||
|
List<GraphLink> links = [];
|
||||||
|
|
||||||
|
Graph({
|
||||||
|
this.zoom = 1,
|
||||||
|
this.items = const {},
|
||||||
|
this.links = const [],
|
||||||
|
});
|
||||||
|
|
||||||
|
void fromDashboard(Map<String, dynamic> j) {
|
||||||
|
items = {};
|
||||||
|
for (var el in (j["elements"] as Map<dynamic, dynamic>).values) {
|
||||||
|
var d = GraphItem();
|
||||||
|
d.fromDashboard(el as Map<String, dynamic>);
|
||||||
|
items[d.id ?? ""] = d;
|
||||||
|
}
|
||||||
|
links = (j["arrows"] as List<dynamic>).map( (el) {
|
||||||
|
var d = GraphLink();
|
||||||
|
d.fromDashboard(el);
|
||||||
|
return d;
|
||||||
|
}).toList();
|
||||||
|
j["zoom"] = zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toDashboard() {
|
||||||
|
List<Map<String, dynamic>> elements = [];
|
||||||
|
List<Map<String, dynamic>> 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<String, dynamic>;
|
||||||
|
} catch (e) { return Graph(); }
|
||||||
|
return 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()) : {},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override Map<String, dynamic> serialize() => {
|
||||||
|
"zoom": zoom,
|
||||||
|
"items": toMapJson(items),
|
||||||
|
"links": toListJson(links),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class GraphLink extends SerializerDeserializer<GraphLink> {
|
||||||
|
Position? source;
|
||||||
|
Position? destination;
|
||||||
|
GraphLinkStyle? style;
|
||||||
|
|
||||||
|
GraphLink({
|
||||||
|
this.source,
|
||||||
|
this.destination,
|
||||||
|
this.style,
|
||||||
|
});
|
||||||
|
|
||||||
|
void fromDashboard(Map<String, dynamic> 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"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> 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(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@override deserialize(dynamic json) {
|
||||||
|
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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override Map<String, dynamic> serialize() {
|
||||||
|
var obj = <String, dynamic>{};
|
||||||
|
if (source != null) {
|
||||||
|
obj["source"] = source!.serialize();
|
||||||
|
}
|
||||||
|
if (destination != null) {
|
||||||
|
obj["destination"] = destination!.serialize();
|
||||||
|
}
|
||||||
|
if (style != null) {
|
||||||
|
obj["style"] = style!.serialize();
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GraphLinkStyle extends SerializerDeserializer<GraphLinkStyle> {
|
||||||
|
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<String, dynamic> 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<String, dynamic> 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<String, dynamic>;
|
||||||
|
} 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<String, dynamic> serialize() {
|
||||||
|
var obj = <String, dynamic> {
|
||||||
|
"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<GraphItem> {
|
||||||
|
String? id;
|
||||||
|
double? width;
|
||||||
|
double? height;
|
||||||
|
Position? position;
|
||||||
|
DataItem? data;
|
||||||
|
ProcessingItem? processing;
|
||||||
|
StorageItem? storage;
|
||||||
|
DataCenterItem? datacenter;
|
||||||
|
WorkflowItem? workflow;
|
||||||
|
|
||||||
|
GraphItem({
|
||||||
|
this.id,
|
||||||
|
this.width,
|
||||||
|
this.height,
|
||||||
|
this.position,
|
||||||
|
this.data,
|
||||||
|
this.processing,
|
||||||
|
this.storage,
|
||||||
|
this.datacenter,
|
||||||
|
this.workflow,
|
||||||
|
});
|
||||||
|
|
||||||
|
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"]);
|
||||||
|
}
|
||||||
|
if (abs.topic == "processing") {
|
||||||
|
processing = ProcessingItem().deserialize(abs.serialize());
|
||||||
|
processing!.model = ResourceModel().deserialize(j["element"]["resource_model"]);
|
||||||
|
}
|
||||||
|
if (abs.topic == "datacenter") {
|
||||||
|
datacenter = DataCenterItem().deserialize(abs.serialize());
|
||||||
|
datacenter!.model = ResourceModel().deserialize(j["element"]["resource_model"]);
|
||||||
|
}
|
||||||
|
if (abs.topic == "storage") {
|
||||||
|
storage = StorageItem().deserialize(abs.serialize());
|
||||||
|
storage!.model = ResourceModel().deserialize(j["element"]["resource_model"]);
|
||||||
|
}
|
||||||
|
if (abs.topic == "workflow") {
|
||||||
|
workflow = WorkflowItem().deserialize(abs.serialize());
|
||||||
|
workflow!.model = ResourceModel().deserialize(j["element"]["resource_model"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toDashboard() {
|
||||||
|
Map<String, dynamic> element = {};
|
||||||
|
for(var el in [data, processing, storage, datacenter, workflow]) {
|
||||||
|
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<String, dynamic>;
|
||||||
|
} 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,
|
||||||
|
datacenter: json.containsKey("datacenter") ? DataCenterItem().deserialize(json["datacenter"]) : null,
|
||||||
|
workflow: json.containsKey("workflow") ? WorkflowItem().deserialize(json["workflow"]) : null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@override Map<String, dynamic> serialize() {
|
||||||
|
return {
|
||||||
|
"id": id,
|
||||||
|
"width": width,
|
||||||
|
"height": height,
|
||||||
|
"data": data?.serialize(),
|
||||||
|
"processing": processing?.serialize(),
|
||||||
|
"storage": storage?.serialize(),
|
||||||
|
"datacenter": datacenter?.serialize(),
|
||||||
|
"workflow": workflow?.serialize(),
|
||||||
|
"position": position?.serialize(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Position extends SerializerDeserializer<Position> {
|
||||||
|
String? id;
|
||||||
|
double? x;
|
||||||
|
double? y;
|
||||||
|
|
||||||
|
Position({
|
||||||
|
this.id,
|
||||||
|
this.x,
|
||||||
|
this.y,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override deserialize(dynamic json) {
|
||||||
|
try { json = json as Map<String, dynamic>;
|
||||||
|
} 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<String, dynamic> serialize() => {
|
||||||
|
"id": id,
|
||||||
|
"x": x,
|
||||||
|
"y": y,
|
||||||
|
};
|
||||||
|
}
|
@ -1,29 +1,48 @@
|
|||||||
import 'package:oc_front/models/abstract.dart';
|
import 'package:oc_front/models/abstract.dart';
|
||||||
|
import 'package:oc_front/models/search.dart';
|
||||||
|
|
||||||
class Workspace extends SerializerDeserializer<Workspace> {
|
class Workspace extends SerializerDeserializer<Workspace> {
|
||||||
String? id;
|
String? id;
|
||||||
List<dynamic> data;
|
String? name;
|
||||||
List<dynamic> datacenter;
|
bool? active;
|
||||||
List<dynamic> storage;
|
List<DataItem> datas;
|
||||||
List<dynamic> computing;
|
List<DataCenterItem> datacenters;
|
||||||
|
List<StorageItem> storages;
|
||||||
|
List<ProcessingItem> processings;
|
||||||
|
List<WorkflowItem> workflows;
|
||||||
|
|
||||||
Workspace({
|
Workspace({
|
||||||
this.id,
|
this.id,
|
||||||
this.computing = const [],
|
this.name,
|
||||||
this.data = const [],
|
this.active = false,
|
||||||
this.datacenter = const [],
|
this.workflows = const [],
|
||||||
this.storage = const [],
|
this.datas = const [],
|
||||||
|
this.datacenters = const [],
|
||||||
|
this.storages = const [],
|
||||||
|
this.processings = const [],
|
||||||
});
|
});
|
||||||
|
|
||||||
@override deserialize(dynamic json) {
|
@override deserialize(dynamic json) {
|
||||||
try { json = json as Map<String, dynamic>;
|
try { json = json as Map<String, dynamic>;
|
||||||
} catch (e) { return Workspace(); }
|
} catch (e) { return Workspace(); }
|
||||||
return Workspace(
|
return Workspace(
|
||||||
computing: json.containsKey("computing") ? json["computing"] : [],
|
id: json.containsKey("id") ? json["id"] : null,
|
||||||
datacenter: json.containsKey("datacenter") ? json["datacenter"] : [],
|
name: json.containsKey("name") ? json["name"] : null,
|
||||||
data: json.containsKey("data") ? json["data"] : [],
|
active: json.containsKey("active") ? json["active"] : false,
|
||||||
storage: json.containsKey("storage") ? json["storage"] : [],
|
processings: json.containsKey("processing_resources") ? fromListJson(json["processing_resources"], ProcessingItem()) : [],
|
||||||
|
storages: json.containsKey("storage_resources") ? fromListJson(json["storage_resources"], StorageItem()) : [],
|
||||||
|
datacenters: json.containsKey("datacenter_resources") ? fromListJson(json["datacenter_resources"], DataCenterItem()) : [],
|
||||||
|
datas: json.containsKey("data_resources") ? fromListJson(json["data_resources"], DataItem()) : [],
|
||||||
|
workflows: json.containsKey("workflow_resources") ? fromListJson(json["workflow_resources"], WorkflowItem()) : []
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@override Map<String, dynamic> serialize() => {};
|
@override Map<String, dynamic> serialize() => {
|
||||||
|
"id": id,
|
||||||
|
"name": name,
|
||||||
|
"processings": processings.map((e) => e.id).toList(),
|
||||||
|
"storages": storages.map((e) => e.id).toList(),
|
||||||
|
"datacenters": datacenters.map((e) => e.id).toList(),
|
||||||
|
"datas": datas.map((e) => e.id).toList(),
|
||||||
|
"workflows": workflows.map((e) => e.id).toList(),
|
||||||
|
};
|
||||||
}
|
}
|
@ -1,11 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:oc_front/core/sections/header/header.dart';
|
import 'package:oc_front/core/sections/header/header.dart';
|
||||||
|
import 'package:oc_front/core/services/specialized_services/resource_service.dart';
|
||||||
import 'package:oc_front/models/search.dart';
|
import 'package:oc_front/models/search.dart';
|
||||||
import 'package:oc_front/widgets/catalog.dart';
|
import 'package:oc_front/widgets/catalog.dart';
|
||||||
import 'package:oc_front/pages/abstract_page.dart';
|
import 'package:oc_front/pages/abstract_page.dart';
|
||||||
import 'package:oc_front/core/sections/header/search.dart';
|
import 'package:oc_front/core/sections/header/search.dart';
|
||||||
import 'package:oc_front/core/services/specialized_services/search_service.dart';
|
import 'package:oc_front/widgets/menu_clipper/workspace_menu.dart';
|
||||||
|
|
||||||
class CatalogFactory implements AbstractFactory {
|
class CatalogFactory implements AbstractFactory {
|
||||||
static List<AbstractItem> items = [];
|
static List<AbstractItem> items = [];
|
||||||
@ -13,10 +14,10 @@ class CatalogFactory implements AbstractFactory {
|
|||||||
@override bool searchFill() { return CatalogFactory.items.isEmpty; }
|
@override bool searchFill() { return CatalogFactory.items.isEmpty; }
|
||||||
@override Widget factory(GoRouterState state, List<String> args) { return CatalogPageWidget(); }
|
@override Widget factory(GoRouterState state, List<String> args) { return CatalogPageWidget(); }
|
||||||
@override void search(BuildContext context) {
|
@override void search(BuildContext context) {
|
||||||
CatalogFactory.key.currentState?.widget.search.get(context, SearchConstants.get()!).then((value) {
|
CatalogFactory.key.currentState?.widget.search.search(context, [ SearchConstants.get()! ], {}).then((value) {
|
||||||
if (value.data == null) { return; }
|
if (value.data == null) { return; }
|
||||||
CatalogFactory.items = [
|
CatalogFactory.items = [ ...value.data!.workflows,
|
||||||
...value.data!.computing, ...value.data!.data, ...value.data!.storage, ...value.data!.datacenter,];
|
...value.data!.processings, ...value.data!.datas, ...value.data!.storages, ...value.data!.datacenters,];
|
||||||
searchWidgetKey.currentState?.setState(() {});
|
searchWidgetKey.currentState?.setState(() {});
|
||||||
CatalogFactory.key.currentState?.setState(() {});
|
CatalogFactory.key.currentState?.setState(() {});
|
||||||
});
|
});
|
||||||
@ -24,16 +25,17 @@ class CatalogFactory implements AbstractFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CatalogPageWidget extends StatefulWidget {
|
class CatalogPageWidget extends StatefulWidget {
|
||||||
final SearchService search = SearchService();
|
final ResourceService search = ResourceService();
|
||||||
CatalogPageWidget (): super(key: CatalogFactory.key);
|
CatalogPageWidget (): super(key: CatalogFactory.key);
|
||||||
@override CatalogPageWidgetState createState() => CatalogPageWidgetState();
|
@override CatalogPageWidgetState createState() => CatalogPageWidgetState();
|
||||||
}
|
}
|
||||||
class CatalogPageWidgetState extends State<CatalogPageWidget> {
|
class CatalogPageWidgetState extends State<CatalogPageWidget> {
|
||||||
@override Widget build(BuildContext context) {
|
@override Widget build(BuildContext context) {
|
||||||
return Column( children : [
|
return Column( children : [
|
||||||
|
CatalogFactory.items.isEmpty ? Container() : MenuWorkspaceWidget(),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width,
|
||||||
height: CatalogFactory.items.isEmpty ? 0 : MediaQuery.of(context).size.height - HeaderConstants.height,
|
height: CatalogFactory.items.isEmpty ? 0 : MediaQuery.of(context).size.height - HeaderConstants.height - 50,
|
||||||
child: CatalogWidget(items: CatalogFactory.items) )
|
child: CatalogWidget(items: CatalogFactory.items) )
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
@ -16,8 +16,8 @@ class CatalogItemFactory implements AbstractFactory {
|
|||||||
var item = CatalogFactory.items.firstWhere( (element) => element.id == id );
|
var item = CatalogFactory.items.firstWhere( (element) => element.id == id );
|
||||||
return CatalogItemPageWidget(item : item);
|
return CatalogItemPageWidget(item : item);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
var item = WorkspaceLocal.getItem(id ?? "");
|
var item = WorkspaceLocal.getItem(id ?? "", false);
|
||||||
if (item != null) { return CatalogItemPageWidget(item : item); }
|
if (item != null) { return CatalogItemPageWidget(item : item as AbstractItem); }
|
||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
|
import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart' as intl;
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:oc_front/core/services/specialized_services/workflow_execution_service.dart';
|
||||||
|
import 'package:oc_front/models/workflow.dart';
|
||||||
import 'package:oc_front/pages/abstract_page.dart';
|
import 'package:oc_front/pages/abstract_page.dart';
|
||||||
import 'package:table_calendar/table_calendar.dart';
|
import 'package:oc_front/widgets/sheduler_items/schedule.dart';
|
||||||
|
|
||||||
class SchedulerFactory implements AbstractFactory {
|
class SchedulerFactory implements AbstractFactory {
|
||||||
static GlobalKey<SchedulerPageWidgetState> key = GlobalKey<SchedulerPageWidgetState>();
|
static GlobalKey<SchedulerPageWidgetState> key = GlobalKey<SchedulerPageWidgetState>();
|
||||||
@ -11,18 +15,169 @@ class SchedulerFactory implements AbstractFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SchedulerPageWidget extends StatefulWidget {
|
class SchedulerPageWidget extends StatefulWidget {
|
||||||
|
bool isList = true;
|
||||||
|
DateTime start = DateTime.now();
|
||||||
|
DateTime end = DateTime.now().add(const Duration(days: 180));
|
||||||
|
final WorkflowExecutionService _service = WorkflowExecutionService();
|
||||||
SchedulerPageWidget(): super(key: SchedulerFactory.key);
|
SchedulerPageWidget(): super(key: SchedulerFactory.key);
|
||||||
@override SchedulerPageWidgetState createState() => SchedulerPageWidgetState();
|
@override SchedulerPageWidgetState createState() => SchedulerPageWidgetState();
|
||||||
static void search(BuildContext context) { }
|
static void search(BuildContext context) { }
|
||||||
static Widget factory() { return SchedulerPageWidget(); }
|
static Widget factory() { return SchedulerPageWidget(); }
|
||||||
}
|
}
|
||||||
class SchedulerPageWidgetState extends State<SchedulerPageWidget> {
|
class SchedulerPageWidgetState extends State<SchedulerPageWidget> {
|
||||||
|
List<Color> colors = [Colors.blue, Colors.orange, Colors.red, Colors.green];
|
||||||
|
List<String> titles = ["SCHEDULED", "RUNNING", "FAILURE", "SUCCESS"];
|
||||||
|
|
||||||
@override Widget build(BuildContext context) {
|
@override Widget build(BuildContext context) {
|
||||||
return TableCalendar(
|
return FutureBuilder(
|
||||||
firstDay: DateTime.utc(2010, 10, 16),
|
future: widget._service.search(context, [
|
||||||
lastDay: DateTime.utc(2030, 3, 14),
|
"${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}"}",
|
||||||
focusedDay: DateTime.now(),
|
"${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) {
|
||||||
|
Map<String, List<WorkflowExecution>> data = {};
|
||||||
|
if (as.hasData && as.data!.data != null) {
|
||||||
|
for (var element in as.data!.data!.executions) {
|
||||||
|
if (element.executionData == null) { continue; }
|
||||||
|
DateTime dateTime = DateTime.parse(element.executionData!);
|
||||||
|
DateTime date = DateTime(dateTime.year, dateTime.month, dateTime.day);
|
||||||
|
var str = "${date.toIso8601String()}Z";
|
||||||
|
if (data[str] == null) { data[str] = []; }
|
||||||
|
data[str]!.add(element);
|
||||||
|
data[str]!.sort((a, b) => DateTime.parse(a.executionData!).compareTo(DateTime.parse(b.executionData!)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GlobalKey<ScheduleWidgetState> k = GlobalKey<ScheduleWidgetState>();
|
||||||
|
return Column( children: [
|
||||||
|
Container( color: const Color.fromRGBO(38, 166, 154, 1),
|
||||||
|
height: 50, width: MediaQuery.of(context).size.width,
|
||||||
|
child: Padding(padding: const EdgeInsets.symmetric(horizontal: 50),
|
||||||
|
child: Row( children: [
|
||||||
|
Padding(padding: const EdgeInsets.only(right: 30),
|
||||||
|
child: Tooltip( message: widget.isList ? "calendar view" : "list view",
|
||||||
|
child: InkWell( child: Icon( widget.isList ? Icons.calendar_month : Icons.list, color: Colors.white
|
||||||
|
, size: 25 ),
|
||||||
|
onTap: () {
|
||||||
|
widget.isList = !widget.isList;
|
||||||
|
k.currentState?.setState(() { k.currentState?.widget.isList = widget.isList; });
|
||||||
|
})
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(padding: const EdgeInsets.only(left: 20),
|
||||||
|
width: MediaQuery.of(context).size.width / 5,
|
||||||
|
height: 30,
|
||||||
|
child: DateTimeField(
|
||||||
|
validator: (value) {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
resetIcon: const Icon(Icons.close, size: 15),
|
||||||
|
onShowPicker: (context, currentValue) async {
|
||||||
|
var date = await showDatePicker(
|
||||||
|
builder: (BuildContext context, Widget? child) {
|
||||||
|
Widget w = Theme(
|
||||||
|
data: ThemeData(
|
||||||
|
cardTheme: CardTheme(elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0))),
|
||||||
|
dialogTheme: DialogTheme(elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0))),
|
||||||
|
colorScheme: ColorScheme.light(
|
||||||
|
background: Colors.grey.shade300,
|
||||||
|
tertiary: Colors.grey,
|
||||||
|
secondary: Colors.grey,
|
||||||
|
primary: Colors.black),
|
||||||
|
),
|
||||||
|
child: child ?? Container(),
|
||||||
);
|
);
|
||||||
|
return w;
|
||||||
|
},
|
||||||
|
context: context,
|
||||||
|
firstDate: DateTime(1900),
|
||||||
|
initialDate: widget.start,
|
||||||
|
lastDate: DateTime(2100)
|
||||||
|
);
|
||||||
|
return date;
|
||||||
|
},
|
||||||
|
format: intl.DateFormat('y-M-dd hh:mm:ss'),
|
||||||
|
initialValue: widget.start,
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value == null) { return; }
|
||||||
|
setState(() { widget.start = value; });
|
||||||
|
},
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||||
|
filled: true,
|
||||||
|
alignLabelWithHint: false,
|
||||||
|
hintText: "enter start date...",
|
||||||
|
labelText: "",
|
||||||
|
errorStyle: TextStyle(fontSize: 0),
|
||||||
|
hintStyle: TextStyle(fontSize: 10),
|
||||||
|
labelStyle: TextStyle(fontSize: 15, color: Colors.black, fontWeight: FontWeight.w500),
|
||||||
|
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.transparent)),
|
||||||
|
border: OutlineInputBorder(borderSide: BorderSide(color: Colors.transparent)),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Container(padding: const EdgeInsets.only(left: 20),
|
||||||
|
child: const Text("TO", style: TextStyle(color: Colors.white, fontSize: 15, fontWeight: FontWeight.w500))),
|
||||||
|
Container( padding: const EdgeInsets.only(left: 20),
|
||||||
|
width: MediaQuery.of(context).size.width / 5,
|
||||||
|
height: 30,
|
||||||
|
child: DateTimeField(
|
||||||
|
validator: (value) {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
resetIcon: const Icon(Icons.close, size: 15),
|
||||||
|
onShowPicker: (context, currentValue) async {
|
||||||
|
var date = await showDatePicker(
|
||||||
|
builder: (BuildContext context, Widget? child) {
|
||||||
|
Widget w = Theme(
|
||||||
|
data: ThemeData(
|
||||||
|
cardTheme: CardTheme(elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0))),
|
||||||
|
dialogTheme: DialogTheme(elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0))),
|
||||||
|
colorScheme: ColorScheme.light(
|
||||||
|
background: Colors.grey.shade300,
|
||||||
|
tertiary: Colors.grey,
|
||||||
|
secondary: Colors.grey,
|
||||||
|
primary: Colors.black),
|
||||||
|
),
|
||||||
|
child: child ?? Container(),
|
||||||
|
);
|
||||||
|
return w;
|
||||||
|
},
|
||||||
|
context: context,
|
||||||
|
firstDate: DateTime(1900),
|
||||||
|
initialDate: widget.end,
|
||||||
|
lastDate: DateTime(2100)
|
||||||
|
);
|
||||||
|
return date;
|
||||||
|
},
|
||||||
|
format: intl.DateFormat('y-M-dd hh:mm:ss'),
|
||||||
|
initialValue: widget.end,
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value == null) { return; }
|
||||||
|
setState(() { widget.start = value; });
|
||||||
|
},
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||||
|
filled: true,
|
||||||
|
alignLabelWithHint: false,
|
||||||
|
hintText: "enter end date...",
|
||||||
|
labelText: "",
|
||||||
|
errorStyle: TextStyle(fontSize: 0),
|
||||||
|
hintStyle: TextStyle(fontSize: 10),
|
||||||
|
labelStyle: TextStyle(fontSize: 15, color: Colors.black, fontWeight: FontWeight.w500),
|
||||||
|
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.transparent)),
|
||||||
|
border: OutlineInputBorder(borderSide: BorderSide(color: Colors.transparent)),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]))
|
||||||
|
),
|
||||||
|
ScheduleWidget( key: k, data: data, start: widget.start, end : widget.end, isList: widget.isList )
|
||||||
|
]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,3 @@
|
|||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
|
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
@ -8,10 +6,16 @@ import 'package:oc_front/core/sections/header/header.dart';
|
|||||||
import 'package:oc_front/core/services/specialized_services/workflow_service.dart';
|
import 'package:oc_front/core/services/specialized_services/workflow_service.dart';
|
||||||
import 'package:oc_front/models/response.dart';
|
import 'package:oc_front/models/response.dart';
|
||||||
import 'package:oc_front/models/search.dart';
|
import 'package:oc_front/models/search.dart';
|
||||||
|
import 'package:oc_front/models/workflow.dart';
|
||||||
import 'package:oc_front/pages/abstract_page.dart';
|
import 'package:oc_front/pages/abstract_page.dart';
|
||||||
import 'package:oc_front/widgets/dialog/new_box.dart';
|
import 'package:oc_front/widgets/dialog/new_box.dart';
|
||||||
|
import 'package:oc_front/widgets/forms/proxy_forms.dart';
|
||||||
|
import 'package:oc_front/widgets/forms/scheduler_forms.dart';
|
||||||
import 'package:oc_front/widgets/items/item_row.dart';
|
import 'package:oc_front/widgets/items/item_row.dart';
|
||||||
Dashboard dash = Dashboard(name: "workflow_${DateTime.now().toString().replaceAll(" ", "_").substring(0, DateTime.now().toString().length - 7)}");
|
import 'package:oc_front/widgets/menu_clipper/workspace_menu.dart';
|
||||||
|
|
||||||
|
Dashboard dash = Dashboard(
|
||||||
|
name: "workflow_${DateTime.now().toString().replaceAll(" ", "_").substring(0, DateTime.now().toString().length - 7)}");
|
||||||
class WorkflowFactory implements AbstractFactory {
|
class WorkflowFactory implements AbstractFactory {
|
||||||
static GlobalKey<WorkflowPageWidgetState> key = GlobalKey<WorkflowPageWidgetState>();
|
static GlobalKey<WorkflowPageWidgetState> key = GlobalKey<WorkflowPageWidgetState>();
|
||||||
@override bool searchFill() { return false; }
|
@override bool searchFill() { return false; }
|
||||||
@ -29,8 +33,10 @@ class WorkflowPageWidgetState extends State<WorkflowPageWidget> {
|
|||||||
final WorflowService _service = WorflowService();
|
final WorflowService _service = WorflowService();
|
||||||
Widget itemBuild(Object item) {
|
Widget itemBuild(Object item) {
|
||||||
var e = item as AbstractItem;
|
var e = item as AbstractItem;
|
||||||
return e.logo != null ? Image.memory(base64Decode(e.logo ?? ""), fit: BoxFit.fill)
|
return Tooltip( message: item.name ?? "",
|
||||||
: Image.network('https://get-picto.com/wp-content/uploads/2024/01/logo-instagram-png.webp', fit: BoxFit.fill);
|
child: e.logo != null ? Image.network(e.logo ?? "", fit: BoxFit.fill)
|
||||||
|
: Image.network('https://get-picto.com/wp-content/uploads/2024/01/logo-instagram-png.webp',
|
||||||
|
fit: BoxFit.fill));
|
||||||
}
|
}
|
||||||
Widget itemTooltipBuild(Object item) {
|
Widget itemTooltipBuild(Object item) {
|
||||||
var e = item as AbstractItem;
|
var e = item as AbstractItem;
|
||||||
@ -39,30 +45,113 @@ final WorflowService _service = WorflowService();
|
|||||||
List<DropdownMenuItem> getItems(Object? data) {
|
List<DropdownMenuItem> getItems(Object? data) {
|
||||||
data = data as APIResponse<RawData>?;
|
data = data as APIResponse<RawData>?;
|
||||||
if (data != null && data.data != null && data.data!.values.isNotEmpty) {
|
if (data != null && data.data != null && data.data!.values.isNotEmpty) {
|
||||||
return (data.data!.values as List<dynamic>).map((dynamic value) {
|
return data.data!.values.map((dynamic value) {
|
||||||
return DropdownMenuItem<String>(
|
return DropdownMenuItem<String>(
|
||||||
value: value.toString(),
|
value: "${value["id"] ?? ""}~${value["name"] ?? ""}",
|
||||||
child: Text(value.toString()),
|
child: Text(value["name"]?.toString() ?? ""),
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
List<Widget> getForms(FlowData? obj) {
|
||||||
|
return obj == null ? [] : [
|
||||||
|
ProxyFormsWidget(item: obj as AbstractItem),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> getDashInfoForms() {
|
||||||
|
return [
|
||||||
|
SchedulerFormsWidget(item: dash),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> loadDash(String selected) async {
|
||||||
|
if (selected.split("~").length > 1) {
|
||||||
|
dash.name = selected.split("~")[1];
|
||||||
|
dash.id = selected.split("~")[0];
|
||||||
|
} else {
|
||||||
|
dash.name = selected;
|
||||||
|
}
|
||||||
|
await _service.get(context, dash.id ?? "").then((value) {
|
||||||
|
if (value.data != null) {
|
||||||
|
dash.deserialize(value.data!.toDashboard());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> saveDash(String? id) async {
|
||||||
|
if (id == null || !dash.isOpened) { return; }
|
||||||
|
var datas = WorkspaceLocal.byTopic("data", true).where(
|
||||||
|
(element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) );
|
||||||
|
var dataCenter = WorkspaceLocal.byTopic("datacenter", true).where(
|
||||||
|
(element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) );
|
||||||
|
var storage = WorkspaceLocal.byTopic("storage", true).where(
|
||||||
|
(element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) );
|
||||||
|
var computing = WorkspaceLocal.byTopic("processing", true).where(
|
||||||
|
(element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) );
|
||||||
|
var workflows = WorkspaceLocal.byTopic("workflows", true).where(
|
||||||
|
(element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) );
|
||||||
|
var updateW = Workflow(
|
||||||
|
name: dash.name,
|
||||||
|
graph: Graph(),
|
||||||
|
data: datas.map((e) => e.id).toSet().toList(),
|
||||||
|
datacenter: dataCenter.map((e) => e.id).toSet().toList(),
|
||||||
|
storage: storage.map((e) => e.id).toSet().toList(),
|
||||||
|
processing: computing.map((e) => e.id).toSet().toList(),
|
||||||
|
workflows: workflows.map((e) => e.id).toSet().toList(),
|
||||||
|
);
|
||||||
|
updateW.fromDashboard(dash.serialize());
|
||||||
|
for (var item in (updateW.graph?.items.values ?? [] as List<GraphItem>)) {
|
||||||
|
if (item.position == null) { continue; }
|
||||||
|
item.position?.x = (item.position?.x ?? 0) + 52.5;
|
||||||
|
item.position?.y = (item.position?.y ?? 0) + 52.5;
|
||||||
|
}
|
||||||
|
print(dash.getZoomFactor());
|
||||||
|
updateW.graph?.zoom = dash.getZoomFactor();
|
||||||
|
await _service.put(context, id, updateW.serialize(), {});
|
||||||
|
}
|
||||||
|
|
||||||
|
FlowData? transformToData(Map<String, dynamic> data) {
|
||||||
|
var d = WorkspaceLocal.getItem(data["id"] ?? "", true);
|
||||||
|
if (d == null) { return null; }
|
||||||
|
d.model = ResourceModel().deserialize(data["resource_model"]);
|
||||||
|
if (d.topic == "data") { return d as DataItem; }
|
||||||
|
if (d.topic == "datacenter") { return d as DataCenterItem; }
|
||||||
|
if (d.topic == "storage") { return d as StorageItem; }
|
||||||
|
if (d.topic == "processing") { return d as ProcessingItem; }
|
||||||
|
if (d.topic == "workflows") { return d as WorkflowItem; }
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Widget menuExtension() {
|
||||||
|
var quart = MediaQuery.of(context).size.width / 6;
|
||||||
|
return MenuWorkspaceWidget(simpliest: true, width: quart > 80 ? quart : 80,
|
||||||
|
onWorkspaceChange: () { dash.selectedLeftMenuKey.currentState?.setState(() { }); });
|
||||||
|
}
|
||||||
|
|
||||||
Widget onDashboardAlertOpened(BuildContext context, Dashboard dash) {
|
Widget onDashboardAlertOpened(BuildContext context, Dashboard dash) {
|
||||||
return NewBoxWidget<RawData>(service: _service, dash: dash,
|
return NewBoxWidget<Workflow>(service: _service, dash: dash,
|
||||||
getItems: getItems);
|
getItems: getItems);
|
||||||
}
|
}
|
||||||
@override Widget build(BuildContext context) {
|
@override Widget build(BuildContext context) {
|
||||||
|
dash.load = loadDash;
|
||||||
|
dash.save = saveDash;
|
||||||
|
dash.transformToData = transformToData;
|
||||||
|
dash.infoItemWidget = getForms;
|
||||||
|
dash.infoWidget = getDashInfoForms;
|
||||||
var quart = MediaQuery.of(context).size.width / 6;
|
var quart = MediaQuery.of(context).size.width / 6;
|
||||||
dash.defaultName = "workflow_${DateTime.now().toString().replaceAll(" ", "_").substring(0, DateTime.now().toString().length - 7)}";
|
dash.defaultName = "workflow_${DateTime.now().toString().replaceAll(" ", "_").substring(0, DateTime.now().toString().length - 7)}";
|
||||||
return FlowChart<AbstractItem>(
|
return FlowChart<AbstractItem>(
|
||||||
onDashboardAlertOpened: onDashboardAlertOpened,
|
onDashboardAlertOpened: onDashboardAlertOpened,
|
||||||
dashboard: dash,
|
dashboard: dash,
|
||||||
itemWidget: itemBuild,
|
itemWidget: itemBuild,
|
||||||
categories: const ["computing", "data", "datacenter", "storage"],
|
categories: const ["processing", "data", "datacenter", "storage", "workflows"],
|
||||||
draggableItemBuilder: (cat) => WorkspaceLocal.byTopic(cat).toList(),
|
draggableItemBuilder: (cat) => WorkspaceLocal.byTopic(cat, true).toList(),
|
||||||
itemWidgetTooltip: itemTooltipBuild,
|
itemWidgetTooltip: itemTooltipBuild,
|
||||||
innerMenuWidth: quart > 80 ? quart : 80,
|
innerMenuWidth: quart > 80 ? quart : 80,
|
||||||
|
menuExtension: menuExtension,
|
||||||
width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width,
|
||||||
height: MediaQuery.of(context).size.height - HeaderConstants.height,
|
height: MediaQuery.of(context).size.height - HeaderConstants.height,
|
||||||
onNewConnection: (p1, p2) { },
|
onNewConnection: (p1, p2) { },
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
|
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
|
||||||
|
import 'package:oc_front/core/models/workspace_local.dart';
|
||||||
|
import 'package:oc_front/core/services/router.dart';
|
||||||
import 'package:oc_front/core/services/specialized_services/abstract_service.dart';
|
import 'package:oc_front/core/services/specialized_services/abstract_service.dart';
|
||||||
import 'package:oc_front/models/abstract.dart';
|
import 'package:oc_front/models/abstract.dart';
|
||||||
import 'package:oc_front/models/response.dart';
|
import 'package:oc_front/models/response.dart';
|
||||||
@ -24,13 +26,33 @@ class NewBoxWidgetState<T extends SerializerDeserializer<dynamic>> extends State
|
|||||||
widget._ctrl.value = TextEditingValue(text: widget.dash.defaultName);
|
widget._ctrl.value = TextEditingValue(text: widget.dash.defaultName);
|
||||||
return Container(
|
return Container(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
padding: const EdgeInsets.all(20),
|
padding: const EdgeInsets.only( top: 0, bottom: 20, left: 20, right: 20),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Container(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
alignment: Alignment.centerRight,
|
||||||
children : [
|
height: 50,
|
||||||
FutureBuilder<APIResponse<T>>(
|
child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [
|
||||||
|
Padding(padding: const EdgeInsets.symmetric(horizontal: 10), child:
|
||||||
|
Text("load or create a new workflow", style: const TextStyle(color: Colors.grey, fontSize: 15)
|
||||||
|
)),
|
||||||
|
Padding ( padding: const EdgeInsets.symmetric(horizontal: 10), child:
|
||||||
|
Tooltip( message: "back", child: InkWell(
|
||||||
|
mouseCursor: SystemMouseCursors.click,
|
||||||
|
onTap: () {
|
||||||
|
AppRouter.catalog.go(context, {});
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.arrow_back, color: Colors.black))),
|
||||||
|
),
|
||||||
|
widget.dash.isOpened ? Row ( mainAxisAlignment: MainAxisAlignment.end, children: [
|
||||||
|
Tooltip( message: "close", child: InkWell(
|
||||||
|
mouseCursor: SystemMouseCursors.click,
|
||||||
|
onTap: () { Navigator.pop(context); },
|
||||||
|
child: const Icon(Icons.close, color: Colors.black))),
|
||||||
|
]) : Container(),
|
||||||
|
],),
|
||||||
|
),
|
||||||
|
FutureBuilder<APIResponse<RawData>>(
|
||||||
future: (widget.service as AbstractService<T>).all(context),
|
future: (widget.service as AbstractService<T>).all(context),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
List<DropdownMenuItem> items = widget.getItems != null ? widget.getItems!(snapshot.data) : [];
|
List<DropdownMenuItem> items = widget.getItems != null ? widget.getItems!(snapshot.data) : [];
|
||||||
@ -41,7 +63,10 @@ class NewBoxWidgetState<T extends SerializerDeserializer<dynamic>> extends State
|
|||||||
child: Text(widget._selected.toString()),
|
child: Text(widget._selected.toString()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
return SizedBox( width: MediaQuery.of(context).size.width <= 540 ? MediaQuery.of(context).size.width - 140 : 400, height: 50,
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children : [
|
||||||
|
SizedBox( width: MediaQuery.of(context).size.width <= 540 ? MediaQuery.of(context).size.width - 140 : 400, height: 50,
|
||||||
child: DropdownButtonFormField(
|
child: DropdownButtonFormField(
|
||||||
value: widget._selected,
|
value: widget._selected,
|
||||||
isExpanded: true,
|
isExpanded: true,
|
||||||
@ -59,12 +84,12 @@ class NewBoxWidgetState<T extends SerializerDeserializer<dynamic>> extends State
|
|||||||
border: OutlineInputBorder( borderRadius: BorderRadius.zero,
|
border: OutlineInputBorder( borderRadius: BorderRadius.zero,
|
||||||
borderSide: BorderSide(color: Colors.grey.shade300, width: 0)),
|
borderSide: BorderSide(color: Colors.grey.shade300, width: 0)),
|
||||||
),
|
),
|
||||||
items: items, onChanged: (value) {
|
items: items,
|
||||||
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
widget._selected = value.toString();
|
widget._selected = value.toString();
|
||||||
});
|
});
|
||||||
}));
|
})),
|
||||||
}),
|
|
||||||
Tooltip(
|
Tooltip(
|
||||||
message: 'empty selection',
|
message: 'empty selection',
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
@ -86,9 +111,13 @@ class NewBoxWidgetState<T extends SerializerDeserializer<dynamic>> extends State
|
|||||||
child: InkWell(
|
child: InkWell(
|
||||||
mouseCursor: widget._selected == null || widget._selected!.isEmpty
|
mouseCursor: widget._selected == null || widget._selected!.isEmpty
|
||||||
? MouseCursor.defer : SystemMouseCursors.click,
|
? MouseCursor.defer : SystemMouseCursors.click,
|
||||||
onTap: () {
|
onTap: () async {
|
||||||
if (widget._selected == null || widget._selected!.isEmpty) { return; }
|
if (widget._selected == null || widget._selected!.isEmpty) { return; }
|
||||||
widget.dash.name = widget._selected ?? widget.dash.name;
|
if (widget._selected != null && widget.dash.load != null) {
|
||||||
|
await widget.dash.load!(widget._selected ?? "");
|
||||||
|
WorkspaceLocal.init(context, true);
|
||||||
|
}
|
||||||
|
widget.dash.isOpened = true;
|
||||||
widget.dash.notifyListeners();
|
widget.dash.notifyListeners();
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
@ -100,7 +129,8 @@ class NewBoxWidgetState<T extends SerializerDeserializer<dynamic>> extends State
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
]),
|
]);}),
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
@ -115,7 +145,7 @@ class NewBoxWidgetState<T extends SerializerDeserializer<dynamic>> extends State
|
|||||||
minLines: null,
|
minLines: null,
|
||||||
cursorColor: const Color.fromARGB(38, 166, 154, 1),
|
cursorColor: const Color.fromARGB(38, 166, 154, 1),
|
||||||
controller: widget._ctrl,
|
controller: widget._ctrl,
|
||||||
onChanged: (value) => setState(() { widget._ctrl.value = TextEditingValue(text: value); }),
|
onChanged: (value) {},
|
||||||
validator: (value) => value == null || value.isEmpty ? "name is required" : null,
|
validator: (value) => value == null || value.isEmpty ? "name is required" : null,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "name a new workflow...",
|
hintText: "name a new workflow...",
|
||||||
@ -137,14 +167,20 @@ class NewBoxWidgetState<T extends SerializerDeserializer<dynamic>> extends State
|
|||||||
mouseCursor: widget._ctrl.value.text.isEmpty ? MouseCursor.defer : SystemMouseCursors.click,
|
mouseCursor: widget._ctrl.value.text.isEmpty ? MouseCursor.defer : SystemMouseCursors.click,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
if (widget._ctrl.value.text.isNotEmpty) {
|
if (widget._ctrl.value.text.isNotEmpty) {
|
||||||
await widget.service.post(context, {}, { "workflowName" : widget._ctrl.value.text });
|
await widget.service.post(context, { "name" : widget._ctrl.value.text }, {}).then(
|
||||||
|
(value) {
|
||||||
widget._selected = widget._ctrl.value.text;
|
widget._selected = widget._ctrl.value.text;
|
||||||
widget._ctrl.value = const TextEditingValue(text: "");
|
widget._ctrl.value = const TextEditingValue(text: "");
|
||||||
widget.dash.name = widget._selected ?? widget.dash.name;
|
widget.dash.id = value.data?.serialize()["id"];
|
||||||
|
widget.dash.name = widget._selected ?? "";
|
||||||
widget.dash.notifyListeners();
|
widget.dash.notifyListeners();
|
||||||
|
WorkspaceLocal.init(context, true);
|
||||||
|
widget.dash.isOpened = true;
|
||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: const EdgeInsets.only(top: 10),
|
margin: const EdgeInsets.only(top: 10),
|
||||||
|
73
lib/widgets/forms/data_forms.dart
Normal file
73
lib/widgets/forms/data_forms.dart
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:oc_front/models/search.dart';
|
||||||
|
|
||||||
|
class DataFormsWidget extends StatefulWidget {
|
||||||
|
DataItem item;
|
||||||
|
String purpose = "";
|
||||||
|
Function validate = () {};
|
||||||
|
DataFormsWidget ({ super.key, required this.item });
|
||||||
|
@override DataFormsWidgetState createState() => DataFormsWidgetState();
|
||||||
|
}
|
||||||
|
class DataFormsWidgetState extends State<DataFormsWidget> {
|
||||||
|
@override Widget build(BuildContext context) {
|
||||||
|
return Column( children: [
|
||||||
|
Tooltip( message: "protocols",
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.only(left: 10),
|
||||||
|
width: 45, height: 25,
|
||||||
|
child: TextFormField( textAlign: TextAlign.center,
|
||||||
|
initialValue: widget.item.protocols.join(","),
|
||||||
|
onChanged: (value) {
|
||||||
|
widget.item.protocols = value.split(",");
|
||||||
|
},
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: true,
|
||||||
|
labelText: "protocols",
|
||||||
|
labelStyle: TextStyle(fontSize: 10),
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||||
|
),
|
||||||
|
))),
|
||||||
|
Tooltip( message: "datatype",
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.only(left: 10),
|
||||||
|
width: 45, height: 25,
|
||||||
|
child: TextFormField( textAlign: TextAlign.center,
|
||||||
|
initialValue: widget.item.dataType,
|
||||||
|
onChanged: (value) {
|
||||||
|
widget.item.dataType = value;
|
||||||
|
},
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: true,
|
||||||
|
labelText: "datatype",
|
||||||
|
labelStyle: TextStyle(fontSize: 10),
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||||
|
),
|
||||||
|
))),
|
||||||
|
Tooltip( message: "example",
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.only(left: 10),
|
||||||
|
width: 45, height: 25,
|
||||||
|
child: TextFormField( textAlign: TextAlign.center,
|
||||||
|
initialValue: widget.item.exemple,
|
||||||
|
onChanged: (value) {
|
||||||
|
widget.item.exemple = value;
|
||||||
|
},
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: true,
|
||||||
|
labelText: "example",
|
||||||
|
labelStyle: TextStyle(fontSize: 10),
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||||
|
),
|
||||||
|
)))
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
61
lib/widgets/forms/proxy_forms.dart
Normal file
61
lib/widgets/forms/proxy_forms.dart
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:oc_front/models/search.dart';
|
||||||
|
import 'package:oc_front/pages/workflow.dart';
|
||||||
|
|
||||||
|
Map<String, Map<String, AbstractItem>> proxyWfItem = {};
|
||||||
|
|
||||||
|
class ProxyFormsWidget extends StatefulWidget {
|
||||||
|
AbstractItem item;
|
||||||
|
ProxyFormsWidget ({ super.key, required this.item });
|
||||||
|
@override ProxyFormsWidgetState createState() => ProxyFormsWidgetState();
|
||||||
|
}
|
||||||
|
class ProxyFormsWidgetState extends State<ProxyFormsWidget> {
|
||||||
|
@override Widget build(BuildContext context) {
|
||||||
|
List<Widget> children = [];
|
||||||
|
var l = widget.item.model?.model?.keys ?? [];
|
||||||
|
for (var child in l) {
|
||||||
|
if (widget.item.model!.model![child]!.type != "string") { continue; }
|
||||||
|
children.add(
|
||||||
|
Tooltip( message: child,
|
||||||
|
child: Container( margin: EdgeInsets.only(top: children.isEmpty ? 0 : 15),
|
||||||
|
width: 160, height: 30,
|
||||||
|
child: TextFormField( textAlign: TextAlign.start,
|
||||||
|
initialValue: widget.item.model?.model?[child]?.value,
|
||||||
|
onChanged: (value) {
|
||||||
|
widget.item.model ?? Model();
|
||||||
|
Future.delayed(const Duration(seconds: 2), () {
|
||||||
|
if (widget.item.model!.model?[child]?.value == value) {
|
||||||
|
dash.save!(dash.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
widget.item.model?.model?[child]?.value = value;
|
||||||
|
},
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: "enter $child...",
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: true,
|
||||||
|
labelText: child,
|
||||||
|
alignLabelWithHint: false,
|
||||||
|
errorStyle: const TextStyle(fontSize: 0),
|
||||||
|
hintStyle: const TextStyle(fontSize: 10),
|
||||||
|
labelStyle: const TextStyle(fontSize: 10),
|
||||||
|
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||||
|
enabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
|
||||||
|
border: const OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||||
|
),
|
||||||
|
)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Column( children: [
|
||||||
|
Container( padding: const EdgeInsets.all(10), width: 200, height: 60, margin: const EdgeInsets.only(bottom: 15),
|
||||||
|
decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),
|
||||||
|
child: const Column( mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||||
|
Text("ELEMENT INFO", style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
||||||
|
Text("<general>", style: TextStyle(fontSize: 12), textAlign: TextAlign.center),
|
||||||
|
])),
|
||||||
|
...children
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
288
lib/widgets/forms/scheduler_forms.dart
Normal file
288
lib/widgets/forms/scheduler_forms.dart
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
import 'package:cron/cron.dart';
|
||||||
|
import 'package:intl/intl.dart' as intl;
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
|
||||||
|
import 'package:flutter_advanced_switch/flutter_advanced_switch.dart';
|
||||||
|
import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
|
||||||
|
|
||||||
|
class SchedulerFormsWidget extends StatefulWidget {
|
||||||
|
Dashboard item;
|
||||||
|
String purpose = "";
|
||||||
|
Function validate = () {};
|
||||||
|
SchedulerFormsWidget ({ super.key, required this.item });
|
||||||
|
@override SchedulerFormsWidgetState createState() => SchedulerFormsWidgetState();
|
||||||
|
}
|
||||||
|
class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
|
||||||
|
@override Widget build(BuildContext context) {
|
||||||
|
if (widget.item.schedulerState["service"] == null) { widget.item.schedulerState["service"] = true; }
|
||||||
|
List<GlobalKey<FormFieldState>> formKeys = [GlobalKey<FormFieldState>(), GlobalKey<FormFieldState>(),
|
||||||
|
GlobalKey<FormFieldState>(), GlobalKey<FormFieldState>()];
|
||||||
|
return Column( children: [
|
||||||
|
Container( padding: const EdgeInsets.all(10), width: 200, height: 60,
|
||||||
|
decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),
|
||||||
|
child: const Column( mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||||
|
Text("WORKFLOW INFO", style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
||||||
|
Text("<general>", style: TextStyle(fontSize: 12), textAlign: TextAlign.center),
|
||||||
|
])),
|
||||||
|
Container(height: 20),
|
||||||
|
AdvancedSwitch(
|
||||||
|
width: 140,
|
||||||
|
initialValue: widget.item.schedulerState["service"] == true,
|
||||||
|
activeColor: Colors.green, inactiveColor: Colors.green,
|
||||||
|
activeChild: const Text("service", style: TextStyle(color: Colors.white)),
|
||||||
|
inactiveChild: const Text("cron task", style: TextStyle(color: Colors.white)),
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(15)), height: 30.0, disabledOpacity: 0.5,
|
||||||
|
onChanged: (value) {
|
||||||
|
Future.delayed(const Duration(milliseconds: 100), () =>
|
||||||
|
setState(() {
|
||||||
|
widget.item.schedulerState["service"] = value;
|
||||||
|
if ((widget.item.schedulerState["service"] == true )) { widget.item.scheduler.remove("cron"); }
|
||||||
|
}));
|
||||||
|
},),
|
||||||
|
Container(height: 5),
|
||||||
|
Tooltip( message: "event name",
|
||||||
|
child: Container( height: 40, margin: const EdgeInsets.only(top: 5),
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 20),
|
||||||
|
child: TextFormField( key: formKeys[0],
|
||||||
|
initialValue: "${widget.item.schedulerState["service"] == true ? "" : "cron_"}${widget.item.scheduler["name"] ?? "${widget.item.name}_event"}",
|
||||||
|
onChanged: (value) {
|
||||||
|
widget.item.scheduler["name"] = value;
|
||||||
|
},
|
||||||
|
onSaved: (value) {
|
||||||
|
widget.item.scheduler["name"] = value ?? "${widget.item.schedulerState["service"] == true ? "" : "cron_"}${widget.item.scheduler["name"] ?? "${widget.item.name}_event"}";
|
||||||
|
},
|
||||||
|
validator: (value) => value == null || value.isEmpty ? "not empty" : null,
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: true,
|
||||||
|
hintText: "enter event name...",
|
||||||
|
labelText: "event name*",
|
||||||
|
errorStyle: TextStyle(fontSize: 0),
|
||||||
|
hintStyle: TextStyle(fontSize: 10),
|
||||||
|
labelStyle: TextStyle(fontSize: 10),
|
||||||
|
error: null,
|
||||||
|
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
|
||||||
|
border: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||||
|
),
|
||||||
|
))),
|
||||||
|
Tooltip( message: "start event",
|
||||||
|
child: Container( height: 40, margin: const EdgeInsets.only(top: 5),
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 20),
|
||||||
|
child: DateTimeField( key: formKeys[1],
|
||||||
|
resetIcon: const Icon(Icons.close, size: 15),
|
||||||
|
onSaved: (value) {
|
||||||
|
widget.item.scheduler["start"] = "${(value ?? DateTime.now()).toIso8601String()}Z";
|
||||||
|
},
|
||||||
|
onShowPicker: (context, currentValue) async {
|
||||||
|
var date = await showDatePicker(
|
||||||
|
builder: (BuildContext context, Widget? child) {
|
||||||
|
Widget w = Theme(
|
||||||
|
data: ThemeData(
|
||||||
|
cardTheme: CardTheme(elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0))),
|
||||||
|
dialogTheme: DialogTheme(elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0))),
|
||||||
|
colorScheme: ColorScheme.light(
|
||||||
|
background: Colors.grey.shade300,
|
||||||
|
tertiary: Colors.grey,
|
||||||
|
secondary: Colors.grey,
|
||||||
|
primary: Colors.black),
|
||||||
|
),
|
||||||
|
child: child ?? Container(),
|
||||||
|
);
|
||||||
|
return w;
|
||||||
|
},
|
||||||
|
context: context,
|
||||||
|
firstDate: DateTime(1900),
|
||||||
|
initialDate: DateTime.parse(widget.item.scheduler["start"] ?? currentValue?.toIso8601String() ?? ""),
|
||||||
|
lastDate: DateTime(2100)
|
||||||
|
);
|
||||||
|
if (date != null) {
|
||||||
|
var time = await showTimePicker(context: context,
|
||||||
|
initialTime: TimeOfDay(hour: date.hour, minute: date.minute),
|
||||||
|
builder: (BuildContext context, Widget? child) {
|
||||||
|
Widget w = Theme(
|
||||||
|
data: ThemeData(
|
||||||
|
cardTheme: CardTheme(elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0))),
|
||||||
|
dialogTheme: DialogTheme(elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0))),
|
||||||
|
colorScheme: ColorScheme.light(
|
||||||
|
background: Colors.grey.shade300,
|
||||||
|
tertiary: Colors.grey,
|
||||||
|
secondary: Colors.grey,
|
||||||
|
primary: Colors.black),
|
||||||
|
),
|
||||||
|
child: child ?? Container(),
|
||||||
|
);
|
||||||
|
return w;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
date = date.add(Duration(hours: time?.hour ?? 0, minutes: time?.minute ?? 0));
|
||||||
|
}
|
||||||
|
return date;
|
||||||
|
},
|
||||||
|
format: intl.DateFormat('y-M-dd hh:mm:ss'),
|
||||||
|
initialValue: DateTime.parse(widget.item.scheduler["start"] ?? DateTime.now().toIso8601String()),
|
||||||
|
onChanged: (value) {
|
||||||
|
widget.item.scheduler["start"] = "${(value ?? DateTime.now()).toIso8601String()}Z";
|
||||||
|
},
|
||||||
|
validator: (value) => value == null ? "not empty" : null,
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: true,
|
||||||
|
alignLabelWithHint: false,
|
||||||
|
hintText: "enter start event...",
|
||||||
|
labelText: "start event*",
|
||||||
|
errorStyle: TextStyle(fontSize: 0),
|
||||||
|
hintStyle: TextStyle(fontSize: 10),
|
||||||
|
labelStyle: TextStyle(fontSize: 10),
|
||||||
|
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
|
||||||
|
border: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||||
|
),
|
||||||
|
))),
|
||||||
|
Tooltip( message: "end event",
|
||||||
|
child: Container( height: 40, margin: const EdgeInsets.only(top: 5),
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 20),
|
||||||
|
child: DateTimeField( key: formKeys[2],
|
||||||
|
validator: (value) {
|
||||||
|
return value == null && !(widget.item.schedulerState["service"] == true ) ? "not empty" : null;
|
||||||
|
},
|
||||||
|
resetIcon: const Icon(Icons.close, size: 15),
|
||||||
|
onShowPicker: (context, currentValue) async {
|
||||||
|
var date = await showDatePicker(
|
||||||
|
builder: (BuildContext context, Widget? child) {
|
||||||
|
Widget w = Theme(
|
||||||
|
data: ThemeData(
|
||||||
|
cardTheme: CardTheme(elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0))),
|
||||||
|
dialogTheme: DialogTheme(elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0))),
|
||||||
|
colorScheme: ColorScheme.light(
|
||||||
|
background: Colors.grey.shade300,
|
||||||
|
tertiary: Colors.grey,
|
||||||
|
secondary: Colors.grey,
|
||||||
|
primary: Colors.black),
|
||||||
|
),
|
||||||
|
child: child ?? Container(),
|
||||||
|
);
|
||||||
|
return w;
|
||||||
|
},
|
||||||
|
context: context,
|
||||||
|
firstDate: DateTime(1900),
|
||||||
|
initialDate: DateTime.parse(widget.item.scheduler["start"] ?? currentValue?.toIso8601String() ?? ""),
|
||||||
|
lastDate: DateTime(2100)
|
||||||
|
);
|
||||||
|
if (date != null) {
|
||||||
|
var time = await showTimePicker(context: context,
|
||||||
|
initialTime: TimeOfDay(hour: date.hour, minute: date.minute),
|
||||||
|
builder: (BuildContext context, Widget? child) {
|
||||||
|
Widget w = Theme(
|
||||||
|
data: ThemeData(
|
||||||
|
cardTheme: CardTheme(elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0))),
|
||||||
|
dialogTheme: DialogTheme(elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0))),
|
||||||
|
colorScheme: ColorScheme.light(
|
||||||
|
background: Colors.grey.shade300,
|
||||||
|
tertiary: Colors.grey,
|
||||||
|
secondary: Colors.grey,
|
||||||
|
primary: Colors.black),
|
||||||
|
),
|
||||||
|
child: child ?? Container(),
|
||||||
|
);
|
||||||
|
return w;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
date = date.add(Duration(hours: time?.hour ?? 0, minutes: time?.minute ?? 0));
|
||||||
|
}
|
||||||
|
return date;
|
||||||
|
},
|
||||||
|
|
||||||
|
format: intl.DateFormat('y-M-dd hh:mm:ss'),
|
||||||
|
initialValue: widget.item.scheduler["end"] != null ? DateTime.parse(widget.item.scheduler["end"]!) : null,
|
||||||
|
onSaved: (value) {
|
||||||
|
if (value != null) {
|
||||||
|
widget.item.scheduler["end"] = "${(value).toIso8601String()}Z";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value == null) { return; }
|
||||||
|
widget.item.scheduler["end"] = "${value.toIso8601String()}Z";
|
||||||
|
},
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Colors.white,
|
||||||
|
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||||
|
filled: true,
|
||||||
|
alignLabelWithHint: false,
|
||||||
|
hintText: "enter end event...",
|
||||||
|
labelText: "end event${!(widget.item.schedulerState["service"] == true) ? "*" : ""}",
|
||||||
|
errorStyle: const TextStyle(fontSize: 0),
|
||||||
|
hintStyle: const TextStyle(fontSize: 10),
|
||||||
|
labelStyle: const TextStyle(fontSize: 10),
|
||||||
|
enabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
|
||||||
|
border: const OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||||
|
),
|
||||||
|
))),
|
||||||
|
widget.item.schedulerState["service"] == true ? Container() : Tooltip( message: "schedule",
|
||||||
|
child: Container( height: 40, margin: const EdgeInsets.only(top: 5),
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 20),
|
||||||
|
child: TextFormField( key: formKeys[3],
|
||||||
|
initialValue: widget.item.scheduler["cron"],
|
||||||
|
onChanged: (value) {
|
||||||
|
widget.item.scheduler["cron"] = value;
|
||||||
|
},
|
||||||
|
onSaved: (value) {
|
||||||
|
if (value != null) {
|
||||||
|
widget.item.scheduler["cron"] = value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
validator: (value) {
|
||||||
|
var cron = Cron();
|
||||||
|
try {
|
||||||
|
cron.schedule(Schedule.parse(value ?? ""), () {});
|
||||||
|
} catch (e) {
|
||||||
|
return "invalid cron";
|
||||||
|
}
|
||||||
|
return value == null || value.isEmpty ? "not empty" : null;
|
||||||
|
},
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: true,
|
||||||
|
hintText: "enter schedule...",
|
||||||
|
labelText: "schedule*",
|
||||||
|
errorStyle: TextStyle(fontSize: 0),
|
||||||
|
hintStyle: TextStyle(fontSize: 10),
|
||||||
|
labelStyle: TextStyle(fontSize: 10),
|
||||||
|
error: null,
|
||||||
|
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
|
||||||
|
border: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||||
|
),
|
||||||
|
))),
|
||||||
|
const Divider(color: Colors.grey),
|
||||||
|
Tooltip( message: "save",
|
||||||
|
child: InkWell( mouseCursor: SystemMouseCursors.click,
|
||||||
|
onTap: () {
|
||||||
|
for (var k in formKeys) {
|
||||||
|
if (k.currentState != null) {
|
||||||
|
if (!k.currentState!.validate()) {
|
||||||
|
return;
|
||||||
|
} else { k.currentState!.save();}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
widget.item.schedulerSave = true;
|
||||||
|
widget.item.save!(widget.item.id);
|
||||||
|
}, child: Container( margin: const EdgeInsets.all(10),
|
||||||
|
decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.black, width: 1)),
|
||||||
|
width: 140, height: 30,
|
||||||
|
child: const Icon(Icons.save_outlined, color: Colors.black),
|
||||||
|
))
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -25,14 +25,14 @@ class ItemRowWidgetState extends State<ItemRowWidget> {
|
|||||||
var endWidth = (itemWidth * ratio) + 80;
|
var endWidth = (itemWidth * ratio) + 80;
|
||||||
Image? image;
|
Image? image;
|
||||||
if (widget.item.logo != null) {
|
if (widget.item.logo != null) {
|
||||||
image = Image.memory(base64Decode(widget.item.logo ?? ""), width: imageSize, height: imageSize);
|
image = Image.network(widget.item.logo ?? "", width: imageSize, height: imageSize);
|
||||||
}
|
}
|
||||||
Widget w = Container(
|
Widget w = Container(
|
||||||
width: widget.contextWidth,
|
width: widget.contextWidth,
|
||||||
height: 100,
|
height: 100,
|
||||||
decoration: BoxDecoration( border: Border(bottom: BorderSide(color: Colors.grey.shade300)) ),
|
decoration: BoxDecoration( border: Border(bottom: BorderSide(color: Colors.grey.shade300)) ),
|
||||||
child: Row( children: [
|
child: Row( children: [
|
||||||
widget.low ? Container( padding: EdgeInsets.only(left: 10),) : Padding( padding: const EdgeInsets.all(10),
|
widget.low ? Container( padding: const EdgeInsets.only(left: 10),) : Padding( padding: const EdgeInsets.all(10),
|
||||||
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(
|
Container(
|
||||||
@ -51,7 +51,7 @@ class ItemRowWidgetState extends State<ItemRowWidget> {
|
|||||||
isStorage(widget.item.topic) ? Colors.red : Colors.grey,
|
isStorage(widget.item.topic) ? Colors.red : Colors.grey,
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
),
|
),
|
||||||
child: Text( MediaQuery.of(context).size.width < 600 ? "" : widget.item.type.toString(),
|
child: Text( MediaQuery.of(context).size.width < 600 ? "" : widget.item.topic.toString(),
|
||||||
style: const TextStyle(fontSize: 10, color: Colors.white, fontWeight: FontWeight.w600)),
|
style: const TextStyle(fontSize: 10, color: Colors.white, fontWeight: FontWeight.w600)),
|
||||||
),
|
),
|
||||||
Expanded( child: Text(widget.item.name?.toUpperCase() ?? "",
|
Expanded( child: Text(widget.item.name?.toUpperCase() ?? "",
|
||||||
@ -59,7 +59,7 @@ class ItemRowWidgetState extends State<ItemRowWidget> {
|
|||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
Text( "From ${widget.item.owner ?? "unknown owner"}",
|
Text( "From ${widget.item.owner ?? "unknown owner"}",
|
||||||
style: 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)),
|
||||||
],)
|
],)
|
||||||
)
|
)
|
||||||
|
@ -11,16 +11,13 @@ class DataItemWidgetState extends State<DataItemWidget> {
|
|||||||
@override Widget build(BuildContext context) {
|
@override Widget build(BuildContext context) {
|
||||||
return Wrap( children: [
|
return Wrap( children: [
|
||||||
Padding(padding: EdgeInsets.symmetric(vertical: 20, horizontal: 100),
|
Padding(padding: EdgeInsets.symmetric(vertical: 20, horizontal: 100),
|
||||||
child: Text("type : ${widget.item.dtype ?? "unknown type"}",
|
child: Text("type : ${widget.item.dataType ?? "unknown type"}",
|
||||||
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600))),
|
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600))),
|
||||||
Padding(padding: EdgeInsets.symmetric(horizontal: 100, vertical: 20),
|
Padding(padding: EdgeInsets.symmetric(horizontal: 100, vertical: 20),
|
||||||
child: Text("location : ${widget.item.location ?? "unknown location"}",
|
child: Text("protocol : ${widget.item.protocols.isEmpty ? "no protocol founded" : widget.item.protocols.join(",")}",
|
||||||
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600))),
|
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600))),
|
||||||
Padding(padding: EdgeInsets.symmetric(horizontal: 100, vertical: 20),
|
Padding(padding: EdgeInsets.symmetric(horizontal: 100, vertical: 20),
|
||||||
child: Text("protocol : ${widget.item.protocol.isEmpty ? "no protocol founded" : widget.item.protocol.join(",")}",
|
child: Text("ex : ${widget.item.exemple ?? "no example"}",
|
||||||
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600))),
|
|
||||||
Padding(padding: EdgeInsets.symmetric(horizontal: 100, vertical: 20),
|
|
||||||
child: Text("ex : ${widget.item.example ?? "no example"}",
|
|
||||||
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600))),
|
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600))),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
73
lib/widgets/logs.dart
Normal file
73
lib/widgets/logs.dart
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import 'package:alert_banner/exports.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:oc_front/models/logs.dart';
|
||||||
|
import 'package:oc_front/widgets/dialog/alert.dart';
|
||||||
|
|
||||||
|
class LogsWidget extends StatefulWidget {
|
||||||
|
final List<Log> items;
|
||||||
|
LogsWidget ({ Key? key, required this.items }): super(key: key);
|
||||||
|
@override LogsWidgetState createState() => LogsWidgetState();
|
||||||
|
}
|
||||||
|
class LogsWidgetState extends State<LogsWidget> {
|
||||||
|
@override Widget build(BuildContext context) {
|
||||||
|
List<LogWidget> itemRows = widget.items.map((e) => LogWidget(item: e)).toList();
|
||||||
|
return SingleChildScrollView( child: Column( children: itemRows ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LogWidget extends StatefulWidget {
|
||||||
|
final Log item;
|
||||||
|
bool expanded = false;
|
||||||
|
LogWidget ({ Key? key, required this.item }): super(key: key);
|
||||||
|
@override LogWidgetState createState() => LogWidgetState();
|
||||||
|
}
|
||||||
|
class LogWidgetState extends State<LogWidget> {
|
||||||
|
@override Widget build(BuildContext context) {
|
||||||
|
return Padding( padding: const EdgeInsets.only(top: 10, left: 30, right: 30), child: Wrap( children: [
|
||||||
|
Row( mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Container( width: 10, height: 15, color: widget.item.level?.toLowerCase() == "info" ? Colors.green :
|
||||||
|
( widget.item.level?.toLowerCase() == "error" ? Colors.red : (
|
||||||
|
widget.item.level?.toLowerCase() == "warning" ? Colors.orange : Colors.blue))),
|
||||||
|
InkWell( mouseCursor: widget.item.map.isEmpty ? MouseCursor.defer : SystemMouseCursors.click, onTap: () {
|
||||||
|
if (widget.item.map.isNotEmpty ) {
|
||||||
|
setState(() {
|
||||||
|
widget.expanded = !widget.expanded;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, child: Container( height: 20,
|
||||||
|
child: Padding( padding: EdgeInsets.symmetric(horizontal: widget.expanded ? 0 : 5),
|
||||||
|
child: Icon( widget.expanded ? Icons.keyboard_arrow_down_outlined : Icons.arrow_forward_ios, size: widget.expanded ? 25 : 15,
|
||||||
|
color: widget.item.map.isEmpty ? Colors.grey : Colors.black, weight: widget.expanded ? 100 : 1000,)))),
|
||||||
|
Padding( padding: const EdgeInsets.only(right: 10),
|
||||||
|
child: Text("${widget.item.timestamp?.toString()}",
|
||||||
|
style: const TextStyle(fontSize: 13, color: Colors.black, fontWeight: FontWeight.w500))),
|
||||||
|
Tooltip( message : "copy to clipboard", child: InkWell( child: const Icon(Icons.copy, size: 15, color: Colors.grey), onTap: () {
|
||||||
|
if (widget.item.message != null) {
|
||||||
|
Clipboard.setData(ClipboardData(text: widget.item.message!));
|
||||||
|
showAlertBanner(context, () {}, const InfoAlertBannerChild(text: "Copy to clipboard"), // <-- Put any widget here you want!
|
||||||
|
alertBannerLocation: AlertBannerLocation.bottom,);
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
]),
|
||||||
|
widget.expanded ? Container(
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 10),
|
||||||
|
decoration: BoxDecoration( color: Colors.grey,
|
||||||
|
borderRadius: BorderRadius.circular(4)),
|
||||||
|
padding: const EdgeInsets.all(10),
|
||||||
|
child: Column( children: widget.item.map.keys.map((e) =>
|
||||||
|
Padding( padding: const EdgeInsets.all(2), child: Row( mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [Flexible( child:Text("$e: \"${widget.item.map[e]}\"",
|
||||||
|
style: const TextStyle(fontSize: 11, color: Colors.white))), ])
|
||||||
|
)).toList()
|
||||||
|
)) : Container(),
|
||||||
|
Row( mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [Flexible( child:Text(widget.item.message ?? "unknown message",
|
||||||
|
style: const TextStyle(fontSize: 14, color: Colors.black))), ])
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
}
|
116
lib/widgets/menu_clipper/workspace_menu.dart
Normal file
116
lib/widgets/menu_clipper/workspace_menu.dart
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import 'dart:ffi';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:oc_front/core/models/workspace_local.dart';
|
||||||
|
class MenuWorkspaceWidget extends StatefulWidget {
|
||||||
|
bool simpliest = false;
|
||||||
|
double? width;
|
||||||
|
void Function()? onWorkspaceChange;
|
||||||
|
TextEditingController ctrl = TextEditingController();
|
||||||
|
MenuWorkspaceWidget ({ Key? key, this.simpliest = false, this.width, this.onWorkspaceChange }): super(key: key);
|
||||||
|
@override MenuWorkspaceWidgetState createState() => MenuWorkspaceWidgetState();
|
||||||
|
}
|
||||||
|
class MenuWorkspaceWidgetState extends State<MenuWorkspaceWidget> {
|
||||||
|
@override Widget build(BuildContext context) {
|
||||||
|
|
||||||
|
return Row( children: [
|
||||||
|
Tooltip( message: "current workspace", child:
|
||||||
|
Theme(
|
||||||
|
data: Theme.of(context).copyWith(
|
||||||
|
canvasColor: widget.simpliest ? Colors.grey.shade300 : Colors.grey,
|
||||||
|
),
|
||||||
|
child: Container( height: 50, width: widget.width ?? MediaQuery.of(context).size.width / ( widget.simpliest ? 1 : 2),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: widget.simpliest ? Colors.white : const Color.fromRGBO(38, 166, 154, 1),
|
||||||
|
border: Border(bottom: BorderSide(color: widget.simpliest ? Colors.grey.shade300 : Colors.transparent, width: 1))
|
||||||
|
),
|
||||||
|
padding: EdgeInsets.only(left: (widget.width ?? 400) < 400 ? 20 : 50, right: (widget.width ?? 400) < 400 ? 20 : 0),
|
||||||
|
child: DropdownButtonFormField(
|
||||||
|
value: WorkspaceLocal.getCurrentWorkspace()?.id,
|
||||||
|
isExpanded: true,
|
||||||
|
style: TextStyle(color: widget.simpliest ? Colors.black : Colors.white, fontSize: 15),
|
||||||
|
hint: Text("load workspace...", style: TextStyle(color: Colors.grey.shade300, fontSize: 15)),
|
||||||
|
icon: Icon( // Add this
|
||||||
|
Icons.arrow_drop_down, // Add this
|
||||||
|
color: widget.simpliest ? Colors.grey : Colors.white, // Add this
|
||||||
|
),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
filled: true,
|
||||||
|
prefixIconColor: widget.simpliest ? Colors.grey : Colors.white,
|
||||||
|
icon: Icon(Icons.shopping_cart, color: Colors.grey.shade300),
|
||||||
|
suffixIconColor: widget.simpliest ? Colors.grey : Colors.white,
|
||||||
|
focusedBorder: const OutlineInputBorder( borderRadius: BorderRadius.zero,
|
||||||
|
borderSide: BorderSide(color: Colors.transparent, width: 0),
|
||||||
|
),
|
||||||
|
fillColor: widget.simpliest ? Colors.white : const Color.fromRGBO(38, 166, 154, 1),
|
||||||
|
contentPadding: EdgeInsets.only(left: (widget.width ?? 400) < 400 ? 0 : 30, right: (widget.width ?? 400) < 400 ? 0 : 30, top: 10, bottom: 30),
|
||||||
|
enabledBorder: const OutlineInputBorder( borderRadius: BorderRadius.zero,
|
||||||
|
borderSide: BorderSide(color: Colors.transparent, width: 0),
|
||||||
|
),
|
||||||
|
border: const OutlineInputBorder( borderRadius: BorderRadius.zero,
|
||||||
|
borderSide: BorderSide(color: Colors.transparent, width: 0)),
|
||||||
|
),
|
||||||
|
items: WorkspaceLocal.getWorkspacesIDS().map((e) => DropdownMenuItem(
|
||||||
|
value: e.id,child: Text(e.name ?? ""),)).toList(),
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
WorkspaceLocal.changeWorkspace(value.toString());
|
||||||
|
if (widget.onWorkspaceChange != null) {
|
||||||
|
widget.onWorkspaceChange!();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})))),
|
||||||
|
widget.simpliest ? Container() : Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: (MediaQuery.of(context).size.width / 2) - 50,
|
||||||
|
height: 50,
|
||||||
|
decoration: const BoxDecoration(border: Border(left: BorderSide(color: Colors.white))),
|
||||||
|
child: TextFormField(
|
||||||
|
expands: true,
|
||||||
|
maxLines: null,
|
||||||
|
minLines: null,
|
||||||
|
style: const TextStyle(color: Colors.white, fontSize: 15),
|
||||||
|
cursorColor: const Color.fromARGB(38, 166, 154, 1),
|
||||||
|
controller: widget.ctrl,
|
||||||
|
onChanged: (value) { setState(() { }); },
|
||||||
|
validator: (value) => value == null || value.isEmpty ? "name is required" : null,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: "name a new workspace...",
|
||||||
|
fillColor: const Color.fromRGBO(38, 166, 154, 1),
|
||||||
|
filled: true,
|
||||||
|
contentPadding: const EdgeInsets.only(left: 30, right: 30, top: 15, bottom: 5),
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
color: Colors.grey.shade300,
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: FontWeight.w400
|
||||||
|
),
|
||||||
|
border: InputBorder.none
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Tooltip(
|
||||||
|
message: 'add',
|
||||||
|
child:InkWell(
|
||||||
|
mouseCursor: widget.ctrl.value.text.isEmpty ? MouseCursor.defer : SystemMouseCursors.click,
|
||||||
|
onTap: () async {
|
||||||
|
if (widget.ctrl.value.text.isNotEmpty) {
|
||||||
|
WorkspaceLocal.createWorkspace(widget.ctrl.value.text, context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
color: Colors.black,
|
||||||
|
child: Icon(Icons.add, color: widget.ctrl.value.text.isEmpty ? Colors.grey : Colors.white)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
179
lib/widgets/sheduler_items/schedule.dart
Normal file
179
lib/widgets/sheduler_items/schedule.dart
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:oc_front/core/sections/header/header.dart';
|
||||||
|
import 'package:oc_front/core/services/specialized_services/logs_service.dart';
|
||||||
|
import 'package:oc_front/models/logs.dart';
|
||||||
|
import 'package:oc_front/models/workflow.dart';
|
||||||
|
import 'package:oc_front/widgets/logs.dart';
|
||||||
|
import 'package:oc_front/widgets/sheduler_items/scheduler_calendar.dart';
|
||||||
|
import 'package:oc_front/widgets/sheduler_items/scheduler_item.dart';
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class ScheduleWidget extends StatefulWidget {
|
||||||
|
DateTime start;
|
||||||
|
DateTime end;
|
||||||
|
bool isDayPlanner = true;
|
||||||
|
Map<String, List<WorkflowExecution>> data;
|
||||||
|
bool isList = true;
|
||||||
|
ScheduleWidget ({ super.key, required this.data, required this.start, required this.end, this.isList = true });
|
||||||
|
@override ScheduleWidgetState createState() => ScheduleWidgetState();
|
||||||
|
}
|
||||||
|
class ScheduleWidgetState extends State<ScheduleWidget> {
|
||||||
|
LogsService _service = LogsService();
|
||||||
|
String? selected;
|
||||||
|
String? selectedReal;
|
||||||
|
List<Color> colors = [Colors.blue, Colors.orange, Colors.red, Colors.green];
|
||||||
|
List<String> titles = ["SCHEDULED", "RUNNING", "FAILURE", "SUCCESS"];
|
||||||
|
|
||||||
|
DateTime getFocusedDay() {
|
||||||
|
if (selected != null) { return DateTime.parse(selected!); }
|
||||||
|
return DateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override Widget build(BuildContext context) {
|
||||||
|
bool isInfo = MediaQuery.of(context).size.width <= 600 && selected != null;
|
||||||
|
double w = selected != null ? MediaQuery.of(context).size.width - 300 : MediaQuery.of(context).size.width;
|
||||||
|
List<Widget> children = [];
|
||||||
|
if (selected != null) {
|
||||||
|
for (var wf in widget.data[selected!] ?? (<WorkflowExecution>[])) {
|
||||||
|
DateTime d2 = DateTime.parse(wf.executionData!);
|
||||||
|
children.add( InkWell(
|
||||||
|
onTap: () => setState(() { selectedReal = wf.executionData; }),
|
||||||
|
child: Container( margin: const EdgeInsets.all(10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: selectedReal != null && selectedReal == wf.executionData ? const Color.fromRGBO(38, 166, 154, 1) : Colors.transparent, width: 2),
|
||||||
|
borderRadius: BorderRadius.circular(4), color: Colors.white
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
|
||||||
|
child: Row(children: [
|
||||||
|
Container( width: 10, height: 10,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: colors[(wf.status ?? 1) - 1],
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container( width: (400 - 250),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 20),
|
||||||
|
child: Text(wf.name?.toUpperCase() ?? "", overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(color: Colors.black, fontSize: 12, fontWeight: FontWeight.w500)),
|
||||||
|
)),
|
||||||
|
Container(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 20),
|
||||||
|
child: Text("${d2.hour > 9 ? d2.hour : "0${d2.hour}"}:${d2.minute > 9 ? d2.minute : "0${d2.minute}"}", overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(fontSize: 15,
|
||||||
|
color: Colors.grey, fontWeight: FontWeight.w500))))
|
||||||
|
])
|
||||||
|
))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
String? selectedID;
|
||||||
|
String? start;
|
||||||
|
String? end;
|
||||||
|
if (selectedReal != null) {
|
||||||
|
try {
|
||||||
|
var sel = widget.data[selected!]!.firstWhere((element) => element.executionData == selectedReal);
|
||||||
|
selectedID = sel.id;
|
||||||
|
print(sel.endDate);
|
||||||
|
if (sel.endDate != null && sel.endDate != "") {
|
||||||
|
var startD = DateTime.parse(sel.executionData!);
|
||||||
|
var endD = DateTime.parse(sel.endDate!);
|
||||||
|
var diff = endD.difference(startD);
|
||||||
|
if (diff.inDays < 30) {
|
||||||
|
var rest = ((30 - diff.inDays) ~/ 2) - 1;
|
||||||
|
start = (startD.subtract(Duration(days: rest)).microsecondsSinceEpoch).toString();
|
||||||
|
end = (endD.add(Duration(days: rest)).microsecondsSinceEpoch).toString();
|
||||||
|
} else {
|
||||||
|
start = (startD.microsecondsSinceEpoch).toString();
|
||||||
|
end = (startD.add( const Duration(days: 29)).microsecondsSinceEpoch).toString();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
start = (DateTime.parse(sel.executionData!).subtract( const Duration(days: 14)).microsecondsSinceEpoch).toString();
|
||||||
|
end = (DateTime.parse(sel.executionData!).add( const Duration(days: 14)).microsecondsSinceEpoch).toString();
|
||||||
|
}
|
||||||
|
} catch(e) { /* */ }
|
||||||
|
}
|
||||||
|
return Row( children: [
|
||||||
|
isInfo ? Container() : SizedBox( width: w,
|
||||||
|
child: widget.isList ? SchedulerItemWidget(data: widget.data, parent: this, focusedDay: getFocusedDay(), width: w)
|
||||||
|
: SchedulerCalendarWidget(data: widget.data, start: widget.start,
|
||||||
|
end: widget.end, parent: this, focusedDay: getFocusedDay(),)
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: MediaQuery.of(context).size.height - HeaderConstants.height - 50,
|
||||||
|
width: isInfo ? MediaQuery.of(context).size.width : (selected != null ? 300 : 0),
|
||||||
|
color: Colors.grey.shade300,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row( children: [
|
||||||
|
InkWell( onTap: () => setState(() { widget.isDayPlanner = true; }),
|
||||||
|
child: Tooltip( message: "day planning", child:
|
||||||
|
Container( height: 50, width: (isInfo ? MediaQuery.of(context).size.width : (selected != null ? 300 : 0)) / (selectedReal != null ? 2 : 1 ),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: widget.isDayPlanner ? Colors.grey : Colors.transparent,
|
||||||
|
border: Border(bottom: BorderSide(color: Colors.grey.shade400), right: BorderSide(color: Colors.grey.shade400))),
|
||||||
|
child: Icon(Icons.calendar_today_outlined, color: widget.isDayPlanner ? Colors.white : Colors.grey),
|
||||||
|
)
|
||||||
|
)),
|
||||||
|
InkWell( onTap: () => setState(() { widget.isDayPlanner = false; }),
|
||||||
|
child: Tooltip( message: "monitor task", child:
|
||||||
|
Container( height: 50, width: selectedReal == null ? 0 : ((isInfo ? MediaQuery.of(context).size.width : (selected != null ? 300 : 0)) / 2),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: !widget.isDayPlanner ? Colors.grey : Colors.transparent,
|
||||||
|
border: Border(bottom: BorderSide(color: Colors.grey.shade400))
|
||||||
|
),
|
||||||
|
child: Icon(Icons.monitor_heart_outlined, size: 25,
|
||||||
|
color: !widget.isDayPlanner ? Colors.white : Colors.grey),
|
||||||
|
)
|
||||||
|
))
|
||||||
|
]),
|
||||||
|
Container( width: isInfo ? MediaQuery.of(context).size.width : (selected != null ? 300 : 0), height: MediaQuery.of(context).size.height - HeaderConstants.height - 100,
|
||||||
|
child: SingleChildScrollView( child: Column(
|
||||||
|
mainAxisAlignment: children.isEmpty ? MainAxisAlignment.center : MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
...( widget.isDayPlanner ? children : ( selectedID != null ? [
|
||||||
|
FutureBuilder(future: _service.search(context, [], {
|
||||||
|
"workflow_execution_id": selectedID,
|
||||||
|
"start": start,
|
||||||
|
"end": end
|
||||||
|
}), builder: (ctx, as) {
|
||||||
|
var speLog = Log(level: "error", timestamp: DateTime.now());
|
||||||
|
speLog.getMessage("{\"Name\":\"oc-monitor-unonip-fauta9hswg\",\"Namespace\":\"argo\",\"Status\":\"Pending\",\"PodRunning\":false,\"Completed\":false,\"Created\":\"Tue Aug 06 11:33:52 +0200 (now)\",\"Started\":\"\",\"Duration\":\"\",\"Progress\":\"\"}");
|
||||||
|
var speLog2 = Log(level: "warning", timestamp: DateTime.now());
|
||||||
|
speLog2.getMessage("{\"Name\":\"oc-monitor-unonip-fauta9hswg\",\"Namespace\":\"argo\",\"Status\":\"Running\",\"PodRunning\":false,\"Completed\":false,\"Created\":\"Tue Aug 06 11:33:52 +0200 (now)\",\"Started\":\"Tue Aug 06 11:33:52 +0200 (now)\",\"Duration\":\"0 seconds\",\"Progress\":\"0/1\"}");
|
||||||
|
List<Log> logs = [
|
||||||
|
Log(
|
||||||
|
level: "info",
|
||||||
|
message: "No logs found",
|
||||||
|
timestamp: DateTime.now()
|
||||||
|
),
|
||||||
|
speLog,
|
||||||
|
speLog2
|
||||||
|
];
|
||||||
|
if (as.hasData && as.data!.data != null) {
|
||||||
|
var d = as.data!.data!;
|
||||||
|
for( var r in d.data?.result ?? <Logs> []) {
|
||||||
|
for (var element in r.logs) {
|
||||||
|
element.level = r.level;
|
||||||
|
logs.add(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logs.sort((a, b) => a.timestamp!.compareTo(b.timestamp!));
|
||||||
|
return LogsWidget(items: logs);
|
||||||
|
})
|
||||||
|
] : [])),
|
||||||
|
children.isEmpty ? Container( height: 100, alignment: Alignment.center, child: const Text("No event found", style: const TextStyle(color: Colors.grey, fontSize: 20))) : Container()
|
||||||
|
]))
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
175
lib/widgets/sheduler_items/scheduler_calendar.dart
Normal file
175
lib/widgets/sheduler_items/scheduler_calendar.dart
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:oc_front/core/sections/header/header.dart';
|
||||||
|
import 'package:oc_front/models/workflow.dart';
|
||||||
|
import 'package:oc_front/widgets/sheduler_items/schedule.dart';
|
||||||
|
import 'package:table_calendar/table_calendar.dart';
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class SchedulerCalendarWidget extends StatefulWidget {
|
||||||
|
Map<String, List<WorkflowExecution>> data;
|
||||||
|
DateTime start;
|
||||||
|
DateTime end;
|
||||||
|
DateTime focusedDay;
|
||||||
|
CalendarFormat format = CalendarFormat.month;
|
||||||
|
bool enabled = true;
|
||||||
|
ScheduleWidgetState? parent;
|
||||||
|
SchedulerCalendarWidget ({ super.key,
|
||||||
|
required this.data,
|
||||||
|
required this.start,
|
||||||
|
required this.end,
|
||||||
|
required this.parent,
|
||||||
|
required this.focusedDay,
|
||||||
|
this.enabled = true});
|
||||||
|
@override SchedulerCalendarWidgetState createState() => SchedulerCalendarWidgetState();
|
||||||
|
}
|
||||||
|
class SchedulerCalendarWidgetState extends State<SchedulerCalendarWidget> {
|
||||||
|
List<Color> colors = [Colors.blue, Colors.orange, Colors.red, Colors.green];
|
||||||
|
List<String> titles = ["SCHEDULED", "RUNNING", "FAILURE", "SUCCESS"];
|
||||||
|
bool isEvent(Map<String, List<WorkflowExecution>> data, DateTime day) {
|
||||||
|
if (data[day.toIso8601String()] == null || data[day.toIso8601String()]!.isEmpty) { return false; }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@override Widget build(BuildContext context) {
|
||||||
|
widget.focusedDay = widget.focusedDay.isBefore(widget.start) ? widget.start : (
|
||||||
|
widget.focusedDay.isAfter(widget.end) ? widget.end : widget.focusedDay );
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20),
|
||||||
|
height: MediaQuery.of(context).size.height - HeaderConstants.height - 50,
|
||||||
|
child: TableCalendar<Event>(
|
||||||
|
firstDay: widget.start,
|
||||||
|
lastDay: widget.end,
|
||||||
|
focusedDay: widget.focusedDay,
|
||||||
|
calendarStyle: const CalendarStyle(
|
||||||
|
markersMaxCount: 3,
|
||||||
|
markersAnchor: 0,
|
||||||
|
markersAlignment: Alignment.topCenter
|
||||||
|
),
|
||||||
|
selectedDayPredicate: (day) => day == widget.focusedDay,
|
||||||
|
calendarFormat: widget.format,
|
||||||
|
calendarBuilders: CalendarBuilders(
|
||||||
|
markerBuilder: (context, day, events) {
|
||||||
|
List<Widget> children = [];
|
||||||
|
for (var ev in events) {
|
||||||
|
if (children.length == 2 && events.length > 3) {
|
||||||
|
children.add( InkWell( onTap: () => widget.parent!.setState(() {
|
||||||
|
widget.parent!.selected = day.toIso8601String();
|
||||||
|
widget.parent!.selectedReal = null;
|
||||||
|
widget.parent!.widget.isDayPlanner = true;
|
||||||
|
}),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 2),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
color: Colors.grey.shade300,
|
||||||
|
),
|
||||||
|
child: const Text("...", style: TextStyle(color: Colors.white, fontSize: 10)),
|
||||||
|
)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
children.add(InkWell( onTap: () => widget.parent!.setState(() {
|
||||||
|
widget.parent!.selected = day.toIso8601String();
|
||||||
|
widget.parent!.selectedReal = ev.executionData;
|
||||||
|
if (widget.parent!.selectedReal == null) {
|
||||||
|
widget.parent!.widget.isDayPlanner = true;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 2),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
color: ev.color,
|
||||||
|
),
|
||||||
|
child: Text(ev.title.length < 30 ? ev.title : "${ev.title.substring(0, 28)}...", style: const TextStyle(color: Colors.white, fontSize: 10)),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
return Column(mainAxisAlignment: MainAxisAlignment.center, children: children);
|
||||||
|
},
|
||||||
|
defaultBuilder: (context, date, events) => Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
margin:const EdgeInsets.all(2.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: Colors.grey.shade300),
|
||||||
|
shape: BoxShape.rectangle,
|
||||||
|
),
|
||||||
|
child: !isEvent(widget.data, date) ? Text(
|
||||||
|
date.day.toString(),
|
||||||
|
style: const TextStyle(color: Colors.grey),
|
||||||
|
) : Column( children: [ Container( padding: const EdgeInsets.symmetric(vertical: 5), child: Text(
|
||||||
|
date.day.toString(),
|
||||||
|
style: const TextStyle(color: Colors.grey),
|
||||||
|
)) ])
|
||||||
|
),
|
||||||
|
outsideBuilder: (context, day, focusedDay) => Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
margin: const EdgeInsets.all(2.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: Colors.grey.shade300),
|
||||||
|
color: Colors.grey.shade300,
|
||||||
|
shape: BoxShape.rectangle,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
day.day.toString(),
|
||||||
|
style: const TextStyle(color: Colors.black),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
selectedBuilder: (context, date, events) => Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
margin: const EdgeInsets.all(2.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: const Color.fromRGBO(38, 166, 154, 1), width: 2),
|
||||||
|
shape: BoxShape.rectangle,
|
||||||
|
),
|
||||||
|
child: !isEvent(widget.data, date) ? Text(
|
||||||
|
date.day.toString(),
|
||||||
|
style: const TextStyle(color: Colors.grey),
|
||||||
|
) : Column( children: [ Container( padding: const EdgeInsets.symmetric(vertical: 5), child: Text(
|
||||||
|
date.day.toString(),
|
||||||
|
style: const TextStyle(color: Colors.grey),
|
||||||
|
)) ]),
|
||||||
|
),
|
||||||
|
todayBuilder: (context, date, events) => Container(
|
||||||
|
margin: const EdgeInsets.all(2.0),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: const Color.fromRGBO(38, 166, 154, .5),
|
||||||
|
shape: BoxShape.rectangle,
|
||||||
|
border: Border.all(color: Colors.grey),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
date.day.toString(),
|
||||||
|
style: const TextStyle(color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onFormatChanged: (format) => setState(() {
|
||||||
|
widget.format = format;
|
||||||
|
}),
|
||||||
|
onDaySelected: (selectedDay, focusedDay) {
|
||||||
|
widget.parent!.setState(() {
|
||||||
|
widget.parent!.selected = selectedDay.toIso8601String();
|
||||||
|
widget.parent!.selectedReal = null;
|
||||||
|
widget.parent!.widget.isDayPlanner = true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
shouldFillViewport: true,
|
||||||
|
eventLoader: (day) {
|
||||||
|
return widget.data[day.toIso8601String()] != null ? widget.data[day.toIso8601String()]!.map((e) {
|
||||||
|
DateTime dateTime = DateTime.parse(e.executionData!);
|
||||||
|
return Event("[${dateTime.hour > 9 ? dateTime.hour : "0${dateTime.hour}"}:${dateTime.minute > 9 ? dateTime.minute : "0${dateTime.minute}"}] ${e.name}",
|
||||||
|
colors[(e.status ?? 1) - 1], e.executionData );
|
||||||
|
}).toList() : [];
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Event {
|
||||||
|
final String title;
|
||||||
|
String? executionData;
|
||||||
|
Color color;
|
||||||
|
|
||||||
|
Event(this.title, this.color, this.executionData);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => title;
|
||||||
|
}
|
115
lib/widgets/sheduler_items/scheduler_item.dart
Normal file
115
lib/widgets/sheduler_items/scheduler_item.dart
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:oc_front/core/sections/header/header.dart';
|
||||||
|
import 'package:oc_front/models/workflow.dart';
|
||||||
|
import 'package:oc_front/widgets/sheduler_items/schedule.dart';
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class SchedulerItemWidget extends StatefulWidget {
|
||||||
|
Map<String, List<WorkflowExecution>> data;
|
||||||
|
bool enabled = true;
|
||||||
|
DateTime focusedDay;
|
||||||
|
double width = 0;
|
||||||
|
ScheduleWidgetState? parent;
|
||||||
|
Map<String, GlobalKey> keys = {};
|
||||||
|
SchedulerItemWidget ({ super.key, required this.data, required this.focusedDay,
|
||||||
|
this.enabled = true, required this.parent, this.width = 0});
|
||||||
|
@override SchedulerItemWidgetState createState() => SchedulerItemWidgetState();
|
||||||
|
}
|
||||||
|
class SchedulerItemWidgetState extends State<SchedulerItemWidget> {
|
||||||
|
List<Color> colors = [Colors.blue, Colors.orange, Colors.red, Colors.green];
|
||||||
|
List<String> titles = ["SCHEDULED", "RUNNING", "FAILURE", "SUCCESS"];
|
||||||
|
|
||||||
|
@override Widget build(BuildContext context) {
|
||||||
|
List<Widget> children = [];
|
||||||
|
for (var element in widget.data.keys.toList()..sort((a, b) => DateTime.parse(a).compareTo(DateTime.parse(b)))) {
|
||||||
|
List<Widget> widgets = [];
|
||||||
|
for (var ev in widget.data[element] ?? ([] as List<WorkflowExecution>)) {
|
||||||
|
widget.keys[ev.executionData!] = GlobalKey();
|
||||||
|
var d2 = DateTime.parse(ev.executionData!);
|
||||||
|
DateTime? d3;
|
||||||
|
try {
|
||||||
|
d3 = DateTime.parse(ev.endDate!);
|
||||||
|
} catch (e) { /* */ }
|
||||||
|
widgets.add(InkWell(
|
||||||
|
onTap: () => widget.parent?.setState(() {
|
||||||
|
widget.parent?.selected = widget.parent?.selected != element ? element : null;
|
||||||
|
widget.parent?.selectedReal = widget.parent?.selected == null ? null : ev.executionData;
|
||||||
|
if (widget.parent!.selectedReal == null) {
|
||||||
|
widget.parent!.widget.isDayPlanner = true;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
child: Container( key: widget.keys[ev.executionData!],
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 50),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: widget.parent?.selected == element ? Border.all(color: const Color.fromRGBO(38, 166, 154, 1), width: 2)
|
||||||
|
: Border(top: BorderSide(color: Colors.grey.shade300)),
|
||||||
|
),
|
||||||
|
child: Row(children: [
|
||||||
|
Container( width: 110,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: colors[(ev.status ?? 1) - 1],
|
||||||
|
borderRadius: BorderRadius.circular(4),
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5),
|
||||||
|
child: Text(titles[(ev.status ?? 1) - 1],
|
||||||
|
overflow: TextOverflow.ellipsis, textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle( color: Colors.white))
|
||||||
|
),
|
||||||
|
SizedBox( width: (widget.width - 312) / 2,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 20),
|
||||||
|
child: Text(ev.name?.toUpperCase() ?? "", overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w500)),
|
||||||
|
)),
|
||||||
|
SizedBox( width: (widget.width - 312) / 2,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 20),
|
||||||
|
child: Container( padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||||
|
child: Text(d3 != null ? "killed at ${d3.day}/${d3.month}/${d3.year} ${d3.hour}:${d3.minute}"
|
||||||
|
: "infinite run till process end", overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle( fontSize: 12, color: Colors.grey, fontWeight: FontWeight.w500))),
|
||||||
|
)),
|
||||||
|
SizedBox(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 20),
|
||||||
|
child: Text("${d2.hour > 9 ? d2.hour : "0${d2.hour}"}:${d2.minute > 9 ? d2.minute : "0${d2.minute}"}", overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(fontSize: 25,
|
||||||
|
color: Colors.grey, fontWeight: FontWeight.w500))))
|
||||||
|
])
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
var date = DateTime.parse(element);
|
||||||
|
children.add(Column( children: [Container(
|
||||||
|
child: ExpansionTile(
|
||||||
|
enabled: widget.enabled,
|
||||||
|
shape: ContinuousRectangleBorder(),
|
||||||
|
iconColor: Colors.grey,
|
||||||
|
initiallyExpanded: true,
|
||||||
|
title: SizedBox(
|
||||||
|
child : Row( children: [
|
||||||
|
const Padding(padding: EdgeInsets.only(right: 10),
|
||||||
|
child: Icon(Icons.view_day, color: Colors.grey)),
|
||||||
|
Flexible(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 5),
|
||||||
|
child: Text("${date.day > 9 ? date.day : "0${date.day}"}-${date.hour > 9 ? date.hour : "0${date.hour}"}-${date.year}".toUpperCase(), overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w500))))
|
||||||
|
])
|
||||||
|
),
|
||||||
|
collapsedIconColor: Colors.grey,
|
||||||
|
children: widgets,
|
||||||
|
)),
|
||||||
|
Divider(color: Colors.grey.shade300, height: 1)
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
Future.delayed( const Duration(milliseconds: 100), () {
|
||||||
|
if (widget.parent?.selectedReal != null) {
|
||||||
|
widget.keys[widget.parent!.selectedReal!]?.currentContext?.findRenderObject()?.showOnScreen();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return SingleChildScrollView( child: Container(
|
||||||
|
height: MediaQuery.of(context).size.height - HeaderConstants.height - 50,
|
||||||
|
child: Column( children: children))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
export 'src/ui/draw_arrow.dart' show ArrowParams, ArrowStyle, ArrowDirection;
|
||||||
export 'src/ui/grid_background.dart' show GridBackgroundParams;
|
export 'src/ui/grid_background.dart' show GridBackgroundParams;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:flutter_flow_chart/src/flow_chart_left_menu.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
@ -23,10 +24,15 @@ typedef ConnectionListener = void Function(
|
|||||||
//
|
//
|
||||||
class Dashboard extends ChangeNotifier {
|
class Dashboard extends ChangeNotifier {
|
||||||
GlobalKey<FlowChartSelectedMenuState> selectedMenuKey = GlobalKey<FlowChartSelectedMenuState>();
|
GlobalKey<FlowChartSelectedMenuState> selectedMenuKey = GlobalKey<FlowChartSelectedMenuState>();
|
||||||
|
GlobalKey<FlowChartLeftMenuState> selectedLeftMenuKey = GlobalKey<FlowChartLeftMenuState>();
|
||||||
GlobalKey<FlowChartMenuState> chartMenuKey = GlobalKey<FlowChartMenuState>();
|
GlobalKey<FlowChartMenuState> chartMenuKey = GlobalKey<FlowChartMenuState>();
|
||||||
GlobalKey<ChartWidgetState> chartKey = GlobalKey<ChartWidgetState>();
|
GlobalKey<ChartWidgetState> chartKey = GlobalKey<ChartWidgetState>();
|
||||||
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, bool> schedulerState = {};
|
||||||
|
bool schedulerSave = false;
|
||||||
|
String? id;
|
||||||
String name;
|
String name;
|
||||||
String defaultName = "";
|
String defaultName = "";
|
||||||
bool isMenu = true;
|
bool isMenu = true;
|
||||||
@ -39,11 +45,17 @@ class Dashboard extends ChangeNotifier {
|
|||||||
double defaultDashWidth = 0;
|
double defaultDashWidth = 0;
|
||||||
double defaultBackWidth = 10;
|
double defaultBackWidth = 10;
|
||||||
double defaultForwardWidth = 10;
|
double defaultForwardWidth = 10;
|
||||||
final void Function()? save;
|
Future<void> Function(String? id)? save;
|
||||||
|
List<Widget> Function(FlowData? obj)? infoItemWidget;
|
||||||
|
List<Widget> Function()? infoWidget;
|
||||||
|
FlowData? Function(Map<String, dynamic> json)? transformToData;
|
||||||
///
|
///
|
||||||
Dashboard({
|
Dashboard({
|
||||||
|
this.id,
|
||||||
|
this.transformToData,
|
||||||
required this.name,
|
required this.name,
|
||||||
this.save,
|
this.save,
|
||||||
|
this.scheduler = const {},
|
||||||
Offset? handlerFeedbackOffset,
|
Offset? handlerFeedbackOffset,
|
||||||
this.isMenu = true,
|
this.isMenu = true,
|
||||||
this.defaultDashSpace = 0,
|
this.defaultDashSpace = 0,
|
||||||
@ -53,6 +65,8 @@ class Dashboard extends ChangeNotifier {
|
|||||||
this.defaultArrowDirection = ArrowDirection.forward,
|
this.defaultArrowDirection = ArrowDirection.forward,
|
||||||
this.defaultArrowStyle = ArrowStyle.curve,
|
this.defaultArrowStyle = ArrowStyle.curve,
|
||||||
this.loadedGraph,
|
this.loadedGraph,
|
||||||
|
this.infoWidget,
|
||||||
|
this.load,
|
||||||
}) : elements = [],
|
}) : elements = [],
|
||||||
_dashboardPosition = Offset.zero,
|
_dashboardPosition = Offset.zero,
|
||||||
dashboardSize = Size.zero,
|
dashboardSize = Size.zero,
|
||||||
@ -80,25 +94,28 @@ class Dashboard extends ChangeNotifier {
|
|||||||
addToHistory();
|
addToHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> Function(String cat)? load;
|
||||||
|
|
||||||
///
|
///
|
||||||
factory Dashboard.fromMap(Map<String, dynamic> map) {
|
factory Dashboard.fromMap(Map<String, dynamic> map) {
|
||||||
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],
|
||||||
)
|
);
|
||||||
..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>),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
..elements = List<FlowElement>.from(
|
..elements = List<FlowElement>.from(
|
||||||
(map['elements'] as List<dynamic>).map<FlowElement>(
|
(map['elements'] as List<dynamic>).map<FlowElement>(
|
||||||
(x) => FlowElement.fromMap(x as Map<String, dynamic>),
|
(x) => FlowElement.fromMap(d, x as Map<String, dynamic>),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
..dashboardSize = Size(
|
..dashboardSize = Size(
|
||||||
@ -120,6 +137,7 @@ class Dashboard extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void copyFromMap(Map<String, dynamic> map) {
|
void copyFromMap(Map<String, dynamic> map) {
|
||||||
|
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;
|
||||||
@ -132,7 +150,7 @@ class Dashboard extends ChangeNotifier {
|
|||||||
);
|
);
|
||||||
elements = List<FlowElement>.from(
|
elements = List<FlowElement>.from(
|
||||||
(map['elements'] as List<dynamic>).map<FlowElement>(
|
(map['elements'] as List<dynamic>).map<FlowElement>(
|
||||||
(x) => FlowElement.fromMap(x as Map<String, dynamic>),
|
(x) => FlowElement.fromMap(this, x as Map<String, dynamic>),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
dashboardSize = Size(
|
dashboardSize = Size(
|
||||||
@ -148,7 +166,6 @@ class Dashboard extends ChangeNotifier {
|
|||||||
blockDefaultZoomGestures =
|
blockDefaultZoomGestures =
|
||||||
(map['blockDefaultZoomGestures'] as bool? ?? false);
|
(map['blockDefaultZoomGestures'] as bool? ?? false);
|
||||||
minimumZoomFactor = map['minimumZoomFactor'] as double? ?? 0.25;
|
minimumZoomFactor = map['minimumZoomFactor'] as double? ?? 0.25;
|
||||||
if (save != null) { save!(); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -194,22 +211,34 @@ class Dashboard extends ChangeNotifier {
|
|||||||
final List<ConnectionListener> _connectionListeners = [];
|
final List<ConnectionListener> _connectionListeners = [];
|
||||||
|
|
||||||
Map<String, dynamic> serialize() {
|
Map<String, dynamic> serialize() {
|
||||||
|
Map<String, dynamic> d = {};
|
||||||
Map<String, dynamic> graph = {};
|
Map<String, dynamic> graph = {};
|
||||||
|
graph['zoom'] = getZoomFactor();
|
||||||
graph['elements'] = {};
|
graph['elements'] = {};
|
||||||
for(var el in elements) {
|
for(var el in elements) {
|
||||||
graph['elements'][el.id] = el.serialize();
|
graph['elements'][el.id] = el.serialize();
|
||||||
}
|
}
|
||||||
graph['arrows'] = arrows.map((e) => e.serialize()).toList();
|
graph['arrows'] = arrows.map((e) => e.serialize()).toList();
|
||||||
return graph;
|
d["id"]=id;
|
||||||
|
d["name"]=name;
|
||||||
|
d["graph"]=graph;
|
||||||
|
if (schedulerSave) {
|
||||||
|
d["schedule"]=scheduler;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deserialize(Map<String, dynamic> graph) {
|
void deserialize(Map<String, dynamic> graph) {
|
||||||
elements.clear();
|
elements = [];
|
||||||
arrows.clear();
|
arrows = [];
|
||||||
for(var el in graph['elements'].values) {
|
print(graph['schedule']);
|
||||||
|
scheduler = graph['schedule'] ?? {};
|
||||||
|
setZoomFactor(graph["graph"]?["zoom"] ?? 1.0);
|
||||||
|
for(var el in graph['graph']?['elements'] ?? []) {
|
||||||
List<ConnectionParams> nexts = [];
|
List<ConnectionParams> nexts = [];
|
||||||
var flow = FlowElement.deserialize(el);
|
var flow = FlowElement.deserialize(this, el);
|
||||||
for(var ar in graph['arrows']) {
|
for(var ar in graph['graph']['arrows']) {
|
||||||
|
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'],
|
||||||
@ -221,8 +250,22 @@ class Dashboard extends ChangeNotifier {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
flow.next = nexts;
|
flow.next = nexts;
|
||||||
|
List<FlowData> arr = [];
|
||||||
|
for (var cat in chartKey.currentState?.widget.flowChart.widget.categories ?? []) {
|
||||||
|
for (var build in chartKey.currentState!.widget.flowChart.widget.draggableItemBuilder(cat)) {
|
||||||
|
arr.add(build);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
FlowData data = arr.firstWhere((element) => element.getID() == flow.element?.getID());
|
||||||
|
flow.kind = ElementKind.widget;
|
||||||
|
flow.widget = chartKey.currentState?.widget.flowChart.widget.itemWidget(data);
|
||||||
|
} catch (e) { print(e); }
|
||||||
|
elements.add(flow);
|
||||||
|
}
|
||||||
|
selectedMenuKey.currentState?.setState(() { });
|
||||||
|
chartMenuKey.currentState?.setState(() { });
|
||||||
|
}
|
||||||
|
|
||||||
/// add listener called when a new connection is created
|
/// add listener called when a new connection is created
|
||||||
void addConnectionListener(ConnectionListener listener) {
|
void addConnectionListener(ConnectionListener listener) {
|
||||||
@ -249,7 +292,7 @@ class Dashboard extends ChangeNotifier {
|
|||||||
void addToHistory() {
|
void addToHistory() {
|
||||||
if (tempHistory.length >= 50) { tempHistory.removeAt(0); }
|
if (tempHistory.length >= 50) { tempHistory.removeAt(0); }
|
||||||
tempHistory.add(toMap());
|
tempHistory.add(toMap());
|
||||||
if (save != null) { save!(); }
|
if (save != null) { save!(id); }
|
||||||
history = tempHistory.map((e) => e).toList();
|
history = tempHistory.map((e) => e).toList();
|
||||||
chartKey.currentState?.setState(() { });
|
chartKey.currentState?.setState(() { });
|
||||||
chartMenuKey.currentState?.setState(() { });
|
chartMenuKey.currentState?.setState(() { });
|
||||||
@ -774,7 +817,7 @@ class Dashboard extends ChangeNotifier {
|
|||||||
|
|
||||||
final loadedElements = List<FlowElement>.from(
|
final loadedElements = List<FlowElement>.from(
|
||||||
(source['elements'] as List<dynamic>).map<FlowElement>(
|
(source['elements'] as List<dynamic>).map<FlowElement>(
|
||||||
(x) => FlowElement.fromMap(x as Map<String, dynamic>),
|
(x) => FlowElement.fromMap(this, x as Map<String, dynamic>),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
elements
|
elements
|
||||||
|
@ -4,7 +4,7 @@ import 'dart:convert';
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
|
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
|
||||||
import 'package:flutter_flow_chart/src/elements/connection_params.dart';
|
import 'package:flutter_flow_chart/src/dashboard.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
/// Kinf od element
|
/// Kinf od element
|
||||||
@ -61,12 +61,16 @@ enum Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Class to store [ElementWidget]s and notify its changes
|
/// Class to store [ElementWidget]s and notify its changes
|
||||||
class FlowElement extends ChangeNotifier {
|
class FlowElement<T extends FlowData> extends ChangeNotifier {
|
||||||
|
Dashboard dashboard;
|
||||||
bool isSelected = false;
|
bool isSelected = false;
|
||||||
|
T? element;
|
||||||
///
|
///
|
||||||
FlowElement({
|
FlowElement({
|
||||||
|
required this.dashboard,
|
||||||
Offset position = Offset.zero,
|
Offset position = Offset.zero,
|
||||||
String? id,
|
String? id,
|
||||||
|
this.element,
|
||||||
this.size = Size.zero,
|
this.size = Size.zero,
|
||||||
this.text = '',
|
this.text = '',
|
||||||
this.textColor = Colors.black,
|
this.textColor = Colors.black,
|
||||||
@ -103,8 +107,12 @@ class FlowElement extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
factory FlowElement.fromMap(Map<String, dynamic> map) {
|
factory FlowElement.fromMap(Dashboard dashboard, Map<String, dynamic> map) {
|
||||||
final e = FlowElement(
|
final e = FlowElement<T>(
|
||||||
|
element: (dashboard.transformToData != null
|
||||||
|
? dashboard.transformToData!(map['element'] ?? {})
|
||||||
|
: null) as T?,
|
||||||
|
dashboard: dashboard,
|
||||||
widget: map['widget'] as Widget?,
|
widget: map['widget'] as Widget?,
|
||||||
size: Size(map['size.width'] as double, map['size.height'] as double),
|
size: Size(map['size.width'] as double, map['size.height'] as double),
|
||||||
text: map['text'] as String,
|
text: map['text'] as String,
|
||||||
@ -141,8 +149,8 @@ class FlowElement extends ChangeNotifier {
|
|||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
factory FlowElement.fromJson(String source) =>
|
factory FlowElement.fromJson(Dashboard dashboard, String source) =>
|
||||||
FlowElement.fromMap(json.decode(source) as Map<String, dynamic>);
|
FlowElement.fromMap(dashboard, json.decode(source) as Map<String, dynamic>);
|
||||||
|
|
||||||
/// Unique id set when adding a [FlowElement] with [Dashboard.addElement()]
|
/// Unique id set when adding a [FlowElement] with [Dashboard.addElement()]
|
||||||
late String id;
|
late String id;
|
||||||
@ -365,14 +373,18 @@ class FlowElement extends ChangeNotifier {
|
|||||||
graphElement['y'] = position.dy;
|
graphElement['y'] = position.dy;
|
||||||
graphElement['width'] = size.width;
|
graphElement['width'] = size.width;
|
||||||
graphElement['height'] = size.height;
|
graphElement['height'] = size.height;
|
||||||
|
graphElement['element']=element?.serialize();
|
||||||
return graphElement;
|
return graphElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FlowElement deserialize(Map<String, dynamic> map) {
|
static FlowElement deserialize<T extends FlowData>(Dashboard dashboard, Map<String, dynamic> map) {
|
||||||
return FlowElement(
|
return FlowElement<T>(
|
||||||
|
dashboard: dashboard,
|
||||||
id: map['id'],
|
id: map['id'],
|
||||||
position: Offset(map['x'], map['y']),
|
kind: ElementKind.widget,
|
||||||
size: Size(map['width'], map['height']),
|
position: Offset(double.parse("${map['x']}"), double.parse("${map['y']}")),
|
||||||
|
size: Size(double.parse("${map['width']}"), double.parse("${map['height']}")),
|
||||||
|
element: (dashboard.transformToData != null ? dashboard.transformToData!(map['element'] ?? {}) : null) as T?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
// ignore: directives_ordering
|
// ignore: directives_ordering
|
||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
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/flutter_flow_chart.dart';
|
||||||
import 'package:flutter_flow_chart/src/dashboard.dart';
|
import 'package:flutter_flow_chart/src/flow_chart_left_menu.dart';
|
||||||
import 'package:flutter_flow_chart/src/elements/flow_element.dart';
|
|
||||||
import 'package:flutter_flow_chart/src/flow_chart_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/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';
|
||||||
@ -15,7 +16,14 @@ import 'package:uuid/uuid.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
|
||||||
class FlowChart<T extends Object> extends StatefulWidget {
|
abstract class FlowData {
|
||||||
|
String getID();
|
||||||
|
String getName();
|
||||||
|
Map<String, dynamic> serialize();
|
||||||
|
FlowData deserialize(Map<String, dynamic> data);
|
||||||
|
}
|
||||||
|
|
||||||
|
class FlowChart<T extends FlowData> extends StatefulWidget {
|
||||||
FlowChart({
|
FlowChart({
|
||||||
required this.dashboard,
|
required this.dashboard,
|
||||||
required this.itemWidget,
|
required this.itemWidget,
|
||||||
@ -44,13 +52,15 @@ class FlowChart<T extends Object> extends StatefulWidget {
|
|||||||
this.categories = const [],
|
this.categories = const [],
|
||||||
required this.draggableItemBuilder,
|
required this.draggableItemBuilder,
|
||||||
this.onDashboardAlertOpened,
|
this.onDashboardAlertOpened,
|
||||||
|
this.menuExtension,
|
||||||
}) {}
|
}) {}
|
||||||
|
|
||||||
final List<String> categories;
|
final List<String> categories;
|
||||||
final double width;
|
final double width;
|
||||||
final double height;
|
final double height;
|
||||||
final double innerMenuWidth;
|
final double innerMenuWidth;
|
||||||
|
|
||||||
|
Widget Function()? menuExtension;
|
||||||
|
|
||||||
double itemWidth = 80;
|
double itemWidth = 80;
|
||||||
double zoom = 1;
|
double zoom = 1;
|
||||||
|
|
||||||
@ -161,7 +171,6 @@ class HoverMenuController {
|
|||||||
currentState?.hideSubMenu();
|
currentState?.hideSubMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool isPopUp = false;
|
|
||||||
class HoverMenu extends StatefulWidget {
|
class HoverMenu extends StatefulWidget {
|
||||||
final Widget title;
|
final Widget title;
|
||||||
final double? width;
|
final double? width;
|
||||||
@ -277,49 +286,8 @@ class HoverMenuState extends State<HoverMenu> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var node = FocusNode();
|
var node = FocusNode();
|
||||||
class FlowChartState<T extends Object> extends State<FlowChart> {
|
class FlowChartState<T extends FlowData> extends State<FlowChart> {
|
||||||
List<Draggable<T>> getDraggable(List<T> items) {
|
|
||||||
List<Draggable<T>> res = [];
|
|
||||||
double realSize = widget.itemWidth * widget.zoom;
|
|
||||||
GlobalKey<HoverMenuState> hoverKey = GlobalKey<HoverMenuState>();
|
|
||||||
for (var e in items) {
|
|
||||||
res.add(Draggable<T>(
|
|
||||||
// Data is the value this Draggable stores.
|
|
||||||
data: e,
|
|
||||||
onDragStarted: () => hoverKey.currentState?.hideSubMenu(),
|
|
||||||
onDragEnd: (d) => node.requestFocus(),
|
|
||||||
childWhenDragging: Opacity(opacity: .5,
|
|
||||||
child: Padding( padding: const EdgeInsets.all(10),
|
|
||||||
child: Container( height: realSize - 20, child: widget.itemWidget(e) ))),
|
|
||||||
feedback: Container( height: realSize, child: widget.itemWidget(e) ),
|
|
||||||
child: InkWell( mouseCursor: SystemMouseCursors.grab, child: Padding( padding: const EdgeInsets.all(10),
|
|
||||||
child: widget.itemWidgetTooltip != null ? HoverMenu( key: hoverKey, width: 400, title: Container(
|
|
||||||
height: realSize - 20, child: widget.itemWidget(e) ),
|
|
||||||
items: [
|
|
||||||
Container(child: widget.itemWidgetTooltip!(e)),
|
|
||||||
]
|
|
||||||
) : Container(
|
|
||||||
height: realSize - 20, child: widget.itemWidget(e)
|
|
||||||
)
|
|
||||||
) )));
|
|
||||||
}
|
|
||||||
if (!widget.dashboard.isOpened && widget.onDashboardAlertOpened != null && isPopUp == false) {
|
|
||||||
isPopUp = true;
|
|
||||||
widget.dashboard.isOpened = true;
|
|
||||||
Future.delayed(Duration(milliseconds: 1), () => showDialog(
|
|
||||||
barrierDismissible: false,
|
|
||||||
context: context, builder: (context) {
|
|
||||||
return AlertDialog(
|
|
||||||
titlePadding: EdgeInsets.zero,
|
|
||||||
insetPadding: EdgeInsets.zero,
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0)),
|
|
||||||
title: widget.onDashboardAlertOpened!(context, widget.dashboard));
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
widget.dashboard.isOpened = true;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -342,48 +310,14 @@ class FlowChartState<T extends Object> extends State<FlowChart> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// disabling default browser context menu on web
|
// disabling default browser context menu on web
|
||||||
if (kIsWeb) BrowserContextMenu.disableContextMenu();
|
if (kIsWeb) BrowserContextMenu.disableContextMenu();
|
||||||
|
|
||||||
List<Widget> menuItems = [];
|
|
||||||
for (var cat in widget.categories) {
|
|
||||||
menuItems.add(
|
|
||||||
Container( width: widget.dashboard.isMenu ? widget.innerMenuWidth : 0, margin: const EdgeInsets.only(bottom: 0.3),
|
|
||||||
decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: .5))),
|
|
||||||
child: Stack( children: [
|
|
||||||
widget.dashboard.isMenu && widget.innerMenuWidth < 200 ? Wrap( alignment: WrapAlignment.start,
|
|
||||||
children: getDraggable(widget.draggableItemBuilder(cat) as List<T>))
|
|
||||||
: ExpansionTile(
|
|
||||||
shape: const ContinuousRectangleBorder(side: BorderSide(color: Colors.transparent)),
|
|
||||||
initiallyExpanded: true,
|
|
||||||
title: SizedBox(
|
|
||||||
child : Row( children: [
|
|
||||||
Padding(padding: const EdgeInsets.only(right: 10),
|
|
||||||
child: Icon(cat.toUpperCase().contains("DATA") ? Icons.grid_on : Icons.bookmark, color: Colors.grey)),
|
|
||||||
Flexible(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(right: 5),
|
|
||||||
child: Text(cat.toUpperCase(), overflow: TextOverflow.ellipsis,
|
|
||||||
style: const TextStyle(color: Colors.black, fontSize: 11, fontWeight: FontWeight.w500))))
|
|
||||||
])
|
|
||||||
),
|
|
||||||
iconColor: Colors.white,
|
|
||||||
collapsedIconColor: Colors.white,
|
|
||||||
children: [
|
|
||||||
Container( width: widget.dashboard.isMenu ? widget.innerMenuWidth : 0, color: Colors.white,
|
|
||||||
child : Wrap( alignment: WrapAlignment.start,
|
|
||||||
children: getDraggable(widget.draggableItemBuilder(cat) as List<T>))
|
|
||||||
)],
|
|
||||||
)
|
|
||||||
]
|
|
||||||
))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return KeyboardListener(
|
return KeyboardListener(
|
||||||
focusNode: node,
|
focusNode: node,
|
||||||
onKeyEvent: (event) {
|
onKeyEvent: (event) {
|
||||||
|
bool change = false;
|
||||||
if ((event is KeyDownEvent || event is KeyRepeatEvent) && event.logicalKey == LogicalKeyboardKey.arrowUp) {
|
if ((event is KeyDownEvent || event is KeyRepeatEvent) && event.logicalKey == LogicalKeyboardKey.arrowUp) {
|
||||||
|
change = true;
|
||||||
for (var el in widget.dashboard.elements) {
|
for (var el in widget.dashboard.elements) {
|
||||||
if (el.isSelected) {
|
if (el.isSelected) {
|
||||||
el.position = Offset(el.position.dx, el.position.dy - 10);
|
el.position = Offset(el.position.dx, el.position.dy - 10);
|
||||||
@ -391,6 +325,7 @@ class FlowChartState<T extends Object> extends State<FlowChart> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((event is KeyDownEvent || event is KeyRepeatEvent) && event.logicalKey == LogicalKeyboardKey.arrowDown) {
|
if ((event is KeyDownEvent || event is KeyRepeatEvent) && event.logicalKey == LogicalKeyboardKey.arrowDown) {
|
||||||
|
change = true;
|
||||||
for (var el in widget.dashboard.elements) {
|
for (var el in widget.dashboard.elements) {
|
||||||
if (el.isSelected) {
|
if (el.isSelected) {
|
||||||
el.position = Offset(el.position.dx, el.position.dy + 10);
|
el.position = Offset(el.position.dx, el.position.dy + 10);
|
||||||
@ -398,6 +333,7 @@ class FlowChartState<T extends Object> extends State<FlowChart> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((event is KeyDownEvent || event is KeyRepeatEvent) && event.logicalKey == LogicalKeyboardKey.arrowLeft) {
|
if ((event is KeyDownEvent || event is KeyRepeatEvent) && event.logicalKey == LogicalKeyboardKey.arrowLeft) {
|
||||||
|
change = true;
|
||||||
for (var el in widget.dashboard.elements) {
|
for (var el in widget.dashboard.elements) {
|
||||||
if (el.isSelected) {
|
if (el.isSelected) {
|
||||||
el.position = Offset(el.position.dx - 10, el.position.dy);
|
el.position = Offset(el.position.dx - 10, el.position.dy);
|
||||||
@ -405,6 +341,7 @@ class FlowChartState<T extends Object> extends State<FlowChart> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((event is KeyDownEvent || event is KeyRepeatEvent) && event.logicalKey == LogicalKeyboardKey.arrowRight) {
|
if ((event is KeyDownEvent || event is KeyRepeatEvent) && event.logicalKey == LogicalKeyboardKey.arrowRight) {
|
||||||
|
change = true;
|
||||||
for (var el in widget.dashboard.elements) {
|
for (var el in widget.dashboard.elements) {
|
||||||
if (el.isSelected) {
|
if (el.isSelected) {
|
||||||
el.position = Offset(el.position.dx + 10, el.position.dy);
|
el.position = Offset(el.position.dx + 10, el.position.dy);
|
||||||
@ -413,8 +350,11 @@ class FlowChartState<T extends Object> extends State<FlowChart> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.add) {
|
if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.add) {
|
||||||
|
change = true;
|
||||||
for (var el in widget.dashboard.elementSelected) {
|
for (var el in widget.dashboard.elementSelected) {
|
||||||
widget.dashboard.elements.add(FlowElement(
|
widget.dashboard.elements.add(FlowElement<T>(
|
||||||
|
element: el.element as T,
|
||||||
|
dashboard: widget.dashboard,
|
||||||
id: const Uuid().v4(),
|
id: const Uuid().v4(),
|
||||||
position: el.position + const Offset(100, 100),
|
position: el.position + const Offset(100, 100),
|
||||||
size: el.size,
|
size: el.size,
|
||||||
@ -427,6 +367,7 @@ class FlowChartState<T extends Object> extends State<FlowChart> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.delete) {
|
if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.delete) {
|
||||||
|
change = true;
|
||||||
widget.dashboard.elements.removeWhere( (el) => el.isSelected );
|
widget.dashboard.elements.removeWhere( (el) => el.isSelected );
|
||||||
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])) {
|
||||||
@ -435,11 +376,13 @@ class FlowChartState<T extends Object> extends State<FlowChart> {
|
|||||||
}
|
}
|
||||||
widget.dashboard.arrows.removeWhere( (el) => el.isSelected );
|
widget.dashboard.arrows.removeWhere( (el) => el.isSelected );
|
||||||
}
|
}
|
||||||
|
if (change) {
|
||||||
DrawingArrow.instance.notifyListeners();
|
DrawingArrow.instance.notifyListeners();
|
||||||
widget.dashboard.chartKey.currentState?.setState(() { });
|
widget.dashboard.chartKey.currentState?.setState(() { });
|
||||||
Future.delayed(Duration(milliseconds: 10), () {
|
/*Future.delayed(Duration(milliseconds: 10), () {
|
||||||
node.requestFocus();
|
node.requestFocus();
|
||||||
});
|
});*/
|
||||||
|
}
|
||||||
},
|
},
|
||||||
child: ClipRect(
|
child: ClipRect(
|
||||||
child: Stack(
|
child: Stack(
|
||||||
@ -456,7 +399,7 @@ class FlowChartState<T extends Object> extends State<FlowChart> {
|
|||||||
return SizedBox(
|
return SizedBox(
|
||||||
width: widget.width,
|
width: widget.width,
|
||||||
height: widget.height,
|
height: widget.height,
|
||||||
child: ChartWidget(
|
child: ChartWidget<T>(
|
||||||
key: widget.dashboard.chartKey,
|
key: widget.dashboard.chartKey,
|
||||||
flowChart: this,
|
flowChart: this,
|
||||||
dashboard: widget.dashboard,
|
dashboard: widget.dashboard,
|
||||||
@ -478,8 +421,10 @@ class FlowChartState<T extends Object> extends State<FlowChart> {
|
|||||||
onAcceptWithDetails: (DragTargetDetails<T> details) {
|
onAcceptWithDetails: (DragTargetDetails<T> details) {
|
||||||
var e = details.data;
|
var e = details.data;
|
||||||
String newID = const Uuid().v4();
|
String newID = const Uuid().v4();
|
||||||
FlowElement el = FlowElement(
|
FlowElement<T> el = FlowElement<T>(
|
||||||
|
dashboard: widget.dashboard,
|
||||||
id: newID,
|
id: newID,
|
||||||
|
element: e,
|
||||||
position: details.offset,
|
position: details.offset,
|
||||||
size: const Size(100, 100),
|
size: const Size(100, 100),
|
||||||
text: '${widget.dashboard.elements.length}',
|
text: '${widget.dashboard.elements.length}',
|
||||||
@ -497,16 +442,70 @@ class FlowChartState<T extends Object> extends State<FlowChart> {
|
|||||||
},
|
},
|
||||||
))]
|
))]
|
||||||
),
|
),
|
||||||
widget.dashboard.isMenu ? Positioned(top: 50, child: Container(
|
widget.dashboard.isMenu ? Positioned(top: 50, child: FlowChartLeftMenu<T>(
|
||||||
height: widget.height - 50,
|
key: widget.dashboard.selectedLeftMenuKey,
|
||||||
constraints: BoxConstraints(minWidth: widget.itemWidth),
|
dashboard: widget.dashboard,
|
||||||
width: widget.dashboard.isMenu ? widget.innerMenuWidth : 0,
|
categories: widget.categories,
|
||||||
color: Colors.grey.shade300,
|
height: widget.height,
|
||||||
child: SingleChildScrollView( child: Column( children: menuItems ) )
|
innerMenuWidth: widget.innerMenuWidth,
|
||||||
)) : Container(),
|
itemWidth: widget.itemWidth,
|
||||||
|
menuExtension: widget.menuExtension,
|
||||||
|
draggableItemBuilder: widget.draggableItemBuilder as List<T> Function(String cat),
|
||||||
|
getDraggable: getDraggable,
|
||||||
|
) )
|
||||||
|
: Container(),
|
||||||
|
widget.dashboard.isInfo ? Positioned(top: 50, right: 0, child:
|
||||||
|
FlowChartSelectedMenu(
|
||||||
|
key: widget.dashboard.selectedMenuKey,
|
||||||
|
dashboard: widget.dashboard,
|
||||||
|
height: MediaQuery.of(context).size.height - 100
|
||||||
|
)
|
||||||
|
) : Container()
|
||||||
])
|
])
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Draggable<T>> getDraggable(List<T> items) {
|
||||||
|
List<Draggable<T>> res = [];
|
||||||
|
double realSize = widget.itemWidth * widget.zoom;
|
||||||
|
for (var e in items) {
|
||||||
|
GlobalKey<HoverMenuState> hoverKey = GlobalKey<HoverMenuState>();
|
||||||
|
res.add(Draggable<T>(
|
||||||
|
// Data is the value this Draggable stores.
|
||||||
|
data: e,
|
||||||
|
onDragStarted: () => hoverKey.currentState?.hideSubMenu(),
|
||||||
|
onDragEnd: (d) => node.requestFocus(),
|
||||||
|
childWhenDragging: Opacity(opacity: .5,
|
||||||
|
child: Padding( padding: const EdgeInsets.all(10),
|
||||||
|
child: Container( height: realSize - 20, child: widget.itemWidget(e) ))),
|
||||||
|
feedback: Container( height: realSize, child: widget.itemWidget(e) ),
|
||||||
|
child: InkWell( mouseCursor: SystemMouseCursors.grab, child: Padding( padding: const EdgeInsets.all(10),
|
||||||
|
child: widget.itemWidgetTooltip != null ? HoverMenu( key: hoverKey, width: 400, title: Container(
|
||||||
|
height: realSize - 20, child: widget.itemWidget(e) ),
|
||||||
|
items: [
|
||||||
|
Container(child: widget.itemWidgetTooltip!(e)),
|
||||||
|
]
|
||||||
|
) : Container(
|
||||||
|
height: realSize - 20, child: widget.itemWidget(e)
|
||||||
|
)
|
||||||
|
) )));
|
||||||
|
}
|
||||||
|
if (!widget.dashboard.isOpened && widget.onDashboardAlertOpened != null ) {
|
||||||
|
Future.delayed(Duration(milliseconds: 100), () {
|
||||||
|
showDialog(
|
||||||
|
barrierDismissible: false,
|
||||||
|
context: context, builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
titlePadding: EdgeInsets.zero,
|
||||||
|
insetPadding: EdgeInsets.zero,
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0)),
|
||||||
|
title: widget.onDashboardAlertOpened!(context, widget.dashboard));
|
||||||
|
|
||||||
|
}); });
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Widget to draw interactive connection when the user tap on handlers
|
/// Widget to draw interactive connection when the user tap on handlers
|
||||||
@ -553,8 +552,7 @@ class _DrawingArrowWidgetState extends State<DrawingArrowWidget> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChartWidget extends StatefulWidget {
|
class ChartWidget<T extends FlowData> extends StatefulWidget {
|
||||||
|
|
||||||
ChartWidget ({ Key? key,
|
ChartWidget ({ Key? key,
|
||||||
required this.flowChart,
|
required this.flowChart,
|
||||||
this.onElementPressed,
|
this.onElementPressed,
|
||||||
@ -667,9 +665,9 @@ class ChartWidget extends StatefulWidget {
|
|||||||
|
|
||||||
final Dashboard dashboard;
|
final Dashboard dashboard;
|
||||||
|
|
||||||
@override ChartWidgetState createState() => ChartWidgetState();
|
@override ChartWidgetState createState() => ChartWidgetState<T>();
|
||||||
}
|
}
|
||||||
class ChartWidgetState extends State<ChartWidget> {
|
class ChartWidgetState<T extends FlowData> extends State<ChartWidget> {
|
||||||
bool hoverImportant = false;
|
bool hoverImportant = false;
|
||||||
final segmentedTension = ValueNotifier<double>(1);
|
final segmentedTension = ValueNotifier<double>(1);
|
||||||
|
|
||||||
@ -710,8 +708,7 @@ class ChartWidgetState extends State<ChartWidget> {
|
|||||||
var secondaryTapDownPos = Offset.zero;
|
var secondaryTapDownPos = Offset.zero;
|
||||||
for (int i = 0; i < widget.dashboard.elements.length; i++)
|
for (int i = 0; i < widget.dashboard.elements.length; i++)
|
||||||
widget.dashboard.elements[i].next.removeWhere((element) =>
|
widget.dashboard.elements[i].next.removeWhere((element) =>
|
||||||
widget.dashboard.findElementIndexById(element.destElementId) < 0
|
widget.dashboard.findElementIndexById(element.destElementId) < 0);
|
||||||
);
|
|
||||||
return Stack( children: [
|
return Stack( children: [
|
||||||
Positioned.fill(
|
Positioned.fill(
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
@ -801,7 +798,7 @@ class ChartWidgetState extends State<ChartWidget> {
|
|||||||
),
|
),
|
||||||
// Draw elements
|
// Draw elements
|
||||||
for (int i = 0; i < widget.dashboard.elements.length; i++)
|
for (int i = 0; i < widget.dashboard.elements.length; i++)
|
||||||
ElementWidget(
|
ElementWidget<T>(
|
||||||
key: UniqueKey(),
|
key: UniqueKey(),
|
||||||
dashboard: widget.dashboard,
|
dashboard: widget.dashboard,
|
||||||
element: widget.dashboard.elements.elementAt(i),
|
element: widget.dashboard.elements.elementAt(i),
|
||||||
@ -904,10 +901,6 @@ class ChartWidgetState extends State<ChartWidget> {
|
|||||||
dashboard: widget.dashboard,
|
dashboard: widget.dashboard,
|
||||||
width: MediaQuery.of(context).size.width)
|
width: MediaQuery.of(context).size.width)
|
||||||
),
|
),
|
||||||
widget.dashboard.isInfo ? Positioned(top: 50, right: 0, child:
|
|
||||||
FlowChartSelectedMenu(key: widget.dashboard.selectedMenuKey, chart: this,
|
|
||||||
dashboard: widget.dashboard, height: MediaQuery.of(context).size.height - 100)
|
|
||||||
) : Container()
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
107
library/flutter_flow_chart/lib/src/flow_chart_left_menu.dart
Normal file
107
library/flutter_flow_chart/lib/src/flow_chart_left_menu.dart
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
|
||||||
|
|
||||||
|
class FlowChartLeftMenu<T extends FlowData> extends StatefulWidget {
|
||||||
|
Dashboard dashboard;
|
||||||
|
List<String> categories;
|
||||||
|
double height;
|
||||||
|
double itemWidth;
|
||||||
|
double innerMenuWidth;
|
||||||
|
Widget Function()? menuExtension;
|
||||||
|
TextEditingController ctrl = TextEditingController();
|
||||||
|
final List<T> Function(String cat) draggableItemBuilder;
|
||||||
|
|
||||||
|
List<Draggable<T>> Function(List<T> items) getDraggable;
|
||||||
|
|
||||||
|
FlowChartLeftMenu ({ super.key, required this.categories, required this.dashboard,
|
||||||
|
this.height = 100,
|
||||||
|
this.innerMenuWidth = 100,
|
||||||
|
this.itemWidth = 100,
|
||||||
|
this.menuExtension,
|
||||||
|
required this.getDraggable,
|
||||||
|
required this.draggableItemBuilder
|
||||||
|
});
|
||||||
|
@override FlowChartLeftMenuState createState() => FlowChartLeftMenuState();
|
||||||
|
}
|
||||||
|
class FlowChartLeftMenuState<T extends FlowData> extends State<FlowChartLeftMenu> {
|
||||||
|
@override Widget build(BuildContext context) {
|
||||||
|
List<Widget> menuItems = [];
|
||||||
|
for (var cat in widget.categories) {
|
||||||
|
if (widget.draggableItemBuilder(cat).isEmpty) continue;
|
||||||
|
var items = widget.draggableItemBuilder(cat).where(
|
||||||
|
(element) => element.getName().toLowerCase().contains(widget.ctrl.value.text.toLowerCase())).toSet().toList();
|
||||||
|
menuItems.add(
|
||||||
|
Container( width: widget.dashboard.isMenu ? widget.innerMenuWidth : 0, margin: const EdgeInsets.only(bottom: 0.3),
|
||||||
|
decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: .5))),
|
||||||
|
child: Stack( children: [
|
||||||
|
widget.dashboard.isMenu && widget.innerMenuWidth < 200 ? Wrap( alignment: WrapAlignment.start,
|
||||||
|
children: widget.getDraggable(items))
|
||||||
|
: ExpansionTile(
|
||||||
|
shape: const ContinuousRectangleBorder(side: BorderSide(color: Colors.transparent)),
|
||||||
|
initiallyExpanded: true,
|
||||||
|
title: SizedBox(
|
||||||
|
child : Row( children: [
|
||||||
|
Padding(padding: const EdgeInsets.only(right: 10),
|
||||||
|
child: Icon(cat.toUpperCase().contains("DATA") ? Icons.grid_on : Icons.bookmark, color: Colors.grey)),
|
||||||
|
Flexible(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 5),
|
||||||
|
child: Text(cat.toUpperCase(), overflow: TextOverflow.ellipsis,
|
||||||
|
style: const TextStyle(color: Colors.black, fontSize: 11, fontWeight: FontWeight.w500))))
|
||||||
|
])
|
||||||
|
),
|
||||||
|
iconColor: Colors.white,
|
||||||
|
collapsedIconColor: Colors.white,
|
||||||
|
children: [
|
||||||
|
Container( width: widget.dashboard.isMenu ? widget.innerMenuWidth : 0, color: Colors.white,
|
||||||
|
child : Wrap( alignment: WrapAlignment.center,
|
||||||
|
children: widget.getDraggable(items))
|
||||||
|
)],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Container(
|
||||||
|
height: widget.height - 50,
|
||||||
|
color: Colors.grey.shade300,
|
||||||
|
child: Stack( children: [
|
||||||
|
Container(
|
||||||
|
width: widget.innerMenuWidth,
|
||||||
|
height: 50,
|
||||||
|
decoration: const BoxDecoration(border: Border(left: BorderSide(color: Colors.white))),
|
||||||
|
child: TextFormField(
|
||||||
|
style: const TextStyle(color: Colors.black, fontSize: 15),
|
||||||
|
cursorColor: const Color.fromARGB(38, 166, 154, 1),
|
||||||
|
controller: widget.ctrl,
|
||||||
|
onChanged: (value) { setState(() { }); },
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: "search item...",
|
||||||
|
fillColor: Colors.white,
|
||||||
|
filled: true,
|
||||||
|
contentPadding: const EdgeInsets.only(left: 30, right: 30, top: 5, bottom: 5),
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
color: Colors.grey,
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: FontWeight.w400
|
||||||
|
),
|
||||||
|
border: InputBorder.none
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
margin: EdgeInsets.only(top: 50),
|
||||||
|
height: widget.height - 150,
|
||||||
|
constraints: BoxConstraints(minWidth: widget.itemWidth),
|
||||||
|
width: widget.dashboard.isMenu ? widget.innerMenuWidth : 0,
|
||||||
|
color: Colors.grey.shade300,
|
||||||
|
child: SingleChildScrollView( child: Column( children: [
|
||||||
|
...menuItems
|
||||||
|
]) )
|
||||||
|
),
|
||||||
|
Positioned( bottom: 0, height: 50,
|
||||||
|
child: widget.menuExtension != null ? widget.menuExtension!() : Container(),),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -35,6 +35,7 @@ class FlowChartMenuState extends State<FlowChartMenu> {
|
|||||||
child: InkWell( mouseCursor: SystemMouseCursors.click,
|
child: InkWell( mouseCursor: SystemMouseCursors.click,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
widget.dashboard.defaultName = "graph_${DateTime.now().toString().replaceAll(" ", "_").substring(0, DateTime.now().toString().length - 7)}";
|
widget.dashboard.defaultName = "graph_${DateTime.now().toString().replaceAll(" ", "_").substring(0, DateTime.now().toString().length - 7)}";
|
||||||
|
widget.dashboard.isOpened = true;
|
||||||
showDialog(
|
showDialog(
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
context: context, builder: (context) {
|
context: context, builder: (context) {
|
||||||
|
@ -6,16 +6,78 @@ import 'package:flutter_colorpicker/flutter_colorpicker.dart';
|
|||||||
import 'package:number_text_input_formatter/number_text_input_formatter.dart';
|
import 'package:number_text_input_formatter/number_text_input_formatter.dart';
|
||||||
|
|
||||||
class FlowChartSelectedMenu extends StatefulWidget {
|
class FlowChartSelectedMenu extends StatefulWidget {
|
||||||
ChartWidgetState chart;
|
|
||||||
Dashboard dashboard;
|
Dashboard dashboard;
|
||||||
double height = 100;
|
double height = 100;
|
||||||
|
bool isDashboardInfo = true;
|
||||||
FlowChartSelectedMenu ({ super.key, required this.chart, required this.dashboard, this.height = 100 });
|
FlowChartSelectedMenu ({ super.key, required this.dashboard, this.height = 100 });
|
||||||
@override FlowChartSelectedMenuState createState() => FlowChartSelectedMenuState();
|
@override FlowChartSelectedMenuState createState() => FlowChartSelectedMenuState();
|
||||||
}
|
}
|
||||||
class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
|
class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
|
||||||
@override Widget build(BuildContext context) {
|
@override Widget build(BuildContext context) {
|
||||||
return Container( // SHORTCUT
|
Widget? w;
|
||||||
|
if (widget.isDashboardInfo && widget.dashboard.elementSelected.length == 1) {
|
||||||
|
w = Container(
|
||||||
|
width: 200,
|
||||||
|
height: widget.height,
|
||||||
|
color: Colors.grey.shade300,
|
||||||
|
child: Column( children: [ ...widget.dashboard.infoItemWidget != null ?
|
||||||
|
widget.dashboard.infoItemWidget!(widget.dashboard.elementSelected.first.element)
|
||||||
|
: [],
|
||||||
|
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),
|
||||||
|
bottom: BorderSide(color: Colors.grey, width: 1))),
|
||||||
|
child: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
|
||||||
|
Tooltip( message: "remove",
|
||||||
|
child: InkWell( mouseCursor: SystemMouseCursors.click,
|
||||||
|
onTap: () {
|
||||||
|
widget.dashboard.arrows.removeWhere((element) {
|
||||||
|
if (element.isSelected && element.elementIndex != null && element.connIndex != null) {
|
||||||
|
widget.dashboard.elements[element.elementIndex!].next.removeAt(element.connIndex!);
|
||||||
|
}
|
||||||
|
return element.isSelected;
|
||||||
|
});
|
||||||
|
widget.dashboard.elements.removeWhere((element) => element.isSelected);
|
||||||
|
Future.delayed(Duration(milliseconds: 100), () {
|
||||||
|
widget.dashboard.chartKey.currentState?.setState(() { });
|
||||||
|
});
|
||||||
|
}, child: Container( margin: EdgeInsets.all(10),
|
||||||
|
decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.black, width: 1)),
|
||||||
|
width: 140, height: 30,
|
||||||
|
child: Icon(Icons.delete_outline, color: Colors.black),
|
||||||
|
))
|
||||||
|
),
|
||||||
|
Tooltip( message: "copy",
|
||||||
|
child: InkWell( mouseCursor: SystemMouseCursors.click,
|
||||||
|
onTap: () {
|
||||||
|
for (var sel in widget.dashboard.elementSelected) {
|
||||||
|
widget.dashboard.elements.add(FlowElement.fromMap(widget.dashboard, sel.toMap()));
|
||||||
|
widget.dashboard.elements.last.position += Offset(50, 50);
|
||||||
|
}
|
||||||
|
Future.delayed(Duration(milliseconds: 100), () {
|
||||||
|
widget.dashboard.chartKey.currentState?.setState(() { });
|
||||||
|
});
|
||||||
|
}, child: Container( margin: EdgeInsets.all(10),
|
||||||
|
decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.black, width: 1)),
|
||||||
|
width: 140, height: 30,
|
||||||
|
child: Icon(Icons.copy, color: Colors.black),
|
||||||
|
))
|
||||||
|
),
|
||||||
|
])
|
||||||
|
) : Container()
|
||||||
|
])
|
||||||
|
);
|
||||||
|
} else if (widget.isDashboardInfo && widget.dashboard.infoWidget != null) {
|
||||||
|
w = Container(
|
||||||
|
width: 200,
|
||||||
|
height: widget.height,
|
||||||
|
color: Colors.grey.shade300,
|
||||||
|
child: Column( children: widget.dashboard.infoWidget != null ? widget.dashboard.infoWidget!() : [])
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
w = Container( // SHORTCUT
|
||||||
width: 200,
|
width: 200,
|
||||||
height: widget.height,
|
height: widget.height,
|
||||||
color: Colors.grey.shade300,
|
color: Colors.grey.shade300,
|
||||||
@ -292,6 +354,9 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
|
|||||||
)))
|
)))
|
||||||
]),
|
]),
|
||||||
])),
|
])),
|
||||||
|
widget.dashboard.elementSelected.isNotEmpty && widget.dashboard.elementSelected.length == 1 ? Container(
|
||||||
|
// TODO : TEST OMG
|
||||||
|
) : Container(),
|
||||||
widget.dashboard.elementSelected.isNotEmpty ? Container() : Container( padding: EdgeInsets.only(left: 10, right: 10, bottom: 20, top: 15),
|
widget.dashboard.elementSelected.isNotEmpty ? Container() : Container( padding: EdgeInsets.only(left: 10, right: 10, bottom: 20, top: 15),
|
||||||
decoration: BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),
|
decoration: BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),
|
||||||
child: Column( children: [
|
child: Column( children: [
|
||||||
@ -477,7 +542,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.elements.add(FlowElement.fromMap(sel.toMap()));
|
widget.dashboard.elements.add(FlowElement.fromMap(widget.dashboard, sel.toMap()));
|
||||||
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), () {
|
||||||
@ -495,6 +560,35 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
|
|||||||
])
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return Column( children: [
|
||||||
|
Container( // SHORTCUT
|
||||||
|
width: 200,
|
||||||
|
height: 50,
|
||||||
|
decoration: BoxDecoration(color: Colors.grey.shade300, border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),
|
||||||
|
child: Row( children: [
|
||||||
|
Tooltip(
|
||||||
|
message: "dashboard information",
|
||||||
|
child: InkWell( onTap: () => setState(() {widget.isDashboardInfo = true; }),
|
||||||
|
mouseCursor: SystemMouseCursors.click,
|
||||||
|
child: Container( alignment: Alignment.center,
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 10),
|
||||||
|
color: widget.isDashboardInfo ? Colors.grey : Colors.grey.shade300,
|
||||||
|
width: 100, child: Icon(Icons.info, color: Colors.white))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Tooltip(
|
||||||
|
message: "element style",
|
||||||
|
child: InkWell( onTap: () => setState(() {widget.isDashboardInfo = false; }),
|
||||||
|
mouseCursor: SystemMouseCursors.click,
|
||||||
|
child: Container( alignment: Alignment.center,
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 10),
|
||||||
|
color: !widget.isDashboardInfo ? Colors.grey : Colors.grey.shade300,
|
||||||
|
width: 100, child: Icon(Icons.format_paint, color: Colors.white)),
|
||||||
|
))
|
||||||
|
])),
|
||||||
|
w
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MySeparator extends StatelessWidget {
|
class MySeparator extends StatelessWidget {
|
||||||
|
@ -3,6 +3,8 @@ import 'dart:convert';
|
|||||||
import 'dart:ui' as ui;
|
import 'dart:ui' as ui;
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/rendering.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
|
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
|
||||||
import 'package:flutter_flow_chart/src/ui/segment_handler.dart';
|
import 'package:flutter_flow_chart/src/ui/segment_handler.dart';
|
||||||
|
|
||||||
@ -349,6 +351,7 @@ 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.arrows.add(painter);
|
widget.flow.widget.dashboard.arrows.add(painter);
|
||||||
|
widget.flow.widget.dashboard.save!(widget.flow.widget.dashboard.id);
|
||||||
} 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}");
|
||||||
@ -416,24 +419,24 @@ 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 {
|
||||||
final String fromID;
|
String fromID;
|
||||||
final String toID;
|
String toID;
|
||||||
bool isSelected = false;
|
bool isSelected = false;
|
||||||
///
|
///
|
||||||
ArrowPainter({
|
ArrowPainter({
|
||||||
this.elementIndex,
|
this.elementIndex,
|
||||||
this.connIndex,
|
this.connIndex,
|
||||||
required this.toID,
|
this.toID = "",
|
||||||
required this.fromID,
|
this.fromID = "",
|
||||||
this.isSelected = false,
|
this.isSelected = false,
|
||||||
required this.params,
|
required this.params,
|
||||||
required this.from,
|
this.from = Offset.zero,
|
||||||
required this.to,
|
this.to = Offset.zero,
|
||||||
List<Pivot>? pivots,
|
List<Pivot>? pivots,
|
||||||
}) : pivots = pivots ?? [];
|
}) : pivots = pivots ?? [];
|
||||||
|
|
||||||
///
|
///
|
||||||
final ArrowParams params;
|
ArrowParams params;
|
||||||
///
|
///
|
||||||
Offset from;
|
Offset from;
|
||||||
int? elementIndex;
|
int? elementIndex;
|
||||||
@ -457,6 +460,15 @@ class ArrowPainter extends CustomPainter {
|
|||||||
final arrowSize = 15;
|
final arrowSize = 15;
|
||||||
final arrowAngle= 25 * math.pi / 180;
|
final arrowAngle= 25 * math.pi / 180;
|
||||||
|
|
||||||
|
ArrowPainter deserialize(Map<String, dynamic> map) {
|
||||||
|
params = ArrowParams.fromMap(map['params']);
|
||||||
|
fromID = map['from']['id'];
|
||||||
|
toID = map['to']['id'];
|
||||||
|
from = Offset(map['from']['x'], map['from']['y']);
|
||||||
|
to = Offset(map['to']['x'], map['to']['y']);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, dynamic> serialize() {
|
Map<String, dynamic> serialize() {
|
||||||
Map<String, dynamic> graphElement = {};
|
Map<String, dynamic> graphElement = {};
|
||||||
graphElement['from'] = { "id" : fromID.split("_")[0], "x" : from.dx, "y" : from.dy };
|
graphElement['from'] = { "id" : fromID.split("_")[0], "x" : from.dx, "y" : from.dy };
|
||||||
|
@ -12,7 +12,7 @@ import 'package:flutter_flow_chart/src/ui/resize_widget.dart';
|
|||||||
import 'package:flutter_flow_chart/src/objects/any_widget.dart';
|
import 'package:flutter_flow_chart/src/objects/any_widget.dart';
|
||||||
|
|
||||||
/// Widget that use [element] properties to display it on the dashboard scene
|
/// Widget that use [element] properties to display it on the dashboard scene
|
||||||
class ElementWidget extends StatefulWidget {
|
class ElementWidget<T extends FlowData> extends StatefulWidget {
|
||||||
///
|
///
|
||||||
ElementWidget({
|
ElementWidget({
|
||||||
required this.dashboard,
|
required this.dashboard,
|
||||||
@ -84,10 +84,10 @@ class ElementWidget extends StatefulWidget {
|
|||||||
)? onHandlerSecondaryLongTapped;
|
)? onHandlerSecondaryLongTapped;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ElementWidget> createState() => ElementWidgetState();
|
State<ElementWidget> createState() => ElementWidgetState<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
class ElementWidgetState extends State<ElementWidget> {
|
class ElementWidgetState<T extends FlowData> extends State<ElementWidget> {
|
||||||
// local widget touch position when start dragging
|
// local widget touch position when start dragging
|
||||||
Offset delta = Offset.zero;
|
Offset delta = Offset.zero;
|
||||||
|
|
||||||
@ -219,6 +219,7 @@ class ElementWidgetState extends State<ElementWidget> {
|
|||||||
sel.changePosition(sel.position + diff);
|
sel.changePosition(sel.position + diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
widget.dashboard.save!(widget.dashboard.id);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -228,7 +229,8 @@ class ElementWidgetState extends State<ElementWidget> {
|
|||||||
element: widget.element,
|
element: widget.element,
|
||||||
dashboard: widget.dashboard,
|
dashboard: widget.dashboard,
|
||||||
handlerColor: widget.isHovered ? Color.fromRGBO(38, 166, 154, 1) : Colors.transparent,
|
handlerColor: widget.isHovered ? Color.fromRGBO(38, 166, 154, 1) : Colors.transparent,
|
||||||
child: w );
|
child: w
|
||||||
|
);
|
||||||
return Transform.translate(
|
return Transform.translate(
|
||||||
offset: widget.element.position,
|
offset: widget.element.position,
|
||||||
transformHitTests: true,
|
transformHitTests: true,
|
||||||
@ -245,7 +247,9 @@ class ElementWidgetState extends State<ElementWidget> {
|
|||||||
widget.dashboard.removeElement(widget.element);
|
widget.dashboard.removeElement(widget.element);
|
||||||
}, icon: Icon(Icons.delete_outline)),
|
}, icon: Icon(Icons.delete_outline)),
|
||||||
IconButton(tooltip: "copy element", onPressed: () {
|
IconButton(tooltip: "copy element", onPressed: () {
|
||||||
FlowElement newElement = FlowElement(
|
FlowElement<T> newElement = FlowElement<T>(
|
||||||
|
element: widget.element.element as T?,
|
||||||
|
dashboard: widget.dashboard,
|
||||||
kind: widget.element.kind,
|
kind: widget.element.kind,
|
||||||
position: widget.element.position + Offset(widget.element.size.width, widget.element.size.height),
|
position: widget.element.position + Offset(widget.element.size.width, widget.element.size.height),
|
||||||
size: widget.element.size,
|
size: widget.element.size,
|
||||||
|
130
pubspec.lock
130
pubspec.lock
@ -81,6 +81,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.1"
|
version: "3.1.1"
|
||||||
|
cron:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: cron
|
||||||
|
sha256: e1b379dec3d7967c8e521a92832a6ac97a11ea4046cbc3e584193a470e3ad8f5
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.1"
|
||||||
crypto:
|
crypto:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -113,6 +121,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.1"
|
version: "1.0.1"
|
||||||
|
datetime_picker_formfield:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: datetime_picker_formfield
|
||||||
|
sha256: "6d0412c98cc5da18a5dca1f81f82a834fbacdb5d249fd6d9bed42d912339720e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.1"
|
||||||
desktop_window:
|
desktop_window:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -206,6 +222,14 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_advanced_switch:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_advanced_switch
|
||||||
|
sha256: e1147161a3dd9b708a71c65e76174d4d1a0a5908a571b8b38b65c79b142c52a0
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.0"
|
||||||
flutter_box_transform:
|
flutter_box_transform:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -222,6 +246,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
|
flutter_event_calendar:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_event_calendar
|
||||||
|
sha256: f5b6f22ae01c24a1fc3f6432d3080130bb40efc976e53941b5f6422b6a4f9d64
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.0"
|
||||||
flutter_flow_chart:
|
flutter_flow_chart:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -312,7 +344,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.2"
|
version: "2.4.2"
|
||||||
intl:
|
intl:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: intl
|
name: intl
|
||||||
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
||||||
@ -335,6 +367,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.0"
|
version: "0.7.0"
|
||||||
|
json_string:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: json_string
|
||||||
|
sha256: "1350ec63197d3df7e7141092085b2b2c93ff18fb8d4cc8cede3ab7ce39a5c925"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.1"
|
||||||
|
json_util:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: json_util
|
||||||
|
sha256: "67d9af645042cb6e4f3acf100fe5eda769e92db8ef118bc3783e3571e4e3d22b"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
latlong2:
|
latlong2:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -551,6 +599,22 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.1.0"
|
||||||
|
scoped_model:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: scoped_model
|
||||||
|
sha256: "8dacc77cb5de78d5e159d54cab883847491a73dfaa3d28c52f4ec8b0be32645b"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
|
shamsi_date:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shamsi_date
|
||||||
|
sha256: "5df195a0b7794b7d4a8dc9321244400147896def157b7530c5b8a2f9cfc6a7a4"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.15.0"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -692,6 +756,30 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.17"
|
version: "0.8.17"
|
||||||
|
syncfusion_flutter_calendar:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: syncfusion_flutter_calendar
|
||||||
|
sha256: "1daa6077a8fb388b692d5d050d58eaa4c01ef92f064a882eb330ef47dc51cf2e"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "26.2.7"
|
||||||
|
syncfusion_flutter_core:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: syncfusion_flutter_core
|
||||||
|
sha256: fd4d2cdbf8d0d1e3441817cb8a03f896566fad5187788957e78492fe16800388
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "26.2.7"
|
||||||
|
syncfusion_flutter_datepicker:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: syncfusion_flutter_datepicker
|
||||||
|
sha256: e541929ccf95a9188ef9f32dfca544f29b3fc222d4dc5da9cb1112305021a615
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "26.2.7"
|
||||||
table_calendar:
|
table_calendar:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -716,6 +804,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.1"
|
version: "0.6.1"
|
||||||
|
timezone:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: timezone
|
||||||
|
sha256: a6ccda4a69a442098b602c44e61a1e2b4bf6f5516e875bbf0f427d5df14745d5
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.9.3"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -788,6 +884,38 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.1"
|
version: "0.5.1"
|
||||||
|
webview_flutter:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: webview_flutter
|
||||||
|
sha256: "6869c8786d179f929144b4a1f86e09ac0eddfe475984951ea6c634774c16b522"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.8.0"
|
||||||
|
webview_flutter_android:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: webview_flutter_android
|
||||||
|
sha256: "0d21cfc3bfdd2e30ab2ebeced66512b91134b39e72e97b43db2d47dda1c4e53a"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.16.3"
|
||||||
|
webview_flutter_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: webview_flutter_platform_interface
|
||||||
|
sha256: d937581d6e558908d7ae3dc1989c4f87b786891ab47bb9df7de548a151779d8d
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.10.0"
|
||||||
|
webview_flutter_wkwebview:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: webview_flutter_wkwebview
|
||||||
|
sha256: "9c62cc46fa4f2d41e10ab81014c1de470a6c6f26051a2de32111b2ee55287feb"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.14.0"
|
||||||
win32:
|
win32:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
10
pubspec.yaml
10
pubspec.yaml
@ -61,6 +61,16 @@ dependencies:
|
|||||||
number_text_input_formatter: ^1.0.0+8
|
number_text_input_formatter: ^1.0.0+8
|
||||||
flutter_colorpicker: ^1.1.0
|
flutter_colorpicker: ^1.1.0
|
||||||
hover_menu: ^1.1.1
|
hover_menu: ^1.1.1
|
||||||
|
datetime_picker_formfield: ^2.0.1
|
||||||
|
intl: ^0.19.0
|
||||||
|
flutter_advanced_switch: ^3.1.0
|
||||||
|
cron: ^0.6.1
|
||||||
|
flutter_event_calendar: ^1.0.0
|
||||||
|
syncfusion_flutter_calendar: ^26.2.7
|
||||||
|
webview_flutter: ^4.8.0
|
||||||
|
webview_flutter_android: ^3.16.3
|
||||||
|
webview_flutter_wkwebview: ^3.14.0
|
||||||
|
json_string: ^3.0.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Loading…
Reference in New Issue
Block a user