--- /dev/null
+#! /bin/bash
+MODULE=rolestarter
+MODULE2=rolestarter
+PAGE=mapping
+cd lib/page/$MODULE
+cp -a ${PAGE}_${MODULE2}_custom.dart ${PAGE}_${MODULE2}_custom.01.dart
+ls -ld ${PAGE}_${MODULE2}_custom.01.dart
--- /dev/null
+#! /bin/bash
+./ReCreateMetaTool
+cd lib/page
+find -name "*custom.dart" -a ! -name "list_benchmark*.dart" -a ! -name "mapping_*.dart" -delete
+#find -name "*custom.dart" -delete
+#rm edit_user_custom.dart
+cd ../..
+./Meta update-modules-files | grep custom | grep -v "override"
import '../../services/global_widget.dart';
import '../../setting/global_data.dart';
import '../../widget/attended_page.dart';
+import '../../widget/date_form_field.dart';
import '../../widget/message_line.dart';
import '../../widget/widget_form.dart';
import 'edit_benchmark_page.dart';
final birthdayController = TextEditingController();
final weightController = TextEditingController();
final incomeController = TextEditingController();
+ final birthdayData = DateData(
+ initialDate: DateTime(1970),
+ firstDate: DateTime(1900),
+ lastDate: DateTime(DateTime.now().year));
EditBenchmarkCustom(this.primaryKey);
+
@override
Widget build(BuildContext context) {
final rc = Scaffold(
birthdayController.text = asString(_fieldData.birthday, dateOnly: true);
weightController.text = asString(_fieldData.weight);
incomeController.text = asString(_fieldData.income);
+ birthdayData.setInitialDate(_fieldData.birthday);
final formItems = <FormItem>[
FormItem(
TextFormField(
onSaved: (value) => _fieldData.email = value ?? ''),
weight: 6),
FormItem(
- TextFormField(
- controller: birthdayController,
+ DateFormField(
+ context: context,
+ dateData: birthdayData,
+ dateController: birthdayData.dateController,
decoration: InputDecoration(labelText: i18n.tr('Birthday')),
validator: (input) => notEmpty(input),
onSaved: (value) => _fieldData.birthday =
super.initState();
}
- void requestRecord() => _futureDbData = globalData.restPersistence.query(
- what: 'query',
- data: {'module': 'Users', 'sql': 'byId', ':id': primaryKey});
-
void onStore() {
final parameters = <String, dynamic>{
'module': 'Benchmarks',
onStore();
}
}
+
+ void requestRecord() => _futureDbData = globalData.restPersistence.query(
+ what: 'query',
+ data: {'module': 'Benchmarks', 'sql': 'byId', ':id': primaryKey});
}
class _FieldData {
--- /dev/null
+// This file is created by the meta_tool. But it can be customized.
+// It will never overridden by the meta_tool.
+import 'package:flutter/material.dart';
+
+import '../../base/defines.dart';
+import '../../base/helper.dart';
+import '../../base/i18n.dart';
+import '../../services/global_widget.dart';
+import '../../setting/global_data.dart';
+import '../../widget/attended_page.dart';
+import '../../widget/widget_form.dart';
+import '../../persistence/persistence.dart';
+import 'mapping_rolestarter_page.dart';
+
+final i18n = I18N();
+
+class MappingRoleStarterCustom extends State<MappingRoleStarterPage> {
+ final globalData = GlobalData();
+ late Future<DbData> _futureDbDataMember;
+ late Future<DbData> _futureDbDataNotMember;
+ AttendedPage? attendedPage;
+ final _fieldData = _FieldData();
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'CreateRole');
+ final textController = TextEditingController();
+ MappingRoleStarterCustom();
+ @override
+ Widget build(BuildContext context) {
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('#LABEL')),
+ drawer: globalData.drawerBuilder(context),
+ body: SafeArea(
+ child: FutureBuilder<List<DbData>>(
+ future: Future.wait([_futureDbDataMember, _futureDbDataNotMember]),
+ builder: (context, AsyncSnapshot<List<DbData>> snapshot) {
+ Widget rc;
+ if (snapshot.connectionState != ConnectionState.done) {
+ rc = const CircularProgressIndicator();
+ } else {
+ if (snapshot.hasData) {
+ final rowsMembers = attendedPage!.getRows(
+ dbData: snapshot.data![0],
+ columnList: 'starter_name;starter_link',
+ onDone: () => setState(() => 1),
+ routeEdit: '',
+ context: context);
+ final rowsNotMembers = attendedPage!.getRows(
+ dbData: snapshot.data![1],
+ columnList: 'starter_name;starter_link',
+ onDone: () => setState(() => 1),
+ routeEdit: '',
+ context: context);
+ rc = buildFrame(
+ rowsMembers: rowsMembers, rowsNotMembers: rowsNotMembers);
+ } else if (snapshot.hasError) {
+ rc = Text('Backend problem: ${snapshot.error}');
+ } else {
+ rc = const CircularProgressIndicator();
+ }
+ }
+ return rc;
+ },
+ )),
+ );
+ return rc;
+ }
+
+ Widget buildFrame(
+ {required JsonList rowsMembers, required JsonList rowsNotMembers}) {
+ final padding = GlobalThemeData.padding;
+ final itemsRoles = <DropdownMenuItem<int>>[];
+ final formItems = <FormItem>[
+ FormItem(
+ DropdownButtonFormField<int>(
+ value: itemsRoles.length == 1 ? 0 : _fieldData.role,
+ items: itemsRoles,
+ isExpanded: true,
+ decoration: InputDecoration(labelText: i18n.tr('Role')),
+ onChanged: (value) => _fieldData.role = value ?? 0,
+ ),
+ weight: 6),
+ FormItem(
+ ElevatedButton(
+ onPressed: () => search(), child: Text(i18n.tr('Search'))),
+ weight: 12,
+ gapAbove: padding),
+ ];
+ final form = Form(
+ key: _formKey,
+ child: Card(
+ color: GlobalThemeData.formBackgroundColor,
+ elevation: GlobalThemeData.formElevation,
+ margin:
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ vertical: padding, horizontal: padding),
+ child: WidgetForm.flexibleGrid(formItems,
+ screenWidth: attendedPage!.pageStates.screenWidth,
+ padding: padding))));
+ final tableMembers = DataTable(
+ columns: <DataColumn>[
+ DataColumn(
+ label: Text(i18n.tr('Id')),
+ ),
+ DataColumn(
+ label: Text(i18n.tr('Name')),
+ ),
+ ],
+ rows: rowsMembers as List<DataRow>,
+ );
+ final tableNotMembers = DataTable(
+ columns: <DataColumn>[
+ DataColumn(
+ label: Text(i18n.tr('Id')),
+ ),
+ DataColumn(
+ label: Text(i18n.tr('Name')),
+ ),
+ ],
+ rows: rowsNotMembers as List<DataRow>,
+ );
+ final frameWidget = ListView(children: [
+ form,
+ Text(i18n.tr('The following items are assigned. Click it to remove.')),
+ SizedBox(height: padding),
+ tableMembers,
+ SizedBox(height: padding),
+ Text(
+ i18n.tr('The following items are not assigned. Click it to assign.')),
+ SizedBox(height: padding),
+ tableNotMembers,
+ ]);
+ return frameWidget;
+ }
+
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+ requestRecords();
+ }
+
+ @override
+ void dispose() {
+ helperDummyUsage(DataType.string);
+ globalWidgetDummyUsage();
+ textController.dispose();
+ super.dispose();
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ void requestRecords() {
+ _futureDbDataMember =
+ globalData.restPersistence.query(what: 'query', data: {
+ 'module': 'RoleStarter',
+ 'sql': 'members',
+ ':role': _fieldData.role,
+ });
+ _futureDbDataNotMember =
+ globalData.restPersistence.query(what: 'query', data: {
+ 'module': 'RoleStarter',
+ 'sql': 'notmembers',
+ ':role': _fieldData.role,
+ });
+ }
+
+ void search() {
+ attendedPage!.pageStates.dbDataState.clear();
+ if (_formKey.currentState!.validate()) {
+ _formKey.currentState!.save();
+ requestRecords();
+ setState(() => 1);
+ }
+ }
+}
+
+class _FieldData {
+ int role = 0;
+}
--- /dev/null
+// This file is created by the meta_tool. But it can be customized.
+// It will never overridden by the meta_tool.
+import 'package:flutter/material.dart';
+
+import '../../base/defines.dart';
+import '../../base/helper.dart';
+import '../../base/i18n.dart';
+import '../../persistence/persistence.dart';
+import '../../services/global_widget.dart';
+import '../../setting/global_data.dart';
+import '../../widget/attended_page.dart';
+import '../../widget/widget_form.dart';
+import 'mapping_rolestarter_page.dart';
+
+final i18n = I18N();
+
+class CommonInfo {
+ final List<String> columns;
+ final List<MemberInfo> members = [];
+ CommonInfo({required this.columns});
+}
+
+class MappingRoleStarterCustom extends State<MappingRoleStarterPage> {
+ final globalData = GlobalData();
+ late Future<DbData> _futureDbDataCommon;
+ late Future<DbData> _futureDbDataMember;
+ late Future<DbData> _futureDbDataConnection;
+ var membersOfCommon = <int, List<int>>{};
+ late AttendedPage attendedPage;
+ final _fieldData = _FieldData();
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'CreateRole');
+ final textController = TextEditingController();
+ final commonColumns = ['role_name'];
+ final memberColumns = ['starter_name', 'starter_route'];
+ final commonInfos = <int, CommonInfo>{};
+
+ /// Members of the current common module:
+ final memberInfos = <MemberInfo>[];
+
+ final notMemberInfos = <MemberInfo>[];
+ JsonList membersRows = [];
+ JsonList commonRows = [];
+ JsonList connectionRows = [];
+ MappingRoleStarterCustom();
+
+ @override
+ Widget build(BuildContext context) {
+ final rc = Scaffold(
+ appBar: globalData.appBarBuilder(i18n.tr('Role/Starter Assignment')),
+ drawer: globalData.drawerBuilder(context),
+ body: SafeArea(
+ child: FutureBuilder<List<DbData>>(
+ future: Future.wait([
+ _futureDbDataMember,
+ _futureDbDataCommon,
+ _futureDbDataConnection
+ ]),
+ builder: (context, AsyncSnapshot<List<DbData>> snapshot) {
+ Widget rc;
+ if (snapshot.connectionState != ConnectionState.done) {
+ rc = const CircularProgressIndicator();
+ } else {
+ if (snapshot.hasData) {
+ commonRows = snapshot.data![0].recordList ?? [];
+ membersRows = snapshot.data![1].recordList ?? [];
+ connectionRows = snapshot.data![2].recordList ?? [];
+ handleConnectionRows();
+ rc = buildFrame();
+ } else if (snapshot.hasError) {
+ rc = Text('Backend problem: ${snapshot.error}');
+ } else {
+ rc = const CircularProgressIndicator();
+ }
+ }
+ return rc;
+ },
+ )),
+ );
+ return rc;
+ }
+
+ /// Builds the items of the common module combobox from the database records.
+ List<DropdownMenuItem<int>> buildCommonItems() {
+ final rc = <DropdownMenuItem<int>>[];
+ for (var record in commonRows) {
+ rc.add(DropdownMenuItem<int>(
+ value: record['role_id'], child: Text(record['role_name'])));
+ }
+ return rc;
+ }
+
+ Widget buildFrame() {
+ final padding = GlobalThemeData.padding;
+ final itemsRoles = <DropdownMenuItem<int>>[];
+ final formItems = <FormItem>[
+ FormItem(
+ DropdownButtonFormField<int>(
+ value: itemsRoles.length == 1 ? 0 : _fieldData.role,
+ items: buildCommonItems(),
+ isExpanded: true,
+ decoration: InputDecoration(labelText: i18n.tr('Role')),
+ onChanged: (value) => _fieldData.role = value ?? 0,
+ ),
+ weight: 6),
+ FormItem(
+ ElevatedButton(onPressed: () => save(), child: Text(i18n.tr('Save'))),
+ weight: 12,
+ gapAbove: padding),
+ ];
+ final form = Form(
+ key: _formKey,
+ child: Card(
+ color: GlobalThemeData.formBackgroundColor,
+ elevation: GlobalThemeData.formElevation,
+ margin:
+ EdgeInsets.symmetric(vertical: padding, horizontal: padding),
+ child: Padding(
+ padding: EdgeInsets.symmetric(
+ vertical: padding, horizontal: padding),
+ child: WidgetForm.flexibleGrid(formItems,
+ screenWidth: attendedPage.pageStates.screenWidth,
+ padding: padding))));
+ final tableMembers = buildMemberTable();
+ final tableNotMembers = buildNotMemberTable();
+ final frameWidget = ListView(children: [
+ form,
+ Text(i18n.tr('The following items are assigned. Click it to remove.')),
+ SizedBox(height: padding),
+ tableMembers,
+ SizedBox(height: padding),
+ Text(
+ i18n.tr('The following items are not assigned. Click it to assign.')),
+ SizedBox(height: padding),
+ tableNotMembers,
+ ]);
+ return frameWidget;
+ }
+
+ buildMemberTable() {
+ final rows = buildTableItems(
+ commonInfos[_fieldData.role]!.members, 'rolestarter_id');
+ final headers = <DataColumn>[];
+ for (var column in commonInfos[_fieldData.role]!.columns) {
+ final label =
+ attendedPage.moduleMetaData.propertyByColumnName(column)?.label ??
+ i18n.tr('Info');
+ headers.add(DataColumn(label: Text(label)));
+ }
+ final rc = DataTable(
+ columns: headers,
+ rows: rows,
+ );
+ return rc;
+ }
+
+ buildNotMemberTable() {
+ final rows = buildTableItems(
+ commonInfos[_fieldData.role]!.members, 'rolestarter_id');
+ final headers = <DataColumn>[];
+ for (var column in commonInfos[_fieldData.role]!.columns) {
+ final label =
+ attendedPage.moduleMetaData.propertyByColumnName(column)?.label ??
+ i18n.tr('Info');
+ headers.add(DataColumn(label: Text(label)));
+ }
+ final rc = DataTable(
+ columns: headers,
+ rows: rows,
+ );
+ return rc;
+ }
+
+ /// Build the [notMemberInfos] list of items not being members of the common
+ /// module with [commonId].
+ void buildNotMembers(int commonId) {
+ notMemberInfos.clear();
+ int order = 10;
+ for (var record in membersRows) {
+ final id = record['rolestarter_starter'];
+ if (record['rolestarter_role'] == commonId && !hasMember(id)) {
+ notMemberInfos.add(MemberInfo(
+ memberId: id, position: order++, columns: memberColumns));
+ }
+ }
+ }
+
+ buildTableItems(List<MemberInfo> members, String primary) {
+ members.map((MemberInfo element) {
+ final cells = <DataCell>[];
+ final record = findRecord(membersRows, primary, element.memberId);
+ if (record != null) {
+ for (var column in element.columns) {
+ cells.add(DataCell(Text(record[column])));
+ }
+ }
+ return DataRow(cells: cells);
+ });
+ }
+
+ @override
+ void didChangeDependencies() {
+ super.didChangeDependencies();
+ requestRecords();
+ }
+
+ @override
+ void dispose() {
+ helperDummyUsage(DataType.string);
+ globalWidgetDummyUsage();
+ textController.dispose();
+ super.dispose();
+ }
+
+ /// Finds a record in a list of records by a given [id] in a given [column].
+ JsonMap? findRecord(JsonList rows, String column, int id) {
+ JsonMap? rc;
+ for (var record in rows) {
+ if (record[column] == id) {
+ rc = record;
+ break;
+ }
+ }
+ return rc;
+ }
+
+ /// Inspects the [connectionRows] and build the internal structures.
+ void handleConnectionRows() {
+ commonInfos.clear();
+ for (var record in commonRows) {
+ int common = record['role_id'];
+ commonInfos[common] = CommonInfo(columns: commonColumns);
+ }
+ for (var record in connectionRows) {
+ int common = record['rolestarter_role'];
+ if (!commonInfos.containsKey(common)) {
+ commonInfos[common] = CommonInfo(columns: commonColumns);
+ }
+ commonInfos[common]!.members.add(MemberInfo(
+ memberId: record['rolestarter_starter'],
+ columns: memberColumns,
+ position: record['rolestarter_position']));
+ }
+ for (var key in commonInfos.keys) {
+ commonInfos[key]!.members.sort((a, b) => a.position - b.position);
+ }
+ }
+
+ /// Returns whether the given [memberId] is part of [memberInfos].
+ bool hasMember(int memberId) {
+ bool rc = false;
+ for (var item in memberInfos) {
+ if (item.memberId == memberId) {
+ rc = true;
+ break;
+ }
+ }
+ return rc;
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ void requestRecords() {
+ _futureDbDataMember =
+ globalData.restPersistence.query(what: 'query', data: {
+ 'module': 'Starters',
+ 'sql': 'all',
+ });
+ _futureDbDataCommon =
+ globalData.restPersistence.query(what: 'query', data: {
+ 'module': 'Roles',
+ 'sql': 'all',
+ });
+ _futureDbDataConnection =
+ globalData.restPersistence.query(what: 'query', data: {
+ 'module': 'RoleStarter',
+ 'sql': 'all',
+ });
+ }
+
+ void save() {
+ attendedPage.pageStates.dbDataState.clear();
+ if (_formKey.currentState!.validate()) {
+ _formKey.currentState!.save();
+ requestRecords();
+ setState(() => 1);
+ }
+ }
+}
+
+class MemberInfo {
+ final int memberId;
+ final int position;
+ final List<String> columns;
+ MemberInfo(
+ {required this.memberId, required this.position, required this.columns});
+}
+
+class _FieldData {
+ int role = 0;
+}
RestPersistence.fromConfig(configuration, logger),
logger);
globalData.initializeAsync().then((value) {
- globalData.navigate(context, '/RoleStarter/mapping');
+ // globalData.navigate(context, '/RoleStarter/mapping');
+ globalData.navigate(context, '/Benchmarks/list');
});
}
});
? Icons.beenhere_outlined
: Icons.first_page_outlined;
} else if (ix == chipCount - 1) {
- icon = currentPage == 1
+ icon = currentPage == pageCount
? Icons.beenhere_outlined
: Icons.last_page_outlined;
} else if (ix == currentIndex) {
--- /dev/null
+import 'package:flutter/material.dart';
+
+import '../base/helper.dart';
+import '../base/i18n.dart';
+import '../setting/global_data.dart';
+
+final i18n = I18N();
+
+/// Manages the main attributes of a DateFormField.
+class DateData {
+ DateTime? initialDate;
+ late final DateTime firstDate;
+ late final DateTime lastDate;
+ DateTime? selectedDate;
+ final Function? onSelected;
+ final dateController = TextEditingController();
+
+ /// Constructor.
+ ///
+ /// [inititialDate]: the date that is displayed while starting the date picker.
+ ///
+ /// [firstDate]: the oldest date showed in the date picker.
+ ///
+ /// [lastDate]: the youngest date showed in the date picker.
+ ///
+ /// [onSelected]: this function is called after a date is selected.
+ DateData(
+ {DateTime? initialDate,
+ DateTime? firstDate,
+ DateTime? lastDate,
+ this.onSelected}) {
+ final now = DateTime.now();
+ this.initialDate = initialDate ?? now;
+ this.lastDate = lastDate ?? DateTime(now.year + 1);
+ this.firstDate = firstDate ?? DateTime(now.year - 1);
+ selectedDate = now;
+ }
+
+ /// Handles the "button pressed" event in DateFormField.
+ onButtonPressed(BuildContext context,
+ {required Function(DateTime selected) storeSelected}) async {
+ final DateTime? picked = await showDatePicker(
+ context: context,
+ initialDate: initialDate ?? DateTime(1970), // Refer step 1
+ firstDate: firstDate,
+ lastDate: lastDate,
+ );
+ if (picked != null) {
+ selectedDate = picked;
+ dateController.text = asString(picked, dateOnly: true);
+ if (onSelected != null) {
+ onSelected!();
+ }
+ }
+ }
+
+ /// Sets the initial date to [dateTime].
+ void setInitialDate(DateTime? dateTime) {
+ initialDate = dateTime;
+ dateController.text =
+ dateTime == null ? '' : asString(dateTime, dateOnly: true);
+ }
+}
+
+/// Manages a text field with a button to call a date picker.
+class DateFormField extends Container {
+ final DateData dateData;
+ final TextEditingController dateController;
+ DateFormField(
+ {required BuildContext context,
+ required this.dateData,
+ required this.dateController,
+ Key? key,
+ FocusNode? focusNode,
+ InputDecoration? decoration = const InputDecoration(),
+ TextInputType? keyboardType = TextInputType.datetime,
+ TextInputAction? textInputAction,
+ TextStyle? style,
+ StrutStyle? strutStyle,
+ TextAlign textAlign = TextAlign.start,
+ TextAlignVertical? textAlignVertical,
+ bool autofocus = false,
+ bool readOnly = false,
+ ToolbarOptions? toolbarOptions,
+ bool? showCursor,
+ bool autocorrect = true,
+ SmartDashesType? smartDashesType,
+ SmartQuotesType? smartQuotesType,
+ bool enableSuggestions = true,
+ bool autovalidate = false,
+ bool maxLengthEnforced = true,
+ bool expands = false,
+ int? maxLength,
+ ValueChanged<String>? onChanged,
+ GestureTapCallback? onTap,
+ VoidCallback? onEditingComplete,
+ ValueChanged<String>? onFieldSubmitted,
+ FormFieldSetter<String>? onSaved,
+ FormFieldValidator<String>? validator,
+ bool? enabled,
+ double cursorWidth = 2.0,
+ double? cursorHeight,
+ Radius? cursorRadius,
+ Color? cursorColor,
+ Brightness? keyboardAppearance,
+ EdgeInsets scrollPadding = const EdgeInsets.all(20.0),
+ bool enableInteractiveSelection = true,
+ TextSelectionControls? selectionControls,
+ InputCounterWidgetBuilder? buildCounter,
+ ScrollPhysics? scrollPhysics,
+ Iterable<String>? autofillHints,
+ AutovalidateMode? autovalidateMode,
+ ScrollController? scrollController,
+ String? restorationId,
+ bool enableIMEPersonalizedLearning = true,
+ double? gapWidth,
+ DateTime? initialDate})
+ : super(
+ child: Row(children: <Widget>[
+ Expanded(
+ child: TextFormField(
+ onTap: onTap,
+ controller: dateController,
+ onEditingComplete: onEditingComplete,
+ onFieldSubmitted: onFieldSubmitted,
+ onSaved: onSaved,
+ validator: validator,
+ enabled: enabled,
+ cursorWidth: cursorWidth,
+ cursorHeight: cursorHeight,
+ cursorRadius: cursorRadius,
+ cursorColor: cursorColor,
+ keyboardAppearance: keyboardAppearance,
+ scrollPadding: scrollPadding,
+ enableInteractiveSelection: enableInteractiveSelection,
+ selectionControls: selectionControls,
+ buildCounter: buildCounter,
+ scrollPhysics: scrollPhysics,
+ autofillHints: autofillHints,
+ autovalidateMode: autovalidateMode,
+ scrollController: scrollController,
+ restorationId: restorationId,
+ enableIMEPersonalizedLearning: enableIMEPersonalizedLearning,
+ )),
+ SizedBox(width: gapWidth ?? GlobalThemeData.padding),
+ ElevatedButton(
+ onPressed: () =>
+ dateData.onButtonPressed(context, storeSelected: (selected) {
+ dateData.selectedDate = selected;
+ }),
+ child: Icon(Icons.calendar_today_outlined)),
+ ]));
+}
--- /dev/null
+import 'package:flutter/material.dart';
+import 'package:sprintf/sprintf.dart';
+
+import '../base/helper.dart';
+import '../base/i18n.dart';
+import '../setting/global_data.dart';
+
+final i18n = I18N();
+
+/// Manages the main attributes of a DateFormField.
+class DateTimeData {
+ DateTime? initialDate;
+ TimeOfDay? initialTime;
+ late final DateTime firstDate;
+ late final DateTime lastDate;
+ DateTime? selectedDate;
+ TimeOfDay? selectedTime;
+ final Function? onSelected;
+ final dateController = TextEditingController();
+
+ /// Constructor.
+ ///
+ /// [inititialDate]: the date that is displayed while starting the date picker.
+ /// [inititialDate]: the date that is displayed while starting the date picker.
+ ///
+ /// [firstDate]: the oldest date showed in the date picker.
+ ///
+ /// [lastDate]: the youngest date showed in the date picker.
+ ///
+ /// [onSelected]: this function is called after a date is selected.
+ DateTimeData(
+ {DateTime? initialDateTime,
+ DateTime? initialDate,
+ TimeOfDay? initialTime,
+ DateTime? firstDate,
+ DateTime? lastDate,
+ this.onSelected}) {
+ final now = DateTime.now();
+ if (initialDateTime != null) {
+ this.initialDate = DateTime(
+ initialDateTime.year, initialDateTime.month, initialDateTime.day);
+ this.initialTime =
+ TimeOfDay(hour: initialDateTime.hour, minute: initialDateTime.minute);
+ } else {
+ this.initialDate = initialDate;
+ this.initialTime = initialTime;
+ }
+ this.initialDate = initialDate ?? now;
+ this.initialTime = initialTime ?? TimeOfDay(hour: 8, minute: 0);
+ this.lastDate = lastDate ?? DateTime(now.year + 1);
+ this.firstDate = firstDate ?? DateTime(now.year - 1);
+ selectedDate = initialDate;
+ }
+
+ /// Handles the "button pressed" event in DateFormField.
+ onButtonPressed(BuildContext context,
+ {required Function(DateTime selected) storeSelected}) async {
+ final TimeOfDay? picked = await showTimePicker(
+ context: context,
+ initialTime: initialTime ?? TimeOfDay(hour: 8, minute: 0),
+ );
+ if (picked != null) {
+ selectedTime = picked;
+ dateController.text = asString(selectedDate, dateOnly: true) +
+ sprintf(' %02d:%02d', [picked.hour, picked.minute]);
+ if (onSelected != null) {
+ onSelected!();
+ }
+ }
+ }
+
+ /// Sets the initial date to [dateTime].
+ void setInitialDate(DateTime? dateTime) {
+ if (dateTime == null) {
+ dateController.text = '';
+ initialDate = null;
+ initialTime = null;
+ } else {
+ initialDate = DateTime(dateTime.year, dateTime.month, dateTime.day);
+ dateController.text = asString(dateTime, dateOnly: true);
+ }
+ }
+}
+
+/// Manages a text field with a button to call a date picker.
+class DateTimeFormField extends Container {
+ final DateTimeData dateData;
+ final TextEditingController dateController;
+ DateTimeFormField(
+ {required BuildContext context,
+ required this.dateData,
+ required this.dateController,
+ Key? key,
+ FocusNode? focusNode,
+ InputDecoration? decoration = const InputDecoration(),
+ TextInputType? keyboardType = TextInputType.datetime,
+ TextInputAction? textInputAction,
+ TextStyle? style,
+ StrutStyle? strutStyle,
+ TextAlign textAlign = TextAlign.start,
+ TextAlignVertical? textAlignVertical,
+ bool autofocus = false,
+ bool readOnly = false,
+ ToolbarOptions? toolbarOptions,
+ bool? showCursor,
+ bool autocorrect = true,
+ SmartDashesType? smartDashesType,
+ SmartQuotesType? smartQuotesType,
+ bool enableSuggestions = true,
+ bool autovalidate = false,
+ bool maxLengthEnforced = true,
+ bool expands = false,
+ int? maxLength,
+ ValueChanged<String>? onChanged,
+ GestureTapCallback? onTap,
+ VoidCallback? onEditingComplete,
+ ValueChanged<String>? onFieldSubmitted,
+ FormFieldSetter<String>? onSaved,
+ FormFieldValidator<String>? validator,
+ bool? enabled,
+ double cursorWidth = 2.0,
+ double? cursorHeight,
+ Radius? cursorRadius,
+ Color? cursorColor,
+ Brightness? keyboardAppearance,
+ EdgeInsets scrollPadding = const EdgeInsets.all(20.0),
+ bool enableInteractiveSelection = true,
+ TextSelectionControls? selectionControls,
+ InputCounterWidgetBuilder? buildCounter,
+ ScrollPhysics? scrollPhysics,
+ Iterable<String>? autofillHints,
+ AutovalidateMode? autovalidateMode,
+ ScrollController? scrollController,
+ String? restorationId,
+ bool enableIMEPersonalizedLearning = true,
+ double? gapWidth,
+ DateTime? initialDate})
+ : super(
+ child: Row(children: <Widget>[
+ Expanded(
+ child: TextFormField(
+ onTap: onTap,
+ controller: dateController,
+ onEditingComplete: onEditingComplete,
+ onFieldSubmitted: onFieldSubmitted,
+ onSaved: onSaved,
+ validator: validator,
+ enabled: enabled,
+ cursorWidth: cursorWidth,
+ cursorHeight: cursorHeight,
+ cursorRadius: cursorRadius,
+ cursorColor: cursorColor,
+ keyboardAppearance: keyboardAppearance,
+ scrollPadding: scrollPadding,
+ enableInteractiveSelection: enableInteractiveSelection,
+ selectionControls: selectionControls,
+ buildCounter: buildCounter,
+ scrollPhysics: scrollPhysics,
+ autofillHints: autofillHints,
+ autovalidateMode: autovalidateMode,
+ scrollController: scrollController,
+ restorationId: restorationId,
+ enableIMEPersonalizedLearning: enableIMEPersonalizedLearning,
+ )),
+ SizedBox(width: gapWidth ?? GlobalThemeData.padding),
+ ElevatedButton(
+ onPressed: () =>
+ dateData.onButtonPressed(context, storeSelected: (selected) {
+ dateData.selectedDate = selected;
+ }),
+ child: Icon(Icons.calendar_today_outlined)),
+ SizedBox(width: gapWidth ?? GlobalThemeData.padding),
+ ElevatedButton(
+ onPressed: () =>
+ dateData.onButtonPressed(context, storeSelected: (selected) {
+ dateData.selectedDate = selected;
+ }),
+ child: Icon(Icons.lock_clock_outlined)),
+ ]));
+}
#! /bin/bash
APP=meta_tool
-/usr/bin/dart compile exe bin/$APP.dart -o ../tools/$APP
-
-
+OUT=$(dirname $(pwd))/tools
+/usr/bin/dart compile exe bin/$APP.dart -o $OUT/$APP
break;
}
var rc = replaceVariables(templateRecordCustom, page)
- .replaceFirst('#REQ_RECORD', requestRecord)
+ .replaceFirst('#REQ_RECORD', replaceVariables(requestRecord, page))
.replaceFirst('#DIDCHANGE', didChangeDependencies)
.replaceFirst('#DEF_CONTROLLER', buildDefinitionControllers(page))
.replaceFirst('#INIT_COMBO', buildInitializeComboBoxes(page))
+++ /dev/null
----
-# DO NOT CHANGE. This file is created by the meta_tool
-# SQL statements of the module "Roles":
-
-module: Roles
-list:
- type: list
- parameters: []
- sql: "SELECT
- t0.*
- FROM Roles t0
-
- ;"
-byId:
- type: record
- parameters: [ "id" ]
- sql: "SELECT * FROM Roles WHERE role_id=:id;"
-delete:
- type: delete
- parameters: [ "id" ]
- sql: "DELETE * FROM Roles WHERE role_id=:id;"
-update:
- type: update
- parameters: [":id",":name",":changedBy"]
- sql: "UPDATE Roles SET
- role_id=:id,role_name=:name,role_changedby=:changedBy,role_changed=NOW()
- WHERE role_id=:id;"
-insert:
- type: insert
- parameters: [":id",":name",":createdBy"]
- sql: "INSERT INTO Roles(role_id,role_name,role_createdby,role_created)
- VALUES(:id,:name,:createdBy,NOW());"
+++ /dev/null
----
-# DO NOT CHANGE. This file is created by the meta_tool
-# SQL statements of the module "Users":
-
-module: Users
-list:
- type: list
- parameters: []
- sql: "SELECT
- t0.*,t1.role_name AS role
- FROM Users t0
- JOIN roles t1 ON t1.role_id=t0.user_role
- ;"
-byId:
- type: record
- parameters: [ "id" ]
- sql: "SELECT * FROM Users WHERE user_id=:id;"
-delete:
- type: delete
- parameters: [ "id" ]
- sql: "DELETE * FROM Users WHERE user_id=:id;"
-update:
- type: update
- parameters: [":id",":name",":displayName",":email",":role",":changedBy"]
- sql: "UPDATE Users SET
- user_id=:id,user_name=:name,user_displayname=:displayName,user_email=:email,
- user_role=:role,user_changedby=:changedBy,user_changed=NOW()
- WHERE user_id=:id;"
-insert:
- type: insert
- parameters: [":id",":name",":displayName",":email",":role",":createdBy"]
- sql: "INSERT INTO Users(user_id,user_name,user_displayname,user_email,
- user_role,user_createdby,user_created)
- VALUES(:id,:name,:displayName,:email,:role,:createdBy,NOW());"
+++ /dev/null
-import 'package:dart_bones/dart_bones.dart';
-import 'package:test/test.dart';
-//import 'package:path/path.dart';
-
-import '../lib/base/defines.dart';
-import '../lib/base/helper.dart';
-import '../lib/base/i18n.dart';
-
-final i18n = I18N();
-
-void main() {
- final logger = MemoryLogger(LEVEL_FINE);
- I18N.internal(logger);
- FileSync.initialize(logger);
- //final fileSync = FileSync();
- //final baseDir = init(logger);
- //final targetDir = join(baseDir, nodeTarget);
- //fileSync.ensureDirectory(targetDir);
- group('secondsAsTime', () {
- test('days', () {
- expect(secondsAsTime(3 * 86400 + 5 * 3600 + 14 * 60 + 32), '3:05:14:32');
- });
- test('hours', () {
- expect(secondsAsTime(23 * 3600 + 9 * 60 + 4), '23:09:04');
- });
- test('minutes', () {
- expect(secondsAsTime(3 * 60 + 19), '03:19');
- });
- test('seconds', () {
- expect(secondsAsTime(59), '59');
- });
- test('days-millisecnds', () {
- expect(
- secondsAsTime((3 * 86400 + 5 * 3600 + 14 * 60 + 32) * 1000 + 49,
- isMilliSeconds: true),
- '3:05:14:32.049');
- });
- });
- group('jsonToObject', () {
- test('bool', () {
- expect(jsonToObject('T', dataType: DataType.bool, defaultValue: false),
- isTrue);
- expect(jsonToObject('F', dataType: DataType.bool, defaultValue: true),
- isFalse);
- expect(jsonToObject('x', dataType: DataType.bool, defaultValue: true),
- isTrue);
- expect(jsonToObject('y', dataType: DataType.bool, defaultValue: false),
- isFalse);
- });
- test('datetime', () {
- expect(
- jsonToObject('2021-8-3 2:4',
- dataType: DataType.datetime, defaultValue: false),
- DateTime(2021, 8, 3, 2, 4));
- });
- test('date', () {
- expect(
- jsonToObject('2021-10-3',
- dataType: DataType.date, defaultValue: false),
- DateTime(2021, 10, 3));
- });
- test('int-nat-reference', () {
- expect(jsonToObject(332211, dataType: DataType.nat), 332211);
- expect(jsonToObject('332209', dataType: DataType.int), 332209);
- expect(jsonToObject('220944', dataType: DataType.reference), 220944);
- expect(jsonToObject(2209443, dataType: DataType.reference), 2209443);
- expect(jsonToObject('xy', dataType: DataType.reference), isNull);
- });
- });
- group('fromString', () {
- test('bool', () {
- expect(fromString('T', dataType: DataType.bool, defaultValue: false),
- isTrue);
- expect(fromString('F', dataType: DataType.bool, defaultValue: true),
- isFalse);
- expect(
- fromString(i18n.tr('Yes'),
- dataType: DataType.bool, defaultValue: false),
- isTrue);
- expect(
- fromString(i18n.tr('No'),
- dataType: DataType.bool, defaultValue: true),
- isFalse);
- expect(fromString('', dataType: DataType.bool, defaultValue: false),
- isFalse);
- expect(
- fromString('', dataType: DataType.bool, defaultValue: true), isTrue);
- });
- test('int', () {
- expect(fromString('123', dataType: DataType.int, defaultValue: -1), 123);
- expect(
- fromString('-1234', dataType: DataType.int, defaultValue: -1), -1234);
- expect(fromString('', dataType: DataType.int, defaultValue: -1), -1);
- expect(fromString('a15', dataType: DataType.int, defaultValue: -1), -1);
- });
- test('nat', () {
- expect(fromString('123', dataType: DataType.nat, defaultValue: -1), 123);
- expect(fromString('-1234', dataType: DataType.nat, defaultValue: -1), -1);
- expect(fromString('', dataType: DataType.nat, defaultValue: -1), -1);
- expect(fromString('a15', dataType: DataType.nat, defaultValue: -1), -1);
- });
- test('reference', () {
- expect(fromString('123', dataType: DataType.reference, defaultValue: -1),
- 123);
- expect(
- fromString('-1234', dataType: DataType.reference, defaultValue: -1),
- -1234);
- expect(
- fromString('', dataType: DataType.reference, defaultValue: -1), -1);
- expect(fromString('a15', dataType: DataType.reference, defaultValue: -1),
- -1);
- });
- test('float', () {
- expect(fromString('123.76', dataType: DataType.float, defaultValue: -1),
- 123.76);
- expect(fromString('-4123.76', dataType: DataType.float, defaultValue: -1),
- -4123.76);
- expect(fromString('', dataType: DataType.float, defaultValue: -99999999),
- -99999999);
- expect(
- fromString('Nothing',
- dataType: DataType.float, defaultValue: -99999999),
- -99999999);
- });
- test('currency', () {
- expect(
- fromString('123.76', dataType: DataType.currency, defaultValue: -1),
- 123.76);
- expect(
- fromString('-4123.76', dataType: DataType.currency, defaultValue: -1),
- -4123.76);
- expect(
- fromString('', dataType: DataType.currency, defaultValue: -99999999),
- -99999999);
- expect(
- fromString('Nothing',
- dataType: DataType.currency, defaultValue: -99999999),
- -99999999);
- });
- test('date', () {
- expect(fromString('7.3.1987', dataType: DataType.date),
- DateTime(1987, 3, 7));
- expect(fromString('17.12.2035', dataType: DataType.date),
- DateTime(2035, 12, 17));
- expect(fromString('2012.6.2', dataType: DataType.date),
- DateTime(2012, 6, 2));
- expect(fromString('1923.10.31', dataType: DataType.date),
- DateTime(1923, 10, 31));
- expect(fromString('17.12.21', dataType: DataType.date), isNull);
- });
- test('datetime', () {
- expect(fromString('17.12.2035', dataType: DataType.datetime),
- DateTime(2035, 12, 17));
- expect(fromString('7.3.1987', dataType: DataType.datetime),
- DateTime(1987, 3, 7));
- expect(fromString('2012.6.2', dataType: DataType.datetime),
- DateTime(2012, 6, 2));
- expect(fromString('1923.10.31', dataType: DataType.datetime),
- DateTime(1923, 10, 31));
- expect(fromString('17.12.21', dataType: DataType.datetime), isNull);
- expect(fromString('7.3.1987T2:44', dataType: DataType.datetime),
- DateTime(1987, 3, 7, 2, 44));
- expect(fromString('17.12.2035 13:59:22', dataType: DataType.datetime),
- DateTime(2035, 12, 17, 13, 59, 22));
- expect(fromString('2012.6.2/23:59:59', dataType: DataType.datetime),
- DateTime(2012, 6, 2, 23, 59, 59));
- expect(fromString('1923.10.31-3:4', dataType: DataType.datetime),
- DateTime(1923, 10, 31, 3, 4));
- });
- });
- group('asPattern', () {
- test('unchanged', () {
- expect(asPattern('A test!123'), 'A test!123%');
- });
- test('with *', () {
- expect(asPattern('*Wu*ff'), '%Wu%ff%');
- });
- test('empty', () {
- expect(asPattern(''), '%');
- });
- test('with ?', () {
- expect(asPattern('M??r'), 'M__r%');
- });
- test('mixed', () {
- expect(asPattern('*M?i*r'), '%M_i%r%');
- });
- });
- group('asString', () {
- test('bool', () {
- expect(asString(true), i18n.tr('Yes'));
- expect(asString(false), i18n.tr('No'));
- expect(asString(true, dbFormat: true), 'T');
- expect(asString(false, dbFormat: true), 'F');
- });
- test('int', () {
- expect(asString(12345), '12345');
- expect(asString(-33), '-33');
- expect(asString(-33, dbFormat: true), '-33');
- expect(asString(884433, dbFormat: true), '884433');
- });
- test('double', () {
- expect(asString(7733.0), '7733.00');
- expect(asString(-123.77), '-123.77');
- expect(asString(1E-99), '.00');
- expect(asString(7733.0, dbFormat: true), '7733.00');
- expect(asString(-123.77, dbFormat: true), '-123.77');
- });
- test('Date', () {
- expect(asString(DateTime(2021, 10, 3), dateOnly: true), '03.10.2021');
- expect(
- asString(DateTime(2021, 10, 3, 9, 33), dateOnly: true), '03.10.2021');
- expect(asString(DateTime(2021, 10, 3, 9, 33), dateOnly: false),
- '03.10.2021 09:33');
- expect(asString(DateTime(2021, 10, 3, 9, 33, 14), dateOnly: false),
- '03.10.2021 09:33');
- expect(
- asString(DateTime(2021, 10, 3, 9, 33, 14),
- dateOnly: false, withSeconds: true),
- '03.10.2021 09:33:14');
- expect(asString(DateTime(2021, 7, 3), dbFormat: true, dateOnly: true),
- '2021-07-03');
- expect(
- asString(DateTime(2021, 10, 3, 9, 33),
- dbFormat: true, dateOnly: true),
- '2021-10-03');
- expect(
- asString(DateTime(2021, 7, 3, 9, 33),
- dbFormat: true, dateOnly: false),
- '2021-07-03 09:33:00');
- expect(
- asString(DateTime(2021, 10, 3, 9, 33, 14),
- dbFormat: true, dateOnly: false),
- '2021-10-03 09:33:14');
- expect(
- asString(DateTime(2021, 10, 3, 9, 33, 14),
- dbFormat: true, dateOnly: false, withSeconds: true),
- '2021-10-03 09:33:14');
- });
- test('string', () {
- expect(asString('A test!123'), 'A test!123');
- expect(asString('A test!123', dbFormat: true), 'A test!123');
- });
- test('string', () {
- expect(asString('A test!123'), 'A test!123');
- });
- test('string', () {
- expect(asString('A test!123'), 'A test!123');
- });
- });
-}
+++ /dev/null
-import 'package:dart_bones/dart_bones.dart';
-import 'package:test/test.dart';
-
-import '../lib/base/validators.dart' as validators;
-import '../lib/base/i18n.dart';
-
-final i18n = I18N();
-
-void main() {
- final logger = MemoryLogger(LEVEL_FINE);
- I18N.internal(logger);
- FileSync.initialize(logger);
- group('isEmail', () {
- test('standard', () {
- expect(validators.isEmail('abc@example.com'), isNull);
- expect(validators.isEmail(null), isNull);
- });
- test('wrong char', () {
- expect(validators.isEmail('/abc@example.com'), 'Illegal character "/" in email address');
- });
- test('wrong syntax', () {
- expect(validators.isEmail('abc@example'), 'Not an email address: abc@example');
- });
- });
- group('isInt', () {
- test('OK', () {
- expect(validators.isInt('123456'), isNull);
- expect(validators.isInt('-123456'), isNull);
- expect(validators.isInt(null), isNull);
- });
- test('errors', () {
- expect(validators.isInt('x'), 'Not an integer: x');
- expect(validators.isInt('123.77'), 'Not an integer: 123.77');
- });
- });
- group('isNat', () {
- test('OK', () {
- expect(validators.isNat('123456'), isNull);
- expect(validators.isNat('0'), isNull);
- expect(validators.isNat(null), isNull);
- });
- test('errors', () {
- expect(validators.isNat('-123456'), 'Not negative integer expected, not: -123456');
- expect(validators.isNat('x'), 'Not an integer: x');
- expect(validators.isNat('123.77'), 'Not an integer: 123.77');
- });
- });
- group('notEmpty', () {
- test('OK', () {
- expect(validators.notEmpty('Go'), isNull);
- });
- test('error', () {
- expect(validators.notEmpty(''), 'Please fill in.');
- expect(validators.notEmpty(null), 'Please fill in.');
- });
- });
- group('validateMultiple', () {
- test('OK', () {
- expect(validators.validateMultiple('abc@example.com', [(x) => validators.notEmpty(x),
- (x) => validators.isEmail(x)]), isNull);
- });
- test('Error', () {
- expect(validators.validateMultiple('0x72z', [(x) => validators.notEmpty(x),
- (x) => validators.isInt(x)]), 'Not an integer: 0x72z');
- });
- });
-}
echo "+++ $*"
}
function MkDirs(){
- for dir in tools rest_server/data; do
- mkdir -p $dir
- done
+ cd $APP
+ for dir in tools rest_server/data; do
+ test -d $dir || mkdir -p $dir
+ done
+ cd ..
}
function EnsureDir(){
local dir=$1
mkdir -p $dir
fi
}
+# Copy many files from exhibition.
function CopyFiles(){
+ cd $APP
local projDir=$(pwd)
cd ../exhibition
local srcDir=$(pwd)
- for file in lib/base/*.dart \
- lib/meta/module_meta_data.dart \
+ for file in lib/meta/module_meta_data.dart \
lib/meta/modules.dart \
rest_server/pubspec.yaml \
tools/PackRestServer \
if [ -z "$DO_UPDATE" -o ! -e $file ]; then
local dir=$(dirname $file)
EnsureDir $dir
- echo "creating $file"
- cp -a ../exhibition/$file $file
+ #echo "creating $file"
+ cp -av $srcDir/$file $file
fi
cd $srcDir
done
cd $projDir
+ cd ..
}
-function CopyFile(){
+# Copy one file.
+function CopyAndReplaceOne(){
local projDir=$1
local file=$2
local srcDir=$3
cd $projDir
local dir=$(dirname $file)
EnsureDir $dir
- local file2=${file/exhibition/$APP}
- echo "copy and replace $file -> $(basename $file2)"
- sed <../exhibition/$file >$file2 -e "s/exhibition/$APP/g" -e "s/Exhibition/$APP2/g"
- chmod --reference=../exhibition/$file $file2
+ local fileTrg=${file/exhibition/$APP}
+ echo "copy and replace $file -> $(basename $fileTrg)"
+ sed <../exhibition/$file >$fileTrg -e "s/exhibition/$APP/g" -e "s/Exhibition/$APP2/g"
+ chmod --reference=../exhibition/$file $fileTrg
cd $srcDir
}
+# Copy many files and replaces variables in the file content.
function CopyAndReplace(){
+ cd $APP
local projDir=$(pwd)
cd ../exhibition
local srcDir=$(pwd)
local filesNewOnly=$(echo pubspec.yaml \
+ lib/base/*.dart \
+ lib/common/*.dart \
+ lib/meta/*_meta.dart \
lib/persistence/*.dart \
lib/page/*.dart \
- lib/main.dart \
- lib/meta/*_meta.dart \
- bin/*.dart \
+ lib/page/benchmarks/*.dart \
+ lib/page/roles/*.dart \
+ lib/page/rolestarter/*.dart \
+ lib/page/starters/*.dart \
+ lib/page/structures/*.dart \
+ lib/page/users/*.dart \
+ lib/services/*.dart \
+ lib/setting/*.dart \
+ lib/widget/*.dart \
+ lib/*.dart
)
local filesAlways=$(echo rest_server/lib/*.dart \
rest_server/bin/*.dart \
rest_server/tools/project.inc \
rest_server/CR
)
-
- if [ -z "$DO_UPDATE" ]; then
- for file in lib/setting/*.dart \
- pubspec.yaml \
- lib/persistence/*.dart \
- lib/page/*.dart \
- rest_server/lib/*.dart rest_server/bin/*.dart rest_server/tools/project.inc \
- rest_server/CR \
- lib/main.dart \
- lib/meta/*_meta.dart \
- bin/*.dart \
- ; do
- CopyFile $projDir $file $srcDir
- done
- else
- fi
+ local files=$filesAlways
+ test -z "$DO_UPDATE" && files="$files $filesNewOnly"
+ for file in $files; do
+ CopyAndReplaceOne $projDir $file $srcDir
+ done
cd $projDir
+ cd ..
}
+# Creates symbolic links to the exhibition directory.
function SymbolicLinks(){
+ cd $APP
for links in ReCreateMetaTool:. Meta:. dart_tools:. \
; do
local src=../exhibition/${links%:*}
ln -s $src $trg2
fi
done
- for links in dart_tools/tools/i18n_text_parser:tools \
+ for link in dart_tools/tools/i18n_text_parser:tools \
dart_tools/tools/yaml_merger:tools \
; do
- local src=../../exhibition/${links%:*}
- local trg=${links#*:}
- local trg2=$trg
- test $trg = . && trg2=$(basename $src)
- echo "trg: $trg2"
+ local src=../../exhibition/${link%:*}
+ local trg=${link#*:}
+ local trg2=$trg/$(basename $src)
+ #echo "trg: $trg2"
if [ ! -L $trg2 ]; then
- echo "linking $src -> $trg2"
- ln -s $src $trg2
+ #echo "linking $src -> $trg2"
+ ln -sv $src $trg2
fi
done
+ cd ..
}
+# Executes scripts in exhibition/tools
function PrepareTools(){
local tool
- local curDir=$(pwd)
- echo "PrepareTools: pwd=$curDir"
- for tool in i18n_text_parser:CompileI18n \
- yaml_merger:CompileMerge; do
- local exe=${tool%:*}
- local script=${tool#*:}
- if [ ! -e ../exhibition/dart_tools/tools/$exe ]; then
- cd ../exhibition/dart_tools
- echo "executing $script"
- tools/$script
- fi
- cd $curDir
- done
+ if [ ! -d exhibition ]; then
+ echo "+++ wrong current directory: missing exhibition"
+ else
+ local baseDir=$( pwd)
+ cd exhibition/dart_tools
+ local curDir=$( pwd)
+ for tool in i18n_text_parser:CompileI18n \
+ yaml_merger:CompileMerge; do
+ local exe=${tool%:*}
+ local script=${tool#*:}
+ if [ -e tools/$exe ]; then
+ echo "already exists: $exe"
+ else
+ echo "executing $script"
+ tools/$script
+ fi
+ cd $curDir
+ done
+ cd $baseDir
+ fi
+}
+# Copies and links files of the metatool directory.
+function CreateMetaData(){
+ cd $APP
+ mkdir -p metatool/lib/base metatool/lib/meta
+ cd metatool/lib/base
+ ln -sv ../../../../exhibition/metatool/lib/base/* .
+ rm -f application_name.dart
+ cat <<EOS >application_name.dart
+const theApplicationName = '$APP';
+const theVariantName = '$APP';
+EOS
+ cd ../..
+ ln -vs ../../exhibition/metatool/bin .
+ cp -av ../../exhibition/metatool/lib/meta/* lib/meta
+ ln -vs ../../exhibition/metatool/Compile .
+ ln -vs ../../exhibition/metatool/pubspec.yaml .
+ cp -av ../../exhibition/metatool/local.properties .
+ cp -av ../../exhibition/metatool/metatool.iml .
+ cd ../..
}
+# Initializes the base directory with flutter
function Flutter(){
local app=$1
flutter create $app
cd $app
flutter config linux
+ cd ..
}
function Finish(){
+ cd $APP
dart pub upgrade
+ cd ..
}
if [ -z "$APP" ]; then
Usage "missing PROJECT"
-elif [ -n $DO_UPDATE -a $DO_UPDATE != '--update' ]; then
+elif [ -n "$DO_UPDATE" -a "$DO_UPDATE" != '--update' ]; then
Usage "Unknown option: $DO_UPDATE"
-elif [ -d $APP ]; then
+elif [ -n "$DO_UPDATE" -a -d $APP ]; then
Usage "PROJECT already exists."
elif [ ! -d exhibition/dart_tools ]; then
Usage "wrong current directory: Please go into the base folder of the project."
else
- test -n "$DO_UPDATE" && Flutter $APP
+ test -z "$DO_UPDATE" && Flutter $APP
PrepareTools
MkDirs
CopyFiles
CopyAndReplace
SymbolicLinks
+ CreateMetaData
Finish
fi
cat <<EOS >$BASE_DIR/INSTALL.TXT
# ------------
# Installation:
-./InstallRestServer
+cd /tmp
+sudo ./InstallRestServer
# or manually:
DIR=\$(pwd)
mkdir -p /usr/share/$PROJECT && cd /usr/share/$PROJECT
-tar xzf \DIR/$TAR_NODE
+tar xzf \$DIR/$TAR_NODE
# ./$EXE install <executable> <service-name>
./$EXE install /usr/share/$PROJECT/$EXE $PROJECT
# see /usr/share/$PROJECT and /etc/$PROJECT