intermediate
This commit is contained in:
@@ -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) )
|
||||
]
|
||||
);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 )
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) { },
|
||||
|
||||
Reference in New Issue
Block a user