intermediate

This commit is contained in:
mr
2024-08-08 08:42:32 +02:00
parent 593f03648b
commit ceeebfc964
74 changed files with 3784 additions and 634 deletions

View File

@@ -1,11 +1,12 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:oc_front/core/sections/header/header.dart';
import 'package:oc_front/core/services/specialized_services/resource_service.dart';
import 'package:oc_front/models/search.dart';
import 'package:oc_front/widgets/catalog.dart';
import 'package:oc_front/pages/abstract_page.dart';
import 'package:oc_front/core/sections/header/search.dart';
import 'package:oc_front/core/services/specialized_services/search_service.dart';
import 'package:oc_front/widgets/menu_clipper/workspace_menu.dart';
class CatalogFactory implements AbstractFactory {
static List<AbstractItem> items = [];
@@ -13,10 +14,10 @@ class CatalogFactory implements AbstractFactory {
@override bool searchFill() { return CatalogFactory.items.isEmpty; }
@override Widget factory(GoRouterState state, List<String> args) { return CatalogPageWidget(); }
@override void search(BuildContext context) {
CatalogFactory.key.currentState?.widget.search.get(context, SearchConstants.get()!).then((value) {
CatalogFactory.key.currentState?.widget.search.search(context, [ SearchConstants.get()! ], {}).then((value) {
if (value.data == null) { return; }
CatalogFactory.items = [
...value.data!.computing, ...value.data!.data, ...value.data!.storage, ...value.data!.datacenter,];
CatalogFactory.items = [ ...value.data!.workflows,
...value.data!.processings, ...value.data!.datas, ...value.data!.storages, ...value.data!.datacenters,];
searchWidgetKey.currentState?.setState(() {});
CatalogFactory.key.currentState?.setState(() {});
});
@@ -24,16 +25,17 @@ class CatalogFactory implements AbstractFactory {
}
class CatalogPageWidget extends StatefulWidget {
final SearchService search = SearchService();
final ResourceService search = ResourceService();
CatalogPageWidget (): super(key: CatalogFactory.key);
@override CatalogPageWidgetState createState() => CatalogPageWidgetState();
}
class CatalogPageWidgetState extends State<CatalogPageWidget> {
@override Widget build(BuildContext context) {
return Column( children : [
CatalogFactory.items.isEmpty ? Container() : MenuWorkspaceWidget(),
SizedBox(
width: MediaQuery.of(context).size.width,
height: CatalogFactory.items.isEmpty ? 0 : MediaQuery.of(context).size.height - HeaderConstants.height,
height: CatalogFactory.items.isEmpty ? 0 : MediaQuery.of(context).size.height - HeaderConstants.height - 50,
child: CatalogWidget(items: CatalogFactory.items) )
]
);

View File

@@ -16,8 +16,8 @@ class CatalogItemFactory implements AbstractFactory {
var item = CatalogFactory.items.firstWhere( (element) => element.id == id );
return CatalogItemPageWidget(item : item);
} catch (e) {
var item = WorkspaceLocal.getItem(id ?? "");
if (item != null) { return CatalogItemPageWidget(item : item); }
var item = WorkspaceLocal.getItem(id ?? "", false);
if (item != null) { return CatalogItemPageWidget(item : item as AbstractItem); }
return Container();
}
}

View File

@@ -1,7 +1,11 @@
import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart' as intl;
import 'package:go_router/go_router.dart';
import 'package:oc_front/core/services/specialized_services/workflow_execution_service.dart';
import 'package:oc_front/models/workflow.dart';
import 'package:oc_front/pages/abstract_page.dart';
import 'package:table_calendar/table_calendar.dart';
import 'package:oc_front/widgets/sheduler_items/schedule.dart';
class SchedulerFactory implements AbstractFactory {
static GlobalKey<SchedulerPageWidgetState> key = GlobalKey<SchedulerPageWidgetState>();
@@ -11,18 +15,169 @@ class SchedulerFactory implements AbstractFactory {
}
class SchedulerPageWidget extends StatefulWidget {
bool isList = true;
DateTime start = DateTime.now();
DateTime end = DateTime.now().add(const Duration(days: 180));
final WorkflowExecutionService _service = WorkflowExecutionService();
SchedulerPageWidget(): super(key: SchedulerFactory.key);
@override SchedulerPageWidgetState createState() => SchedulerPageWidgetState();
static void search(BuildContext context) { }
static Widget factory() { return SchedulerPageWidget(); }
}
class SchedulerPageWidgetState extends State<SchedulerPageWidget> {
List<Color> colors = [Colors.blue, Colors.orange, Colors.red, Colors.green];
List<String> titles = ["SCHEDULED", "RUNNING", "FAILURE", "SUCCESS"];
@override Widget build(BuildContext context) {
return TableCalendar(
firstDay: DateTime.utc(2010, 10, 16),
lastDay: DateTime.utc(2030, 3, 14),
focusedDay: DateTime.now(),
);
return FutureBuilder(
future: widget._service.search(context, [
"${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) {
Map<String, List<WorkflowExecution>> data = {};
if (as.hasData && as.data!.data != null) {
for (var element in as.data!.data!.executions) {
if (element.executionData == null) { continue; }
DateTime dateTime = DateTime.parse(element.executionData!);
DateTime date = DateTime(dateTime.year, dateTime.month, dateTime.day);
var str = "${date.toIso8601String()}Z";
if (data[str] == null) { data[str] = []; }
data[str]!.add(element);
data[str]!.sort((a, b) => DateTime.parse(a.executionData!).compareTo(DateTime.parse(b.executionData!)));
}
}
GlobalKey<ScheduleWidgetState> k = GlobalKey<ScheduleWidgetState>();
return Column( children: [
Container( color: const Color.fromRGBO(38, 166, 154, 1),
height: 50, width: MediaQuery.of(context).size.width,
child: Padding(padding: const EdgeInsets.symmetric(horizontal: 50),
child: Row( children: [
Padding(padding: const EdgeInsets.only(right: 30),
child: Tooltip( message: widget.isList ? "calendar view" : "list view",
child: InkWell( child: Icon( widget.isList ? Icons.calendar_month : Icons.list, color: Colors.white
, size: 25 ),
onTap: () {
widget.isList = !widget.isList;
k.currentState?.setState(() { k.currentState?.widget.isList = widget.isList; });
})
),
),
Container(padding: const EdgeInsets.only(left: 20),
width: MediaQuery.of(context).size.width / 5,
height: 30,
child: DateTimeField(
validator: (value) {
return null;
},
resetIcon: const Icon(Icons.close, size: 15),
onShowPicker: (context, currentValue) async {
var date = await showDatePicker(
builder: (BuildContext context, Widget? child) {
Widget w = Theme(
data: ThemeData(
cardTheme: CardTheme(elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0))),
dialogTheme: DialogTheme(elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0))),
colorScheme: ColorScheme.light(
background: Colors.grey.shade300,
tertiary: Colors.grey,
secondary: Colors.grey,
primary: Colors.black),
),
child: child ?? Container(),
);
return w;
},
context: context,
firstDate: DateTime(1900),
initialDate: widget.start,
lastDate: DateTime(2100)
);
return date;
},
format: intl.DateFormat('y-M-dd hh:mm:ss'),
initialValue: widget.start,
onChanged: (value) {
if (value == null) { return; }
setState(() { widget.start = value; });
},
style: const TextStyle(fontSize: 12),
decoration: const InputDecoration(
fillColor: Colors.white,
floatingLabelBehavior: FloatingLabelBehavior.always,
filled: true,
alignLabelWithHint: false,
hintText: "enter start date...",
labelText: "",
errorStyle: TextStyle(fontSize: 0),
hintStyle: TextStyle(fontSize: 10),
labelStyle: TextStyle(fontSize: 15, color: Colors.black, fontWeight: FontWeight.w500),
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.transparent)),
border: OutlineInputBorder(borderSide: BorderSide(color: Colors.transparent)),
contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
),
)
),
Container(padding: const EdgeInsets.only(left: 20),
child: const Text("TO", style: TextStyle(color: Colors.white, fontSize: 15, fontWeight: FontWeight.w500))),
Container( padding: const EdgeInsets.only(left: 20),
width: MediaQuery.of(context).size.width / 5,
height: 30,
child: DateTimeField(
validator: (value) {
return null;
},
resetIcon: const Icon(Icons.close, size: 15),
onShowPicker: (context, currentValue) async {
var date = await showDatePicker(
builder: (BuildContext context, Widget? child) {
Widget w = Theme(
data: ThemeData(
cardTheme: CardTheme(elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0))),
dialogTheme: DialogTheme(elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0))),
colorScheme: ColorScheme.light(
background: Colors.grey.shade300,
tertiary: Colors.grey,
secondary: Colors.grey,
primary: Colors.black),
),
child: child ?? Container(),
);
return w;
},
context: context,
firstDate: DateTime(1900),
initialDate: widget.end,
lastDate: DateTime(2100)
);
return date;
},
format: intl.DateFormat('y-M-dd hh:mm:ss'),
initialValue: widget.end,
onChanged: (value) {
if (value == null) { return; }
setState(() { widget.start = value; });
},
style: const TextStyle(fontSize: 12),
decoration: const InputDecoration(
fillColor: Colors.white,
floatingLabelBehavior: FloatingLabelBehavior.always,
filled: true,
alignLabelWithHint: false,
hintText: "enter end date...",
labelText: "",
errorStyle: TextStyle(fontSize: 0),
hintStyle: TextStyle(fontSize: 10),
labelStyle: TextStyle(fontSize: 15, color: Colors.black, fontWeight: FontWeight.w500),
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.transparent)),
border: OutlineInputBorder(borderSide: BorderSide(color: Colors.transparent)),
contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
),
)
)
]))
),
ScheduleWidget( key: k, data: data, start: widget.start, end : widget.end, isList: widget.isList )
]);
});
}
}
}

View File

@@ -1,5 +1,3 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
import 'package:go_router/go_router.dart';
@@ -8,10 +6,16 @@ import 'package:oc_front/core/sections/header/header.dart';
import 'package:oc_front/core/services/specialized_services/workflow_service.dart';
import 'package:oc_front/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/widgets/dialog/new_box.dart';
import 'package:oc_front/widgets/forms/proxy_forms.dart';
import 'package:oc_front/widgets/forms/scheduler_forms.dart';
import 'package:oc_front/widgets/items/item_row.dart';
Dashboard dash = Dashboard(name: "workflow_${DateTime.now().toString().replaceAll(" ", "_").substring(0, DateTime.now().toString().length - 7)}");
import 'package:oc_front/widgets/menu_clipper/workspace_menu.dart';
Dashboard dash = Dashboard(
name: "workflow_${DateTime.now().toString().replaceAll(" ", "_").substring(0, DateTime.now().toString().length - 7)}");
class WorkflowFactory implements AbstractFactory {
static GlobalKey<WorkflowPageWidgetState> key = GlobalKey<WorkflowPageWidgetState>();
@override bool searchFill() { return false; }
@@ -29,8 +33,10 @@ class WorkflowPageWidgetState extends State<WorkflowPageWidget> {
final WorflowService _service = WorflowService();
Widget itemBuild(Object item) {
var e = item as AbstractItem;
return e.logo != null ? Image.memory(base64Decode(e.logo ?? ""), fit: BoxFit.fill)
: Image.network('https://get-picto.com/wp-content/uploads/2024/01/logo-instagram-png.webp', fit: BoxFit.fill);
return Tooltip( message: item.name ?? "",
child: e.logo != null ? Image.network(e.logo ?? "", fit: BoxFit.fill)
: Image.network('https://get-picto.com/wp-content/uploads/2024/01/logo-instagram-png.webp',
fit: BoxFit.fill));
}
Widget itemTooltipBuild(Object item) {
var e = item as AbstractItem;
@@ -39,30 +45,113 @@ final WorflowService _service = WorflowService();
List<DropdownMenuItem> getItems(Object? data) {
data = data as APIResponse<RawData>?;
if (data != null && data.data != null && data.data!.values.isNotEmpty) {
return (data.data!.values as List<dynamic>).map((dynamic value) {
return data.data!.values.map((dynamic value) {
return DropdownMenuItem<String>(
value: value.toString(),
child: Text(value.toString()),
value: "${value["id"] ?? ""}~${value["name"] ?? ""}",
child: Text(value["name"]?.toString() ?? ""),
);
}).toList();
}
return [];
}
List<Widget> getForms(FlowData? obj) {
return obj == null ? [] : [
ProxyFormsWidget(item: obj as AbstractItem),
];
}
List<Widget> getDashInfoForms() {
return [
SchedulerFormsWidget(item: dash),
];
}
Future<void> loadDash(String selected) async {
if (selected.split("~").length > 1) {
dash.name = selected.split("~")[1];
dash.id = selected.split("~")[0];
} else {
dash.name = selected;
}
await _service.get(context, dash.id ?? "").then((value) {
if (value.data != null) {
dash.deserialize(value.data!.toDashboard());
}
});
}
Future<void> saveDash(String? id) async {
if (id == null || !dash.isOpened) { return; }
var datas = WorkspaceLocal.byTopic("data", true).where(
(element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) );
var dataCenter = WorkspaceLocal.byTopic("datacenter", true).where(
(element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) );
var storage = WorkspaceLocal.byTopic("storage", true).where(
(element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) );
var computing = WorkspaceLocal.byTopic("processing", true).where(
(element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) );
var workflows = WorkspaceLocal.byTopic("workflows", true).where(
(element) => dash.elements.map( (e) => e.element?.getID()).contains(element.id) );
var updateW = Workflow(
name: dash.name,
graph: Graph(),
data: datas.map((e) => e.id).toSet().toList(),
datacenter: dataCenter.map((e) => e.id).toSet().toList(),
storage: storage.map((e) => e.id).toSet().toList(),
processing: computing.map((e) => e.id).toSet().toList(),
workflows: workflows.map((e) => e.id).toSet().toList(),
);
updateW.fromDashboard(dash.serialize());
for (var item in (updateW.graph?.items.values ?? [] as List<GraphItem>)) {
if (item.position == null) { continue; }
item.position?.x = (item.position?.x ?? 0) + 52.5;
item.position?.y = (item.position?.y ?? 0) + 52.5;
}
print(dash.getZoomFactor());
updateW.graph?.zoom = dash.getZoomFactor();
await _service.put(context, id, updateW.serialize(), {});
}
FlowData? transformToData(Map<String, dynamic> data) {
var d = WorkspaceLocal.getItem(data["id"] ?? "", true);
if (d == null) { return null; }
d.model = ResourceModel().deserialize(data["resource_model"]);
if (d.topic == "data") { return d as DataItem; }
if (d.topic == "datacenter") { return d as DataCenterItem; }
if (d.topic == "storage") { return d as StorageItem; }
if (d.topic == "processing") { return d as ProcessingItem; }
if (d.topic == "workflows") { return d as WorkflowItem; }
return null;
}
Widget menuExtension() {
var quart = MediaQuery.of(context).size.width / 6;
return MenuWorkspaceWidget(simpliest: true, width: quart > 80 ? quart : 80,
onWorkspaceChange: () { dash.selectedLeftMenuKey.currentState?.setState(() { }); });
}
Widget onDashboardAlertOpened(BuildContext context, Dashboard dash) {
return NewBoxWidget<RawData>(service: _service, dash: dash,
return NewBoxWidget<Workflow>(service: _service, dash: dash,
getItems: getItems);
}
@override Widget build(BuildContext context) {
dash.load = loadDash;
dash.save = saveDash;
dash.transformToData = transformToData;
dash.infoItemWidget = getForms;
dash.infoWidget = getDashInfoForms;
var quart = MediaQuery.of(context).size.width / 6;
dash.defaultName = "workflow_${DateTime.now().toString().replaceAll(" ", "_").substring(0, DateTime.now().toString().length - 7)}";
return FlowChart<AbstractItem>(
onDashboardAlertOpened: onDashboardAlertOpened,
dashboard: dash,
itemWidget: itemBuild,
categories: const ["computing", "data", "datacenter", "storage"],
draggableItemBuilder: (cat) => WorkspaceLocal.byTopic(cat).toList(),
categories: const ["processing", "data", "datacenter", "storage", "workflows"],
draggableItemBuilder: (cat) => WorkspaceLocal.byTopic(cat, true).toList(),
itemWidgetTooltip: itemTooltipBuild,
innerMenuWidth: quart > 80 ? quart : 80,
menuExtension: menuExtension,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height - HeaderConstants.height,
onNewConnection: (p1, p2) { },