Rules on dashboard + Permissions
This commit is contained in:
parent
2ceab090fd
commit
7fea931b63
@ -42,51 +42,42 @@ Map<Perms, String> perms = {
|
|||||||
|
|
||||||
class PermsService {
|
class PermsService {
|
||||||
static final Map<Perms, bool> _perms = {
|
static final Map<Perms, bool> _perms = {
|
||||||
Perms.SEARCH_INTERNAL: true,
|
Perms.SEARCH_INTERNAL: false,
|
||||||
Perms.SEARCH_EXTERNAL: true,
|
Perms.SEARCH_EXTERNAL: false,
|
||||||
Perms.WORKSPACE_SHARE: true,
|
Perms.WORKSPACE_SHARE: false,
|
||||||
Perms.WORKSPACE_UNSHARE: true,
|
Perms.WORKSPACE_UNSHARE: false,
|
||||||
Perms.WORKFLOW_CREATE: true,
|
Perms.WORKFLOW_CREATE: false,
|
||||||
Perms.WORKFLOW_EDIT: true,
|
Perms.WORKFLOW_EDIT: false,
|
||||||
Perms.WORKFLOW_DELETE: true,
|
Perms.WORKFLOW_DELETE: false,
|
||||||
Perms.WORKFLOW_BOOKING: true,
|
Perms.WORKFLOW_BOOKING: false,
|
||||||
Perms.WORKFLOW_SHARE: true,
|
Perms.WORKFLOW_SHARE: false,
|
||||||
Perms.WORKFLOW_UNSHARE: true,
|
Perms.WORKFLOW_UNSHARE: false,
|
||||||
Perms.PEER_SHARE: true,
|
Perms.PEER_SHARE: false,
|
||||||
Perms.PEER_UNSHARE: true,
|
Perms.PEER_UNSHARE: false,
|
||||||
Perms.COLLABORATIVE_AREA_CREATE: true,
|
Perms.COLLABORATIVE_AREA_CREATE: false,
|
||||||
Perms.COLLABORATIVE_AREA_EDIT: true,
|
Perms.COLLABORATIVE_AREA_EDIT: false,
|
||||||
Perms.COLLABORATIVE_AREA_DELETE: true,
|
Perms.COLLABORATIVE_AREA_DELETE: false,
|
||||||
};
|
};
|
||||||
static final PermsService _instance = PermsService._internal();
|
static final PermsService _instance = PermsService._internal();
|
||||||
factory PermsService() => _instance;
|
factory PermsService() => _instance;
|
||||||
PermsService._internal();
|
PermsService._internal();
|
||||||
/* should decode claims such as in oc-auth */
|
/* should decode claims such as in oc-auth */
|
||||||
static Future<void> init(String token ) async {
|
static Future<void> init(String token ) async {
|
||||||
/* var claims = token.split(".").last;
|
var claims = token.split(".").last;
|
||||||
var decoded = base64.decode(claims);
|
var decoded = base64.decode(claims);
|
||||||
String foo = utf8.decode(decoded);
|
String foo = utf8.decode(decoded);
|
||||||
var what = json.decode(foo);
|
|
||||||
try {
|
try {
|
||||||
|
var what = json.decode(foo);
|
||||||
what = what["session"]["access_token"] as Map<String, dynamic>;
|
what = what["session"]["access_token"] as Map<String, dynamic>;
|
||||||
|
|
||||||
for (var w in perms.values) {
|
for (var w in perms.keys) {
|
||||||
|
if (what.keys.contains(perms[w])) {
|
||||||
if (what.keys.contains(w)) {
|
_perms[w] = true;
|
||||||
print("CONTAINS");
|
|
||||||
} else {
|
} else {
|
||||||
for (var y in what.keys) {
|
_perms[w] = false;
|
||||||
print("${w}, ${y} ${what.keys.contains(w)}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} catch (e) {/**/}
|
||||||
} catch (e) {
|
|
||||||
print("THERE");
|
|
||||||
}*/
|
|
||||||
|
|
||||||
_perms.forEach((key, value) {
|
|
||||||
_perms[key] = true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear() {
|
static void clear() {
|
||||||
|
@ -11,7 +11,6 @@ class WorkflowExecutionService extends AbstractService<WorkflowExecutions> {
|
|||||||
@override String subPath = "/";
|
@override String subPath = "/";
|
||||||
|
|
||||||
@override Future<APIResponse<WorkflowExecutions>> search(BuildContext? context, List<String> words, Map<String, dynamic> params) {
|
@override Future<APIResponse<WorkflowExecutions>> search(BuildContext? context, List<String> words, Map<String, dynamic> params) {
|
||||||
print("${subPath}search/${words.join("/")}");
|
|
||||||
return service.get("${subPath}search/${words.join("/")}", false, context);
|
return service.get("${subPath}search/${words.join("/")}", false, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,9 +26,6 @@ class SchedulerPageWidget extends StatefulWidget {
|
|||||||
static Widget factory() { return SchedulerPageWidget(); }
|
static Widget factory() { return SchedulerPageWidget(); }
|
||||||
}
|
}
|
||||||
class SchedulerPageWidgetState extends State<SchedulerPageWidget> {
|
class SchedulerPageWidgetState extends State<SchedulerPageWidget> {
|
||||||
List<Color> colors = [Colors.blue, Colors.orange, redColor, Colors.green, redColor];
|
|
||||||
List<String> titles = ["SCHEDULED", "RUNNING", "FAILURE", "SUCCESS", "FORGOTTEN"];
|
|
||||||
|
|
||||||
@override Widget build(BuildContext context) {
|
@override Widget build(BuildContext context) {
|
||||||
GlobalKey<ScheduleWidgetState> k = GlobalKey<ScheduleWidgetState>();
|
GlobalKey<ScheduleWidgetState> k = GlobalKey<ScheduleWidgetState>();
|
||||||
return Column( children: [
|
return Column( children: [
|
||||||
|
@ -290,6 +290,38 @@ final WorflowService _service = WorflowService();
|
|||||||
dash.infoItemWidget = getForms;
|
dash.infoItemWidget = getForms;
|
||||||
dash.infoWidget = getDashInfoForms;
|
dash.infoWidget = getDashInfoForms;
|
||||||
dash.widthOffset = 50;
|
dash.widthOffset = 50;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
];
|
||||||
return FlowChart<AbstractItem>(
|
return FlowChart<AbstractItem>(
|
||||||
key: dash.flutterChartKey,
|
key: dash.flutterChartKey,
|
||||||
itemLeftBottomBadges: getBottomLeftBadge,
|
itemLeftBottomBadges: getBottomLeftBadge,
|
||||||
|
@ -73,7 +73,7 @@ class ProcessingFormsWidgetState extends State<ProcessingFormsWidget> {
|
|||||||
widget.item.model ?? Model();
|
widget.item.model ?? Model();
|
||||||
Future.delayed(const Duration(seconds: 2), () {
|
Future.delayed(const Duration(seconds: 2), () {
|
||||||
if (widget.item.getVariable([child, st], widget.item.serialize()) == value) {
|
if (widget.item.getVariable([child, st], widget.item.serialize()) == value) {
|
||||||
dash.save!(dash.id);
|
dash.saveDash(dash.id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var el = dash.getElement(widget.elementID);
|
var el = dash.getElement(widget.elementID);
|
||||||
|
@ -48,7 +48,7 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
|
|||||||
dash.scheduler["end"] = now.add(const Duration(minutes: 1)).toUtc().toIso8601String();
|
dash.scheduler["end"] = now.add(const Duration(minutes: 1)).toUtc().toIso8601String();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
widget.item.save!(widget.item.id);
|
widget.item.saveDash(widget.item.id);
|
||||||
}
|
}
|
||||||
void checkBooking(List<GlobalKey<FormFieldState>> formKeys, void Function(List<GlobalKey<FormFieldState>> )? f){
|
void checkBooking(List<GlobalKey<FormFieldState>> formKeys, void Function(List<GlobalKey<FormFieldState>> )? f){
|
||||||
if (widget.item.scheduler["start"] == null) {
|
if (widget.item.scheduler["start"] == null) {
|
||||||
@ -93,12 +93,18 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
|
|||||||
bool readOnly = !PermsService.getPerm(Perms.WORKFLOW_EDIT);
|
bool readOnly = !PermsService.getPerm(Perms.WORKFLOW_EDIT);
|
||||||
DateTime? start;
|
DateTime? start;
|
||||||
DateTime? end;
|
DateTime? end;
|
||||||
|
|
||||||
|
Duration delayed = const Duration(minutes: 5);
|
||||||
if (widget.item.scheduler["start"] != null) {
|
if (widget.item.scheduler["start"] != null) {
|
||||||
start = DateTime.parse(widget.item.scheduler["start"]!);
|
start = DateTime.parse(widget.item.scheduler["start"]!);
|
||||||
if (start.isBefore(DateTime.now()) && !dash.scheduleActive) {
|
if (start.isBefore(DateTime.now()) && !dash.scheduleActive) {
|
||||||
start = DateTime.now().add(const Duration(minutes: 5));
|
start = DateTime.now().add(const Duration(minutes: 5));
|
||||||
widget.item.scheduler["start"] = start.toUtc().toIso8601String();
|
widget.item.scheduler["start"] = start.toUtc().toIso8601String();
|
||||||
}
|
}
|
||||||
|
if (start.isBefore(DateTime.now())) {
|
||||||
|
// get difference between now and start
|
||||||
|
delayed = start.difference(DateTime.now());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (widget.item.scheduler["end"] != null) {
|
if (widget.item.scheduler["end"] != null) {
|
||||||
end = DateTime.parse(widget.item.scheduler["end"]!);
|
end = DateTime.parse(widget.item.scheduler["end"]!);
|
||||||
@ -106,6 +112,13 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
|
|||||||
end = DateTime.now().add(const Duration(minutes: 5));
|
end = DateTime.now().add(const Duration(minutes: 5));
|
||||||
widget.item.scheduler["end"] = end.toUtc().toIso8601String();
|
widget.item.scheduler["end"] = end.toUtc().toIso8601String();
|
||||||
}
|
}
|
||||||
|
if (end.isBefore(DateTime.now())) {
|
||||||
|
// get difference between now and start
|
||||||
|
delayed = end.difference(DateTime.now());
|
||||||
|
}
|
||||||
|
Future.delayed(delayed, () {
|
||||||
|
WorkflowFactory.key.currentState?.setState(() { });
|
||||||
|
});
|
||||||
}
|
}
|
||||||
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(
|
var shallow = ShallowTextInputWidget(
|
||||||
@ -160,7 +173,7 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
|
|||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
Future.delayed(const Duration(seconds: 100), () {
|
Future.delayed(const Duration(seconds: 100), () {
|
||||||
if (widget.item.scheduler["name"] == value) {
|
if (widget.item.scheduler["name"] == value) {
|
||||||
widget.item.save!(widget.item.id);
|
widget.item.saveDash(widget.item.id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
widget.item.scheduler["name"] = value;
|
widget.item.scheduler["name"] = value;
|
||||||
@ -183,11 +196,11 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
|
|||||||
labelText: "executions name*",
|
labelText: "executions name*",
|
||||||
hintStyle: TextStyle(fontSize: 10),
|
hintStyle: TextStyle(fontSize: 10),
|
||||||
labelStyle: TextStyle(fontSize: 10),
|
labelStyle: TextStyle(fontSize: 10),
|
||||||
focusedErrorBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.error != null ? Colors.red : Colors.black)),
|
focusedErrorBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.item.error != null || widget.error != null ? Colors.red : Colors.black)),
|
||||||
errorBorder: OutlineInputBorder(borderSide: BorderSide(color: 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.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.error != null ? Colors.red : Colors.grey)),
|
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: widget.item.error != null || widget.error != null ? Colors.red : Colors.grey)),
|
||||||
border: OutlineInputBorder(borderSide: BorderSide(color: 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),
|
contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
|
||||||
),
|
),
|
||||||
))),
|
))),
|
||||||
@ -254,7 +267,7 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
|
|||||||
date = DateTime(date.year, date.month, date.day, time.hour, time.minute);
|
date = DateTime(date.year, date.month, date.day, time.hour, time.minute);
|
||||||
widget.item.scheduler["start"] = date.toUtc().toIso8601String();
|
widget.item.scheduler["start"] = date.toUtc().toIso8601String();
|
||||||
}
|
}
|
||||||
widget.item.save!(widget.item.id);
|
widget.item.saveDash(widget.item.id);
|
||||||
}
|
}
|
||||||
return date;
|
return date;
|
||||||
},
|
},
|
||||||
@ -359,7 +372,7 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
|
|||||||
date = DateTime(date.year, date.month, date.day, time.hour, time.minute);
|
date = DateTime(date.year, date.month, date.day, time.hour, time.minute);
|
||||||
widget.item.scheduler["end"] = date.toUtc().toIso8601String();
|
widget.item.scheduler["end"] = date.toUtc().toIso8601String();
|
||||||
}
|
}
|
||||||
widget.item.save!(widget.item.id);
|
widget.item.saveDash(widget.item.id);
|
||||||
}
|
}
|
||||||
return date;
|
return date;
|
||||||
},
|
},
|
||||||
@ -392,7 +405,7 @@ class SchedulerFormsWidgetState extends State<SchedulerFormsWidget> {
|
|||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
Future.delayed(const Duration(seconds: 100), () {
|
Future.delayed(const Duration(seconds: 100), () {
|
||||||
if (widget.item.scheduler["cron"] == value) {
|
if (widget.item.scheduler["cron"] == value) {
|
||||||
widget.item.save!(widget.item.id);
|
widget.item.saveDash(widget.item.id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
widget.item.scheduler["cron"] = value;
|
widget.item.scheduler["cron"] = value;
|
||||||
|
@ -29,7 +29,7 @@ class SubExposeFormsWidgetState extends State<SubExposeFormsWidget> {
|
|||||||
widget.item.port = int.parse(value);
|
widget.item.port = int.parse(value);
|
||||||
Future.delayed(const Duration(seconds: 2), () {
|
Future.delayed(const Duration(seconds: 2), () {
|
||||||
if (widget.item.port == int.parse(value) && int.parse(value) != 0) {
|
if (widget.item.port == int.parse(value) && int.parse(value) != 0) {
|
||||||
widget.dash.save!(widget.dash.id);
|
widget.dash.saveDash(widget.dash.id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (e) { widget.item.port = null; }
|
} catch (e) { widget.item.port = null; }
|
||||||
@ -44,7 +44,7 @@ class SubExposeFormsWidgetState extends State<SubExposeFormsWidget> {
|
|||||||
widget.item.PAT = int.parse(value);
|
widget.item.PAT = int.parse(value);
|
||||||
Future.delayed(const Duration(seconds: 2), () {
|
Future.delayed(const Duration(seconds: 2), () {
|
||||||
if (widget.item.PAT == int.parse(value) && int.parse(value) != 0) {
|
if (widget.item.PAT == int.parse(value) && int.parse(value) != 0) {
|
||||||
widget.dash.save!(widget.dash.id);
|
widget.dash.saveDash(widget.dash.id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (e) { widget.item.PAT = null; }
|
} catch (e) { widget.item.PAT = null; }
|
||||||
@ -57,7 +57,7 @@ class SubExposeFormsWidgetState extends State<SubExposeFormsWidget> {
|
|||||||
try {
|
try {
|
||||||
widget.item.path = value;
|
widget.item.path = value;
|
||||||
Future.delayed(const Duration(seconds: 2), () {
|
Future.delayed(const Duration(seconds: 2), () {
|
||||||
if (widget.item.path == value) { widget.dash.save!(widget.dash.id); }
|
if (widget.item.path == value) { widget.dash.saveDash(widget.dash.id); }
|
||||||
});
|
});
|
||||||
} catch (e) { widget.item.path = null; }
|
} catch (e) { widget.item.path = null; }
|
||||||
var el = widget.dash.getElement(widget.elementID);
|
var el = widget.dash.getElement(widget.elementID);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
|
||||||
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
|
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
|
||||||
import 'package:oc_front/models/workflow.dart';
|
import 'package:oc_front/models/workflow.dart';
|
||||||
import 'package:oc_front/widgets/inputs/sub_text_input.dart';
|
import 'package:oc_front/widgets/inputs/sub_text_input.dart';
|
||||||
@ -46,7 +45,7 @@ class SubKeysMapFormsWidgetState extends State<SubKeysMapFormsWidget> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (save) {
|
if (save) {
|
||||||
widget.dash.save!(widget.dash.id);
|
widget.dash.saveDash(widget.dash.id);
|
||||||
}
|
}
|
||||||
if (children.isEmpty) {
|
if (children.isEmpty) {
|
||||||
return Container();
|
return Container();
|
||||||
|
@ -52,7 +52,7 @@ class SubMapFormsWidgetState extends State<SubMapFormsWidget> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
widget.forms[i].key = value;
|
widget.forms[i].key = value;
|
||||||
Future.delayed(const Duration(seconds: 2), () {
|
Future.delayed(const Duration(seconds: 2), () {
|
||||||
widget.dash.save!(widget.dash.id);
|
widget.dash.saveDash(widget.dash.id);
|
||||||
});
|
});
|
||||||
var el = widget.dash.getElement(widget.elementID);
|
var el = widget.dash.getElement(widget.elementID);
|
||||||
widget.item = widget.item.deserialize(widget.item.setVariable(l, toMap(), widget.item.serialize())) as dynamic;
|
widget.item = widget.item.deserialize(widget.item.setVariable(l, toMap(), widget.item.serialize())) as dynamic;
|
||||||
@ -63,7 +63,7 @@ class SubMapFormsWidgetState extends State<SubMapFormsWidget> {
|
|||||||
SubTextInputWidget(subkey: "value", initialValue: widget.forms[i].value, width: 77.5, empty: widget.empty,
|
SubTextInputWidget(subkey: "value", initialValue: widget.forms[i].value, width: 77.5, empty: widget.empty,
|
||||||
readOnly: widget.readOnly, change: (value) {
|
readOnly: widget.readOnly, change: (value) {
|
||||||
Future.delayed(const Duration(seconds: 2), () {
|
Future.delayed(const Duration(seconds: 2), () {
|
||||||
widget.dash.save!(widget.dash.id);
|
widget.dash.saveDash(widget.dash.id);
|
||||||
});
|
});
|
||||||
widget.forms[i].value = value;
|
widget.forms[i].value = value;
|
||||||
var el = widget.dash.getElement(widget.elementID);
|
var el = widget.dash.getElement(widget.elementID);
|
||||||
@ -99,7 +99,7 @@ class SubMapFormsWidgetState extends State<SubMapFormsWidget> {
|
|||||||
widget.item.setVariable(l, toMap(), widget.item.serialize())) as dynamic;
|
widget.item.setVariable(l, toMap(), widget.item.serialize())) as dynamic;
|
||||||
var el = widget.dash.getElement(widget.elementID);
|
var el = widget.dash.getElement(widget.elementID);
|
||||||
el!.element = widget.item as dynamic;
|
el!.element = widget.item as dynamic;
|
||||||
setState(() { widget.dash.save!(widget.dash.id); });
|
setState(() { widget.dash.saveDash(widget.dash.id); });
|
||||||
}, child:
|
}, child:
|
||||||
Container( margin: const EdgeInsets.only(left: 5, 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)),
|
decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.grey, width: 1)),
|
||||||
|
@ -31,7 +31,6 @@ class ScheduleWidgetState extends State<ScheduleWidget> {
|
|||||||
String search = "";
|
String search = "";
|
||||||
String? level;
|
String? level;
|
||||||
List<Color> colors = [Colors.blue, Colors.orange, redColor, Colors.green, redColor];
|
List<Color> colors = [Colors.blue, Colors.orange, redColor, Colors.green, redColor];
|
||||||
List<String> titles = ["SCHEDULED", "RUNNING", "FAILURE", "SUCCESS", "MISSED"];
|
|
||||||
|
|
||||||
DateTime getFocusedDay() {
|
DateTime getFocusedDay() {
|
||||||
if (selected != null) { return DateTime.parse(selected!); }
|
if (selected != null) { return DateTime.parse(selected!); }
|
||||||
|
@ -28,8 +28,10 @@ class Dashboard extends ChangeNotifier {
|
|||||||
GlobalKey<FlowChartMenuState> chartMenuKey = GlobalKey<FlowChartMenuState>();
|
GlobalKey<FlowChartMenuState> chartMenuKey = GlobalKey<FlowChartMenuState>();
|
||||||
GlobalKey<ChartWidgetState> chartKey = GlobalKey<ChartWidgetState>();
|
GlobalKey<ChartWidgetState> chartKey = GlobalKey<ChartWidgetState>();
|
||||||
GlobalKey<FlowChartState> flutterChartKey = GlobalKey<FlowChartState>();
|
GlobalKey<FlowChartState> flutterChartKey = GlobalKey<FlowChartState>();
|
||||||
|
|
||||||
List<Map<String, dynamic>> tempHistory = [];
|
List<Map<String, dynamic>> tempHistory = [];
|
||||||
List<Map<String, dynamic>> history = [];
|
List<Map<String, dynamic>> history = [];
|
||||||
|
|
||||||
Map<String, dynamic> scheduler = {};
|
Map<String, dynamic> scheduler = {};
|
||||||
Map<String, dynamic> info = {};
|
Map<String, dynamic> info = {};
|
||||||
bool scheduleActive = false;
|
bool scheduleActive = false;
|
||||||
@ -58,7 +60,10 @@ class Dashboard extends ChangeNotifier {
|
|||||||
/// This is used to move the dashboard on the screen
|
/// This is used to move the dashboard on the screen
|
||||||
double widthOffset = 0;
|
double widthOffset = 0;
|
||||||
double heightOffset = 0;
|
double heightOffset = 0;
|
||||||
///
|
List<bool Function(Dashboard)> saveRules = [];
|
||||||
|
|
||||||
|
String? error;
|
||||||
|
|
||||||
Dashboard({
|
Dashboard({
|
||||||
this.id,
|
this.id,
|
||||||
this.widthOffset = 0,
|
this.widthOffset = 0,
|
||||||
@ -104,7 +109,20 @@ class Dashboard extends ChangeNotifier {
|
|||||||
tempHistory = [];
|
tempHistory = [];
|
||||||
history = [];
|
history = [];
|
||||||
}
|
}
|
||||||
|
Future<void> saveDash(String? id) async {
|
||||||
|
shouldSave = true;
|
||||||
|
for (var element in saveRules) {
|
||||||
|
if (element(this)) {
|
||||||
|
shouldSave = true;
|
||||||
|
} else {
|
||||||
|
shouldSave = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (save != null && shouldSave) {
|
||||||
|
save!(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
Future<void> Function(String cat)? load;
|
Future<void> Function(String cat)? load;
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -305,23 +323,17 @@ class Dashboard extends ChangeNotifier {
|
|||||||
void addArrows(ArrowPainter f) {
|
void addArrows(ArrowPainter f) {
|
||||||
arrows.add(f);
|
arrows.add(f);
|
||||||
addChange = true;
|
addChange = true;
|
||||||
if (save != null) {
|
saveDash(id);
|
||||||
save!(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeArrows(bool Function(ArrowPainter) f) {
|
void removeArrows(bool Function(ArrowPainter) f) {
|
||||||
arrows.removeWhere((element) => f(element));
|
arrows.removeWhere((element) => f(element));
|
||||||
if (save != null) {
|
saveDash(id);
|
||||||
save!(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeElements(bool Function(FlowElement<FlowData>) f) {
|
void removeElements(bool Function(FlowElement<FlowData>) f) {
|
||||||
elements.removeWhere((element) => f(element));
|
elements.removeWhere((element) => f(element));
|
||||||
if (save != null) {
|
saveDash(id);
|
||||||
save!(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
@ -388,9 +400,7 @@ class Dashboard extends ChangeNotifier {
|
|||||||
bool notify = true,
|
bool notify = true,
|
||||||
}) {
|
}) {
|
||||||
element.isResizing = resizable;
|
element.isResizing = resizable;
|
||||||
if (save != null) {
|
saveDash(id);
|
||||||
save!(id);
|
|
||||||
}
|
|
||||||
if (notify) notifyListeners();
|
if (notify) notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,9 +419,7 @@ class Dashboard extends ChangeNotifier {
|
|||||||
element.setScale(1, gridBackgroundParams.scale);
|
element.setScale(1, gridBackgroundParams.scale);
|
||||||
elements.add(element);
|
elements.add(element);
|
||||||
addChange = true;
|
addChange = true;
|
||||||
if (save != null) {
|
saveDash(id);
|
||||||
save!(id);
|
|
||||||
}
|
|
||||||
if (notify) {
|
if (notify) {
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
@ -534,9 +542,7 @@ class Dashboard extends ChangeNotifier {
|
|||||||
void removeAllElements({bool notify = true}) {
|
void removeAllElements({bool notify = true}) {
|
||||||
elements.clear();
|
elements.clear();
|
||||||
if (notify) notifyListeners();
|
if (notify) notifyListeners();
|
||||||
if (save != null) {
|
saveDash(id);
|
||||||
save!(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// remove the [handler] connection of [element]
|
/// remove the [handler] connection of [element]
|
||||||
@ -579,9 +585,7 @@ class Dashboard extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (notify) notifyListeners();
|
if (notify) notifyListeners();
|
||||||
if (save != null) {
|
saveDash(id);
|
||||||
save!(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// dissect an element connection
|
/// dissect an element connection
|
||||||
@ -674,9 +678,7 @@ class Dashboard extends ChangeNotifier {
|
|||||||
void removeElementConnections(FlowElement element, {bool notify = true}) {
|
void removeElementConnections(FlowElement element, {bool notify = true}) {
|
||||||
element.next.clear();
|
element.next.clear();
|
||||||
if (notify) notifyListeners();
|
if (notify) notifyListeners();
|
||||||
if (save != null) {
|
saveDash(id);
|
||||||
save!(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// remove all the elements with [id] from the dashboard
|
/// remove all the elements with [id] from the dashboard
|
||||||
@ -697,9 +699,7 @@ class Dashboard extends ChangeNotifier {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (notify) notifyListeners();
|
if (notify) notifyListeners();
|
||||||
if (save != null) {
|
saveDash(id);
|
||||||
save!(id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// remove element
|
/// remove element
|
||||||
@ -720,9 +720,7 @@ class Dashboard extends ChangeNotifier {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (notify) notifyListeners();
|
if (notify) notifyListeners();
|
||||||
if (save != null) {
|
saveDash(id);
|
||||||
save!(id);
|
|
||||||
}
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,25 +86,16 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
|
|||||||
Text("STYLE ${widget.dashboard.elementSelected.isNotEmpty ? "ELEMENT" : "ARROW"}", style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
Text("STYLE ${widget.dashboard.elementSelected.isNotEmpty ? "ELEMENT" : "ARROW"}", style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
||||||
Text("<${widget.dashboard.arrowsSelected.isEmpty && widget.dashboard.elementSelected.isEmpty ? "general" : "selected"}>", style: TextStyle(fontSize: 12), textAlign: TextAlign.center),
|
Text("<${widget.dashboard.arrowsSelected.isEmpty && widget.dashboard.elementSelected.isEmpty ? "general" : "selected"}>", style: TextStyle(fontSize: 12), textAlign: TextAlign.center),
|
||||||
])),
|
])),
|
||||||
Container( width: 200, height: widget.height - 60, child: SingleChildScrollView( child: Column( children: [
|
SizedBox( width: 200, height: widget.height - 60, child: SingleChildScrollView( child: Column( children: [
|
||||||
widget.dashboard.elementSelected.isNotEmpty ? Container() : Container( padding: EdgeInsets.symmetric(horizontal: 10, vertical: 20),
|
widget.dashboard.elementSelected.isNotEmpty ? Container() : Container( padding: EdgeInsets.symmetric(horizontal: 10, vertical: 20),
|
||||||
decoration: BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),
|
decoration: BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),
|
||||||
child: Column( children: [
|
child: Column( children: [
|
||||||
Row( children: [
|
Row( children: [
|
||||||
InkWell( mouseCursor: SystemMouseCursors.click, child: Container(
|
InkWell( mouseCursor: SystemMouseCursors.click,
|
||||||
child: Padding( padding: EdgeInsets.only(left: 10, right: 10),
|
child: Padding( padding: EdgeInsets.only(left: 10, right: 10),
|
||||||
child: PopupMenuButton<ArrowDash>(
|
child: PopupMenuButton<ArrowDash>(
|
||||||
tooltip: "line defaults",
|
tooltip: "line defaults",
|
||||||
constraints: BoxConstraints(maxWidth: 100),
|
constraints: BoxConstraints(maxWidth: 100),
|
||||||
child: Row( children: [
|
|
||||||
MySeparator(
|
|
||||||
width: 35,
|
|
||||||
dashWidth: widget.dashboard.defaultDashWidth,
|
|
||||||
dashSpace: widget.dashboard.defaultDashSpace,
|
|
||||||
color: Colors.black
|
|
||||||
),
|
|
||||||
SizedBox(height: 25, width: 10),
|
|
||||||
Icon(Icons.arrow_drop_down, size: 10, color: Colors.black) ]),
|
|
||||||
initialValue: null,
|
initialValue: null,
|
||||||
onSelected: (ArrowDash value) {
|
onSelected: (ArrowDash value) {
|
||||||
if (widget.dashboard.elementSelected.isEmpty) {
|
if (widget.dashboard.elementSelected.isEmpty) {
|
||||||
@ -162,18 +153,22 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
|
|||||||
MySeparator(width: 25, dashWidth: widthArrowDash(ArrowDash.lightDotted), dashSpace: spaceArrowDash(ArrowDash.lightDotted),)
|
MySeparator(width: 25, dashWidth: widthArrowDash(ArrowDash.lightDotted), dashSpace: spaceArrowDash(ArrowDash.lightDotted),)
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
]
|
],
|
||||||
|
child: Row( children: [
|
||||||
|
MySeparator(
|
||||||
|
width: 35,
|
||||||
|
dashWidth: widget.dashboard.defaultDashWidth,
|
||||||
|
dashSpace: widget.dashboard.defaultDashSpace,
|
||||||
|
color: Colors.black
|
||||||
|
),
|
||||||
|
SizedBox(height: 25, width: 10),
|
||||||
|
Icon(Icons.arrow_drop_down, size: 10, color: Colors.black) ])
|
||||||
),
|
),
|
||||||
)
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
PopupMenuButton<void>(
|
PopupMenuButton<void>(
|
||||||
tooltip: "color picker",
|
tooltip: "color picker",
|
||||||
constraints: BoxConstraints(maxWidth: 664),
|
constraints: BoxConstraints(maxWidth: 664),
|
||||||
child: Row( children: [
|
|
||||||
Container(width: 15, height: 15, color: widget.dashboard.defaultColor),
|
|
||||||
Container(height: 25, width: 5),
|
|
||||||
Icon(Icons.arrow_drop_down, size: 10, color: Colors.black) ]),
|
|
||||||
initialValue: null,
|
initialValue: null,
|
||||||
onSelected: (void value) {},
|
onSelected: (void value) {},
|
||||||
itemBuilder: (BuildContext context) => <PopupMenuEntry<void>>[
|
itemBuilder: (BuildContext context) => <PopupMenuEntry<void>>[
|
||||||
@ -186,7 +181,11 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
|
|||||||
setState(() { widget.dashboard.defaultColor = value; });
|
setState(() { widget.dashboard.defaultColor = value; });
|
||||||
},),
|
},),
|
||||||
),
|
),
|
||||||
]
|
],
|
||||||
|
child: Row( children: [
|
||||||
|
Container(width: 15, height: 15, color: widget.dashboard.defaultColor),
|
||||||
|
SizedBox(height: 25, width: 5),
|
||||||
|
Icon(Icons.arrow_drop_down, size: 10, color: Colors.black) ])
|
||||||
),
|
),
|
||||||
Tooltip( message: "stroke width",
|
Tooltip( message: "stroke width",
|
||||||
child: Container(
|
child: Container(
|
||||||
@ -228,13 +227,9 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
|
|||||||
)))
|
)))
|
||||||
]),
|
]),
|
||||||
Row(children: [
|
Row(children: [
|
||||||
InkWell( mouseCursor: SystemMouseCursors.click, child: Container(
|
InkWell( mouseCursor: SystemMouseCursors.click, child: Padding(
|
||||||
child: Padding( padding: EdgeInsets.only(left: 10, top: 10, right: 10),
|
padding: EdgeInsets.only(left: 10, top: 10, right: 10),
|
||||||
child: PopupMenuButton<ArrowStyle>(
|
child: PopupMenuButton<ArrowStyle>(
|
||||||
child:
|
|
||||||
Row( children: [ Icon(widget.dashboard.defaultArrowStyle == ArrowStyle.segmented ? Icons.turn_slight_left : widget.dashboard.defaultArrowStyle == ArrowStyle.curve ? Icons.roundabout_left : Icons.turn_sharp_left_outlined
|
|
||||||
, color: Colors.black),
|
|
||||||
Icon(Icons.arrow_drop_down, size: 10, color: Colors.black) ]),
|
|
||||||
initialValue: null,
|
initialValue: null,
|
||||||
onSelected: (ArrowStyle value) {
|
onSelected: (ArrowStyle value) {
|
||||||
if (widget.dashboard.elementSelected.isEmpty) {
|
if (widget.dashboard.elementSelected.isEmpty) {
|
||||||
@ -270,8 +265,11 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
|
|||||||
child: Text('rectangular', textAlign: TextAlign.center,))
|
child: Text('rectangular', textAlign: TextAlign.center,))
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
]
|
],
|
||||||
)
|
child:
|
||||||
|
Row( children: [ Icon(widget.dashboard.defaultArrowStyle == ArrowStyle.segmented ? Icons.turn_slight_left : widget.dashboard.defaultArrowStyle == ArrowStyle.curve ? Icons.roundabout_left : Icons.turn_sharp_left_outlined
|
||||||
|
, color: Colors.black),
|
||||||
|
Icon(Icons.arrow_drop_down, size: 10, color: Colors.black) ])
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@ -352,22 +350,14 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
|
|||||||
)))
|
)))
|
||||||
]),
|
]),
|
||||||
])),
|
])),
|
||||||
widget.dashboard.elementSelected.isNotEmpty && widget.dashboard.elementSelected.length == 1 ? Container(
|
widget.dashboard.elementSelected.isNotEmpty ? Container() :
|
||||||
// TODO : TEST OMG
|
Container( padding: EdgeInsets.only(left: 10, right: 10, bottom: 20, top: 15),
|
||||||
) : Container(),
|
|
||||||
widget.dashboard.elementSelected.isNotEmpty ? Container() : Container( padding: EdgeInsets.only(left: 10, right: 10, bottom: 20, top: 15),
|
|
||||||
decoration: BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),
|
decoration: BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),
|
||||||
child: Column( children: [
|
child: Column( children: [
|
||||||
Row( mainAxisAlignment: MainAxisAlignment.center, children : [
|
Row( mainAxisAlignment: MainAxisAlignment.center, children : [
|
||||||
InkWell( mouseCursor: SystemMouseCursors.click, child: Container(
|
InkWell( mouseCursor: SystemMouseCursors.click,
|
||||||
child: Padding( padding: EdgeInsets.symmetric(horizontal: 10),
|
child: Padding( padding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
child: PopupMenuButton<ArrowDirection>(
|
child: PopupMenuButton<ArrowDirection>(
|
||||||
child:
|
|
||||||
Row( children: [
|
|
||||||
Icon(widget.dashboard.defaultArrowDirection == ArrowDirection.forward ? Icons.arrow_forward : widget.dashboard.defaultArrowDirection == ArrowDirection.backward ? Icons.arrow_back : Icons.sync_alt_outlined, color: Colors.black),
|
|
||||||
Padding( padding: EdgeInsets.symmetric(horizontal: 10),
|
|
||||||
child: Text(widget.dashboard.defaultArrowDirection == ArrowDirection.forward ? 'forward' : widget.dashboard.defaultArrowDirection == ArrowDirection.backward ? 'backward' : 'bidirectionnal')),
|
|
||||||
Icon(Icons.arrow_drop_down, size: 10, color: Colors.black) ]),
|
|
||||||
initialValue: null,
|
initialValue: null,
|
||||||
onSelected: (ArrowDirection value) {
|
onSelected: (ArrowDirection value) {
|
||||||
if (widget.dashboard.elementSelected.isEmpty) {
|
if (widget.dashboard.elementSelected.isEmpty) {
|
||||||
@ -403,9 +393,14 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
|
|||||||
child: Text('bidirectionnal', textAlign: TextAlign.center,))
|
child: Text('bidirectionnal', textAlign: TextAlign.center,))
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
]
|
],
|
||||||
|
child:
|
||||||
|
Row( children: [
|
||||||
|
Icon(widget.dashboard.defaultArrowDirection == ArrowDirection.forward ? Icons.arrow_forward : widget.dashboard.defaultArrowDirection == ArrowDirection.backward ? Icons.arrow_back : Icons.sync_alt_outlined, color: Colors.black),
|
||||||
|
Padding( padding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
|
child: Text(widget.dashboard.defaultArrowDirection == ArrowDirection.forward ? 'forward' : widget.dashboard.defaultArrowDirection == ArrowDirection.backward ? 'backward' : 'bidirectionnal')),
|
||||||
|
Icon(Icons.arrow_drop_down, size: 10, color: Colors.black) ])
|
||||||
),)
|
),)
|
||||||
)
|
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
Row(children: [
|
Row(children: [
|
||||||
@ -560,12 +555,11 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
|
|||||||
}
|
}
|
||||||
return Column( children: [
|
return Column( children: [
|
||||||
Container( // SHORTCUT
|
Container( // SHORTCUT
|
||||||
width: 200,
|
width: 200, height: 50,
|
||||||
height: 50,
|
decoration: BoxDecoration(color: widget.dashboard.midDashColor,
|
||||||
decoration: BoxDecoration(color: widget.dashboard.midDashColor, border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),
|
border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),
|
||||||
child: Row( children: [
|
child: Row( children: [
|
||||||
Tooltip(
|
Tooltip( message: "dashboard information",
|
||||||
message: "dashboard information",
|
|
||||||
child: InkWell( onTap: () => setState(() {widget.isDashboardInfo = true; }),
|
child: InkWell( onTap: () => setState(() {widget.isDashboardInfo = true; }),
|
||||||
mouseCursor: SystemMouseCursors.click,
|
mouseCursor: SystemMouseCursors.click,
|
||||||
child: Container( alignment: Alignment.center,
|
child: Container( alignment: Alignment.center,
|
||||||
@ -582,24 +576,30 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
|
|||||||
padding: EdgeInsets.symmetric(vertical: 10),
|
padding: EdgeInsets.symmetric(vertical: 10),
|
||||||
color: !widget.isDashboardInfo ? Colors.grey : widget.dashboard.midDashColor,
|
color: !widget.isDashboardInfo ? Colors.grey : widget.dashboard.midDashColor,
|
||||||
width: 200 / 2, child: Icon(Icons.format_paint, color: Colors.white)),
|
width: 200 / 2, child: Icon(Icons.format_paint, color: Colors.white)),
|
||||||
))
|
)
|
||||||
])),
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
widget.dashboard.error != null ? Container( width: 200, color: Colors.red, padding: EdgeInsets.all(10),
|
||||||
|
child: Center( child: Text(widget.dashboard.error!,
|
||||||
|
style: TextStyle(color: Colors.white, fontSize: 15), textAlign: TextAlign.center))) : Container(),
|
||||||
w
|
w
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
class MySeparator extends StatelessWidget {
|
class MySeparator extends StatelessWidget {
|
||||||
double width = 1; double dashWidth = 10; double dashSpace = 10;
|
double width = 1; double dashWidth = 10; double dashSpace = 10;
|
||||||
MySeparator({Key? key, this.width = 1, this.dashSpace = 10, this.dashWidth = 10,
|
MySeparator({super.key, this.width = 1, this.dashSpace = 10, this.dashWidth = 10,
|
||||||
this.height = 1, this.color = Colors.black})
|
this.height = 1, this.color = Colors.black});
|
||||||
: super(key: key);
|
|
||||||
final double height;
|
final double height;
|
||||||
final Color color;
|
final Color color;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container( width: width, child: dashSpace == 0 ?
|
return SizedBox( width: width, child: dashSpace == 0 ?
|
||||||
Divider( thickness: 2, color: color )
|
Divider( thickness: 2, color: color )
|
||||||
: DottedLine(
|
: DottedLine(
|
||||||
dashLength: dashWidth,
|
dashLength: dashWidth,
|
||||||
|
Loading…
Reference in New Issue
Block a user