This commit is contained in:
mr
2024-11-08 13:59:22 +01:00
parent 685badc59a
commit 1ca77b6611
69 changed files with 1601 additions and 1337 deletions

View File

@@ -0,0 +1,22 @@
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<ComputeFormsWidget> {
@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,),
]);
}
}

View File

@@ -11,7 +11,6 @@ class DataFormsWidget extends StatefulWidget {
}
class DataFormsWidgetState extends State<DataFormsWidget> {
@override Widget build(BuildContext context) {
print(widget.item.serialize());
return Column( children: [
WebReferenceFormsWidget(item: widget.item),
]);

View File

@@ -1,5 +1,7 @@
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';
@@ -18,7 +20,7 @@ class ProcessingFormsWidget extends StatefulWidget {
@override ProcessingFormsWidgetState createState() => ProcessingFormsWidgetState();
}
class ProcessingFormsWidgetState extends State<ProcessingFormsWidget> {
Widget getInputAndOutputVariableForms() {
Widget getInputAndOutputVariableForms(bool readOnly) {
var inList = widget.dash.GetArrowByElementID(widget.elementID, true);
var outList = widget.dash.GetArrowByElementID(widget.elementID, false);
List<Widget> res = [];
@@ -40,16 +42,17 @@ class ProcessingFormsWidgetState extends State<ProcessingFormsWidget> {
}
if (inItems.isNotEmpty) {
res.add(SubKeysMapFormsWidget(dash: widget.dash, isInput: true, item: widget.item, elementID: widget.elementID,
categoryKey: "container", varKey: "env", graphItems: inItems));
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));
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<Widget> categories = [];
var l = widget.item.model?.model?.keys ?? [];
for (var child in l) {
@@ -59,11 +62,14 @@ class ProcessingFormsWidgetState extends State<ProcessingFormsWidget> {
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, initialValue: widget.item.getVariable([child, st], widget.item.serialize()),
width: 200, empty: children.isEmpty, change: (value) {
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) {
@@ -78,41 +84,40 @@ class ProcessingFormsWidgetState extends State<ProcessingFormsWidget> {
}
}
categories.add(Container(
padding: const EdgeInsets.all(10),
width: 250,
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: 200, empty: false, change: (value) {},
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(),
getInputAndOutputVariableForms(readOnly),
],)
));
}
// EXPOSE
categories.add(Container(
padding: const EdgeInsets.all(10),
width: 250,
decoration: const BoxDecoration(border: Border(top: BorderSide(color: Colors.grey, width: 1))),
padding: const EdgeInsets.symmetric(vertical: 10),
width: 180,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Padding(padding: EdgeInsets.only(bottom: 5), child: Text("<EXPOSE>",
style: TextStyle(fontSize: 13, fontWeight: FontWeight.bold), textAlign: TextAlign.center)),
Row( children: [
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(left: 15, top: 5),
Container( margin: const EdgeInsets.only(top: 5),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.grey, width: 1)),
width: 150, height: 30,
width: 125, height: 30,
child: const Row( mainAxisAlignment: MainAxisAlignment.center,
children: [ Padding( padding: EdgeInsets.only(right: 5), child: Icon(Icons.add)), Text("add exposure")]),
children: [ Padding( padding: EdgeInsets.only(right: 5), child: Icon(Icons.add)), Text("add expose")]),
)
),
InkWell( onTap: () {
@@ -122,7 +127,7 @@ class ProcessingFormsWidgetState extends State<ProcessingFormsWidget> {
el!.element = widget.item as dynamic;
setState(() {});
}, child:
Container( margin: const EdgeInsets.only(left: 5, right: 10, top: 5),
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,
@@ -133,10 +138,10 @@ class ProcessingFormsWidgetState extends State<ProcessingFormsWidget> {
],)
));
for (var expose in widget.item.expose) {
categories.add(SubExposeFormsWidget( width: 200, dash: dash, empty: categories.isEmpty,
categories.add(SubExposeFormsWidget( readOnly: readOnly, width: 180, dash: dash, empty: categories.isEmpty,
item: expose, elementID: widget.elementID));
}
return SizedBox( height: MediaQuery.of(context).size.height - 330, child: SingleChildScrollView( child: Column(
return SizedBox( height: getHeight(context) - 330, child: SingleChildScrollView( child: Column(
children: categories )) );
}
}

View File

@@ -3,12 +3,12 @@ import 'package:cron/cron.dart';
import 'package:intl/intl.dart' as intl;
import 'package:flutter/material.dart';
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
import 'package:flutter_advanced_switch/flutter_advanced_switch.dart';
import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
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/main.dart';
import 'package:oc_front/pages/shared.dart';
import 'package:oc_front/pages/workflow.dart';
import 'package:oc_front/widgets/dialog/alert.dart';
@@ -18,6 +18,9 @@ class SchedulerFormsWidget extends StatefulWidget {
Dashboard item;
String purpose = "";
bool? booking;
String? error;
String? errorEndDate;
String? errorCron;
Function validate = () {};
SchedulerFormsWidget ({ super.key, required this.item, });
@override SchedulerFormsWidgetState createState() => SchedulerFormsWidgetState();
@@ -26,9 +29,12 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
CheckService check = CheckService();
void save(List<GlobalKey<FormFieldState>> formKeys) {
dash.scheduleActive = !dash.scheduleActive;
widget.error = null;
widget.errorEndDate = null;
widget.errorCron = null;
for (var k in formKeys) {
if (k.currentState != null) {
if (!k.currentState!.validate()) {
if (!k.currentState!.validate() && dash.scheduleActive) {
dash.scheduleActive = !dash.scheduleActive;
return;
} else { k.currentState!.save();}
@@ -41,7 +47,6 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
dash.scheduler["end"] = now.add(const Duration(minutes: 1)).toUtc().toIso8601String();
}
}
print(widget.item.id);
widget.item.save!(widget.item.id);
}
void checkBooking(List<GlobalKey<FormFieldState>> formKeys, void Function(List<GlobalKey<FormFieldState>> )? f){
@@ -60,9 +65,7 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
(v) {
if (v.data == null) { return; }
widget.booking = v.data!.is_available;
print(v.data!.is_available);
if (v.data!.is_available) {
print(f);
if (f != null) { f(formKeys);
} else {
showAlertBanner( context, () {},
@@ -80,11 +83,13 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
}
@override Widget build(BuildContext context) {
bool isService = true;
try {
if (widget.item.scheduler["mode"] == null) { widget.item.scheduler["mode"] = 1; }
widget.item.elements.firstWhere((element) => (element.element?.serialize()["is_service"] ?? false) == true);
} catch (e) {
widget.item.scheduler = { "mode": 1 };
isService = false;
}
bool readOnly = !PermsService.getPerm(Perms.WORKFLOW_EDIT);
DateTime? start;
DateTime? end;
if (widget.item.scheduler["start"] != null) {
@@ -101,14 +106,13 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
widget.item.scheduler["end"] = end.toUtc().toIso8601String();
}
}
List<GlobalKey<FormFieldState>> formKeys = [GlobalKey<FormFieldState>(), GlobalKey<FormFieldState>(),
GlobalKey<FormFieldState>(), GlobalKey<FormFieldState>()];
List<GlobalKey<FormFieldState>> formKeys = [GlobalKey<FormFieldState>(), GlobalKey<FormFieldState>(), GlobalKey<FormFieldState>(), GlobalKey<FormFieldState>()];
var shallow = ShallowTextInputWidget(
width: 250 - 1,
width: 200 - 1, readOnly: readOnly,
current: widget.item.name,
type: SharedWorkspaceType.workflow,
canRemove: (p0) => p0 != null && p0.isNotEmpty,
remove: (p0) async {
type: CollaborativeAreaType.workflow,
canRemove: PermsService.getPerm(Perms.WORKFLOW_DELETE) ? (p0) => p0 != null && p0.isNotEmpty : null,
remove: PermsService.getPerm(Perms.WORKFLOW_DELETE) ? (p0) async {
await WorflowService().delete(context, widget.item.id ?? "", {}).then((value) {
dash.id = null;
dash.name = "";
@@ -116,7 +120,7 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
dash.clear();
dash.chartKey.currentState?.widget.flowChart.setState(() { });
});
},
} : null,
);
shallow.change =(p0) => Future.delayed( const Duration(seconds: 2), () async {
if (shallow.compare == p0) {
@@ -126,7 +130,7 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
}
});
return Column( children: [
Container( padding: const EdgeInsets.all(10), width: 250, height: 60,
Container( padding: const EdgeInsets.all(10), width: 200, height: 60,
decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),
child: const Column( mainAxisAlignment: MainAxisAlignment.center, children: [
Text("WORKFLOW INFO", style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
@@ -134,32 +138,17 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
])),
widget.item.name == "" ? Container() : Container(
decoration: BoxDecoration( border: Border(
left: BorderSide(color: Colors.grey.shade300, width: 1),
left: BorderSide(color: midColor, width: 1),
bottom: const BorderSide(color: Colors.grey))),
child: shallow ),
const SizedBox(height: 20, width: 250 ),
AdvancedSwitch(
width: 140,
initialValue: widget.item.scheduler["mode"] == 1,
activeColor: Colors.green, inactiveColor: Colors.green,
activeChild: const Text("simple task", style: TextStyle(color: Colors.white)),
inactiveChild: const Text("cron task", style: TextStyle(color: Colors.white)),
borderRadius: const BorderRadius.all(Radius.circular(15)), height: 30.0, disabledOpacity: 0.5,
onChanged: (value) {
Future.delayed(const Duration(milliseconds: 100), () =>
setState(() {
widget.item.scheduler["mode"] = value == true ? 1 : 0;
if ((widget.item.scheduler["mode"] == 1 )) { widget.item.scheduler.remove("cron"); }
widget.item.save!(widget.item.id);
}));
},),
Container(height: 5),
Tooltip( message: "event name",
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: 20),
child: TextFormField( key: formKeys[0],
initialValue: "${widget.item.scheduler["mode"] == 1 ? "" : "cron_"}${widget.item.scheduler["name"] ?? "${widget.item.name}_event"}",
enabled: !dash.scheduleActive,
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) {
@@ -169,30 +158,36 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
widget.item.scheduler["name"] = value;
},
onSaved: (value) {
widget.item.scheduler["name"] = value ?? "${widget.item.scheduler["mode"] == 1 ? "" : "cron_"}${widget.item.scheduler["name"] ?? "${widget.item.name}_event"}";
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;
},
validator: (value) => value == null || value.isEmpty ? "not empty" : null,
style: const TextStyle(fontSize: 12),
decoration: const InputDecoration(
decoration: InputDecoration(
floatingLabelBehavior: FloatingLabelBehavior.always,
fillColor: Colors.white,
filled: true,
hintText: "enter event name...",
labelText: "event name*",
errorStyle: TextStyle(fontSize: 0),
hintText: "enter executions name...",
labelText: "executions name*",
hintStyle: TextStyle(fontSize: 10),
labelStyle: TextStyle(fontSize: 10),
error: null,
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
border: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
focusedErrorBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.error != null ? Colors.red : Colors.black)),
errorBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.error != null ? Colors.red : Colors.black)),
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.error != null ? Colors.red : Colors.black)),
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.error != null ? Colors.red : Colors.grey)),
border: OutlineInputBorder(borderSide: BorderSide(color: widget.error != null ? Colors.red : Colors.grey)),
contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
),
))),
Tooltip( message: "start event",
Tooltip( message: "start executions",
child: Container( height: 40, margin: const EdgeInsets.only(top: 5),
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 20),
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
child: DateTimeField( key: formKeys[1],
enabled: !dash.scheduleActive,
enabled: !dash.scheduleActive && !readOnly,
resetIcon: null,
onShowPicker: (context, currentValue) async {
var date = await showDatePicker(
@@ -202,7 +197,7 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
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,
background: midColor,
tertiary: Colors.grey,
secondary: Colors.grey,
primary: Colors.black),
@@ -236,7 +231,7 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
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,
background: midColor,
tertiary: Colors.grey,
secondary: Colors.grey,
primary: Colors.black),
@@ -258,16 +253,17 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
format: intl.DateFormat('y-M-dd HH:mm:ss'),
initialValue: start?.toLocal() ?? DateTime.now(),
onChanged: (value) { },
validator: (value) => value == null ? "not empty" : null,
validator: (value) {
return value == null ? "not empty" : null;
},
style: const TextStyle(fontSize: 12),
decoration: const InputDecoration(
floatingLabelBehavior: FloatingLabelBehavior.always,
fillColor: Colors.white,
filled: true,
alignLabelWithHint: false,
hintText: "enter start event...",
labelText: "start event*",
errorStyle: TextStyle(fontSize: 0),
hintText: "enter start executions...",
labelText: "start executions*",
hintStyle: TextStyle(fontSize: 10),
labelStyle: TextStyle(fontSize: 10),
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
@@ -275,13 +271,18 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
),
))),
Tooltip( message: "end event",
Tooltip( message: "end executions",
child: Container( height: 40, margin: const EdgeInsets.only(top: 5),
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 20),
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
child: DateTimeField( key: formKeys[2],
enabled: !dash.scheduleActive,
enabled: !dash.scheduleActive && !readOnly,
validator: (value) {
return value == null && !(widget.item.scheduler["mode"] == 1 ) ? "not empty" : null;
if (value == null && widget.item.scheduler["cron"] != null && widget.item.scheduler["cron"].isNotEmpty) {
setState(() {
widget.errorEndDate = 'missing start date';
});
}
return value == null && widget.item.scheduler["cron"] != null && widget.item.scheduler["cron"].isNotEmpty ? "not empty" : null;
},
onChanged: (value) {
if (value == null) {
@@ -297,7 +298,7 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
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,
background: midColor,
tertiary: Colors.grey,
secondary: Colors.grey,
primary: Colors.black),
@@ -321,11 +322,12 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
while(date!.microsecondsSinceEpoch <= (DateTime.now().microsecondsSinceEpoch)
|| time == null
|| (date.microsecondsSinceEpoch) <= (DateTime.parse(widget.item.scheduler["start"] ?? DateTime.now().toIso8601String()).microsecondsSinceEpoch)) {
if (count > 0) {
showAlertBanner( context, () {},
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!
alertBannerLocation: AlertBannerLocation.bottom,);
}
// ignore: use_build_context_synchronously
time = await showTimePicker(context: context,
initialTime: TimeOfDay(hour: date.hour, minute: date.minute),
builder: (BuildContext context, Widget? child) {
@@ -334,7 +336,7 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
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,
background: midColor,
tertiary: Colors.grey,
secondary: Colors.grey,
primary: Colors.black),
@@ -361,21 +363,23 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
floatingLabelBehavior: FloatingLabelBehavior.always,
filled: true,
alignLabelWithHint: false,
hintText: "enter end event...",
labelText: "end event${!(widget.item.scheduler["mode"] == 1) ? "*" : ""}",
errorStyle: const TextStyle(fontSize: 0),
hintText: "enter end executions...",
labelText: "end executions",
hintStyle: const TextStyle(fontSize: 10),
labelStyle: const TextStyle(fontSize: 10),
enabledBorder: const OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
border: const OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
focusedErrorBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.errorEndDate != null ? Colors.red : Colors.black)),
errorBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.errorEndDate != null ? Colors.red : Colors.black)),
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.errorEndDate != null ? Colors.red : Colors.black)),
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.errorEndDate != null ? Colors.red : Colors.grey)),
border: OutlineInputBorder(borderSide: BorderSide(color: widget.errorEndDate != null ? Colors.red : Colors.grey)),
contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
),
))),
widget.item.scheduler["mode"] == 1 ? Container() : Tooltip( message: "schedule",
Tooltip( message: "cron command",
child: Container( height: 40, margin: const EdgeInsets.only(top: 5),
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 20),
padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
child: TextFormField( key: formKeys[3],
enabled: !dash.scheduleActive,
enabled: !dash.scheduleActive && !readOnly,
initialValue: widget.item.scheduler["cron"],
onChanged: (value) {
Future.delayed(const Duration(seconds: 100), () {
@@ -392,58 +396,67 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
},
validator: (value) {
var cron = Cron();
try {
cron.schedule(Schedule.parse(value ?? ""), () {});
} catch (e) {
return "invalid cron";
if (value != null && value.isNotEmpty) {
try {
cron.schedule(Schedule.parse(value), () {});
} catch (e) {
setState(() {
widget.errorCron = e.toString();
});
return "invalid cron";
}
}
return value == null || value.isEmpty ? "not empty" : null;
return null;
},
style: const TextStyle(fontSize: 12),
decoration: const InputDecoration(
decoration: InputDecoration(
floatingLabelBehavior: FloatingLabelBehavior.always,
fillColor: Colors.white,
filled: true,
hintText: "enter schedule...",
labelText: "schedule*",
errorStyle: TextStyle(fontSize: 0),
hintText: "enter cron command...",
labelText: "cron",
errorStyle: TextStyle(height: 0),
hintStyle: TextStyle(fontSize: 10),
labelStyle: TextStyle(fontSize: 10),
error: null,
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
border: OutlineInputBorder(borderSide: BorderSide(color: Colors.grey)),
focusedErrorBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.errorCron != null ? Colors.red : Colors.black)),
errorBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.errorCron != null ? Colors.red : Colors.black)),
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.errorCron != null ? Colors.red : Colors.black)),
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.errorCron != null ? Colors.red : Colors.grey)),
border: OutlineInputBorder(borderSide: BorderSide(color: widget.errorCron != null ? Colors.red : Colors.grey)),
contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
),
))),
Container(
width: 250,
width: 200,
height: 20,
decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),
),
const SizedBox(
width: 250,
width: 200,
height: 10,
),
Tooltip( message: "check booking",
child: InkWell( mouseCursor: SystemMouseCursors.click,
onTap: () {
checkBooking(formKeys, null);
}, child: Container( margin: const EdgeInsets.only(bottom: 5),
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 ? Colors.black : (widget.booking == true || dash.scheduleActive ? Colors.green : Colors.red), width: 1)),
border: Border.all(color: widget.booking == null && !dash.scheduleActive ? (
PermsService.getPerm(Perms.WORKFLOW_BOOKING) && PermsService.getPerm(Perms.WORKFLOW_EDIT) ? Colors.black : Colors.grey) : (
widget.booking == true || dash.scheduleActive ? 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 : Colors.red)),
color: widget.booking == null && !dash.scheduleActive ? Colors.black : (widget.booking == true || dash.scheduleActive ? Colors.green : redColor)),
))
),
Tooltip( message: dash.scheduleActive ? "unbook" : "book",
child: InkWell( mouseCursor: SystemMouseCursors.click,
onTap: () {
dash.scheduleActive ? setState(() { save(formKeys); }) : checkBooking(formKeys, save);
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),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(5),
border: Border.all(color: dash.scheduleActive ? Colors.green : Colors.black)),
border: Border.all(color: dash.scheduleActive ? Colors.green : ( PermsService.getPerm(Perms.WORKFLOW_BOOKING) ?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),
@@ -452,17 +465,17 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
widget.item.info["shared"] != null && (widget.item.info["shared"] as List<dynamic>).isNotEmpty ? Column( children: [
Container(
height: 20,
width: 250,
width: 200,
decoration: const BoxDecoration(border: Border(top: BorderSide(color: Colors.black))),
),
Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 20),
Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 10),
child:Text( textAlign: TextAlign.center, overflow: TextOverflow.ellipsis,
style: const TextStyle(fontSize: 14, color: Colors.black, fontWeight: FontWeight.bold),
"Workflow is shared in ${(widget.item.info["shared"] as List<dynamic>).length} workspace(s)")),
...(widget.item.info["shared"] as List<dynamic>).where( (e) => SharedWorkspaceLocal.getSharedWorkspace(e) != null
...(widget.item.info["shared"] as List<dynamic>).where( (e) => CollaborativeAreaLocal.getCollaborativeArea(e) != null
).map((e) {
var sw = SharedWorkspaceLocal.getSharedWorkspace(e);
return Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 5),
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)),
Text(style: const TextStyle(fontSize: 12, color: Colors.grey),

View File

@@ -5,12 +5,13 @@ import 'package:oc_front/models/search.dart';
import 'package:oc_front/widgets/inputs/sub_text_input.dart';
class SubExposeFormsWidget extends StatefulWidget {
bool readOnly;
Expose item;
Dashboard dash;
String elementID = "";
double width = 200;
double width = 180;
bool empty = false;
SubExposeFormsWidget ({ super.key, required this.dash,
SubExposeFormsWidget ({ super.key, required this.dash, this.readOnly = false,
this.empty = false, required this.item, required this.elementID, required this.width });
@override SubExposeFormsWidgetState createState() => SubExposeFormsWidgetState();
}
@@ -19,9 +20,10 @@ class SubExposeFormsWidgetState extends State<SubExposeFormsWidget> {
return Column( children : [
Container( margin: const EdgeInsets.only(left: 10, right: 10, top: 5),
decoration: BoxDecoration(border: Border.all(color: Colors.grey, width: 1)),
width: 250
width: 180
),
SubTextInputWidget(subkey: "reference port", initialValue: widget.item.port != null ? '${widget.item.port}' : null,
SubTextInputWidget(subkey: "reference port", readOnly: widget.readOnly,
initialValue: widget.item.port != null ? '${widget.item.port}' : null,
width: widget.width, empty: widget.empty, change: (value) {
try {
widget.item.port = int.parse(value);
@@ -34,7 +36,9 @@ class SubExposeFormsWidgetState extends State<SubExposeFormsWidget> {
var el = widget.dash.getElement(widget.elementID);
el!.element = widget.item as dynamic;
}),
SubTextInputWidget(subkey: "PAT", initialValue: widget.item.PAT != null ? '${widget.item.PAT}' : null,
SubTextInputWidget(
readOnly: widget.readOnly,
subkey: "PAT", initialValue: widget.item.PAT != null ? '${widget.item.PAT}' : null,
width: widget.width, empty: widget.empty, change: (value) {
try {
widget.item.PAT = int.parse(value);
@@ -48,6 +52,7 @@ class SubExposeFormsWidgetState extends State<SubExposeFormsWidget> {
el!.element = widget.item as dynamic;
}),
SubTextInputWidget(subkey: "reverse path", initialValue: widget.item.PAT != null ? '${widget.item.PAT}' : null,
readOnly: widget.readOnly,
width: widget.width, empty: widget.empty, change: (value) {
try {
widget.item.path = value;

View File

@@ -6,6 +6,7 @@ import 'package:oc_front/models/workflow.dart';
import 'package:oc_front/widgets/inputs/sub_text_input.dart';
class SubKeysMapFormsWidget extends StatefulWidget {
bool readOnly = false;
FlowData item;
Dashboard dash;
String varKey = "";
@@ -14,7 +15,7 @@ class SubKeysMapFormsWidget extends StatefulWidget {
String elementID = "";
String categoryKey = "";
List<GraphItem> graphItems = [];
SubKeysMapFormsWidget({ super.key, required this.dash, required this.isInput,
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 });
@override SubKeysMapFormsWidgetState createState() => SubKeysMapFormsWidgetState();
@@ -31,7 +32,7 @@ class SubKeysMapFormsWidgetState extends State<SubKeysMapFormsWidget> {
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<String, dynamic>) { continue; }
if (env == null || env is Map<String, dynamic>) { continue; }
var n = "${el.topic.toUpperCase()}_${el.getName().toUpperCase().replaceAll(" ", "_")}_${r.toUpperCase()}_$count";
if (env[n] == null) {
save = true;
@@ -39,7 +40,8 @@ class SubKeysMapFormsWidgetState extends State<SubKeysMapFormsWidget> {
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: 200, empty: false, change: (value) {}, initialValue: n, readOnly: true, noLabel: true)));
child: SubTextInputWidget(subkey: n, width: 180, empty: false, change: (value) {},
initialValue: n, readOnly: true, noLabel: true)));
count++;
}
}
@@ -50,7 +52,7 @@ class SubKeysMapFormsWidgetState extends State<SubKeysMapFormsWidget> {
return Container();
}
return Column( children : [
Container(width: 250, padding: const EdgeInsets.only(top: 10, bottom: 10),
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),

View File

@@ -10,6 +10,7 @@ class MapForm {
}
class SubMapFormsWidget extends StatefulWidget {
bool readOnly;
String categoryKey = "";
String varKey = "";
String elementID = "";
@@ -17,7 +18,7 @@ class SubMapFormsWidget extends StatefulWidget {
Dashboard dash;
bool empty = false;
List<MapForm> forms = [];
SubMapFormsWidget ({ super.key, required this.dash,
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();
@@ -44,8 +45,9 @@ class SubMapFormsWidgetState extends State<SubMapFormsWidget> {
continue;
}
widget.forms.add(MapForm(key: key, value: m[key]));
children.add(Padding( padding: const EdgeInsets.symmetric(horizontal: 15), child: Row( children: [
SubTextInputWidget(subkey: "key", initialValue: key, width: 91, empty: widget.empty,
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;
@@ -58,8 +60,8 @@ class SubMapFormsWidgetState extends State<SubMapFormsWidget> {
});
}),
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: 90.8, empty: widget.empty,
change: (value) {
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.save!(widget.dash.id);
});
@@ -69,13 +71,13 @@ class SubMapFormsWidgetState extends State<SubMapFormsWidget> {
widget.item.setVariable(l, toMap(), widget.item.serialize())) as dynamic;
el!.element = widget.item as dynamic;
}),
])));
]));
i++;
}
return Column( children : [
Container(width: 250, padding: const EdgeInsets.only(top: 10),
Container(width: 200, padding: const EdgeInsets.only(top: 10),
decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),),
Row( children: [
widget.readOnly ? Container() : Row( children: [
InkWell( onTap: () {
widget.forms.add(MapForm(key: "", value: ""));
var el = widget.dash.getElement(widget.elementID);
@@ -83,9 +85,9 @@ class SubMapFormsWidgetState extends State<SubMapFormsWidget> {
widget.item.setVariable(l, toMap(), widget.item.serialize())) as dynamic;
el!.element = widget.item as dynamic;
setState(() {});
}, child: Container( margin: const EdgeInsets.only(left: 15, top: 10),
}, child: Container( margin: const EdgeInsets.only(top: 10),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.grey, width: 1)),
width: 150, height: 30,
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")]),
),
@@ -99,7 +101,7 @@ class SubMapFormsWidgetState extends State<SubMapFormsWidget> {
el!.element = widget.item as dynamic;
setState(() { widget.dash.save!(widget.dash.id); });
}, child:
Container( margin: const EdgeInsets.only(left: 5, right: 10, top: 10),
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,

View File

@@ -9,14 +9,14 @@ class WebReferenceFormsWidget extends StatefulWidget {
class WebReferenceFormsWidgetState extends State<WebReferenceFormsWidget> {
@override Widget build(BuildContext context) {
return Column( children: [
SubTextInputWidget(subkey: "path", width: 200, empty: false, change: (value) {
widget.item.protocols = value.split(",");
SubTextInputWidget(subkey: "path", width: 180, empty: false, change: (value) {
widget.item.path = value.split(",");
}, initialValue: widget.item.path, readOnly: true,),
SubTextInputWidget(subkey: "protocol", width: 200, empty: false, change: (value) {
widget.item.protocols = value.split(",");
SubTextInputWidget(subkey: "protocol", width: 180, empty: false, change: (value) {
widget.item.protocol = value.split(",");
}, initialValue: widget.item.protocol, readOnly: true,),
SubTextInputWidget(subkey: "type", width: 200, empty: false, change: (value) {
widget.item.protocols = value.split(",");
SubTextInputWidget(subkey: "type", width: 180, empty: false, change: (value) {
widget.item.type = value.split(",");
}, initialValue: widget.item.type, readOnly: true,),
]);
}