diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json index ef55960..2f8bf9f 100644 --- a/.dart_tool/package_config.json +++ b/.dart_tool/package_config.json @@ -3,193 +3,193 @@ "packages": [ { "name": "alert_banner", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/alert_banner-1.0.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/alert_banner-1.0.1", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "animated_toggle_switch", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/animated_toggle_switch-0.8.3", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/animated_toggle_switch-0.8.3", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "args", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/args-2.6.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/args-2.6.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "async", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/async-2.11.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/async-2.11.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "boolean_selector", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "box_transform", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/box_transform-0.4.4", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/box_transform-0.4.4", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "characters", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/characters-1.3.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/characters-1.3.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "clock", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/clock-1.1.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/clock-1.1.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "collection", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/collection-1.19.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/collection-1.18.0", "packageUri": "lib/", - "languageVersion": "3.4" + "languageVersion": "2.18" }, { "name": "convert", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/convert-3.1.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/convert-3.1.1", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "cron", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/cron-0.6.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/cron-0.6.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "crypto", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/crypto-3.0.3", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/crypto-3.0.3", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "cupertino_icons", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/cupertino_icons-1.0.8", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/cupertino_icons-1.0.8", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "dart_earcut", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/dart_earcut-1.1.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/dart_earcut-1.1.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "dashed_path", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/dashed_path-1.0.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/dashed_path-1.0.1", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "datetime_picker_formfield", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/datetime_picker_formfield-2.0.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/datetime_picker_formfield-2.0.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "desktop_window", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/desktop_window-0.4.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/desktop_window-0.4.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "device_info_plus", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "device_info_plus_platform_interface", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/device_info_plus_platform_interface-7.0.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/device_info_plus_platform_interface-7.0.1", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "dio", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/dio-5.7.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/dio-5.7.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "dio_web_adapter", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/dio_web_adapter-2.0.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/dio_web_adapter-2.0.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "dotted_line", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/dotted_line-3.2.3", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/dotted_line-3.2.3", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "el_tooltip", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/el_tooltip-2.2.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/el_tooltip-2.2.1", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "fake_async", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/fake_async-1.3.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/fake_async-1.3.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "ffi", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/ffi-2.1.3", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/ffi-2.1.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "file", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/file-7.0.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/file-7.0.1", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "fixnum", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/fixnum-1.1.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/fixnum-1.1.1", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "flutter", - "rootUri": "file:///home/opencloud/Tools/flutter/packages/flutter", + "rootUri": "file:///home/mr/snap/flutter/common/flutter/packages/flutter", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "flutter_advanced_switch", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_advanced_switch-3.1.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/flutter_advanced_switch-3.1.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "flutter_box_transform", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_box_transform-0.4.6", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/flutter_box_transform-0.4.6", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "flutter_colorpicker", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_colorpicker-1.1.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/flutter_colorpicker-1.1.0", "packageUri": "lib/", "languageVersion": "2.14" }, { "name": "flutter_event_calendar", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_event_calendar-1.0.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/flutter_event_calendar-1.0.0", "packageUri": "lib/", "languageVersion": "2.12" }, @@ -201,523 +201,523 @@ }, { "name": "flutter_lints", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_lints-4.0.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/flutter_lints-4.0.0", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "flutter_map", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_map-7.0.2", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/flutter_map-7.0.2", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "flutter_spinkit", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_spinkit-5.2.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/flutter_spinkit-5.2.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "flutter_svg", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_svg-2.0.10+1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/flutter_svg-2.0.10+1", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "flutter_test", - "rootUri": "file:///home/opencloud/Tools/flutter/packages/flutter_test", + "rootUri": "file:///home/mr/snap/flutter/common/flutter/packages/flutter_test", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "flutter_web_plugins", - "rootUri": "file:///home/opencloud/Tools/flutter/packages/flutter_web_plugins", + "rootUri": "file:///home/mr/snap/flutter/common/flutter/packages/flutter_web_plugins", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "font_awesome_flutter", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/font_awesome_flutter-10.8.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/font_awesome_flutter-10.8.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "get_it", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/get_it-7.7.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/get_it-7.7.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "go_router", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/go_router-14.3.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/go_router-14.3.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "hover_menu", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/hover_menu-1.1.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/hover_menu-1.1.1", "packageUri": "lib/", "languageVersion": "2.16" }, { "name": "http", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/http-1.2.2", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/http-1.2.2", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "http_parser", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/http_parser-4.0.2", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/http_parser-4.0.2", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "injectable", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/injectable-2.4.2", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/injectable-2.4.2", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "intl", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/intl-0.19.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/intl-0.19.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "irondash_engine_context", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "irondash_message_channel", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/irondash_message_channel-0.7.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/irondash_message_channel-0.7.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "json_string", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/json_string-3.0.1", + "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/opencloud/.pub-cache/hosted/pub.dev/json_util-2.0.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/json_util-2.0.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "latlong2", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/latlong2-0.9.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/latlong2-0.9.1", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "leak_tracker", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker-10.0.7", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker-10.0.5", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "leak_tracker_flutter_testing", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.8", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.5", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "leak_tracker_testing", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.1", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "lints", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/lints-4.0.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/lints-4.0.0", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "lists", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/lists-1.0.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/lists-1.0.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "localstorage", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/localstorage-5.0.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/localstorage-5.0.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "logger", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/logger-2.4.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/logger-2.4.0", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "logging", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/logging-1.2.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/logging-1.2.0", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "matcher", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/matcher-0.12.16+1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/matcher-0.12.16+1", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "material_color_utilities", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "meta", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/meta-1.15.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/meta-1.15.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "mgrs_dart", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/mgrs_dart-2.0.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/mgrs_dart-2.0.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "number_text_input_formatter", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/number_text_input_formatter-1.0.0+8", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/number_text_input_formatter-1.0.0+8", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "path", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/path-1.9.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/path-1.9.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "path_parsing", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/path_parsing-1.0.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/path_parsing-1.0.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "path_provider", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider-2.1.4", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/path_provider-2.1.4", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "path_provider_android", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider_android-2.2.4", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/path_provider_android-2.2.4", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "path_provider_foundation", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "path_provider_linux", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "path_provider_platform_interface", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider_platform_interface-2.1.2", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/path_provider_platform_interface-2.1.2", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "path_provider_windows", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "petitparser", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/petitparser-6.0.2", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/petitparser-6.0.2", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "pixel_snap", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/pixel_snap-0.1.5", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/pixel_snap-0.1.5", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "platform", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/platform-3.1.6", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/platform-3.1.6", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "plugin_platform_interface", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "polylabel", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/polylabel-1.0.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/polylabel-1.0.1", "packageUri": "lib/", "languageVersion": "2.13" }, { "name": "proj4dart", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/proj4dart-2.1.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/proj4dart-2.1.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "scoped_model", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/scoped_model-2.0.0", + "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/opencloud/.pub-cache/hosted/pub.dev/shamsi_date-0.15.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/shamsi_date-0.15.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "shared_preferences", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences-2.2.3", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences-2.2.3", "packageUri": "lib/", "languageVersion": "3.1" }, { "name": "shared_preferences_android", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_android-2.2.2", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_android-2.2.2", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "shared_preferences_foundation", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.3", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "shared_preferences_linux", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "shared_preferences_platform_interface", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_platform_interface-2.4.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_platform_interface-2.4.1", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "shared_preferences_web", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.1", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "shared_preferences_windows", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "simple_gesture_detector", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/simple_gesture_detector-0.2.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/simple_gesture_detector-0.2.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "sky_engine", - "rootUri": "file:///home/opencloud/Tools/flutter/bin/cache/pkg/sky_engine", + "rootUri": "file:///home/mr/snap/flutter/common/flutter/bin/cache/pkg/sky_engine", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "source_span", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/source_span-1.10.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/source_span-1.10.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "sprintf", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/sprintf-7.0.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/sprintf-7.0.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "stack_trace", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/stack_trace-1.12.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/stack_trace-1.11.1", "packageUri": "lib/", - "languageVersion": "3.4" + "languageVersion": "2.18" }, { "name": "star_menu", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/star_menu-4.0.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/star_menu-4.0.1", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "stream_channel", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/stream_channel-2.1.2", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/stream_channel-2.1.2", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "string_scanner", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/string_scanner-1.3.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/string_scanner-1.2.0", "packageUri": "lib/", - "languageVersion": "3.1" + "languageVersion": "2.18" }, { "name": "super_clipboard", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/super_clipboard-0.8.19", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/super_clipboard-0.8.19", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "super_drag_and_drop", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/super_drag_and_drop-0.8.19", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/super_drag_and_drop-0.8.19", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "super_native_extensions", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "syncfusion_flutter_calendar", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/syncfusion_flutter_calendar-27.1.55", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_calendar-27.1.55", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "syncfusion_flutter_core", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/syncfusion_flutter_core-27.1.55", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_core-27.1.55", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "syncfusion_flutter_datepicker", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/syncfusion_flutter_datepicker-27.1.55", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_datepicker-27.1.55", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "table_calendar", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/table_calendar-3.1.2", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/table_calendar-3.1.2", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "term_glyph", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/term_glyph-1.2.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/term_glyph-1.2.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "test_api", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/test_api-0.7.3", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/test_api-0.7.2", "packageUri": "lib/", - "languageVersion": "3.4" + "languageVersion": "3.2" }, { "name": "timezone", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/timezone-0.9.4", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/timezone-0.9.4", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "typed_data", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/typed_data-1.3.2", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/typed_data-1.3.2", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "unicode", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/unicode-0.3.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/unicode-0.3.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "uuid", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/uuid-4.5.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/uuid-4.5.1", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "vector_graphics", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/vector_graphics-1.1.11+1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/vector_graphics-1.1.11+1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "vector_graphics_codec", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/vector_graphics_codec-1.1.11+1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/vector_graphics_codec-1.1.11+1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "vector_graphics_compiler", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/vector_graphics_compiler-1.1.11+1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/vector_graphics_compiler-1.1.11+1", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "vector_math", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/vector_math-2.1.4", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/vector_math-2.1.4", "packageUri": "lib/", "languageVersion": "2.14" }, { "name": "vm_service", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/vm_service-14.3.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/vm_service-14.2.5", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "web", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/web-0.5.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/web-0.5.1", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "win32", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/win32-5.7.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/win32-5.7.1", "packageUri": "lib/", "languageVersion": "3.5" }, { "name": "win32_registry", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/win32_registry-1.1.3", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/win32_registry-1.1.3", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "wkt_parser", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/wkt_parser-2.0.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/wkt_parser-2.0.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "xdg_directories", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "xml", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/xml-6.5.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/xml-6.5.0", "packageUri": "lib/", "languageVersion": "3.2" }, @@ -728,10 +728,10 @@ "languageVersion": "3.3" } ], - "generated": "2025-01-09T14:13:17.895902Z", + "generated": "2025-02-17T08:56:44.408862Z", "generator": "pub", - "generatorVersion": "3.6.0", - "flutterRoot": "file:///home/opencloud/Tools/flutter", - "flutterVersion": "3.27.1", - "pubCache": "file:///home/opencloud/.pub-cache" + "generatorVersion": "3.5.3", + "flutterRoot": "file:///home/mr/snap/flutter/common/flutter", + "flutterVersion": "3.24.3", + "pubCache": "file:///home/mr/.pub-cache" } diff --git a/.dart_tool/package_config_subset b/.dart_tool/package_config_subset index 570a0cc..59e124a 100644 --- a/.dart_tool/package_config_subset +++ b/.dart_tool/package_config_subset @@ -1,485 +1,485 @@ alert_banner 2.18 -file:///home/opencloud/.pub-cache/hosted/pub.dev/alert_banner-1.0.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/alert_banner-1.0.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/alert_banner-1.0.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/alert_banner-1.0.1/lib/ animated_toggle_switch 2.17 -file:///home/opencloud/.pub-cache/hosted/pub.dev/animated_toggle_switch-0.8.3/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/animated_toggle_switch-0.8.3/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/animated_toggle_switch-0.8.3/ +file:///home/mr/.pub-cache/hosted/pub.dev/animated_toggle_switch-0.8.3/lib/ args 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/args-2.6.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/args-2.6.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/args-2.6.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/args-2.6.0/lib/ async 2.18 -file:///home/opencloud/.pub-cache/hosted/pub.dev/async-2.11.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/async-2.11.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/async-2.11.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/async-2.11.0/lib/ boolean_selector 2.17 -file:///home/opencloud/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1/lib/ box_transform 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/box_transform-0.4.4/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/box_transform-0.4.4/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/box_transform-0.4.4/ +file:///home/mr/.pub-cache/hosted/pub.dev/box_transform-0.4.4/lib/ characters 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/characters-1.3.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/characters-1.3.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/characters-1.3.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/characters-1.3.0/lib/ clock 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/clock-1.1.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/clock-1.1.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/clock-1.1.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/clock-1.1.1/lib/ collection -3.4 -file:///home/opencloud/.pub-cache/hosted/pub.dev/collection-1.19.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/collection-1.19.0/lib/ +2.18 +file:///home/mr/.pub-cache/hosted/pub.dev/collection-1.18.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/collection-1.18.0/lib/ convert 2.18 -file:///home/opencloud/.pub-cache/hosted/pub.dev/convert-3.1.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/convert-3.1.1/lib/ +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/ cron 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/cron-0.6.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/cron-0.6.1/lib/ +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 2.19 -file:///home/opencloud/.pub-cache/hosted/pub.dev/crypto-3.0.3/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/crypto-3.0.3/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/crypto-3.0.3/ +file:///home/mr/.pub-cache/hosted/pub.dev/crypto-3.0.3/lib/ cupertino_icons 3.1 -file:///home/opencloud/.pub-cache/hosted/pub.dev/cupertino_icons-1.0.8/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/cupertino_icons-1.0.8/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/cupertino_icons-1.0.8/ +file:///home/mr/.pub-cache/hosted/pub.dev/cupertino_icons-1.0.8/lib/ dart_earcut 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/dart_earcut-1.1.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/dart_earcut-1.1.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/dart_earcut-1.1.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/dart_earcut-1.1.0/lib/ dashed_path 2.19 -file:///home/opencloud/.pub-cache/hosted/pub.dev/dashed_path-1.0.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/dashed_path-1.0.1/lib/ +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/ datetime_picker_formfield 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/datetime_picker_formfield-2.0.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/datetime_picker_formfield-2.0.1/lib/ +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 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/desktop_window-0.4.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/desktop_window-0.4.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/desktop_window-0.4.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/desktop_window-0.4.1/lib/ device_info_plus 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/ +file:///home/mr/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/lib/ device_info_plus_platform_interface 2.18 -file:///home/opencloud/.pub-cache/hosted/pub.dev/device_info_plus_platform_interface-7.0.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/device_info_plus_platform_interface-7.0.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/device_info_plus_platform_interface-7.0.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/device_info_plus_platform_interface-7.0.1/lib/ dio 2.18 -file:///home/opencloud/.pub-cache/hosted/pub.dev/dio-5.7.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/dio-5.7.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/dio-5.7.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/dio-5.7.0/lib/ dio_web_adapter 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/dio_web_adapter-2.0.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/dio_web_adapter-2.0.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/dio_web_adapter-2.0.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/dio_web_adapter-2.0.0/lib/ dotted_line 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/dotted_line-3.2.3/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/dotted_line-3.2.3/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/dotted_line-3.2.3/ +file:///home/mr/.pub-cache/hosted/pub.dev/dotted_line-3.2.3/lib/ el_tooltip 2.18 -file:///home/opencloud/.pub-cache/hosted/pub.dev/el_tooltip-2.2.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/el_tooltip-2.2.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/el_tooltip-2.2.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/el_tooltip-2.2.1/lib/ fake_async 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/fake_async-1.3.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/fake_async-1.3.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/fake_async-1.3.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/fake_async-1.3.1/lib/ ffi 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/ffi-2.1.3/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/ffi-2.1.3/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/ffi-2.1.3/ +file:///home/mr/.pub-cache/hosted/pub.dev/ffi-2.1.3/lib/ file 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/file-7.0.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/file-7.0.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/file-7.0.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/file-7.0.1/lib/ fixnum 3.1 -file:///home/opencloud/.pub-cache/hosted/pub.dev/fixnum-1.1.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/fixnum-1.1.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/fixnum-1.1.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/fixnum-1.1.1/lib/ flutter_advanced_switch 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_advanced_switch-3.1.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_advanced_switch-3.1.0/lib/ +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 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_box_transform-0.4.6/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_box_transform-0.4.6/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/flutter_box_transform-0.4.6/ +file:///home/mr/.pub-cache/hosted/pub.dev/flutter_box_transform-0.4.6/lib/ flutter_colorpicker 2.14 -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_colorpicker-1.1.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_colorpicker-1.1.0/lib/ +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/ flutter_event_calendar 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_event_calendar-1.0.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_event_calendar-1.0.0/lib/ +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 3.1 -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_lints-4.0.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_lints-4.0.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/flutter_lints-4.0.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/flutter_lints-4.0.0/lib/ flutter_map 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_map-7.0.2/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_map-7.0.2/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/flutter_map-7.0.2/ +file:///home/mr/.pub-cache/hosted/pub.dev/flutter_map-7.0.2/lib/ flutter_spinkit 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_spinkit-5.2.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_spinkit-5.2.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/flutter_spinkit-5.2.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/flutter_spinkit-5.2.1/lib/ flutter_svg 2.19 -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_svg-2.0.10+1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_svg-2.0.10+1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/flutter_svg-2.0.10+1/ +file:///home/mr/.pub-cache/hosted/pub.dev/flutter_svg-2.0.10+1/lib/ font_awesome_flutter 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/font_awesome_flutter-10.8.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/font_awesome_flutter-10.8.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/font_awesome_flutter-10.8.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/font_awesome_flutter-10.8.0/lib/ get_it 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/get_it-7.7.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/get_it-7.7.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/get_it-7.7.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/get_it-7.7.0/lib/ go_router 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/go_router-14.3.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/go_router-14.3.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/go_router-14.3.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/go_router-14.3.0/lib/ hover_menu 2.16 -file:///home/opencloud/.pub-cache/hosted/pub.dev/hover_menu-1.1.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/hover_menu-1.1.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/hover_menu-1.1.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/hover_menu-1.1.1/lib/ http 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/http-1.2.2/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/http-1.2.2/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/http-1.2.2/ +file:///home/mr/.pub-cache/hosted/pub.dev/http-1.2.2/lib/ http_parser 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/http_parser-4.0.2/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/http_parser-4.0.2/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/http_parser-4.0.2/ +file:///home/mr/.pub-cache/hosted/pub.dev/http_parser-4.0.2/lib/ injectable 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/injectable-2.4.2/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/injectable-2.4.2/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/injectable-2.4.2/ +file:///home/mr/.pub-cache/hosted/pub.dev/injectable-2.4.2/lib/ intl 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/intl-0.19.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/intl-0.19.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/intl-0.19.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/intl-0.19.0/lib/ irondash_engine_context 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4/ +file:///home/mr/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4/lib/ irondash_message_channel 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/irondash_message_channel-0.7.0/ -file:///home/opencloud/.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/ +file:///home/mr/.pub-cache/hosted/pub.dev/irondash_message_channel-0.7.0/lib/ json_string 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/json_string-3.0.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/json_string-3.0.1/lib/ +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/opencloud/.pub-cache/hosted/pub.dev/json_util-2.0.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/json_util-2.0.0/lib/ +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 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/latlong2-0.9.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/latlong2-0.9.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/latlong2-0.9.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/latlong2-0.9.1/lib/ leak_tracker 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker-10.0.7/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker-10.0.7/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker-10.0.5/ +file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker-10.0.5/lib/ leak_tracker_flutter_testing 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.8/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.8/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.5/ +file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.5/lib/ leak_tracker_testing 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.1/lib/ lints 3.1 -file:///home/opencloud/.pub-cache/hosted/pub.dev/lints-4.0.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/lints-4.0.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/lints-4.0.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/lints-4.0.0/lib/ lists 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/lists-1.0.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/lists-1.0.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/lists-1.0.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/lists-1.0.1/lib/ localstorage 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/localstorage-5.0.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/localstorage-5.0.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/localstorage-5.0.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/localstorage-5.0.0/lib/ logger 2.17 -file:///home/opencloud/.pub-cache/hosted/pub.dev/logger-2.4.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/logger-2.4.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/logger-2.4.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/logger-2.4.0/lib/ logging 2.19 -file:///home/opencloud/.pub-cache/hosted/pub.dev/logging-1.2.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/logging-1.2.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/logging-1.2.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/logging-1.2.0/lib/ matcher 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/matcher-0.12.16+1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/matcher-0.12.16+1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/matcher-0.12.16+1/ +file:///home/mr/.pub-cache/hosted/pub.dev/matcher-0.12.16+1/lib/ material_color_utilities 2.17 -file:///home/opencloud/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1/lib/ meta 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/meta-1.15.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/meta-1.15.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/meta-1.15.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/meta-1.15.0/lib/ mgrs_dart 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/mgrs_dart-2.0.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/mgrs_dart-2.0.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/mgrs_dart-2.0.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/mgrs_dart-2.0.0/lib/ number_text_input_formatter 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/number_text_input_formatter-1.0.0+8/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/number_text_input_formatter-1.0.0+8/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/number_text_input_formatter-1.0.0+8/ +file:///home/mr/.pub-cache/hosted/pub.dev/number_text_input_formatter-1.0.0+8/lib/ path 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/path-1.9.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/path-1.9.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/path-1.9.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/path-1.9.0/lib/ path_parsing 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/path_parsing-1.0.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/path_parsing-1.0.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/path_parsing-1.0.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/path_parsing-1.0.1/lib/ path_provider 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider-2.1.4/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider-2.1.4/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/path_provider-2.1.4/ +file:///home/mr/.pub-cache/hosted/pub.dev/path_provider-2.1.4/lib/ path_provider_android 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider_android-2.2.4/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider_android-2.2.4/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/path_provider_android-2.2.4/ +file:///home/mr/.pub-cache/hosted/pub.dev/path_provider_android-2.2.4/lib/ path_provider_foundation 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0/lib/ path_provider_linux 2.19 -file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/lib/ path_provider_platform_interface 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider_platform_interface-2.1.2/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider_platform_interface-2.1.2/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/path_provider_platform_interface-2.1.2/ +file:///home/mr/.pub-cache/hosted/pub.dev/path_provider_platform_interface-2.1.2/lib/ path_provider_windows 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/lib/ petitparser 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/petitparser-6.0.2/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/petitparser-6.0.2/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/petitparser-6.0.2/ +file:///home/mr/.pub-cache/hosted/pub.dev/petitparser-6.0.2/lib/ pixel_snap 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/pixel_snap-0.1.5/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/pixel_snap-0.1.5/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/pixel_snap-0.1.5/ +file:///home/mr/.pub-cache/hosted/pub.dev/pixel_snap-0.1.5/lib/ platform 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/platform-3.1.6/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/platform-3.1.6/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/platform-3.1.6/ +file:///home/mr/.pub-cache/hosted/pub.dev/platform-3.1.6/lib/ plugin_platform_interface 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8/ +file:///home/mr/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8/lib/ polylabel 2.13 -file:///home/opencloud/.pub-cache/hosted/pub.dev/polylabel-1.0.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/polylabel-1.0.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/polylabel-1.0.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/polylabel-1.0.1/lib/ proj4dart 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/proj4dart-2.1.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/proj4dart-2.1.0/lib/ +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/ scoped_model 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/scoped_model-2.0.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/scoped_model-2.0.0/lib/ +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/opencloud/.pub-cache/hosted/pub.dev/shamsi_date-0.15.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/shamsi_date-0.15.0/lib/ +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 3.1 -file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences-2.2.3/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences-2.2.3/lib/ +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/lib/ shared_preferences_android 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_android-2.2.2/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_android-2.2.2/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_android-2.2.2/ +file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_android-2.2.2/lib/ shared_preferences_foundation 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.3/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.3/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.3/ +file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.3/lib/ shared_preferences_linux 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/lib/ shared_preferences_platform_interface 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_platform_interface-2.4.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_platform_interface-2.4.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_platform_interface-2.4.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_platform_interface-2.4.1/lib/ shared_preferences_web 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.1/lib/ shared_preferences_windows 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/lib/ simple_gesture_detector 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/simple_gesture_detector-0.2.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/simple_gesture_detector-0.2.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/simple_gesture_detector-0.2.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/simple_gesture_detector-0.2.1/lib/ source_span 2.18 -file:///home/opencloud/.pub-cache/hosted/pub.dev/source_span-1.10.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/source_span-1.10.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/source_span-1.10.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/source_span-1.10.0/lib/ sprintf 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/sprintf-7.0.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/sprintf-7.0.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/sprintf-7.0.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/sprintf-7.0.0/lib/ stack_trace -3.4 -file:///home/opencloud/.pub-cache/hosted/pub.dev/stack_trace-1.12.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/stack_trace-1.12.0/lib/ +2.18 +file:///home/mr/.pub-cache/hosted/pub.dev/stack_trace-1.11.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/stack_trace-1.11.1/lib/ star_menu 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/star_menu-4.0.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/star_menu-4.0.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/star_menu-4.0.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/star_menu-4.0.1/lib/ stream_channel 2.19 -file:///home/opencloud/.pub-cache/hosted/pub.dev/stream_channel-2.1.2/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/stream_channel-2.1.2/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/stream_channel-2.1.2/ +file:///home/mr/.pub-cache/hosted/pub.dev/stream_channel-2.1.2/lib/ string_scanner -3.1 -file:///home/opencloud/.pub-cache/hosted/pub.dev/string_scanner-1.3.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/string_scanner-1.3.0/lib/ +2.18 +file:///home/mr/.pub-cache/hosted/pub.dev/string_scanner-1.2.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/string_scanner-1.2.0/lib/ super_clipboard 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/super_clipboard-0.8.19/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/super_clipboard-0.8.19/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/super_clipboard-0.8.19/ +file:///home/mr/.pub-cache/hosted/pub.dev/super_clipboard-0.8.19/lib/ super_drag_and_drop 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/super_drag_and_drop-0.8.19/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/super_drag_and_drop-0.8.19/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/super_drag_and_drop-0.8.19/ +file:///home/mr/.pub-cache/hosted/pub.dev/super_drag_and_drop-0.8.19/lib/ super_native_extensions 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/ +file:///home/mr/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/lib/ syncfusion_flutter_calendar 2.17 -file:///home/opencloud/.pub-cache/hosted/pub.dev/syncfusion_flutter_calendar-27.1.55/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/syncfusion_flutter_calendar-27.1.55/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_calendar-27.1.55/ +file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_calendar-27.1.55/lib/ syncfusion_flutter_core 2.17 -file:///home/opencloud/.pub-cache/hosted/pub.dev/syncfusion_flutter_core-27.1.55/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/syncfusion_flutter_core-27.1.55/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_core-27.1.55/ +file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_core-27.1.55/lib/ syncfusion_flutter_datepicker 2.17 -file:///home/opencloud/.pub-cache/hosted/pub.dev/syncfusion_flutter_datepicker-27.1.55/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/syncfusion_flutter_datepicker-27.1.55/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_datepicker-27.1.55/ +file:///home/mr/.pub-cache/hosted/pub.dev/syncfusion_flutter_datepicker-27.1.55/lib/ table_calendar 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/table_calendar-3.1.2/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/table_calendar-3.1.2/lib/ +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/lib/ term_glyph 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/term_glyph-1.2.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/term_glyph-1.2.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/term_glyph-1.2.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/term_glyph-1.2.1/lib/ test_api -3.4 -file:///home/opencloud/.pub-cache/hosted/pub.dev/test_api-0.7.3/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/test_api-0.7.3/lib/ +3.2 +file:///home/mr/.pub-cache/hosted/pub.dev/test_api-0.7.2/ +file:///home/mr/.pub-cache/hosted/pub.dev/test_api-0.7.2/lib/ timezone 2.19 -file:///home/opencloud/.pub-cache/hosted/pub.dev/timezone-0.9.4/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/timezone-0.9.4/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/timezone-0.9.4/ +file:///home/mr/.pub-cache/hosted/pub.dev/timezone-0.9.4/lib/ typed_data 2.17 -file:///home/opencloud/.pub-cache/hosted/pub.dev/typed_data-1.3.2/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/typed_data-1.3.2/lib/ +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/lib/ unicode 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/unicode-0.3.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/unicode-0.3.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/unicode-0.3.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/unicode-0.3.1/lib/ uuid 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/uuid-4.5.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/uuid-4.5.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/uuid-4.5.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/uuid-4.5.1/lib/ vector_graphics 2.17 -file:///home/opencloud/.pub-cache/hosted/pub.dev/vector_graphics-1.1.11+1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/vector_graphics-1.1.11+1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/vector_graphics-1.1.11+1/ +file:///home/mr/.pub-cache/hosted/pub.dev/vector_graphics-1.1.11+1/lib/ vector_graphics_codec 2.17 -file:///home/opencloud/.pub-cache/hosted/pub.dev/vector_graphics_codec-1.1.11+1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/vector_graphics_codec-1.1.11+1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/vector_graphics_codec-1.1.11+1/ +file:///home/mr/.pub-cache/hosted/pub.dev/vector_graphics_codec-1.1.11+1/lib/ vector_graphics_compiler 2.19 -file:///home/opencloud/.pub-cache/hosted/pub.dev/vector_graphics_compiler-1.1.11+1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/vector_graphics_compiler-1.1.11+1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/vector_graphics_compiler-1.1.11+1/ +file:///home/mr/.pub-cache/hosted/pub.dev/vector_graphics_compiler-1.1.11+1/lib/ vector_math 2.14 -file:///home/opencloud/.pub-cache/hosted/pub.dev/vector_math-2.1.4/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/vector_math-2.1.4/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/vector_math-2.1.4/ +file:///home/mr/.pub-cache/hosted/pub.dev/vector_math-2.1.4/lib/ vm_service 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/vm_service-14.3.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/vm_service-14.3.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/vm_service-14.2.5/ +file:///home/mr/.pub-cache/hosted/pub.dev/vm_service-14.2.5/lib/ web 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/web-0.5.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/web-0.5.1/lib/ +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/ win32 3.5 -file:///home/opencloud/.pub-cache/hosted/pub.dev/win32-5.7.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/win32-5.7.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/win32-5.7.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/win32-5.7.1/lib/ win32_registry 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/win32_registry-1.1.3/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/win32_registry-1.1.3/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/win32_registry-1.1.3/ +file:///home/mr/.pub-cache/hosted/pub.dev/win32_registry-1.1.3/lib/ wkt_parser 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/wkt_parser-2.0.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/wkt_parser-2.0.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/wkt_parser-2.0.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/wkt_parser-2.0.0/lib/ xdg_directories 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0/lib/ xml 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/xml-6.5.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/xml-6.5.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/xml-6.5.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/xml-6.5.0/lib/ oc_front 3.3 -file:///home/opencloud/Source/opencloud/oc-local/src/oc-front/ -file:///home/opencloud/Source/opencloud/oc-local/src/oc-front/lib/ +file:///home/mr/Documents/OC/oc-front/ +file:///home/mr/Documents/OC/oc-front/lib/ flutter_flow_chart 3.3 -file:///home/opencloud/Source/opencloud/oc-local/src/oc-front/library/flutter_flow_chart/ -file:///home/opencloud/Source/opencloud/oc-local/src/oc-front/library/flutter_flow_chart/lib/ +file:///home/mr/Documents/OC/oc-front/library/flutter_flow_chart/ +file:///home/mr/Documents/OC/oc-front/library/flutter_flow_chart/lib/ sky_engine 3.2 -file:///home/opencloud/Tools/flutter/bin/cache/pkg/sky_engine/ -file:///home/opencloud/Tools/flutter/bin/cache/pkg/sky_engine/lib/ +file:///home/mr/snap/flutter/common/flutter/bin/cache/pkg/sky_engine/ +file:///home/mr/snap/flutter/common/flutter/bin/cache/pkg/sky_engine/lib/ flutter 3.3 -file:///home/opencloud/Tools/flutter/packages/flutter/ -file:///home/opencloud/Tools/flutter/packages/flutter/lib/ +file:///home/mr/snap/flutter/common/flutter/packages/flutter/ +file:///home/mr/snap/flutter/common/flutter/packages/flutter/lib/ flutter_test 3.3 -file:///home/opencloud/Tools/flutter/packages/flutter_test/ -file:///home/opencloud/Tools/flutter/packages/flutter_test/lib/ +file:///home/mr/snap/flutter/common/flutter/packages/flutter_test/ +file:///home/mr/snap/flutter/common/flutter/packages/flutter_test/lib/ flutter_web_plugins 3.2 -file:///home/opencloud/Tools/flutter/packages/flutter_web_plugins/ -file:///home/opencloud/Tools/flutter/packages/flutter_web_plugins/lib/ +file:///home/mr/snap/flutter/common/flutter/packages/flutter_web_plugins/ +file:///home/mr/snap/flutter/common/flutter/packages/flutter_web_plugins/lib/ 2 diff --git a/.dart_tool/version b/.dart_tool/version index b8b1d81..ffba2c8 100644 --- a/.dart_tool/version +++ b/.dart_tool/version @@ -1 +1 @@ -3.27.1 \ No newline at end of file +3.24.3 \ No newline at end of file diff --git a/.flutter-plugins b/.flutter-plugins index bb17651..9bdf805 100644 --- a/.flutter-plugins +++ b/.flutter-plugins @@ -1,16 +1,16 @@ # This is a generated file; do not edit or check into version control. -desktop_window=/home/opencloud/.pub-cache/hosted/pub.dev/desktop_window-0.4.1/ -device_info_plus=/home/opencloud/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/ -irondash_engine_context=/home/opencloud/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4/ -path_provider=/home/opencloud/.pub-cache/hosted/pub.dev/path_provider-2.1.4/ -path_provider_android=/home/opencloud/.pub-cache/hosted/pub.dev/path_provider_android-2.2.4/ -path_provider_foundation=/home/opencloud/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0/ -path_provider_linux=/home/opencloud/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ -path_provider_windows=/home/opencloud/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/ -shared_preferences=/home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences-2.2.3/ -shared_preferences_android=/home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_android-2.2.2/ -shared_preferences_foundation=/home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.3/ -shared_preferences_linux=/home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/ -shared_preferences_web=/home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.1/ -shared_preferences_windows=/home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/ -super_native_extensions=/home/opencloud/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/ +desktop_window=/home/mr/.pub-cache/hosted/pub.dev/desktop_window-0.4.1/ +device_info_plus=/home/mr/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/ +irondash_engine_context=/home/mr/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4/ +path_provider=/home/mr/.pub-cache/hosted/pub.dev/path_provider-2.1.4/ +path_provider_android=/home/mr/.pub-cache/hosted/pub.dev/path_provider_android-2.2.4/ +path_provider_foundation=/home/mr/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0/ +path_provider_linux=/home/mr/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ +path_provider_windows=/home/mr/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/ +shared_preferences=/home/mr/.pub-cache/hosted/pub.dev/shared_preferences-2.2.3/ +shared_preferences_android=/home/mr/.pub-cache/hosted/pub.dev/shared_preferences_android-2.2.2/ +shared_preferences_foundation=/home/mr/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.3/ +shared_preferences_linux=/home/mr/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/ +shared_preferences_web=/home/mr/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.1/ +shared_preferences_windows=/home/mr/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/ +super_native_extensions=/home/mr/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/ diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 84772c5..390d52c 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"device_info_plus","path":"/home/opencloud/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/","native_build":true,"dependencies":[]},{"name":"irondash_engine_context","path":"/home/opencloud/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/home/opencloud/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"shared_preferences_foundation","path":"/home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.3/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"super_native_extensions","path":"/home/opencloud/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/","native_build":true,"dependencies":["irondash_engine_context","device_info_plus"]}],"android":[{"name":"device_info_plus","path":"/home/opencloud/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/","native_build":true,"dependencies":[]},{"name":"irondash_engine_context","path":"/home/opencloud/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4/","native_build":true,"dependencies":[]},{"name":"path_provider_android","path":"/home/opencloud/.pub-cache/hosted/pub.dev/path_provider_android-2.2.4/","native_build":true,"dependencies":[]},{"name":"shared_preferences_android","path":"/home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_android-2.2.2/","native_build":true,"dependencies":[]},{"name":"super_native_extensions","path":"/home/opencloud/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/","native_build":true,"dependencies":["irondash_engine_context","device_info_plus"]}],"macos":[{"name":"desktop_window","path":"/home/opencloud/.pub-cache/hosted/pub.dev/desktop_window-0.4.1/","native_build":true,"dependencies":[]},{"name":"device_info_plus","path":"/home/opencloud/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/","native_build":true,"dependencies":[]},{"name":"irondash_engine_context","path":"/home/opencloud/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/home/opencloud/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"shared_preferences_foundation","path":"/home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.3/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"super_native_extensions","path":"/home/opencloud/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/","native_build":true,"dependencies":["irondash_engine_context","device_info_plus"]}],"linux":[{"name":"desktop_window","path":"/home/opencloud/.pub-cache/hosted/pub.dev/desktop_window-0.4.1/","native_build":true,"dependencies":[]},{"name":"device_info_plus","path":"/home/opencloud/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/","native_build":false,"dependencies":[]},{"name":"irondash_engine_context","path":"/home/opencloud/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4/","native_build":true,"dependencies":[]},{"name":"path_provider_linux","path":"/home/opencloud/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[]},{"name":"shared_preferences_linux","path":"/home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/","native_build":false,"dependencies":["path_provider_linux"]},{"name":"super_native_extensions","path":"/home/opencloud/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/","native_build":true,"dependencies":["irondash_engine_context","device_info_plus"]}],"windows":[{"name":"desktop_window","path":"/home/opencloud/.pub-cache/hosted/pub.dev/desktop_window-0.4.1/","native_build":true,"dependencies":[]},{"name":"device_info_plus","path":"/home/opencloud/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/","native_build":false,"dependencies":[]},{"name":"irondash_engine_context","path":"/home/opencloud/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4/","native_build":true,"dependencies":[]},{"name":"path_provider_windows","path":"/home/opencloud/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[]},{"name":"shared_preferences_windows","path":"/home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/","native_build":false,"dependencies":["path_provider_windows"]},{"name":"super_native_extensions","path":"/home/opencloud/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/","native_build":true,"dependencies":["irondash_engine_context","device_info_plus"]}],"web":[{"name":"device_info_plus","path":"/home/opencloud/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/","dependencies":[]},{"name":"shared_preferences_web","path":"/home/opencloud/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.1/","dependencies":[]},{"name":"super_native_extensions","path":"/home/opencloud/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/","dependencies":["device_info_plus"]}]},"dependencyGraph":[{"name":"desktop_window","dependencies":[]},{"name":"device_info_plus","dependencies":[]},{"name":"irondash_engine_context","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]},{"name":"super_native_extensions","dependencies":["irondash_engine_context","device_info_plus"]}],"date_created":"2025-01-09 15:13:25.803643","version":"3.27.1","swift_package_manager_enabled":false} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"device_info_plus","path":"/home/mr/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/","native_build":true,"dependencies":[]},{"name":"irondash_engine_context","path":"/home/mr/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/home/mr/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"shared_preferences_foundation","path":"/home/mr/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.3/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"super_native_extensions","path":"/home/mr/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/","native_build":true,"dependencies":["irondash_engine_context","device_info_plus"]}],"android":[{"name":"device_info_plus","path":"/home/mr/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/","native_build":true,"dependencies":[]},{"name":"irondash_engine_context","path":"/home/mr/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4/","native_build":true,"dependencies":[]},{"name":"path_provider_android","path":"/home/mr/.pub-cache/hosted/pub.dev/path_provider_android-2.2.4/","native_build":true,"dependencies":[]},{"name":"shared_preferences_android","path":"/home/mr/.pub-cache/hosted/pub.dev/shared_preferences_android-2.2.2/","native_build":true,"dependencies":[]},{"name":"super_native_extensions","path":"/home/mr/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/","native_build":true,"dependencies":["irondash_engine_context","device_info_plus"]}],"macos":[{"name":"desktop_window","path":"/home/mr/.pub-cache/hosted/pub.dev/desktop_window-0.4.1/","native_build":true,"dependencies":[]},{"name":"device_info_plus","path":"/home/mr/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/","native_build":true,"dependencies":[]},{"name":"irondash_engine_context","path":"/home/mr/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/home/mr/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.0/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"shared_preferences_foundation","path":"/home/mr/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.3/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"super_native_extensions","path":"/home/mr/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/","native_build":true,"dependencies":["irondash_engine_context","device_info_plus"]}],"linux":[{"name":"desktop_window","path":"/home/mr/.pub-cache/hosted/pub.dev/desktop_window-0.4.1/","native_build":true,"dependencies":[]},{"name":"device_info_plus","path":"/home/mr/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/","native_build":false,"dependencies":[]},{"name":"irondash_engine_context","path":"/home/mr/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4/","native_build":true,"dependencies":[]},{"name":"path_provider_linux","path":"/home/mr/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[]},{"name":"shared_preferences_linux","path":"/home/mr/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/","native_build":false,"dependencies":["path_provider_linux"]},{"name":"super_native_extensions","path":"/home/mr/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/","native_build":true,"dependencies":["irondash_engine_context","device_info_plus"]}],"windows":[{"name":"desktop_window","path":"/home/mr/.pub-cache/hosted/pub.dev/desktop_window-0.4.1/","native_build":true,"dependencies":[]},{"name":"device_info_plus","path":"/home/mr/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/","native_build":false,"dependencies":[]},{"name":"irondash_engine_context","path":"/home/mr/.pub-cache/hosted/pub.dev/irondash_engine_context-0.5.4/","native_build":true,"dependencies":[]},{"name":"path_provider_windows","path":"/home/mr/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[]},{"name":"shared_preferences_windows","path":"/home/mr/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1/","native_build":false,"dependencies":["path_provider_windows"]},{"name":"super_native_extensions","path":"/home/mr/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/","native_build":true,"dependencies":["irondash_engine_context","device_info_plus"]}],"web":[{"name":"device_info_plus","path":"/home/mr/.pub-cache/hosted/pub.dev/device_info_plus-10.1.2/","dependencies":[]},{"name":"shared_preferences_web","path":"/home/mr/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.1/","dependencies":[]},{"name":"super_native_extensions","path":"/home/mr/.pub-cache/hosted/pub.dev/super_native_extensions-0.8.19/","dependencies":["device_info_plus"]}]},"dependencyGraph":[{"name":"desktop_window","dependencies":[]},{"name":"device_info_plus","dependencies":[]},{"name":"irondash_engine_context","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]},{"name":"super_native_extensions","dependencies":["irondash_engine_context","device_info_plus"]}],"date_created":"2025-02-17 09:56:44.733341","version":"3.24.3","swift_package_manager_enabled":false} \ No newline at end of file diff --git a/lib/core/models/shared_workspace_local.dart b/lib/core/models/shared_workspace_local.dart index 28e7b5e..e9aa615 100644 --- a/lib/core/models/shared_workspace_local.dart +++ b/lib/core/models/shared_workspace_local.dart @@ -41,7 +41,7 @@ class CollaborativeAreaLocal { await _service.delete(null, id, {}); } - static Future createCollaborativeArea(String name, BuildContext? context) async { + static Future createCollaborativeArea(BuildContext context, String name) async { Workspace n = Workspace(name: name); await _service.post(context, n.serialize(), {}).then((value) { if (value.data != null) { diff --git a/lib/core/models/workspace_local.dart b/lib/core/models/workspace_local.dart index 8a57959..13291c3 100644 --- a/lib/core/models/workspace_local.dart +++ b/lib/core/models/workspace_local.dart @@ -1,9 +1,13 @@ 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/core/sections/header/header.dart'; +import 'package:oc_front/models/resources/compute.dart'; +import 'package:oc_front/models/resources/data.dart'; +import 'package:oc_front/models/resources/processing.dart'; +import 'package:oc_front/models/resources/resources.dart'; +import 'package:oc_front/models/resources/storage.dart'; +import 'package:oc_front/models/resources/workflow.dart'; import 'package:oc_front/models/response.dart'; -import 'package:oc_front/models/search.dart'; import 'package:oc_front/models/workspace.dart'; import 'package:oc_front/core/services/specialized_services/workspace_service.dart'; import 'package:oc_front/pages/catalog.dart'; @@ -22,7 +26,7 @@ class WorkspaceLocal { static final WorkspaceService _service = WorkspaceService(); static List items = []; - static Future init(BuildContext context, bool changeCurrent) async { + static Future init(BuildContext? context, bool changeCurrent) async { var value = await _service.all(context); if (value.data != null && value.data!.values.isNotEmpty ) { var vals = value.data!.values; @@ -144,7 +148,7 @@ class WorkspaceLocal { } static List byWorkspace(String id) { - List> d = []; + List d = []; var w = workspaces[id]!; d = [ ...d, ...w.datas.where((element) => !d.map( (d2) => d2.id).contains(element.id)) ]; d = [ ...d, ...w.computes.where((element) => !d.map( (d2) => d2.id).contains(element.id)) ]; @@ -156,7 +160,7 @@ class WorkspaceLocal { static List byTopic(String topic, bool all) { if (all) { - List> d = []; + List d = []; for (var w in workspaces.values) { d = [ ...d, ...w.datas.where((element) => !d.map( (d2) => d2.id).contains(element.id)) ]; d = [ ...d, ...w.computes.where((element) => !d.map( (d2) => d2.id).contains(element.id)) ]; @@ -171,7 +175,7 @@ class WorkspaceLocal { static AbstractItem? getItem(String id, bool all) { if (all) { - List> d = []; + List 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.computes.where((element) => element.id.toString() == id).where((element) => !d.map( (d2) => d2.id).contains(element.id)) ]; @@ -189,13 +193,15 @@ class WorkspaceLocal { if (!WorkspaceLocal.hasItem(item) && workspaces[current] != null && workspaces[current]!.id != null) { items.add(item); if (item.topic == "data") { workspaces[current]!.datas.add(item as DataItem); } - if (item.topic == "processing") { workspaces[current]!.processings.add(item as ProcessingItem); } + if (item.topic == "processing") { workspaces[current]!.processings.add(item as ProcessingItem); } if (item.topic == "compute") { workspaces[current]!.computes.add(item as ComputeItem); } 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) { /* */ } - _service.put(null, item.id ?? "", workspaces[current]!.serialize(), {}); + try { + _service.put(null, workspaces[current]!.id!, workspaces[current]!.serialize(), {}); + } catch (e) { + _service.put(null, item.id ?? "", workspaces[current]!.serialize(), {}); + } } } static void removeItem(AbstractItem item) { @@ -205,9 +211,11 @@ class WorkspaceLocal { if (item.topic == "compute") { workspaces[current]!.computes.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) { /* */ } - _service.put(null, item.id ?? "", workspaces[current]!.serialize(), {}); + try { + _service.put(null, workspaces[current]!.id!, workspaces[current]!.serialize(), {}); + } catch (e) { + _service.put(null, item.id ?? "", workspaces[current]!.serialize(), {}); + } } static bool hasItemByID(String id) { return items.where((element) => element.id == id).isNotEmpty; diff --git a/lib/core/sections/end_drawer.dart b/lib/core/sections/end_drawer.dart index e9ec330..a735181 100644 --- a/lib/core/sections/end_drawer.dart +++ b/lib/core/sections/end_drawer.dart @@ -1,11 +1,12 @@ -import 'package:flutter/material.dart'; import 'package:oc_front/main.dart'; -import 'package:oc_front/models/search.dart'; -import 'package:oc_front/pages/catalog.dart'; -import 'package:oc_front/core/models/workspace_local.dart'; +import 'package:flutter/material.dart'; import 'package:oc_front/pages/shared.dart'; -import 'package:oc_front/widgets/inputs/shallow_text_input.dart'; +import 'package:oc_front/pages/catalog.dart'; import 'package:oc_front/widgets/items/item_row.dart'; +import 'package:oc_front/models/resources/resources.dart'; +import 'package:oc_front/core/models/workspace_local.dart'; +import 'package:oc_front/widgets/inputs/shallow_text_input.dart'; +import 'package:oc_front/core/models/shared_workspace_local.dart'; import 'package:oc_front/widgets/inputs/shallow_dropdown_input.dart'; import 'package:oc_front/core/services/specialized_services/workspace_service.dart'; @@ -62,7 +63,7 @@ class EndDrawerWidgetState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Padding(padding: EdgeInsets.only(right: 5), child: Icon(Icons.share, size: 12, color: Colors.grey)), Text( (WorkspaceLocal.workspaces[WorkspaceLocal.current]?.shared) == null ? - "actually not shared" : "share with ${WorkspaceLocal.workspaces[WorkspaceLocal.current]!.shared!}", + "actually not shared" : "share with ${CollaborativeAreaLocal.workspaces[WorkspaceLocal.workspaces[WorkspaceLocal.current]!.shared!]}", style: TextStyle( fontSize: 14, color: Colors.grey ),), ]), ), diff --git a/lib/core/sections/header/header.dart b/lib/core/sections/header/header.dart index 482a131..8b7f9b5 100644 --- a/lib/core/sections/header/header.dart +++ b/lib/core/sections/header/header.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:localstorage/localstorage.dart'; import 'package:oc_front/core/models/workspace_local.dart'; import 'package:oc_front/core/sections/header/default.dart'; import 'package:oc_front/core/sections/header/menu.dart'; @@ -14,7 +15,10 @@ class SearchConstants { static String? get() { return _searchHost[AppRouter.currentRoute.route]; } static void set(String? search) { _searchHost[AppRouter.currentRoute.route] = search; } static void remove() { _searchHost.remove(AppRouter.currentRoute.route); } - static void clear() { _searchHost.clear(); } + static void clear() { + localStorage.setItem("search", ""); + _searchHost.clear(); + } } class HeaderConstants { @@ -56,7 +60,7 @@ class HeaderConstants { } class HeaderWidget extends StatefulWidget { - HeaderWidget () : super(key: null); + const HeaderWidget () : super(key: null); @override HeaderWidgetState createState() => HeaderWidgetState(); } class HeaderWidgetState extends State { @@ -79,24 +83,34 @@ class HeaderWidgetState extends State { child: Row(crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisAlignment: MainAxisAlignment.end, children: [ + InkWell( onTap: () { + AppRouter.currentRoute.factory.back(context); + }, + child: + Container(width: 50, height: 50, + color: Colors.black, + child: Center(child: Icon(Icons.keyboard_backspace, color: Colors.white)) + ), + ), ShallowTextInputWidget( - filled: midColor, - width: getMainWidth(context) - 451, - type: CollaborativeAreaType.workspace, - hint: "search in resources...", - iconLoad: PermsService.getPerm(Perms.SEARCH_INTERNAL) ? Icons.search : null, - iconRemove: PermsService.getPerm(Perms.SEARCH_EXTERNAL) ? Icons.screen_search_desktop_outlined : null, - tooltipLoad: PermsService.getPerm(Perms.SEARCH_INTERNAL) ? "search" : null, - tooltipRemove: PermsService.getPerm(Perms.SEARCH_EXTERNAL) ? "distributed search" : null, - canLoad: PermsService.getPerm(Perms.SEARCH_INTERNAL) ? (String? str) => str != null && str.isNotEmpty : null, - canRemove: PermsService.getPerm(Perms.SEARCH_EXTERNAL) ? (String? str) => str != null && str.isNotEmpty : null, - change: (value) => SearchConstants.set(value), - loadStr: PermsService.getPerm(Perms.SEARCH_INTERNAL) ? (String val) async { - AppRouter.currentRoute.factory.search(context, false); - } : null, - remove: PermsService.getPerm(Perms.SEARCH_EXTERNAL) ? (String val) async { - AppRouter.currentRoute.factory.search(context, true); - } : null, + filled: midColor, + current: AppRouter.currentRoute.factory.getSearch(), + width: getMainWidth(context) - 501, + type: CollaborativeAreaType.workspace, + hint: "search in resources...", + iconLoad: PermsService.getPerm(Perms.SEARCH_INTERNAL) ? Icons.search : null, + iconRemove: PermsService.getPerm(Perms.SEARCH_EXTERNAL) ? Icons.screen_search_desktop_outlined : null, + tooltipLoad: PermsService.getPerm(Perms.SEARCH_INTERNAL) ? "search" : null, + tooltipRemove: PermsService.getPerm(Perms.SEARCH_EXTERNAL) ? "distributed search" : null, + canLoad: PermsService.getPerm(Perms.SEARCH_INTERNAL) ? (String? str) => str != null && str.isNotEmpty : null, + canRemove: PermsService.getPerm(Perms.SEARCH_EXTERNAL) ? (String? str) => str != null && str.isNotEmpty : null, + change: (value) => SearchConstants.set(value), + loadStr: PermsService.getPerm(Perms.SEARCH_INTERNAL) ? (String val) async { + AppRouter.currentRoute.factory.search(context, false); + } : null, + remove: PermsService.getPerm(Perms.SEARCH_EXTERNAL) ? (String val) async { + AppRouter.currentRoute.factory.search(context, true); + } : null, ), Container( padding: EdgeInsets.only(left: 50), decoration: BoxDecoration( border: Border( left: BorderSide( color: Colors.white ))), diff --git a/lib/core/sections/header/menu.dart b/lib/core/sections/header/menu.dart index 6b71ac4..d0fd065 100644 --- a/lib/core/sections/header/menu.dart +++ b/lib/core/sections/header/menu.dart @@ -5,13 +5,13 @@ import 'package:oc_front/core/services/auth.service.dart'; import 'package:oc_front/core/services/router.dart'; import 'package:oc_front/main.dart'; import 'package:flutter/material.dart'; +import 'package:oc_front/pages/catalog.dart'; class HeaderMenuWidget extends StatefulWidget{ HeaderMenuWidget (): super(key: HeaderConstants.getKey()); @override HeaderMenuWidgetState createState() => HeaderMenuWidgetState(); } class HeaderMenuWidgetState extends State { - @override Widget build(BuildContext context) { return Container( width: getWidth(context), @@ -23,12 +23,16 @@ class HeaderMenuWidgetState extends State { child: Stack(children: [ AppRouter.currentRoute.factory.searchFill() ? Container() : Positioned( top: 0, left: 30, child: InkWell( onTap: () { + CatalogFactory.key.currentState?.widget.isSearch = true; + CatalogFactory.key.currentState?.widget.items = []; AppRouter.zones.first.go(context, {}); + AppRouter.zones.first.factory.getKey().currentState?.setState(() {}); + HeaderConstants.headerKey.currentState?.setState(() {}); }, child: Wrap( alignment: WrapAlignment.center, children: [ - SvgPicture.asset("assets/images/icon.svg", width: 70, height: 70, semanticsLabel: 'OpenCloud Logo'), - Container( height: 50, alignment: Alignment.centerLeft, margin: const EdgeInsets.only(left: 20), - child: Text(AppRouter.currentRoute.label ?? "Where am I ?", style: TextStyle( color: Colors.grey))) + SvgPicture.asset("assets/images/icon.svg", width: 70, height: 70, semanticsLabel: 'OpenCloud Logo'), + Container( height: 50, alignment: Alignment.centerLeft, margin: const EdgeInsets.only(left: 20), + child: Text(AppRouter.currentRoute.label ?? "Where am I ?", style: TextStyle( color: Colors.grey))) ]))), Padding( padding: const EdgeInsets.only(left: 50), child: Row(crossAxisAlignment: CrossAxisAlignment.stretch, diff --git a/lib/core/services/api_service.dart b/lib/core/services/api_service.dart index b224a72..6b18441 100644 --- a/lib/core/services/api_service.dart +++ b/lib/core/services/api_service.dart @@ -18,9 +18,8 @@ class APIService { Dio _dio = Dio( BaseOptions( - baseUrl: config.get('HOST', - defaultValue: 'http://localhost:8080'), // you can keep this blank - headers: {'Content-Type': 'application/json; charset=UTF-8'}, + baseUrl: const String.fromEnvironment('HOST', defaultValue: 'http://localhost:8080'), // you can keep this blank + headers: { 'Content-Type': 'application/json; charset=UTF-8', 'Access-Control-Allow-Origin': '*' }, ), )..interceptors.add(LogInterceptor( requestHeader: true, @@ -30,7 +29,7 @@ class APIService { _dio = Dio( BaseOptions( baseUrl: baseURL, // you can keep this blank - headers: {'Content-Type': 'application/json; charset=UTF-8'}, + headers: { 'Content-Type': 'application/json; charset=UTF-8', 'Access-Control-Allow-Origin': '*' }, ), )..interceptors.add( LogInterceptor( @@ -102,45 +101,29 @@ class APIService { } catch (e) {/* */} } - Future> _main( - String url, - dynamic body, - String method, - String succeed, - bool force, - BuildContext? context, - Options? options) async { - var err = ""; - try { - var type = localStorage.getItem('tokenType') ?? "bearer"; - _dio.options.headers["Authorization"] = - "${type[0].toUpperCase() + type.substring(1)} ${localStorage.getItem('accessToken') ?? ""}"; - _dio.interceptors.clear(); - var response = await _request(url, method, body, options); - if (response.statusCode != null && response.statusCode! < 400) { - if (method == "delete") { - cache.remove(url); - return APIResponse(); - } - APIResponse resp = APIResponse().deserialize(response.data); - if (resp.error == "") { - if (context != null && succeed != "") { - // ignore: use_build_context_synchronously - showAlertBanner( - context, - () {}, - InfoAlertBannerChild( - text: succeed), // <-- Put any widget here you want! - alertBannerLocation: AlertBannerLocation.bottom, - ); + Future> _main(String url, dynamic body, String method, String succeed, bool force, + BuildContext? context, Options? options) async { + var err = ""; + try { + var type = localStorage.getItem('tokenType') ?? "bearer"; + _dio.options.headers["Authorization"] = "${type[0].toUpperCase() + type.substring(1)} ${localStorage.getItem('accessToken') ?? ""}"; + _dio.interceptors.clear(); + var response = await _request(url, method, body, options); + if (response.statusCode != null && response.statusCode! < 400) { + if (method == "delete") { cache.remove(url); return APIResponse(); } + APIResponse resp = APIResponse().deserialize(response.data); + if (resp.error == "") { + if (context != null && succeed != "") { + // ignore: use_build_context_synchronously + try { + showAlertBanner(context, () {}, InfoAlertBannerChild(text: succeed), // <-- Put any widget here you want! + alertBannerLocation: AlertBannerLocation.bottom,); + } catch (e) { /* */ } + } + return resp; } - return resp; - } - err = resp.error ?? "internal error"; - } - if (response.statusCode == 401) { - err = "not authorized"; - } + err = resp.error ?? "internal error"; + } else if (response.statusCode == 401) { err = "not authorized"; } } catch (e, s) { print(e); print(s); @@ -149,12 +132,11 @@ class APIService { //if (err.contains("token") && err.contains("expired")) { AuthService().unAuthenticate(); } if (context != null) { // ignore: use_build_context_synchronously - showAlertBanner( - context, () {}, - AlertAlertBannerChild(text: err), // <-- Put any widget here you want! - alertBannerLocation: AlertBannerLocation.bottom, - ); - } + try { + showAlertBanner( context, () {}, AlertAlertBannerChild(text: err),// <-- Put any widget here you want! + alertBannerLocation: AlertBannerLocation.bottom,); + } catch (e) { /* */ } + } throw Exception(err); } diff --git a/lib/core/services/auth.service.dart b/lib/core/services/auth.service.dart index 88e0551..61aa3cc 100644 --- a/lib/core/services/auth.service.dart +++ b/lib/core/services/auth.service.dart @@ -1,21 +1,15 @@ import 'package:localstorage/localstorage.dart'; import 'package:oc_front/core/conf/conf_reader.dart'; -import 'package:oc_front/core/sections/header/header.dart'; import 'package:oc_front/core/services/api_service.dart'; import 'package:oc_front/core/services/perms_service.dart'; +import 'package:oc_front/main.dart'; import 'package:oc_front/models/response.dart'; class AuthService { - static var config = AppConfig(); - static var isAuth = false; - - AuthService() { - isAuth = config.get('AUTH_MODE') == 'true'; - } - + static var isAuth = const bool.fromEnvironment('AUTH_MODE', defaultValue: false); + static const _clientID = String.fromEnvironment('CLIENT_ID', defaultValue: 'test-client'); static APIService service = APIService( - baseURL: - config.get('AUTH_HOST', defaultValue: 'http://localhost:8080/auth'), + baseURL: AppConfig().get('AUTH_HOST', defaultValue: 'http://localhost:8080/auth'), ); static Future init() async { @@ -42,7 +36,8 @@ class AuthService { if (!isAuth) { return true; } - return (localStorage.getItem('accessToken') ?? "") != ""; + return (localStorage.getItem('accessToken') ?? "") != "" + && localStorage.getItem('username') != ""; } static String? getUsername() { @@ -53,18 +48,17 @@ class AuthService { } static Future login(String username, String password) async { - var token = await service.post("/ldap/login", - {"username": username, "password": password}, null); + var token = await service.post("/login?client_id=$_clientID", { + "username": username, + "password": password + }, null); if (token.code == 200 && token.data != null) { localStorage.setItem('accessToken', token.data?.value['access_token']); localStorage.setItem('tokenType', token.data?.value['token_type']); localStorage.setItem('username', username); - localStorage.setItem( - 'expiresIn', - DateTime.now() - .add(Duration(seconds: token.data?.value['expires_in'])) - .toIso8601String()); - HeaderConstants.headerKey.currentState?.setState(() {}); + localStorage.setItem('expiresIn', DateTime.now().add( + Duration(seconds: token.data?.value['expires_in'])).toIso8601String()); + mainKey?.currentState?.setState(() {}); PermsService.init(token.data?.value['access_token']); refresh(token.data?.value['access_token'] ?? "", username, Duration(seconds: token.data?.value['expires_in'])); @@ -72,7 +66,7 @@ class AuthService { } static Future logout() async { - var token = await service.delete("/ldap/logout", null); + var token = await service.delete("/logout?client_id=$_clientID", null); if (token.code == 200) { localStorage.setItem('accessToken', ''); localStorage.setItem('username', ''); @@ -85,22 +79,18 @@ class AuthService { if (!isConnected()) { return false; } - var isIntrospected = await service.get("/introspect", true, null); + // ignore: invalid_return_type_for_catch_error + var isIntrospected = await service.get("/introspect", true, null).catchError((e) => mainKey?.currentState?.setState(() {})); return isIntrospected.code == 200; } static Future refresh( String accessToken, String username, Duration duration) async { Future.delayed(duration, () { - service - .post( - "/refresh", - { - "access_token": accessToken, - "username": username - }, - null) - .then((token) { + service.post("/refresh?client_id=$_clientID", { + "access_token": accessToken, + "username": username + }, null).then((token) { if (token.code == 200 && token.data != null) { PermsService.init(token.data?.value['access_token']); localStorage.setItem( diff --git a/lib/core/services/enum_service.dart b/lib/core/services/enum_service.dart new file mode 100644 index 0000000..6644d5d --- /dev/null +++ b/lib/core/services/enum_service.dart @@ -0,0 +1,49 @@ +import 'package:oc_front/models/response.dart'; +import 'package:oc_front/core/services/api_service.dart'; + +class EnumService { + static final APIService _service = APIService( + baseURL: const String.fromEnvironment('ITEM_HOST', + defaultValue: 'http://localhost:8080/catalog') + ); + static String subPath = "/enum/"; + static Map> enums = {}; + + static int? get(String path, dynamic name) { + var n = enums[path]; + if (n == null) { + return null; + } + var names = "$name"; + for (var nn in n.keys) { + if (n[nn] == names || nn == names) { + return int.parse(nn); + } + } + return null; + } + + static void init() { + _load("infrastructure"); + _load("storage/type"); + _load("storage/size"); + _load("resource/type"); + _load("booking/status"); + _load("status"); + _load("pricing/strategy/buy"); + _load("pricing/strategy/data"); + _load("pricing/strategy/time"); + _load("pricing/strategy/storage"); + _load("pricing/strategy/privilege/storage"); + _load("pricing/strategy/privilege"); + _load("pricing/refund/type"); + } + + static void _load(String name) { + _service.get("$subPath$name", false, null).then((response) { + if (response.code == 200) { + enums[name] = response.data!.value; + } + }); + } +} \ No newline at end of file diff --git a/lib/core/services/perms_service.dart b/lib/core/services/perms_service.dart index 011e7c5..203049c 100644 --- a/lib/core/services/perms_service.dart +++ b/lib/core/services/perms_service.dart @@ -1,5 +1,7 @@ import 'dart:convert'; +import 'package:oc_front/main.dart'; + enum Perms { SEARCH_INTERNAL,// ignore: constant_identifier_names SEARCH_EXTERNAL, // ignore: constant_identifier_names @@ -23,21 +25,21 @@ enum Perms { } Map perms = { - Perms.SEARCH_INTERNAL: 'GET__catalog_compute_search_search'.toUpperCase(), + Perms.SEARCH_INTERNAL: 'GET__CATALOG_COMPUTE_SEARCH_SEARCH'.toUpperCase(), Perms.SEARCH_EXTERNAL: 'Search External'.toUpperCase(), - Perms.WORKSPACE_SHARE: 'POST__shared_collaborative_area_id_workspace_id2'.toUpperCase(), - Perms.WORKFLOW_CREATE: 'POST__workflow_'.toUpperCase(), - Perms.WORKFLOW_UNSHARE: 'DELETE__shared_collaborative_area_id_workflow_id2'.toUpperCase(), - Perms.PEER_SHARE: 'POST__shared_collaborative_area_id_peer_id2'.toUpperCase(), - Perms.PEER_UNSHARE: 'DELETE__shared_collaborative_area_id_peer_id2'.toUpperCase(), - Perms.COLLABORATIVE_AREA_CREATE: 'POST__shared_collaborative_area_'.toUpperCase(), - Perms.COLLABORATIVE_AREA_EDIT: 'PUT__shared_collaborative_area_id'.toUpperCase(), - Perms.COLLABORATIVE_AREA_DELETE: 'DELETE__shared_collaborative_area_id'.toUpperCase(), - Perms.WORKSPACE_UNSHARE: 'DELETE__shared_collaborative_area_id_workspace_id2'.toUpperCase(), - Perms.WORKFLOW_EDIT: 'PUT__workflow_id'.toUpperCase(), - Perms.WORKFLOW_DELETE: 'DELETE__workflow_id'.toUpperCase(), - Perms.WORKFLOW_BOOKING: 'POST__datacenter_booking_'.toUpperCase(), - Perms.WORKFLOW_SHARE: 'POST__shared_collaborative_area_id_workflow_id2'.toUpperCase(), + Perms.WORKSPACE_SHARE: 'POST__SHARED_COLLABORATIVE_AREA_ID_WORKSPACE_ID2'.toUpperCase(), + Perms.WORKFLOW_CREATE: 'POST__WORKFLOW_'.toUpperCase(), + Perms.WORKFLOW_UNSHARE: 'DELETE__SHARED_COLLABORATIVE_AREA_ID_WORKFLOW_ID2'.toUpperCase(), + Perms.PEER_SHARE: 'POST__SHARED_COLLABORATIVE_AREA_ID_PEER_ID2'.toUpperCase(), + Perms.PEER_UNSHARE: 'DELETE__SHARED_COLLABORATIVE_AREA_ID_PEER_ID2'.toUpperCase(), + Perms.COLLABORATIVE_AREA_CREATE: 'POST__SHARED_COLLABORATIVE_AREA_'.toUpperCase(), + Perms.COLLABORATIVE_AREA_EDIT: 'PUT__SHARED_COLLABORATIVE_AREA_ID'.toUpperCase(), + Perms.COLLABORATIVE_AREA_DELETE: 'DELETE__SHARED_COLLABORATIVE_AREA_ID'.toUpperCase(), + Perms.WORKSPACE_UNSHARE: 'DELETE__SHARED_COLLABORATIVE_AREA_ID_WORKSPACE_ID2'.toUpperCase(), + Perms.WORKFLOW_EDIT: 'PUT__WORKFLOW_ID'.toUpperCase(), + Perms.WORKFLOW_DELETE: 'DELETE__WORKFLOW_ID'.toUpperCase(), + Perms.WORKFLOW_BOOKING: 'POST__DATACENTER_BOOKING_'.toUpperCase(), + Perms.WORKFLOW_SHARE: 'POST__SHARED_COLLABORATIVE_AREA_ID_WORKFLOW_ID2'.toUpperCase(), }; class PermsService { @@ -69,7 +71,7 @@ class PermsService { try { var what = json.decode(foo); what = what["session"]["access_token"] as Map; - + for (var w in perms.keys) { if (what.keys.contains(perms[w])) { _perms[w] = true; @@ -77,6 +79,7 @@ class PermsService { _perms[w] = false; } } + mainKey?.currentState?.setState(() {}); } catch (e) {/**/} } diff --git a/lib/core/services/router.dart b/lib/core/services/router.dart index fd6aff5..1771b99 100644 --- a/lib/core/services/router.dart +++ b/lib/core/services/router.dart @@ -57,7 +57,7 @@ class AppRouter { static final RouterItem workflowItem = RouterItem(icon: Icons.rebase_edit, label: "workflow manager", route: "workflow", factory: WorkflowFactory()); static final RouterItem workflowIDItem = RouterItem(description: "", help: "", route: "workflow/:id", factory: WorkflowFactory(), args: ["id"]); - static final RouterItem catalogItem = RouterItem(description: "", help: "", route: "catalog/:id", factory: CatalogItemFactory(), args: ["id"]); + static final RouterItem catalogItem = RouterItem(label: "resource", description: "", help: "", route: "catalog/:id", factory: CatalogItemFactory(), args: ["id"]); static final RouterItem catalog= RouterItem(icon: Icons.book_outlined, label: "catalog searcher", route: "catalog", factory: CatalogFactory()); static final RouterItem scheduler = RouterItem(icon: Icons.schedule, label: "scheduled tasks", route: "scheduler", factory: SchedulerFactory()); static final RouterItem compute = RouterItem(icon: Icons.dns_outlined, label: "my compute", route: "compute", factory: DatacenterFactory()); diff --git a/lib/core/services/specialized_services/booking_service.dart b/lib/core/services/specialized_services/booking_service.dart index 6d1c3f0..95f0314 100644 --- a/lib/core/services/specialized_services/booking_service.dart +++ b/lib/core/services/specialized_services/booking_service.dart @@ -4,34 +4,20 @@ import 'package:oc_front/core/services/specialized_services/abstract_service.dar import 'package:oc_front/models/response.dart'; import 'package:oc_front/models/workflow.dart'; -class BookingExecutionService extends AbstractService { - @override - late final APIService service; - @override - String subPath = "/booking/"; +class BookingExecutionService extends AbstractService { + @override APIService service = APIService( + baseURL: const String.fromEnvironment('DATACENTER_HOST', defaultValue: 'http://localhost:8080/datacenter') + ); + @override String subPath = "/booking/"; - BookingExecutionService() { - service = APIService( - baseURL: super.conf.get('DATACENTER_HOST', - defaultValue: 'http://localhost:8080/datacenter')); - } - - @override - Future> search( - BuildContext? context, List words, Map params) { - print("${subPath}search/${words.join("/")}"); + @override Future> search(BuildContext? context, List words, Map params) { return service.get("${subPath}search/${words.join("/")}", false, context); } - @override - Future> post(BuildContext? context, - Map body, Map params) { + @override Future> post(BuildContext? context, Map body, Map params) { return throw UnimplementedError(); } - - @override - Future> put(BuildContext? context, String id, - Map body, Map params) { + @override Future> put(BuildContext? context, String id, Map body, Map params) { return throw UnimplementedError(); } } diff --git a/lib/core/services/specialized_services/datacenter_service.dart b/lib/core/services/specialized_services/datacenter_service.dart new file mode 100644 index 0000000..ade9525 --- /dev/null +++ b/lib/core/services/specialized_services/datacenter_service.dart @@ -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/resources/resources.dart'; +import 'package:oc_front/models/response.dart'; + +class DatacenterService extends AbstractService { + @override APIService service = APIService( + baseURL: const String.fromEnvironment('DATACENTER_HOST', defaultValue: 'http://localhost:8080/datacenter') + ); + @override String subPath = "/"; + + @override Future> search(BuildContext? context, List words, Map params) { + return throw UnimplementedError(); + } + + @override Future> post(BuildContext? context, Map body, Map params) { + return throw UnimplementedError(); + } + @override Future> put(BuildContext? context, String id, Map body, Map params) { + return throw UnimplementedError(); + } +} \ No newline at end of file diff --git a/lib/core/services/specialized_services/logs_service.dart b/lib/core/services/specialized_services/logs_service.dart index a287847..8c9be00 100644 --- a/lib/core/services/specialized_services/logs_service.dart +++ b/lib/core/services/specialized_services/logs_service.dart @@ -26,13 +26,8 @@ class LogsService extends AbstractService { continue; } v.add("$p=\"${params[p]}\""); - } - print( - "${subPath}query_range?query={${v.join(", ")}}&start=${params["start"].toString().substring(0, 10)}&end=${params["end"].toString().substring(0, 10)}"); - return service.get( - "${subPath}query_range?query={${v.join(", ")}}&start=${params["start"].toString().substring(0, 10)}&end=${params["end"].toString().substring(0, 10)}", - false, - context); + } + return service.get("${subPath}query_range?query={${v.join(", ")}}&start=${params["start"].toString().substring(0, 10)}&end=${params["end"].toString().substring(0, 10)}", false, context); } @override diff --git a/lib/core/services/specialized_services/resource_service.dart b/lib/core/services/specialized_services/resource_service.dart index eea3b94..ae8b937 100644 --- a/lib/core/services/specialized_services/resource_service.dart +++ b/lib/core/services/specialized_services/resource_service.dart @@ -1,8 +1,8 @@ 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'; +import 'package:oc_front/core/services/api_service.dart'; +import 'package:oc_front/models/resources/resources.dart'; +import 'package:oc_front/core/services/specialized_services/abstract_service.dart'; class ResourceService extends AbstractService { @override diff --git a/lib/core/services/specialized_services/workflow_execution_service.dart b/lib/core/services/specialized_services/workflow_execution_service.dart index 7eb07c1..1a3c203 100644 --- a/lib/core/services/specialized_services/workflow_execution_service.dart +++ b/lib/core/services/specialized_services/workflow_execution_service.dart @@ -5,11 +5,10 @@ import 'package:oc_front/models/response.dart'; import 'package:oc_front/models/workflow.dart'; class WorkflowExecutionService extends AbstractService { - @override - late final APIService service; - - @override - String subPath = "/"; + @override APIService service = APIService( + baseURL: const String.fromEnvironment('SCHEDULER_HOST', defaultValue: 'http://localhost:8080/scheduler') + ); + @override String subPath = "/execution/"; WorkflowExecutionService() { service = APIService( diff --git a/lib/core/services/specialized_services/workflow_scheduler_service.dart b/lib/core/services/specialized_services/workflow_scheduler_service.dart new file mode 100644 index 0000000..04d5c4e --- /dev/null +++ b/lib/core/services/specialized_services/workflow_scheduler_service.dart @@ -0,0 +1,28 @@ +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 SchedulerService extends AbstractService { + @override APIService service = APIService( + baseURL: const String.fromEnvironment('SCHEDULER_HOST', defaultValue: 'http://localhost:8080/scheduler') + ); + @override String subPath = "/"; + + Future> schedule(BuildContext? context, String id, Map body, Map params) { + print("$subPath$id"); + return service.post("$subPath$id", body, context); + } + + @override Future> search(BuildContext? context, List words, Map params) { + return throw UnimplementedError(); + } + + @override Future> post(BuildContext? context, Map body, Map params) { + return throw UnimplementedError(); + } + @override Future> put(BuildContext? context, String id, Map body, Map params) { + return throw UnimplementedError(); + } +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 0099a9a..bb7eec9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -9,6 +9,7 @@ import 'package:oc_front/core/sections/header/header.dart'; import 'package:oc_front/core/sections/header/menu.dart'; import 'package:oc_front/core/sections/left_menu.dart'; import 'package:oc_front/core/services/auth.service.dart'; +import 'package:oc_front/core/services/enum_service.dart'; import 'package:oc_front/core/services/router.dart'; import 'package:oc_front/core/sections/end_drawer.dart'; import 'package:oc_front/widgets/dialog/login.dart'; @@ -35,7 +36,9 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { AuthService.init(); - return MaterialApp.router(routerConfig: GoRouter(routes: AppRouter.routes)); + EnumService.init(); + SearchConstants.clear(); + return MaterialApp.router( routerConfig: GoRouter( routes: AppRouter.routes ) ); } } @@ -83,7 +86,7 @@ double getMainHeight(BuildContext context) { double getMainWidth(BuildContext context) { return getWidth(context) - 50; } - +bool loginIsSet = false; class MainPageState extends State { bool isCtrl = false; final FocusNode node = FocusNode(); @@ -103,15 +106,14 @@ class MainPageState extends State { // fast, so that you can just rebuild anything that needs updating rather // than having to individually change instances of widgets.i scaffoldKey = GlobalKey(); - isCtrl = false; - if (!AuthService.isConnected()) { - print("isConnected: ${AuthService.isConnected()}"); - Future.delayed(const Duration(milliseconds: 500), () { - showDialog( - barrierDismissible: false, - context: context, - builder: (context) { - return AlertDialog( + isCtrl = false; + if (!AuthService.isConnected() && !loginIsSet) { + Future.delayed(const Duration(milliseconds: 500), () { + loginIsSet = true; + showDialog( + barrierDismissible: false, + context: context ?? context, builder: (context) { + return AlertDialog( insetPadding: EdgeInsets.zero, backgroundColor: Colors.white, shape: RoundedRectangleBorder( @@ -120,63 +122,46 @@ class MainPageState extends State { }); }); } - return FutureBuilder( - future: AuthService.init(), - builder: (e, s) { - WorkspaceLocal.init(context, false); - CollaborativeAreaLocal.init(context, false); - - HeaderConstants.height = - HeaderConstants.isNoHeader(AppRouter.currentRoute.route) || - AppRouter.currentRoute.factory.searchFill() - ? 50 - : 100; - return Scaffold( - key: scaffoldKey, - endDrawer: EndDrawerWidget(), - body: SingleChildScrollView( - controller: ScrollController(), - scrollDirection: Axis.horizontal, - child: SingleChildScrollView( - child: Column(children: [ - HeaderMenuWidget(), - Row(children: [ - Container( - padding: const EdgeInsets.symmetric(vertical: 30), - decoration: BoxDecoration(color: darkColor), - width: 50, - height: getHeight(context) - 50, - child: - SingleChildScrollView(child: LeftMenuWidget())), - SizedBox( - width: getMainWidth(context), - height: getHeight(context) - 50, - child: KeyboardListener( - focusNode: node, - onKeyEvent: (event) async { - if (event.logicalKey == - LogicalKeyboardKey.controlLeft) { - isCtrl = (event is KeyDownEvent); - node.requestFocus(); - } else if ((event is KeyDownEvent) && - event.logicalKey == - LogicalKeyboardKey.enter) { - AppRouter.currentRoute.factory - .search(context, isCtrl); - node.requestFocus(); - } - }, - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - HeaderWidget(), - widget.page ?? - Container() // CatalogPageWidget(), - ], - ), - )), - ]) - ])))); - }); + return FutureBuilder(future: AuthService.init(), + builder: (e, s) { + WorkspaceLocal.init(context, false); + HeaderConstants.height = HeaderConstants.isNoHeader(AppRouter.currentRoute.route) || AppRouter.currentRoute.factory.searchFill() ? 50 : 100; + return Scaffold( key: scaffoldKey, endDrawer: EndDrawerWidget(), body: + SingleChildScrollView( + controller: ScrollController(), + scrollDirection: Axis.horizontal, + child: SingleChildScrollView( + child: Column( children: [ + HeaderMenuWidget(), + Row( children : [ + Container( padding: const EdgeInsets.symmetric(vertical: 30), + decoration: BoxDecoration( color: darkColor), + width: 50, height: getHeight(context) - 50, + child: SingleChildScrollView( child: LeftMenuWidget() )), + SizedBox( width: getMainWidth(context), height: getHeight(context) - 50, + child: KeyboardListener( + focusNode: node, + onKeyEvent: (event) async { + if ( event.logicalKey == LogicalKeyboardKey.controlLeft ) { + isCtrl = (event is KeyDownEvent); + node.requestFocus(); + } else if( (event is KeyDownEvent) && event.logicalKey == LogicalKeyboardKey.enter) { + AppRouter.currentRoute.factory.search(context, isCtrl); + node.requestFocus(); + } + }, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + HeaderWidget(), + widget.page ?? Container() // CatalogPageWidget(), + ], + ), + )), + ]) + ]) + ) + )); + }); } } diff --git a/lib/models/resources/compute.dart b/lib/models/resources/compute.dart new file mode 100644 index 0000000..1c9cb53 --- /dev/null +++ b/lib/models/resources/compute.dart @@ -0,0 +1,222 @@ + +import 'package:flutter/material.dart'; +import 'package:oc_front/core/services/enum_service.dart'; +import 'package:oc_front/models/abstract.dart'; +import 'package:oc_front/models/resources/processing.dart'; +import 'package:oc_front/models/resources/resources.dart'; + +class ComputeItem extends AbstractItem { + // special attributes + int? infrastructureEnum; + String? architecture; + + ComputeItem({ + this.infrastructureEnum, + this.architecture + }): super(); + + @override String get topic => "compute"; + + @override deserialize(dynamic data) { + try { data = data as Map; + } catch (e) { return ComputeItem(); } + var w = ComputeItem( + infrastructureEnum: data.containsKey("infrastructure") ? EnumService.get("infrastructure", data["infrastructure"]) : null, + architecture: data.containsKey("architecture") && data["architecture"] != null ? data["architecture"] : null, + ); + w.mapFromJSON(data, ComputeInstance()); + if (w.logo != null) { // get image dimensions + var image = Image.network(w.logo!); + image.image + .resolve(const ImageConfiguration()) + .addListener( + ImageStreamListener( + (ImageInfo info, bool _) { + w.width = info.image.width.toDouble(); + w.height = info.image.height.toDouble(); + })); + } + return w; + } + + @override + Map infos() { + return { + "infrastructure": EnumService.enums["infrastructure"] != null + && EnumService.enums["infrastructure"]!["$infrastructureEnum"] != null ? EnumService.enums["infrastructure"]!["$infrastructureEnum"] : infrastructureEnum, + "architecture": architecture, + }; + } + + @override Map serialize() { + Map obj = infos(); + obj["infrastructure"] = infrastructureEnum; + obj.addAll(toJSON()); + return obj; + } +} + +class ComputeInstance extends AbstractInstance { + String? securityLevel; + List? powerSources = []; + double? annualEnergyConsumption; + Map cpus = {}; + Map gpus = {}; + List nodes = []; + + ComputeInstance({ + this.securityLevel, + this.powerSources = const [], + this.annualEnergyConsumption, + this.cpus = const {}, + this.gpus = const {}, + this.nodes = const [], + }): super(); + + @override + Map infos() { + return { + "security_level": securityLevel, + "power_sources": powerSources, + "annual_co2_emissions": annualEnergyConsumption, + "cpus": toMapJson(cpus), + "gpus": toMapJson(gpus), + "nodes": toListJson(nodes), + "inputs": toListJson(inputs), + "outputs": toListJson(outputs), + }; + } + + @override + ComputeInstance deserialize(json) { + try { json = json as Map; + } catch (e) { return ComputeInstance(); } + var w = ComputeInstance( + securityLevel: json.containsKey("security_level") && json["security_level"] != null ? json["security_level"] : null, + powerSources: json.containsKey("power_sources") && json["power_sources"] != null ? List.from(json["power_sources"]) : [], + annualEnergyConsumption: json.containsKey("annual_co2_emissions") && json["annual_co2_emissions"] != null ? json["annual_co2_emissions"] : null, + //cpus: json.containsKey("cpus") && json["cpus"] != null ? fromMapJson(json["cpus"], CPU()) : {}, + // gpus: json.containsKey("gpus") && json["gpus"] != null ? fromMapJson(json["gpus"], GPU()) : {}, + //nodes: json.containsKey("nodes") && json["nodes"] != null ? fromListJson(json["nodes"], ComputeNode()) : [], + ); + w.mapFromJSON(json, ComputePartnership()); + return w; + } + + @override + Map serialize() { + var obj = infos(); + obj.addAll(toJSON()); + return obj; + } +} + +class ComputePartnership extends AbstractPartnerShip { + Map maxAllowedCPUsCores = {}; + Map maxAllowedGPUsMemoryGB = {}; + double? maxAllowedRAM; + + ComputePartnership({ + this.maxAllowedCPUsCores = const {}, + this.maxAllowedGPUsMemoryGB = const {}, + this.maxAllowedRAM, + }): super(); + + @override + ComputePartnership deserialize(json) { + try { json = json as Map; + } catch (e) { return ComputePartnership(); } + var w = ComputePartnership( + maxAllowedCPUsCores: json.containsKey("allowed_cpus") && json["allowed_cpus"] != null ? json["allowed_cpus"] : {}, + maxAllowedGPUsMemoryGB: json.containsKey("allowed_gpus") && json["allowed_gpus"] != null ? json["allowed_gpus"] : {}, + maxAllowedRAM: json.containsKey("allowed_ram") && json["allowed_ram"] != null ? double.parse("${json["allowed_ram"]}") : null, + ); + w.mapFromJSON(json, ComputePricing()); + return w; + } + + @override + Map serialize() { + Map obj = { + "allowed_cpus": maxAllowedCPUsCores, + "allowed_gpus": maxAllowedGPUsMemoryGB, + "allowed_ram": maxAllowedRAM, + }; + obj.addAll(toJSON()); + return obj; + } +} + + +class ComputePricing extends AbstractPricing { + Map cpusPrice = {}; + Map gpusPrice = {}; + double? ramPrice; + + ComputePricing({ + this.cpusPrice = const {}, + this.gpusPrice = const {}, + this.ramPrice, + }); + + @override ComputePricing deserialize(json) { + var w = ComputePricing( + cpusPrice: json.containsKey("cpus") && json["cpus"] != null ? json["cpus"] : {}, + gpusPrice: json.containsKey("gpus") && json["gpus"] != null ? json["gpus"] : {}, + ramPrice: json.containsKey("ram") && json["ram"] != null ? json["ram"] : null, + ); + w.mapFromJSON(json); + return w; + } + @override + Map serialize() { + var obj = { + "cpus": cpusPrice, + "gpus": gpusPrice, + "ram": ramPrice, + }; + obj.addAll(toJSON()); + return obj; + } +} + +class ComputeNode extends SerializerDeserializer { + String? name; + int? quantity; + Map cpus = {}; + Map gpus = {}; + RAM? ram; + + ComputeNode({ + this.cpus = const {}, + this.gpus = const {}, + this.ram, + this.name, + this.quantity, + }); + + @override + ComputeNode deserialize(json) { + try { json = json as Map; + } catch (e) { return ComputeNode(); } + return ComputeNode( + name: json.containsKey("name") && json["name"] != null ? json["name"] : null, + quantity: json.containsKey("quantity") && json["quantity"] != null ? json["quantity"] : null, + cpus: json.containsKey("cpus") && json["cpus"] != null ? fromMapJson(json["cpus"], CPU()) : {}, + gpus: json.containsKey("gpus") && json["gpus"] != null ? fromMapJson(json["gpus"], GPU()) : {}, + ram: json.containsKey("ram") && json["ram"] != null ? RAM().deserialize(json["ram"]) : null, + ); + } + + @override + Map serialize() { + return { + "name": name, + "quantity": quantity, + "cpus": cpus, + "gpus": gpus, + "ram": ram!.serialize(), + }; + } + +} \ No newline at end of file diff --git a/lib/models/resources/data.dart b/lib/models/resources/data.dart new file mode 100644 index 0000000..4cfeb75 --- /dev/null +++ b/lib/models/resources/data.dart @@ -0,0 +1,166 @@ + +import 'package:flutter/material.dart'; +import 'package:oc_front/models/abstract.dart'; +import 'package:oc_front/models/resources/resources.dart'; + +class DataItem extends AbstractItem { + // special attributes + String? type; + String? source; + String? quality; + bool openData = false; + bool static = false; + bool personalData = false; + bool anonymizedPersonalData = false; + double? size; + String? example; + DateTime? updatePeriod; + + DataItem({ + this.type, + this.source, + this.quality, + this.openData = false, + this.static = false, + this.personalData = false, + this.anonymizedPersonalData = false, + this.size, + this.example, + this.updatePeriod, + }): super(); + + @override String get topic => "data"; + + @override deserialize(dynamic data) { + try { data = data as Map; + } catch (e) { return DataItem(); } + var w = DataItem( + type: data.containsKey("type") && data["type"] != null ? data["type"] : null, + source: data.containsKey("source") && data["source"] != null ? data["source"] : null, + quality: data.containsKey("quality") && data["quality"] != null ? data["quality"] : null, + openData: data.containsKey("open_data") && data["open_data"] != null ? data["open_data"] : false, + static: data.containsKey("static") && data["static"] != null ? data["static"] : false, + personalData: data.containsKey("personal_data") && data["l"] != null ? data["personal_data"] : false, + anonymizedPersonalData: data.containsKey("anonymized_personal_data") && data["anonymized_personal_data"] != null ? data["anonymized_personal_data"] : false, + size: data.containsKey("size") && data["size"] != null ? data["size"] : null, + example: data.containsKey("example") && data["example"] != null ? data["example"] : null, + updatePeriod: data.containsKey("update_period") && data["update_period"] != null ? DateTime.parse(data["update_period"]) : null, + ); + w.mapFromJSON(data, DataInstance()); + if (w.logo != null) { // get image dimensions + var image = Image.network(w.logo!); + image.image + .resolve(const ImageConfiguration()) + .addListener( + ImageStreamListener( + (ImageInfo info, bool _) { + w.width = info.image.width.toDouble(); + w.height = info.image.height.toDouble(); + })); + } + return w; + } + + @override + Map infos() { + return { + "type": type, + "quality": quality, + "open_data": openData, + "static": static, + "personal_data": personalData, + "anonymized_personal_data": anonymizedPersonalData, + "size": size, + "example": example, + "update_period": updatePeriod?.toIso8601String(), + }; + } + + @override Map serialize() { + var obj = infos(); + obj.addAll(toJSON()); + return obj; + } +} + +class DataInstance extends AbstractInstance { + String? source; + DataInstance( + {this.source} + ): super(); + + @override + Map infos() { + return { + "inputs": toListJson(inputs), + "outputs": toListJson(outputs), + }; + } + + @override + DataInstance deserialize(json) { + try { json = json as Map; + } catch (e) { return DataInstance(); } + var w = DataInstance( + source: json.containsKey("source") && json["source"] != null ? json["source"] : null, + ); + w.mapFromJSON(json, DataPartnership()); + return w; + } + + @override + Map serialize() { + var obj = toJSON(); + obj["source"] = source; + obj.addAll(infos()); + return obj; + } +} + +class DataPartnership extends AbstractPartnerShip { + double? maxDownloadableGBAllowed; + bool personalDataAllowed = false; + bool anonymizedPersonalDataAllowed = false; + + DataPartnership({ + this.maxDownloadableGBAllowed, + this.personalDataAllowed = false, + this.anonymizedPersonalDataAllowed = false, + }): super(); + + @override + DataPartnership deserialize(json) { + try { json = json as Map; + } catch (e) { return DataPartnership(); } + var w = DataPartnership( + maxDownloadableGBAllowed: json.containsKey("max_downloadable_gb_allowed") && json["max_downloadable_gb_allowed"] != null ? json["max_downloadable_gb_allowed"] : null, + personalDataAllowed: json.containsKey("personal_data_allowed") && json["personal_data_allowed"] != null ? json["personal_data_allowed"] : false, + anonymizedPersonalDataAllowed: json.containsKey("anonymized_personal_data_allowed") && json["anonymized_personal_data_allowed"] != null ? json["anonymized_personal_data_allowed"] : false, + ); + w.mapFromJSON(json, DataPricing()); + return w; + } + + @override + Map serialize() { + Map obj = { + "max_downloadable_gb_allowed": maxDownloadableGBAllowed, + "personal_data_allowed": personalDataAllowed, + "anonymized_personal_data_allowed": anonymizedPersonalDataAllowed, + }; + obj.addAll(toJSON()); + return obj; + } +} + +class DataPricing extends AbstractPricing { + @override DataPricing deserialize(json) { + var w = DataPricing(); + w.mapFromJSON(json); + return w; + } + @override + Map serialize() { + return toJSON(); + } +} \ No newline at end of file diff --git a/lib/models/resources/processing.dart b/lib/models/resources/processing.dart new file mode 100644 index 0000000..6d30d59 --- /dev/null +++ b/lib/models/resources/processing.dart @@ -0,0 +1,357 @@ + +import 'package:flutter/material.dart'; +import 'package:oc_front/core/services/enum_service.dart'; +import 'package:oc_front/models/abstract.dart'; +import 'package:oc_front/models/resources/resources.dart'; + +class ProcessingItem extends AbstractItem { + // special attributes + int? infrastructureEnum; + bool isService = false; + bool openSource = false; + String? license; + String? maturity; + ProcessingUsage? usage; + + ProcessingItem({ + this.infrastructureEnum, + this.isService = false, + this.openSource = false, + this.license, + this.maturity, + this.usage, + }): super(); + + @override String get topic => "processing"; + + @override deserialize(dynamic data) { + try { data = data as Map; + } catch (e) { return ProcessingItem(); } + var w = ProcessingItem( + infrastructureEnum: data.containsKey("infrastructure") ? EnumService.get("infrastructure", data["infrastructure"]) : null, + isService: data.containsKey("is_service") && data["is_service"] != null ? data["is_service"] : false, + openSource: data.containsKey("open_source") && data["open_source"] != null ? data["open_source"] : false, + license: data.containsKey("license") && data["license"] != null ? data["license"] : null, + maturity: data.containsKey("maturity") && data["maturity"] != null ? data["maturity"] : null, + usage: data.containsKey("usage") && data["usage"] != null ? ProcessingUsage().deserialize(data["usage"]) : null, + ); + w.mapFromJSON(data, ProcessingInstance()); + if (w.logo != null) { // get image dimensions + var image = Image.network(w.logo!); + image.image + .resolve(const ImageConfiguration()) + .addListener( + ImageStreamListener( + (ImageInfo info, bool _) { + w.width = info.image.width.toDouble(); + w.height = info.image.height.toDouble(); + })); + } + return w; + } + + @override + Map infos() { + return { + "infrastructure": EnumService.enums["infrastructure"] != null + && EnumService.enums["infrastructure"]!["$infrastructureEnum"] != null ? + EnumService.enums["infrastructure"]!["$infrastructureEnum"] : infrastructureEnum, + "is_service": isService, + "open_source": openSource, + "license": license, + "maturity": maturity, + }; + } + + @override Map serialize() { + var obj = infos(); + obj["infrastructure"] = infrastructureEnum; + obj["usage"] = usage?.serialize(); + obj.addAll(toJSON()); + return obj; + } +} + +class ProcessingAccess extends SerializerDeserializer { + Containered? container; + + ProcessingAccess({ + this.container, + }); + + @override ProcessingAccess deserialize(dynamic json) { + try { + json = json as Map; + } catch (e) { + return ProcessingAccess(); + } + return ProcessingAccess( + container: json.containsKey("container") && json["container"] != null ? Containered().deserialize(json["container"]) : null, + ); + } + + @override Map serialize() { + return { + "container": container?.serialize(), + }; + } +} + +class ProcessingInstance extends AbstractInstance { + ProcessingAccess? access; + ProcessingInstance( + {this.access} + ): super(); + + @override + ProcessingInstance deserialize(json) { + try { json = json as Map; + } catch (e) { return ProcessingInstance(); } + var w = ProcessingInstance(); + w.access = json.containsKey("access") && json["access"] != null ? ProcessingAccess().deserialize(json['access']) : null; + w.mapFromJSON(json, ProcessingPartnership()); + return w; + } + + @override + Map serialize() { + var obj = toJSON(); + obj["access"] = access?.serialize(); + return obj; + } + + @override + Map infos() { + return { + "inputs": toListJson(inputs), + "outputs": toListJson(outputs), + }; + } +} + +class ProcessingPartnership extends AbstractPartnerShip { + ProcessingPartnership(): super(); + + @override + ProcessingPartnership deserialize(json) { + try { json = json as Map; + } catch (e) { return ProcessingPartnership(); } + var w = ProcessingPartnership(); + w.mapFromJSON(json, ProcessingPricing()); + return w; + } + + @override + Map serialize() { + return toJSON(); + } +} + +class ProcessingPricing extends AbstractPricing { + @override ProcessingPricing deserialize(json) { + var w = ProcessingPricing(); + w.mapFromJSON(json); + return w; + } + @override + Map serialize() { + return toJSON(); + } +} + +class ProcessingUsage extends SerializerDeserializer { + Map cpus = {}; + Map gpus = {}; + RAM? ram; + double? storageSize; + String? hypothesis; + String? scalingModel; + + ProcessingUsage({ + this.cpus = const {}, + this.gpus = const {}, + this.ram, + this.storageSize, + this.hypothesis, + this.scalingModel, + }); + + @override + ProcessingUsage deserialize(json) { + return ProcessingUsage( + cpus: json.containsKey("cpus") && json["cpus"] != null ? fromMapJson(json["cpus"], CPU()) : {}, + gpus: json.containsKey("gpus") && json["gpus"] != null ? fromMapJson(json["gpus"], GPU()) : {}, + ram: json.containsKey("ram") && json["ram"] != null ? RAM().deserialize(json["ram"]) : null, + storageSize: json.containsKey("storage_size") && json["storage_size"] != null ? json["storage_size"]?.toDouble() : null, + hypothesis: json.containsKey("hypothesis") && json["hypothesis"] != null ? json["hypothesis"] : null, + scalingModel: json.containsKey("scaling_model") && json["scaling_model"] != null ? json["scaling_model"] : null, + ); + } + + @override + Map serialize() { + return { + "cpus": toMapJson(cpus), + "gpus": toMapJson(gpus), + "ram": ram?.serialize(), + "storage_size": storageSize, + "hypothesis": hypothesis, + "scaling_model": scalingModel, + }; + } + +} + +class CPU extends SerializerDeserializer { + CPU({ + this.cores, + this.platform, + this.architecture, + this.minimumMemory, + this.shared = false, + }); + double? cores; + String? platform; + bool shared = false; + String? architecture; + double? minimumMemory; + + @override deserialize(dynamic json) { + try { json = json as Map; + } catch (e) { return CPU(); } + return CPU( + cores: json.containsKey("cores") && json["cores"] != null ? json["cores"]?.toDouble() : null, + platform: json.containsKey("platform") && json["platform"] != null ? json["platform"] : null, + architecture: json.containsKey("architecture") && json["architecture"] != null ? json["architecture"] : null, + minimumMemory: json.containsKey("minimumMemory") && json["minimumMemory"] != null ? json["minimumMemory"]?.toDouble() : null, + shared: json.containsKey("shared") && json["shared"] != null ? json["shared"] : false, + ); + } + @override Map serialize() => { + "cores": cores, + "platform": platform, + "architecture": architecture, + "minimumMemory": minimumMemory, + "shared": shared, + }; +} +class GPU extends SerializerDeserializer { + GPU({ + this.cudaCores, + this.memory, + this.model, + this.tensorCores, + }); + double? cudaCores; + double? memory; + String? model; + double? tensorCores; + + @override deserialize(dynamic json) { + try { json = json as Map; + } catch (e) { return GPU(); } + return GPU( + cudaCores: json.containsKey("cuda_cores") && json["cuda_cores"] != null ? json["cuda_cores"]?.toDouble() : null, + memory: json.containsKey("memory") && json["memory"] != null ? json["memory"]?.toDouble() : null, + model: json.containsKey("model") && json["model"] != null ? json["model"] : null, + tensorCores: json.containsKey("tensor_cores") && json["tensor_cores"] != null ? json["tensor_cores"]?.toDouble() : null, + ); + } + @override Map serialize() => { + "cuda_cores": cudaCores, + "memory": memory, + "model": model, + "tensor_cores": tensorCores, + }; +} +class RAM extends SerializerDeserializer { + RAM({ + this.ecc = false, + this.size, + }); + bool ecc = false; + double? size; + + @override deserialize(dynamic json) { + try { json = json as Map; + } catch (e) { return RAM(); } + return RAM( + ecc: json.containsKey("ecc") && json["ecc"] != null ? json["ecc"] : false, + size: json.containsKey("size") && json["size"] != null ? json["size"]?.toDouble() : null, + ); + } + @override Map serialize() => { + "ecc": ecc, + "size": size, + }; +} + +class Expose extends SerializerDeserializer { + Expose({ + this.PAT, + this.port, + this.path, + }); + + int? port; + int? PAT; + String? path; + + @override deserialize(dynamic json) { + try { json = json as Map; + } catch (e) { return Expose(); } + return Expose( + port: json.containsKey("port") && json["port"] != null ? json["port"] : null, + PAT: json.containsKey("PAT") && json["PAT"] != null ? json["PAT"] : null, + path: json.containsKey("reverse") && json["reverse"] != null ? json["reverse"] : null, + ); + } + + @override Map serialize() => { + "port": port, + "PAT": PAT, + "reverse": path, + }; +} + +class Containered extends SerializerDeserializer { + Containered({ + this.image, + this.args, + this.command, + this.env, + this.volumes, + this.exposes = const [], + }); + + String? args; + String? image; + String? command; + Map? env; + Map? volumes; + List exposes = []; + + @override deserialize(dynamic json) { + try { json = json as Map; + } catch (e) { return Containered(); } + return Containered( + args: json.containsKey("args") && json["args"] != null ? json["args"] : null, + image: json.containsKey("image") && json["image"] != null ? json["image"] : null, + command: json.containsKey("command") && json["command"] != null ? json["command"] : null, + env: json.containsKey("env") && json["env"] != null ? json["env"] : null, + volumes: json.containsKey("volumes") && json["volumes"] != null ? json["volumes"] : null, + exposes: json.containsKey("exposes") && json["exposes"] != null ? fromListJson(json["exposes"], Expose()) : [], + ); + } + @override Map serialize() { + var w = { + "args": args, + "image": image, + "command": command, + "env": env, + "volumes": volumes, + "exposes": toListJson(exposes), + }; + return w; + } +} \ No newline at end of file diff --git a/lib/models/resources/resources.dart b/lib/models/resources/resources.dart new file mode 100644 index 0000000..91abfd7 --- /dev/null +++ b/lib/models/resources/resources.dart @@ -0,0 +1,529 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_flow_chart/flutter_flow_chart.dart'; +import 'package:oc_front/main.dart'; +import 'package:oc_front/models/abstract.dart'; +import 'package:oc_front/models/resources/compute.dart'; +import 'package:oc_front/models/resources/data.dart'; +import 'package:oc_front/models/resources/processing.dart'; +import 'package:oc_front/models/resources/storage.dart'; +import 'package:oc_front/models/resources/workflow.dart'; + +class Resource implements SerializerDeserializer { + List datas = []; + List processings = []; + List storages = []; + List computes = []; + List workflows = []; + + Resource({ + this.datas = const [], + this.processings = const [], + this.storages = const [], + this.computes = const [], + this.workflows = const [], + }); + + @override Resource deserialize(json) { + try { json = json as Map; + } catch (e) { return Resource(); } + return Resource( + computes: json.containsKey("compute_resource") ? fromListJson(json["compute_resource"], ComputeItem()) : [], + 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 serialize() { + return { + "compute_resource": toListJson(computes), + "data_resource": toListJson(datas), + "processing_resource": toListJson(processings), + "storage_resource": toListJson(storages), + "workflow_resource": toListJson(workflows), + }; + } +} + +class Owner extends SerializerDeserializer { + String? name; + String? logo; + + Owner({ + this.name, + this.logo, + }); + + @override Owner deserialize(json) { + try { json = json as Map; + } catch (e) { return Owner(); } + return Owner( + name: json.containsKey("name") ? json["name"] : null, + logo: json.containsKey("logo") ? json["logo"] : null, + ); + } + + @override Map serialize() { + return { + "name": name, + "logo": logo, + }; + } +} + +abstract class Infos { + Map infos(); +} + +class Artifact extends SerializerDeserializer { + String? attrPath; + String? attrFrom; + bool readOnly = true; + + Artifact({ + this.attrPath, + this.attrFrom, + this.readOnly = true, + }); + + @override Artifact deserialize(json) { + try { json = json as Map; + } catch (e) { return Artifact(); } + return Artifact( + attrPath: json.containsKey("attr_path") ? json["attr_path"] : null, + attrFrom: json.containsKey("attr_from") ? json["attr_from"] : null, + readOnly: json.containsKey("readonly") ? json["readonly"] : true, + ); + } + + @override Map serialize() { + return { + "attr_path": attrPath, + "attr_from": attrFrom, + "readonly": readOnly, + }; + } +} +class Param extends SerializerDeserializer { + String? name; + String? attr; + dynamic value; + String? origin; + bool optionnal = false; + bool readOnly = true; + + Param({ + this.name, + this.attr, + this.value, + this.origin, + this.optionnal = false, + this.readOnly = true, + }); + + @override Param deserialize(json) { + try { json = json as Map; + } catch (e) { return Param(); } + return Param( + name: json.containsKey("name") ? json["name"] : null, + attr: json.containsKey("attr") ? json["attr"] : null, + value: json.containsKey("value") ? json["value"] : null, + origin: json.containsKey("origin") ? json["origin"] : null, + optionnal: json.containsKey("optionnal") ? json["optionnal"] : false, + readOnly: json.containsKey("readonly") ? json["readonly"] : false, + ); + } + + @override Map serialize() { + return { + "name": name, + "attr": attr, + "value": value, + "origin": origin, + "optionnal": optionnal, + "readonly": readOnly, + }; + } +} + +class Credential extends SerializerDeserializer { + String? login; + String? password; + + Credential({ + this.login, + this.password, + }); + + @override + Credential deserialize(json) { + try { json = json as Map; + } catch (e) { return Credential(); } + return Credential( + login: json.containsKey("login") ? json["login"] : null, + password: json.containsKey("password") ? json["password"] : null, + ); + } + + @override + Map serialize() { + return { + "login": login, + "password": password, + }; + } +} + +abstract class AbstractItem, S extends AbstractInstance, T extends FlowData> extends FlowData implements SerializerDeserializer, Infos { + String? id; + String? name; + String? logo; + String? type; + String? creatorID; + String? updaterID; + DateTime? createdAt; + DateTime? updatedAt; + List owners; + String? description; + String? restrictions; + String? shortDescription; + int selectedInstance = 0; + + List> instances = []; + + String get topic => ""; + + AbstractItem({ + this.id, + this.type, + this.name, + this.logo, + this.creatorID, + this.updaterID, + this.createdAt, + this.updatedAt, + this.description, + this.shortDescription, + this.owners = const [], + this.selectedInstance = 0, + }); + + void addEnv(List infos) { + var inst = getSelectedInstance(); + if (inst == null) { return; } + inst.env = []; + for (var info in infos) { + inst.env.add(Param(name: info["name"], attr: info["attr"], value: info["value"], + origin: info["origin"], optionnal: info["optionnal"], readOnly: info["readonly"])); + } + } + + AbstractInstance? getSelectedInstance() { + if (selectedInstance == -1) { return instances.isEmpty ? null : instances[0]; } + return instances.isNotEmpty ? instances[selectedInstance] : null; + } + + @override String getID() { + return id ?? ""; + } + + @override String getType() { + return type ?? ""; + } + + + @override String getName() { + return name ?? ""; + } + + @override + Map infos(); + + double? width; + double? height; + @override + double? getWidth() { + return width; + } + @override + double? getHeight() { + return height; + } + + Map setVariable(String key, dynamic value, Map map) { + map[key] = value; + return map; + } + + dynamic getVariable(String key, Map map) { + return map[key]; + } + + Map toJSON() { + return { + "id": id, + "type": type ?? topic, + "name": name, + "logo": logo, + "owners": toListJson(owners), + "creator_id": creatorID, + "updater_id": updaterID, + "creation_date": createdAt?.toIso8601String(), + "update_date": updatedAt?.toIso8601String(), + "description": description, + "short_description": shortDescription, + "selected_instance": selectedInstance, + "instances": instances.map((e) => e.serialize()).toList(), + }; + } + + void mapFromJSON(dynamic json, S ex) { + try { json = json as Map; + } catch (e) { return; } + this.id = json.containsKey("id") ? json["id"] : null; + this.type = json.containsKey("type") ? json["type"] : topic; + this.name = json.containsKey("name") ? json["name"] : null; + this.logo = json.containsKey("logo") ? json["logo"] : null; + this.creatorID = json.containsKey("creator_id") ? json["creator_id"] : null; + this.updaterID = json.containsKey("updater_id") ? json["updater_id"] : null; + this.description = json.containsKey("description") ? json["description"] : null; + this.owners = json.containsKey("owners") ? fromListJson(json["owners"], Owner()) : []; + this.instances = json.containsKey("instances") ? fromListJson(json["instances"], ex) : []; + this.updatedAt = json.containsKey("update_date") ? DateTime.parse(json["update_date"]) : null; + this.selectedInstance = json.containsKey("selected_instance") ? json["selected_instance"] : 0; + this.shortDescription = json.containsKey("short_description") ? json["short_description"] : null; + this.createdAt = json.containsKey("creation_date") ? DateTime.parse(json["creation_date"]) : null; + } +} + +class Location extends SerializerDeserializer { + double? latitude; + double? longitude; + + Location({ + this.latitude, + this.longitude, + }); + + @override + Location deserialize(json) { + return Location( + latitude: json.containsKey("latitude") ? json["latitude"] : null, + longitude: json.containsKey("longitude") ? json["longitude"] : null, + ); + } + @override + Map serialize() { + return { + "latitude": latitude, + "longitude": longitude, + }; + } +} + +abstract class AbstractInstance> extends SerializerDeserializer> implements Infos { + String? id; + String? name; + int? countryCode; + Location? location; + List partnerships = []; + List env = []; + List inputs = []; + List outputs = []; + Credential? credential; + + + bool isEnv(String key) { + for (var e in env) { + if (e.name?.contains(key) ?? false || key.contains(e.name ?? "none")) { return true; } + } + return false; + } + + bool isEnvAttr(String attr, String origin, bool isOrigin) { + for (var e in env) { + if (e.attr == attr && ((isOrigin && e.origin != null) || (!isOrigin && e.origin == origin))) { return true; } + } + return false; + } + + @override + Map infos(); + + void mapFromJSON(dynamic json, S ex) { + try { json = json as Map; + } catch (e) { return; } + this.countryCode = json.containsKey("country_code") ? json["country_code"] : null; + this.id = json.containsKey("id") ? json["id"] : null; + this.name = json.containsKey("name") ? json["name"] : null; + this.env = json.containsKey("env") ? fromListJson(json["env"], Param()) : []; + this.inputs = json.containsKey("inputs") ? fromListJson(json["inputs"], Param()) : []; + this.outputs = json.containsKey("outputs") ? fromListJson(json["outputs"], Param()) : []; + this.location = json.containsKey("location") ? Location().deserialize(json["location"]) : null; + this.credential = json.containsKey("credential") ? Credential().deserialize(json["credential"]) : null; + this.partnerships = json.containsKey("partnerships") ? fromListJson(json["partnerships"], ex) : []; + } + + Map toJSON() { + return { + "country_code": countryCode, + "id": id, + "name": name, + "location": location?.serialize(), + "env": toListJson(env), + "inputs": toListJson(inputs), + "outputs": toListJson(outputs), + "credential": credential?.serialize(), // TODO CREDENTIAL FORM + "partnerships": partnerships.map((e) => e.serialize()).toList(), + }; + } +} + +abstract class AbstractPartnerShip extends SerializerDeserializer> { + String? namespace; + List pricings = []; + + void mapFromJSON(dynamic json, S ex) { + try { json = json as Map; + } catch (e) { return; } + this.namespace = json.containsKey("namespace") ? json["namespace"] : null; + this.pricings = json.containsKey("pricings") ? fromListJson(json["pricings"], ex) : []; + } + + Map toJSON() { + return { + "namespace": namespace, + "pricings": pricings, + }; + } +} + +abstract class AbstractPricing extends SerializerDeserializer { + PricingStrategy? pricing; + int? refundTypeEnum; + int? refundRatio; + List additionnalRefundTypeEnum = []; + int? privilegeStrategyEnum; + int? garantedDelaySecond; + bool exceeding = false; + int? exceedingRatio; + + void mapFromJSON(dynamic json) { + try { json = json as Map; + } catch (e) { return; } + pricing = json.containsKey("pricing") ? PricingStrategy().deserialize(json["pricing"]) : null; + refundTypeEnum = json.containsKey("refund_type") ? json["refund_type"] : null; + refundRatio = json.containsKey("refund_ratio") ? json["refund_ratio"] : null; + additionnalRefundTypeEnum = json.containsKey("additionnal_refund_type") ? json["additionnal_refund_type"] : []; + privilegeStrategyEnum = json.containsKey("privilege_strategy") ? json["privilege_strategy"] : null; + garantedDelaySecond = json.containsKey("garanted_delay") ? json["garanted_delay"] : null; + exceeding = json.containsKey("exceeding") ? json["exceeding"] : false; + exceedingRatio = json.containsKey("exceeding_ratio") ? json["exceeding_ratio"] : null; + } + + Map toJSON() { + return { + "pricing": pricing?.serialize(), + "refund_type": refundTypeEnum, + "refund_ratio": refundRatio, + "additionnal_refund_type": additionnalRefundTypeEnum, + "privilege_strategy": privilegeStrategyEnum, + "garanted_delay": garantedDelaySecond, + "exceeding": exceeding, + "exceeding_ratio": exceedingRatio, + }; + } +} + +class PricingStrategy extends SerializerDeserializer { + double? price; + String? currency; + int? buyingStrategyEnum; + int? timeStrategyEnum; + int? overrideStrategyEnum; + + PricingStrategy({ + this.price, + this.currency, + this.buyingStrategyEnum, + this.timeStrategyEnum, + this.overrideStrategyEnum, + }); + + @override + PricingStrategy deserialize(dynamic json) { + return PricingStrategy( + price: json.containsKey("price") && json["price"] != null ? json["price"] : null, + currency: json.containsKey("currency") && json["currency"] != null ? json["currency"] : null, + buyingStrategyEnum: json.containsKey("buying_strategy") ? json["buying_strategy"] : null, + timeStrategyEnum: json.containsKey("time_strategy") ? json["time_strategy"] : null, + overrideStrategyEnum: json.containsKey("override_strategy") ? json["override_strategy"] : null, + ); + } + @override + Map serialize() { + return { + "price": price, + "currency": currency, + "buying_strategy": buyingStrategyEnum, + "time_strategy": timeStrategyEnum, + "override_strategy": overrideStrategyEnum, + }; + } +} + +class Model extends SerializerDeserializer { + dynamic value; + String? type; + bool readonly = false; + + Model({ + this.value, + this.type, + this.readonly = false, + }); + + @override deserialize(dynamic json) { + try { json = json as Map; + } 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 serialize() => { + "value": value, + "type": type, + "readonly": readonly, + }; +} + +Type? getTopicType(String topic) { + if (topic == "processing") { return ProcessingItem; } + else if (topic == "data") { return DataItem; } + else if (topic == "compute") { return ComputeItem; } + else if (topic == "storage") { return StorageItem; } + else if (topic == "workflow") { return WorkflowItem; } + else { return null; } +} + +String getTopic(Type type) { + if (type == AbstractItem) { return "resource"; } + if (type == ProcessingItem) { return "processing"; } + if (type == DataItem) { return "data"; } + if (type == ComputeItem) { return "compute"; } + if (type == StorageItem) { return "storage"; } + if (type == WorkflowItem) { return "workflow"; } + return ""; +} + +bool isComputing(String topic) => topic == "processing"; +bool isData(String topic) => topic == "data"; +bool isCompute(String topic) => topic == "compute"; +bool isStorage(String topic) => topic == "storage"; +bool isWorkflow(String topic) => topic == "workflow"; + +Color getColor(String topic) => isData(topic) ? Colors.blue : isComputing(topic) ? Colors.green : + isCompute(topic) ? Colors.orange : isStorage(topic) ? redColor : Colors.grey; \ No newline at end of file diff --git a/lib/models/resources/storage.dart b/lib/models/resources/storage.dart new file mode 100644 index 0000000..d9a0fab --- /dev/null +++ b/lib/models/resources/storage.dart @@ -0,0 +1,166 @@ + +import 'package:flutter/material.dart'; +import 'package:oc_front/core/services/enum_service.dart'; +import 'package:oc_front/models/abstract.dart'; +import 'package:oc_front/models/resources/resources.dart'; + +class StorageItem extends AbstractItem { + StorageItem({ + this.acronym, + this.typeEnum, + }): super(); + + @override String get topic => "storage"; + // special attributes + String? acronym; + int? typeEnum; + + @override deserialize(dynamic data) { + try { data = data as Map; + } catch (e) { return StorageItem(); } + var w = StorageItem( + acronym: data.containsKey("acronym") && data["acronym"] != null ? data["acronym"] : null, + typeEnum: data.containsKey("storage_type") && data["storage_type"] != null ? EnumService.get("storage/type", data["storage_type"]) : null, + ); + w.mapFromJSON(data, StorageInstance()); + if (w.logo != null) { // get image dimensions + var image = Image.network(w.logo!); + image.image + .resolve(const ImageConfiguration()) + .addListener( + ImageStreamListener( + (ImageInfo info, bool _) { + w.width = info.image.width.toDouble(); + w.height = info.image.height.toDouble(); + })); + } + return w; + } + + @override + Map infos() { + return { + "acronym": acronym, + "storage_type": EnumService.enums["storage/type"] != null + && EnumService.enums["storage/type"]!["$typeEnum"] != null ? + EnumService.enums["storage/type"]!["$typeEnum"] : typeEnum, + }; + } + + @override Map serialize() { + var obj = infos(); + obj.addAll(toJSON()); + return obj; + } +} + +class StorageInstance extends AbstractInstance { + String? source; + bool local = false; + String? securityLevel; + int? storageSizeEnum; + int? size; + bool encryption = false; + String? redundancy; + String? throughput; + + StorageInstance({ + this.source, + this.local = false, + this.securityLevel, + this.storageSizeEnum, + this.size, + this.encryption = false, + this.redundancy, + this.throughput, + }): super(); + + @override + StorageInstance deserialize(json) { + try { json = json as Map; + } catch (e) { return StorageInstance(); } + var w = StorageInstance( + source: json.containsKey("source") && json["source"] != null ? json["source"] : null, + local: json.containsKey("local") && json["local"] != null ? json["local"] : false, + securityLevel: json.containsKey("security_level") && json["security_level"] != null ? json["security_level"] : null, + storageSizeEnum: json.containsKey("size_type") ? EnumService.get("storage/size", json["size_type"]) : null, + size: json.containsKey("size") && json["size"] != null ? json["size"] : null, + encryption: json.containsKey("encryption") && json["encryption"] != null ? json["encryption"] : false, + redundancy: json.containsKey("redundancy") && json["redundancy"] != null ? json["redundancy"] : null, + throughput: json.containsKey("throughput") && json["throughput"] != null ? json["throughput"] : null, + ); + w.mapFromJSON(json, StoragePartnership()); + return w; + } + + @override + Map infos() { + return { + "local": local, + "security_level": securityLevel, + "size_type": EnumService.enums["storage/size"] != null + && EnumService.enums["storage/size"]!["$storageSizeEnum"] != null ? + EnumService.enums["storage/size"]!["$storageSizeEnum"] : storageSizeEnum, + "size": size, + "encryption": encryption, + "redundancy": redundancy, + "throughput": throughput, + "inputs": toListJson(inputs), + "outputs": toListJson(outputs), + }; + } + + + @override + Map serialize() { + var obj = infos(); + obj["source"] = source; + obj["size_type"] = storageSizeEnum; + obj.addAll(toJSON()); + return obj; + } +} + +class StoragePartnership extends AbstractPartnerShip { + double? maxSizeGBAllowed; + bool onlyEncryptedAllowed = false; + + StoragePartnership({ + this.maxSizeGBAllowed, + this.onlyEncryptedAllowed = false, + }): super(); + + @override + StoragePartnership deserialize(json) { + try { json = json as Map; + } catch (e) { return StoragePartnership(); } + var w = StoragePartnership( + maxSizeGBAllowed: json.containsKey("allowed_gb") && json["allowed_gb"] != null ? json["allowed_gb"] : null, + onlyEncryptedAllowed: json.containsKey("personal_data_allowed") && json["personal_data_allowed"] != null ? json["personal_data_allowed"] : false, + ); + w.mapFromJSON(json, StoragePricing()); + return w; + } + + @override + Map serialize() { + Map obj = { + "allowed_gb": maxSizeGBAllowed, + "personal_data_allowed": onlyEncryptedAllowed, + }; + obj.addAll(toJSON()); + return obj; + } +} + +class StoragePricing extends AbstractPricing { + @override StoragePricing deserialize(json) { + var w = StoragePricing(); + w.mapFromJSON(json); + return w; + } + @override + Map serialize() { + return toJSON(); + } +} \ No newline at end of file diff --git a/lib/models/resources/workflow.dart b/lib/models/resources/workflow.dart new file mode 100644 index 0000000..2be8e16 --- /dev/null +++ b/lib/models/resources/workflow.dart @@ -0,0 +1,101 @@ + +import 'package:flutter/material.dart'; +import 'package:oc_front/models/resources/resources.dart'; + +class WorkflowItem extends AbstractItem { + // special attributes + String? workflowID; + + WorkflowItem({ + this.workflowID, + }): super(); + + @override String get topic => "workflow"; + + @override deserialize(dynamic data) { + try { data = data as Map; + } catch (e) { return WorkflowItem(); } + var w = WorkflowItem( + workflowID: data.containsKey("workflow_id") && data["workflow_id"] != null ? data["workflow_id"] : null, + ); + w.mapFromJSON(data, WorkflowInstance()); + if (w.logo != null) { // get image dimensions + var image = Image.network(w.logo!); + image.image + .resolve(const ImageConfiguration()) + .addListener( + ImageStreamListener( + (ImageInfo info, bool _) { + w.width = info.image.width.toDouble(); + w.height = info.image.height.toDouble(); + })); + } + return w; + } + + @override + Map infos() { + return {}; + } + + @override Map serialize() { + Map obj ={ + "workflow_id": workflowID, + }; + obj.addAll(toJSON()); + return obj; + } +} + +class WorkflowInstance extends AbstractInstance { + WorkflowInstance(): super(); + + @override + WorkflowInstance deserialize(json) { + try { json = json as Map; + } catch (e) { return WorkflowInstance(); } + var w = WorkflowInstance(); + w.mapFromJSON(json, WorkflowPartnership()); + return w; + } + + @override + Map infos() { + return {}; + } + + @override + Map serialize() { + return toJSON(); + } +} + +class WorkflowPartnership extends AbstractPartnerShip { + WorkflowPartnership(): super(); + + @override + WorkflowPartnership deserialize(json) { + try { json = json as Map; + } catch (e) { return WorkflowPartnership(); } + var w = WorkflowPartnership(); + w.mapFromJSON(json, WorkflowPricing()); + return w; + } + + @override + Map serialize() { + return toJSON(); + } +} + +class WorkflowPricing extends AbstractPricing { + @override WorkflowPricing deserialize(json) { + var w = WorkflowPricing(); + w.mapFromJSON(json); + return w; + } + @override + Map serialize() { + return toJSON(); + } +} \ No newline at end of file diff --git a/lib/models/response.dart b/lib/models/response.dart index afb7a37..1b7db03 100644 --- a/lib/models/response.dart +++ b/lib/models/response.dart @@ -1,5 +1,10 @@ import 'package:oc_front/models/abstract.dart'; import 'package:oc_front/models/logs.dart'; +import 'package:oc_front/models/resources/compute.dart'; +import 'package:oc_front/models/resources/data.dart'; +import 'package:oc_front/models/resources/processing.dart'; +import 'package:oc_front/models/resources/resources.dart'; +import 'package:oc_front/models/resources/storage.dart'; import 'package:oc_front/models/search.dart'; import 'package:oc_front/models/shared.dart'; import 'package:oc_front/models/workflow.dart'; @@ -20,6 +25,7 @@ Map refs = { Check: Check(), CollaborativeArea: CollaborativeArea(), SimpleData: SimpleData(), + EnumData: EnumData(), }; class APIResponse { @@ -53,7 +59,9 @@ class APIResponse { code: j.containsKey("code") && j["code"] != null ? j["code"] : 200, error: j.containsKey("error") && j["error"] != null ? j["error"] : "", ); - } catch (e) { return APIResponse( data: refs[T]!.deserialize(data), ); } + } catch (e) { + return APIResponse( data: refs[T]?.deserialize(data), ); + } } } @@ -66,17 +74,34 @@ class SimpleData extends SerializerDeserializer { @override Map serialize() => { }; } +class EnumData extends SerializerDeserializer { + EnumData({ this.value = const {} }); + Map value = {}; + @override deserialize(dynamic json) { + return EnumData(value: json as Map); + } + @override Map serialize() => { }; +} + class RawData extends SerializerDeserializer { RawData({ this.values = const []}); List values = []; @override deserialize(dynamic json) { - return RawData(values: json ?? []); } + try { + return RawData(values: json ?? []); + } catch (e) { + print(e); + print(json); + return RawData(); + } + } @override Map serialize() => { }; } abstract class ShallowData { String getID(); String getName(); + Map serialize(); } class Shallow { diff --git a/lib/models/schedule.dart b/lib/models/schedule.dart new file mode 100644 index 0000000..b7d170a --- /dev/null +++ b/lib/models/schedule.dart @@ -0,0 +1,37 @@ +import 'package:oc_front/models/abstract.dart'; + +class Scheduler extends SerializerDeserializer { + DateTime? start; + DateTime? end; + double? duration; + String? cron; + + Scheduler({ + this.start, + this.end, + this.duration, + this.cron, + }); + + @override + Scheduler deserialize(json) { + try { json = json as Map; + } catch (e) { return Scheduler(); } + var w = Scheduler( + start: json.containsKey("start") && json["start"] != null ? DateTime.parse(json["start"]) : null, + end: json.containsKey("end") && json["end"] != null ? DateTime.parse(json["end"]) : null, + duration: json.containsKey("duration_s") && json["duration_s"] != null ? json["duration_s"] : -1, + cron: json.containsKey("cron") && json["cron"] != null ? json["cron"] : null, + ); + return w; + } + + @override Map serialize() { + return { + "start": start?.toIso8601String(), + "end": end?.toIso8601String(), + "duration_s": duration, + "cron": cron, + }; + } +} \ No newline at end of file diff --git a/lib/models/search.dart b/lib/models/search.dart index bad965a..26d18cf 100644 --- a/lib/models/search.dart +++ b/lib/models/search.dart @@ -1,19 +1,15 @@ -import 'dart:async'; -import 'dart:ui' as ui; -import 'package:flutter/material.dart'; -import 'package:flutter_flow_chart/flutter_flow_chart.dart'; import 'package:oc_front/models/abstract.dart'; +import 'package:oc_front/models/resources/compute.dart'; +import 'package:oc_front/models/resources/data.dart'; +import 'package:oc_front/models/resources/processing.dart'; +import 'package:oc_front/models/resources/storage.dart'; -const List _emptyComputing = []; -const List _emptyData = []; -const List _emptyCompute = []; -const List _emptyStorage = []; class Search extends SerializerDeserializer { Search({ - this.computing = _emptyComputing, - this.compute = _emptyCompute, - this.data = _emptyData, - this.storage = _emptyStorage, + this.computing = const [], + this.compute = const [], + this.data = const [], + this.storage = const [], }); List computing; List compute; @@ -35,1111 +31,3 @@ class Search extends SerializerDeserializer { "storage": toListJson(storage), }; } -const List _empty = []; - -class Resource implements SerializerDeserializer { - List datas = []; - List processings = []; - List storages = []; - List computes = []; - List workflows = []; - - Resource({ - this.datas = const [], - this.processings = const [], - this.storages = const [], - this.computes = const [], - this.workflows = const [], - }); - - @override Resource deserialize(json) { - try { json = json as Map; - } catch (e) { return Resource(); } - return Resource( - computes: json.containsKey("compute_resource") ? fromListJson(json["compute_resource"], ComputeItem()) : [], - 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 serialize() { - return { - "compute_resource": toListJson(computes), - "data_resource": toListJson(datas), - "processing_resource": toListJson(processings), - "storage_resource": toListJson(storages), - "workflow_resource": toListJson(workflows), - }; - } -} - -abstract class AbstractItem extends FlowData implements SerializerDeserializer { - String? id; - String? name; - String? logo; - String? owner; - String? ownerLogo; - String? source; - String? description; - String? shortDescription; - double? price; - String? licence; - List inputs = []; - List outputs = []; - ResourceModel? model; - 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 ?? ""; - } - - String getTopic() { - return topic; - } -} - -class Model extends SerializerDeserializer { - dynamic value; - String? type; - bool readonly = false; - - Model({ - this.value, - this.type, - this.readonly = false, - }); - - @override deserialize(dynamic json) { - try { json = json as Map; - } 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 serialize() => { - "value": value, - "type": type, - "readonly": readonly, - }; -} - -class ResourceModel extends SerializerDeserializer { - String? id; - String? type; - Map refs; - Map>? model; - - ResourceModel({ - this.id, - this.type, - this.refs = const {}, - this.model, - }); - - @override deserialize(dynamic json) { - try { json = json as Map; - } catch (e) { return ResourceModel(); } - var w = ResourceModel( - id: json.containsKey("id") ? json["id"] : null, - type: json.containsKey("type") ? json["type"] : null, - refs: json.containsKey("var_refs") ? json["var_refs"] : {}, - ); - if (json.containsKey("model")) { - w.model = {}; - for (var key in (json["model"] as Map).keys) { - w.model![key] = {}; - for (var k2 in (json["model"][key] as Map).keys) { - w.model![key]![k2] = Model().deserialize(json["model"][key][k2]); - } - } - } - return w; - } - @override Map serialize() { - Map t = { - "id": id, - "type": type, - "var_refs": refs, - }; - t["model"] = {}; - if (model != null) { - for (var key in model!.keys) { - t["model"][key] = {}; - for (var k2 in model![key]!.keys) { - t["model"][key]![k2] = model![key]![k2]!.serialize(); - } - } - } - - return t; - } -} - -Type? getTopicType(String topic) { - if (topic == "processing") { return ProcessingItem; } - else if (topic == "data") { return DataItem; } - else if (topic == "compute") { return ComputeItem; } - else if (topic == "storage") { return StorageItem; } - else if (topic == "workflow") { return WorkflowItem; } - else { return null; } -} - -String getTopic(Type type) { - if (type == AbstractItem) { return "resource"; } - if (type == ProcessingItem) { return "processing"; } - if (type == DataItem) { return "data"; } - if (type == ComputeItem) { return "compute"; } - if (type == StorageItem) { return "storage"; } - if (type == WorkflowItem) { return "workflow"; } - return ""; -} - -bool isComputing(String topic) => topic == "processing"; -bool isData(String topic) => topic == "data"; -bool isCompute(String topic) => topic == "compute"; -bool isStorage(String topic) => topic == "storage"; -bool isWorkflow(String topic) => topic == "workflow"; - -class Expose extends SerializerDeserializer { - Expose({ - this.PAT, - this.port, - this.path, - }); - - int? port; - int? PAT; - String? path; - - @override deserialize(dynamic json) { - try { json = json as Map; - } catch (e) { return Expose(); } - return Expose( - port: json.containsKey("port") ? json["port"] : null, - PAT: json.containsKey("PAT") ? json["PAT"] : null, - path: json.containsKey("reverse") ? json["reverse"] : null, - ); - } - - @override Map serialize() => { - "port": port, - "PAT": PAT, - "reverse": path, - }; -} - -class Containered extends SerializerDeserializer { - Containered({ - this.image, - this.args, - this.command, - this.env, - this.volumes, - }); - - String? args; - String? image; - String? command; - Map? env; - Map? volumes; - - @override deserialize(dynamic json) { - try { json = json as Map; - } catch (e) { return Containered(); } - return Containered( - args: json.containsKey("args") ? json["args"] : null, - image: json.containsKey("image") ? json["image"] : null, - command: json.containsKey("command") ? json["command"] : null, - env: json.containsKey("env") ? json["env"] : null, - volumes: json.containsKey("volumes") ? json["volumes"] : null, - ); - } - - @override Map serialize() { - var w = { - "args": args, - "image": image, - "command": command, - "env": env, - "volumes": volumes, - }; - return w; - } -} - -class ProcessingItem extends SerializerDeserializer implements AbstractItem { - @override - String getTopic() { - return topic; - } - - ProcessingItem({ - this.id, - this.name, - this.logo, - this.owner, - this.ownerLogo, - this.price, - this.source, - this.licence, - this.description, - this.shortDescription, - this.inputs = _empty, - this.outputs = _empty, - - this.cpus = const [], - this.gpus = const [], - this.ram, - this.storage, - this.parrallel = false, - this.scallingModel, - this.diskIO, - - this.expose = const [], - this.container, - this.model, - }); - @override ResourceModel? model; - @override String? id; - @override String? name; - @override String? logo; - @override String? source; - @override String? ownerLogo; - @override String? owner; - @override String topic = "processing"; - @override double? price; - @override String? licence; - @override List inputs; - @override List outputs; - @override String? description; - @override String? shortDescription; - - Containered? container; - List expose = []; - // Special Attributes - List cpus = []; - List gpus = []; - RAM? ram; - int? storage; - bool parrallel = false; - int? scallingModel; - String? diskIO; - - @override String getID() { - return id ?? ""; - } - - @override String getName() { - return name ?? ""; - } - double? width; - double? height; - @override - double? getWidth() { - return width; - } - @override - double? getHeight() { - return height; - } - @override - Map setVariable(List keys, dynamic value, Map map) { - if (keys.isEmpty) { return map; } - var key = keys[0]; - if (keys.length > 1 && map[key] != null) { - map[key] = setVariable(keys.sublist(1), value, map[key]); - } else { - map[key] = value; - } - return map; - } - @override - dynamic getVariable(List keys, Map map) { - if (keys.isEmpty) { return null; } - var key = keys[0]; - if (keys.length > 1 && map[key] != null) { - return getVariable(keys.sublist(1), map[key]); - } - return map[key]; - } - - @override deserialize(dynamic json) { - try { json = json as Map; - } catch (e) { return ProcessingItem(); } - var w = ProcessingItem( - id: json.containsKey("id") ? json["id"] : null, - name: json.containsKey("name") ? json["name"] : null, - logo: json.containsKey("logo") ? json["logo"] : 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, - 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, - - expose: json.containsKey("expose") ? fromListJson(json["expose"], Expose()) : [], - container: json.containsKey("container") ? Containered().deserialize(json["container"]) : 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, - ); - if (w.logo != null) { - var image = Image.network(w.logo!); - image.image - .resolve(const ImageConfiguration()) - .addListener( - ImageStreamListener( - (ImageInfo info, bool _) { - w.width = info.image.width.toDouble(); - w.height = info.image.height.toDouble(); - })); - } - return w; - } - @override Map serialize() { - return { - "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(cpus), - "gpus": toListJson(gpus), - "ram": ram?.serialize(), - "storage": storage, - "parrallel": parrallel, - "scalling_model": scallingModel, - "disk_io": diskIO, - "" - "expose": toListJson(expose), - "container": container?.serialize(), - }; } -} - -class WorkflowItem extends SerializerDeserializer implements AbstractItem { - @override - String getTopic() { - return topic; - } - - WorkflowItem({ - this.id, - this.name, - this.logo, - this.owner, - this.ownerLogo, - this.price, - this.source, - this.licence, - this.description, - this.shortDescription, - this.inputs = _empty, - this.outputs = _empty, - this.model, - this.workflowID, - }); - @override ResourceModel? model; - @override String? id; - @override String? name; - @override String? logo; - @override String? source; - @override String? ownerLogo; - @override String? owner; - @override String topic = "workflow"; - @override double? price; - @override String? licence; - @override List inputs; - @override List outputs; - @override String? description; - @override String? shortDescription; - - String? workflowID; - @override String getID() { - return id ?? ""; - } - - double? width; - double? height; - @override - double? getWidth() { - return width; - } - @override - double? getHeight() { - return height; - } - - @override String getName() { - return name ?? ""; - } - @override - Map setVariable(List keys, dynamic value, Map map) { - if (keys.isEmpty) { return map; } - var key = keys[0]; - if (keys.length > 1 && map[key] != null) { - map[key] = setVariable(keys.sublist(1), value, map[key]); - } else { - map[key] = value; - } - return map; - } - @override - dynamic getVariable(List keys, Map map) { - if (keys.isEmpty) { return null; } - var key = keys[0]; - if (keys.length > 1 && map[key] != null) { - return getVariable(keys.sublist(1), map[key]); - } - return map[key]; - } - - @override deserialize(dynamic json) { - try { json = json as Map; - } catch (e) { return WorkflowItem(); } - var w = WorkflowItem( - id: json.containsKey("id") ? json["id"] : null, - name: json.containsKey("name") ? json["name"] : null, - logo: json.containsKey("logo") ? json["logo"] : 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, - 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, - ); - if (w.logo != null) { - // - var image = Image.network(w.logo!); - image.image - .resolve(const ImageConfiguration()) - .addListener( - ImageStreamListener( - (ImageInfo info, bool _) { - w.width = info.image.width.toDouble(); - w.height = info.image.height.toDouble(); - })); - } - return w; - } - @override Map 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 implements AbstractItem { - @override - String getTopic() { - return topic; - } - DataItem({ - this.id, - this.name, - this.logo, - this.owner, - this.ownerLogo, - this.price, - this.source, - this.licence, - this.description, - this.shortDescription, - this.inputs = _empty, - this.outputs = _empty, - this.model, - this.protocol, - this.path, - this.protocols = const [], - this.type, - this.exemple, - }); - @override String? id; - @override String? name; - @override String? logo; - @override String? source; - @override String? ownerLogo; - @override String? owner; - @override String topic = "data"; - @override double? price; - @override String? licence; - @override List inputs; - @override List outputs; - @override String? description; - @override String? shortDescription; - @override ResourceModel? model; - // Special Attributes - List protocols = []; - String? type; - String? protocol; - String? path; - String? exemple; - @override String getName() { - return name ?? ""; - } - @override String getID() { - return id ?? ""; - } - - double? width; - double? height; - @override - double? getWidth() { - return width; - } - @override - double? getHeight() { - return height; - } - - @override - Map setVariable(List keys, dynamic value, Map map) { - if (keys.isEmpty) { return map; } - var key = keys[0]; - if (keys.length > 1 && map[key] != null) { - map[key] = setVariable(keys.sublist(1), value, map[key]); - } else { - map[key] = value; - } - return map; - } - @override - dynamic getVariable(List keys, Map map) { - if (keys.isEmpty) { return null; } - var key = keys[0]; - if (keys.length > 1 && map[key] != null) { - return getVariable(keys.sublist(1), map[key]); - } - return map[key]; - } - - @override deserialize(dynamic json) { - try { json = json as Map; - } catch (e) { return DataItem(); } - var w = DataItem( - id: json.containsKey("id") ? json["id"] : null, - name: json.containsKey("name") ? json["name"] : null, - logo: json.containsKey("logo") ? json["logo"] : 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, - 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, - protocols: json.containsKey("protocols") ? json["protocols"] : [], - type: json.containsKey("type") ? json["type"] : null, - protocol: json.containsKey("protocol") ? json["protocol"] : null, - path: json.containsKey("path") ? json["path"] : null, - exemple: json.containsKey("exemple") ? json["exemple"] : null, - ); - if (w.logo != null) { - // - var image = Image.network(w.logo!); - image.image - .resolve(const ImageConfiguration()) - .addListener( - ImageStreamListener( - (ImageInfo info, bool _) { - w.width = info.image.width.toDouble(); - w.height = info.image.height.toDouble(); - })); - } - return w; - } - - @override Map 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, - "type": type, - "protocol": protocol, - "path": path, - "exemple": exemple, - }; -} - -class ComputeItem extends SerializerDeserializer implements AbstractItem { - @override - String getTopic() { - return topic; - } - - ComputeItem({ - this.id, - this.name, - this.logo, - this.owner, - this.ownerLogo, - this.price, - this.source, - this.licence, - this.description, - this.shortDescription, - this.inputs = _empty, - this.outputs = _empty, - this.model, - this.cpus = const [], - this.gpus = const [], - this.ram, - this.technology, - this.access, - this.architecture, - this.localisation, - this.isService = false, - }); - @override String? id; - @override String? name; - @override String? logo; - @override String? source; - @override String? ownerLogo; - @override String? owner; - @override String topic = "compute"; - @override double? price; - @override String? licence; - @override List inputs; - @override List outputs; - @override String? description; - @override String? shortDescription; - @override ResourceModel? model; - bool isService = false; - String? architecture; - int? access; - String? localisation; - // Special Attributes - List cpus = []; - List gpus = []; - int? technology; - RAM? ram; - @override String getID() { - return id ?? ""; - } - @override String getName() { - return name ?? ""; - } - double? width; - double? height; - @override - double? getWidth() { - return width; - } - @override - double? getHeight() { - return height; - } - String getTechnology() { - if (technology == 0) { return "docker"; } - if (technology == 1) { return "kubernetes"; } - if (technology == 2) { return "slurm"; } - if (technology == 3) { return "hardware"; } - if (technology == 4) { return "condor"; } - return ""; - } - String getAccess() { - if (access == 0) { return "ssh"; } - if (access == 1) { return "ssh kube api"; } - if (access == 2) { return "ssh slurm"; } - if (access == 3) { return "ssh docker"; } - if (access == 4) { return "opencloud"; } - if (access == 5) { return "vpn"; } - return ""; - } - - @override deserialize(dynamic json) { - try { json = json as Map; - } catch (e) { return ComputeItem(); } - var w = ComputeItem( - isService: json.containsKey("is_service") ? json["is_service"] : false, - id: json.containsKey("id") ? json["id"] : null, - name: json.containsKey("name") ? json["name"] : null, - logo: json.containsKey("logo") ? json["logo"] : null, - technology: json.containsKey("technology") ? json["technology"] : 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, - licence: json.containsKey("licence") ? json["licence"] : null, - description: json.containsKey("description") ? json["description"] : null, - shortDescription: json.containsKey("short_description") ? json["short_description"] : null, - access: json.containsKey("access") ? json["access"] : null, - architecture: json.containsKey("architecture") ? json["architecture"] : null, - localisation: json.containsKey("localisation") ? json["localisation"] : 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, - 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, - ); - if (w.logo != null) { - // - var image = Image.network(w.logo!); - image.image - .resolve(const ImageConfiguration()) - .addListener( - ImageStreamListener( - (ImageInfo info, bool _) { - w.width = info.image.width.toDouble(); - w.height = info.image.height.toDouble(); - })); - } - return w; - } - - @override - Map setVariable(List keys, dynamic value, Map map) { - if (keys.isEmpty) { return map; } - var key = keys[0]; - if (keys.length > 1 && map[key] != null) { - map[key] = setVariable(keys.sublist(1), value, map[key]); - } else { - map[key] = value; - } - return map; - } - - @override - dynamic getVariable(List keys, Map map) { - if (keys.isEmpty) { return null; } - var key = keys[0]; - if (keys.length > 1 && map[key] != null) { - return getVariable(keys.sublist(1), map[key]); - } - return map[key]; - } - - @override Map serialize() => { - "id": id, - "name": name, - "logo": logo, - "owner": owner, - "owner_logo": ownerLogo, - "price": price, - "is_service": isService, - "licence": licence, - "access": access, - "architecture": architecture, - "localisation": localisation, - "description": description, - "short_description": shortDescription, - "inputs": inputs, - "outputs": outputs, - "source": source, - "technology": technology, - "resource_model": model?.serialize(), - "cpus": toListJson(cpus), - "gpus": toListJson(gpus), - "ram": ram?.serialize(), - }; -} -class CPU extends SerializerDeserializer { - CPU({ - this.cores, - this.platform, - this.architecture, - this.minimumMemory, - this.shared = false, - }); - double? cores; - String? platform; - bool shared = false; - String? architecture; - double? minimumMemory; - - @override deserialize(dynamic json) { - try { json = json as Map; - } catch (e) { return CPU(); } - return CPU( - cores: json.containsKey("cores") ? json["cores"]?.toDouble() : null, - platform: json.containsKey("platform") ? json["platform"] : null, - architecture: json.containsKey("architecture") ? json["architecture"] : null, - minimumMemory: json.containsKey("minimumMemory") ? json["minimumMemory"]?.toDouble() : null, - shared: json.containsKey("shared") ? json["shared"] : false, - ); - } - @override Map serialize() => { - "cores": cores, - "platform": platform, - "architecture": architecture, - "minimumMemory": minimumMemory, - "shared": shared, - }; -} -class GPU extends SerializerDeserializer { - GPU({ - this.cudaCores, - this.memory, - this.model, - this.tensorCores, - }); - double? cudaCores; - double? memory; - String? model; - double? tensorCores; - - @override deserialize(dynamic json) { - try { json = json as Map; - } catch (e) { return GPU(); } - return GPU( - cudaCores: json.containsKey("cuda_cores") ? json["cuda_cores"]?.toDouble() : null, - memory: json.containsKey("memory") ? json["memory"]?.toDouble() : null, - model: json.containsKey("model") ? json["model"] : null, - tensorCores: json.containsKey("tensor_cores") ? json["tensor_cores"]?.toDouble() : null, - ); - } - @override Map serialize() => { - "cuda_cores": cudaCores, - "memory": memory, - "model": model, - "tensor_cores": tensorCores, - }; -} -class RAM extends SerializerDeserializer { - RAM({ - this.ecc = false, - this.size, - }); - bool ecc = false; - double? size; - - @override deserialize(dynamic json) { - try { json = json as Map; - } catch (e) { return RAM(); } - return RAM( - ecc: json.containsKey("ecc") ? json["ecc"] : false, - size: json.containsKey("size") ? json["size"]?.toDouble() : null, - ); - } - @override Map serialize() => { - "ecc": ecc, - "size": size, - }; -} -class StorageItem extends SerializerDeserializer implements AbstractItem { - @override - String getTopic() { - return topic; - } - - StorageItem({ - this.id, - this.name, - this.logo, - this.owner, - this.ownerLogo, - this.price, - this.source, - this.licence, - this.description, - this.shortDescription, - this.inputs = _empty, - this.outputs = _empty, - this.acronym, - this.type, - this.size, - this.path, - this.protocol, - this.encryption = false, - this.redundancy, - this.throughput, - this.model, - this.local = false, - }); - bool local = false; - @override String? id; - @override String? name; - @override String? logo; - @override String? source; - @override String? ownerLogo; - @override String? owner; - @override String topic = "storage"; - @override double? price; - @override String? licence; - @override List inputs; - @override List outputs; - @override String? description; - @override String? shortDescription; - @override ResourceModel? model; - // special attributes - String? acronym; - String? type; - String? path; - String? protocol; - int? size; - bool encryption = false; - String? redundancy; - String? throughput; - @override String getName() { - return name ?? ""; - } - @override String getID() { - return id ?? ""; - } - double? width; - double? height; - @override - double? getWidth() { - return width; - } - @override - double? getHeight() { - return height; - } - - @override - dynamic getVariable(List keys, Map map) { - if (keys.isEmpty) { return null; } - var key = keys[0]; - if (keys.length > 1 && map[key] != null) { - return getVariable(keys.sublist(1), map[key]); - } - return map[key]; - } - - @override - Map setVariable(List keys, dynamic value, Map map) { - if (keys.isEmpty) { return map; } - var key = keys[0]; - if (keys.length > 1 && map[key] != null) { - map[key] = setVariable(keys.sublist(1), value, map[key]); - } else { - map[key] = value; - } - return map; - } - - @override deserialize(dynamic json) { - try { json = json as Map; - } catch (e) { return StorageItem(); } - var w = StorageItem( - id: json.containsKey("id") ? json["id"] : null, - name: json.containsKey("name") ? json["name"] : null, - logo: json.containsKey("logo") ? json["logo"] : 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, - licence: json.containsKey("licence") ? json["licence"] : null, - description: json.containsKey("description") ? json["description"] : null, - shortDescription: json.containsKey("short_description") ? json["short_description"] : null, - local: json.containsKey("local") ? json["local"] : false, - 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, - path: json.containsKey("path") ? json["path"] : null, - protocol: json.containsKey("protocol") ? json["protocol"] : null, - encryption: json.containsKey("encryption") ? json["encryption"] : false, - redundancy: json.containsKey("redundancy") ? json["redundancy"] : null, - throughput: json.containsKey("throughput") ? json["throughput"] : null, - ); - if (w.logo != null) { - // - var image = Image.network(w.logo!); - image.image - .resolve(const ImageConfiguration()) - .addListener( - ImageStreamListener( - (ImageInfo info, bool _) { - w.width = info.image.width.toDouble(); - w.height = info.image.height.toDouble(); - })); - } - return w; - } - @override Map serialize() => { - "id": id, - "name": name, - "logo": logo, - "owner": owner, - "owner_logo": ownerLogo, - "price": price, - "local": local, - "licence": licence, - "description": description, - "short_description": shortDescription, - "inputs": inputs, - "outputs": outputs, - "source": source, - "resource_model": model?.serialize(), - "acronym": acronym, - "type": type, - "size": size, - "path": path, - "protocol": protocol, - "encryption": encryption, - "redundancy": redundancy, - "throughput": throughput, - }; -} \ No newline at end of file diff --git a/lib/models/shared.dart b/lib/models/shared.dart index e657acc..0b3a930 100644 --- a/lib/models/shared.dart +++ b/lib/models/shared.dart @@ -79,13 +79,14 @@ class CollaborativeArea extends SerializerDeserializer { rule : json.containsKey("collaborative_area") ? CollaborativeAreaRule().deserialize(json["collaborative_area"]) : CollaborativeAreaRule(), id: json.containsKey("id") ? json["id"] : null, name: json.containsKey("name") ? json["name"] : null, + creatorID: json.containsKey("creator_id") ? json["creator_id"] : null, description: json.containsKey("description") ? json["description"] : null, version: json.containsKey("version") ? json["version"] : null, attributes: json.containsKey("attributes") ? json["attributes"] : {}, - workspaces: json.containsKey("shared_workspaces") ? fromListJson(json["shared_workspaces"], Workspace()) : [], - workflows: json.containsKey("shared_workflows") ? fromListJson(json["shared_workflows"], Workflow()) : [], - peers: json.containsKey("shared_peers") ? fromListJson(json["shared_peers"], Peer()) : [], - rules: json.containsKey("rules") ? json["rules"] : [], + workspaces: json.containsKey("shared_workspaces") && json["shared_workspaces"] != null ? fromListJson(json["shared_workspaces"], Workspace()) : [], + workflows: json.containsKey("shared_workflows") && json["shared_workflows"] != null ? fromListJson(json["shared_workflows"], Workflow()) : [], + peers: json.containsKey("shared_peers") && json["shared_peers"] != null ? fromListJson(json["shared_peers"], Peer()) : [], + rules: json.containsKey("shared_rules") && json["shared_rules"] != null ? json["shared_rules"] : [], ); } @override diff --git a/lib/models/workflow.dart b/lib/models/workflow.dart index c2e5791..3d6b047 100644 --- a/lib/models/workflow.dart +++ b/lib/models/workflow.dart @@ -1,40 +1,41 @@ import 'package:flutter/material.dart'; import 'package:flutter_colorpicker/flutter_colorpicker.dart'; import 'package:flutter_flow_chart/flutter_flow_chart.dart'; -import 'package:oc_front/core/models/workspace_local.dart'; import 'package:oc_front/models/abstract.dart'; import 'package:oc_front/models/logs.dart'; +import 'package:oc_front/models/resources/compute.dart'; +import 'package:oc_front/models/resources/data.dart'; +import 'package:oc_front/models/resources/processing.dart'; +import 'package:oc_front/models/resources/resources.dart'; +import 'package:oc_front/models/resources/storage.dart'; +import 'package:oc_front/models/resources/workflow.dart'; import 'package:oc_front/models/response.dart'; -import 'package:oc_front/models/search.dart'; +import 'package:oc_front/widgets/forms/sub_keys_forms.dart'; class Check extends SerializerDeserializer { - bool is_available = false; + bool isAvailable = false; Check({ - this.is_available = false, + this.isAvailable = false, }); @override deserialize(dynamic json) { try { json = json as Map; } catch (e) { return Check(); } return Check( - is_available: json.containsKey("is_available") ? json["is_available"] : false, + isAvailable: json.containsKey("is_available") ? json["is_available"] : false, ); } @override Map serialize() { return { - "is_available": is_available, + "is_available": isAvailable, }; } } - class WorkflowExecutions extends SerializerDeserializer { List executions = []; - String? executionData; - int? status; - String? workflowId; - + WorkflowExecutions({ this.executions = const [], }); @@ -56,7 +57,7 @@ class WorkflowExecutions extends SerializerDeserializer { class WorkflowExecution extends SerializerDeserializer { String? id; String? name; - String? executionData; + String? startDate; String? endDate; int? status; String? workflowId; @@ -66,7 +67,7 @@ class WorkflowExecution extends SerializerDeserializer { WorkflowExecution({ this.id, - this.executionData, + this.startDate, this.status, this.workflowId, this.name, @@ -79,7 +80,7 @@ class WorkflowExecution extends SerializerDeserializer { return WorkflowExecution( id: json.containsKey("id") ? json["id"] : "", endDate: json.containsKey("end_date") ? json["end_date"] : "", - executionData: json.containsKey("execution_date") ? json["execution_date"] : "", + startDate: json.containsKey("execution_date") ? json["execution_date"] : "", status: json.containsKey("state") ? json["state"] : 1, workflowId: json.containsKey("workflow_id") ? json["workflow_id"] : "", name: json.containsKey("name") ? json["name"] : "", @@ -91,7 +92,7 @@ class WorkflowExecution extends SerializerDeserializer { "id": id, "name": name, "end_date": endDate, - "execution_data": executionData, + "execution_data": startDate, "status": status, "workflow_id": workflowId, }; @@ -108,8 +109,6 @@ class Workflow extends SerializerDeserializer implements ShallowData List processing; List workflows; Graph? graph; - Scheduler? schedule; - bool scheduleActive = false; List shared; Workflow({ @@ -121,14 +120,12 @@ class Workflow extends SerializerDeserializer implements ShallowData this.processing = const [], this.workflows = const [], this.graph, - this.schedule, - this.scheduleActive = false, this.shared = const [], }); @override String getID() => id ?? ""; @override String getName() => name ?? ""; - @override String getDescription() => ""; + String getDescription() => ""; @override deserialize(dynamic json) { try { json = json as Map; @@ -140,11 +137,9 @@ class Workflow extends SerializerDeserializer implements ShallowData processing: json.containsKey("processings") ? json["processings"] : [], compute: json.containsKey("computes") ? json["computes"] : [], data: json.containsKey("datas") ? json["datas"] : [], - scheduleActive: json.containsKey("schedule_active") ? json["schedule_active"] : false, storage: json.containsKey("storages") ? json["storages"] : [], shared: json.containsKey("shared") ? json["shared"] : [], graph: json.containsKey("graph") ? Graph().deserialize(json["graph"]) : null, - schedule: json.containsKey("schedule") ? Scheduler().deserialize(json["schedule"]) : null, ); } @override Map serialize() { @@ -152,12 +147,10 @@ class Workflow extends SerializerDeserializer implements ShallowData "id": id, "name": name, "datas": data, - "computes" : compute, "storages": storage, - "processings": processing, + "computes" : compute, "workflows": workflows, - "schedule_active": scheduleActive, - "schedule": schedule?.serialize(), + "processings": processing, }; if (graph != null) { obj["graph"] = graph!.serialize(); @@ -168,24 +161,17 @@ class Workflow extends SerializerDeserializer implements ShallowData void fromDashboard(Map j) { id = j["id"]; name = j["name"]; - scheduleActive = j["schedule_active"]; if (j.containsKey("graph")) { graph = Graph(); graph!.fromDashboard(j["graph"]); } - if (j.containsKey("schedule")) { - schedule = Scheduler(); - schedule!.fromDashboard(j["schedule"]); - } } Map toDashboard() { return { "id": id, "name": name, - "graph": graph?.toDashboard(), - "schedule_active": scheduleActive, - "schedule": schedule?.toDashboard(), "shared": shared, + "graph": graph?.toDashboard(), }; } } @@ -221,7 +207,7 @@ class Scheduler extends SerializerDeserializer { end = DateTime.parse(j["end"]); } - } catch (e) {} + } catch (e) { /**/ } } Map toDashboard() { return { @@ -279,6 +265,159 @@ class Graph extends SerializerDeserializer { this.links = const [], }); + Map> getInfosToUpdate(SubMapFormsType type) { + Map> infos = {}; + for (var item in items.values) { + var inst = item.getElement()?.getSelectedInstance(); + if (inst == null) { return infos; } + infos[item.id ?? ""] = (type == SubMapFormsType.INPUT ? inst.inputs : ( + type == SubMapFormsType.OUTPUT ? inst.outputs : inst.env)).map( (e) => e.serialize()).toList(); + } + return infos; + } + + Map> getEnvToUpdate() { + return getInfosToUpdate(SubMapFormsType.ENV); + } + + Map> getInputToUpdate() { + return getInfosToUpdate(SubMapFormsType.INPUT); + } + + Map> getOutputToUpdate() { + return getInfosToUpdate(SubMapFormsType.OUTPUT); + } + + + GraphItem getItemByElementID(String id) { + return items[id] ?? GraphItem(); + } + Map getArrowByElementID(String id) { + Map arr = {}; + for (var link in links) { + var nested = false; + var reverse = false; + String? from = link.source?.id; + String? to = link.destination?.id; + bool isInLink = (from?.contains(id) ?? false) || (to?.contains(id) ?? false); + if (isInLink && (["storage", "compute"].contains(getItemByElementID(from ?? "").getElement()?.getType()) + || ["storage", "compute"].contains(getItemByElementID(to ?? "").getElement()?.getType()))) { + nested = true; + reverse = link.source?.id?.contains(id) ?? false; + } + if (nested || isInLink) { + arr[reverse ? (to ?? "") : (from ?? "") ] = getItemByElementID(reverse ? (to ?? "") : (from ?? "") ); + } + } + return arr; + } + + void fillEnv(AbstractItem? mainItem, GraphItem? item, SubMapFormsType type, Map alreadySeen) { + if (mainItem == null || item == null) { + return; + } + AbstractItem? el = item.getElement(); + if (el?.getSelectedInstance() == null) { + return; + } + var inst = el!.getSelectedInstance()!; + + var inst2 = mainItem.getSelectedInstance()!; + var what = type == SubMapFormsType.INPUT ? inst.inputs : ( + type == SubMapFormsType.OUTPUT ? inst.outputs : inst.env); + var what2 = type == SubMapFormsType.INPUT ? inst2.inputs : ( + type == SubMapFormsType.OUTPUT ? inst2.outputs : inst2.env); + for (var e in what2) { + if (e.attr != null && e.value == null) { + e.value = inst2.serialize()[e.attr!]; + } + } + // should find arrow env info and add it to the env + List extParams = []; + var arrows = links.where( (e) => (e.source?.id?.contains(item.id ?? "") ?? false) || (e.destination?.id?.contains(item.id ?? "") ?? false)); + for (var arrow in arrows) { + for (var info in arrow.infos) { + var i = info as Map; + for (var entry in i.entries) { + if (entry.value == null) { continue; } + + var varName = "LINK_${el.getName().toUpperCase().replaceAll(" ", "_")}_${entry.key.toUpperCase()}"; + /*alreadySeen[varName] = (alreadySeen[varName] ?? -1) + 1; + if ((alreadySeen[varName] ?? 0) > 1) { + varName = "${varName}_${alreadySeen[varName]}"; + }*/ + if ((entry.value is String) && !isEnvAttr(entry.value, what2)) { + extParams.add(Param( name: varName, + attr: entry.key, value: entry.value, origin: item.id, readOnly: true)); + } + } + } + } + for ( var param in what) { + if (param.attr == null) { continue; } + var varName = param.name != null && (param.name!.contains("LINK_") + || param.name!.contains("DATA_") + || param.name!.contains("PROCESSING_") + || param.name!.contains("STORAGE_") + || param.name!.contains("WORKFLOW_") + || param.name!.contains("COMPUTE") ) ? param.name : "${el.topic.toUpperCase()}_${el.getName().toUpperCase().replaceAll(" ", "_")}_${param.attr!.toUpperCase()}"; + /*alreadySeen[varName] = (alreadySeen[varName] ?? -1) + 1; + if ((alreadySeen[varName] ?? 0) > 0) { + varName = "${varName}_${alreadySeen[varName]}"; + }*/ + dynamic env; + if (param.value == null) { + var s = el.serialize(); + s.addAll(el.getSelectedInstance()?.serialize() ?? {}); + env = s[param.attr!]; + } else { + env = param.value; + } + // bool isSrc = param.origin == null; + //if (isSrc) { continue; } + if (!isEnvAttr(env, what2)) { + extParams.add(Param( name: varName, + attr: param.attr, value: env, origin: item.id, readOnly: true)); + } + } + for (var param in extParams) { + what2.add(param); + } + } + + bool isEnvAttr(String value, List params) { + for (var e in params) { + if (value == e.value) { return true; } + } + return false; + } + + void fill() { + Map alreadySeen = {}; + var its = items.values.toList(); + for (var type in [SubMapFormsType.INPUT, SubMapFormsType.OUTPUT, SubMapFormsType.ENV]) { + for (var item in its) { + var envs = type == SubMapFormsType.INPUT ? item.getElement()?.getSelectedInstance()?.inputs : ( + type == SubMapFormsType.OUTPUT ? item.getElement()?.getSelectedInstance()?.outputs : item.getElement()?.getSelectedInstance()?.env); + if (envs != null) { + envs.removeWhere( (e) => e.readOnly && e.name != null + && (e.name!.contains("LINK_") + || e.name!.contains("DATA_") + || e.name!.contains("PROCESSING_") + || e.name!.contains("STORAGE_") + || e.name!.contains("WORKFLOW_") + || e.name!.contains("COMPUTE") )); + } + } + for (var item in [...its, ...its.reversed]) { + var itss = getArrowByElementID(item.id ?? ""); + for (var i in itss.values) { + fillEnv(item.getElement(), i, type, alreadySeen); + } + } + } + } + void fromDashboard(Map j) { items = {}; for (var el in (j["elements"] as Map).values) { @@ -292,9 +431,11 @@ class Graph extends SerializerDeserializer { return d; }).toList(); j["zoom"] = zoom; + fill(); } Map toDashboard() { + fill(); List> elements = []; List> arrows = []; for (var el in items.values) { @@ -313,28 +454,70 @@ class Graph extends SerializerDeserializer { @override deserialize(dynamic json) { try { json = json as Map; } catch (e) { return Graph(); } - return Graph( + var g = Graph( zoom: json.containsKey("zoom") ? double.parse(json["zoom"].toString()) : 0, links: json.containsKey("links") ? fromListJson(json["links"], GraphLink()) : [], items: json.containsKey("items") ? fromMapJson(json["items"], GraphItem()) : {}, ); + g.fill(); + return g; + } + @override Map serialize() { + fill(); + return { + "zoom": zoom, + "items": toMapJson(items), + "links": toListJson(links), + }; + } +} + +class StorageProcessingGraphLink extends SerializerDeserializer { + bool write = false; + String? source; + String? destination; + String? filename; + + StorageProcessingGraphLink({ + this.write = false, + this.source, + this.destination, + this.filename, + }); + + @override deserialize(dynamic json) { + try { json = json as Map; + } catch (e) { return StorageProcessingGraphLink(); } + return StorageProcessingGraphLink( + write: json.containsKey("write") ? json["write"] : false, + source: json.containsKey("source") ? json["source"] : "", + destination: json.containsKey("destination") ? json["destination"] : "", + filename: json.containsKey("filename") && json["filename"] != null ? json["filename"] : "", + ); + } + @override Map serialize() { + return { + "write": write, + "source": source, + "destination": destination, + "filename": filename, + }; } - @override Map serialize() => { - "zoom": zoom, - "items": toMapJson(items), - "links": toListJson(links), - }; } class GraphLink extends SerializerDeserializer { Position? source; Position? destination; GraphLinkStyle? style; + List infos = []; + List env = []; GraphLink({ this.source, this.destination, this.style, + this.infos = const [], + this.env = const [], }); void fromDashboard(Map j) { @@ -342,6 +525,8 @@ class GraphLink extends SerializerDeserializer { destination = Position(id: j["to"]["id"], x: j["to"]["x"], y: j["to"]["y"]); style = GraphLinkStyle(); style!.fromDashboard(j["params"]); + infos = fromListJson(j["infos"], StorageProcessingGraphLink()); + env = fromListJson(j["env"], Param()); } Map toDashboard() { @@ -357,6 +542,8 @@ class GraphLink extends SerializerDeserializer { "y": destination?.y ?? 0, }, "params": style?.toDashboard(), + "infos": toListJson(infos), + "env": env.map( (el) => el.serialize()).toList(), }; } @@ -364,9 +551,11 @@ class GraphLink extends SerializerDeserializer { try { json = json as Map; } catch (e) { return GraphLink(); } return GraphLink( - source: json.containsKey("source") ? Position().deserialize(json["source"]) : null, - destination: json.containsKey("destination") ? Position().deserialize(json["destination"]) : null, - style: json.containsKey("style") ? GraphLinkStyle().deserialize(json["style"]) : null, + source: json.containsKey("source") && json["source"] != null ? Position().deserialize(json["source"]) : null, + destination: json.containsKey("destination") && json["destination"] != null ? Position().deserialize(json["destination"]) : null, + style: json.containsKey("style") && json["style"] != null ? GraphLinkStyle().deserialize(json["style"]) : null, + infos: json.containsKey("storage_link_infos") && json["storage_link_infos"] != null ? fromListJson(json["storage_link_infos"], StorageProcessingGraphLink()) : [], + env: json.containsKey("env") && json["env"] != null ? fromListJson(json["env"], Param()) : [], ); } @override Map serialize() { @@ -380,6 +569,8 @@ class GraphLink extends SerializerDeserializer { if (style != null) { obj["style"] = style!.serialize(); } + obj["storage_link_infos"] = toListJson(infos); + obj["env"] = toListJson(env); return obj; } } @@ -521,33 +712,19 @@ class GraphItem extends SerializerDeserializer { return null; } + void fromDashboard(Map 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?; - if (abs != null) { - if (abs.topic == "data") { - data = DataItem().deserialize(abs.serialize()); - data!.model = ResourceModel().deserialize(j["element"]["resource_model"]); - } else if (abs.topic == "processing") { - processing = ProcessingItem().deserialize(abs.serialize()); - processing!.model = ResourceModel().deserialize(j["element"]["resource_model"]); - if ((j["element"] as Map).containsKey("container")) { - processing!.container = Containered().deserialize(j["element"]["container"]); - processing!.container?.env?.removeWhere((key, value) => key == "" || value == ""); - processing!.container?.volumes?.removeWhere((key, value) => key == "" || value == ""); - processing!.expose.removeWhere((element) => element.port == null || element.port == 0 || (element.PAT == 0 && element.path == "")); - - } - } else if (abs.topic == "compute") { - compute = ComputeItem().deserialize(abs.serialize()); - } else if (abs.topic == "storage") { - storage = StorageItem().deserialize(abs.serialize()); - } else if (abs.topic == "workflow") { - workflow = WorkflowItem().deserialize(abs.serialize()); + if (j["element"] != null) { + if (j["element"]["type"] == "data") { data = DataItem().deserialize(j["element"]); + } else if (j["element"]["type"] == "processing") { processing = ProcessingItem().deserialize(j["element"]); + } else if (j["element"]["type"] == "compute") { compute = ComputeItem().deserialize(j["element"]); + } else if (j["element"]["type"] == "storage") { storage = StorageItem().deserialize(j["element"]); + } else if (j["element"]["type"] == "workflow") { workflow = WorkflowItem().deserialize(j["element"]); } else { compute = null; data = null; @@ -566,7 +743,8 @@ class GraphItem extends SerializerDeserializer { Map toDashboard() { Map element = {}; - for(var el in [data, processing, storage, compute, workflow]) { + List items = [data, processing, storage, compute, workflow]; + for(var el in items) { if (el != null && el.getID() != "") { element = el.serialize(); break; diff --git a/lib/models/workspace.dart b/lib/models/workspace.dart index 755ebd4..b0b08d6 100644 --- a/lib/models/workspace.dart +++ b/lib/models/workspace.dart @@ -1,7 +1,10 @@ -import 'package:flutter_flow_chart/flutter_flow_chart.dart'; import 'package:oc_front/models/abstract.dart'; +import 'package:oc_front/models/resources/compute.dart'; +import 'package:oc_front/models/resources/data.dart'; +import 'package:oc_front/models/resources/processing.dart'; +import 'package:oc_front/models/resources/storage.dart'; +import 'package:oc_front/models/resources/workflow.dart'; import 'package:oc_front/models/response.dart'; -import 'package:oc_front/models/search.dart'; class Workspace extends SerializerDeserializer implements ShallowData { String? id; @@ -44,13 +47,15 @@ class Workspace extends SerializerDeserializer implements ShallowData workflows: json.containsKey("workflow_resources") ? fromListJson(json["workflow_resources"], WorkflowItem()) : [] ); } - @override Map serialize() => { - "id": id, - "name": name, - "processings": processings.map((e) => e.id).toList(), - "storages": storages.map((e) => e.id).toList(), - "computes": computes.map((e) => e.id).toList(), - "datas": datas.map((e) => e.id).toList(), - "workflows": workflows.map((e) => e.id).toList(), - }; + @override Map serialize() { + return { + "id": id, + "name": name, + "processings": processings.map((e) => e.id).toList(), + "storages": storages.map((e) => e.id).toList(), + "computes": computes.map((e) => e.id).toList(), + "datas": datas.map((e) => e.id).toList(), + "workflows": workflows.map((e) => e.id).toList(), + }; + } } \ No newline at end of file diff --git a/lib/pages/abstract_page.dart b/lib/pages/abstract_page.dart index eefc6ea..214badb 100644 --- a/lib/pages/abstract_page.dart +++ b/lib/pages/abstract_page.dart @@ -6,4 +6,6 @@ abstract class AbstractFactory { Widget factory(GoRouterState state, List args); bool searchFill(); void search(BuildContext context, bool special); + String? getSearch(); + void back(BuildContext context); } \ No newline at end of file diff --git a/lib/pages/catalog.dart b/lib/pages/catalog.dart index 7c19372..646b511 100644 --- a/lib/pages/catalog.dart +++ b/lib/pages/catalog.dart @@ -1,26 +1,71 @@ +import 'package:oc_front/main.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:oc_front/widgets/catalog.dart'; +import 'package:localstorage/localstorage.dart'; +import 'package:oc_front/pages/abstract_page.dart'; +import 'package:oc_front/models/resources/resources.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/main.dart'; -import 'package:oc_front/models/search.dart'; -import 'package:oc_front/widgets/catalog.dart'; -import 'package:oc_front/pages/abstract_page.dart'; + class CatalogFactory implements AbstractFactory { @override GlobalKey getKey() { return key; } static GlobalKey key = GlobalKey(); - @override bool searchFill() { return key.currentState?.widget.items.isEmpty ?? true; } - @override Widget factory(GoRouterState state, List args) { return CatalogPageWidget(); } - @override void search(BuildContext context, bool special) { - if (special) { return; } - CatalogFactory.key.currentState?.widget.search.search(context, [ SearchConstants.get()! ], {}).then((value) { - if (value.data == null) { return; } - key.currentState?.widget.items = [ ...value.data!.workflows, - ...value.data!.processings, ...value.data!.datas, ...value.data!.storages, ...value.data!.computes,]; + @override void back(BuildContext context) { + var s = (localStorage.getItem("search") ?? ""); + if (s != "") { + localStorage.setItem("search", s.split(",").sublist(1).join(",")); + SearchConstants.set(s.split(",").sublist(1).join(",")); + if ((localStorage.getItem("search") ?? "") == "") { + SearchConstants.remove(); + key.currentState?.widget.isSearch = true; + key.currentState?.widget.items = []; + HeaderConstants.headerKey.currentState?.setState(() {}); + HeaderConstants.headerWidget?.setState(() {}); + CatalogFactory.key.currentState?.setState(() {}); + } else { + CatalogFactory().search(context, false); + } + } else { + SearchConstants.remove(); + key.currentState?.widget.isSearch = true; + key.currentState?.widget.items = []; HeaderConstants.headerKey.currentState?.setState(() {}); HeaderConstants.headerWidget?.setState(() {}); - CatalogFactory.key.currentState?.setState(() {}); // ignore: invalid_use_of_protected_member + CatalogFactory.key.currentState?.setState(() {}); + } + } + @override bool searchFill() { return (key.currentState?.widget.items.isEmpty ?? true) && (key.currentState?.widget.isSearch ?? true); } + @override Widget factory(GoRouterState state, List args) { return CatalogPageWidget(); } + @override String? getSearch() { + if ((localStorage.getItem("search") ?? "") == "") { return null; } + return localStorage.getItem("search")!.split(",")[0]; + } + @override void search(BuildContext context, bool special) { + if (special) { return; } // T + key.currentState?.widget.isSearch = true; + var s = (localStorage.getItem("search") ?? ""); + if (s != "") { + if (SearchConstants.get() == null) { + localStorage.setItem("search", s); + } else if (s.split(",")[0] != SearchConstants.get()) { + localStorage.setItem("search", "${SearchConstants.get()!},$s"); + } + } else if ((SearchConstants.get() ?? "") == "") { return; + } else { localStorage.setItem("search", SearchConstants.get()!); } + CatalogFactory.key.currentState?.widget.search.search(context, [ + localStorage.getItem("search")!.split(",")[0] ], {}).then((value) { + if (value.data == null) { + key.currentState?.widget.items = []; + } else { + key.currentState?.widget.isSearch = false; + key.currentState?.widget.items = [ ...value.data!.workflows, + ...value.data!.processings, ...value.data!.datas, ...value.data!.storages, ...value.data!.computes,]; + } + HeaderConstants.headerKey.currentState?.setState(() {}); + HeaderConstants.headerWidget?.setState(() {}); + CatalogFactory.key.currentState?.setState(() {}); // ignore: invalid_use_of_protected_member }); } } @@ -28,6 +73,7 @@ class CatalogFactory implements AbstractFactory { // ignore: must_be_immutable class CatalogPageWidget extends StatefulWidget { double? itemWidth; + bool isSearch = true; List items = []; final ResourceService search = ResourceService(); CatalogPageWidget ({ @@ -37,7 +83,16 @@ class CatalogPageWidget extends StatefulWidget { } class CatalogPageWidgetState extends State { @override Widget build(BuildContext context) { - if (widget.items.isEmpty) { return Container(); } + if (widget.items.isEmpty) { + if (widget.isSearch) { return Container(); } + return Container( + width: getMainWidth(context), + height: getMainHeight(context) - 50, + color: Colors.grey.shade300, + child: const Center(child: Text("NO RESOURCES FOUND", + style: TextStyle(fontSize: 30, color: Colors.grey)) + ), + ); } return Column( children : [ SizedBox( width: getMainWidth(context), height: getMainHeight(context) - 50, @@ -46,35 +101,3 @@ class CatalogPageWidgetState extends State { ); } } -/* - - PermsService.getPerm(Perms.WORKSPACE_SHARE) ? ShallowDropdownInputWidget( - iconLoad: Icons.share_rounded, - tooltipLoad: 'share', - tooltipRemove: 'unshare', - color: Colors.white, - filled: const Color.fromRGBO(38, 166, 154, 1), - hintColor: midColor, - type: CollaborativeAreaType.workspace, - all: () async => CollaborativeAreaLocal.workspaces.values.map( - (e) => Shallow(id: e.id ?? "", name: e.name ?? "") ).toList(), - current: WorkspaceLocal.workspaces[WorkspaceLocal.current]?.shared, - width: (getMainWidth(context) / 3), - canLoad: (String? change) => CollaborativeAreaLocal.workspaces[change] == null - || !CollaborativeAreaLocal.workspaces[change]!.workspaces.map( - (e) => e.id ).contains(WorkspaceLocal.current), - canRemove: (String? change) => CollaborativeAreaLocal.workspaces[change] == null - || CollaborativeAreaLocal.workspaces[change]!.workspaces.map( - (e) => e.id ).contains(WorkspaceLocal.current), - load: (String val) async { - await SharedService().addWorkspace(context, val, WorkspaceLocal.current ?? ""); - // ignore: use_build_context_synchronously - CollaborativeAreaLocal.init(context, false); - }, - remove: (String val) async { - await SharedService().removeWorkspace(context, val, WorkspaceLocal.current ?? ""); - // ignore: use_build_context_synchronously - CollaborativeAreaLocal.init(context, false); - }) : Container(width: (getMainWidth(context) / 3), height: 50, - color: const Color.fromRGBO(38, 166, 154, 1)), -*/ \ No newline at end of file diff --git a/lib/pages/catalog_item.dart b/lib/pages/catalog_item.dart index acaf8c6..cf6b1a3 100644 --- a/lib/pages/catalog_item.dart +++ b/lib/pages/catalog_item.dart @@ -1,8 +1,11 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:localstorage/localstorage.dart'; import 'package:oc_front/core/models/workspace_local.dart'; +import 'package:oc_front/core/sections/header/header.dart'; +import 'package:oc_front/core/services/router.dart'; import 'package:oc_front/main.dart'; -import 'package:oc_front/models/search.dart'; +import 'package:oc_front/models/resources/resources.dart'; import 'package:oc_front/pages/abstract_page.dart'; import 'package:oc_front/pages/catalog.dart'; import 'package:oc_front/widgets/items/item.dart'; @@ -11,6 +14,13 @@ import 'package:oc_front/widgets/items/item_row.dart'; class CatalogItemFactory implements AbstractFactory { static GlobalKey key = GlobalKey(); @override GlobalKey getKey() { return key; } + @override void back(BuildContext context) { + search(context, false); + } + @override String? getSearch() { + if ((localStorage.getItem("search") ?? "") == "") { return null; } + return localStorage.getItem("search")!.split(",")[0]; + } @override bool searchFill() { return false; } @override Widget factory(GoRouterState state, List args) { var id = state.pathParameters[args.first]; @@ -19,13 +29,22 @@ class CatalogItemFactory implements AbstractFactory { return CatalogItemPageWidget(item : item!); } catch (e) { var item = WorkspaceLocal.getItem(id ?? "", false); - if (item != null) { return CatalogItemPageWidget(item : item as AbstractItem); } + if (item != null) { return CatalogItemPageWidget(item : item); } return Container(); } } - @override void search(BuildContext context, bool special) { } + @override void search(BuildContext context, bool special) { + if (special) { return; } // T + var s = SearchConstants.get(); + AppRouter.catalog.go(context, {}); + Future.delayed(Duration(milliseconds: 10), () { + SearchConstants.set(s); + CatalogFactory().search(context, false); + }); + } } +// ignore: must_be_immutable class CatalogItemPageWidget extends StatefulWidget { AbstractItem item; CatalogItemPageWidget ({ required this.item }) : super(key: CatalogItemFactory.key); @@ -35,7 +54,7 @@ class CatalogItemPageWidgetState extends State { @override Widget build(BuildContext context) { return Column( children: [ ItemRowWidget(contextWidth: getMainWidth(context), item: widget.item, readOnly: true,), - ItemWidget(item: widget.item,), + ItemWidget(item: widget.item), ]); } } \ No newline at end of file diff --git a/lib/pages/datacenter.dart b/lib/pages/datacenter.dart index 7d12c27..421aaa7 100644 --- a/lib/pages/datacenter.dart +++ b/lib/pages/datacenter.dart @@ -4,18 +4,20 @@ import 'package:go_router/go_router.dart'; import 'package:oc_front/core/services/specialized_services/booking_service.dart'; import 'package:oc_front/main.dart'; import 'package:intl/intl.dart' as intl; -import 'package:oc_front/models/workflow.dart'; import 'package:oc_front/pages/abstract_page.dart'; import 'package:oc_front/widgets/sheduler_items/schedule.dart'; class DatacenterFactory implements AbstractFactory { @override GlobalKey getKey() { return key; } + @override String? getSearch() { return ""; } + @override void back(BuildContext context) { } static GlobalKey key = GlobalKey(); @override bool searchFill() { return false; } @override Widget factory(GoRouterState state, List args) { return ComputePageWidget(); } @override void search(BuildContext context, bool special) { } } +// ignore: must_be_immutable class ComputePageWidget extends StatefulWidget { bool isList = true; DateTime start = DateTime.now(); @@ -169,7 +171,7 @@ class ComputePageWidgetState extends State { ) ])) ), - ScheduleWidget( service: widget._service, key: k, start: widget.start, end : widget.end, isList: widget.isList, isBox: false) + ScheduleWidget( key: k, start: widget.start, end : widget.end, isList: widget.isList, isBox: false) ]); } } \ No newline at end of file diff --git a/lib/pages/map.dart b/lib/pages/map.dart index 0112b9a..453dcf6 100644 --- a/lib/pages/map.dart +++ b/lib/pages/map.dart @@ -1,18 +1,32 @@ +import 'dart:math'; + import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:go_router/go_router.dart'; import 'package:latlong2/latlong.dart'; import 'package:flutter_map/flutter_map.dart'; +import 'package:oc_front/core/services/specialized_services/datacenter_service.dart'; +import 'package:oc_front/main.dart'; +import 'package:oc_front/models/resources/compute.dart'; +import 'package:oc_front/models/resources/resources.dart'; +import 'package:oc_front/models/resources/storage.dart'; import 'package:oc_front/pages/abstract_page.dart'; +import 'package:oc_front/widgets/items/item_row.dart'; + class MapFactory implements AbstractFactory { @override GlobalKey getKey() { return key; } + @override String? getSearch() { return ""; } + @override void back(BuildContext context) { } static GlobalKey key = GlobalKey(); @override bool searchFill() { return false; } @override Widget factory(GoRouterState state, List args) { return MapPageWidget(); } @override void search(BuildContext context, bool special) { } } - +double menuSize = 0; class MapPageWidget extends StatefulWidget { + bool isShowed = false; + final DatacenterService _service = DatacenterService(); MapPageWidget(): super(key: MapFactory.key); @override MapPageWidgetState createState() => MapPageWidgetState(); static void search(BuildContext context) { } @@ -22,26 +36,193 @@ class MapPageWidgetState extends State { double currentZoom = 2.0; LatLng currentCenter = const LatLng(51.5, -0.09); static final MapController _mapController = MapController(); - void _zoom() { - currentZoom = currentZoom - 1; - _mapController.move(currentCenter, currentZoom); -} + bool selected = true; @override Widget build(BuildContext context) { - return Expanded( - child : FlutterMap( - mapController: _mapController, - options: MapOptions( - initialCenter: currentCenter, - initialZoom: currentZoom, + return FutureBuilder(future: widget._service.all(context), builder: (BuildContext context, AsyncSnapshot snapshot) { + Map> coordinates = {}; + List markerCoordinates = []; + if (snapshot.data != null&& snapshot.data!.data != null && snapshot.data!.data!.values.isNotEmpty) { + for (var element in snapshot.data!.data!.values) { + if (element["type"] == "storage") { + StorageItem resource = StorageItem().deserialize(element); + var instance = resource.getSelectedInstance(); + if (instance == null || instance.location == null) { continue; } + if (coordinates[resource.topic] == null) { coordinates[resource.topic] = {}; } + coordinates[resource.topic]![resource] = LatLng(instance.location!.latitude ?? 0, instance.location!.longitude ?? 0); + } else if (element["type"] == "compute") { + ComputeItem resource = ComputeItem().deserialize(element); + var instance = resource.getSelectedInstance(); + if (instance == null || instance.location == null) { continue; } + if (coordinates[resource.topic] == null) { coordinates[resource.topic] = {}; } + var lr = Random().nextInt(max(1, 100)) / 10000; + var lfr = Random().nextInt(max(1, 100)) / 10000; + coordinates[resource.topic]![resource] = LatLng((instance.location!.latitude ?? 0) + lr, (instance.location!.longitude ?? 0) + lfr); + } + } + for (var topic in coordinates.keys) { + for (var coord in coordinates[topic]!.keys) { + markerCoordinates.add(Marker( + width: 25, + height: 30, + point: coordinates[topic]![coord]!, + child: HoverMenu( width: 110, title: Container( alignment: Alignment.center, + constraints: BoxConstraints( maxHeight: 100, maxWidth: 100 ), + child: Icon(FontAwesomeIcons.locationDot, + shadows: [Shadow(color: Color.fromRGBO(0, 0, 0, 1), blurRadius: 10.0)], + color: getColor(topic)) ), + items: [ Container(color: Colors.white, + child: ItemRowWidget(low: true, contextWidth: 290, item: coord)) ] + ), + )); + } + } + Rect rect = Rect.fromCenter( center: MediaQuery.of(context).size.center(Offset.zero), + width: selected ? menuSize : 0, height: (getMainHeight(context) - 50) > 0 ? (getMainHeight(context) - 50) : 0); + return Expanded( + child : FlutterMap( + mapController: _mapController, + options: MapOptions( + initialCenter: currentCenter, + initialZoom: currentZoom, + ), + children: [ + TileLayer( + urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', + userAgentPackageName: 'dev.fleaflet.flutter_map.example', + ), + MarkerLayer( + markers: markerCoordinates, + ), + ], + ), + ); + } else { + return const CircularProgressIndicator(); + } + } + ); + } +} + +class HoverMenuController { + HoverMenuState? currentState; + + void hideSubMenu() { + currentState?.hideSubMenu(); + } +} + +class HoverMenu extends StatefulWidget { + final Widget title; + final double? width; + final List items; + final HoverMenuController? controller; + bool isHovered = false; + + + HoverMenu({ + Key? key, + required this.title, + this.items = const [], + this.width, + this.controller, + }) : super(key: key); + + @override + HoverMenuState createState() => HoverMenuState(); +} + +class HoverMenuState extends State { + OverlayEntry? _overlayEntry; + final _focusNode = FocusNode(); + + @override + void initState() { + super.initState(); + _focusNode.addListener(_onFocusChanged); + + if (widget.controller != null) { + widget.controller?.currentState = this; + } + } + + @override + void dispose() { + _focusNode.dispose(); + super.dispose(); + } + + void _onFocusChanged() { + if (_focusNode.hasFocus) { + _overlayEntry = _createOverlayEntry(); + Overlay.of(context).insert(_overlayEntry!); + } else { + _overlayEntry?.remove(); + _removeOverlay(); + } + } + + void _removeOverlay() { + widget.isHovered = false; + } + + void hideSubMenu() { + _focusNode.unfocus(); + } + + @override + Widget build(BuildContext context) { + return TextButton( + style: TextButton.styleFrom( + elevation: 0.0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0)), + splashFactory: NoSplash.splashFactory, + padding: EdgeInsets.zero, + foregroundColor: Colors.transparent, + surfaceTintColor: Colors.transparent, + backgroundColor: Colors.transparent, + shadowColor: Colors.transparent, ), - children: [ - TileLayer( - urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', - userAgentPackageName: 'dev.fleaflet.flutter_map.example', - ) - ], - ) + focusNode: _focusNode, + onHover: (isHovered) { + if (isHovered && !widget.isHovered) { + _focusNode.requestFocus(); + isHovered = true; + } else { + _focusNode.unfocus(); + widget.isHovered = false; + } + }, + onPressed: () {}, + child: widget.title, + ); + } + + OverlayEntry _createOverlayEntry() { + final renderBox = context.findRenderObject() as RenderBox; + final size = renderBox.size; + final offset = renderBox.localToGlobal(Offset.zero); + + return OverlayEntry( + maintainState: true, + builder: (context) => Positioned( + left: offset.dx - 300, + top: offset.dy + size.height, + width: 300, + child: TextButton( + style: TextButton.styleFrom( + padding: EdgeInsets.zero, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0)), + splashFactory: NoSplash.splashFactory, + backgroundColor: Colors.transparent, + ), + onPressed: () {}, + child: ListView( + padding: EdgeInsets.zero, + shrinkWrap: true, + children: widget.items)), + ), ); } } \ No newline at end of file diff --git a/lib/pages/scheduler.dart b/lib/pages/scheduler.dart index 7c1b8ae..6bd816e 100644 --- a/lib/pages/scheduler.dart +++ b/lib/pages/scheduler.dart @@ -9,12 +9,15 @@ import 'package:oc_front/widgets/sheduler_items/schedule.dart'; class SchedulerFactory implements AbstractFactory { @override GlobalKey getKey() { return key; } + @override String? getSearch() { return ""; } + @override void back(BuildContext context) { } static GlobalKey key = GlobalKey(); @override bool searchFill() { return false; } @override Widget factory(GoRouterState state, List args) { return SchedulerPageWidget(); } @override void search(BuildContext context, bool special) { } } +// ignore: must_be_immutable class SchedulerPageWidget extends StatefulWidget { bool isList = true; DateTime start = DateTime.now(); @@ -164,7 +167,7 @@ class SchedulerPageWidgetState extends State { ) ])) ), - ScheduleWidget( service: widget._service, key: k, start: widget.start, end : widget.end, isList: widget.isList, ) + ScheduleWidget( key: k, start: widget.start, end : widget.end, isList: widget.isList, ) ]); } } diff --git a/lib/pages/shared.dart b/lib/pages/shared.dart index 1a4e074..7a4e830 100644 --- a/lib/pages/shared.dart +++ b/lib/pages/shared.dart @@ -1,33 +1,32 @@ import 'dart:async'; -import 'dart:math'; - +import 'package:intl/intl.dart'; +import 'package:oc_front/main.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import 'package:intl/intl.dart'; -import 'package:oc_front/core/models/shared_workspace_local.dart'; +import 'package:oc_front/models/shared.dart'; +import 'package:oc_front/models/workflow.dart'; +import 'package:oc_front/widgets/catalog.dart'; +import 'package:oc_front/models/response.dart'; +import 'package:oc_front/pages/abstract_page.dart'; +import 'package:oc_front/models/resources/resources.dart'; import 'package:oc_front/core/models/workspace_local.dart'; import 'package:oc_front/core/sections/header/header.dart'; import 'package:oc_front/core/services/perms_service.dart'; -import 'package:oc_front/core/services/router.dart'; +import 'package:oc_front/widgets/items/shallow_item_row.dart'; +import 'package:oc_front/widgets/dialog/shallow_creation.dart'; +import 'package:oc_front/widgets/inputs/shallow_text_input.dart'; +import 'package:oc_front/core/models/shared_workspace_local.dart'; +import 'package:oc_front/widgets/inputs/shallow_dropdown_input.dart'; import 'package:oc_front/core/services/specialized_services/peer_service.dart'; import 'package:oc_front/core/services/specialized_services/shared_service.dart'; import 'package:oc_front/core/services/specialized_services/workflow_service.dart'; -import 'package:oc_front/main.dart'; -import 'package:oc_front/models/response.dart'; -import 'package:oc_front/models/search.dart'; -import 'package:oc_front/models/shared.dart'; -import 'package:oc_front/models/workflow.dart'; -import 'package:oc_front/pages/abstract_page.dart'; -import 'package:oc_front/widgets/catalog.dart'; -import 'package:oc_front/widgets/dialog/shallow_creation.dart'; -import 'package:oc_front/widgets/inputs/shallow_text_input.dart'; -import 'package:oc_front/widgets/items/shallow_item_row.dart'; -import 'package:oc_front/widgets/inputs/shallow_dropdown_input.dart'; enum CollaborativeAreaType { global, collaborative_area, workspace, workflow, peer, resource } class SharedFactory implements AbstractFactory { @override GlobalKey getKey() { return key; } + @override String? getSearch() { return ""; } + @override void back(BuildContext context) { } static GlobalKey key = GlobalKey(); @override bool searchFill() { return false; } @override Widget factory(GoRouterState state, List args) { return SharedPageWidget(); } @@ -36,6 +35,7 @@ class SharedFactory implements AbstractFactory { class SharedPageWidget extends StatefulWidget { CollaborativeAreaType type = CollaborativeAreaType.global; + bool showDialog = false; SharedPageWidget(): super(key: SharedFactory.key); @override SharedPageWidgetState createState() => SharedPageWidgetState(); static void search(BuildContext context) { } @@ -56,7 +56,6 @@ class SharedPageWidgetState extends State { child : Icon(icon, color: widget.type == workspaceType ? Colors.white : Colors.white, size: 20)))); } - @override Widget build(BuildContext context) { GlobalKey key = GlobalKey(); if (CollaborativeAreaLocal.current == null) { @@ -64,52 +63,59 @@ class SharedPageWidgetState extends State { HeaderConstants.setTitle("Choose a Collaborative Area"); HeaderConstants.setDescription("select a shared workspace to continue"); }); - Future.delayed( const Duration(milliseconds: 100), () { - showDialog( - barrierDismissible: false, - context: context, builder: (BuildContext ctx) => AlertDialog( - titlePadding: EdgeInsets.zero, - insetPadding: EdgeInsets.zero, - backgroundColor: Colors.white, - shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0)), - title: ShallowCreationDialogWidget( - formKey: key, - canClose: () => CollaborativeAreaLocal.current != null, - context: context, - load: (p0) async { - CollaborativeAreaLocal.current = p0; - HeaderConstants.setTitle("Collaborative Area <${CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current]?.name ?? ""}>"); - HeaderConstants.setDescription(CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current]?.description ?? ""); - Future.delayed(const Duration(seconds: 1), () => SharedFactory.key.currentState?.setState(() {})); - }, - form: [ - ShallowTextInputWidget( - change :(p0) => key.currentState?.setState(() {}), - canLoad: (po) => po != null && po.isNotEmpty, - type: CollaborativeAreaType.collaborative_area, - width: getMainWidth(context) <= 540 ? getMainWidth(context) - 140 : 400, - attr: "description", - color: Colors.black, - hintColor: Colors.grey, - hint: "enter collaborative area description...", - filled: midColor, - ) - ], - create: PermsService.getPerm(Perms.COLLABORATIVE_AREA_CREATE) ? (p0) async => await SharedService().post(context, p0, {}).then((value) { - if (value.data != null) { - CollaborativeAreaLocal.current = value.data!.id; - } - CollaborativeAreaLocal.init(context, true); + if (!widget.showDialog) { + Future.delayed( const Duration(milliseconds: 100), () { + widget.showDialog = true; + showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext ctx) => AlertDialog( + titlePadding: EdgeInsets.zero, + insetPadding: EdgeInsets.zero, + backgroundColor: Colors.white, + shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0)), + title: ShallowCreationDialogWidget( + formKey: key, + canClose: () => CollaborativeAreaLocal.current != null, + context: context, + load: (p0) async { + CollaborativeAreaLocal.current = p0; + HeaderConstants.setTitle("Collaborative Area <${CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current]?.name ?? ""}>"); + HeaderConstants.setDescription(CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current]?.description ?? ""); + Future.delayed(const Duration(seconds: 1), () => SharedFactory.key.currentState?.setState(() { widget.showDialog = false; })); + }, + form: [ + ShallowTextInputWidget( + change :(p0) => key.currentState?.setState(() {}), + canLoad: (po) => po != null && po.isNotEmpty, + type: CollaborativeAreaType.collaborative_area, + width: getMainWidth(context) <= 540 ? getMainWidth(context) - 140 : 400, + attr: "description", + color: Colors.black, + hintColor: Colors.grey, + hint: "enter collaborative area description...", + filled: midColor, + ) + ], + create: PermsService.getPerm(Perms.COLLABORATIVE_AREA_CREATE) ? (p0) async => await SharedService().post(context, p0, {}).then((value) { + if (value.data != null) { + CollaborativeAreaLocal.current = value.data!.id; + } + CollaborativeAreaLocal.init(context, true); - HeaderConstants.setTitle("Collaborative Area <${CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current]?.name ?? ""}>"); - HeaderConstants.setDescription(CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current]?.description ?? ""); - Future.delayed(const Duration(seconds: 1), () => SharedFactory.key.currentState?.setState(() {})); - }) : null, - type: CollaborativeAreaType.collaborative_area, - all: () async => CollaborativeAreaLocal.workspaces.values.map( - (e) => Shallow(id: e.id ?? "", name: e.name ?? "") ).toList(), - ))); - }); + HeaderConstants.setTitle("Collaborative Area <${CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current]?.name ?? ""}>"); + HeaderConstants.setDescription(CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current]?.description ?? ""); + Future.delayed(const Duration(seconds: 1), () => SharedFactory.key.currentState?.setState(() { widget.showDialog = false; })); + }) : null, + type: CollaborativeAreaType.collaborative_area, + all: () async { + await CollaborativeAreaLocal.init(context, true); + return CollaborativeAreaLocal.workspaces.values.map( + (e) => Shallow(id: e.id ?? "", name: e.name ?? "") ).toList(); + } + ))); + }); + } } else { Future.delayed( const Duration(milliseconds: 100), () { HeaderConstants.setTitle("Collaborative Area <${CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current]?.name ?? ""}>"); @@ -119,107 +125,7 @@ class SharedPageWidgetState extends State { Widget w = WorkspaceSharedPageWidget(type: widget.type); List addMenu = []; CollaborativeArea? current = CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current ?? ""]; - if (widget.type == CollaborativeAreaType.workspace) { - addMenu.add( Row( mainAxisAlignment: MainAxisAlignment.end, - children : [ Container( padding: EdgeInsets.only(left: 20), decoration: BoxDecoration( - border: Border(left: BorderSide(color: Colors.white)) - ), child: ShallowDropdownInputWidget( - tooltipLoad: "share", - tooltipRemove: "unshare", - iconLoad: Icons.share, - type: widget.type, - filled: lightColor, - hintColor: midColor, - color: Colors.white, - prefixIcon: Icon(Icons.shopping_cart, color: Colors.white), - current: WorkspaceLocal.current, - all: () async => WorkspaceLocal.getWorkspacesShallow(), - width: getMainWidth(context) / 3, - canLoad: (String? change) => current == null || !current.workspaces.map( (e) => e.id ).contains(change), - canRemove: (String? change) => current == null || current.workspaces.map( (e) => e.id ).contains(change), - load: PermsService.getPerm(Perms.WORKSPACE_SHARE) ? (String val) async { - await service.addWorkspace(context, CollaborativeAreaLocal.current ?? "", val); - await CollaborativeAreaLocal.init(context, false); - setState(() {}); - } : null, - remove: PermsService.getPerm(Perms.WORKSPACE_UNSHARE) ? (String val) async { - await service.removeWorkspace(context, CollaborativeAreaLocal.current ?? "", val); - await CollaborativeAreaLocal.init(context, false); - setState(() {}); - } : null)) - ])); - } - if (widget.type == CollaborativeAreaType.workflow) { - addMenu.add( Row( mainAxisAlignment: MainAxisAlignment.end, - children : [ Container( padding: EdgeInsets.only(left: 20), decoration: BoxDecoration( - border: Border(left: BorderSide(color: Colors.white)) - ), child: ShallowDropdownInputWidget( - tooltipLoad: "share", - tooltipRemove: "unshare", - iconLoad: Icons.share, - filled: lightColor, - hintColor: midColor, - color: Colors.white, - type: widget.type, all: () async { - List shals = []; - await WorflowService().all(context).then((value) { - if (value.data != null) { - shals = value.data!.values.map((e) => Shallow(id: e["id"], name: e["name"])).toList(); - } - }); - return shals; - }, - width: getMainWidth(context) / 3, - canLoad: (String? change) => current == null || !current.workflows.map( (e) => e.id ).contains(change), - canRemove: (String? change) => current == null || current.workflows.map( (e) => e.id ).contains(change), - load: PermsService.getPerm(Perms.WORKFLOW_SHARE) ? (String change) async { - await service.addWorkflow(context, CollaborativeAreaLocal.current ?? "", change); - await CollaborativeAreaLocal.init(context, false); - setState(() {}); - } : null, - remove: PermsService.getPerm(Perms.WORKFLOW_UNSHARE) ? (String change) async { - await service.removeWorkflow(context, CollaborativeAreaLocal.current ?? "", change); - await CollaborativeAreaLocal.init(context, false); - setState(() {}); - } : null)) - ])); - } - if (widget.type == CollaborativeAreaType.peer) { - addMenu.add( Row( mainAxisAlignment: MainAxisAlignment.end, - children : [ - Container( padding: EdgeInsets.only(left: 20), decoration: BoxDecoration( - border: Border(left: BorderSide(color: Colors.white)) - ), child: ShallowDropdownInputWidget( - tooltipLoad: "add", - iconLoad: Icons.add, - filled: lightColor, - hintColor: midColor, - color: Colors.white, - type: widget.type, all: () async { - List shals = []; - await PeerService().all(context).then((value) { - if (value.data != null) { - shals = value.data!.values.map((e) => Shallow(id: e["id"], name: e["name"])).toList(); - } - }); - return shals; - }, - width: getMainWidth(context) / 3, - canLoad: (String? change) => current == null || !current.peers.map( (e) => e.id ).contains(change), - canRemove: (String? change) => current == null || current.peers.map( (e) => e.id ).contains(change), - load: PermsService.getPerm(Perms.PEER_SHARE) ? (String change) async { - await service.addPeer(context, CollaborativeAreaLocal.current ?? "", change); - await CollaborativeAreaLocal.init(context, false); - setState(() {}); - } : null, - remove: PermsService.getPerm(Perms.PEER_UNSHARE) ? (String change) async { - await service.removePeer(context, CollaborativeAreaLocal.current ?? "", change); - await CollaborativeAreaLocal.init(context, false); - setState(() {}); - } : null)) - ])); - } - print(w); + addMenu.add(getDropdown(widget.type, current, this, context, false)); return Column( children: [ Container( height: 50, @@ -318,9 +224,10 @@ class WorkspaceSharedPageWidgetState extends State { List badges = []; List bbadges = []; badges.add(Container( margin: const EdgeInsets.only(left: 5), padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5), - decoration: BoxDecoration( borderRadius: BorderRadius.circular(4), - color: isData(w.topic) ? Colors.blue : isComputing(w.topic) ? Colors.green : - isCompute(w.topic) ? Colors.orange : isStorage(w.topic) ? redColor : Colors.grey ), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: getColor(w.topic) + ), child:Text(w.topic, style: TextStyle( color: Colors.white, fontSize: 11) ))); bbadges.add(Container( margin: const EdgeInsets.only(left: 5), decoration: BoxDecoration( color: Colors.grey, borderRadius: BorderRadius.circular(4) ), @@ -337,10 +244,16 @@ class WorkspaceSharedPageWidgetState extends State { List getCardItems(List data) { List items = []; - for (var w in data) { + List neoData = []; + for (var d in data) { + try { neoData.firstWhere( (e) => e.getID() == d.getID()); + } catch (e) { neoData.add(d); } + } + for (var w in neoData) { List badges = []; - if (w is Peer && w.getID( - ) == CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current ?? ""]?.rule?.creator) { + if (w is Peer && ( + w.getID() != CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current ?? ""]?.rule?.creator + || w.getID() != CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current ?? ""]?.creatorID)) { badges.add(Padding( padding: const EdgeInsets.only(left: 5), child: Icon(Icons.star, color: Colors.orange.shade300 ))); } else if (widget.type == CollaborativeAreaType.workspace) { badges.add(Container( margin: const EdgeInsets.only(left: 5), padding: EdgeInsets.all(5), color: Colors.grey.shade200, @@ -349,11 +262,13 @@ class WorkspaceSharedPageWidgetState extends State { items.add(ShallowItemRowWidget( color: Colors.grey.shade200, item: w, badges: badges, - delete: w is Peer && PermsService.getPerm(Perms.PEER_UNSHARE) && w.getID() != CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current ?? ""]?.rule?.creator ? (String? change) async { + delete: w is Peer ? (PermsService.getPerm(Perms.PEER_UNSHARE) && ( + w.getID() != CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current ?? ""]?.rule?.creator + && w.getID() != CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current ?? ""]?.creatorID) ? (String? change) async { await SharedService().removePeer(context, CollaborativeAreaLocal.current ?? "", change ?? ""); await CollaborativeAreaLocal.init(context, false); setState(() {}); - } : (w is Workflow && PermsService.getPerm(Perms.WORKSPACE_UNSHARE)) ? (String? change) async { + } : null) : (w is Workflow && PermsService.getPerm(Perms.WORKSPACE_UNSHARE)) ? (String? change) async { await SharedService().removeWorkflow(context, CollaborativeAreaLocal.current ?? "", change ?? ""); await CollaborativeAreaLocal.init(context, false); setState(() {}); @@ -381,7 +296,7 @@ class WorkspaceSharedPageWidgetState extends State { Peer? creator; SharedService service = SharedService(); try { creator = space.peers.firstWhere( (e) => (space.rule?.creator ?? "") == e.id); - } catch (e) { } + } catch (e) { /**/ } Map> datas = {}; for (var w in space.workspaces) { datas[w.getName()] = [ @@ -406,9 +321,9 @@ class WorkspaceSharedPageWidgetState extends State { padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 50), child: Text(space.description ?? "", style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w400, color: Colors.grey)) - ), // TODO - Text("COLLABORATIVE AREA ACCESS RULES", textAlign: TextAlign.start, - style: TextStyle(color: darkColor, fontSize: 20, fontWeight: FontWeight.bold), overflow: TextOverflow.clip), + ), + Padding( padding: EdgeInsets.only(left: 30), child: Text("COLLABORATIVE AREA ACCESS RULES", textAlign: TextAlign.start, + style: TextStyle(color: darkColor, fontSize: 20, fontWeight: FontWeight.bold), overflow: TextOverflow.clip)), Container( width: getMainWidth(context) - 50, margin: EdgeInsets.symmetric(vertical: 20), @@ -427,39 +342,14 @@ class WorkspaceSharedPageWidgetState extends State { ), Row( children: [ - Text("COLLABORATIVE AREA PEERS", textAlign: TextAlign.start, - style: TextStyle(color: darkColor, fontSize: 20, fontWeight: FontWeight.bold), overflow: TextOverflow.clip), + Padding( padding: EdgeInsets.only(left: 30), child: Text("COLLABORATIVE AREA PEERS", textAlign: TextAlign.start, + style: TextStyle(color: darkColor, fontSize: 20, fontWeight: FontWeight.bold), overflow: TextOverflow.clip)), PermsService.getPerm(Perms.PEER_SHARE) ? Container( margin: EdgeInsets.only(left: 20), padding: EdgeInsets.only(left: 15), decoration: BoxDecoration( border: Border(left: BorderSide(color: Colors.grey)) - ), child:ShallowDropdownInputWidget( - tooltipLoad: "add peer", - hint: "add peer", - iconLoad: Icons.add, - type: widget.type, - filled: midColor, - hintColor: Colors.grey, - color: Colors.black, - prefixIcon: Icon(Icons.person, color: Colors.grey), - all: () async { - List shals = []; - await PeerService().all(context).then((value) { - if (value.data != null) { - shals = value.data!.values.map((e) => Shallow(id: e["id"], name: e["name"])).where( (e) => !space.peers.map( (e) => e.id ).contains(e.id)).toList(); - } - setState(() {}); - }); - return shals; - }, - width: getMainWidth(context) / 3, - canLoad: (String? change) => true, - load: (String val) async { - await service.addPeer(context, CollaborativeAreaLocal.current ?? "", val); - await CollaborativeAreaLocal.init(context, false); - setState(() {}); - }, - ) ) : Container()]), + ), child: getDropdown(CollaborativeAreaType.peer, CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current], this, context, true) + ) : Container()]), Container( width: getMainWidth(context) - 50, margin: EdgeInsets.symmetric(vertical: 20), @@ -467,8 +357,8 @@ class WorkspaceSharedPageWidgetState extends State { padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 50), child: Wrap( alignment: WrapAlignment.center, children: getCardItems(space.peers)), ), - space.rules.isNotEmpty ? Text("RULES", textAlign: TextAlign.start, - style: TextStyle(color: darkColor, fontSize: 20, fontWeight: FontWeight.bold), overflow: TextOverflow.clip) : Container(), + space.rules.isNotEmpty ? Padding( padding: EdgeInsets.only(left: 30), child: Text("RULES", textAlign: TextAlign.start, + style: TextStyle(color: darkColor, fontSize: 20, fontWeight: FontWeight.bold), overflow: TextOverflow.clip)) : Container(), space.rules.isNotEmpty ? Container( width: getMainWidth(context) - 50, margin: EdgeInsets.symmetric(vertical: 20), @@ -483,30 +373,13 @@ class WorkspaceSharedPageWidgetState extends State { }).toList() ) ) : Container(), Row( children: [ - Text("WORKSPACES / RESOURCES", textAlign: TextAlign.start, - style: TextStyle(color: darkColor, fontSize: 20, fontWeight: FontWeight.bold), overflow: TextOverflow.clip), + Padding( padding: EdgeInsets.only(left: 30), child: Text("WORKSPACES / RESOURCES", textAlign: TextAlign.start, + style: TextStyle(color: darkColor, fontSize: 20, fontWeight: FontWeight.bold), overflow: TextOverflow.clip)), PermsService.getPerm(Perms.WORKSPACE_SHARE) ? Container( margin: EdgeInsets.only(left: 20), padding: EdgeInsets.only(left: 15), decoration: BoxDecoration( border: Border(left: BorderSide(color: Colors.grey)) - ), child: ShallowDropdownInputWidget( - tooltipLoad: "add workspace", - hint: "add workspace", - iconLoad: Icons.add, - type: widget.type, - filled: midColor, - hintColor: Colors.grey, - color: Colors.black, - prefixIcon: Icon(Icons.shopping_cart, color: Colors.grey), - all: () async => WorkspaceLocal.getWorkspacesShallow().where( (e) => !space.workspaces.map( (e) => e.id ).contains(e.id)).toList(), - width: getMainWidth(context) / 3, - canLoad: (String? change) => true, - load: (String val) async { - await service.addWorkspace(context, CollaborativeAreaLocal.current ?? "", val); - await CollaborativeAreaLocal.init(context, false); - setState(() {}); - }, - )) : Container() ]), + ), child: getDropdown(CollaborativeAreaType.workspace, CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current], this, context, true)) : Container() ]), Container( width: getMainWidth(context) - 50, margin: EdgeInsets.symmetric(vertical: 20), @@ -515,38 +388,13 @@ class WorkspaceSharedPageWidgetState extends State { child: Wrap( alignment: WrapAlignment.center, children: getCardWorkspaceItems(datas)) ), Row( children: [ - Text("WORKFLOWS", textAlign: TextAlign.start, - style: TextStyle(color: darkColor, fontSize: 20, fontWeight: FontWeight.bold), overflow: TextOverflow.clip), + Padding( padding: EdgeInsets.only(left: 30), child: Text("WORKFLOWS", textAlign: TextAlign.start, + style: TextStyle(color: darkColor, fontSize: 20, fontWeight: FontWeight.bold), overflow: TextOverflow.clip)), PermsService.getPerm(Perms.WORKFLOW_SHARE) ? Container( margin: EdgeInsets.only(left: 20), padding: EdgeInsets.only(left: 15), decoration: BoxDecoration( border: Border(left: BorderSide(color: Colors.grey)) - ), child:ShallowDropdownInputWidget( - tooltipLoad: "add workflow", - hint: "add workflow", - iconLoad: Icons.add, - type: widget.type, - filled: midColor, - hintColor: Colors.grey, - color: Colors.black, - prefixIcon: Icon(Icons.rebase_edit, color: Colors.grey), - all: () async { - List shals = []; - await WorflowService().all(context).then((value) { - if (value.data != null) { - shals = value.data!.values.map((e) => Shallow(id: e["id"], name: e["name"])).where( (e) => !space.workflows.map( (e) => e.id ).contains(e.id)).toList(); - } - }); - return shals; - }, - width: getMainWidth(context) / 3, - canLoad: (String? change) => true, - load: (String val) async { - await service.addWorkflow(context, CollaborativeAreaLocal.current ?? "", val); - await CollaborativeAreaLocal.init(context, false); - setState(() {}); - }, - )) : Container()]), + ), child: getDropdown(CollaborativeAreaType.workflow, CollaborativeAreaLocal.workspaces[CollaborativeAreaLocal.current], this, context, true)) : Container()]), Container( width: getMainWidth(context) - 50, margin: EdgeInsets.symmetric(vertical: 20), @@ -557,6 +405,7 @@ class WorkspaceSharedPageWidgetState extends State { ],) ); } + if (CollaborativeAreaLocal.current == null) { return Container( color: midColor, @@ -576,11 +425,14 @@ class WorkspaceSharedPageWidgetState extends State { data = space?.peers ?? []; } if (widget.type == CollaborativeAreaType.workspace) { - for (var w in data) { - if (widget.type == CollaborativeAreaType.workspace) { - if (WorkspaceLocal.workspaces[w.getID()] == null) { continue; } - items.add(WorkspaceSharedItemPageWidget(name: "Workspace <${WorkspaceLocal.workspaces[w.getID()]!.name}>", id: w.getID())); - } + List neoData = []; + for (var d in data) { + try { neoData.firstWhere( (e) => e.getID() == d.getID()); + } catch (e) { neoData.add(d); } + } + for (var w in neoData) { + if (WorkspaceLocal.workspaces[w.getID()] == null) { continue; } + items.add(WorkspaceSharedItemPageWidget(name: "Workspace <${WorkspaceLocal.workspaces[w.getID()]!.name}>", id: w.getID())); } } else { items = getCardItems(data); @@ -603,6 +455,7 @@ class WorkspaceSharedPageWidgetState extends State { } } +// ignore: must_be_immutable class WorkspaceSharedItemPageWidget extends StatefulWidget { bool open = true; String id = ""; @@ -638,4 +491,129 @@ class WorkspaceSharedItemPageWidgetState extends State state, BuildContext context, bool mainPage ) { + if (type == CollaborativeAreaType.workspace) { + return Row( mainAxisAlignment: MainAxisAlignment.end, + children : [ Container( padding: EdgeInsets.only(left: mainPage ? 0 : 20), decoration: BoxDecoration( + border: mainPage ? null : Border(left: BorderSide(color: Colors.white)) + ), child: ShallowDropdownInputWidget( + tooltipLoad: "share", + tooltipRemove: "unshare", + iconLoad: Icons.share, + type: type, + filled: mainPage ? Colors.white : lightColor, + hintColor: mainPage ? Colors.grey : midColor, + color: mainPage ? Colors.black : Colors.white, + prefixIcon: Icon(Icons.shopping_cart, color: Colors.white), + current: WorkspaceLocal.current, + all: () async => WorkspaceLocal.getWorkspacesShallow(), + width: getMainWidth(context) / 3, + canLoad: (String? change) => current != null && !current.workspaces.map( (e) => e.id ).contains(change), + canRemove: (String? change) => current != null && current.workspaces.map( (e) => e.id ).contains(change), + load: PermsService.getPerm(Perms.WORKSPACE_SHARE) ? (String val) async { + await SharedService().addWorkspace(context, CollaborativeAreaLocal.current ?? "", val); + await CollaborativeAreaLocal.init(context, false); + state.setState(() {}); + if (mainPage) { + SharedFactory.key.currentState?.setState(() {}); + } + } : null, + remove: PermsService.getPerm(Perms.WORKSPACE_UNSHARE) ? (String val) async { + await SharedService().removeWorkspace(context, CollaborativeAreaLocal.current ?? "", val); + await CollaborativeAreaLocal.init(context, false); + state.setState(() {}); + if (mainPage) { + SharedFactory.key.currentState?.setState(() {}); + } + } : null)) + ]); + } + if (type == CollaborativeAreaType.workflow) { + return Row( mainAxisAlignment: MainAxisAlignment.end, + children : [ Container( padding: EdgeInsets.only(left: mainPage ? 0 : 20), decoration: BoxDecoration( + border: mainPage ? null : Border(left: BorderSide(color: Colors.white)) + ), child: ShallowDropdownInputWidget( + tooltipLoad: "share", + tooltipRemove: "unshare", + iconLoad: Icons.share, + filled: mainPage ? Colors.white : lightColor, + hintColor: mainPage ? Colors.grey : midColor, + color: mainPage ? Colors.black : Colors.white, + type: type, all: () async { + List shals = []; + await WorflowService().all(context).then((value) { + if (value.data != null) { + shals = value.data!.values.map((e) => Shallow(id: e["id"], name: e["name"])).toList(); + } + }); + return shals; + }, + width: getMainWidth(context) / 3, + canLoad: (String? change) => current != null && !current.workflows.map( (e) => e.id ).contains(change), + canRemove: (String? change) => current != null && current.workflows.map( (e) => e.id ).contains(change), + load: PermsService.getPerm(Perms.WORKFLOW_SHARE) ? (String change) async { + await SharedService().addWorkflow(context, CollaborativeAreaLocal.current ?? "", change); + await CollaborativeAreaLocal.init(context, false); + state.setState(() {}); + if (mainPage) { + SharedFactory.key.currentState?.setState(() {}); + } + } : null, + remove: PermsService.getPerm(Perms.WORKFLOW_UNSHARE) ? (String change) async { + await SharedService().removeWorkflow(context, CollaborativeAreaLocal.current ?? "", change); + await CollaborativeAreaLocal.init(context, false); + state.setState(() {}); + if (mainPage) { + SharedFactory.key.currentState?.setState(() {}); + } + } : null)) + ]); + } + if (type == CollaborativeAreaType.peer) { + return Row( mainAxisAlignment: MainAxisAlignment.end, + children : [ + Container( padding: EdgeInsets.only(left: mainPage ? 0 : 20), decoration: BoxDecoration( + border: mainPage ? null : Border(left: BorderSide(color : Colors.white)) + ), child: ShallowDropdownInputWidget( + tooltipLoad: "add", + iconLoad: Icons.add, + filled: mainPage ? Colors.white : lightColor, + hintColor: mainPage ? Colors.grey : midColor, + color: mainPage ? Colors.black : Colors.white, + type: type, all: () async { + List shals = []; + await PeerService().all(context).then((value) { + if (value.data != null) { + shals = value.data!.values.where( (e) { + return e["id"] != current?.creatorID; + } + ).map((e) => Shallow(id: e["id"], name: e["name"])).toList(); + } + }); + return shals; + }, + width: getMainWidth(context) / 3, + canLoad: (String? change) => current != null && !current.peers.map( (e) => e.id ).contains(change), + canRemove: (String? change) => current != null && current.peers.map( (e) => e.id ).contains(change), + load: PermsService.getPerm(Perms.PEER_SHARE) ? (String change) async { + await SharedService().addPeer(context, CollaborativeAreaLocal.current ?? "", change); + await CollaborativeAreaLocal.init(context, false); + state.setState(() {}); + if (mainPage) { + SharedFactory.key.currentState?.setState(() {}); + } + } : null, + remove: PermsService.getPerm(Perms.PEER_UNSHARE) ? (String change) async { + await SharedService().removePeer(context, CollaborativeAreaLocal.current ?? "", change); + await CollaborativeAreaLocal.init(context, false); + state.setState(() {}); + if (mainPage) { + SharedFactory.key.currentState?.setState(() {}); + } + } : null)) + ]); + } + return Container(); + } \ No newline at end of file diff --git a/lib/pages/workflow.dart b/lib/pages/workflow.dart index be0f6f1..af17bfa 100644 --- a/lib/pages/workflow.dart +++ b/lib/pages/workflow.dart @@ -6,35 +6,41 @@ import 'package:oc_front/core/models/workspace_local.dart'; import 'package:oc_front/core/services/perms_service.dart'; import 'package:oc_front/core/services/specialized_services/workflow_service.dart'; import 'package:oc_front/main.dart'; +import 'package:oc_front/models/resources/compute.dart'; +import 'package:oc_front/models/resources/data.dart'; +import 'package:oc_front/models/resources/processing.dart'; +import 'package:oc_front/models/resources/resources.dart'; +import 'package:oc_front/models/resources/storage.dart'; +import 'package:oc_front/models/resources/workflow.dart'; import 'package:oc_front/models/response.dart'; -import 'package:oc_front/models/search.dart'; import 'package:oc_front/models/workflow.dart'; import 'package:oc_front/pages/abstract_page.dart'; import 'package:oc_front/pages/shared.dart'; import 'package:oc_front/widgets/dialog/shallow_creation.dart'; -import 'package:oc_front/widgets/forms/compute_forms.dart'; -import 'package:oc_front/widgets/forms/data_forms.dart'; -import 'package:oc_front/widgets/forms/processing_forms.dart'; +import 'package:oc_front/widgets/forms/resource_forms.dart'; import 'package:oc_front/widgets/forms/scheduler_forms.dart'; -import 'package:oc_front/widgets/forms/storage_forms.dart'; +import 'package:oc_front/widgets/forms/storage_processing_link_forms.dart'; import 'package:oc_front/widgets/items/item_row.dart'; import 'package:oc_front/widgets/inputs/shallow_dropdown_input.dart'; Dashboard dash = Dashboard(name: ""); class WorkflowFactory implements AbstractFactory { @override GlobalKey getKey() { return key; } + @override String? getSearch() { return ""; } + @override void back(BuildContext context) { } static GlobalKey key = GlobalKey(); @override bool searchFill() { return false; } @override Widget factory(GoRouterState state, List args) { String? id; try { id = state.pathParameters[args.first]; - } catch (e) { } + } catch (e) { /**/ } return WorkflowPageWidget(id: id); } @override void search(BuildContext context, bool special) { } } bool getAll = true; +// ignore: must_be_immutable class WorkflowPageWidget extends StatefulWidget { String? id; WorkflowPageWidget ({ this.id }) : super(key: WorkflowFactory.key); @@ -55,19 +61,20 @@ final WorflowService _service = WorflowService(); var e = item as AbstractItem; return Container(color: Colors.white, child: ItemRowWidget(low: true, contextWidth: 290, item: e)); } + Widget getArrowForms(ArrowPainter? arrow) { + if (arrow == null) { return Container(); } + var from = dash.getElement(arrow.fromID); + var to = dash.getElement(arrow.toID); + if ((from?.element?.getType() == "storage" && to?.element?.getType() == "processing") + || (from?.element?.getType() == "processing" && to?.element?.getType() == "storage")) { + return StorageProcessingLinkFormsWidget( dash: dash, item: arrow); + } + return Container(); + } List getForms(FlowData? obj, String id) { var objAbs = obj as AbstractItem?; if (objAbs == null) { return []; } - List res = []; - if ( objAbs.topic == "processing") { - res = [ProcessingFormsWidget(item: objAbs as ProcessingItem, dash: dash, elementID: id)]; - } else if ( objAbs.topic == "data" ) { - res = [DataFormsWidget(item: objAbs as DataItem)]; - } else if ( objAbs.topic == "storage" ) { - res = [StorageFormsWidget(item: objAbs as StorageItem)]; - } else if ( objAbs.topic == "compute" ) { - res = [ComputeFormsWidget(item: objAbs as ComputeItem)]; - } + List res = [ ResourceFormsWidget(item: objAbs, dash: dash, elementID: id) ]; return [ Wrap( alignment: WrapAlignment.center, children: [ @@ -84,18 +91,20 @@ final WorflowService _service = WorflowService(); Widget? getTopRight(FlowData? obj) { var objAbs = obj as AbstractItem?; if (objAbs == null) { return null; } - if (objAbs.topic == "compute" ) { - var compute = objAbs as ComputeItem; - if (compute.technology == 0) { - return Icon(FontAwesomeIcons.docker, size: 16); - } else if (compute.technology == 1) { - return Icon(FontAwesomeIcons.lifeRing, size: 16); - } else if (compute.technology == 2) { - return Icon(FontAwesomeIcons.cubes, size: 16); - } else if (compute.technology == 3) { - return Icon(FontAwesomeIcons.hardDrive, size: 16); - } else if (compute.technology == 4) { - return Icon(FontAwesomeIcons.v, size: 16); + if (objAbs.topic == "compute") { + var instance = objAbs as ComputeItem; + if (instance.infrastructureEnum != null) { + if (instance.infrastructureEnum == 0) { + return Icon(FontAwesomeIcons.docker, size: 16); + } else if (instance.infrastructureEnum == 1) { + return Icon(FontAwesomeIcons.lifeRing, size: 16); + } else if (instance.infrastructureEnum == 2) { + return Icon(FontAwesomeIcons.cubes, size: 16); + } else if (instance.infrastructureEnum == 3) { + return Icon(FontAwesomeIcons.hardDrive, size: 16); + } else if (instance.infrastructureEnum == 4) { + return Icon(FontAwesomeIcons.v, size: 16); + } } } return null; @@ -136,10 +145,11 @@ final WorflowService _service = WorflowService(); } await _service.get(context, dash.id ?? "").then((value) async { if (value.data != null) { + // ignore: use_build_context_synchronously await WorkspaceLocal.init(context, false); WorkspaceLocal.changeWorkspaceByName("${value.data?.name ?? ""}_workspace"); dash.clear(); - dash.deserialize(value.data!.toDashboard()); + dash.deserialize(value.data!.toDashboard(), false); Future.delayed(const Duration(seconds: 1), () { dash.name = name; dash.shouldSave = true; @@ -149,26 +159,20 @@ final WorflowService _service = WorflowService(); }); } - Future saveDash(String? id) async { - if (id == null || !dash.isOpened || !dash.shouldSave - || !PermsService.getPerm(Perms.WORKFLOW_EDIT)) { return; } - var datas = WorkspaceLocal.byTopic("data", true).where( - (element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) ); - var compute = WorkspaceLocal.byTopic("compute", true).where( - (element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) ); - var storage = WorkspaceLocal.byTopic("storage", true).where( - (element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) ); - var computing = WorkspaceLocal.byTopic("processing", true).where( - (element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) ); - var workflows = WorkspaceLocal.byTopic("workflows", true).where( - (element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) ); + Future saveDash(String? id, BuildContext? context) async { + if (id == null || !dash.isOpened || !dash.shouldSave || !PermsService.getPerm(Perms.WORKFLOW_EDIT)) { return; } + var datas = dash.elements.where( (e) => e.element?.serialize()["type"] == "data"); + var compute = dash.elements.where( (e) => e.element?.serialize()["type"] == "compute"); + var storage = dash.elements.where( (e) => e.element?.serialize()["type"] == "storage"); + var processing = dash.elements.where( (e) => e.element?.serialize()["type"] == "processing"); + var workflows = dash.elements.where( (e) => e.element?.serialize()["type"] == "workflow"); var updateW = Workflow( name: dash.name, graph: Graph(), data: datas.map((e) => e.id).toSet().toList(), compute: compute.map((e) => e.id).toSet().toList(), storage: storage.map((e) => e.id).toSet().toList(), - processing: computing.map((e) => e.id).toSet().toList(), + processing: processing.map((e) => e.id).toSet().toList(), workflows: workflows.map((e) => e.id).toSet().toList(), ); updateW.fromDashboard(dash.serialize()); @@ -177,8 +181,8 @@ final WorflowService _service = WorflowService(); item.position?.x = (item.position?.x ?? 0) + (item.width! / 2) + 7.5; item.position?.y = (item.position?.y ?? 0) + (item.height! / 2) + 7.5; for (var i in (updateW.graph?.links ?? [] as List).where((element) => id == element.source?.id)) { - i.source?.x = (i.source?.x ?? 0) + (item.width! / 2) + 7; - i.source?.y = (i.source?.y ?? 0) + (item.width! / 2) + 7; + i.source?.x = (i.source?.x ?? 0) + (item.width! / 2) + 7.5; + i.source?.y = (i.source?.y ?? 0) + (item.width! / 2) + 7.5; } for (var i in (updateW.graph?.links ?? [] as List).where((element) => id == element.destination?.id)) { i.destination?.x = (i.destination?.x ?? 0) + (item.width! / 2) + 7.5; @@ -187,31 +191,24 @@ final WorflowService _service = WorflowService(); } updateW.graph?.zoom = dash.getZoomFactor(); dash.addToHistory(); - await _service.put(context, id, updateW.serialize(), {}).then( (e) async { - if (dash.addChange) { - dash.addChange = false; - await WorkspaceLocal.init(context, false); - WorkspaceLocal.changeWorkspaceByName("${dash.name}_workspace"); - dash.selectedLeftMenuKey.currentState?.setState(() { }); - } - }); + _service.put(null, id, updateW.serialize(), {}).then( (e) async { + dash.applyInfos(updateW.graph?.getEnvToUpdate() ?? {}, updateW.toDashboard()); + if (dash.addChange) { + dash.addChange = false; + // ignore: use_build_context_synchronously + await WorkspaceLocal.init(context, false); + WorkspaceLocal.changeWorkspaceByName("${dash.name}_workspace"); + dash.selectedLeftMenuKey.currentState?.setState(() { }); + } + }); } FlowData? transformToData(Map data) { - var d = WorkspaceLocal.getItem(data["id"] ?? "", true); - if (d == null) { return null; } - d.model = ResourceModel().deserialize(data["resource_model"]); - if (d.topic == "data") { return d as DataItem; } - if (d.topic == "compute") { return d as ComputeItem; } - if (d.topic == "storage") { return d as StorageItem; } - if (d.topic == "processing") { - d = d as ProcessingItem; - if (data.containsKey("container")) { - d.container = Containered().deserialize(data["container"]); - } - return d; - } - if (d.topic == "workflows") { return d as WorkflowItem; } + if (data["type"] == "data") { return DataItem().deserialize(data); } + if (data["type"] == "compute") { return ComputeItem().deserialize(data); } + if (data["type"] == "storage") { return StorageItem().deserialize(data); } + if (data["type"] == "processing") { return ProcessingItem().deserialize(data); } + if (data["type"] == "workflows") { return WorkflowItem().deserialize(data); } return null; } @@ -249,12 +246,14 @@ final WorflowService _service = WorflowService(); WorkspaceLocal.changeWorkspaceByName(p0.split("~")[1]); await dash.load!(p0); } + dash.inDialog = false; dash.notifyListeners(); }, create: PermsService.getPerm(Perms.WORKFLOW_CREATE) ? (p0) async => await _service.post(context, p0, {}).then( (value) async { dash.clear(); dash.id = value.data?.getID() ?? ""; dash.name = value.data?.getName() ?? ""; + dash.inDialog = false; dash.notifyListeners(); await WorkspaceLocal.init(context, true); dash.isOpened = true; @@ -288,26 +287,33 @@ final WorflowService _service = WorflowService(); dash.midDashColor = midColor; dash.transformToData = transformToData; dash.infoItemWidget = getForms; + dash.infoLinkWidget = getArrowForms; dash.infoWidget = getDashInfoForms; dash.widthOffset = 50; dash.arrowStyleRules = [ (dash) { for (var arrow in dash.arrows) { - var from = dash.elements.firstWhere((element) => arrow.fromID.contains(element.id)).element; - var to = dash.elements.firstWhere((element) => arrow.toID.contains(element.id)).element; - if ((from is ProcessingItem && to is ComputeItem) || (to is ProcessingItem && from is ComputeItem)) { - arrow.params.color = Colors.orange; - arrow.params.dashSpace = 2; - arrow.params.dashWidth = 2; - } else if ((from is ProcessingItem && to is StorageItem) || (to is ProcessingItem && from is StorageItem)) { - arrow.params.color = redColor; - arrow.params.dashSpace = 2; - arrow.params.dashWidth = 2; - } else if ((from is ProcessingItem && to is DataItem) || (to is ProcessingItem && from is DataItem)) { - arrow.params.color = Colors.blue; - arrow.params.dashSpace = 2; - arrow.params.dashWidth = 2; - } else { + try { + var from = dash.elements.firstWhere((element) => arrow.fromID.split("_")[0] == element.id).element; + var to = dash.elements.firstWhere((element) => arrow.toID.split("_")[0] == element.id).element; + if ((from is ProcessingItem && to is ComputeItem) || (to is ProcessingItem && from is ComputeItem)) { + arrow.params.color = Colors.orange; + arrow.params.dashSpace = 2; + arrow.params.dashWidth = 2; + } else if ((from is ProcessingItem && to is StorageItem) || (to is ProcessingItem && from is StorageItem)) { + arrow.params.color = redColor; + arrow.params.dashSpace = 2; + arrow.params.dashWidth = 2; + } else if ((from is ProcessingItem && to is DataItem) || (to is ProcessingItem && from is DataItem)) { + arrow.params.color = Colors.blue; + arrow.params.dashSpace = 2; + arrow.params.dashWidth = 2; + } else { + arrow.params.color = Colors.black; + arrow.params.dashSpace = 0; + arrow.params.dashWidth = 0; + } + } catch (e) { arrow.params.color = Colors.black; arrow.params.dashSpace = 0; arrow.params.dashWidth = 0; @@ -319,32 +325,7 @@ final WorflowService _service = WorflowService(); dash.saveRules = [ (dash) { dash.error = null; - if (dash.scheduleActive) { - if (dash.elements.isEmpty || dash.elements.where((element) => element.element is ProcessingItem).isEmpty) { - dash.error = "You need at least one processing element"; - dash.scheduleActive = false; - } - var processings = dash.elements.where((element) => element.element is ProcessingItem).map((e) => e.element as ProcessingItem); - var computes = dash.elements.where((element) => element.element is ComputeItem).map((e) => e.element as ComputeItem); - if (processings.length != computes.length) { - dash.error = "You need the same number of processing and compute elements"; - dash.scheduleActive = false; - } - for (var p in processings) { - var links = dash.arrows.where((element) => element.fromID.contains(p.getID()) || element.toID.contains(p.getID())); - try { - computes.firstWhere( (e) => links.first.toID.contains(e.getID()) || links.first.fromID.contains(e.getID()) ); - } catch (e) { - dash.error = "You need to link each processing element to a compute element"; - dash.scheduleActive = false; - } - } - if (dash.error != null) { - print(dash.error); - setState(() {}); - } - return dash.scheduleActive; - } + return true; } ]; diff --git a/lib/widgets/catalog.dart b/lib/widgets/catalog.dart index 456d6d2..15fdbc9 100644 --- a/lib/widgets/catalog.dart +++ b/lib/widgets/catalog.dart @@ -1,14 +1,14 @@ -import 'package:flutter/material.dart'; -import 'package:oc_front/core/models/workspace_local.dart'; import 'package:oc_front/main.dart'; -import 'package:oc_front/models/search.dart'; +import 'package:flutter/material.dart'; import 'package:oc_front/widgets/items/item_row.dart'; +import 'package:oc_front/models/resources/resources.dart'; +import 'package:oc_front/core/models/workspace_local.dart'; class CatalogWidget extends StatefulWidget { double? itemWidth; bool readOnly = false; final List? items; - CatalogWidget ({ Key? key, this.items, this.itemWidth, this.readOnly = false }): super(key: key); + CatalogWidget ({ super.key, this.items, this.itemWidth, this.readOnly = false }); @override CatalogWidgetState createState() => CatalogWidgetState(); } class CatalogWidgetState extends State { diff --git a/lib/widgets/dialog/login.dart b/lib/widgets/dialog/login.dart index ac08d3f..eda7360 100644 --- a/lib/widgets/dialog/login.dart +++ b/lib/widgets/dialog/login.dart @@ -4,6 +4,7 @@ import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:go_router/go_router.dart'; import 'package:oc_front/core/services/auth.service.dart'; import 'package:oc_front/main.dart'; +import 'package:oc_front/pages/workflow.dart'; class LoginWidget extends StatefulWidget { LoginWidget ({ Key? key }): super(key: key); @@ -30,26 +31,32 @@ class LoginWidgetState extends State { loading = false; error = "Invalid username or password"; }); + }).then( (e) { + if (error == null) { + // ignore: use_build_context_synchronously + setState(() { + loading = false; + }); + loginIsSet = false; + dash.inDialog = false; + context.pop(); + mainKey?.currentState?.setState(() {}); + } }); - if (error == null) { - // ignore: use_build_context_synchronously - setState(() { - loading = false; - }); - context.pop(); - } } }, - child: Padding( - padding: const EdgeInsets.all(50), child: Column(mainAxisSize: MainAxisSize.min, children: [ - const Center(child: Icon(Icons.person_search, size: 150, color: Colors.grey,)), + child: Container( padding: const EdgeInsets.all(50), child: Column(children: [ + getMainHeight(context) < 600 ? Container() : SizedBox( width: getMainWidth(context) / 4, height: getMainHeight(context) / 4, + child: FittedBox( + child:const Center(child: Icon(Icons.person_search, size: 150, color: Colors.grey,)))), Center(child: Padding( padding: const EdgeInsets.only(top: 5, bottom: 20), child: Text("WELCOME ON OPENCLOUD", style: TextStyle(fontSize: 25, fontWeight: FontWeight.w600, - color: lightColor ) ))), - Container( margin: const EdgeInsets.only(bottom: 10), child: Center(child: Row( mainAxisAlignment: MainAxisAlignment.center, + color: lightColor ), overflow: TextOverflow.ellipsis, ))), + Container( margin: const EdgeInsets.only(bottom: 10), + child: Center(child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( - width: getMainWidth(context) / 3, + width: MediaQuery.of(context).size.width / 3, alignment : Alignment.center, child: TextField( controller: usernameCtrl, @@ -69,7 +76,7 @@ class LoginWidgetState extends State { Center(child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( - width: getMainWidth(context) / 3, + width: MediaQuery.of(context).size.width / 3, alignment : Alignment.center, child: TextField( controller: passwordCtrl, @@ -105,20 +112,22 @@ class LoginWidgetState extends State { loading = false; error = "Invalid username or password"; }); + }).then( (e) { + if (error == null) { + // ignore: use_build_context_synchronously + setState(() { + loading = false; + }); + loginIsSet = false; + dash.inDialog = false; + context.pop(); + mainKey?.currentState?.setState(() {}); + } }); - - if (error == null) { - // ignore: use_build_context_synchronously - setState(() { - loading = true; - }); - context.pop(); - //mainKey?.currentState!.setState(() {}); - } }, mouseCursor: SystemMouseCursors.click, child: Container( - width: getMainWidth(context) / 3, + width: MediaQuery.of(context).size.width / 3, padding: const EdgeInsets.symmetric(vertical: 20), color: usernameCtrl.text == "" || passwordCtrl.text == "" ? Colors.grey : lightColor, child: Center( child: loading ? SpinKitWave(color: Colors.white, size: 20) : Text("LOGIN", style: TextStyle( diff --git a/lib/widgets/dialog/shallow_creation.dart b/lib/widgets/dialog/shallow_creation.dart index d8d8220..8c36574 100644 --- a/lib/widgets/dialog/shallow_creation.dart +++ b/lib/widgets/dialog/shallow_creation.dart @@ -3,9 +3,11 @@ import 'package:oc_front/main.dart'; import 'package:oc_front/models/response.dart'; import 'package:oc_front/core/services/router.dart'; import 'package:oc_front/pages/shared.dart'; +import 'package:oc_front/pages/workflow.dart'; import 'package:oc_front/widgets/inputs/shallow_dropdown_input.dart'; import 'package:oc_front/widgets/inputs/shallow_text_input.dart'; +// ignore: must_be_immutable class ShallowCreationDialogWidget extends StatefulWidget { GlobalKey? formKey; BuildContext context; @@ -43,6 +45,7 @@ class ShallowCreationDialogState extends State { Tooltip( message: "back", child: InkWell( mouseCursor: SystemMouseCursors.click, onTap: () { + dash.inDialog = false; AppRouter.catalog.go(context, {}); }, child: const Icon(Icons.arrow_back, color: Colors.black))), @@ -50,7 +53,10 @@ class ShallowCreationDialogState extends State { widget.canClose != null && !widget.canClose!() ? Container() : Row ( mainAxisAlignment: MainAxisAlignment.end, children: [ Tooltip( message: "close", child: InkWell( mouseCursor: SystemMouseCursors.click, - onTap: () { Navigator.pop(context); }, + onTap: () { + dash.inDialog = false; + Navigator.pop(context); + }, child: const Icon(Icons.close, color: Colors.black))), ]), ],), @@ -62,6 +68,7 @@ class ShallowCreationDialogState extends State { width: getMainWidth(context) <= 540 ? getMainWidth(context) - 140 : 400, load: (e) async { await widget.load!(e); + dash.inDialog = false; Navigator.pop(widget.context); }, iconLoad: Icons.open_in_browser_outlined, @@ -83,6 +90,7 @@ class ShallowCreationDialogState extends State { width: getMainWidth(context) <= 540 ? getMainWidth(context) - 140 : 400, load: (e) async { await widget.create!(e); + dash.inDialog = false; Navigator.pop(widget.context); }, forms: widget.form, diff --git a/lib/widgets/forms/compute_forms.dart b/lib/widgets/forms/compute_forms.dart deleted file mode 100644 index d9f7c4b..0000000 --- a/lib/widgets/forms/compute_forms.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:oc_front/widgets/inputs/sub_text_input.dart'; - -class ComputeFormsWidget extends StatefulWidget { - dynamic item; - ComputeFormsWidget ({ super.key, required this.item }); - @override ComputeFormsWidgetState createState() => ComputeFormsWidgetState(); -} -class ComputeFormsWidgetState extends State { - @override Widget build(BuildContext context) { - return Column( children: [ - SubTextInputWidget(subkey: "technology", width: 180, empty: false, change: (value) { - }, initialValue: widget.item.getTechnology(), readOnly: true,), - SubTextInputWidget(subkey: "architecture", width: 180, empty: false, change: (value) { - }, initialValue: widget.item.architecture, readOnly: true,), - SubTextInputWidget(subkey: "access", width: 180, empty: false, change: (value) { - }, initialValue: widget.item.getAccess(), readOnly: true,), - SubTextInputWidget(subkey: "localisation", width: 180, empty: false, change: (value) { - }, initialValue: widget.item.localisation, readOnly: true,), - ]); - } -} \ No newline at end of file diff --git a/lib/widgets/forms/container_forms.dart b/lib/widgets/forms/container_forms.dart new file mode 100644 index 0000000..3cc8769 --- /dev/null +++ b/lib/widgets/forms/container_forms.dart @@ -0,0 +1,105 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_flow_chart/flutter_flow_chart.dart'; +import 'package:oc_front/models/resources/processing.dart'; +import 'package:oc_front/models/resources/resources.dart'; +import 'package:oc_front/widgets/forms/sub_expose_forms.dart'; +import 'package:oc_front/widgets/inputs/sub_text_input.dart'; + +// ignore: must_be_immutable +class ContainerFormsWidget extends StatefulWidget { + int instanceID = 0; + Dashboard dash; + AbstractItem item; + String elementID; + ContainerFormsWidget({ super.key, required this.item, required this.dash, required this.elementID }); + @override ContainerFormsWidgetState createState() => ContainerFormsWidgetState(); +} + +class ContainerFormsWidgetState extends State { + @override Widget build(BuildContext context) { + List widgets = []; + var instance = widget.item.getSelectedInstance(); + if (instance != null && instance is ProcessingInstance && instance.access?.container != null) { + var container = instance.access!.container!; + widgets.add(Container( + padding: const EdgeInsets.only(bottom: 10), + width: 180, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("", style: const TextStyle(fontSize: 13, fontWeight: FontWeight.bold), textAlign: TextAlign.center), + SubTextInputWidget(subkey: "image", width: 180, empty: false, change: (value) { }, + initialValue: container.image, readOnly: true), + SubTextInputWidget(subkey: "command", width: 180, empty: false, change: (value) { + container.command = value; + for (var el in widget.dash.elements) { + if (el.id == widget.elementID) { + el.element = widget.item; + break; + } + } + widget.dash.saveDash(widget.dash.id, context); + }, initialValue: container.command, readOnly: false,), + SubTextInputWidget(subkey: "args", width: 180, empty: false, change: (value) { + container.args = value; + for (var el in widget.dash.elements) { + if (el.id == widget.elementID) { + el.element = widget.item; + break; + } + } + widget.dash.saveDash(widget.dash.id, context); + }, + initialValue: container.args, readOnly: false,) + ],) + )); + widgets.add(Container( + width: 200, decoration: BoxDecoration( border: Border(bottom: BorderSide(color: Colors.grey))), + )); + widgets.add(Container( + padding: const EdgeInsets.symmetric(vertical: 10), + width: 180, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Padding(padding: EdgeInsets.only(bottom: 5), child: Text("", + style: TextStyle(fontSize: 13, fontWeight: FontWeight.bold), textAlign: TextAlign.center)), + Row( children: [ + InkWell( onTap: () { + container.exposes.add(Expose()); + var el = widget.dash.getElement(widget.elementID); + el!.element = widget.item as dynamic; + setState(() {}); + }, child: + Container( margin: const EdgeInsets.only(top: 5), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.grey, width: 1)), + width: 125, height: 30, + child: const Row( mainAxisAlignment: MainAxisAlignment.center, + children: [ Padding( padding: EdgeInsets.only(right: 5), child: Icon(Icons.add)), Text("add expose")]), + ) + ), + InkWell( onTap: () { + if (container.exposes.isEmpty) { return; } + container.exposes = container.exposes.sublist(0, container.exposes.length - 1); + var el = widget.dash.getElement(widget.elementID); + el!.element = widget.item as dynamic; + setState(() {}); + }, child: + Container( margin: const EdgeInsets.only(left: 5, top: 5), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.grey, width: 1)), + width: 45, height: 30, + child: const Row( mainAxisAlignment: MainAxisAlignment.center, + children: [ Icon(Icons.delete, color: Colors.black) ]), + ) + ) + ]), + ],) + )); + for (var expose in container.exposes) { + widgets.add(SubExposeFormsWidget( readOnly: true, width: 180, dash: widget.dash, empty: widgets.isEmpty, + item: expose, elementID: widget.elementID)); + } + } + return Column(children: widgets); + } +} \ No newline at end of file diff --git a/lib/widgets/forms/credentials_forms.dart b/lib/widgets/forms/credentials_forms.dart new file mode 100644 index 0000000..b4c4a8c --- /dev/null +++ b/lib/widgets/forms/credentials_forms.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_flow_chart/flutter_flow_chart.dart'; +import 'package:oc_front/models/resources/resources.dart'; +import 'package:oc_front/widgets/inputs/sub_text_input.dart'; + +// ignore: must_be_immutable +class CredentialsFormsWidget extends StatefulWidget { + int instanceID = 0; + Dashboard dash; + AbstractItem item; + String elementID; + CredentialsFormsWidget({ super.key, required this.item, required this.dash, required this.elementID }); + @override CredentialsFormsWidgetState createState() => CredentialsFormsWidgetState(); +} + +class CredentialsFormsWidgetState extends State { + @override Widget build(BuildContext context) { + List widgets = []; + var instance = widget.item.getSelectedInstance(); + if (instance != null && instance.credential != null) { + var creds = instance.credential!; + widgets.add(Container( margin: EdgeInsets.only(bottom: 15), + width: 200, decoration: BoxDecoration( border: Border(bottom: BorderSide(color: Colors.grey))), + )); + widgets.add(Container( + padding: const EdgeInsets.only(bottom: 10), + width: 180, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("", style: const TextStyle(fontSize: 13, fontWeight: FontWeight.bold), textAlign: TextAlign.center), + SubTextInputWidget(subkey: "login", width: 180, empty: false, change: (value) { + creds.password = value; + for (var el in widget.dash.elements) { + if (el.id == widget.elementID) { + el.element = widget.item; + break; + } + } + widget.dash.saveDash(widget.dash.id, context); + }, initialValue: creds.login), + SubTextInputWidget(subkey: "password", width: 180, empty: false, change: (value) { + creds.password = value; + for (var el in widget.dash.elements) { + if (el.id == widget.elementID) { + el.element = widget.item; + break; + } + } + widget.dash.saveDash(widget.dash.id, context); + }, initialValue: creds.password, readOnly: false,), + ],) + )); + widgets.add(Container( padding: EdgeInsets.only(bottom: 15), width: 200 )); + } + return Column(children: widgets); + } +} \ No newline at end of file diff --git a/lib/widgets/forms/data_forms.dart b/lib/widgets/forms/data_forms.dart deleted file mode 100644 index 99c2af5..0000000 --- a/lib/widgets/forms/data_forms.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:oc_front/models/search.dart'; -import 'package:oc_front/widgets/forms/web_reference_forms.dart'; - -class DataFormsWidget extends StatefulWidget { - DataItem item; - String purpose = ""; - Function validate = () {}; - DataFormsWidget ({ super.key, required this.item }); - @override DataFormsWidgetState createState() => DataFormsWidgetState(); -} -class DataFormsWidgetState extends State { - @override Widget build(BuildContext context) { - return Column( children: [ - WebReferenceFormsWidget(item: widget.item), - ]); - } -} \ No newline at end of file diff --git a/lib/widgets/forms/processing_forms.dart b/lib/widgets/forms/processing_forms.dart deleted file mode 100644 index 65b9793..0000000 --- a/lib/widgets/forms/processing_forms.dart +++ /dev/null @@ -1,147 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_flow_chart/flutter_flow_chart.dart'; -import 'package:oc_front/core/services/perms_service.dart'; -import 'package:oc_front/main.dart'; -import 'package:oc_front/models/search.dart'; -import 'package:oc_front/models/workflow.dart'; -import 'package:oc_front/pages/workflow.dart'; -import 'package:oc_front/widgets/forms/sub_keys_forms.dart'; -import 'package:oc_front/widgets/forms/sub_expose_forms.dart'; -import 'package:oc_front/widgets/forms/sub_map_forms.dart'; -import 'package:oc_front/widgets/inputs/sub_text_input.dart'; - -Map> proxyWfItem = {}; -// ADD EXPOSE -class ProcessingFormsWidget extends StatefulWidget { - String elementID; - ProcessingItem item; - Dashboard dash; - ProcessingFormsWidget ({ super.key, required this.item, required this.dash, required this.elementID }); - @override ProcessingFormsWidgetState createState() => ProcessingFormsWidgetState(); -} -class ProcessingFormsWidgetState extends State { - Widget getInputAndOutputVariableForms(bool readOnly) { - var inList = widget.dash.GetArrowByElementID(widget.elementID, true); - var outList = widget.dash.GetArrowByElementID(widget.elementID, false); - List res = []; - List inItems = []; - List outItems = []; - for (var inItem in inList) { - var element = widget.dash.getElement(inItem.fromID.substring(0,36)); - if (element == null) { continue; } - var g = GraphItem(); - g.fromDashboard(element.serialize()); - inItems.add(g); - } - for (var outItem in outList) { - var element = widget.dash.getElement(outItem.toID.substring(0,36)); - if (element == null) { continue; } - var g = GraphItem(); - g.fromDashboard(element.serialize()); - outItems.add(g); - } - if (inItems.isNotEmpty) { - res.add(SubKeysMapFormsWidget(dash: widget.dash, isInput: true, item: widget.item, elementID: widget.elementID, - categoryKey: "container", varKey: "env", graphItems: inItems, readOnly: readOnly)); - } - if (outItems.isNotEmpty) { - res.add(SubKeysMapFormsWidget(dash: widget.dash, isInput: false, item: widget.item, elementID: widget.elementID, - categoryKey: "container", varKey: "env", graphItems: outItems, readOnly: readOnly)); - } - return Column( children: res ); - } - - @override Widget build(BuildContext context) { - bool readOnly = !PermsService.getPerm(Perms.WORKFLOW_EDIT); - List categories = []; - var l = widget.item.model?.model?.keys ?? []; - for (var child in l) { - var sub = widget.item.model!.model![child]!; - List children = []; - for (var st in sub.keys) { - if (sub[st]!.type?.contains("map") ?? false) { - children.add( - SubMapFormsWidget(dash: dash, empty: children.isEmpty, item: widget.item, - readOnly: readOnly, - elementID: widget.elementID, categoryKey: child, varKey: st) - ); - } else if (sub[st]!.type == "string") { - children.add(SubTextInputWidget(subkey: st, - readOnly: readOnly, - initialValue: widget.item.getVariable([child, st], widget.item.serialize()), - width: 180, empty: children.isEmpty, change: (value) { - widget.item.model ?? Model(); - Future.delayed(const Duration(seconds: 2), () { - if (widget.item.getVariable([child, st], widget.item.serialize()) == value) { - dash.saveDash(dash.id); - } - }); - var el = dash.getElement(widget.elementID); - widget.item = widget.item.deserialize(widget.item.setVariable([child, st], value, widget.item.serialize())) as dynamic; - el!.element = widget.item as dynamic; - }) - ); - } - } - categories.add(Container( - padding: const EdgeInsets.symmetric(vertical: 10), - width: 180, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text("<${child.toUpperCase()}>", style: const TextStyle(fontSize: 13, fontWeight: FontWeight.bold), textAlign: TextAlign.center), - Padding(padding: const EdgeInsets.only(bottom: 10), child: SubTextInputWidget(subkey: "image", width: 180, empty: false, change: (value) {}, - initialValue: widget.item.container?.image, readOnly: true,)), - ...children, - getInputAndOutputVariableForms(readOnly), - ],) - )); - } - // EXPOSE - categories.add(Container( - padding: const EdgeInsets.symmetric(vertical: 10), - width: 180, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Padding(padding: EdgeInsets.only(bottom: 5), child: Text("", - style: TextStyle(fontSize: 13, fontWeight: FontWeight.bold), textAlign: TextAlign.center)), - readOnly ? Container() : Row( children: [ - InkWell( onTap: () { - widget.item.expose.add(Expose()); - var el = dash.getElement(widget.elementID); - el!.element = widget.item as dynamic; - setState(() {}); - }, child: - Container( margin: const EdgeInsets.only(top: 5), - decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.grey, width: 1)), - width: 125, height: 30, - child: const Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ Padding( padding: EdgeInsets.only(right: 5), child: Icon(Icons.add)), Text("add expose")]), - ) - ), - InkWell( onTap: () { - if (widget.item.expose.isEmpty) { return; } - widget.item.expose = widget.item.expose.sublist(0, widget.item.expose.length - 1); - var el = dash.getElement(widget.elementID); - el!.element = widget.item as dynamic; - setState(() {}); - }, child: - Container( margin: const EdgeInsets.only(left: 5, top: 5), - decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.grey, width: 1)), - width: 45, height: 30, - child: const Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ Icon(Icons.delete, color: Colors.black) ]), - ) - ) - ]), - ],) - )); - for (var expose in widget.item.expose) { - categories.add(SubExposeFormsWidget( readOnly: readOnly, width: 180, dash: dash, empty: categories.isEmpty, - item: expose, elementID: widget.elementID)); - } - return SizedBox( height: getHeight(context) - 330, child: SingleChildScrollView( child: Column( - children: categories )) ); - } -} \ No newline at end of file diff --git a/lib/widgets/forms/resource_forms.dart b/lib/widgets/forms/resource_forms.dart new file mode 100644 index 0000000..aff14b4 --- /dev/null +++ b/lib/widgets/forms/resource_forms.dart @@ -0,0 +1,92 @@ +import 'package:oc_front/main.dart'; +import 'package:flutter/material.dart'; +import 'package:oc_front/models/workflow.dart'; +import 'package:oc_front/models/resources/resources.dart'; +import 'package:oc_front/core/services/perms_service.dart'; +import 'package:oc_front/widgets/forms/credentials_forms.dart'; +import 'package:oc_front/widgets/forms/sub_keys_forms.dart'; +import 'package:flutter_flow_chart/flutter_flow_chart.dart'; +import 'package:oc_front/widgets/inputs/sub_text_input.dart'; +import 'package:oc_front/widgets/forms/container_forms.dart'; +import 'package:oc_front/widgets/inputs/sub_dropdown_input%20.dart'; + +// ignore: must_be_immutable +class ResourceFormsWidget extends StatefulWidget { + AbstractItem item; + Dashboard dash; + String elementID; + ResourceFormsWidget ({ super.key, required this.item, required this.dash, required this.elementID }); + @override ResourceFormsWidgetState createState() => ResourceFormsWidgetState(); +} + +class ResourceFormsWidgetState extends State { + List getWidgets(Map infos) { + List widgets = []; + for (var key in infos.keys) { + if (infos[key] == null && infos[key] != 0) { continue; } + if (infos[key] is Map) { widgets.addAll(getWidgets(infos[key])); + } if (infos[key] is List) { + if (infos[key].isEmpty) { continue; } + widgets.add(SubTextInputWidget(subkey: key.replaceAll("_", " "), width: 180, empty: false, readOnly: true, + change: (value) {}, initialValue: (infos[key] as List).join(",") )); + } else if (infos[key] is Map) { + widgets.addAll(getWidgets(infos[key] as Map)); + } else { + widgets.add(SubTextInputWidget(subkey: key.replaceAll("_", " "), width: 180, empty: false, readOnly: true, + change: (value) {}, initialValue: infos[key] is List ? infos[key].join(",") : "${infos[key]}" )); + } + } + if (widgets.isNotEmpty) { + widgets.add(SizedBox( width: 200, height: 15) ); + } + return widgets; + } + + Widget getInputAndOutputVariableForms(bool readOnly) { + List res = []; + res.add(SubKeysMapFormsWidget(dash: widget.dash, type: SubMapFormsType.INPUT, item: widget.item, elementID: widget.elementID, + readOnly: readOnly)); + res.add(SubKeysMapFormsWidget(dash: widget.dash, type: SubMapFormsType.OUTPUT, item: widget.item, elementID: widget.elementID, + readOnly: readOnly)); + res.add(SubKeysMapFormsWidget(dash: widget.dash, type: SubMapFormsType.ENV, item: widget.item, elementID: widget.elementID, + readOnly: readOnly)); + return Column( children: res ); + } + + + @override Widget build(BuildContext context) { + List instancesCat = []; + List childrenReadOnly = getWidgets(widget.item.infos()); + List> dpItems = []; + for (var (i, instance) in widget.item.instances.indexed) { + dpItems.add(DropdownMenuItem(value: '$i', child: Text('${instance.name}', overflow: TextOverflow.ellipsis,))); + } + if (dpItems.isNotEmpty) { + childrenReadOnly.add(Padding( padding: EdgeInsets.only(top: 20), + child : Container( + width: 200, decoration: BoxDecoration( border: Border(bottom: BorderSide(color: Colors.grey))), + ))); + childrenReadOnly.add(Padding(padding: EdgeInsets.only(bottom: 15), child: + SubDropdownInputWidget( dropdownMenuEntries: dpItems, subkey: "", width: 180, empty: false, + initialValue: "${widget.item.selectedInstance}", change: (value) { + if (value != null) { setState(() { widget.item.selectedInstance = int.parse(value); }); } + }, + )) + ); + if (widget.item.instances.length > (widget.item.selectedInstance)) { + childrenReadOnly.addAll(getWidgets(widget.item.instances[(widget.item.selectedInstance)].infos())); + } + } + instancesCat.add(ContainerFormsWidget(dash: widget.dash, item: widget.item, elementID: widget.elementID)); + instancesCat.add(CredentialsFormsWidget(dash: widget.dash, item: widget.item, elementID: widget.elementID)); + if (instancesCat.isNotEmpty) { + instancesCat.add(Container( + width: 200, decoration: BoxDecoration( border: Border(bottom: BorderSide(color: Colors.grey))), + )); + } + bool readOnly = !PermsService.getPerm(Perms.WORKFLOW_EDIT); + // missing env input and output variables + return SizedBox( height: getHeight(context) - 330, child: SingleChildScrollView( child: Column( + children: [ getInputAndOutputVariableForms(readOnly), ...childrenReadOnly, ...instancesCat, ]))); + } +} \ No newline at end of file diff --git a/lib/widgets/forms/scheduler_forms.dart b/lib/widgets/forms/scheduler_forms.dart index 8f69bd1..846c673 100644 --- a/lib/widgets/forms/scheduler_forms.dart +++ b/lib/widgets/forms/scheduler_forms.dart @@ -1,72 +1,120 @@ -import 'package:alert_banner/exports.dart'; + 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:datetime_picker_formfield/datetime_picker_formfield.dart'; -import 'package:oc_front/core/models/shared_workspace_local.dart'; -import 'package:oc_front/core/services/perms_service.dart'; -import 'package:oc_front/core/services/specialized_services/workflow_service.dart'; -import 'package:oc_front/core/services/specialized_services/check_service.dart'; +import 'package:oc_front/core/services/specialized_services/workflow_execution_service.dart'; +import 'package:oc_front/core/services/specialized_services/workflow_scheduler_service.dart'; import 'package:oc_front/main.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart' as intl; +import 'package:alert_banner/exports.dart'; +import 'package:oc_front/models/resources/compute.dart'; +import 'package:oc_front/models/resources/processing.dart'; +import 'package:oc_front/models/workflow.dart'; import 'package:oc_front/pages/shared.dart'; import 'package:oc_front/pages/workflow.dart'; import 'package:oc_front/widgets/dialog/alert.dart'; import 'package:oc_front/widgets/dialog/confirm_box.dart'; +import 'package:oc_front/core/services/perms_service.dart'; +import 'package:flutter_flow_chart/flutter_flow_chart.dart'; import 'package:oc_front/widgets/inputs/shallow_text_input.dart'; +import 'package:oc_front/core/models/shared_workspace_local.dart'; +import 'package:datetime_picker_formfield/datetime_picker_formfield.dart'; +import 'package:oc_front/core/services/specialized_services/check_service.dart'; +import 'package:oc_front/core/services/specialized_services/workflow_service.dart'; +// ignore: must_be_immutable class SchedulerFormsWidget extends StatefulWidget { + Scheduler schedule = Scheduler(); Dashboard item; - String purpose = ""; bool? booking; + bool valid = false; + bool shouldSearch = true; + int scheduleFutureCount = 0; + int scheduleBeforeCount = 0; String? error; String? errorEndDate; String? errorCron; Function validate = () {}; + final SchedulerService _schedulerService = SchedulerService(); + final WorkflowExecutionService _executionService = WorkflowExecutionService(); SchedulerFormsWidget ({ super.key, required this.item, }); @override SchedulerFormsWidgetState createState() => SchedulerFormsWidgetState(); } class SchedulerFormsWidgetState extends State { CheckService check = CheckService(); void save(List> formKeys) { - dash.scheduleActive = !dash.scheduleActive; + print("save"); widget.error = null; widget.errorEndDate = null; widget.errorCron = null; + if (dash.elements.isEmpty || dash.elements.where((element) => element.element is ProcessingItem).isEmpty) { + dash.error = "You need at least one processing element"; + } + var processings = dash.elements.where((element) => element.element is ProcessingItem); + var computes = dash.elements.where((element) => element.element is ComputeItem); + for (var p in processings) { + var links = dash.arrows.where((element) => element.fromID.contains(p.id) || element.toID.contains(p.id)); + try { + List c = []; + for (var link in links) { + c.addAll(computes.where( (e) => link.toID.contains(e.id) || link.fromID.contains(e.id)).map( (e) => e.element as ComputeItem)); + } + if (c.isEmpty) { throw Exception("no compute element linked"); } + } catch (e) { + dash.error = "You need to link each processing element to a compute element"; + } + } + if (dash.error != null) { + showAlertBanner( context, () {}, AlertAlertBannerChild(text: dash.error.toString()),// <-- Put any widget here you want! + alertBannerLocation: AlertBannerLocation.bottom,); + setState(() {}); + return; + } for (var k in formKeys) { if (k.currentState != null) { - if (!k.currentState!.validate() && dash.scheduleActive) { - dash.scheduleActive = !dash.scheduleActive; + if (!k.currentState!.validate()) { return; } else { k.currentState!.save();} } } DateTime now = DateTime.now().add(const Duration(minutes: 1)); - if (dash.scheduler["start"] == null || DateTime.parse(dash.scheduler["start"]!).isBefore(now)) { - dash.scheduler["start"] = now.toUtc().toIso8601String(); - if (dash.scheduler["end"] != null) { - dash.scheduler["end"] = now.add(const Duration(minutes: 1)).toUtc().toIso8601String(); + if (widget.schedule.start == null || widget.schedule.start!.isBefore(now)) { + widget.schedule.start = now.toUtc(); + if (widget.schedule.end != null) { + widget.schedule.end = now.add(const Duration(minutes: 1)).toUtc(); } } - widget.item.saveDash(widget.item.id); + Duration durationBefore = widget.schedule.start!.difference(DateTime.now().toUtc()) + Duration(seconds: 5); + widget._schedulerService.schedule(context, widget.item.id ?? "", widget.schedule.serialize(), {}).then((value) { + setState(() { widget.valid = true; }); + Future.delayed(durationBefore, () { + try { + setState(() {}); + } catch (e) { /* */ } + }); + Future.delayed(const Duration(seconds: 10), () { + try { + setState(() { widget.valid = false; }); + } catch (e) { /* */ } + }); + }); } void checkBooking(List> formKeys, void Function(List> )? f){ - if (widget.item.scheduler["start"] == null) { + if (widget.schedule.start == null) { DateTime now = DateTime.now().add(const Duration(minutes: 5)); - widget.item.scheduler["start"] = now.toUtc().toIso8601String(); + widget.schedule.start = now.toUtc(); } - var s = DateTime.parse(widget.item.scheduler["start"]).toUtc().toIso8601String(); + var s = widget.schedule.start!.toUtc().toIso8601String(); var e = ""; - if (widget.item.scheduler["end"] == null) { - e = DateTime.parse(widget.item.scheduler["start"]).add(const Duration(seconds: 5)).toUtc().toIso8601String(); + if (widget.schedule.end == null) { + e = widget.schedule.start!.add(const Duration(seconds: 5)).toUtc().toIso8601String(); } else { - e = DateTime.parse(widget.item.scheduler["end"]).toUtc().toIso8601String(); + e = widget.schedule.end!.toUtc().toIso8601String(); } check.search(context, [widget.item.id ?? "", s.substring(0, 19), e.substring(0, 19)], {}).then( (v) { if (v.data == null) { return; } - widget.booking = v.data!.is_available; - if (v.data!.is_available) { + widget.booking = v.data!.isAvailable; + if (v.data!.isAvailable) { if (f != null) { f(formKeys); } else { showAlertBanner( context, () {}, @@ -84,6 +132,31 @@ class SchedulerFormsWidgetState extends State { } @override Widget build(BuildContext context) { + if (widget.shouldSearch && widget.item.name != "") { + widget.shouldSearch = false; + widget._executionService.search(null, [widget.item.name], {}).then((value) { + if (value.data != null) { + try { + setState(() { + widget.scheduleFutureCount = 0; + widget.scheduleBeforeCount = 0; + for (var exec in value.data!.executions) { + if (exec.startDate != null && DateTime.parse(exec.startDate!).isAfter(DateTime.now().toUtc())) { + widget.scheduleFutureCount++; + } else { + widget.scheduleBeforeCount++; + } + } + }); + } catch (e) { /* */ } + + } + }); + } else { + Future.delayed(const Duration(milliseconds: 100), () { + widget.shouldSearch = true; + }); + } bool isService = true; try { widget.item.elements.firstWhere((element) => (element.element?.serialize()["is_service"] ?? false) == true); @@ -95,22 +168,22 @@ class SchedulerFormsWidgetState extends State { DateTime? end; Duration delayed = const Duration(minutes: 5); - if (widget.item.scheduler["start"] != null) { - start = DateTime.parse(widget.item.scheduler["start"]!); - if (start.isBefore(DateTime.now()) && !dash.scheduleActive) { + if (widget.schedule.start != null) { + start = widget.schedule.start!; + if (start.isBefore(DateTime.now())) { start = DateTime.now().add(const Duration(minutes: 5)); - widget.item.scheduler["start"] = start.toUtc().toIso8601String(); + widget.schedule.start = start.toUtc(); } if (start.isBefore(DateTime.now())) { // get difference between now and start delayed = start.difference(DateTime.now()); } } - if (widget.item.scheduler["end"] != null) { - end = DateTime.parse(widget.item.scheduler["end"]!); - if (end.isBefore(DateTime.now()) && !dash.scheduleActive) { + if (widget.schedule.end != null) { + end = widget.schedule.end!; + if (end.isBefore(DateTime.now())) { end = DateTime.now().add(const Duration(minutes: 5)); - widget.item.scheduler["end"] = end.toUtc().toIso8601String(); + widget.schedule.end = end.toUtc(); } if (end.isBefore(DateTime.now())) { // get difference between now and start @@ -164,51 +237,11 @@ class SchedulerFormsWidgetState extends State { child: shallow ), const SizedBox(height: 20, width: 200 ), isService ? Text("Warning a processing is a service, if no end execution it will run forever.") : Container(), - Tooltip( message: "executions name", - child: Container( height: 40, margin: const EdgeInsets.only(top: 5), - padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), - child: TextFormField( key: formKeys[0], readOnly: readOnly, - initialValue: "${widget.item.scheduler["name"] ?? "${widget.item.name}_executions"}", - enabled: !dash.scheduleActive && !readOnly, - onChanged: (value) { - Future.delayed(const Duration(seconds: 100), () { - if (widget.item.scheduler["name"] == value) { - widget.item.saveDash(widget.item.id); - } - }); - widget.item.scheduler["name"] = value; - }, - onSaved: (value) { - widget.item.scheduler["name"] = value ?? "${widget.item.scheduler["name"] ?? "${widget.item.name}_executions"}"; - }, - validator: (value) { - if (value == null || value.isEmpty) { - setState(() { widget.error = 'missing name'; }); - } - return value == null || value.isEmpty ? "not empty" : null; - }, - style: const TextStyle(fontSize: 12), - decoration: InputDecoration( - floatingLabelBehavior: FloatingLabelBehavior.always, - fillColor: Colors.white, - filled: true, - hintText: "enter executions name...", - labelText: "executions name*", - hintStyle: TextStyle(fontSize: 10), - labelStyle: TextStyle(fontSize: 10), - focusedErrorBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.item.error != null || widget.error != null ? Colors.red : Colors.black)), - errorBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.item.error != null || widget.error != null ? Colors.red : Colors.black)), - focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.item.error != null || widget.error != null ? Colors.red : Colors.black)), - enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.item.error != null || widget.error != null ? Colors.red : Colors.grey)), - border: OutlineInputBorder(borderSide: BorderSide(color: widget.item.error != null || widget.error != null ? Colors.red : Colors.grey)), - contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5), - ), - ))), Tooltip( message: "start executions", child: Container( height: 40, margin: const EdgeInsets.only(top: 5), padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), child: DateTimeField( key: formKeys[1], - enabled: !dash.scheduleActive && !readOnly, + enabled: !readOnly, resetIcon: null, onShowPicker: (context, currentValue) async { var date = await showDatePicker( @@ -228,7 +261,7 @@ class SchedulerFormsWidgetState extends State { return w; }, context: context, - firstDate: dash.scheduleActive ? DateTime(1900) : DateTime.now().add(const Duration(minutes: 5)), + firstDate: DateTime.now().add(const Duration(minutes: 5)), initialDate: DateTime.parse( start?.toLocal().toIso8601String() ?? currentValue?.toIso8601String() ?? DateTime.now().add(const Duration(minutes: 5)).toUtc().toIso8601String()).toLocal(), @@ -265,9 +298,9 @@ class SchedulerFormsWidgetState extends State { if (time == null) { return DateTime.now().add( const Duration(minutes: 1)); } count++; date = DateTime(date.year, date.month, date.day, time.hour, time.minute); - widget.item.scheduler["start"] = date.toUtc().toIso8601String(); + widget.schedule.start = date.toUtc(); } - widget.item.saveDash(widget.item.id); + widget.item.saveDash(widget.item.id, context); } return date; }, @@ -296,18 +329,18 @@ class SchedulerFormsWidgetState extends State { child: Container( height: 40, margin: const EdgeInsets.only(top: 5), padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), child: DateTimeField( key: formKeys[2], - enabled: !dash.scheduleActive && !readOnly, + enabled: !readOnly, validator: (value) { - if (value == null && widget.item.scheduler["cron"] != null && widget.item.scheduler["cron"].isNotEmpty) { + if (value == null && widget.schedule.cron != null && widget.schedule.cron!.isNotEmpty) { setState(() { widget.errorEndDate = 'missing start date'; }); } - return value == null && widget.item.scheduler["cron"] != null && widget.item.scheduler["cron"].isNotEmpty ? "not empty" : null; + return value == null && widget.schedule.cron != null && widget.schedule.cron!.isNotEmpty ? "not empty" : null; }, onChanged: (value) { if (value == null) { - widget.item.scheduler.remove("end"); + widget.schedule.end = null; } }, resetIcon: const Icon(Icons.close, size: 15), @@ -329,7 +362,7 @@ class SchedulerFormsWidgetState extends State { return w; }, context: context, - firstDate: dash.scheduleActive ? DateTime(1900) : DateTime.now().add(const Duration(minutes: 5)), + firstDate: DateTime.now().add(const Duration(minutes: 5)), initialDate: DateTime.parse( end?.toLocal().toIso8601String() ?? currentValue?.toIso8601String() ?? DateTime.now().add(const Duration(minutes: 5)).toUtc().toIso8601String()).toLocal(), @@ -342,7 +375,7 @@ class SchedulerFormsWidgetState extends State { var count = 0; while(date!.microsecondsSinceEpoch <= (DateTime.now().microsecondsSinceEpoch) || time == null - || (date.microsecondsSinceEpoch) <= (DateTime.parse(widget.item.scheduler["start"] ?? DateTime.now().toIso8601String()).microsecondsSinceEpoch)) { + || (date.microsecondsSinceEpoch) <= (widget.schedule.start ?? DateTime.now()).microsecondsSinceEpoch) { if (count > 0) { showAlertBanner( context, () {}, // ignore: use_build_context_synchronously const AlertAlertBannerChild(text: "must be at least 1 minute from now to let system check info && upper starting date"),// <-- Put any widget here you want! @@ -370,9 +403,9 @@ class SchedulerFormsWidgetState extends State { if (time == null) { return null; } count++; date = DateTime(date.year, date.month, date.day, time.hour, time.minute); - widget.item.scheduler["end"] = date.toUtc().toIso8601String(); + widget.schedule.end = date.toUtc(); } - widget.item.saveDash(widget.item.id); + widget.item.saveDash(widget.item.id, context); } return date; }, @@ -400,19 +433,19 @@ class SchedulerFormsWidgetState extends State { child: Container( height: 40, margin: const EdgeInsets.only(top: 5), padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), child: TextFormField( key: formKeys[3], - enabled: !dash.scheduleActive && !readOnly, - initialValue: widget.item.scheduler["cron"], + enabled: !readOnly, + initialValue: widget.schedule.cron, onChanged: (value) { Future.delayed(const Duration(seconds: 100), () { - if (widget.item.scheduler["cron"] == value) { - widget.item.saveDash(widget.item.id); + if (widget.schedule.cron == value) { + widget.item.saveDash(widget.item.id, context); } }); - widget.item.scheduler["cron"] = value; + widget.schedule.cron = value; }, onSaved: (value) { if (value != null) { - widget.item.scheduler["cron"] = value; + widget.schedule.cron = value; } }, validator: (value) { @@ -450,55 +483,65 @@ class SchedulerFormsWidgetState extends State { Container( width: 200, height: 20, - decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))), + decoration: BoxDecoration(border: Border(bottom: BorderSide(color: + PermsService.getPerm(Perms.WORKFLOW_BOOKING)? Colors.grey : Colors.transparent, width: 1))), ), const SizedBox( width: 200, height: 10, ), - Tooltip( message: "check booking", - child: InkWell( mouseCursor: SystemMouseCursors.click, - onTap: () { - PermsService.getPerm(Perms.WORKFLOW_BOOKING) ? checkBooking(formKeys, null) : null; - }, child: Container( margin: const EdgeInsets.only(bottom: 5, left: 10, right: 10), - decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), - border: Border.all(color: widget.booking == null && !dash.scheduleActive ? ( + PermsService.getPerm(Perms.WORKFLOW_BOOKING)? Tooltip( message: "check booking", child: InkWell( mouseCursor: SystemMouseCursors.click, + onTap: () { PermsService.getPerm(Perms.WORKFLOW_BOOKING) ? checkBooking(formKeys, null) : null; + }, child: Container( margin: const EdgeInsets.only(bottom: 5, left: 10, right: 10), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), + border: Border.all(color: widget.booking == null ? ( PermsService.getPerm(Perms.WORKFLOW_BOOKING) && PermsService.getPerm(Perms.WORKFLOW_EDIT) ? Colors.black : Colors.grey) : ( - widget.booking == true || dash.scheduleActive ? Colors.green : redColor), width: 1)), + widget.booking == true ? Colors.green : redColor), width: 1)), width: 200, height: 30, - child: Icon( - Icons.verified_outlined, - color: widget.booking == null && !dash.scheduleActive ? Colors.black : (widget.booking == true || dash.scheduleActive ? Colors.green : redColor)), + child: Icon( Icons.verified_outlined, + color: widget.booking == null ? Colors.black : (widget.booking == true ? Colors.green : redColor)), )) - ), - Tooltip( message: dash.scheduleActive ? "unbook" : "book", - child: InkWell( mouseCursor: SystemMouseCursors.click, + ): Container(), + PermsService.getPerm(Perms.WORKFLOW_BOOKING) ? Tooltip( message: "book", child: InkWell( mouseCursor: SystemMouseCursors.click, onTap: () { - PermsService.getPerm(Perms.WORKFLOW_BOOKING) && PermsService.getPerm(Perms.WORKFLOW_EDIT) ? (dash.scheduleActive ? setState(() { save(formKeys); }) : checkBooking(formKeys, save)) : null; - }, child: Container( margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), + setState(() { save(formKeys); }); + }, child: Container( margin: const EdgeInsets.only(top: 5, bottom: 10, left: 10, right: 10), decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), - border: Border.all(color: dash.scheduleActive ? Colors.green : ( PermsService.getPerm(Perms.WORKFLOW_BOOKING) ?Colors.black : Colors.grey ))), + border: Border.all(color: dash.error != null ? Colors.red : ( PermsService.getPerm(Perms.WORKFLOW_BOOKING) ?(widget.valid ? Colors.green : Colors.black) : Colors.grey ))), width: 200, height: 30, - child: Icon( - dash.scheduleActive ? Icons.cancel_schedule_send : Icons.schedule_send, color: dash.scheduleActive ? Colors.green : Colors.black), + child: Icon(Icons.schedule_send, color: dash.error != null ? Colors.red : (widget.valid ? Colors.green : Colors.black)), )) - ), + ) : Container(), + Column( children: [ + Container( + height: 15, width: 200, + decoration: const BoxDecoration(border: Border(top: BorderSide(color: Colors.grey))), + ), + Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 10), + child:Text( textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, + style: const TextStyle(fontSize: 13, color: Colors.grey ), + "Was booked ${widget.scheduleBeforeCount} times.")), + Container( alignment: Alignment.center, padding: const EdgeInsets.only(left: 10, right: 10, bottom: 15), + child:Text( textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, + style: const TextStyle(fontSize: 13, color: Colors.grey ), + "Is booked ${widget.scheduleFutureCount} times.")), + ]), widget.item.info["shared"] != null && (widget.item.info["shared"] as List).isNotEmpty ? Column( children: [ Container( height: 30, width: 200, decoration: const BoxDecoration(border: Border(top: BorderSide(color: Colors.grey))), ), - Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 10), - child:Text( textAlign: TextAlign.center, overflow: TextOverflow.ellipsis, + Container( alignment: Alignment.center, + child:Text( overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 14, color: Colors.black, fontWeight: FontWeight.bold), - "Workflow is shared in ${(widget.item.info["shared"] as List).length} workspace(s)")), + "Is shared ${(widget.item.info["shared"] as List).length} time(s).")), ...(widget.item.info["shared"] as List).where( (e) => CollaborativeAreaLocal.getCollaborativeArea(e) != null ).map((e) { var sw = CollaborativeAreaLocal.getCollaborativeArea(e); return Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), child: Row( children: [ - const Padding(padding: EdgeInsets.only(right: 10), child: Icon(Icons.work, color: Colors.grey, size: 15)), + const Padding(padding: EdgeInsets.only( left: 10, right: 10), child: Icon(Icons.work, color: Colors.grey, size: 15)), Text(style: const TextStyle(fontSize: 12, color: Colors.grey), "Workspace: ${sw != null && sw.name != null ? "${sw.name!.substring(0, sw.name!.length > 15 ? 12 : sw.name!.length)}${sw.name!.length > 15 ? "..." : ""}" : ""}") ])); diff --git a/lib/widgets/forms/storage_forms.dart b/lib/widgets/forms/storage_forms.dart deleted file mode 100644 index 3fee6e6..0000000 --- a/lib/widgets/forms/storage_forms.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:oc_front/models/search.dart'; -import 'package:oc_front/widgets/forms/web_reference_forms.dart'; - -class StorageFormsWidget extends StatefulWidget { - StorageItem item; - String purpose = ""; - Function validate = () {}; - StorageFormsWidget ({ super.key, required this.item }); - @override StorageFormsWidgetState createState() => StorageFormsWidgetState(); -} -class StorageFormsWidgetState extends State { - @override Widget build(BuildContext context) { - return Column( children: [ - WebReferenceFormsWidget(item: widget.item), - ]); - } -} \ No newline at end of file diff --git a/lib/widgets/forms/storage_processing_link_forms.dart b/lib/widgets/forms/storage_processing_link_forms.dart new file mode 100644 index 0000000..34c9bcf --- /dev/null +++ b/lib/widgets/forms/storage_processing_link_forms.dart @@ -0,0 +1,154 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_advanced_switch/flutter_advanced_switch.dart'; +import 'package:oc_front/main.dart'; +import 'package:oc_front/models/resources/resources.dart'; +import 'package:flutter_flow_chart/flutter_flow_chart.dart'; +import 'package:oc_front/models/workflow.dart'; +import 'package:oc_front/widgets/inputs/sub_text_input.dart'; + +// ignore: must_be_immutable +class StorageProcessingLinkFormsWidget extends StatefulWidget { + Dashboard dash; + ArrowPainter item; + bool readOnly = false; + StorageProcessingLinkFormsWidget ({ super.key, required this.dash, required this.item, this.readOnly = false }); + @override StorageProcessingLinkFormsWidgetState createState() => StorageProcessingLinkFormsWidgetState(); +} + +class StorageProcessingLinkFormsWidgetState extends State { + + List getParams(String fromID, String toID) { + List arr = []; + var els = widget.dash.elements.where( (e) => fromID.contains(e.id) || toID.contains(e.id)); + for (var element in els) { + var g = GraphItem(); + g.fromDashboard(element.serialize()); + var e = g.getElement(); + if (e == null) { continue; } + if (e.getSelectedInstance() != null) { + for (var env in e.getSelectedInstance()!.env) { + if (env.name?.contains("LINK") ?? true) { continue; } + arr.add(env); + } + } + } + return arr.where( (e) => e.name != null && e.value != null).toList(); + } + + + @override Widget build(BuildContext context) { + List children = [ + Padding( padding: const EdgeInsets.only(top: 10), + child: Text("", + style: const TextStyle(fontSize: 13, fontWeight: FontWeight.bold), textAlign: TextAlign.center)), + ]; + var params = getParams(widget.item.fromID, widget.item.toID); + widget.item.env = params.map( (e) => e.serialize()).toList(); + for (var param in params) { + children.add(SubTextInputWidget(subkey: param.name ?? "", width: 180, empty: false, readOnly: true, + change: (value) {}, initialValue: param.value ?? "", copyLabel: true)); + } + children.add(Container(width: 200, padding: const EdgeInsets.only(top: 10, bottom: 10), + decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))))); + List inf = []; + int count = 0; + for(var info in widget.item.infos) { + count++; + inf.add(Padding( padding: EdgeInsets.only(top: 10, bottom: 5), + child : Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ + Padding(padding: EdgeInsets.only(left: 10, right: 10), child: Text("N°$count")), + Container(width: 140, decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1)))) + ]))); + for (var key in (info as Map).keys) { + if (info[key] is bool) { + inf.add(AdvancedSwitch( + width: 150.0, + height: 25.0, + initialValue: info[key] as bool? ?? false, + enabled: !widget.readOnly, + activeChild: Text(key, style: const TextStyle(color: Colors.white)), + inactiveChild: Text(key == "write" ? "read" : "no $key", style: const TextStyle(color: Colors.white)), + activeColor: Colors.green, + inactiveColor: redColor, + onChanged: (v) { + try { + info[key] = v; + Future.delayed(const Duration(seconds: 1), () { + for (var a in widget.dash.arrows) { + if (a.fromID == widget.item.fromID && a.toID == widget.item.toID) { + a.infos = widget.item.infos; + } + } + widget.dash.saveDash(widget.dash.id, context); + }); + } catch (e) { /* */ } + + }, + )); + } else if (info[key] is String?) { + inf.add(SubTextInputWidget(subkey: key, width: 180, empty: false, change: (v) { + try { + info[key] = v; + Future.delayed(const Duration(seconds: 1), () { + if (info[key] != v) { return; } + for (var a in widget.dash.arrows) { + if (a.fromID == widget.item.fromID && a.toID == widget.item.toID) { + a.infos = widget.item.infos; + } + } + widget.dash.saveDash(widget.dash.id, context); + }); + } catch (e) { + print(e); + } + + }, initialValue: "${info[key] ?? ""}", readOnly: false, noLabel: false)); + } + + + } + } + return SizedBox( height: getHeight(context) - 230, child: SingleChildScrollView( child: Column(children: [ + ...children, + Row( mainAxisAlignment: MainAxisAlignment.center, children: [ + InkWell( onTap: () { + widget.item.infos.add({ + "write": false, + "source": null, + "destination": null, + "filename": null, + }); + setState(() { + widget.dash.saveDash(widget.dash.id, context); + }); + }, child: Container( margin: const EdgeInsets.only(top: 10), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), + border: Border.all(color: Colors.grey, width: 1)), + width: 125, height: 30, + child: Row( mainAxisAlignment: MainAxisAlignment.center, + children: [ Padding( padding: EdgeInsets.only(right: 5), child: Icon(Icons.add, color: Colors.black,)), + Text("link infos", + style: TextStyle( color: Colors.black))]), + ), + ), + InkWell( onTap: () { + if (widget.item.infos.isEmpty) { return; } + setState(() { + widget.item.infos.removeLast(); + widget.dash.saveDash(widget.dash.id, context); + }); + }, child: + Container( margin: const EdgeInsets.only(left: 5, top: 10), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), + border: Border.all(color: widget.item.infos.isEmpty ? Colors.grey : Colors.black , width: 1)), + width: 50, height: 30, + child: Row( mainAxisAlignment: MainAxisAlignment.center, + children: [ Icon( Icons.delete, size: 18, + color: widget.item.infos.isEmpty ? Colors.grey : Colors.black ) ]), + ) + ), + ]), + ...inf + ] ) )); + } +} \ No newline at end of file diff --git a/lib/widgets/forms/sub_add_forms.dart b/lib/widgets/forms/sub_add_forms.dart new file mode 100644 index 0000000..47dbfcd --- /dev/null +++ b/lib/widgets/forms/sub_add_forms.dart @@ -0,0 +1,174 @@ + +import 'package:flutter/material.dart'; +import 'package:flutter_flow_chart/flutter_flow_chart.dart'; +import 'package:oc_front/models/resources/resources.dart'; +import 'package:oc_front/widgets/forms/sub_keys_forms.dart'; +import 'package:oc_front/widgets/inputs/sub_text_input.dart'; + +// ignore: must_be_immutable +class SubAddFormsWidget extends StatefulWidget { + bool readOnly; + SubMapFormsType type; + String elementID = ""; + AbstractItem item; + Dashboard dash; + bool empty = false; + List forms = []; + SubAddFormsWidget ({ super.key, required this.dash, this.readOnly = false, + this.empty = false, required this.item, required this.elementID, + required this.type }); + @override SubAddFormsWidgetState createState() => SubAddFormsWidgetState(); +} +class SubAddFormsWidgetState extends State { + Param? addedparam; + @override Widget build(BuildContext context) { + AbstractInstance instance = widget.item.getSelectedInstance()!; + var f = (widget.type == SubMapFormsType.INPUT ? instance.inputs : ( + widget.type == SubMapFormsType.OUTPUT ? instance.outputs : instance.env)).where( (e) => !e.readOnly).toList(); + widget.forms = f; + if (addedparam != null) { + widget.forms.add(addedparam!); + } + List children = []; + for (var param in widget.forms) { + children.add(Row( mainAxisAlignment: MainAxisAlignment.center, children: [ + SubTextInputWidget(subkey: "key", readOnly: widget.readOnly, + initialValue: param.name, width: 81, empty: widget.empty, + change: (value) { + setState(() { + param.name = value; + param.attr = value; + if (addedparam?.value != null && addedparam?.name != null) { + addedparam = null; + } + var sel = widget.item.getSelectedInstance(); + if (sel != null) { + if (widget.type == SubMapFormsType.INPUT) { sel.inputs = [ + ...sel.inputs.where( (e) => e.readOnly), + ...widget.forms.where((e) => e.name != null && e.value != null) + ]; + } else if (widget.type == SubMapFormsType.OUTPUT) { + sel.outputs = [ + ...sel.outputs.where( (e) => e.readOnly), + ...widget.forms.where((e) => e.name != null && e.value != null) + ]; + } else { + sel.env = [ + ...sel.env.where( (e) => e.readOnly), + ...widget.forms.where((e) => e.name != null && e.value != null) + ]; + } + } + Future.delayed(const Duration(milliseconds: 100), () { + if (param.name == value) { + widget.dash.saveDash(widget.dash.id, context); + } + }); + var el = widget.dash.getElement(widget.elementID); + el!.element = widget.item as dynamic; + setState(() {}); + }); + }), + const Padding(padding: EdgeInsets.only(left: 5, right: 5, top: 15), child: Text("=", textAlign: TextAlign.center,)), + SubTextInputWidget(subkey: "value", initialValue: param.value, width: 81, empty: widget.empty, + readOnly: widget.readOnly, change: (value) { + param.value = value; + if (addedparam?.value != null && addedparam?.name != null) { + addedparam = null; + } + var sel = widget.item.getSelectedInstance(); + if (sel != null) { + if (widget.type == SubMapFormsType.INPUT) { sel.inputs = [ + ...sel.inputs.where( (e) => e.readOnly), + ...widget.forms.where((e) => e.name != null && e.value != null) + ]; + } else if (widget.type == SubMapFormsType.OUTPUT) { + sel.outputs = [ + ...sel.outputs.where( (e) => e.readOnly), + ...widget.forms.where((e) => e.name != null && e.value != null) + ]; + } else { + sel.env = [ + ...sel.env.where( (e) => e.readOnly ), + ...widget.forms.where((e) => e.name != null && e.value != null) + ]; + } + } + var el = widget.dash.getElement(widget.elementID); + el!.element = widget.item as dynamic; + setState(() {}); + Future.delayed(const Duration(milliseconds: 100), () { + if (param.value == value) { + widget.dash.saveDash(widget.dash.id, context); + } + }); + }), + ])); + } + return Column( crossAxisAlignment: CrossAxisAlignment.center, children : [ + widget.readOnly ? Container() : Row( mainAxisAlignment: MainAxisAlignment.center, children: [ + InkWell( onTap: () { + if (widget.forms.isNotEmpty && (widget.forms[widget.forms.length - 1].name == null + || widget.forms[widget.forms.length - 1].value == null)) { return;} + widget.forms.add(Param(readOnly: false)); + addedparam = widget.forms.last; + var el = widget.dash.getElement(widget.elementID); + el!.element = widget.item as dynamic; + setState(() {}); + }, child: Container( margin: const EdgeInsets.only(top: 10), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), + border: Border.all(color: widget.forms.isNotEmpty && (widget.forms[widget.forms.length - 1].name == null + || widget.forms[widget.forms.length - 1].value == null) ? Colors.grey : Colors.grey, width: 1)), + width: 125, height: 30, + child: Row( mainAxisAlignment: MainAxisAlignment.center, + children: [ Padding( padding: EdgeInsets.only(right: 5), child: Icon(Icons.add, color: widget.forms.isNotEmpty && (widget.forms[widget.forms.length - 1].name == null + || widget.forms[widget.forms.length - 1].value == null) ? Colors.grey : Colors.black,)), + Text(widget.type == SubMapFormsType.ENV ? "env" : (widget.type == SubMapFormsType.INPUT ? "input" : "output"), + style: TextStyle( color: widget.forms.isNotEmpty && (widget.forms[widget.forms.length - 1].name == null + || widget.forms[widget.forms.length - 1].value == null) ? Colors.grey : Colors.black))]), + ), + ), + InkWell( onTap: () { + if (addedparam != null) { + addedparam = null; + return setState(() {}); + } + if (widget.forms.isEmpty) { return; } + widget.forms.sublist(0, widget.forms.length - 1); + var el = widget.dash.getElement(widget.elementID); + var sel = widget.item.getSelectedInstance(); + if (sel != null) { + widget.forms.removeLast(); + if (widget.type == SubMapFormsType.INPUT) { sel.inputs = [ + ...sel.inputs.where( (e) => e.readOnly), + ...widget.forms.where((e) => e.name != null && e.value != null) + ]; + } else if (widget.type == SubMapFormsType.OUTPUT) { + sel.outputs = [ + ...sel.outputs.where( (e) => e.readOnly), + ...widget.forms.where((e) => e.name != null && e.value != null) + ]; + } else { + sel.env = [ + ...sel.env.where( (e) => e.readOnly), + ...widget.forms.where((e) => e.name != null && e.value != null) + ]; + } + } + el!.element = widget.item as dynamic; + setState(() { widget.dash.saveDash(widget.dash.id, context); }); + }, child: + Container( margin: const EdgeInsets.only(left: 5, top: 10), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), + border: Border.all(color: widget.forms.isEmpty ? Colors.grey : Colors.black , width: 1)), + width: 50, height: 30, + child: Row( mainAxisAlignment: MainAxisAlignment.center, + children: [ Icon( Icons.delete, size: 18, + color: widget.forms.isEmpty ? Colors.grey : Colors.black ) ]), + ) + ), + ]), + ...children + ]); + } +} \ No newline at end of file diff --git a/lib/widgets/forms/sub_expose_forms.dart b/lib/widgets/forms/sub_expose_forms.dart index 19cffb4..d82b45a 100644 --- a/lib/widgets/forms/sub_expose_forms.dart +++ b/lib/widgets/forms/sub_expose_forms.dart @@ -1,9 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:oc_front/models/resources/processing.dart'; import 'package:flutter_flow_chart/flutter_flow_chart.dart'; -import 'package:oc_front/models/search.dart'; import 'package:oc_front/widgets/inputs/sub_text_input.dart'; +// ignore: must_be_immutable class SubExposeFormsWidget extends StatefulWidget { bool readOnly; Expose item; @@ -29,7 +30,7 @@ class SubExposeFormsWidgetState extends State { widget.item.port = int.parse(value); Future.delayed(const Duration(seconds: 2), () { if (widget.item.port == int.parse(value) && int.parse(value) != 0) { - widget.dash.saveDash(widget.dash.id); + widget.dash.saveDash(widget.dash.id, context); } }); } catch (e) { widget.item.port = null; } @@ -44,7 +45,7 @@ class SubExposeFormsWidgetState extends State { widget.item.PAT = int.parse(value); Future.delayed(const Duration(seconds: 2), () { if (widget.item.PAT == int.parse(value) && int.parse(value) != 0) { - widget.dash.saveDash(widget.dash.id); + widget.dash.saveDash(widget.dash.id, context); } }); } catch (e) { widget.item.PAT = null; } @@ -57,7 +58,7 @@ class SubExposeFormsWidgetState extends State { try { widget.item.path = value; Future.delayed(const Duration(seconds: 2), () { - if (widget.item.path == value) { widget.dash.saveDash(widget.dash.id); } + if (widget.item.path == value) { widget.dash.saveDash(widget.dash.id, context); } }); } catch (e) { widget.item.path = null; } var el = widget.dash.getElement(widget.elementID); diff --git a/lib/widgets/forms/sub_keys_forms.dart b/lib/widgets/forms/sub_keys_forms.dart index 20e7ab2..ffb935d 100644 --- a/lib/widgets/forms/sub_keys_forms.dart +++ b/lib/widgets/forms/sub_keys_forms.dart @@ -1,62 +1,97 @@ import 'package:flutter/material.dart'; +import 'package:flutter_advanced_switch/flutter_advanced_switch.dart'; import 'package:flutter_flow_chart/flutter_flow_chart.dart'; +import 'package:oc_front/main.dart'; +import 'package:oc_front/models/resources/resources.dart'; import 'package:oc_front/models/workflow.dart'; +import 'package:oc_front/widgets/forms/sub_add_forms.dart'; import 'package:oc_front/widgets/inputs/sub_text_input.dart'; - +enum SubMapFormsType { + ENV, + INPUT, + OUTPUT +} +// ignore: must_be_immutable class SubKeysMapFormsWidget extends StatefulWidget { bool readOnly = false; - FlowData item; + AbstractItem item; Dashboard dash; - String varKey = ""; bool empty = false; - bool isInput = true; + SubMapFormsType type; String elementID = ""; - String categoryKey = ""; - List graphItems = []; - SubKeysMapFormsWidget({ super.key, required this.dash, required this.isInput, this.readOnly = false, - this.empty = false, required this.item, required this.elementID, required this.graphItems, - required this.categoryKey, required this.varKey }); + SubKeysMapFormsWidget({ super.key, required this.dash, required this.type, this.readOnly = false, + this.empty = false, required this.item, required this.elementID }); @override SubKeysMapFormsWidgetState createState() => SubKeysMapFormsWidgetState(); } class SubKeysMapFormsWidgetState extends State { + bool _save = false; + + List getParams(String fromID, String toID) { + List arr = []; + var els = widget.dash.elements.where( (e) => fromID.contains(e.id) || toID.contains(e.id)); + for (var element in els) { + var g = GraphItem(); + g.fromDashboard(element.serialize()); + var e = g.getElement(); + if (e != null && e.getSelectedInstance() != null) { + arr = [...arr, ...e.getSelectedInstance()!.env]; + } + } + return arr; + } + List getInstanceInOutput(AbstractItem? item, SubMapFormsType type) { + List children = []; + if (item == null || item.getSelectedInstance() == null) { + return []; + } + AbstractInstance instance = item.getSelectedInstance()!; + List params = widget.type == SubMapFormsType.INPUT ? instance.inputs : ( widget.type == SubMapFormsType.OUTPUT ? instance.outputs : instance.env); + for ( var param in params) { + if (!param.readOnly) { continue; } + dynamic env; + if (param.value == null && param.attr != null) { + var s = item.serialize(); + s.addAll(item.getSelectedInstance()?.serialize() ?? {}); + env = s[param.attr!]; + } else { env = param.value; } + _save = true; + if (env is bool) { + var ctrl = ValueNotifier(env); + children.add(AdvancedSwitch( + width: 150.0, + height: 25.0, + controller: ctrl, + enabled: false, + activeChild: Text(param.name!, style: const TextStyle(color: Colors.white)), + inactiveChild: Text("no ${param.name!}", style: const TextStyle(color: Colors.white)), + activeColor: Colors.green, + inactiveColor: redColor, + onChanged: (value) {}, + )); + } else { + children.add(SubTextInputWidget( subkey: param.name!, width: 180, empty: false, change: (value) { }, + initialValue: env, readOnly: true, noLabel: false, copyLabel: true )); + } + } + return children; + } @override Widget build(BuildContext context) { List children = []; - - bool save = false; - for (var graphItem in widget.graphItems) { - int count = 0; - var el = graphItem.getElement(); - if (el == null || el.model == null) { continue; } - for ( var r in el.model!.refs.keys) { - var env = widget.item.getVariable(["container", "env"], widget.item.serialize()); - if (env == null || env is Map) { continue; } - var n = "${el.topic.toUpperCase()}_${el.getName().toUpperCase().replaceAll(" ", "_")}_${r.toUpperCase()}_$count"; - if (env[n] == null) { - save = true; - } - env[n]= "{{ ${ widget.isInput ? "in" : "out" }_${graphItem.id}_$r }}"; - widget.item.setVariable(["container", "env"], env, el.serialize()); - children.add( Padding(padding: const EdgeInsets.only(bottom: 10), - child: SubTextInputWidget(subkey: n, width: 180, empty: false, change: (value) {}, - initialValue: n, readOnly: true, noLabel: true))); - count++; - } + var newwidget = getInstanceInOutput(widget.item, widget.type); + children.add(Column( children : [ + Padding( padding: const EdgeInsets.only(top: 10), + child: Text("<${widget.type == SubMapFormsType.INPUT ? "INPUT" : (widget.type == SubMapFormsType.OUTPUT ? "OUTPUT" : "")} ENV VARIABLES>", + style: const TextStyle(fontSize: 13, fontWeight: FontWeight.bold), textAlign: TextAlign.center)), + ...newwidget, + SubAddFormsWidget(dash: widget.dash, item: widget.item, elementID: widget.elementID, type: widget.type), + Container(width: 200, padding: const EdgeInsets.only(top: 10, bottom: 10), + decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1)))), + ])); + if (_save) { + widget.dash.saveDash(widget.dash.id, context); } - if (save) { - widget.dash.saveDash(widget.dash.id); - } - if (children.isEmpty) { - return Container(); - } - return Column( children : [ - Container(width: 200, padding: const EdgeInsets.only(top: 10, bottom: 10), - decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1)))), - Padding( padding: const EdgeInsets.only(top: 10), - child: Text("<${widget.isInput ? "INPUT ENV VARIABLE" : "OUTPUT ENV VARIABLE"}>", style: const TextStyle(fontSize: 13, fontWeight: FontWeight.bold), - textAlign: TextAlign.center)), - Column( children: children), - ]); + return Column( children : children ); } } \ No newline at end of file diff --git a/lib/widgets/forms/sub_map_forms.dart b/lib/widgets/forms/sub_map_forms.dart deleted file mode 100644 index 134e345..0000000 --- a/lib/widgets/forms/sub_map_forms.dart +++ /dev/null @@ -1,115 +0,0 @@ - -import 'package:flutter/material.dart'; -import 'package:flutter_flow_chart/flutter_flow_chart.dart'; -import 'package:oc_front/widgets/inputs/sub_text_input.dart'; - -class MapForm { - String key = ""; - String value = ""; - MapForm({ required this.key, required this.value }); -} - -class SubMapFormsWidget extends StatefulWidget { - bool readOnly; - String categoryKey = ""; - String varKey = ""; - String elementID = ""; - FlowData item; - Dashboard dash; - bool empty = false; - List forms = []; - SubMapFormsWidget ({ super.key, required this.dash, this.readOnly = false, - this.empty = false, required this.item, required this.elementID, - required this.categoryKey, required this.varKey }); - @override SubMapFormsWidgetState createState() => SubMapFormsWidgetState(); -} -class SubMapFormsWidgetState extends State { - - Map toMap() { - Map m = {}; - for (var form in widget.forms) { - m[form.key] = form.value; - } - return m; - } - - @override Widget build(BuildContext context) { - Map? m = widget.item.getVariable([widget.categoryKey, widget.varKey], widget.item.serialize()); - var l = [widget.categoryKey, widget.varKey]; - List children = []; - List empty = []; - widget.forms = []; - var i = 0; - for (var key in (m?.keys.toList() ?? empty)) { - if (((m![key] as String?)?.contains('{{') ?? false)) { - continue; - } - widget.forms.add(MapForm(key: key, value: m[key])); - children.add(Row( children: [ - SubTextInputWidget(subkey: "key", readOnly: widget.readOnly, - initialValue: key, width: 77.5, empty: widget.empty, - change: (value) { - setState(() { - widget.forms[i].key = value; - Future.delayed(const Duration(seconds: 2), () { - widget.dash.saveDash(widget.dash.id); - }); - var el = widget.dash.getElement(widget.elementID); - widget.item = widget.item.deserialize(widget.item.setVariable(l, toMap(), widget.item.serialize())) as dynamic; - el!.element = widget.item as dynamic; - }); - }), - const Padding(padding: EdgeInsets.only(left: 5, right: 5, top: 15), child: Text("=", textAlign: TextAlign.center,)), - SubTextInputWidget(subkey: "value", initialValue: widget.forms[i].value, width: 77.5, empty: widget.empty, - readOnly: widget.readOnly, change: (value) { - Future.delayed(const Duration(seconds: 2), () { - widget.dash.saveDash(widget.dash.id); - }); - widget.forms[i].value = value; - var el = widget.dash.getElement(widget.elementID); - widget.item = widget.item.deserialize( - widget.item.setVariable(l, toMap(), widget.item.serialize())) as dynamic; - el!.element = widget.item as dynamic; - }), - ])); - i++; - } - return Column( children : [ - Container(width: 200, padding: const EdgeInsets.only(top: 10), - decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),), - widget.readOnly ? Container() : Row( children: [ - InkWell( onTap: () { - widget.forms.add(MapForm(key: "", value: "")); - var el = widget.dash.getElement(widget.elementID); - widget.item = widget.item.deserialize( - widget.item.setVariable(l, toMap(), widget.item.serialize())) as dynamic; - el!.element = widget.item as dynamic; - setState(() {}); - }, child: Container( margin: const EdgeInsets.only(top: 10), - decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.grey, width: 1)), - width: 125, height: 30, - child: Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ const Padding( padding: EdgeInsets.only(right: 5), child: Icon(Icons.add)), Text("add ${widget.varKey} vars")]), - ), - ), - InkWell( onTap: () { - if (widget.forms.isEmpty) { return;} - widget.forms.sublist(0, widget.forms.length - 1); - widget.item = widget.item.deserialize( - widget.item.setVariable(l, toMap(), widget.item.serialize())) as dynamic; - var el = widget.dash.getElement(widget.elementID); - el!.element = widget.item as dynamic; - setState(() { widget.dash.saveDash(widget.dash.id); }); - }, child: - Container( margin: const EdgeInsets.only(left: 5, top: 10), - decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.grey, width: 1)), - width: 45, height: 30, - child: const Row( mainAxisAlignment: MainAxisAlignment.center, - children: [ Icon( Icons.delete, color: Colors.black ) ]), - ) - ), - ]), - ...children - ]); - } -} \ No newline at end of file diff --git a/lib/widgets/forms/web_reference_forms.dart b/lib/widgets/forms/web_reference_forms.dart deleted file mode 100644 index 6c2dfab..0000000 --- a/lib/widgets/forms/web_reference_forms.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:oc_front/widgets/inputs/sub_text_input.dart'; - -class WebReferenceFormsWidget extends StatefulWidget { - dynamic item; - WebReferenceFormsWidget ({ super.key, required this.item }); - @override WebReferenceFormsWidgetState createState() => WebReferenceFormsWidgetState(); -} -class WebReferenceFormsWidgetState extends State { - @override Widget build(BuildContext context) { - return Column( children: [ - SubTextInputWidget(subkey: "path", width: 180, empty: false, change: (value) { - widget.item.path = value.split(","); - }, initialValue: widget.item.path, readOnly: true,), - SubTextInputWidget(subkey: "protocol", width: 180, empty: false, change: (value) { - widget.item.protocol = value.split(","); - }, initialValue: widget.item.protocol, readOnly: true,), - SubTextInputWidget(subkey: "type", width: 180, empty: false, change: (value) { - widget.item.type = value.split(","); - }, initialValue: widget.item.type, readOnly: true,), - ]); - } -} \ No newline at end of file diff --git a/lib/widgets/inputs/shallow_dropdown_input.dart b/lib/widgets/inputs/shallow_dropdown_input.dart index 8b37ef6..f4b47e3 100644 --- a/lib/widgets/inputs/shallow_dropdown_input.dart +++ b/lib/widgets/inputs/shallow_dropdown_input.dart @@ -5,6 +5,7 @@ import 'package:oc_front/pages/shared.dart'; class ShallowDropdownInputWidget extends StatefulWidget { double? width; + double? height; CollaborativeAreaType type = CollaborativeAreaType.workspace; Future> Function()? all; Future Function(String)? load; @@ -17,7 +18,7 @@ class ShallowDropdownInputWidget extends StatefulWidget { Widget? prefixIcon; IconData? iconLoad; IconData? iconRemove; - + String? label; String? hint; String? tooltipLoad; @@ -30,8 +31,8 @@ class ShallowDropdownInputWidget extends StatefulWidget { bool deletion = false; ShallowDropdownInputWidget ({ Key? key, this.width, this.current, required this.all, this.prefixIcon, - this.iconLoad, this.iconRemove, this.hint, this.filled, this.hintColor, this.color, - this.tooltipLoad, this.tooltipRemove, this.deletion = false, this.maptoDropdown, + this.iconLoad, this.iconRemove, this.hint, this.filled, this.hintColor, this.color, this.height, + this.tooltipLoad, this.tooltipRemove, this.deletion = false, this.maptoDropdown, this.label, required this.type, this.canLoad, this.canRemove, this.load, this.remove, this.change }): super(key: key); @override ShallowDropdownInputWidgetState createState() => ShallowDropdownInputWidgetState(); } @@ -54,11 +55,12 @@ class ShallowDropdownInputWidgetState extends State data: Theme.of(context).copyWith( canvasColor: widget.filled ??Colors.white, ), - child: Container( height: 50, width: (widget.width ?? getMainWidth(context)) - (widget.load == null ? 0 : 50) - (widget.remove == null ? 0 : 50), + child: Container( height: widget.height ?? 50, + width: (widget.width ?? getMainWidth(context)) - (widget.load == null ? 0 : 50) - (widget.remove == null ? 0 : 50), decoration: const BoxDecoration( color: Colors.white, ), - child: DropdownButtonFormField( + child: Center(child: DropdownButtonFormField( onChanged: (value) { setState(() { widget.current = value; @@ -78,6 +80,8 @@ class ShallowDropdownInputWidgetState extends State ), decoration: InputDecoration( filled: true, + label: widget.label == null ? null : Text(widget.label!), + alignLabelWithHint: false, prefixIconColor: Colors.grey, prefixIcon: widget.prefixIcon, suffixIconColor: widget.hintColor ?? Colors.grey , @@ -88,13 +92,14 @@ class ShallowDropdownInputWidgetState extends State contentPadding: EdgeInsets.only(left: (widget.width ?? 400) < 200 ? 0 : 30, right: (widget.width ?? 400) < 200 ? 0 : 30, top: 18, bottom: 18), ), items: items, - )))), + ))))), widget.load == null ? Container() : Tooltip( message: widget.tooltipLoad ?? "load $t", child:InkWell( mouseCursor: SystemMouseCursors.click, onTap: () async { - if (widget.canLoad == null || !widget.canLoad!(widget.current) || widget.load == null || widget.current == null) { + if (widget.canLoad == null || !widget.canLoad!(widget.current) + || widget.load == null || widget.current == null) { return; } await widget.load!(widget.current!); diff --git a/lib/widgets/inputs/shallow_text_input.dart b/lib/widgets/inputs/shallow_text_input.dart index c5f712d..a5fc360 100644 --- a/lib/widgets/inputs/shallow_text_input.dart +++ b/lib/widgets/inputs/shallow_text_input.dart @@ -54,6 +54,8 @@ class ShallowTextInputWidget extends StatefulWidget { } } class ShallowTextInputWidgetState extends State { + TextEditingController ctrl = TextEditingController(); + bool validForms() { for (var form in widget.forms) { if (!form.validate()) { @@ -65,6 +67,7 @@ class ShallowTextInputWidgetState extends State { @override Widget build(BuildContext context) { var t = widget.type == CollaborativeAreaType.workspace ? "workspace" : (widget.type == CollaborativeAreaType.workflow ? "workflow" : "peer"); + ctrl.text = widget.current ?? ""; return Row( mainAxisAlignment: widget.alignment, children: [ Tooltip( message: widget.hint ?? "current $t", child: Theme( @@ -83,7 +86,7 @@ class ShallowTextInputWidgetState extends State { } }); }, - initialValue: widget.current, + controller: ctrl, style: TextStyle(color: widget.color ?? Colors.black, fontSize: 15), decoration: InputDecoration( filled: true, diff --git a/lib/widgets/inputs/sub_dropdown_input .dart b/lib/widgets/inputs/sub_dropdown_input .dart index 6b7b73b..df46433 100644 --- a/lib/widgets/inputs/sub_dropdown_input .dart +++ b/lib/widgets/inputs/sub_dropdown_input .dart @@ -4,10 +4,11 @@ class SubDropdownInputWidget extends StatefulWidget { String subkey; double width; bool empty; + String? initialValue; List> dropdownMenuEntries = []; void Function(String?)? change = (value) {}; - SubDropdownInputWidget ({ Key? key, required this.dropdownMenuEntries, - required this.subkey, required this.width, required this.empty, required this.change }): super(key: key); + SubDropdownInputWidget ({ super.key, required this.dropdownMenuEntries, this.initialValue, + required this.subkey, required this.width, required this.empty, required this.change }); @override SubDropdownInputWidgetState createState() => SubDropdownInputWidgetState(); } class SubDropdownInputWidgetState extends State { @@ -17,9 +18,11 @@ class SubDropdownInputWidgetState extends State { child: Container( margin: EdgeInsets.only(top: widget.empty ? 0 : 15), width: widget.width, height: 30, child: DropdownButtonFormField( + isExpanded: true, items: widget.dropdownMenuEntries, + value: widget.initialValue, onChanged: widget.change, - style: const TextStyle(fontSize: 12), + style: const TextStyle(fontSize: 12,color: Colors.black, overflow: TextOverflow.ellipsis), decoration: InputDecoration( hintText: "select ${widget.subkey}...", fillColor: Colors.white, diff --git a/lib/widgets/inputs/sub_text_input.dart b/lib/widgets/inputs/sub_text_input.dart index fc325aa..994b2a9 100644 --- a/lib/widgets/inputs/sub_text_input.dart +++ b/lib/widgets/inputs/sub_text_input.dart @@ -10,9 +10,10 @@ class SubTextInputWidget extends StatefulWidget { bool empty; bool noLabel; bool readOnly = false; + bool copyLabel = false; void Function(String) change = (value) {}; SubTextInputWidget ({ Key? key, - required this.subkey, this.readOnly = false, this.noLabel = false, + required this.subkey, this.readOnly = false, this.noLabel = false, this.copyLabel = false, this.initialValue, required this.width, required this.empty, required this.change }): super(key: key); @override SubTextInputWidgetState createState() => SubTextInputWidgetState(); @@ -47,7 +48,7 @@ class SubTextInputWidgetState extends State { ), ))), widget.readOnly ? InkWell( onTap: () { - Clipboard.setData(ClipboardData(text: widget.initialValue!)); + Clipboard.setData(ClipboardData(text: widget.copyLabel ? "\$${widget.subkey}" : widget.initialValue!)); showAlertBanner(context, () {}, const InfoAlertBannerChild(text: "successfully add to clipboard"), // <-- Put any widget here you want! alertBannerLocation: AlertBannerLocation.bottom,); }, child: Container( margin: EdgeInsets.only(left: 5, top: widget.empty ? 0 : 15), diff --git a/lib/widgets/items/infos.dart b/lib/widgets/items/infos.dart new file mode 100644 index 0000000..d9906d9 --- /dev/null +++ b/lib/widgets/items/infos.dart @@ -0,0 +1,24 @@ + +import 'package:flutter/material.dart'; +import 'package:oc_front/models/resources/resources.dart'; + +// ignore: must_be_immutable +class InfosWidget extends StatefulWidget { + AbstractItem item; + InfosWidget ({ super.key, required this.item }); + @override InfosWidgetState createState() => InfosWidgetState(); +} +class InfosWidgetState extends State { + @override Widget build(BuildContext context) { + List children = []; + var obj = widget.item.infos(); + for (var key in obj.keys) { + children.add( + Padding(padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 100), + child: Text("$key : ${obj[key] ?? "no $key"}", + style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600))), + ); + } + return Wrap( children: children); + } +} \ No newline at end of file diff --git a/lib/widgets/items/item.dart b/lib/widgets/items/item.dart index 49f6bd8..688afae 100644 --- a/lib/widgets/items/item.dart +++ b/lib/widgets/items/item.dart @@ -1,9 +1,12 @@ - -import 'package:flutter/material.dart'; import 'package:oc_front/main.dart'; -import 'package:oc_front/models/search.dart'; -import 'package:oc_front/widgets/items/items_details/data_item.dart'; +import 'package:flutter/material.dart'; +import 'package:oc_front/models/resources/resources.dart'; +import 'package:oc_front/models/response.dart'; +import 'package:oc_front/pages/shared.dart'; +import 'package:oc_front/widgets/inputs/shallow_dropdown_input.dart'; +import 'package:oc_front/widgets/inputs/sub_dropdown_input%20.dart'; +// ignore: must_be_immutable class ItemWidget extends StatefulWidget { AbstractItem item; ItemWidget ({ super.key, required this.item }); @@ -11,28 +14,88 @@ class ItemWidget extends StatefulWidget { } class ItemWidgetState extends State { @override Widget build(BuildContext context) { - Widget w = Container(); - /* if (isData(widget.item.topic)) { w = DataItemWidget(item: widget.item as DataItem); } - else if (isComputing(widget.item.topic)) { w = DataItemWidget(item: widget.item as DataItem); } - else if (isCompute(widget.item.topic)) { w = DataItemWidget(item: widget.item as DataItem); } - else if (isStorage(widget.item.topic)) { w = DataItemWidget(item: widget.item as DataItem); } */ - - return Container( - height: getHeight(context) - 300, + List widgets = [ + Container( margin: EdgeInsets.only(bottom: 20), + decoration: BoxDecoration(border: Border(bottom: BorderSide(color: midColor))), + width: getMainWidth(context) / 2, + child: Center(child: Padding( padding: EdgeInsets.only(bottom: 20), + child: Text("RESOURCE INFORMATIONS", style: TextStyle(fontSize: 18, color: Colors.grey, fontWeight: FontWeight.w500))))) + ]; + var infos = widget.item.infos(); + var count = 0; + for (var info in infos.keys) { + count++; + widgets.add(Padding( padding: EdgeInsets.symmetric(vertical: 5), child : Row(children: [ + Padding( padding: EdgeInsets.only(left: 50, right: 10), child : Text("${info.toUpperCase().replaceAll("_", " ")} :", style: TextStyle(fontSize: 15, color: Colors.grey))), + Text("${infos[info] is bool ? (infos[info] == true ? "yes" : "no") : infos[info] ?? "unknown"}", + overflow: TextOverflow.ellipsis, + style: TextStyle(fontSize: 15, color: Colors.black, fontWeight: FontWeight.w500)) + ]))); + } + if (count == 0 ) { + widgets.add(Center(child: Padding( padding: EdgeInsets.symmetric(vertical: 5), child : Row(children: [ + Padding( padding: EdgeInsets.only(left: 50, right: 10), child : Text("NO INFORMATION", style: TextStyle(fontSize: 15, color: Colors.grey))), + ])))); + } + List widgetsInstance = []; + List dpItems = []; + for (var (i, instance) in widget.item.instances.indexed) { + dpItems.add(Shallow(id: "$i", name: instance.name ?? "")); + } + if (dpItems.isNotEmpty) { + widgetsInstance.add(Center( child: Padding(padding: EdgeInsets.only(bottom: 15), child: + ShallowDropdownInputWidget( all: () async => dpItems, width: (getWidth(context) / 2) - 25, + label: "instances", type: CollaborativeAreaType.resource, height: 65, + current: "${widget.item.selectedInstance}", change: (value) { + if (value != null) { setState(() { widget.item.selectedInstance = int.parse(value); }); } + }, + )) + )); + } + if (widget.item.instances.length > widget.item.selectedInstance) { + var instance = widget.item.instances[widget.item.selectedInstance]; + widgetsInstance.add(Container(height: 20, width: getWidth(context) / 2,)); + var count = 0; + for (var info in instance.infos().keys) { + if (instance.infos()[info] == null || instance.infos()[info] is List || instance.infos()[info] is Map) { continue; } + count++; + widgetsInstance.add(Center(child: Padding( padding: EdgeInsets.symmetric(vertical: 5), child : Row(children: [ + Padding( padding: EdgeInsets.only(left: 50, right: 10), child : Text("${info.toUpperCase().replaceAll("_", " ")} :", style: TextStyle(fontSize: 15, color: Colors.grey))), + Text("${instance.infos()[info] is bool ? (instance.infos()[info] == true ? "yes" : "no") : instance.infos()[info] ?? "unknown"}", + overflow: TextOverflow.ellipsis, + style: TextStyle(fontSize: 15, color: Colors.black, fontWeight: FontWeight.w500)) + ])))); + } + if (count == 0 ) { + widgetsInstance.add(Padding( padding: EdgeInsets.symmetric(vertical: 5), child : Row(children: [ + Padding( padding: EdgeInsets.only(left: 50, right: 10), child : Text("NO INSTANCE INFORMATION", style: TextStyle(fontSize: 15, color: Colors.grey))), + ]))); + } + } + Widget w = Column( mainAxisSize: MainAxisSize.max, children: widgets ); + Widget w2 = Column( mainAxisSize: MainAxisSize.max, children: widgetsInstance ); + return SizedBox( + height: getHeight(context) - 200, child: SingleChildScrollView( - child: Column( children: [ + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ widget.item.description == null ? Container() : Container( width: getMainWidth(context), alignment: Alignment.center, - decoration: BoxDecoration(border: Border(bottom: BorderSide(color: midColor))), - padding: const EdgeInsets.all(30), - child: Text(widget.item.description!, + height: 100, + decoration: BoxDecoration( + color: Colors.white, + border: Border(bottom: BorderSide(color: midColor))), + padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 50), + child: Text(widget.item.description!.length > 350 ? "${widget.item.description!.substring(0, 347)}..." : widget.item.description!, style: TextStyle(fontSize: 15, color: Colors.grey, fontWeight: FontWeight.w500))), - Container(padding: const EdgeInsets.all(30), - color: midColor, - width: getMainWidth(context) / 2, - child: w - ) + Row( children: [ + Container(padding: const EdgeInsets.symmetric(vertical: 20), + height: getHeight(context) - 300, + decoration: BoxDecoration(border: Border(right: BorderSide(color: midColor))), + alignment: Alignment.topLeft, width: getMainWidth(context) / 2, child: w), + Container(height: getHeight(context) - 300, + alignment: Alignment.topRight, width: getMainWidth(context) / 2, child: w2) + ]) ] ) ) diff --git a/lib/widgets/items/item_row.dart b/lib/widgets/items/item_row.dart index 95984cd..dee40f2 100644 --- a/lib/widgets/items/item_row.dart +++ b/lib/widgets/items/item_row.dart @@ -1,9 +1,8 @@ -import 'dart:convert'; -import 'package:flutter/material.dart'; import 'package:oc_front/main.dart'; -import 'package:oc_front/models/search.dart'; -import 'package:oc_front/core/models/workspace_local.dart'; +import 'package:flutter/material.dart'; import 'package:oc_front/core/services/router.dart'; +import 'package:oc_front/models/resources/resources.dart'; +import 'package:oc_front/core/models/workspace_local.dart'; const List> _empty = []; // ignore: must_be_immutable @@ -38,7 +37,7 @@ class ItemRowWidgetState extends State { constraints: BoxConstraints(maxWidth: imageSize, minWidth: imageSize), child: image ?? Image.network('https://get-picto.com/wp-content/uploads/2024/01/logo-instagram-png.webp', height: imageSize, width: imageSize)), - Container( + SizedBox( width: widget.low ? widget.contextWidth - 20 : widget.contextWidth - (imageSize + 20) - endWidth, child: Padding(padding: widget.contextWidth != getMainWidth(context) ? const EdgeInsets.symmetric(horizontal: 10) : const EdgeInsets.symmetric(horizontal: 20), @@ -48,10 +47,7 @@ class ItemRowWidgetState extends State { widget.low ? Container() : Container(padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10), margin: const EdgeInsets.only(right: 20), decoration: BoxDecoration( - color: isData(widget.item.topic) ? Colors.blue : - isComputing(widget.item.topic) ? Colors.green : - isCompute(widget.item.topic) ? Colors.orange : - isStorage(widget.item.topic) ? redColor : Colors.grey, + color: getColor(widget.item.topic), borderRadius: BorderRadius.circular(4), ), child: Text( getMainWidth(context) < 600 ? "" : widget.item.topic.toString(), @@ -61,13 +57,13 @@ class ItemRowWidgetState extends State { style: TextStyle(fontSize: widget.low ? 14 : 20, overflow: TextOverflow.ellipsis, fontWeight: FontWeight.w600, color: Color(0xFFF67C0B9))), ) ]), - Text( "From ${widget.item.owner ?? "unknown owner"}", + widget.item.owners.isEmpty ? Container() : Text( "From ${widget.item.owners.map( (e) => e.name).join(", ")}", style: const TextStyle(fontSize: 14, color: Colors.grey, overflow: TextOverflow.ellipsis)), Text(widget.item.shortDescription ?? "", style: const TextStyle(fontSize: 12, overflow: TextOverflow.ellipsis)), ],) ) ), - widget.low ? Container() : Container( + widget.low ? Container() : SizedBox( width: endWidth, child: Row( mainAxisAlignment: MainAxisAlignment.center, @@ -91,7 +87,8 @@ class ItemRowWidgetState extends State { borderRadius: BorderRadius.circular(4), ), child: Icon(WorkspaceLocal.hasItem(widget.item) ? Icons.remove_shopping_cart : Icons.add_shopping_cart, - color: Colors.white, size: 20 )) + color: Colors.white, size: 20 ) + ) ), ...(ratio > 1 ? [Padding( padding: const EdgeInsets.only(left: 20), child: InkWell( diff --git a/lib/widgets/items/items_details/data_item.dart b/lib/widgets/items/items_details/data_item.dart deleted file mode 100644 index 762531f..0000000 --- a/lib/widgets/items/items_details/data_item.dart +++ /dev/null @@ -1,24 +0,0 @@ - -import 'package:flutter/material.dart'; -import 'package:oc_front/models/search.dart'; - -class DataItemWidget extends StatefulWidget { - DataItem item; - DataItemWidget ({ super.key, required this.item }); - @override DataItemWidgetState createState() => DataItemWidgetState(); -} -class DataItemWidgetState extends State { - @override Widget build(BuildContext context) { - return Wrap( children: [ - Padding(padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 100), - child: Text("type : ${widget.item.type ?? "unknown type"}", - style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600))), - Padding(padding: const EdgeInsets.symmetric(horizontal: 100, vertical: 20), - child: Text("protocol : ${widget.item.protocols.isEmpty ? "no protocol founded" : widget.item.protocols.join(",")}", - style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600))), - Padding(padding: const EdgeInsets.symmetric(horizontal: 100, vertical: 20), - child: Text("ex : ${widget.item.exemple ?? "no example"}", - style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600))), - ]); - } -} \ No newline at end of file diff --git a/lib/widgets/logs.dart b/lib/widgets/logs.dart index e9c7201..b2ef98c 100644 --- a/lib/widgets/logs.dart +++ b/lib/widgets/logs.dart @@ -1,24 +1,35 @@ import 'package:alert_banner/exports.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:json_string/json_string.dart'; -import 'package:oc_front/core/services/specialized_services/logs_service.dart'; import 'package:oc_front/main.dart'; import 'package:oc_front/models/logs.dart'; import 'package:oc_front/models/workflow.dart'; import 'package:oc_front/widgets/dialog/alert.dart'; +import 'package:json_string/json_string.dart'; +import 'package:oc_front/core/services/specialized_services/logs_service.dart'; +bool isLoading = true; +Map valid = {}; class LogsWidget extends StatefulWidget { String? level; String search = ""; - WorkflowExecution? exec; + List logs = []; LogsWidget ({ Key? key, this.search = "", this.level, this.exec }): super(key: key); @override LogsWidgetState createState() => LogsWidgetState(); } class LogsWidgetState extends State { @override Widget build(BuildContext context) { + if (!isLoading) { + isLoading = true; + Future.delayed(const Duration(milliseconds: 100), () { + try { setState(() { }); + } catch (e) { /**/ } + }); + return Container( height: getMainHeight(context) - 100, + child: Center( child: CircularProgressIndicator()) ); + } if (widget.exec == null) { return Container(); } else { @@ -26,7 +37,7 @@ class LogsWidgetState extends State { String end = ""; try { if (widget.exec!.endDate != null && widget.exec!.endDate != "") { - var startD = DateTime.parse(widget.exec!.executionData!); + var startD = DateTime.parse(widget.exec!.startDate!); var endD = DateTime.parse(widget.exec!.endDate!); var diff = endD.difference(startD); if (diff.inDays < 30) { @@ -38,20 +49,22 @@ class LogsWidgetState extends State { end = (startD.add( const Duration(days: 29)).microsecondsSinceEpoch).toString(); } } else { - start = (DateTime.parse(widget.exec!.executionData!).subtract( const Duration(days: 14)).microsecondsSinceEpoch).toString(); - end = (DateTime.parse(widget.exec!.executionData!).add( const Duration(days: 14)).microsecondsSinceEpoch).toString(); + start = (DateTime.parse(widget.exec!.startDate!).subtract( const Duration(days: 14)).microsecondsSinceEpoch).toString(); + end = (DateTime.parse(widget.exec!.startDate!).add( const Duration(days: 14)).microsecondsSinceEpoch).toString(); } } catch(e) { /* */ } + Future.delayed(const Duration(minutes: 1), () { + try { setState(() {}); + } catch (e) { /**/ } + }); return FutureBuilder(future: LogsService().search(context, [], { "workflow_execution_id": widget.exec!.id, "start": start, "end": end }), builder: (a, b) { - Future.delayed(const Duration(minutes: 1), () { - setState(() {}); - }); List logs = []; if (b.data != null && b.data!.data != null) { + isLoading = false; var d = b.data!.data!; for( var r in d.result) { for (var element in r.logs) { @@ -63,6 +76,10 @@ class LogsWidgetState extends State { } List itemRows = logs.where((element) => (element.message?.toLowerCase().contains(widget.search.toLowerCase()) ?? true) && (widget.level?.contains(element.level ?? "") ?? true) ).map((e) => LogWidget(item: e)).toList(); + if (isLoading) { + return Container( height: getMainHeight(context) - 100, + child: Center( child: CircularProgressIndicator()) ); + } return Stack( children: [ SingleChildScrollView( child: itemRows.isEmpty ? Container( height: getMainHeight(context) - 100, diff --git a/lib/widgets/sheduler_items/schedule.dart b/lib/widgets/sheduler_items/schedule.dart index 4f15d27..07c0ab3 100644 --- a/lib/widgets/sheduler_items/schedule.dart +++ b/lib/widgets/sheduler_items/schedule.dart @@ -1,14 +1,13 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_box_transform/flutter_box_transform.dart'; -import 'package:oc_front/core/services/specialized_services/abstract_service.dart'; -import 'package:oc_front/core/services/specialized_services/booking_service.dart'; import 'package:oc_front/main.dart'; -import 'package:oc_front/models/workflow.dart'; +import 'package:flutter/material.dart'; import 'package:oc_front/widgets/logs.dart'; -import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:oc_front/models/workflow.dart'; +import 'package:flutter_box_transform/flutter_box_transform.dart'; import 'package:oc_front/widgets/lib/tranformablebox.dart' as fork; -import 'package:oc_front/widgets/sheduler_items/scheduler_calendar.dart'; import 'package:oc_front/widgets/sheduler_items/scheduler_item.dart'; +import 'package:oc_front/widgets/sheduler_items/scheduler_calendar.dart'; +import 'package:oc_front/core/services/specialized_services/abstract_service.dart'; +import 'package:oc_front/core/services/specialized_services/workflow_execution_service.dart'; double menuSize = 300; // ignore: must_be_immutable @@ -19,8 +18,9 @@ class ScheduleWidget extends StatefulWidget { bool loading = true; bool isList = true; bool isBox = true; - AbstractService service; - ScheduleWidget ({ super.key, required this.start, required this.end, required this.service, + String? selectedID; + AbstractService service = WorkflowExecutionService(); + ScheduleWidget ({ super.key, required this.start, required this.end, this.isBox =true, this.isList = true, this.loading = false}); @override ScheduleWidgetState createState() => ScheduleWidgetState(); } @@ -43,19 +43,16 @@ class ScheduleWidgetState extends State { "${widget.start.year}-${widget.start.month > 9 ? widget.start.month : "0${widget.start.month}"}-${widget.start.day > 9 ? widget.start.day : "0${widget.start.day}"}", "${widget.end.year}-${widget.end.month > 9 ? widget.end.month : "0${widget.end.month}"}-${widget.end.day > 9 ? widget.end.day : "0${widget.end.day}"}"], {}), builder: (ctx, as) { - Future.delayed(const Duration(minutes: 1), () { - setState(() {}); - }); Map> 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!); + if (element.startDate == null) { continue; } + DateTime dateTime = DateTime.parse(element.startDate!); 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!))); + data[str]!.sort((a, b) => DateTime.parse(a.startDate!).compareTo(DateTime.parse(b.startDate!))); } } bool isInfo = getMainWidth(context) <= 600 && selected != null && widget.isBox; @@ -63,12 +60,14 @@ class ScheduleWidgetState extends State { List children = []; if (selected != null) { for (var wf in data[selected!] ?? ([])) { - DateTime d2 = DateTime.parse(wf.executionData!).toLocal(); + DateTime d2 = DateTime.parse(wf.startDate!).toLocal(); children.add( InkWell( - onTap: () => setState(() { selectedReal = wf.executionData; }), + onTap: () => setState(() { + selectedReal = wf.startDate; + }), child: Container( margin: const EdgeInsets.all(10), decoration: BoxDecoration( - border: Border.all(color: selectedReal != null && selectedReal == wf.executionData ? lightColor : Colors.transparent, width: 2), + border: Border.all(color: selectedReal != null && selectedReal == wf.startDate ? lightColor : Colors.transparent, width: 2), borderRadius: BorderRadius.circular(4), color: Colors.white ), child: Container( @@ -96,14 +95,13 @@ class ScheduleWidgetState extends State { )) )); } - } - String? selectedID; + WorkflowExecution? sel; if (selectedReal != null) { try { - sel = data[selected!]!.firstWhere((element) => element.executionData == selectedReal); - selectedID = sel.id; + sel = data[selected!]!.firstWhere((element) => element.startDate == selectedReal); + widget.selectedID = sel.id; } catch(e) { /* */ } } menuSize = isInfo ? getMainWidth(context) : (menuSize > getMainWidth(context) / 2 ? getMainWidth(context) / 2 : menuSize); @@ -133,7 +131,9 @@ class ScheduleWidgetState extends State { child: Column( children: [ Row( children: [ - InkWell( onTap: () => setState(() { widget.isDayPlanner = true; }), + InkWell( onTap: () => setState(() { + widget.isDayPlanner = true; + }), child: Tooltip( message: "day planning", child: Container( height: 50, width: (isInfo ? getMainWidth(context) : (selected != null ? menuSize : 0)) / (selectedReal != null ? 2 : 1 ), alignment: Alignment.center, @@ -143,7 +143,10 @@ class ScheduleWidgetState extends State { child: Icon(Icons.calendar_today_outlined, color: widget.isDayPlanner ? Colors.white : Colors.grey), ) )), - InkWell( onTap: () => setState(() { widget.isDayPlanner = false; }), + InkWell( onTap: () => setState(() { + widget.isDayPlanner = false; + + }), child: Tooltip( message: "monitor task", child: Container( height: 50, width: selectedReal == null ? 0 : ( (isInfo ? getMainWidth(context) : (selected != null ? menuSize : 0)) / 2), @@ -162,8 +165,8 @@ class ScheduleWidgetState extends State { SingleChildScrollView( child: Column( mainAxisAlignment: children.isEmpty || widget.loading ? MainAxisAlignment.center : MainAxisAlignment.start, children: [ - ...( widget.isDayPlanner ? children : ( selectedID != null ? [ - widget.loading ? const SpinKitCircle(color: Colors.white,) : LogsWidget(exec: sel, search: search, level: level) + ...( widget.isDayPlanner ? children : ( widget.selectedID != null ? [ + LogsWidget(exec: sel, search: search, level: level) ] : [])), children.isEmpty ? Container( height: 100, alignment: Alignment.center, child: const Text("No event found", style: TextStyle(color: Colors.grey, fontSize: 20))) : Container() ]), diff --git a/lib/widgets/sheduler_items/scheduler_calendar.dart b/lib/widgets/sheduler_items/scheduler_calendar.dart index 79865c3..b4964cc 100644 --- a/lib/widgets/sheduler_items/scheduler_calendar.dart +++ b/lib/widgets/sheduler_items/scheduler_calendar.dart @@ -70,7 +70,7 @@ class SchedulerCalendarWidgetState extends State { } children.add(InkWell( onTap: () => widget.parent!.setState(() { selected = day.toIso8601String(); - selectedReal = ev.executionData; + selectedReal = ev.startDate; if (selectedReal == null) { widget.parent!.widget.isDayPlanner = true; } @@ -158,9 +158,9 @@ class SchedulerCalendarWidgetState extends State { shouldFillViewport: true, eventLoader: (day) { return widget.data[day.toIso8601String()] != null ? widget.data[day.toIso8601String()]!.map((e) { - DateTime dateTime = DateTime.parse(e.executionData!); + DateTime dateTime = DateTime.parse(e.startDate!); return Event("[${dateTime.hour > 9 ? dateTime.hour : "0${dateTime.hour}"}:${dateTime.minute > 9 ? dateTime.minute : "0${dateTime.minute}"}:${dateTime.second > 9 ? dateTime.second : "0${dateTime.second}"}] ${e.name}", - colors[(e.status ?? 1) - 1], e.executionData ); + colors[(e.status ?? 1) - 1], e.startDate ); }).toList() : []; }, )); @@ -169,10 +169,10 @@ class SchedulerCalendarWidgetState extends State { class Event { final String title; - String? executionData; + String? startDate; Color color; - Event(this.title, this.color, this.executionData); + Event(this.title, this.color, this.startDate); @override String toString() => title; diff --git a/lib/widgets/sheduler_items/scheduler_item.dart b/lib/widgets/sheduler_items/scheduler_item.dart index 4052515..58b5fb3 100644 --- a/lib/widgets/sheduler_items/scheduler_item.dart +++ b/lib/widgets/sheduler_items/scheduler_item.dart @@ -1,6 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_box_transform/flutter_box_transform.dart'; -import 'package:oc_front/core/sections/header/header.dart'; import 'package:oc_front/main.dart'; import 'package:oc_front/models/workflow.dart'; import 'package:oc_front/widgets/sheduler_items/schedule.dart'; @@ -26,23 +24,25 @@ class SchedulerItemWidgetState extends State { for (var element in widget.data.keys.toList()..sort((a, b) => DateTime.parse(a).compareTo(DateTime.parse(b)))) { List widgets = []; for (var ev in widget.data[element] ?? ([] as List)) { - widget.keys[ev.executionData!] = GlobalKey(); - var d2 = DateTime.parse(ev.executionData!).toLocal(); + widget.keys[ev.startDate!] = GlobalKey(); + var d2 = DateTime.parse(ev.startDate!).toLocal(); DateTime? d3; try { d3 = DateTime.parse(ev.endDate!).toLocal(); } catch (e) { /* */ } widgets.add(InkWell( onTap: () => widget.parent?.setState(() { - selected = selected != element || ev.executionData != selectedReal ? element : null; - selectedReal = selected == null ? null : ev.executionData; + selected = selected != element || ev.startDate != selectedReal ? element : null; + widget.parent!.widget.selectedID = selected; + selectedReal = selected == null ? null : ev.startDate; + print("there"); if (selectedReal == null) { widget.parent!.widget.isDayPlanner = true; } }), - child: Container( key: widget.keys[ev.executionData!], + child: Container( key: widget.keys[ev.startDate!], padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 50), decoration: BoxDecoration( - border: selectedReal == ev.executionData ? + border: selectedReal == ev.startDate ? Border.all(color: lightColor, width: 2) : Border(top: BorderSide(color: midColor)), ), child: Row(children: [ @@ -59,7 +59,7 @@ class SchedulerItemWidgetState extends State { SizedBox( width: (widget.width - 330) / 2, child: Padding( padding: const EdgeInsets.only(left: 20), - child: Text(ev.name?.toUpperCase() ?? "", overflow: TextOverflow.ellipsis, + child: Text("${ev.name?.toUpperCase().split("EXECUTION")[0].replaceAll("_", "") ?? ""} EXECUTION", overflow: TextOverflow.ellipsis, style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w500)), )), SizedBox( width: (widget.width - 340) / 2, diff --git a/library/flutter_flow_chart/.dart_tool/package_config.json b/library/flutter_flow_chart/.dart_tool/package_config.json index 3a00dcc..b98484b 100644 --- a/library/flutter_flow_chart/.dart_tool/package_config.json +++ b/library/flutter_flow_chart/.dart_tool/package_config.json @@ -3,223 +3,223 @@ "packages": [ { "name": "async", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/async-2.11.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/async-2.11.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "boolean_selector", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "box_transform", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/box_transform-0.4.4", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/box_transform-0.4.4", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "characters", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/characters-1.3.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/characters-1.3.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "clock", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/clock-1.1.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/clock-1.1.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "collection", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/collection-1.18.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/collection-1.18.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "crypto", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/crypto-3.0.3", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/crypto-3.0.3", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "dashed_path", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/dashed_path-1.0.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/dashed_path-1.0.1", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "dotted_line", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/dotted_line-3.2.2", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/dotted_line-3.2.2", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "fake_async", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/fake_async-1.3.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/fake_async-1.3.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "fixnum", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/fixnum-1.1.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/fixnum-1.1.0", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "flutter", - "rootUri": "file:///home/opencloud/Tools/flutter/packages/flutter", + "rootUri": "file:///home/mr/snap/flutter/common/flutter/packages/flutter", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "flutter_box_transform", - "rootUri": "file:///home/opencloud/.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", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "flutter_colorpicker", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_colorpicker-1.1.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/flutter_colorpicker-1.1.0", "packageUri": "lib/", "languageVersion": "2.14" }, { "name": "flutter_test", - "rootUri": "file:///home/opencloud/Tools/flutter/packages/flutter_test", + "rootUri": "file:///home/mr/snap/flutter/common/flutter/packages/flutter_test", "packageUri": "lib/", "languageVersion": "3.3" }, { "name": "hover_menu", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/hover_menu-1.1.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/hover_menu-1.1.1", "packageUri": "lib/", "languageVersion": "2.16" }, { "name": "leak_tracker", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker-10.0.5", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker-10.0.5", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "leak_tracker_flutter_testing", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.5", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.5", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "leak_tracker_testing", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.1", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "matcher", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/matcher-0.12.16+1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/matcher-0.12.16+1", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "material_color_utilities", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "meta", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/meta-1.15.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/meta-1.15.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "number_text_input_formatter", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/number_text_input_formatter-1.0.0+8", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/number_text_input_formatter-1.0.0+8", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "path", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/path-1.9.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/path-1.9.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "sky_engine", - "rootUri": "file:///home/opencloud/Tools/flutter/bin/cache/pkg/sky_engine", + "rootUri": "file:///home/mr/snap/flutter/common/flutter/bin/cache/pkg/sky_engine", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "source_span", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/source_span-1.10.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/source_span-1.10.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "sprintf", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/sprintf-7.0.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/sprintf-7.0.0", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "stack_trace", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/stack_trace-1.11.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/stack_trace-1.11.1", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "stream_channel", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/stream_channel-2.1.2", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/stream_channel-2.1.2", "packageUri": "lib/", "languageVersion": "2.19" }, { "name": "string_scanner", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/string_scanner-1.2.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/string_scanner-1.2.0", "packageUri": "lib/", "languageVersion": "2.18" }, { "name": "term_glyph", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/term_glyph-1.2.1", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/term_glyph-1.2.1", "packageUri": "lib/", "languageVersion": "2.12" }, { "name": "test_api", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/test_api-0.7.2", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/test_api-0.7.2", "packageUri": "lib/", "languageVersion": "3.2" }, { "name": "typed_data", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/typed_data-1.3.2", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/typed_data-1.3.2", "packageUri": "lib/", "languageVersion": "2.17" }, { "name": "uuid", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/uuid-4.4.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/uuid-4.4.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "vector_math", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/vector_math-2.1.4", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/vector_math-2.1.4", "packageUri": "lib/", "languageVersion": "2.14" }, { "name": "very_good_analysis", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/very_good_analysis-5.1.0", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/very_good_analysis-5.1.0", "packageUri": "lib/", "languageVersion": "3.0" }, { "name": "vm_service", - "rootUri": "file:///home/opencloud/.pub-cache/hosted/pub.dev/vm_service-14.2.5", + "rootUri": "file:///home/mr/.pub-cache/hosted/pub.dev/vm_service-14.2.5", "packageUri": "lib/", "languageVersion": "3.3" }, @@ -230,10 +230,10 @@ "languageVersion": "3.3" } ], - "generated": "2024-12-17T16:53:00.428443Z", + "generated": "2025-02-17T08:57:16.568019Z", "generator": "pub", - "generatorVersion": "3.5.4", - "flutterRoot": "file:///home/opencloud/Tools/flutter", - "flutterVersion": "3.24.5", - "pubCache": "file:///home/opencloud/.pub-cache" + "generatorVersion": "3.5.3", + "flutterRoot": "file:///home/mr/snap/flutter/common/flutter", + "flutterVersion": "3.24.3", + "pubCache": "file:///home/mr/.pub-cache" } diff --git a/library/flutter_flow_chart/.dart_tool/package_config_subset b/library/flutter_flow_chart/.dart_tool/package_config_subset index ba74447..76b530e 100644 --- a/library/flutter_flow_chart/.dart_tool/package_config_subset +++ b/library/flutter_flow_chart/.dart_tool/package_config_subset @@ -1,153 +1,153 @@ async 2.18 -file:///home/opencloud/.pub-cache/hosted/pub.dev/async-2.11.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/async-2.11.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/async-2.11.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/async-2.11.0/lib/ boolean_selector 2.17 -file:///home/opencloud/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/boolean_selector-2.1.1/lib/ box_transform 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/box_transform-0.4.4/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/box_transform-0.4.4/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/box_transform-0.4.4/ +file:///home/mr/.pub-cache/hosted/pub.dev/box_transform-0.4.4/lib/ characters 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/characters-1.3.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/characters-1.3.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/characters-1.3.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/characters-1.3.0/lib/ clock 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/clock-1.1.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/clock-1.1.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/clock-1.1.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/clock-1.1.1/lib/ collection 2.18 -file:///home/opencloud/.pub-cache/hosted/pub.dev/collection-1.18.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/collection-1.18.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/collection-1.18.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/collection-1.18.0/lib/ crypto 2.19 -file:///home/opencloud/.pub-cache/hosted/pub.dev/crypto-3.0.3/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/crypto-3.0.3/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/crypto-3.0.3/ +file:///home/mr/.pub-cache/hosted/pub.dev/crypto-3.0.3/lib/ dashed_path 2.19 -file:///home/opencloud/.pub-cache/hosted/pub.dev/dashed_path-1.0.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/dashed_path-1.0.1/lib/ +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/ dotted_line 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/dotted_line-3.2.2/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/dotted_line-3.2.2/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/dotted_line-3.2.2/ +file:///home/mr/.pub-cache/hosted/pub.dev/dotted_line-3.2.2/lib/ fake_async 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/fake_async-1.3.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/fake_async-1.3.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/fake_async-1.3.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/fake_async-1.3.1/lib/ fixnum 2.19 -file:///home/opencloud/.pub-cache/hosted/pub.dev/fixnum-1.1.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/fixnum-1.1.0/lib/ +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/ flutter_box_transform 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_box_transform-0.4.4/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_box_transform-0.4.4/lib/ +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/lib/ flutter_colorpicker 2.14 -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_colorpicker-1.1.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/flutter_colorpicker-1.1.0/lib/ +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/ hover_menu 2.16 -file:///home/opencloud/.pub-cache/hosted/pub.dev/hover_menu-1.1.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/hover_menu-1.1.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/hover_menu-1.1.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/hover_menu-1.1.1/lib/ leak_tracker 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker-10.0.5/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker-10.0.5/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker-10.0.5/ +file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker-10.0.5/lib/ leak_tracker_flutter_testing 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.5/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.5/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.5/ +file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.5/lib/ leak_tracker_testing 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.1/lib/ matcher 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/matcher-0.12.16+1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/matcher-0.12.16+1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/matcher-0.12.16+1/ +file:///home/mr/.pub-cache/hosted/pub.dev/matcher-0.12.16+1/lib/ material_color_utilities 2.17 -file:///home/opencloud/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1/lib/ meta 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/meta-1.15.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/meta-1.15.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/meta-1.15.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/meta-1.15.0/lib/ number_text_input_formatter 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/number_text_input_formatter-1.0.0+8/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/number_text_input_formatter-1.0.0+8/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/number_text_input_formatter-1.0.0+8/ +file:///home/mr/.pub-cache/hosted/pub.dev/number_text_input_formatter-1.0.0+8/lib/ path 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/path-1.9.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/path-1.9.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/path-1.9.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/path-1.9.0/lib/ source_span 2.18 -file:///home/opencloud/.pub-cache/hosted/pub.dev/source_span-1.10.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/source_span-1.10.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/source_span-1.10.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/source_span-1.10.0/lib/ sprintf 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/sprintf-7.0.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/sprintf-7.0.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/sprintf-7.0.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/sprintf-7.0.0/lib/ stack_trace 2.18 -file:///home/opencloud/.pub-cache/hosted/pub.dev/stack_trace-1.11.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/stack_trace-1.11.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/stack_trace-1.11.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/stack_trace-1.11.1/lib/ stream_channel 2.19 -file:///home/opencloud/.pub-cache/hosted/pub.dev/stream_channel-2.1.2/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/stream_channel-2.1.2/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/stream_channel-2.1.2/ +file:///home/mr/.pub-cache/hosted/pub.dev/stream_channel-2.1.2/lib/ string_scanner 2.18 -file:///home/opencloud/.pub-cache/hosted/pub.dev/string_scanner-1.2.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/string_scanner-1.2.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/string_scanner-1.2.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/string_scanner-1.2.0/lib/ term_glyph 2.12 -file:///home/opencloud/.pub-cache/hosted/pub.dev/term_glyph-1.2.1/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/term_glyph-1.2.1/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/term_glyph-1.2.1/ +file:///home/mr/.pub-cache/hosted/pub.dev/term_glyph-1.2.1/lib/ test_api 3.2 -file:///home/opencloud/.pub-cache/hosted/pub.dev/test_api-0.7.2/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/test_api-0.7.2/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/test_api-0.7.2/ +file:///home/mr/.pub-cache/hosted/pub.dev/test_api-0.7.2/lib/ typed_data 2.17 -file:///home/opencloud/.pub-cache/hosted/pub.dev/typed_data-1.3.2/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/typed_data-1.3.2/lib/ +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/lib/ uuid 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/uuid-4.4.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/uuid-4.4.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/uuid-4.4.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/uuid-4.4.0/lib/ vector_math 2.14 -file:///home/opencloud/.pub-cache/hosted/pub.dev/vector_math-2.1.4/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/vector_math-2.1.4/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/vector_math-2.1.4/ +file:///home/mr/.pub-cache/hosted/pub.dev/vector_math-2.1.4/lib/ very_good_analysis 3.0 -file:///home/opencloud/.pub-cache/hosted/pub.dev/very_good_analysis-5.1.0/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/very_good_analysis-5.1.0/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/very_good_analysis-5.1.0/ +file:///home/mr/.pub-cache/hosted/pub.dev/very_good_analysis-5.1.0/lib/ vm_service 3.3 -file:///home/opencloud/.pub-cache/hosted/pub.dev/vm_service-14.2.5/ -file:///home/opencloud/.pub-cache/hosted/pub.dev/vm_service-14.2.5/lib/ +file:///home/mr/.pub-cache/hosted/pub.dev/vm_service-14.2.5/ +file:///home/mr/.pub-cache/hosted/pub.dev/vm_service-14.2.5/lib/ flutter_flow_chart 3.3 -file:///home/opencloud/Source/opencloud/oc-local/src/oc-front/library/flutter_flow_chart/ -file:///home/opencloud/Source/opencloud/oc-local/src/oc-front/library/flutter_flow_chart/lib/ +file:///home/mr/Documents/OC/oc-front/library/flutter_flow_chart/ +file:///home/mr/Documents/OC/oc-front/library/flutter_flow_chart/lib/ sky_engine 3.2 -file:///home/opencloud/Tools/flutter/bin/cache/pkg/sky_engine/ -file:///home/opencloud/Tools/flutter/bin/cache/pkg/sky_engine/lib/ +file:///home/mr/snap/flutter/common/flutter/bin/cache/pkg/sky_engine/ +file:///home/mr/snap/flutter/common/flutter/bin/cache/pkg/sky_engine/lib/ flutter 3.3 -file:///home/opencloud/Tools/flutter/packages/flutter/ -file:///home/opencloud/Tools/flutter/packages/flutter/lib/ +file:///home/mr/snap/flutter/common/flutter/packages/flutter/ +file:///home/mr/snap/flutter/common/flutter/packages/flutter/lib/ flutter_test 3.3 -file:///home/opencloud/Tools/flutter/packages/flutter_test/ -file:///home/opencloud/Tools/flutter/packages/flutter_test/lib/ +file:///home/mr/snap/flutter/common/flutter/packages/flutter_test/ +file:///home/mr/snap/flutter/common/flutter/packages/flutter_test/lib/ 2 diff --git a/library/flutter_flow_chart/.dart_tool/version b/library/flutter_flow_chart/.dart_tool/version index 9d67c4f..ffba2c8 100644 --- a/library/flutter_flow_chart/.dart_tool/version +++ b/library/flutter_flow_chart/.dart_tool/version @@ -1 +1 @@ -3.24.5 \ No newline at end of file +3.24.3 \ No newline at end of file diff --git a/library/flutter_flow_chart/lib/flutter_flow_chart.dart b/library/flutter_flow_chart/lib/flutter_flow_chart.dart index 181fe31..e9fa498 100755 --- a/library/flutter_flow_chart/lib/flutter_flow_chart.dart +++ b/library/flutter_flow_chart/lib/flutter_flow_chart.dart @@ -5,5 +5,5 @@ export 'src/dashboard.dart'; export 'src/elements/connection_params.dart'; export 'src/elements/flow_element.dart'; export 'src/flow_chart.dart'; -export 'src/ui/draw_arrow.dart' show ArrowParams, ArrowStyle, ArrowDirection; +export 'src/ui/draw_arrow.dart' show ArrowParams, ArrowStyle, ArrowDirection, ArrowPainter; export 'src/ui/grid_background.dart' show GridBackgroundParams; diff --git a/library/flutter_flow_chart/lib/src/dashboard.dart b/library/flutter_flow_chart/lib/src/dashboard.dart index 5279fb4..08eeaf1 100755 --- a/library/flutter_flow_chart/lib/src/dashboard.dart +++ b/library/flutter_flow_chart/lib/src/dashboard.dart @@ -28,13 +28,11 @@ class Dashboard extends ChangeNotifier { GlobalKey chartMenuKey = GlobalKey(); GlobalKey chartKey = GlobalKey(); GlobalKey flutterChartKey = GlobalKey(); - + bool inDialog = false; List> tempHistory = []; List> history = []; - Map scheduler = {}; Map info = {}; - bool scheduleActive = false; String? id; String name = ""; bool isMenu = true; @@ -47,8 +45,9 @@ class Dashboard extends ChangeNotifier { double defaultDashWidth = 0; double defaultBackWidth = 10; double defaultForwardWidth = 10; - Future Function(String? id)? save; + Future Function(String? id, BuildContext? context)? save; List Function(FlowData? obj, String id)? infoItemWidget; + Widget Function(ArrowPainter item)? infoLinkWidget; List Function()? infoWidget; FlowData? Function(Map json)? transformToData; bool addChange = false; @@ -74,7 +73,6 @@ class Dashboard extends ChangeNotifier { this.save, this.dashColor = Colors.grey, this.midDashColor = Colors.blueGrey, - this.scheduler = const {}, Offset? handlerFeedbackOffset, this.isMenu = true, this.defaultDashSpace = 0, @@ -93,7 +91,7 @@ class Dashboard extends ChangeNotifier { // This is a workaround to set the handlerFeedbackOffset // to improve the user experience on devices with touch screens // This will prevent the handler being covered by user's finger - if (loadedGraph != null) { deserialize(loadedGraph!); } + if (loadedGraph != null) { deserialize(loadedGraph!, false); } if (handlerFeedbackOffset != null) { this.handlerFeedbackOffset = handlerFeedbackOffset; } else { @@ -110,18 +108,15 @@ class Dashboard extends ChangeNotifier { tempHistory = []; history = []; } - Future saveDash(String? id) async { - shouldSave = true; + Future saveDash(String? id, BuildContext? context) async { for (var element in saveRules) { - if (element(this)) { - shouldSave = true; - } else { + if (!element(this)) { shouldSave = false; break; } } if (save != null && shouldSave) { - save!(id); + save!(id, context); } } Future Function(String cat)? load; @@ -131,14 +126,12 @@ class Dashboard extends ChangeNotifier { final d = Dashboard( name: map['name'] as String, isMenu: map['isMenu'] as bool, - scheduler: map['schedule'] as Map? ?? {}, defaultDashSpace: map['defaultDashSpace'] as double? ?? 0, defaultDashWidth: map['defaultDashWidth'] as double? ?? 0, defaultArrowDirection: ArrowDirection.values[ map['defaultArrowDirection'] as int? ?? 0], defaultArrowStyle: ArrowStyle.values[map['arrowStyle'] as int? ?? 0], ); - d..scheduleActive = map['schedule_active'] as bool? ?? false; d..arrows = List.from( (map['arrows'] as List).map( (x) => ArrowPainter.fromMap(x as Map), @@ -170,15 +163,14 @@ class Dashboard extends ChangeNotifier { } void copyFromMap(Map map) { - scheduleActive = map['schedule_active'] as bool? ?? false; - scheduler = map['schedule'] as Map? ?? {}; + debugPrintStack(stackTrace: StackTrace.current, label: 'my_label', maxFrames: 5); defaultArrowStyle = ArrowStyle.values[map['arrowStyle'] as int? ?? 0]; defaultDashSpace = map['defaultDashSpace'] as double? ?? 0; defaultDashWidth = map['defaultDashWidth'] as double? ?? 0; defaultArrowDirection = ArrowDirection.values[ map['defaultArrowDirection'] as int? ?? 0]; arrows = List.from( - (map['arrows'] as List).map( + (map['arrows'] as List).map( (x) => ArrowPainter.fromMap(x as Map), ), ); @@ -257,26 +249,25 @@ class Dashboard extends ChangeNotifier { d["id"]=id; d["name"]=name; d["graph"]=graph; - d["schedule"]=scheduler; - d["schedule_active"]=scheduleActive; return d; } - void deserialize(Map graph) { + void deserialize(Map graph, bool noHistory) { elements = []; arrows = []; info["shared"] = graph["shared"] ?? []; - scheduler = graph['schedule'] ?? {}; - scheduleActive = graph['schedule_active'] ?? false; setZoomFactor(graph["graph"]?["zoom"] ?? 1.0); for(var el in graph['graph']?['elements'] ?? []) { List nexts = []; var flow = FlowElement.deserialize(this, el); for(var ar in graph['graph']['arrows']) { + if (ar['from']['id'] != flow.id) { continue; } nexts.add(ConnectionParams( srcElementId: ar['from']['id'], destElementId: ar['to']['id'], + infos: ar['infos'], + env: ar['env'], arrowParams: ArrowParams.fromMap(ar["params"]), pivots: [ Pivot(Offset(ar['from']['x'], (ar['from']['y']))), @@ -291,16 +282,35 @@ class Dashboard extends ChangeNotifier { arr.add(build); } } - try { - FlowData data = arr.firstWhere((element) => element.getID() == flow.element?.getID()); + if (flow.element != null) { flow.kind = ElementKind.widget; - flow.widget = chartKey.currentState?.widget.flowChart.widget.itemWidget(data); - } catch (e) { print(e); } + flow.widget = chartKey.currentState?.widget.flowChart.widget.itemWidget(flow.element!); + } elements.add(flow); } selectedMenuKey.currentState?.setState(() { }); chartMenuKey.currentState?.setState(() { }); - addToHistory(); + if (!noHistory) { + addToHistory(); + } + } + + + void applyInfos(Map> elInfos, Map graph) { + for(var id in elInfos.keys) { + try { + var element = elements.firstWhere((element) => element.id == id); + element.element?.addEnv(elInfos[id] ?? []); + } catch (e) { /* */ } + } + for(var ar in graph['graph']['arrows']) { + var arr = arrows.where((a) => a.fromID == ar['from']['id'] && a.toID == ar['to']['id']).toList(); + for (var a in arr) { + a.infos = ar['infos']; + a.env = ar['env']; + } + } + selectedLeftMenuKey.currentState?.setState(() { }); } /// add listener called when a new connection is created @@ -325,30 +335,31 @@ class Dashboard extends ChangeNotifier { handlerFeedbackOffset = offset; } - List GetArrowByElementID(String id, bool isinput) { - return arrows.where((element) => (isinput && element.toID.contains(id)) || (!isinput && element.fromID.contains(id))).toList(); + List getArrowByElementID(String id, bool isinput) { + return arrows.where((element) => + (isinput && element.toID.contains(id)) || (!isinput && element.fromID.contains(id))).toList(); } - void addArrows(ArrowPainter f) { + void addArrows(ArrowPainter f, BuildContext? context) { arrows.add(f); for (var f in arrowStyleRules) { arrows = f(this); } addChange = true; - saveDash(id); + saveDash(id, context); } - void removeArrows(bool Function(ArrowPainter) f) { + void removeArrows(bool Function(ArrowPainter) f, BuildContext? context) { arrows.removeWhere((element) => f(element)); for (var f in arrowStyleRules) { arrows = f(this); } - saveDash(id); + saveDash(id, context); } - void removeElements(bool Function(FlowElement) f) { + void removeElements(bool Function(FlowElement) f, BuildContext? context) { elements.removeWhere((element) => f(element)); - saveDash(id); + saveDash(id, context); } void clear() { @@ -356,9 +367,7 @@ class Dashboard extends ChangeNotifier { arrows.clear(); tempHistory = []; history = []; - scheduler = {}; info = {}; - scheduleActive = false; notifyListeners(); } bool noHistory = false; @@ -375,14 +384,13 @@ class Dashboard extends ChangeNotifier { Future.delayed(Duration(seconds: 1), () { chartMenuKey.currentState?.setState(() { }); }); - ; } bool isBack = false; void back() { if (canBack()) { noHistory = true; tempHistory.removeLast(); - if (tempHistory.length > 0) { + if (tempHistory.isNotEmpty) { copyFromMap(tempHistory.last); } chartKey.currentState?.setState(() { }); @@ -413,28 +421,29 @@ class Dashboard extends ChangeNotifier { FlowElement element, bool resizable, { bool notify = true, + BuildContext? context }) { element.isResizing = resizable; - saveDash(id); + saveDash(id, context); if (notify) notifyListeners(); } FlowElement? getElement(String id, {bool notify = true}) { try { return elements.firstWhere((element) { - return element.id == id; + return id.contains(element.id); }); } catch (e) { return null; } } /// add a [FlowElement] to the dashboard - void addElement(FlowElement element, {bool notify = true}) { + void addElement(FlowElement element, BuildContext? context, {bool notify = true}) { if (element.id.isEmpty) { element.id = const Uuid().v4(); } element.setScale(1, gridBackgroundParams.scale); elements.add(element); addChange = true; - saveDash(id); + saveDash(id, context); if (notify) { notifyListeners(); } @@ -554,16 +563,16 @@ class Dashboard extends ChangeNotifier { } /// remove all elements - void removeAllElements({bool notify = true}) { + void removeAllElements(BuildContext? context, {bool notify = true}) { elements.clear(); if (notify) notifyListeners(); - saveDash(id); + saveDash(id, context); } /// remove the [handler] connection of [element] void removeElementConnection( FlowElement element, - Handler handler, { + Handler handler, BuildContext? context, { bool notify = true, }) { Alignment alignment; @@ -600,7 +609,7 @@ class Dashboard extends ChangeNotifier { } } if (notify) notifyListeners(); - saveDash(id); + saveDash(id, context); } /// dissect an element connection @@ -690,19 +699,20 @@ class Dashboard extends ChangeNotifier { } /// remove all the connection from the [element] - void removeElementConnections(FlowElement element, {bool notify = true}) { + void removeElementConnections(FlowElement element, BuildContext? context, {bool notify = true}) { element.next.clear(); if (notify) notifyListeners(); - saveDash(id); + saveDash(id, context); } /// remove all the elements with [id] from the dashboard - void removeElementById(String id, {bool notify = true}) { + void removeElementById(String id, BuildContext? context, {bool notify = true}) { // remove the element var elementId = ''; elements.removeWhere((element) { if (element.id == id) { elementId = element.id; + arrows.removeWhere((a) => a.fromID.contains(elementId) || a.toID.contains(elementId)); } return element.id == id; }); @@ -714,20 +724,23 @@ class Dashboard extends ChangeNotifier { }); } if (notify) notifyListeners(); - saveDash(id); + saveDash(id, context); } /// remove element /// return true if it has been removed - bool removeElement(FlowElement element, {bool notify = true}) { + bool removeElement(FlowElement element, BuildContext? context, {bool notify = true}) { // remove the element var found = false; final elementId = element.id; elements.removeWhere((e) { - if (e.id == element.id) found = true; + if (e.id == element.id) { + found = true; + + } return e.id == element.id; }); - + arrows.removeWhere( (e) => e.fromID.contains(elementId) || e.toID.contains(elementId)); // remove all connections to the element for (final e in elements) { e.next.removeWhere( @@ -735,7 +748,7 @@ class Dashboard extends ChangeNotifier { ); } if (notify) notifyListeners(); - saveDash(id); + saveDash(id, context); return found; } diff --git a/library/flutter_flow_chart/lib/src/elements/connection_params.dart b/library/flutter_flow_chart/lib/src/elements/connection_params.dart index 976c1c5..6808bc2 100755 --- a/library/flutter_flow_chart/lib/src/elements/connection_params.dart +++ b/library/flutter_flow_chart/lib/src/elements/connection_params.dart @@ -11,14 +11,19 @@ class ConnectionParams { required this.srcElementId, required this.destElementId, required this.arrowParams, + this.env = const [], + this.infos = const [], List? pivots, }) : pivots = pivots ?? []; - + List env = []; + List infos = []; /// factory ConnectionParams.fromMap(Map map) { return ConnectionParams( srcElementId: map['srcElementId'] as String, destElementId: map['destElementId'] as String, + infos: map['infos'] as List? ?? [], + env: map['env'] as List? ?? [], arrowParams: ArrowParams.fromMap(map['arrowParams'] as Map), pivots: (map['pivots'] as List?) ?.map( @@ -37,7 +42,6 @@ class ConnectionParams { final String destElementId; final String srcElementId; - /// Arrow parameters. final ArrowParams arrowParams; diff --git a/library/flutter_flow_chart/lib/src/elements/flow_element.dart b/library/flutter_flow_chart/lib/src/elements/flow_element.dart index d8e5d28..642e134 100755 --- a/library/flutter_flow_chart/lib/src/elements/flow_element.dart +++ b/library/flutter_flow_chart/lib/src/elements/flow_element.dart @@ -374,6 +374,7 @@ class FlowElement extends ChangeNotifier { graphElement['width'] = size.width; graphElement['height'] = size.height; graphElement['element']=element?.serialize(); + graphElement['next'] = next.map((x) => x.toMap()).toList(); return graphElement; } @@ -385,6 +386,13 @@ class FlowElement extends ChangeNotifier { 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?, + /*next: map['next'] != null && (map['next'] as List).isNotEmpty + ? List.from( + (map['next'] as List).map( + (x) => ConnectionParams.fromMap(x as Map), + ), + ) + : []*/ ); } } diff --git a/library/flutter_flow_chart/lib/src/flow_chart.dart b/library/flutter_flow_chart/lib/src/flow_chart.dart index 6931776..1d06592 100755 --- a/library/flutter_flow_chart/lib/src/flow_chart.dart +++ b/library/flutter_flow_chart/lib/src/flow_chart.dart @@ -1,29 +1,27 @@ // ignore: directives_ordering -import 'dart:developer'; - +import 'package:uuid/uuid.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter_flow_chart/flutter_flow_chart.dart'; -import 'package:flutter_flow_chart/src/flow_chart_left_menu.dart'; -import 'package:flutter_flow_chart/src/flow_chart_menu.dart'; -import 'package:flutter_flow_chart/src/flow_chart_selected_menu.dart'; import 'package:flutter_flow_chart/src/ui/draw_arrow.dart'; +import 'package:flutter_flow_chart/flutter_flow_chart.dart'; +import 'package:flutter_flow_chart/src/flow_chart_menu.dart'; import 'package:flutter_flow_chart/src/ui/element_widget.dart'; import 'package:flutter_flow_chart/src/ui/grid_background.dart'; import 'package:flutter_flow_chart/src/ui/segment_handler.dart'; -import 'package:uuid/uuid.dart'; +import 'package:flutter_flow_chart/src/flow_chart_left_menu.dart'; +import 'package:flutter_flow_chart/src/flow_chart_selected_menu.dart'; + /// Main flow chart Widget. /// It displays the background grid, all the elements and connection lines abstract class FlowData { String getID(); String getName(); + String getType(); double? getWidth(); double? getHeight(); - - Map setVariable(List keys, dynamic value, Map map); - dynamic getVariable(List keys, Map map); + void addEnv(List infos); Map serialize(); FlowData deserialize(Map data); } @@ -321,17 +319,21 @@ class FlowChartState extends State { Future.delayed(Duration(milliseconds: 100), () => widget.dashboard.load!(widget.dashboard.id!) ); } else { 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)); - - }); }); + if (!widget.dashboard.inDialog) { + widget.dashboard.inDialog = true; + 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)); + + }); + } + }); } } else { widget.dashboard.isOpened = true; @@ -357,14 +359,14 @@ class FlowChartState extends State { onKeyEvent: (event) { bool change = false; if (event.logicalKey == LogicalKeyboardKey.controlLeft) { - isCtrl = event is KeyDownEvent || event is KeyRepeatEvent; + isCtrl = event is KeyDownEvent || event is KeyRepeatEvent; } - if (event is KeyDownEvent || event.logicalKey == LogicalKeyboardKey.keyZ && isCtrl) { + /*if ((event is KeyDownEvent || event.logicalKey == LogicalKeyboardKey.keyZ) && isCtrl) { widget.dashboard.back(); } - if (event is KeyDownEvent || event.logicalKey == LogicalKeyboardKey.keyY && isCtrl) { + if ((event is KeyDownEvent || event.logicalKey == LogicalKeyboardKey.keyY) && isCtrl) { widget.dashboard.forward(); - } + }*/ if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.add) { change = true; for (var el in widget.dashboard.elementSelected) { @@ -379,18 +381,23 @@ class FlowChartState extends State { kind: el.kind, handlers: el.handlers, handlerSize: el.handlerSize, - )); + ), context); } } if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.delete) { change = true; - widget.dashboard.removeElements( (el) => el.isSelected ); + widget.dashboard.removeElements((element) { + if (element.isSelected) { + widget.dashboard.arrows.removeWhere( (e) => e.toID.contains(element.id) || e.fromID.contains(element.id)); + } + return element.isSelected; + }, context); for (var arrow in widget.dashboard.arrowsSelected) { for (var el in widget.dashboard.elements.where((element) => element.id == arrow.fromID.split("_")[0])) { el.next.removeAt(int.parse(arrow.fromID.split("_")[1])); } } - widget.dashboard.removeArrows( (el) => el.isSelected ); + widget.dashboard.removeArrows( (el) => el.isSelected, context ); } if (change) { DrawingArrow.instance.notifyListeners(); @@ -459,7 +466,7 @@ class FlowChartState extends State { Handler.rightCenter, ], ); - widget.dashboard.addElement(el); + widget.dashboard.addElement(el, context); }, ))] ), @@ -495,8 +502,8 @@ class FlowChartState extends State { onDragEnd: (d) => node.requestFocus(), childWhenDragging: Opacity(opacity: .5, child: Padding( padding: const EdgeInsets.all(10), - child: Container( child: widget.itemWidget(e), alignment: Alignment.center, - constraints: BoxConstraints(maxHeight: realSize - 10, maxWidth: realSize - 10), ))), + child: Container( alignment: Alignment.center, + constraints: BoxConstraints(maxHeight: realSize - 10, maxWidth: realSize - 10), child: widget.itemWidget(e), ))), feedback: Container( alignment: Alignment.center, constraints: BoxConstraints(maxHeight: realSize, maxWidth: realSize), child: widget.itemWidget(e) ), child: InkWell( mouseCursor: SystemMouseCursors.grab, child: Padding( padding: const EdgeInsets.all(10), @@ -548,6 +555,8 @@ class _DrawingArrowWidgetState extends State { painter: ArrowPainter( fromID: DrawingArrow.instance.fromID, toID: "", + env: DrawingArrow.instance.env, + infos: DrawingArrow.instance.infos, params: DrawingArrow.instance.params, from: DrawingArrow.instance.from, to: DrawingArrow.instance.to, @@ -878,9 +887,7 @@ class ChartWidgetState extends State { ), // Draw arrows for (int i = 0; i < widget.dashboard.elements.length; i++) - for (int n = 0; n < widget.dashboard.elements[i].next.length; n++) - DrawArrow( flow: this, key: UniqueKey(), @@ -889,6 +896,8 @@ class ChartWidgetState extends State { destElement: widget.dashboard.elements[widget.dashboard.findElementIndexById( widget.dashboard.elements[i].next[n].destElementId, )], + env: widget.dashboard.elements[i].next[n].env, + infos: widget.dashboard.elements[i].next[n].infos, arrowParams: widget.dashboard.elements[i].next[n].arrowParams, pivots: widget.dashboard.elements[i].next[n].pivots, ), diff --git a/library/flutter_flow_chart/lib/src/flow_chart_menu.dart b/library/flutter_flow_chart/lib/src/flow_chart_menu.dart index 2563f86..fa8418c 100644 --- a/library/flutter_flow_chart/lib/src/flow_chart_menu.dart +++ b/library/flutter_flow_chart/lib/src/flow_chart_menu.dart @@ -37,17 +37,20 @@ class FlowChartMenuState extends State { onTap: () { widget.dashboard.name = "graph_${DateTime.now().toString().replaceAll(" ", "_").substring(0, DateTime.now().toString().length - 7)}"; widget.dashboard.isOpened = true; - 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.chart.widget.flowChart.widget.onDashboardAlertOpened!( - context, widget.dashboard)); - }); + if (!widget.dashboard.inDialog) { + widget.dashboard.inDialog = true; + 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.chart.widget.flowChart.widget.onDashboardAlertOpened!( + context, widget.dashboard)); + }); + } }, child: Icon(Icons.folder, color: Colors.white))))), ])), @@ -57,8 +60,6 @@ class FlowChartMenuState extends State { ), child: Padding( padding: EdgeInsets.symmetric(horizontal: 10), child: PopupMenuButton( - child: - Row( children: [ Icon(Icons.fullscreen, color: Colors.white), Icon(Icons.arrow_drop_down, size: 10, color: Colors.white) ]), initialValue: null, onSelected: (DisplayEnum value) { if (value == DisplayEnum.MENU) { widget.dashboard.isMenu = !widget.dashboard.isMenu; } @@ -83,7 +84,9 @@ class FlowChartMenuState extends State { child: Text(widget.dashboard.isInfo ? 'hide info' : 'show info', textAlign: TextAlign.center,)) ]), ), - ] + ], + child: + Row( children: [ Icon(Icons.fullscreen, color: Colors.white), Icon(Icons.arrow_drop_down, size: 10, color: Colors.white) ]) ),) ) ), diff --git a/library/flutter_flow_chart/lib/src/flow_chart_selected_menu.dart b/library/flutter_flow_chart/lib/src/flow_chart_selected_menu.dart index c77edd0..4d7adcd 100644 --- a/library/flutter_flow_chart/lib/src/flow_chart_selected_menu.dart +++ b/library/flutter_flow_chart/lib/src/flow_chart_selected_menu.dart @@ -4,6 +4,7 @@ import 'package:flutter_flow_chart/src/ui/draw_arrow.dart'; import 'package:flutter_flow_chart/flutter_flow_chart.dart'; import 'package:flutter_colorpicker/flutter_colorpicker.dart'; import 'package:number_text_input_formatter/number_text_input_formatter.dart'; +import 'package:uuid/uuid.dart'; class FlowChartSelectedMenu extends StatefulWidget { Dashboard dashboard; @@ -30,16 +31,15 @@ class FlowChartSelectedMenuState extends State { child: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [ Tooltip( message: "remove", child: InkWell( mouseCursor: SystemMouseCursors.click, - onTap: () { - widget.dashboard.removeArrows((element) { - if (element.isSelected && element.elementIndex != null && element.connIndex != null) { - widget.dashboard.elements[element.elementIndex!].next.removeAt(element.connIndex!); + onTap: () { + widget.dashboard.removeElements((element) { + if (element.isSelected) { + widget.dashboard.arrows.removeWhere( (e) => e.toID.contains(element.id) || e.fromID.contains(element.id)); } return element.isSelected; - }); - widget.dashboard.removeElements((element) => element.isSelected); + }, context); Future.delayed(Duration(milliseconds: 100), () { - widget.dashboard.chartKey.currentState?.setState(() { }); + widget.dashboard.flutterChartKey.currentState?.setState(() { }); }); }, child: Container( margin: EdgeInsets.all(10), decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.black, width: 1)), @@ -51,7 +51,9 @@ class FlowChartSelectedMenuState extends State { child: InkWell( mouseCursor: SystemMouseCursors.click, onTap: () { for (var sel in widget.dashboard.elementSelected) { - widget.dashboard.addElement(FlowElement.fromMap(widget.dashboard, sel.toMap())); + var el =FlowElement.fromMap(widget.dashboard, sel.toMap()); + el.id = Uuid().v8(); + widget.dashboard.addElement(FlowElement.fromMap(widget.dashboard, sel.toMap()), context); widget.dashboard.elements.last.position += Offset(50, 50); } Future.delayed(Duration(milliseconds: 100), () { @@ -67,6 +69,42 @@ class FlowChartSelectedMenuState extends State { ) : Container() ]) )); + } else if (widget.isDashboardInfo && widget.dashboard.arrowsSelected.length == 1) { + w = Container( + width: 200, + height: widget.height, + color: widget.dashboard.midDashColor, + child: SingleChildScrollView( child: Column( children: [ + widget.dashboard.infoItemWidget != null ? + widget.dashboard.infoLinkWidget!(widget.dashboard.arrowsSelected.first) : Container(), + widget.dashboard.arrowsSelected.isNotEmpty || widget.dashboard.elementSelected.isNotEmpty ? Container( + width: 200, + margin: EdgeInsets.only(top: 15), + decoration: BoxDecoration(border: Border( + top: BorderSide(color: Colors.grey, width: 1))), + child: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [ + Tooltip( message: "remove", + child: InkWell( mouseCursor: SystemMouseCursors.click, + onTap: () { + widget.dashboard.removeArrows((element) { + if (element.isSelected && element.elementIndex != null && element.connIndex != null) { + widget.dashboard.elements[element.elementIndex!].next.removeAt(element.connIndex!); + } + return element.isSelected; + }, context); + Future.delayed(Duration(milliseconds: 100), () { + widget.dashboard.flutterChartKey.currentState?.setState(() { }); + }); + }, child: Container( margin: EdgeInsets.all(10), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.black, width: 1)), + width: 200, height: 30, + child: Icon(Icons.delete_outline, color: Colors.black), + )) + ), + ]) + ) : Container() + ]) + )); } else if (widget.isDashboardInfo && widget.dashboard.infoWidget != null) { w = Container( width: 200, @@ -515,15 +553,14 @@ class FlowChartSelectedMenuState extends State { Tooltip( message: "remove", child: InkWell( mouseCursor: SystemMouseCursors.click, onTap: () { - widget.dashboard.removeArrows((element) { - if (element.isSelected && element.elementIndex != null && element.connIndex != null) { - widget.dashboard.elements[element.elementIndex!].next.removeAt(element.connIndex!); + widget.dashboard.removeElements((element) { + if (element.isSelected) { + widget.dashboard.arrows.removeWhere( (e) => e.toID.contains(element.id) || e.fromID.contains(element.id)); } return element.isSelected; - }); - widget.dashboard.removeElements((element) => element.isSelected); + }, context); Future.delayed(Duration(milliseconds: 100), () { - widget.dashboard.chartKey.currentState?.setState(() { }); + widget.dashboard.flutterChartKey.currentState?.setState(() { }); }); }, child: Container( margin: EdgeInsets.all(10), decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.black, width: 1)), @@ -535,7 +572,7 @@ class FlowChartSelectedMenuState extends State { child: InkWell( mouseCursor: SystemMouseCursors.click, onTap: () { for (var sel in widget.dashboard.elementSelected) { - widget.dashboard.addElement(FlowElement.fromMap(widget.dashboard, sel.toMap())); + widget.dashboard.addElement(FlowElement.fromMap(widget.dashboard, sel.toMap()), context); widget.dashboard.elements.last.position += Offset(50, 50); } Future.delayed(Duration(milliseconds: 100), () { diff --git a/library/flutter_flow_chart/lib/src/ui/draw_arrow.dart b/library/flutter_flow_chart/lib/src/ui/draw_arrow.dart index 22aea97..f7d73c5 100755 --- a/library/flutter_flow_chart/lib/src/ui/draw_arrow.dart +++ b/library/flutter_flow_chart/lib/src/ui/draw_arrow.dart @@ -211,6 +211,8 @@ class DrawingArrow extends ChangeNotifier { /// Arrow parameters. ArrowParams params = ArrowParams(); + List env = []; + List infos = []; String fromID = ""; String toID = ""; @@ -264,13 +266,16 @@ class DrawArrow extends StatefulWidget { required this.srcElement, required this.destElement, required List pivots, + this.infos = const [], + this.env = const [], super.key, ArrowParams? arrowParams, }) : arrowParams = arrowParams ?? ArrowParams(), pivots = PivotsNotifier(pivots); final int index; - + List env = []; + List infos = []; /// final ArrowParams arrowParams; @@ -340,6 +345,8 @@ class DrawArrowState extends State { builder: (context) { var painter = ArrowPainter( connIndex: widget.index, + infos: widget.infos, + env: widget.env, elementIndex: widget.flow.widget.dashboard.elements.indexOf(widget.srcElement), fromID: "${widget.srcElement.id}_${widget.index}", toID: "${widget.destElement.id}_${widget.index}", @@ -351,8 +358,8 @@ class DrawArrowState extends State { ); if ( widget.flow.widget.dashboard.arrows.where( (element) => element.fromID == "${widget.srcElement.id}_${widget.index}").isEmpty) { - widget.flow.widget.dashboard.addArrows(painter); - widget.flow.widget.dashboard.saveDash(widget.flow.widget.dashboard.id); + widget.flow.widget.dashboard.addArrows(painter, context); + widget.flow.widget.dashboard.saveDash(widget.flow.widget.dashboard.id, context); } else { var i = widget.flow.widget.dashboard.arrows.indexWhere( (element) => element.fromID == "${widget.srcElement.id}_${widget.index}"); @@ -390,7 +397,7 @@ class GraphParamsWidgetState extends State { child: Row(children: [ IconButton(onPressed: () { widget.comp.setState(() { - widget.comp.widget.dashboard.removeArrows((el) => el.fromID == "${widget.element.id}${widget.index}"); + widget.comp.widget.dashboard.removeArrows((el) => el.fromID == "${widget.element.id}${widget.index}", context); widget.element.next.removeAt(widget.index); }); }, icon: Icon(Icons.delete)) @@ -421,13 +428,13 @@ class ArrowInfoWidgetState extends State { /// [ArrowParams.startArrowPosition] and /// [ArrowParams.endArrowPosition] alignment. class ArrowPainter extends CustomPainter { - - /// ArrowPainter({ this.elementIndex, this.connIndex, this.toID = "", this.fromID = "", + this.infos = const [], + this.env = const [], this.isSelected = false, required this.params, this.from = Offset.zero, @@ -435,9 +442,9 @@ class ArrowPainter extends CustomPainter { List? pivots, }) : pivots = pivots ?? []; - /// + List env; + List infos; ArrowParams params; - /// String toID; String fromID; Offset to; @@ -462,6 +469,8 @@ class ArrowPainter extends CustomPainter { final arrowAngle= 25 * math.pi / 180; ArrowPainter deserialize(Map map) { + infos = map['infos']; + env = map['env']; params = ArrowParams.fromMap(map['params']); fromID = map['from']['id']; toID = map['to']['id']; @@ -469,9 +478,10 @@ class ArrowPainter extends CustomPainter { to = Offset(map['to']['x'], map['to']['y']); return this; } - Map serialize() { Map graphElement = {}; + graphElement['infos'] = infos; + graphElement['env'] = env; graphElement['from'] = { "id" : fromID.split("_")[0], "x" : from.dx, "y" : from.dy }; graphElement['to'] = { "id" : toID.split("_")[0], "x" : to.dx, "y" : to.dy }; graphElement['params'] = params.toMap(); @@ -484,6 +494,8 @@ class ArrowPainter extends CustomPainter { elementIndex: map['elementIndex'] as int, toID: map['toID'] != null ? map['toID'] as String : "", fromID: map['fromID'] as String, + infos: map['infos'] as List, + env: map['env'] as List, isSelected: map['isSelected'] != null ? map['isSelected'] as bool : false, params: ArrowParams.fromMap(map['params']), from: Offset( @@ -511,6 +523,8 @@ class ArrowPainter extends CustomPainter { "fromDy" : from.dy, "toDx" : to.dx, "toDy" : to.dy, + "infos" : infos, + "env" : env, 'pivots': pivots.map((e) => e.toMap()).toList(), }; } diff --git a/library/flutter_flow_chart/lib/src/ui/element_widget.dart b/library/flutter_flow_chart/lib/src/ui/element_widget.dart index adc3d63..718e348 100755 --- a/library/flutter_flow_chart/lib/src/ui/element_widget.dart +++ b/library/flutter_flow_chart/lib/src/ui/element_widget.dart @@ -151,12 +151,15 @@ class ElementWidgetState extends State { for (var element in widget.dashboard.elements) { element.isSelected = false; element.dashboard.chartKey.currentState?. setState(() { }); + widget.dashboard.selectedMenuKey.currentState?. setState(() { }); } } - widget.element.isSelected = !widget.element.isSelected; - for (var sel in widget.dashboard.arrows) { sel.isSelected = false; } - widget.dashboard.selectedMenuKey.currentState?. setState(() { }); - Future.delayed(Duration(seconds: 1), () { DrawingArrow.instance.notifyListeners(); }); + Future.delayed(Duration(milliseconds: 100), () { + DrawingArrow.instance.notifyListeners(); + widget.element.isSelected = !widget.element.isSelected; + for (var sel in widget.dashboard.arrows) { sel.isSelected = false; } + widget.dashboard.selectedMenuKey.currentState?. setState(() { }); + }); }); widget.onElementPressed?.call(context, tapLocation); }, @@ -234,7 +237,7 @@ class ElementWidgetState extends State { sel.changePosition(sel.position + diff); } } - widget.dashboard.save!(widget.dashboard.id); + widget.dashboard.saveDash(widget.dashboard.id, context); }, ), ), @@ -263,7 +266,7 @@ class ElementWidgetState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.center, children: (!widget.isHovered ? [] : [ IconButton(tooltip: "remove element", onPressed: () { - widget.dashboard.removeElement(widget.element); + widget.dashboard.removeElement(widget.element, context); }, icon: Icon(Icons.delete_outline)), IconButton(tooltip: "copy element", onPressed: () { FlowElement newElement = FlowElement( @@ -274,7 +277,7 @@ class ElementWidgetState extends State { size: widget.element.size, widget: widget.element.widget, ); - widget.dashboard.addElement(newElement); + widget.dashboard.addElement(newElement, context); }, icon: Icon(Icons.copy, size: 20)), ])) ), diff --git a/pubspec.lock b/pubspec.lock index 8e737e3..01bd5c3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -69,10 +69,10 @@ packages: dependency: transitive description: name: collection - sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.19.0" + version: "1.18.0" convert: dependency: "direct main" description: @@ -411,18 +411,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.7" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "3.0.8" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: @@ -707,7 +707,7 @@ packages: dependency: transitive description: flutter source: sdk - version: "0.0.0" + version: "0.0.99" source_span: dependency: transitive description: @@ -728,10 +728,10 @@ packages: dependency: transitive description: name: stack_trace - sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.11.1" star_menu: dependency: "direct main" description: @@ -752,10 +752,10 @@ packages: dependency: transitive description: name: string_scanner - sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.2.0" super_clipboard: dependency: transitive description: @@ -824,10 +824,10 @@ packages: dependency: transitive description: name: test_api - sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.7.3" + version: "0.7.2" timezone: dependency: transitive description: @@ -896,10 +896,10 @@ packages: dependency: transitive description: name: vm_service - sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "14.3.0" + version: "14.2.5" web: dependency: transitive description: