--- /dev/null
+#! /bin/bash
+MODULE=$1
+if [ -z "$MODULE" ]; then
+ echo "Missing module name"
+else
+ cd lib/src/page
+ if [ -d $MODULE ]; then
+ FN_NEW=/tmp/$MODULE.$(date "+%s")
+ echo "$MODULE already exists, moving to $FN_NEW"
+ mv $MODULE $FN_NEW
+ fi
+ mkdir $MODULE
+ cp -av role/* $MODULE/
+ FN_REPL=/tmp/create_module.repl
+ MODULE3=$(echo $MODULE | tr a-z A-Z)
+ MODULE2=${MODULE3:0:1}${MODULE:1}
+ # echo -e "role\t$MODULE\nRole\t$MODULE2" >$FN_REPL
+ cd $MODULE
+ perl -pi -e"s/role/$MODULE/g;s/Role/$MODULE2/g;" *.dart
+ rename -v "s/role(.*)/${MODULE}\$1/;" *.dart
+fi
\ No newline at end of file
import 'src/page/role/role_change_page.dart';
import 'src/page/role/role_create_page.dart';
import 'src/page/role/role_list_page.dart';
-import 'src/page/user/user_change_page.dart';
-import 'src/page/user/user_create_page.dart';
-import 'src/page/user/user_list_page.dart';
-import 'src/page/configuration/configuration_change_page.dart';
-import 'src/page/configuration/configuration_create_page.dart';
-import 'src/page/configuration/configuration_list_page.dart';
import 'src/private/bsettings.dart';
class BoneApp extends StatefulWidget {
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
- initialRoute: '/role/list',
+ initialRoute: '/role/create',
onGenerateRoute: _getRoute,
);
}
case '/role/create':
page = RoleCreatePage(BSettings.lastInstance.pageData);
break;
- /*
+ /*
case '/user/list':
page = UserListPage(BSettings.lastInstance.pageData);
break;
+++ /dev/null
-import 'package:flutter_bones/flutter_bones.dart';
-
-/// Base class of all controller classes in this package.
-abstract class BaseController {
- /// Returns the assigned model.
- WidgetModel getModel();
-
- /// Returns a unique name of the controller inside the module, mostly the
- /// widget name of the assigned model.
- String getName();
-}
--- /dev/null
+import 'package:flutter_bones/flutter_bones.dart';
+
+/// Base class of all controller classes in this package.
+abstract class BaseController {
+ /// Returns the assigned model.
+ WidgetModel getModel();
+
+ /// Returns a unique name of the controller inside the module, mostly the
+ /// widget name of the assigned model.
+ String getName();
+}
+++ /dev/null
-import 'package:flutter_bones/flutter_bones.dart';
-import 'package:flutter_bones/src/controller/base_controller.dart';
-
-import '../widget/raised_button_bone.dart';
-
-class ButtonController extends BaseController
- implements ButtonCallbackController {
- ButtonModel model;
-
- ButtonController(this.model);
-
- @override
- WidgetModel getModel() {
- return model;
- }
-
- @override
- String getName() {
- return model.widgetName();
- }
-
- @override
- getOnHighlightChanged(
- String customString, ButtonCallbackController controller) {
- return null;
- }
-
- @override
- getOnLongPressed(String customString, ButtonCallbackController controller) {
- return null;
- }
-
- @override
- getOnPressed(String customString, ButtonCallbackController controller) {
- var rc;
- switch (model.buttonModelType) {
- case ButtonModelType.cancel:
- break;
- case ButtonModelType.custom:
- break;
- case ButtonModelType.search:
- break;
- case ButtonModelType.store:
- break;
- }
- return rc;
- }
-}
--- /dev/null
+import 'package:flutter/material.dart';
+import 'package:flutter_bones/flutter_bones.dart';
+import 'package:flutter_bones/src/controller/base_controller.dart';
+
+import '../widget/raised_button_bone.dart';
+
+class ButtonController extends BaseController
+ implements ButtonCallbackController {
+ ButtonModel model;
+
+ ButtonController(this.model);
+
+ @override
+ WidgetModel getModel() {
+ return model;
+ }
+
+ @override
+ String getName() {
+ return model.widgetName();
+ }
+
+ @override
+ getOnHighlightChanged(String customString, ButtonCallbackController controller) {
+ return null;
+ }
+
+ @override
+ getOnLongPressed(String customString, ButtonCallbackController controller) {
+ return null;
+ }
+
+ @override
+ getOnPressed(String customString, ButtonCallbackController controller) {
+ var rc;
+ switch (model.buttonModelType) {
+ case ButtonModelType.cancel:
+ break;
+ case ButtonModelType.custom:
+ break;
+ case ButtonModelType.search:
+ break;
+ case ButtonModelType.store:
+ break;
+ }
+ return rc;
+ }
+
+ @override
+ BuildContext getContext() {
+ return null;
+ }
+}
+++ /dev/null
-import 'package:flutter_bones/flutter_bones.dart';
-
-import '../widget/dropdown_button_form_bone.dart';
-import 'base_controller.dart';
-
-class ComboboxController<T> extends BaseController
- implements ComboboxCallbackController {
- ComboboxModel model;
-
- ComboboxController(this.model);
-
- @override
- WidgetModel getModel() {
- return model;
- }
-
- @override
- String getName() {
- return model.widgetName();
- }
-
- @override
- getOnChanged(String customString, ComboboxCallbackController controller) {
- return null;
- }
-
- @override
- getOnSaved(String customString, ComboboxCallbackController controller) {
- return null;
- }
-
- @override
- getOnSelectedItemBuilder(
- String customString, ComboboxCallbackController controller) {
- return null;
- }
-
- @override
- getOnTap(String customString, ComboboxCallbackController controller) {
- return null;
- }
-
- @override
- getOnValidator(String customString, ComboboxCallbackController controller) {
- return null;
- }
-
- @override
- List<String> texts() {
- return model.texts;
- }
-
- @override
- List<dynamic> values() {
- return model.values;
- }
-}
--- /dev/null
+import 'package:flutter_bones/flutter_bones.dart';
+
+import '../widget/dropdown_button_form_bone.dart';
+import 'base_controller.dart';
+
+class ComboboxController<T> extends BaseController
+ implements ComboboxCallbackController {
+ ComboboxModel model;
+
+ ComboboxController(this.model);
+
+ @override
+ WidgetModel getModel() {
+ return model;
+ }
+
+ @override
+ String getName() {
+ return model.widgetName();
+ }
+
+ @override
+ getOnChanged(String customString, ComboboxCallbackController controller) {
+ return null;
+ }
+
+ @override
+ getOnSaved(String customString, ComboboxCallbackController controller) {
+ return null;
+ }
+
+ @override
+ getOnSelectedItemBuilder(
+ String customString, ComboboxCallbackController controller) {
+ return null;
+ }
+
+ @override
+ getOnTap(String customString, ComboboxCallbackController controller) {
+ return null;
+ }
+
+ @override
+ getOnValidator(String customString, ComboboxCallbackController controller) {
+ return null;
+ }
+
+ @override
+ List<String> texts() {
+ return model.texts;
+ }
+
+ @override
+ List<dynamic> values() {
+ return model.values;
+ }
+}
+++ /dev/null
-import 'package:flutter_bones/flutter_bones.dart';
-
-import '../widget/text_form_field_bone.dart';
-import 'base_controller.dart';
-
-class TextFormController extends BaseController
- implements TextFormCallbackController {
- ComboboxModel model;
-
- TextFormController(this.model);
-
- @override
- WidgetModel getModel() {
- return model;
- }
-
- @override
- String getName() {
- return model.widgetName();
- }
-
- @override
- getOnChanged(String customString, TextFormCallbackController controller) {
- return null;
- }
-
- @override
- getOnEditingComplete(
- String customString, TextFormCallbackController controller) {
- return null;
- }
-
- @override
- getOnFieldSubmitted(
- String customString, TextFormCallbackController controller) {
- return null;
- }
-
- @override
- getOnSaved(String customString, TextFormCallbackController controller) {
- return null;
- }
-
- @override
- getOnTap(String customString, TextFormCallbackController controller) {
- return null;
- }
-
- @override
- getValidator(String customString, TextFormCallbackController controller) {
- return null;
- }
-}
--- /dev/null
+import 'package:flutter_bones/flutter_bones.dart';
+
+import '../widget/text_form_field_bone.dart';
+import 'base_controller.dart';
+
+class TextFormController extends BaseController
+ implements TextFormCallbackController {
+ ComboboxModel model;
+
+ TextFormController(this.model);
+
+ @override
+ WidgetModel getModel() {
+ return model;
+ }
+
+ @override
+ String getName() {
+ return model.widgetName();
+ }
+
+ @override
+ getOnChanged(String customString, TextFormCallbackController controller) {
+ return null;
+ }
+
+ @override
+ getOnEditingComplete(
+ String customString, TextFormCallbackController controller) {
+ return null;
+ }
+
+ @override
+ getOnFieldSubmitted(
+ String customString, TextFormCallbackController controller) {
+ return null;
+ }
+
+ @override
+ getOnSaved(String customString, TextFormCallbackController controller) {
+ return null;
+ }
+
+ @override
+ getOnTap(String customString, TextFormCallbackController controller) {
+ return null;
+ }
+
+ @override
+ getValidator(String customString, TextFormCallbackController controller) {
+ return null;
+ }
+}
String countryCode;
SettingLocale({this.languageCode, this.countryCode});
}
+
class BaseSettings {
static var locale = SettingLocale(countryCode: 'US', languageCode: 'en');
}
return rc;
}
+
+ /// Convert [value] into a string for storing in a database respecting [dataType].
+ static String asDatabaseString(dynamic value, DataType dataType) {
+ if (value == null) {
+ value = 'NULL';
+ } else {
+ switch (dataType) {
+ case DataType.dateTime:
+ value = DateFormat('yyyy-MM-dd HH:mm:ss').format(value);
+ break;
+ case DataType.date:
+ value = DateFormat('yyyy-MM-dd').format(value);
+ break;
+ case DataType.bool:
+ value = value ? 'T' : 'F';
+ break;
+ default:
+ value = value.toString();
+ break;
+ }
+ }
+ return value;
+ }
}
import 'package:dart_bones/dart_bones.dart';
+import 'db_reference_model.dart';
import 'page_model.dart';
import 'section_model.dart';
+import 'table_model.dart';
import 'widget_model.dart';
/// Describes a text widget without user interaction.
AllDbFieldsModel(
SectionModel section, PageModel page, this.map, BaseLogger logger)
- : super(section, page, WidgetModelType.text, logger);
+ : super(section, page, WidgetModelType.allDbFields, logger);
/// Returns the name including the names of the parent
@override
/// Dumps the internal structure into a [stringBuffer]
StringBuffer dump(StringBuffer stringBuffer) {
- stringBuffer
- .write(' allDbFields $id text: options: ${options.join(' ')}\n');
+ stringBuffer.write(' allDbFields $id options: ${options.join(' ')}\n');
return stringBuffer;
}
void parse() {
checkSuperfluousAttributes(map, 'options widgetType'.split(' '));
options = parseOptions('options', map);
+ addFieldsOfTable(page.module.mainTable());
checkOptionsByRegExpr(options, regExprOptions);
}
@override
String widgetName() => 'allDbFields$id';
+
+ void addFieldsOfTable(TableModel table) {
+ bool isCreatePage = page.pageModelType == PageModelType.create;
+ table.columns.forEach((col) {
+ if (col.hasOption('doStore') ||
+ (!col.hasOption('hidden') &&
+ (!isCreatePage || !col.hasOption('primary')))) {
+ final field = DbReferenceModel.direct(section, page, col, logger);
+ page.addField(field);
+ page.widgets.add(field);
+ }
+ });
+ }
}
/// Parses the map and stores the data in the instance.
void parse() {
- super.parse();
checkSuperfluousAttributes(
map,
'name label dataType filterType options texts toolTip widgetType values'
.split(' '));
+ super.parse();
texts = parseStringList('texts', map);
values = parseValueList('values', map, dataType);
options = parseOptions('options', map);
/// Describes a form text field widget.
class DbReferenceModel extends FieldModel {
static final regExprOptions =
- RegExp(r'^(readonly|disabled|required|password|unique)$');
+ RegExp(r'^(readonly|disabled|required|password|unique|combobox|undef)$');
int maxSize;
int rows;
var value;
ColumnModel column;
- final Map<String, dynamic> map;
+ /// A constructor fetching the properties by parsing the [map].
DbReferenceModel(
- SectionModel section, PageModel page, this.map, BaseLogger logger)
- : super(section, page, map, WidgetModelType.textField, logger);
+ SectionModel section, PageModel page, Map map, BaseLogger logger)
+ : super(section, page, map, WidgetModelType.dbReference, logger);
+
+ /// A constructor without map parsing.
+ DbReferenceModel.direct(SectionModel section, PageModel page,
+ ColumnModel column, BaseLogger logger)
+ : super.direct(
+ section,
+ page,
+ null,
+ WidgetModelType.dbReference,
+ column.name,
+ column.label,
+ column.toolTip,
+ column.dataType,
+ column.options,
+ logger) {
+ this.column = column;
+ maxSize = column.size;
+ rows = column.rows;
+ }
/// Dumps the internal structure into a [stringBuffer]
StringBuffer dump(StringBuffer stringBuffer) {
WidgetModelType fieldModelType, BaseLogger logger)
: super(section, page, fieldModelType, logger);
+ FieldModel.direct(
+ SectionModel section,
+ PageModel page,
+ this.map,
+ WidgetModelType fieldModelType,
+ String name,
+ String label,
+ String toolTip,
+ DataType dataType,
+ List<String> options,
+ BaseLogger logger,
+ [FilterType filterType])
+ : super(section, page, fieldModelType, logger) {
+ this.name = name;
+ this.label = label;
+ this.toolTip = toolTip;
+ this.options = options;
+ this.dataType = dataType;
+ this.filterType = filterType;
+ }
+
get value => _value;
/// Stores the value of the field.
addColumnIfMissing(columns, table.columns, '${table.name}_createdby');
buffer.write(columns.fold(
'',
- (prev, col) =>
- (prev as String) +
+ (prev, col) =>
+ (prev as String) +
((prev as String).isEmpty ? col.name : ',' + col.name)));
buffer.write(')\n');
buffer.write(' VALUES(');
buffer.write(columns.fold(
'',
- (prev, col) =>
- (prev as String) +
+ (prev, col) =>
+ (prev as String) +
((prev as String).isEmpty ? '' : ',') +
(col.name.endsWith('createdat') ? 'NOW()' : (':' + col.name))));
buffer.write(');"\n');
/// Writes the list SQL part into the [buffer].
void exportList(StringBuffer buffer, TableModel table) {
final page = pages.firstWhere(
- (element) => element.pageModelType == PageModelType.list,
+ (element) => element.pageModelType == PageModelType.list,
orElse: () => null);
if (page != null) {
buffer.write(''' - name: list
type: list
sql: "SELECT * from ${table.name}\n''');
// @ToDo: joins
- final fields = page.fields.values
+ final fields = page.fields
.where((item) => item is FieldModel && item.filterType != null);
if (fields.isEmpty) {
buffer.write(' WHERE 1;"');
.forEach((col) {
exportRecordOne(
'by_${col.name}',
- '${col.name}=:${col.name}&&${table.name}_id!=:excluded', buffer,
+ '${col.name}=:${col.name}&&${table.name}_id!=:excluded',
+ buffer,
table);
});
}
/// Writes the record SQL part into the [buffer].
- void exportRecordOne(String sqlName, String condition, StringBuffer buffer,
- TableModel table) {
+ void exportRecordOne(
+ String sqlName, String condition, StringBuffer buffer, TableModel table) {
buffer.write(' - name: $sqlName\n');
buffer.write(' type: record\n');
buffer.write(
buffer.write(' sql: "UPDATE ${table.name} SET\n ');
final columns = table.columns
.where((col) =>
- col.hasOption('doStore') ||
- (!col.hasOption('primary') && !col.hasOption('hidden')))
+ col.hasOption('doStore') ||
+ (!col.hasOption('primary') && !col.hasOption('hidden')))
.toList();
addColumnIfMissing(columns, table.columns, '${table.name}_changedat');
addColumnIfMissing(columns, table.columns, '${table.name}_changedby');
/// Returns a child page given by [name], null otherwise.
PageModel pageByName(String name) {
final found =
- pages.firstWhere((element) => element.name == name, orElse: () => null);
+ pages.firstWhere((element) => element.name == name, orElse: () => null);
return found;
}
final List<SectionModel> sections = [];
PageModelType pageModelType;
List<String> options;
- final fields = <String, FieldModel>{};
+ final fields = <FieldModel>[];
final buttons = <String, ButtonModel>{};
final widgets = <WidgetModel>[];
}
}
+ /// Tests whether the field with [name] is part of the page.
+ bool hasField(String name) {
+ final first = fields.firstWhere((element) => element.name == name,
+ orElse: () => null);
+ final rc = first != null;
+ return rc;
+ }
+
/// Adds a [field] to the [this.fields].
/// If already defined and error is logged.
void addField(FieldModel field) {
final name = field.name;
- if (fields.containsKey(name)) {
+ if (hasField(name)) {
logger.error('field ${field.fullName()} already defined: ' +
- fields[name].fullName());
+ getField(name).fullName());
} else {
- fields[name] = field;
+ fields.add(field);
}
}
/// Returns a field by [name] or null on error.
FieldModel getField(String name, {bool required = true}) {
- FieldModel rc;
- if (!fields.containsKey(name)) {
- if (required) {
- logger.error('missing field $name in page ${fullName()}');
- }
- } else {
- rc = fields[name];
+ final rc = fields.firstWhere((element) => element.name == name,
+ orElse: () => null);
+ if (required && rc == null) {
+ logger.error('missing field $name in page ${fullName()}');
}
return rc;
}
import 'package:dart_bones/dart_bones.dart';
+
import 'all_db_fields_model.dart';
-import 'db_reference_model.dart';
import 'button_model.dart';
import 'checkbox_model.dart';
import 'combobox_model.dart';
+import 'db_reference_model.dart';
import 'empty_line_model.dart';
import 'model_base.dart';
import 'page_model.dart';
if (!ModelBase.isMap(child)) {
logger
.error('child $no of "children" is not a map in ${fullName()}: '
- '${StringUtils.limitString(child.toString(), 80)}');
+ '${StringUtils.limitString(child.toString(), 80)}');
} else {
if (!child.containsKey('widgetType')) {
logger.error(
break;
case WidgetModelType.combobox:
widget = ComboboxModel(this, page, child, logger);
- page.addField(widget);
break;
case WidgetModelType.textField:
widget = TextFieldModel(this, page, child, logger);
case WidgetModelType.textField:
case WidgetModelType.combobox:
case WidgetModelType.checkbox:
+ case WidgetModelType.dbReference:
page.addField(widget);
break;
default:
import 'package:dart_bones/dart_bones.dart';
+
import '../module_model.dart';
class RoleModel extends ModuleModel {
"filterType": "pattern",
"name": "role_name",
"label": "Name",
- "toolTip": "Suchmuster des Rollennamens: Joker: '*' (beliebiger Text), z.B. '*min*'"
+ "toolTip":
+ "Suchmuster des Rollennamens: Joker: '*' (beliebiger Text), z.B. '*min*'"
}
]
}
/// Data class for storing parameter to build a page.
class ApplicationData {
final BaseConfiguration configuration;
+ final BaseLogger logger;
/// Signature: AppBar func(String title)
final AppBar Function(String title) appBarBuilder;
final Drawer Function(dynamic context) drawerBuilder;
final Persistence persistence;
+ String currentUser;
+ int currentRoleId;
+
/// Constructor.
/// [configuration] is a map with the widget data (e.g. padding)
/// [appBarBuilder] is a factory of a function returning a outside designed AppBar
/// [drawerBuilder] is a factory of a function returning a Drawer which handles the "Hamburger menu"
- ApplicationData(this.configuration, this.appBarBuilder, this.drawerBuilder, this.persistence);
+ ApplicationData(this.configuration, this.appBarBuilder, this.drawerBuilder,
+ this.persistence, this.logger) {
+ currentUser = 'Gast';
+ currentRoleId = 100;
+ }
}
import 'configuration_controller.dart';
class ConfigurationChangePage extends StatefulWidget {
- final ApplicationData pageData;
+ final ApplicationData applicationData;
final logger = Settings().logger;
- ConfigurationChangePageState lastState;
- ConfigurationChangePage(this.pageData, {Key key}) : super(key: key);
+ //ConfigurationChangePageState lastState;
+
+ ConfigurationChangePage(this.applicationData, {Key key}) : super(key: key);
@override
ConfigurationChangePageState createState() {
- final rc = lastState = ConfigurationChangePageState(pageData);
+ final rc = ConfigurationChangePageState(applicationData);
+ // lastState = rc;
return rc;
}
}
class ConfigurationChangePageState extends State<ConfigurationChangePage> {
- final ApplicationData pageData;
+ final ApplicationData applicationData;
- final GlobalKey<FormState> _formKey = GlobalKey<FormState>(debugLabel: 'configuration');
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'configuration_change');
ConfigurationController controller;
- ConfigurationChangePageState(this.pageData);
+ ConfigurationChangePageState(this.applicationData);
@override
Widget build(BuildContext context) {
- controller = controller ?? ConfigurationController(_formKey, this);
+ controller = controller ??
+ ConfigurationController(
+ _formKey, this, 'change', context, applicationData);
return Scaffold(
- appBar: pageData.appBarBuilder('Rolle ändern'),
- drawer: pageData.drawerBuilder(context),
+ appBar: applicationData.appBarBuilder('Rolle ändern'),
+ drawer: applicationData.drawerBuilder(context),
body: EditForm.editForm(
key: _formKey,
- isCreateForm: false,
- moduleController: controller,
- configuration: pageData.configuration,
+ pageController: controller,
+ configuration: applicationData.configuration,
));
}
}
import 'package:flutter_bones/flutter_bones.dart';
import '../../model/standard/configuration_model.dart';
-import '../../widget/module_controller.dart';
+import '../../widget/page_controller_bones.dart';
-class ConfigurationController extends ModuleController {
- ConfigurationController(GlobalKey<FormState> formKey, State<StatefulWidget> parent)
- : super(formKey, parent, ConfigurationModel(Settings().logger)) {
+class ConfigurationController extends PageControllerBones {
+ /// Controller for a page named [pageName].
+ ConfigurationController(
+ GlobalKey<FormState> formKey,
+ State<StatefulWidget> parent,
+ String pageName,
+ BuildContext context,
+ ApplicationData applicationData)
+ : super(
+ formKey,
+ parent,
+ ConfigurationModel(Settings().logger),
+ pageName,
+ context,
+ applicationData,
+ ) {
moduleModel.parse();
}
}
class ConfigurationCreatePage extends StatefulWidget {
final ApplicationData pageData;
final logger = Settings().logger;
- ConfigurationCreatePageState lastState;
ConfigurationCreatePage(this.pageData, {Key key}) : super(key: key);
@override
ConfigurationCreatePageState createState() {
- final rc = lastState = ConfigurationCreatePageState(pageData);
+ final rc = ConfigurationCreatePageState(pageData);
return rc;
}
}
class ConfigurationCreatePageState extends State<ConfigurationCreatePage> {
- final ApplicationData pageData;
+ final ApplicationData applicationData;
- final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'configuration_create');
ConfigurationController controller;
- ConfigurationCreatePageState(this.pageData);
+ ConfigurationCreatePageState(this.applicationData);
@override
Widget build(BuildContext context) {
- controller = controller ?? ConfigurationController(_formKey, this);
+ controller = controller ??
+ ConfigurationController(
+ _formKey, this, 'create', context, applicationData);
return Scaffold(
- appBar: pageData.appBarBuilder('Neue Rolle'),
- drawer: pageData.drawerBuilder(context),
+ appBar: applicationData.appBarBuilder('Neue Rolle'),
+ drawer: applicationData.drawerBuilder(context),
body: EditForm.editForm(
key: _formKey,
- isCreateForm: true,
- moduleController: controller,
- configuration: pageData.configuration,
+ pageController: controller,
+ configuration: applicationData.configuration,
));
}
}
import 'package:flutter/material.dart';
-import '../../helper/settings.dart';
-import '../../model/model_types.dart';
-import '../../widget/filter_fields.dart';
+import '../../widget/filter_set.dart';
import '../../widget/list_form.dart';
-import '../../widget/raised_button_bone.dart';
import '../application_data.dart';
+import 'configuration_controller.dart';
class ConfigurationListPage extends StatefulWidget {
final ApplicationData pageData;
}
class ConfigurationListPageState extends State<ConfigurationListPage> {
- ConfigurationListPageState(this.pageData);
-
- final ApplicationData pageData;
-
- final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
- static Configuration currentConfiguration = Configuration();
-
- Iterable<dynamic> getRows(FilterSet filters) {
- final rows = <Map<String, dynamic>>[
- {
- 'configuration_id': '1',
- 'configuration_name': 'Administrator',
- 'configuration_priority': '10',
- },
- {
- 'configuration_id': '2',
- 'configuration_name': 'Verwalter',
- 'configuration_priority': '20',
- },
- {
- 'configuration_id': '3',
- 'configuration_name': 'Benutzer',
- 'configuration_priority': '30',
- },
- {
- 'configuration_id': '4',
- 'configuration_name': 'Gast',
- 'configuration_priority': '40',
- },
- ];
- final rc = rows.where((row) => filters.isValid(row)).toList();
- return rc;
- }
+ final ApplicationData applicationData;
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'configuration_list');
+ Iterable<dynamic> rows;
+ ConfigurationController controller;
FilterSet filters;
+ ConfigurationListPageState(this.applicationData);
+
@override
Widget build(BuildContext context) {
- final logger = Settings().logger;
- if (filters == null) {
- filters = FilterSet.ready(
- _formKey,
- this,
- [
- FilterItem(
- name: 'configuration_name',
- filterType: FilterType.pattern,
- label: 'Name'),
- ],
- logger);
- }
+ controller ??= ConfigurationController(
+ _formKey, this, 'list', context, applicationData);
+ filters ??= controller.filterSet(page: 'list');
+ getRows();
return Scaffold(
- appBar: pageData.appBarBuilder('Rollen'),
- drawer: pageData.drawerBuilder(context),
+ appBar: applicationData.appBarBuilder('Rollen'),
+ drawer: applicationData.drawerBuilder(context),
body: ListForm.listForm(
key: _formKey,
- configuration: pageData.configuration,
+ configuration: applicationData.configuration,
titles: ListForm.stringsToTitles(';Id;Name;Priorität'),
- columnNames: 'configuration_id configuration_name configuration_priority'.split(' '),
- rows: getRows(filters),
+ columnNames:
+ 'configuration_id configuration_name configuration_priority'
+ .split(' '),
+ rows: rows ?? [],
showEditIcon: true,
buttons: <Widget>[
- RaisedButtonBone(
- 'search',
- filters,
- child: Text('Suchen'),
- ),
+ ButtonBar(alignment: MainAxisAlignment.center, children: [
+ RaisedButton(
+ child: Text('Suchen'),
+ onPressed: () {
+ rows = null;
+ if (_formKey.currentState.validate()) {
+ _formKey.currentState.save();
+ getRows();
+ }
+ },
+ ),
+ RaisedButton(
+ child: Text('Neue Rolle'),
+ onPressed: () {
+ Navigator.pushNamed(context, '/configuration/create');
+ },
+ ),
+ ]),
],
filters: filters,
),
);
}
-}
-class Configuration {
- int id;
- String priority;
- String name;
+ void getRows() {
+ final persistence = applicationData.persistence;
+ final namePattern = filters.valueOf('configuration_name') ?? '';
+ persistence.list(module: 'configuration', params: {
+ ':configuration_name': namePattern.replaceAll('*', '%') + '%'
+ }).then((list) {
+ if (rows == null) {
+ rows = list;
+ setState(() {});
+ }
+ }, onError: (error) {
+ applicationData.logger
+ .error('cannot retrieve configuration list: $error');
+ });
+ }
}
import 'role_controller.dart';
class RoleChangePage extends StatefulWidget {
- final ApplicationData pageData;
+ final ApplicationData applicationData;
final logger = Settings().logger;
- RoleChangePageState lastState;
- RoleChangePage(this.pageData, {Key key}) : super(key: key);
+ //RoleChangePageState lastState;
+
+ RoleChangePage(this.applicationData, {Key key}) : super(key: key);
@override
RoleChangePageState createState() {
- final rc = lastState = RoleChangePageState(pageData);
+ final rc = RoleChangePageState(applicationData);
+ // lastState = rc;
return rc;
}
}
class RoleChangePageState extends State<RoleChangePage> {
- final ApplicationData pageData;
+ final ApplicationData applicationData;
- final GlobalKey<FormState> _formKey = GlobalKey<FormState>(debugLabel: 'role_change');
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'role_change');
RoleController controller;
- RoleChangePageState(this.pageData);
+ RoleChangePageState(this.applicationData);
@override
Widget build(BuildContext context) {
- controller = controller ?? RoleController(_formKey, this);
+ controller = controller ??
+ RoleController(_formKey, this, 'change', context, applicationData);
return Scaffold(
- appBar: pageData.appBarBuilder('Rolle ändern'),
- drawer: pageData.drawerBuilder(context),
+ appBar: applicationData.appBarBuilder('Rolle ändern'),
+ drawer: applicationData.drawerBuilder(context),
body: EditForm.editForm(
key: _formKey,
- isCreateForm: false,
- moduleController: controller,
- configuration: pageData.configuration,
+ pageController: controller,
+ configuration: applicationData.configuration,
));
}
}
import 'package:flutter/material.dart';
import 'package:flutter_bones/flutter_bones.dart';
-import 'package:flutter_bones/src/widget/filter_fields.dart';
import '../../model/standard/role_model.dart';
-import '../../widget/module_controller.dart';
+import '../../widget/page_controller_bones.dart';
-class RoleController extends ModuleController {
- RoleController(GlobalKey<FormState> formKey, State<StatefulWidget> parent)
- : super(formKey, parent, RoleModel(Settings().logger)) {
+class RoleController extends PageControllerBones {
+ /// Controller for a page named [pageName].
+ RoleController(GlobalKey<FormState> formKey, State<StatefulWidget> parent,
+ String pageName, BuildContext context, ApplicationData applicationData)
+ : super(
+ formKey,
+ parent,
+ RoleModel(Settings().logger),
+ pageName,
+ context,
+ applicationData,
+ ) {
moduleModel.parse();
}
- FilterSet filterSet({@required String page}) {
- final rc = FilterSet(globalKey, parent, moduleModel.logger);
- moduleModel
- .pageByName(page)
- .fields
- .values
- .where((element) => element.filterType != null)
- .forEach((element) {
- rc.add(FilterItem(
- label: element.label,
- filterType: element.filterType,
- toolTip: element.toolTip,
- name: element.name));
- });
- return rc;
- }
}
class RoleCreatePage extends StatefulWidget {
final ApplicationData pageData;
final logger = Settings().logger;
- RoleCreatePageState lastState;
RoleCreatePage(this.pageData, {Key key}) : super(key: key);
@override
RoleCreatePageState createState() {
- final rc = lastState = RoleCreatePageState(pageData);
+ final rc = RoleCreatePageState(pageData);
return rc;
}
}
class RoleCreatePageState extends State<RoleCreatePage> {
- final ApplicationData pageData;
+ final ApplicationData applicationData;
- final GlobalKey<FormState> _formKey = GlobalKey<FormState>(debugLabel: 'role_create');
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'role_create');
RoleController controller;
- RoleCreatePageState(this.pageData);
+ RoleCreatePageState(this.applicationData);
@override
Widget build(BuildContext context) {
- controller = controller ?? RoleController(_formKey, this);
+ if (controller == null) {
+ controller =
+ RoleController(_formKey, this, 'create', context, applicationData);
+ controller.initialize();
+ }
return Scaffold(
- appBar: pageData.appBarBuilder('Neue Rolle'),
- drawer: pageData.drawerBuilder(context),
+ appBar: applicationData.appBarBuilder('Neue Rolle'),
+ drawer: applicationData.drawerBuilder(context),
body: EditForm.editForm(
key: _formKey,
- isCreateForm: true,
- moduleController: controller,
- configuration: pageData.configuration,
+ pageController: controller,
+ configuration: applicationData.configuration,
));
}
}
import 'package:flutter/material.dart';
-import '../../helper/settings.dart';
-import '../../model/model_types.dart';
-import '../../widget/filter_fields.dart';
+import '../../widget/filter_set.dart';
import '../../widget/list_form.dart';
-import '../../widget/raised_button_bone.dart';
import '../application_data.dart';
import 'role_controller.dart';
}
class RoleListPageState extends State<RoleListPage> {
- final ApplicationData pageData;
+ final ApplicationData applicationData;
final GlobalKey<FormState> _formKey =
GlobalKey<FormState>(debugLabel: 'role_list');
Iterable<dynamic> rows;
RoleController controller;
FilterSet filters;
- RoleListPageState(this.pageData);
+
+ RoleListPageState(this.applicationData);
@override
Widget build(BuildContext context) {
- final logger = Settings().logger;
- controller ??= RoleController(_formKey, this);
+ controller ??=
+ RoleController(_formKey, this, 'list', context, applicationData);
filters ??= controller.filterSet(page: 'list');
getRows();
return Scaffold(
- appBar: pageData.appBarBuilder('Rollen'),
- drawer: pageData.drawerBuilder(context),
+ appBar: applicationData.appBarBuilder('Rollen'),
+ drawer: applicationData.drawerBuilder(context),
body: ListForm.listForm(
key: _formKey,
- configuration: pageData.configuration,
+ configuration: applicationData.configuration,
titles: ListForm.stringsToTitles(';Id;Name;Priorität'),
columnNames: 'role_id role_name role_priority'.split(' '),
rows: rows ?? [],
buttons: <Widget>[
ButtonBar(alignment: MainAxisAlignment.center, children: [
RaisedButton(
- child: Text('Suchen'),
- onPressed: () {
- rows = null;
- if (_formKey.currentState.validate()) {
- _formKey.currentState.save();
- getRows();
- }
- },
+ child: Text('Suchen'),
+ onPressed: () {
+ rows = null;
+ if (_formKey.currentState.validate()) {
+ _formKey.currentState.save();
+ getRows();
+ }
+ },
),
RaisedButton(
child: Text('Neue Rolle'),
- onPressed: () {},
+ onPressed: () {
+ Navigator.pushNamed(context, '/role/create');
+ },
),
]),
],
}
void getRows() {
- final persistence = pageData.persistence;
- var rc;
+ final persistence = applicationData.persistence;
final namePattern = filters.valueOf('role_name') ?? '';
- persistence.list(
- module: 'role',
- params: {':role_name': namePattern.replaceAll('*', '%') + '%'}).then((list) {
+ persistence.list(module: 'role', params: {
+ ':role_name': namePattern.replaceAll('*', '%') + '%'
+ }).then((list) {
if (rows == null) {
rows = list;
setState(() {});
}
}, onError: (error) {
- pageData.configuration.logger.error('cannot retrieve role list: $error');
+ applicationData.logger.error('cannot retrieve role list: $error');
});
}
}
import 'user_controller.dart';
class UserChangePage extends StatefulWidget {
- final ApplicationData pageData;
+ final ApplicationData applicationData;
final logger = Settings().logger;
- UserChangePageState lastState;
- UserChangePage(this.pageData, {Key key}) : super(key: key);
+ //UserChangePageState lastState;
+
+ UserChangePage(this.applicationData, {Key key}) : super(key: key);
@override
UserChangePageState createState() {
- final rc = lastState = UserChangePageState(pageData);
+ final rc = UserChangePageState(applicationData);
+ // lastState = rc;
return rc;
}
}
class UserChangePageState extends State<UserChangePage> {
- final ApplicationData pageData;
+ final ApplicationData applicationData;
- final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'user_change');
UserController controller;
- UserChangePageState(this.pageData);
+ UserChangePageState(this.applicationData);
@override
Widget build(BuildContext context) {
- controller = controller ?? UserController(_formKey, this);
+ controller = controller ??
+ UserController(_formKey, this, 'change', context, applicationData);
return Scaffold(
- appBar: pageData.appBarBuilder('Rolle ändern'),
- drawer: pageData.drawerBuilder(context),
+ appBar: applicationData.appBarBuilder('Rolle ändern'),
+ drawer: applicationData.drawerBuilder(context),
body: EditForm.editForm(
key: _formKey,
- isCreateForm: false,
- moduleController: controller,
- configuration: pageData.configuration,
+ pageController: controller,
+ configuration: applicationData.configuration,
));
}
}
import 'package:flutter_bones/flutter_bones.dart';
import '../../model/standard/user_model.dart';
-import '../../widget/module_controller.dart';
+import '../../widget/page_controller_bones.dart';
-class UserController extends ModuleController {
- UserController(GlobalKey<FormState> formKey, State<StatefulWidget> parent)
- : super(formKey, parent, UserModel(Settings().logger)) {
+class UserController extends PageControllerBones {
+ /// Controller for a page named [pageName].
+ UserController(GlobalKey<FormState> formKey, State<StatefulWidget> parent,
+ String pageName, BuildContext context, ApplicationData applicationData)
+ : super(
+ formKey,
+ parent,
+ UserModel(Settings().logger),
+ pageName,
+ context,
+ applicationData,
+ ) {
moduleModel.parse();
}
}
class UserCreatePage extends StatefulWidget {
final ApplicationData pageData;
final logger = Settings().logger;
- UserCreatePageState lastState;
UserCreatePage(this.pageData, {Key key}) : super(key: key);
@override
UserCreatePageState createState() {
- final rc = lastState = UserCreatePageState(pageData);
+ final rc = UserCreatePageState(pageData);
return rc;
}
}
class UserCreatePageState extends State<UserCreatePage> {
- final ApplicationData pageData;
+ final ApplicationData applicationData;
- final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'user_create');
UserController controller;
- UserCreatePageState(this.pageData);
+ UserCreatePageState(this.applicationData);
@override
Widget build(BuildContext context) {
- controller = controller ?? UserController(_formKey, this);
+ controller = controller ??
+ UserController(_formKey, this, 'create', context, applicationData);
return Scaffold(
- appBar: pageData.appBarBuilder('Neue Rolle'),
- drawer: pageData.drawerBuilder(context),
+ appBar: applicationData.appBarBuilder('Neue Rolle'),
+ drawer: applicationData.drawerBuilder(context),
body: EditForm.editForm(
key: _formKey,
- isCreateForm: true,
- moduleController: controller,
- configuration: pageData.configuration,
+ pageController: controller,
+ configuration: applicationData.configuration,
));
}
}
import 'package:flutter/material.dart';
-import '../../helper/settings.dart';
-import '../../model/model_types.dart';
-import '../../widget/filter_fields.dart';
+import '../../widget/filter_set.dart';
import '../../widget/list_form.dart';
-import '../../widget/raised_button_bone.dart';
import '../application_data.dart';
+import 'user_controller.dart';
class UserListPage extends StatefulWidget {
final ApplicationData pageData;
}
class UserListPageState extends State<UserListPage> {
- UserListPageState(this.pageData);
-
- final ApplicationData pageData;
-
- final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
- static User currentUser = User();
-
- List<Map<String, dynamic>> getRows(FilterSet filters) {
- final rows = <Map<String, dynamic>>[
- {
- 'user_id': '1',
- 'user_name': 'Administrator',
- 'user_priority': '10',
- },
- {
- 'user_id': '2',
- 'user_name': 'Verwalter',
- 'user_priority': '20',
- },
- {
- 'user_id': '3',
- 'user_name': 'Benutzer',
- 'user_priority': '30',
- },
- {
- 'user_id': '4',
- 'user_name': 'Gast',
- 'user_priority': '40',
- },
- ];
- final rc = rows.where((row) => filters.isValid(row)).toList();
- return rc;
- }
+ final ApplicationData applicationData;
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'user_list');
+ Iterable<dynamic> rows;
+ UserController controller;
FilterSet filters;
+ UserListPageState(this.applicationData);
+
@override
Widget build(BuildContext context) {
- final logger = Settings().logger;
- if (filters == null) {
- filters = FilterSet.ready(
- _formKey,
- this,
- [
- FilterItem(
- name: 'user_name',
- filterType: FilterType.pattern,
- label: 'Name'),
- ],
- logger);
- }
+ controller ??=
+ UserController(_formKey, this, 'list', context, applicationData);
+ filters ??= controller.filterSet(page: 'list');
+ getRows();
return Scaffold(
- appBar: pageData.appBarBuilder('Rollen'),
- drawer: pageData.drawerBuilder(context),
+ appBar: applicationData.appBarBuilder('Rollen'),
+ drawer: applicationData.drawerBuilder(context),
body: ListForm.listForm(
key: _formKey,
- configuration: pageData.configuration,
+ configuration: applicationData.configuration,
titles: ListForm.stringsToTitles(';Id;Name;Priorität'),
columnNames: 'user_id user_name user_priority'.split(' '),
- rows: getRows(filters),
+ rows: rows ?? [],
showEditIcon: true,
buttons: <Widget>[
- RaisedButtonBone(
- 'search',
- filters,
- child: Text('Suchen'),
- ),
+ ButtonBar(alignment: MainAxisAlignment.center, children: [
+ RaisedButton(
+ child: Text('Suchen'),
+ onPressed: () {
+ rows = null;
+ if (_formKey.currentState.validate()) {
+ _formKey.currentState.save();
+ getRows();
+ }
+ },
+ ),
+ RaisedButton(
+ child: Text('Neue Rolle'),
+ onPressed: () {
+ Navigator.pushNamed(context, '/user/create');
+ },
+ ),
+ ]),
],
filters: filters,
),
);
}
-}
-class User {
- int id;
- String priority;
- String name;
+ void getRows() {
+ final persistence = applicationData.persistence;
+ final namePattern = filters.valueOf('user_name') ?? '';
+ persistence.list(module: 'user', params: {
+ ':user_name': namePattern.replaceAll('*', '%') + '%'
+ }).then((list) {
+ if (rows == null) {
+ rows = list;
+ setState(() {});
+ }
+ }, onError: (error) {
+ applicationData.logger.error('cannot retrieve user list: $error');
+ });
+ }
}
-import 'package:flutter/material.dart';
import 'package:dart_bones/dart_bones.dart';
+import 'package:flutter/material.dart';
import 'package:flutter_bones/flutter_bones.dart';
class UserPage extends StatefulWidget {
final ApplicationData pageData;
- final GlobalKey<FormState> _formKey = GlobalKey<FormState>(debugLabel: 'user_page');
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'user_page');
static User currentUser = User();
@override
/// Returns a record with primary key [id] of the [module] with the
/// SQL statement [sqlName].
- Future<Map<String, dynamic>> record({@required String module, String sqlName, @required int id});
+ Future<Map<String, dynamic>> record(
+ {@required String module, String sqlName, @required int id});
/// Updates a record of [module] with the [data] using the SQL statement [sqlName].
- Future update({@required String module,
- String sqlName,
- @required Map<String, dynamic> data});
+ Future update(
+ {@required String module,
+ String sqlName,
+ @required Map<String, dynamic> data});
}
import 'dart:convert' as convert;
+
import 'package:dart_bones/dart_bones.dart';
import 'package:flutter_bones/src/persistence/persistence.dart';
import 'package:http/http.dart' as http;
return _instance;
}
- RestPersistence.internal({this.application,
- @required this.version,
- @required this.host,
- @required this.port,
- this.scheme = 'http',
- @required this.logger}) {
+ RestPersistence.internal(
+ {this.application,
+ @required this.version,
+ @required this.host,
+ @required this.port,
+ this.scheme = 'http',
+ @required this.logger}) {
uriPrefix = '$scheme://$host:$port';
}
@override
- Future customQuery({String module,
- String sqlName,
- String sqlType,
- Map<String, dynamic> params}) async {
+ Future customQuery(
+ {String module,
+ String sqlName,
+ String sqlType,
+ Map<String, dynamic> params}) async {
var rc;
assert(['list', 'record', 'update'].contains(sqlType));
final params2 = params == null ? '{}' : convert.jsonEncode(params);
}
@override
- Future<dynamic> list(
- {String module, String sqlName, Map params}) async {
+ Future<dynamic> list({String module, String sqlName, Map params}) async {
sqlName ??= 'list';
Iterable<dynamic> rc;
final body = params == null ? '{}' : convert.jsonEncode(params);
- final answer = await runRequest(module, sqlName, 'list',
- body: body);
+ final answer = await runRequest(module, sqlName, 'list', body: body);
if (answer.isNotEmpty) {
rc = convert.jsonDecode(answer);
}
import 'package:flutter/material.dart';
import 'package:flutter_bones/flutter_bones.dart';
import 'package:flutter_bones/src/private/bsettings.dart';
+
import '../page/configuration/configuration_list_page.dart';
import '../page/role/role_list_page.dart';
import '../page/user/user_list_page.dart';
+
class MenuItem {
final String title;
final dynamic page;
final ApplicationData pageData;
Persistence persistence;
static BSettings lastInstance;
+
/// Returns the singleton of VSetting.
factory BSettings() {
final map = {
port: 58011,
host: 'localhost',
logger: logger);
- final pageData = ApplicationData(BaseConfiguration(map, logger), BAppBar.builder,
- BonesDrawer.builder, persistence);
- final rc =
- BSettings.internal(BaseConfiguration(map, logger), pageData, persistence, logger);
+ final pageData = ApplicationData(BaseConfiguration(map, logger),
+ BAppBar.builder, BonesDrawer.builder, persistence, logger);
+ final rc = BSettings.internal(
+ BaseConfiguration(map, logger), pageData, persistence, logger);
return lastInstance = rc;
}
- BSettings.internal(this.configuration, this.pageData, this.persistence, this.logger);
+
+ BSettings.internal(
+ this.configuration, this.pageData, this.persistence, this.logger);
}
--- /dev/null
+import 'package:flutter/material.dart';
+import 'package:flutter_bones/flutter_bones.dart';
+
+/// Interface for a callback controller for flutter_bones specific widgets.
+/// flutter_bones specific widgets: [CheckboxListTileBone],
+/// [DropDownButtonFormBone], [RaisedButtonBone], [TextFormFieldBone]
+abstract class CallbackControllerBones {
+ List<String> comboboxTexts(
+ String customString, CallbackControllerBones controller);
+
+ List<dynamic> comboboxValues(
+ String customString, CallbackControllerBones controller);
+
+ ApplicationData getApplicationData();
+
+ BuildContext getContext();
+
+ FieldModel getModel(String customString, CallbackControllerBones controller);
+
+ String getName();
+
+ ValueChanged<String> getOnChanged(
+ String customString, CallbackControllerBones controller);
+
+ ValueChanged<bool> getOnChangedCheckbox(
+ String customString, CallbackControllerBones controller);
+
+ ValueChanged<T> getOnChangedCombobox<T>(
+ String customString, CallbackControllerBones controller);
+
+ VoidCallback getOnEditingComplete(
+ String customString, CallbackControllerBones controller);
+
+ ValueChanged<String> getOnFieldSubmitted(
+ String customString, CallbackControllerBones controller);
+
+ ValueChanged<bool> getOnHighlightChanged(
+ String customString, CallbackControllerBones controller);
+
+ VoidCallback getOnLongPressed(
+ String customString, CallbackControllerBones controller);
+
+ VoidCallback getOnPressed(
+ String customString, CallbackControllerBones controller);
+
+ FormFieldSetter<String> getOnSaved(
+ String customString, CallbackControllerBones controller);
+
+ DropdownButtonBuilder getOnSelectedItemBuilder(
+ String customString, CallbackControllerBones controller);
+
+ GestureTapCallback getOnTap(
+ String customString, CallbackControllerBones controller);
+
+ FormFieldValidator getOnValidator(
+ String customString, CallbackControllerBones controller);
+
+ FormFieldValidator<String> getValidator(
+ String customString, CallbackControllerBones controller);
+}
--- /dev/null
+import 'package:flutter/material.dart';
+import 'package:flutter/rendering.dart';
+import 'package:flutter_bones/src/widget/page_controller_bones.dart';
+
+/// Implements a [Checkbox] with "outsourced" callbacks:
+/// [customString] a string mostly used for a name needed in the [callbackController]
+/// [callbackController] handles the callback methods.
+class CheckboxListTileBone extends CheckboxListTile {
+ final String customString;
+ final PageControllerBones callbackController;
+
+ CheckboxListTileBone(this.customString, this.callbackController,
+ {key,
+ bool value,
+ MouseCursor mouseCursor,
+ Color activeColor,
+ Color checkColor,
+ Color tileColor,
+ Widget title,
+ Widget subtitle,
+ bool isThreeLine = false,
+ bool dense,
+ Widget secondary,
+ bool selected = false,
+ ListTileControlAffinity controlAffinity =
+ ListTileControlAffinity.platform,
+ bool autofocus = false,
+ EdgeInsetsGeometry contentPadding,
+ bool tristate = false,
+ ShapeBorder shape})
+ : super(
+ key: key,
+ value: value,
+ activeColor: activeColor,
+ onChanged: callbackController.getOnChangedCheckbox(
+ customString, callbackController),
+ checkColor: checkColor,
+ tileColor: tileColor,
+ title: title,
+ subtitle: subtitle,
+ isThreeLine: isThreeLine,
+ dense: dense,
+ secondary: secondary,
+ selected: selected,
+ controlAffinity: controlAffinity,
+ autofocus: autofocus,
+ contentPadding: contentPadding,
+ tristate: tristate,
+ shape: shape);
+}
import 'package:flutter/material.dart';
+import 'callback_controller_bones.dart';
+
/// Implements a [DropdownButtonFormField] with "outsourced" callbacks:
/// [customString] a string mostly used for a name needed in the [customController]
/// [callbackController] handles the callback methods.
class DropdownButtonFormBone<T> extends DropdownButtonFormField<T> {
final String customString;
- final ComboboxCallbackController callbackController;
+ final CallbackControllerBones callbackController;
DropdownButtonFormBone(
this.customString,
FormFieldValidator<T> validator,
AutovalidateMode autovalidateMode,
}) : super(
- key: key,
- items: items,
- selectedItemBuilder: callbackController.getOnSelectedItemBuilder(
- customString, callbackController),
- value: value,
- hint: hint,
- disabledHint: disabledHint,
- onChanged:
- callbackController.getOnChanged(customString, callbackController),
- onTap: callbackController.getOnTap(customString, callbackController),
- elevation: elevation,
- style: style,
- icon: icon,
- iconDisabledColor: iconDisabledColor,
- iconEnabledColor: iconEnabledColor,
- iconSize: iconSize,
- isDense: isDense,
- isExpanded: isExpanded,
- itemHeight: itemHeight,
+ key: key,
+ items: items,
+ selectedItemBuilder: callbackController.getOnSelectedItemBuilder(
+ customString, callbackController),
+ value: value,
+ hint: hint,
+ disabledHint: disabledHint,
+ onChanged: callbackController.getOnChangedCombobox<T>(
+ customString, callbackController),
+ onTap: callbackController.getOnTap(customString, callbackController),
+ elevation: elevation,
+ style: style,
+ icon: icon,
+ iconDisabledColor: iconDisabledColor,
+ iconEnabledColor: iconEnabledColor,
+ iconSize: iconSize,
+ isDense: isDense,
+ isExpanded: isExpanded,
+ itemHeight: itemHeight,
focusColor: focusColor,
focusNode: focusNode,
autofocus: autofocus,
autovalidateMode: autovalidateMode,
);
}
-
-/// Interface for a [DropdownButtonFormBone] specific callback controller.
-abstract class ComboboxCallbackController<T> {
- ValueChanged<T> getOnChanged(
- String customString, ComboboxCallbackController controller);
-
- FormFieldSetter<T> getOnSaved(
- String customString, ComboboxCallbackController controller);
-
- DropdownButtonBuilder getOnSelectedItemBuilder(
- String customString, ComboboxCallbackController controller);
-
- VoidCallback getOnTap(
- String customString, ComboboxCallbackController controller);
-
- FormFieldValidator<T> getOnValidator(
- String customString, ComboboxCallbackController controller);
-
- String getName();
-
- List<String> texts();
-
- List<dynamic> values();
-}
import 'package:dart_bones/dart_bones.dart';
import 'package:flutter/material.dart';
-import 'module_controller.dart';
+import 'page_controller_bones.dart';
import 'raised_button_bone.dart';
typedef Function OnEditTap(Map<String, dynamic> row, int index);
class EditForm {
/// Returns a widget with a form containing at least some input fields
/// and a save/cancel button.
- /// [titles] is used for the table header.
- /// [columnNames] are the keys to display: @precondition: titles.length == columnNames.length
- /// [rows] is a list of rows normally delivered from a database query:
- /// each row is a map with (key, value) pairs.
- /// If [showEditItems] is true the edit icon is shown in the first column.
+ /// a change page.
+ /// [page] is the name of the page in the model.
static Form editForm({
@required Key key,
- @required bool isCreateForm,
- @required ModuleController moduleController,
+ @required PageControllerBones pageController,
@required BaseConfiguration configuration,
}) {
final padding =
configuration.asFloat('form.card.padding', defaultValue: 16.0);
+ final widgets = pageController.getWidgets();
return Form(
key: key,
child: Card(
padding: EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
child: ListView(
children: <Widget>[
- ...moduleController.getWidgets(isCreateForm),
+ ...widgets,
SizedBox(
height: configuration.asFloat(
'form.gap.field_button.height',
children: <Widget>[
FlatButton(
child: Text('Abbruch'),
- onPressed: moduleController.getOnPressed(
- 'cancel', moduleController),
+ onPressed: pageController.getOnPressed(
+ 'cancel', pageController),
),
RaisedButtonBone(
'store',
- moduleController,
+ pageController,
child: Text('Speichern'),
),
],
+++ /dev/null
-import 'package:dart_bones/dart_bones.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bones/flutter_bones.dart';
-import 'package:flutter_bones/src/widget/list_form.dart';
-
-import 'text_form_field_bone.dart';
-
-typedef FilterPredicate = bool Function(Map<String, dynamic> row);
-
-class FilterItem {
- final String name;
- final String label;
- final FilterType filterType;
- final String toolTip;
- final FilterPredicate filterPredicate;
- var value;
-
- FilterItem({
- this.label,
- this.filterType,
- this.toolTip,
- this.name,
- this.filterPredicate,
- });
-
- bool isValid(Map<String, dynamic> row) {
- bool rc = true;
- if (filterPredicate != null) {
- rc = filterPredicate(row);
- } else {
- final current = row[name].toString();
- final value2 = value ?? '';
- switch (filterType) {
- case FilterType.pattern:
- rc = value2 == ''
- ? true
- : (value2.startsWith('*')
- ? current.contains(value2.replaceAll('*', ''))
- : current.startsWith(value2));
- break;
- case FilterType.dateFrom:
- // TODO: Handle this case.
- break;
- case FilterType.dateTil:
- // TODO: Handle this case.
- break;
- case FilterType.dateTimeFrom:
- // TODO: Handle this case.
- break;
- case FilterType.dateTimeTil:
- // TODO: Handle this case.
- break;
- default:
- rc = true;
- break;
- }
- }
- return rc;
- }
-}
-
-class FilterSet
- implements
- TextFormCallbackController,
- ButtonCallbackController,
- TableCallbackController {
- var filters = <FilterItem>[];
- final BaseLogger logger;
- final GlobalKey globalKey;
-
- State<StatefulWidget> parent;
-
- FilterSet(this.globalKey, this.parent, this.logger);
-
- FilterSet.ready(this.globalKey, this.parent, this.filters, this.logger);
-
- void add(FilterItem item) => filters.add(item);
-
- FilterItem byName(String name) =>
- filters.firstWhere((element) => element.name == name, orElse: () => null);
- @override
- getOnChanged(String customString, TextFormCallbackController controller) {
- return null;
- }
- @override
- getOnEditingComplete(
- String customString, TextFormCallbackController controller) {
- return null;
- }
-
- @override
- getOnEditTap(String customString, TableCallbackController controller,
- Map<String, dynamic> row) {
- return null;
- }
-
- @override
- getOnFieldSubmitted(
- String customString, TextFormCallbackController controller) {
- return null;
- }
-
- @override
- getOnHighlightChanged(
- String customString, ButtonCallbackController controller) {
- return null;
- }
-
- @override
- getOnLongPressed(String customString, ButtonCallbackController controller) {
- return null;
- }
-
- @override
- getOnPressed(String customString, ButtonCallbackController controller) {
- var rc;
- if (customString == 'search') {
- rc = () {
- final key = globalKey as GlobalKey<FormState>;
- if (key.currentState.validate()) {
- key.currentState.save();
- parent.setState(() => null);
- }
- };
- }
- return rc;
- }
-
- @override
- getOnSaved(String customString, TextFormCallbackController controller) {
- return (input) {
- byName(customString).value = input;
- };
- }
-
- @override
- getOnTap(String customString, TextFormCallbackController controller) {
- return null;
- }
-
- @override
- getValidator(String customString, TextFormCallbackController controller) {
- return null;
- }
-
- /// Returns a list of widgets for the filter fields.
- List<Widget> getWidgets() {
- final rc = filters.map((filter) {
- Widget rc = TextFormFieldBone(
- filter.name,
- this,
- decoration: InputDecoration(labelText: filter.label),
- );
- if (filter.toolTip != null) {
- rc = Tooltip(message: filter.toolTip, child: rc);
- }
- return rc;
- }).toList();
- return rc;
- }
-
- /// Tests whether the [row] belongs to the result.
- bool isValid(Map<String, dynamic> row) {
- var rc = true;
- for (var filter in filters) {
- if (!filter.isValid(row)) {
- rc = false;
- break;
- }
- }
- return rc;
- }
-
- dynamic valueOf(String name) => byName(name).value;
-}
--- /dev/null
+import 'package:dart_bones/dart_bones.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bones/flutter_bones.dart';
+import 'package:flutter_bones/src/widget/page_controller_bones.dart';
+
+import 'text_form_field_bone.dart';
+
+typedef FilterPredicate = bool Function(Map<String, dynamic> row);
+
+class FilterItem {
+ final String name;
+ final String label;
+ final FilterType filterType;
+ final String toolTip;
+ final FilterPredicate filterPredicate;
+ var value;
+
+ FilterItem({
+ this.label,
+ this.filterType,
+ this.toolTip,
+ this.name,
+ this.filterPredicate,
+ });
+
+ bool isValid(Map<String, dynamic> row) {
+ bool rc = true;
+ if (filterPredicate != null) {
+ rc = filterPredicate(row);
+ } else {
+ final current = row[name].toString();
+ final value2 = value ?? '';
+ switch (filterType) {
+ case FilterType.pattern:
+ rc = value2 == ''
+ ? true
+ : (value2.startsWith('*')
+ ? current.contains(value2.replaceAll('*', ''))
+ : current.startsWith(value2));
+ break;
+ case FilterType.dateFrom:
+ // TODO: Handle this case.
+ break;
+ case FilterType.dateTil:
+ // TODO: Handle this case.
+ break;
+ case FilterType.dateTimeFrom:
+ // TODO: Handle this case.
+ break;
+ case FilterType.dateTimeTil:
+ // TODO: Handle this case.
+ break;
+ default:
+ rc = true;
+ break;
+ }
+ }
+ return rc;
+ }
+}
+
+class FilterSet {
+ var filters = <FilterItem>[];
+ final BaseLogger logger;
+ final GlobalKey globalKey;
+ final PageControllerBones pageController;
+ State<StatefulWidget> parent;
+
+ FilterSet(this.globalKey, this.parent, this.pageController, this.logger);
+
+ FilterSet.ready(this.globalKey, this.parent, this.filters,
+ this.pageController, this.logger);
+
+ void add(FilterItem item) => filters.add(item);
+
+ FilterItem byName(String name) =>
+ filters.firstWhere((element) => element.name == name, orElse: () => null);
+
+ /// Returns a list of widgets for the filter fields.
+ List<Widget> getWidgets() {
+ final rc = filters.map((filter) {
+ Widget rc = TextFormFieldBone(
+ filter.name,
+ pageController,
+ decoration: InputDecoration(labelText: filter.label),
+ );
+ if (filter.toolTip != null) {
+ rc = Tooltip(message: filter.toolTip, child: rc);
+ }
+ return rc;
+ }).toList();
+ return rc;
+ }
+
+ /// Tests whether the [row] belongs to the result.
+ bool isValid(Map<String, dynamic> row) {
+ var rc = true;
+ for (var filter in filters) {
+ if (!filter.isValid(row)) {
+ rc = false;
+ break;
+ }
+ }
+ return rc;
+ }
+
+ dynamic valueOf(String name) => byName(name).value;
+}
import 'package:dart_bones/dart_bones.dart';
import 'package:flutter/material.dart';
-import 'filter_fields.dart';
+
import '../helper/string_helper.dart';
+import 'filter_set.dart';
typedef Function OnEditTap(Map<String, dynamic> row, int index);
/// [rows] is a list of rows normally delivered from a database query:
/// each row is a map with (key, value) pairs.
/// If [showEditItems] is true the edit icon is shown in the first column.
- static Form listForm({@required Key key,
- @required FilterSet filters,
- @required List<Widget> buttons,
- @required List<Widget> titles,
- @required List<String> columnNames,
- @required Iterable<dynamic> rows,
- bool showEditIcon = false,
- TableCallbackController tableCallbackController,
- @required BaseConfiguration configuration,
- String customString}) {
+ static Form listForm(
+ {@required Key key,
+ @required FilterSet filters,
+ @required List<Widget> buttons,
+ @required List<Widget> titles,
+ @required List<String> columnNames,
+ @required Iterable<dynamic> rows,
+ bool showEditIcon = false,
+ TableCallbackController tableCallbackController,
+ @required BaseConfiguration configuration,
+ String customString}) {
final padding =
- configuration.asFloat('form.card.padding', defaultValue: 16.0);
+ configuration.asFloat('form.card.padding', defaultValue: 16.0);
return Form(
key: key,
child: Card(
+++ /dev/null
-import 'package:flutter/material.dart';
-import 'package:flutter_bones/flutter_bones.dart';
-import 'package:flutter_bones/src/widget/widget_list.dart';
-
-import '../model/model_types.dart';
-import '../model/module_model.dart';
-import '../model/table_model.dart';
-import 'raised_button_bone.dart';
-import 'text_form_field_bone.dart';
-import 'widget_helper.dart';
-
-// This interface allows the generic handling of the edit form by a model driven module.
-class ModuleController
- implements TextFormCallbackController, ButtonCallbackController {
- final ModuleModel moduleModel;
- String primaryColumn;
- WidgetList createWidgets;
- WidgetList changeWidgets;
- final modelsMap = <String, ModelBase>{};
- final dataTypes = <String, DataType>{};
- final Map values = <String, dynamic>{};
- final GlobalKey<FormState> globalKey;
-
- State parent;
-
- ModuleController(this.globalKey, this.parent, this.moduleModel) {
- createWidgets = WidgetList(
- '${moduleModel.fullName()}.createWidgets', moduleModel.logger);
- changeWidgets = WidgetList(
- '${moduleModel.fullName()}.changeWidgets', moduleModel.logger);
- }
-
- ModuleModel getModuleModel() => moduleModel;
-
- @override
- getOnChanged(String customString, TextFormCallbackController controller) {
- return null;
- }
-
- @override
- getOnEditingComplete(
- String customString, TextFormCallbackController controller) {
- return null;
- }
-
- @override
- getOnFieldSubmitted(
- String customString, TextFormCallbackController controller) {
- return null;
- }
-
- @override
- getOnHighlightChanged(
- String customString, ButtonCallbackController controller) {
- return null;
- }
-
- @override
- getOnLongPressed(String customString, ButtonCallbackController controller) {
- return null;
- }
-
- @override
- getOnPressed(String customString, ButtonCallbackController controller) {
- var rc;
- if (customString == 'store') {
- rc = () {
- if (globalKey.currentState.validate()) {
- globalKey.currentState.save();
- moduleModel.logger.log('missing storage in onPressed');
- }
- };
- }
- return rc;
- }
-
- @override
- getOnSaved(String customString, TextFormCallbackController controller) {
- final rc = (input) {
- values[customString] =
- StringHelper.fromString(input, dataTypes[customString]);
- };
- return rc;
- }
-
- @override
- getOnTap(String customString, TextFormCallbackController controller) {
- return null;
- }
-
- @override
- getValidator(String customString, TextFormCallbackController controller) {
- return null;
- }
-
- /// Returns the widgets with at least the input fields of the form
- ///
- List<Widget> getWidgets(bool isCreateForm) {
- List<Widget> rc;
- if (isCreateForm) {
- if (createWidgets == null || createWidgets.widgets.length == 0) {
- modelToWidgets(moduleModel.mainTable(), this, createWidgets);
- }
- rc = createWidgets.widgets;
- } else {
- if (changeWidgets.widgets.length == 0) {
- modelToWidgets(moduleModel.mainTable(), this, changeWidgets);
- }
- rc = changeWidgets.widgets;
- }
- return rc;
- }
-
- /// Reads the [tableModel] and creates the [widgetList] with all relevant
- /// input fields.
- void modelToWidgets(TableModel tableModel, ModuleController controller,
- WidgetList widgetList) {
- for (var column in tableModel.columns) {
- if (!column.hasOption('hidden')) {
- if (column.hasOption('primary')) {
- primaryColumn = column.name;
- }
- Widget widget;
- modelsMap[column.name] = column;
- dataTypes[column.name] = column.dataType;
- switch (column.dataType) {
- case DataType.bool:
- widget = null;
- break;
- default:
- widget = WidgetHelper.toolTip(
- TextFormFieldBone(
- column.name,
- controller,
- decoration: InputDecoration(labelText: column.label),
- ),
- column.toolTip);
- break;
- }
- if (widget != null) {
- widgetList.addWidget(column.name, widget);
- }
- }
- }
- }
-}
--- /dev/null
+import 'package:flutter/material.dart';
+import 'package:flutter_bones/flutter_bones.dart';
+import 'package:flutter_bones/src/widget/widget_list.dart';
+
+import '../model/module_model.dart';
+import '../page/application_data.dart';
+import 'callback_controller_bones.dart';
+import 'filter_set.dart';
+import 'view.dart';
+
+// This interface allows the generic handling of the edit form by a model driven module.
+class PageControllerBones implements CallbackControllerBones {
+ final ModuleModel moduleModel;
+ String primaryColumn;
+ WidgetList widgetList;
+
+ //WidgetList changeWidgets;
+ final GlobalKey<FormState> globalKey;
+ final String pageName;
+ PageModel page;
+ final ApplicationData applicationData;
+ State parent;
+ final BuildContext context;
+
+ PageControllerBones(this.globalKey, this.parent, this.moduleModel,
+ this.pageName, this.context, this.applicationData) {}
+
+ /// Initializes the controller when the instance is complete constructed,
+ /// e.g. ModuleModel.parse() is called.
+ /// This method must be called early after the constructor.
+ void initialize() {
+ widgetList =
+ WidgetList('${moduleModel.fullName()}.widgets', moduleModel.logger);
+ page = moduleModel.pageByName(pageName);
+ page.fields.forEach((model) {
+ widgetList.addWidget(
+ model.name, View(moduleModel.logger).modelToWidget(model, this));
+ });
+ }
+
+ @override
+ List<String> comboboxTexts(
+ String customString, CallbackControllerBones controller) {
+ return [];
+ }
+
+ @override
+ List comboboxValues(String customString, CallbackControllerBones controller) {
+ return [];
+ }
+
+ FilterSet filterSet({@required String page}) {
+ final rc = FilterSet(globalKey, parent, this, moduleModel.logger);
+ moduleModel
+ .pageByName(page)
+ .fields
+ .where((element) => element.filterType != null)
+ .forEach((element) {
+ rc.add(FilterItem(
+ label: element.label,
+ filterType: element.filterType,
+ toolTip: element.toolTip,
+ name: element.name));
+ });
+ return rc;
+ }
+
+ @override
+ BuildContext getContext() {
+ return context;
+ }
+
+ @override
+ FieldModel getModel(String customString, CallbackControllerBones controller) {
+ final rc = moduleModel.pageByName(pageName)?.getField(customString);
+ return rc;
+ }
+
+ ModuleModel getModuleModel() => moduleModel;
+
+ @override
+ String getName() {
+ return null;
+ }
+
+ @override
+ getOnChanged(String customString, CallbackControllerBones controller) {
+ return null;
+ }
+
+ @override
+ getOnChangedCheckbox(
+ String customString, CallbackControllerBones controller) {
+ return null;
+ }
+
+ @override
+ getOnChangedCombobox<T>(
+ String customString, CallbackControllerBones controller) {
+ return null;
+ }
+
+ @override
+ getOnEditingComplete(
+ String customString, CallbackControllerBones controller) {
+ return null;
+ }
+
+ @override
+ getOnFieldSubmitted(String customString, CallbackControllerBones controller) {
+ return null;
+ }
+
+ @override
+ getOnHighlightChanged(String customString,
+ CallbackControllerBones controller) {
+ return null;
+ }
+
+ @override
+ getOnLongPressed(String customString, CallbackControllerBones controller) {
+ return null;
+ }
+
+ @override
+ getOnPressed(String customString, CallbackControllerBones controller) {
+ var rc;
+ if (customString == 'store') {
+ rc = () {
+ if (globalKey.currentState.validate()) {
+ globalKey.currentState.save();
+ final params = widgetList.buildSqlParams(this);
+ PageModelType pageType =
+ moduleModel
+ .pageByName(pageName)
+ .pageModelType;
+ switch (pageType) {
+ case PageModelType.create:
+ applicationData.persistence
+ .insert(module: moduleModel.name, data: params);
+ break;
+ case PageModelType.change:
+ applicationData.persistence
+ .update(module: moduleModel.name, data: params);
+ break;
+ default:
+ moduleModel.logger
+ .error('unexpected pageType $pageType for $customString');
+ break;
+ }
+ }
+ };
+ } else if (customString == 'cancel') {
+ rc = () => Navigator.pop(controller.getContext());
+ }
+ return rc;
+ }
+
+ @override
+ getOnSaved(String customString, CallbackControllerBones controller) {
+ final rc = (input) {
+ final page = moduleModel.pageByName(pageName);
+ FieldModel model = page.getField(customString);
+ model.value = StringHelper.fromString(input, model.dataType);
+ };
+ return rc;
+ }
+
+ @override
+ getOnSelectedItemBuilder(String customString,
+ CallbackControllerBones controller) {
+ return null;
+ }
+
+ @override
+ getOnTap(String customString, CallbackControllerBones controller) {
+ return null;
+ }
+
+ @override
+ getOnValidator(String customString, CallbackControllerBones controller) {
+ return null;
+ }
+
+ @override
+ TextEditingController getTextEditingController(String customString,
+ CallbackControllerBones controller) {
+ return null;
+ }
+
+ @override
+ getValidator(String customString, CallbackControllerBones controller) {
+ return null;
+ }
+
+ /// Returns the widgets with at least the input fields of the form defined
+ /// in the page named [pageName].
+ ///
+ List<Widget> getWidgets() {
+ List<Widget> rc;
+ final page = moduleModel.pageByName(pageName);
+ rc = View(moduleModel.logger).modelsToWidgets(page.fields, this);
+ return rc ?? [];
+ }
+
+ @override
+ ApplicationData getApplicationData() {
+ return applicationData;
+ }
+}
import 'package:flutter/material.dart';
-/// Interface for a button specific callback controller.
-abstract class ButtonCallbackController {
- ValueChanged<bool> getOnHighlightChanged(
- String customString, ButtonCallbackController controller);
-
- VoidCallback getOnLongPressed(
- String customString, ButtonCallbackController controller);
-
- VoidCallback getOnPressed(
- String customString, ButtonCallbackController controller);
-}
+import 'callback_controller_bones.dart';
/// Implements a raised button with two additional properties:
/// [customString] a string often used for a name needed in a callback method
/// [customObject] an object known by the controller, often used in callback methods like onPressed
class RaisedButtonBone extends RaisedButton {
final String customString;
- final ButtonCallbackController callbackController;
+ final CallbackControllerBones callbackController;
RaisedButtonBone(this.customString, this.callbackController,
{ButtonTextTheme textTheme,
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
+import 'callback_controller_bones.dart';
+
/// Interface for a [TextFormField] specific callback controller.
abstract class TextFormCallbackController {
ValueChanged<String> getOnChanged(
}
/// Implements a [TextFormField] with "outsourced" callbacks:
-/// [customString] a string mostly used for a name needed in the [customController]
+/// [customString] a string mostly used for a name needed in the [callbackController].
/// [callbackController] handles the callback methods.
class TextFormFieldBone extends TextFormField {
final String customString;
- final TextFormCallbackController callbackController;
+ final CallbackControllerBones callbackController;
TextFormFieldBone(this.customString,
this.callbackController, {
bool autofocus = false,
bool readOnly = false,
ToolbarOptions toolbarOptions,
- bool showCursor,
- String obscuringCharacter = '•',
- bool obscureText = false,
- bool autocorrect = true,
- SmartDashesType smartDashesType,
- SmartQuotesType smartQuotesType,
- bool enableSuggestions = true,
- bool maxLengthEnforced = true,
- int maxLines = 1,
- int minLines,
+ bool showCursor,
+ String obscuringCharacter = '•',
+ bool obscureText = false,
+ bool autocorrect = true,
+ SmartDashesType smartDashesType,
+ SmartQuotesType smartQuotesType,
+ bool enableSuggestions = true,
+ bool maxLengthEnforced = true,
+ int maxLines = 1,
+ int minLines,
bool expands = false,
int maxLength,
List<TextInputFormatter> inputFormatters,
import 'package:dart_bones/dart_bones.dart';
import 'package:flutter/material.dart';
-import 'package:flutter_bones/src/controller/button_controller.dart';
+import 'package:flutter_bones/flutter_bones.dart';
+import 'package:flutter_bones/src/widget/callback_controller_bones.dart';
+import 'package:flutter_bones/src/widget/checkbox_list_tile_bone.dart';
-import '../controller/combobox_controller.dart';
import '../helper/settings.dart';
+import '../model/db_reference_model.dart';
import '../model/empty_line_model.dart';
import '../model/field_model.dart';
import '../model/section_model.dart';
-import '../model/text_field_model.dart';
import '../model/text_model.dart';
import '../model/widget_model.dart';
import 'dropdown_button_form_bone.dart';
View.internal(this.logger);
/// Creates a button from the [controller].
- Widget button(ButtonController controller) {
+ Widget button(ButtonModel model, CallbackControllerBones controller) {
final rc = RaisedButtonBone(
- controller.getName(),
+ model.name,
controller,
- child: Text(controller.model.text),
+ child: Text(model.text),
);
return rc;
}
/// Creates a list of buttons from a list of [controllers].
- List<Widget> buttonList(List<ButtonController> controllers) {
+ List<Widget> buttonList(
+ List<ButtonModel> buttonModels, CallbackControllerBones controller) {
final rc = <Widget>[];
- for (var item in controllers) {
- rc.add(button(item));
+ for (var model in buttonModels) {
+ rc.add(button(model, controller));
}
return rc;
}
/// Creates a combobox via the [controller].
- Widget combobox<T>(ComboboxController controller, onTap) {
- final texts = controller.texts();
- final values = controller.values() ?? texts;
+ Widget combobox<T>(FieldModel model, CallbackControllerBones controller) {
+ final texts = controller.comboboxTexts(model.name, controller);
+ final values = controller.comboboxValues(model.name, controller) ?? texts;
final items = <DropdownMenuItem<T>>[];
for (var ix = 0; ix < texts.length; ix++) {
items.add(DropdownMenuItem(
- onTap: onTap, value: values[ix], child: Text(texts[ix])));
+ onTap: controller.getOnTap(model.name, controller),
+ value: values[ix],
+ child: Text(texts[ix])));
}
- final rc =
- DropdownButtonFormBone(controller.getName(), controller, items: items);
+ final rc = DropdownButtonFormBone(model.name, controller, items: items);
return rc;
}
/// Creates a checkbox from the [model].
- Widget checkbox(WidgetModel model) {
- var rc;
+ Widget checkbox(FieldModel model, CallbackControllerBones controller) {
+ final tristate = model.hasOption('undef');
+ final rc = toolTip(
+ CheckboxListTileBone(model.name, controller,
+ value: tristate ? model.value : model.value ?? false,
+ tristate: tristate,
+ title: Text(model.label),
+ selected: model.value ?? false),
+ model);
return rc;
}
- Widget dbReference(WidgetModel child) {
+ Widget dbReference(
+ DbReferenceModel model, CallbackControllerBones controller) {
var rc;
+ if (model.dataType == DataType.bool) {
+ rc = checkbox(model, controller);
+ } else if (model.hasOption('combobox')) {
+ rc = combobox(model, controller);
+ } else {
+ rc = textField(model, controller);
+ }
return rc;
}
/// Returns a form with the properties given by the [model]
/// [formKey] identifies the form. Used for form validation and saving.
- Form simpleForm({SectionModel model, Key formKey}) {
+ Form simpleForm(
+ {SectionModel model, CallbackControllerBones controller, Key formKey}) {
assert(formKey != null);
final padding =
- widgetConfiguration.asFloat('form.card.padding', defaultValue: 16.0);
- final children = widgetsOfSection(model.children);
- final controllers = model.buttons.map((button) => ButtonController(button));
- final buttons = buttonList(controllers);
+ widgetConfiguration.asFloat('form.card.padding', defaultValue: 16.0);
+ final children = modelsToWidgets(model.children, controller);
+ final buttons = buttonList(model.buttons, controller);
final rc = Form(
key: formKey,
child: Card(
}
/// Creates a form text field from the [model].
- Widget textField(TextFieldModel model) {
+ Widget textField(FieldModel model, CallbackControllerBones controller) {
var rc = toolTip(
- TextFormField(
+ TextFormFieldBone(
+ model.name, controller,
//validator: model.validator,
decoration: InputDecoration(labelText: model.label),
- onSaved: (input) => model.value(input),
),
model);
return rc;
return rc;
}
- List<Widget> widgetsOfSection(List<WidgetModel> children) {
+ /// Converts a list of [models] into a list of [Widget]s.
+ List<Widget> modelsToWidgets(List<WidgetModel> models,
+ CallbackControllerBones controller) {
final rc = <Widget>[];
- for (var child in children) {
- switch (child.widgetModelType) {
- case WidgetModelType.textField:
- rc.add(textField(child));
- break;
- case WidgetModelType.button:
- rc.add(button(ButtonController(child)));
- break;
- case WidgetModelType.emptyLine:
- rc.add(emptyLine(child));
- break;
- case WidgetModelType.text:
- rc.add(text(child));
- break;
- case WidgetModelType.checkbox:
- rc.add(checkbox(child));
- break;
- case WidgetModelType.combobox:
- rc.add(text(child));
- break;
- case WidgetModelType.image:
- rc.add(image(child));
- break;
- case WidgetModelType.section:
- rc.add(section(child));
- break;
- case WidgetModelType.dbReference:
- rc.add(dbReference(child));
- break;
- case WidgetModelType.table:
- case WidgetModelType.column:
- case WidgetModelType.allDbFields:
- logger.error('not allowed in section: ${child.fullName()}');
- break;
+ for (var model in models) {
+ final widget = modelToWidget(model, controller);
+ if (widget != null) {
+ rc.add(widget);
}
}
return rc;
}
+
+ /// Converts a [model] into a [Widget].
+ Widget modelToWidget(WidgetModel model, CallbackControllerBones controller) {
+ Widget rc;
+ switch (model.widgetModelType) {
+ case WidgetModelType.textField:
+ rc = textField(model, controller);
+ break;
+ case WidgetModelType.button:
+ rc = button(model, controller);
+ break;
+ case WidgetModelType.emptyLine:
+ rc = emptyLine(model);
+ break;
+ case WidgetModelType.text:
+ rc = text(model);
+ break;
+ case WidgetModelType.checkbox:
+ rc = checkbox(model, controller);
+ break;
+ case WidgetModelType.combobox:
+ rc = text(model);
+ break;
+ case WidgetModelType.image:
+ rc = image(model);
+ break;
+ case WidgetModelType.section:
+ rc = section(model);
+ break;
+ case WidgetModelType.dbReference:
+ rc = dbReference(model, controller);
+ break;
+ case WidgetModelType.allDbFields:
+ break;
+ case WidgetModelType.table:
+ case WidgetModelType.column:
+ logger.error('not allowed in section: ${model.fullName()}');
+ break;
+ }
+ return rc;
+ }
}
import 'package:dart_bones/dart_bones.dart';
import 'package:flutter/material.dart';
+import 'package:flutter_bones/flutter_bones.dart';
+
+import '../helper/string_helper.dart';
+import '../model/model_types.dart';
+import 'dropdown_button_form_bone.dart';
+import 'page_controller_bones.dart';
+import 'text_form_field_bone.dart';
/// Manages a list of named widgets.
class WidgetList {
WidgetList(this.name, this.logger);
+ /// Tests whether the widget list is empty.
+ bool get isEmpty => widgets.isEmpty;
+
/// Adds a [widget] to the [widgets] behind the position of [predecessor].
/// If [predecessor] is null the widget will be the first in [widgets]
void addSuccessorOf(String predecessor, String name, Widget widget) {
}
}
+ /// Builds the SQL parameters of all members of the [widgets].
+ Map<String, String> buildSqlParams(PageControllerBones controller) {
+ final rc = <String, String>{};
+ final page = controller.moduleModel.pageByName(controller.pageName);
+ final isCreatePage = page.pageModelType == PageModelType.create;
+ widgets.forEach((element) {
+ dynamic value;
+ DataType dataType;
+ String name;
+ if (element is TextFormFieldBone) {
+ name = element.customString;
+ final model = page.getField(name, required: true);
+ value = model?.value;
+ dataType = model?.dataType;
+ } else if (element is DropdownButtonFormBone) {
+ name = element.customString;
+ final model = page.getField(name, required: true);
+ value = model?.value;
+ dataType = model?.dataType;
+ }
+ if (name != null && dataType != null) {
+ rc[':$name'] = StringHelper.asDatabaseString(value, dataType);
+ }
+ });
+ final name = controller.moduleModel.mainTable().name +
+ (isCreatePage ? '_createdby' : '_changedby');
+ if (!rc.containsKey(name)) {
+ rc[':$name'] = controller.getApplicationData().currentUser;
+ }
+ return rc;
+ }
+
/// Returns the widget given by [name] or null if not found.
Widget byName(String name) {
final rc = widgetMap.containsKey(name) ? widgetMap[name] : null;
}
return rc;
}
+
+ /// Remove all widgets from the list.
+ void clear() {
+ widgets.clear();
+ widgetMap.clear();
+ }
}
setUpAll(() => BaseSettings.setLocaleByNames(language: 'en'));
group('Settings', () {
test('basic', () {
- BaseSettings.setLocale(Locale('de', 'DE'));
+ BaseSettings.setLocale(SettingLocale(languageCode: 'de', countryCode: 'DE'));
expect(BaseSettings.language, 'de');
expect(BaseSettings.translate('abc', map), equals('abc'));
expect(BaseSettings.translate('help', map), equals('Hilfe'));
sortable: false, withSeconds: false),
equals('4.3.2020 09:33'));
});
+ test('asDatabaseString', () {
+ expect(StringHelper.asDatabaseString('abc', DataType.string), equals('abc'));
+ expect(StringHelper.asDatabaseString(345, DataType.int), equals('345'));
+ expect(StringHelper.asDatabaseString(34.5, DataType.float), equals('34.5'));
+ expect(StringHelper.asDatabaseString(true, DataType.bool), equals('T'));
+ expect(StringHelper.asDatabaseString(false, DataType.bool), equals('F'));
+ expect(StringHelper.asDatabaseString(null, DataType.bool), equals('NULL'));
+ expect(StringHelper.asDatabaseString(null, DataType.currency), equals('NULL'));
+ expect(StringHelper.asDatabaseString(DateTime(2020, 3, 4, 9, 33, 44), DataType.dateTime),
+ equals('2020-03-04 09:33:44'));
+ expect(StringHelper.asDatabaseString(DateTime(2020, 3, 4, 9, 33, 44), DataType.date),
+ equals('2020-03-04'));
+ });
});
group("diverse", () {
test('splitArgs', () {
column user_id: DataType.int "Id" options: primary notnull unique
column user_name: DataType.string "User" options: unique
column user_role: DataType.reference "Role" options:
- column user_createdat: DataType.dateTime "Erzeugt" options: hidden null doStore
- column user_createdby: DataType.string "Erzeugt von" options: hidden doStore
- column user_changedat: DataType.dateTime "Geändert" options: hidden null doStore
- column user_changedby: DataType.string "Geändert von" options: hidden doStore
+ column user_createdat: DataType.dateTime "Erzeugt" options: hidden null
+ column user_createdby: DataType.string "Erzeugt von" options: hidden
+ column user_changedat: DataType.dateTime "Geändert" options: hidden null
+ column user_changedby: DataType.string "Geändert von" options: hidden
== table role: options:
column role_id: DataType.int "Id" options: primary notnull unique
column role_name: DataType.string "Role" options: unique
- column role_createdat: DataType.dateTime "Erzeugt" options: hidden null doStore
- column role_createdby: DataType.string "Erzeugt von" options: hidden doStore
- column role_changedat: DataType.dateTime "Geändert" options: hidden null doStore
- column role_changedby: DataType.string "Geändert von" options: hidden doStore
+ column role_createdat: DataType.dateTime "Erzeugt" options: hidden null
+ column role_createdby: DataType.string "Erzeugt von" options: hidden
+ column role_changedat: DataType.dateTime "Geändert" options: hidden null
+ column role_changedby: DataType.string "Geändert von" options: hidden
== page create: PageModelType.create options:
= section simpleForm1: SectionModelType.simpleForm options: [
textField user: options: required unique
expect(module.fullName(), equals('demo1'));
final dump = module.dump(StringBuffer()).toString();
expect(dump, '''= module demo1: options:
+== table user: options:
+ column user_id: DataType.int "Id" options: primary notnull unique
+ column user_name: DataType.string "User" options: unique notnull
+ column user_role: DataType.reference "Role" options:
+ column user_createdat: DataType.dateTime "Erzeugt" options: hidden null
+ column user_createdby: DataType.string "Erzeugt von" options: hidden
+ column user_changedat: DataType.dateTime "Geändert" options: hidden null
+ column user_changedby: DataType.string "Geändert von" options: hidden
== page create: PageModelType.create options:
= section simpleForm1: SectionModelType.simpleForm options: [
textField user: options: required unique
button buttonStore: text: options: null
] # create.simpleForm1
+== page change: PageModelType.change options:
+ = section simpleForm1: SectionModelType.simpleForm options: [
+ allDbFields 12 options:
+ ] # change.simpleForm1
''');
final userField = page.getField('user');
expect(userField, isNotNull);
expect(checkbox.dataType, DataType.bool);
final dump = module.dump(StringBuffer()).toString();
expect(dump, equals('''= module demo1: options:
+== table user: options:
+ column user_id: DataType.int "Id" options: primary notnull unique
+ column user_name: DataType.string "User" options: unique notnull
+ column user_role: DataType.reference "Role" options:
+ column user_createdat: DataType.dateTime "Erzeugt" options: hidden null
+ column user_createdby: DataType.string "Erzeugt von" options: hidden
+ column user_changedat: DataType.dateTime "Geändert" options: hidden null
+ column user_changedby: DataType.string "Geändert von" options: hidden
== page create: PageModelType.create options:
= section simpleForm1: SectionModelType.simpleForm options: [
checkbox hidden: text: options: required
button buttonStore: text: options: null
] # create.simpleForm1
+== page change: PageModelType.change options:
+ = section simpleForm1: SectionModelType.simpleForm options: [
+ allDbFields 102 options:
+ ] # change.simpleForm1
'''));
});
});
expect(combobox.dataType, DataType.int);
final dump = module.dump(StringBuffer()).toString();
expect(dump, equals('''= module demo1: options:
+== table user: options:
+ column user_id: DataType.int "Id" options: primary notnull unique
+ column user_name: DataType.string "User" options: unique notnull
+ column user_role: DataType.reference "Role" options:
+ column user_createdat: DataType.dateTime "Erzeugt" options: hidden null
+ column user_createdby: DataType.string "Erzeugt von" options: hidden
+ column user_changedat: DataType.dateTime "Geändert" options: hidden null
+ column user_changedby: DataType.string "Geändert von" options: hidden
== page create: PageModelType.create options:
= section simpleForm1: SectionModelType.simpleForm options: [
combobox class: texts: bad OK good options: undef
button buttonStore: text: options: null
] # create.simpleForm1
+== page change: PageModelType.change options:
+ = section simpleForm1: SectionModelType.simpleForm options: [
+ allDbFields 117 options:
+ ] # change.simpleForm1
'''));
});
});
+ group('allDbFields', (){
+ test('allDbFields', (){
+ logger.clear();
+ final map = cloneOfMap(userModel);
+ var module = Demo1(map, logger);
+ module.parse();
+ var errors = logger.errors;
+ expect(errors.length, equals(0));
+ final page = module.pageByName('change');
+ expect(page, isNotNull);
+ expect(page.fields.length, equals(3));
+ expect(page.hasField('user_id'), isTrue);
+ expect(page.hasField('user_name'), isTrue);
+ expect(page.hasField('user_role'), isTrue);
+ });
+ });
group('Non field widgets', () {
test('basic', () {
logger.clear();
final userModel = <String, dynamic>{
'module': 'demo1',
+ 'tables': [
+ {
+ 'table': 'user',
+ 'columns': [
+ {
+ 'column': 'user_id',
+ 'dataType': 'int',
+ 'label': 'Id',
+ 'options': 'primary',
+ },
+ {
+ 'column': 'user_name',
+ 'dataType': 'string',
+ 'label': 'User',
+ 'size': 64,
+ 'options': 'unique;notnull',
+ },
+ {
+ 'column': 'user_role',
+ 'dataType': 'reference',
+ 'label': 'Role',
+ 'foreignKey': 'role.role_id',
+ 'widgetType': 'combobox',
+ },
+ ]
+ },
+ ],
'pages': [
{
'page': 'create',
'label': 'Save',
},
]
- }
+ },
]
},
+ {
+ 'page': 'change',
+ 'pageType': 'change',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'widgetType': 'allDbFields',
+ },
+ ],
+ },
+ ],
+ },
],
};
column role_name: DataType.string "Rolle" options: unique notnull
column role_priority: DataType.int "Priorität" options:
column role_active: DataType.bool "Aktiv" options:
- column role_createdat: DataType.dateTime "Erzeugt" options: hidden null doStore
- column role_createdby: DataType.string "Erzeugt von" options: hidden doStore
- column role_changedat: DataType.dateTime "Geändert" options: hidden null doStore
- column role_changedby: DataType.string "Geändert von" options: hidden doStore
+ column role_createdat: DataType.dateTime "Erzeugt" options: hidden null
+ column role_createdby: DataType.string "Erzeugt von" options: hidden
+ column role_changedat: DataType.dateTime "Geändert" options: hidden null
+ column role_changedby: DataType.string "Geändert von" options: hidden
== page create: PageModelType.create options:
= section simpleForm1: SectionModelType.simpleForm options: [
- allDbFields 10 text: options:
+ allDbFields 10 options:
] # create.simpleForm1
== page change: PageModelType.change options:
= section simpleForm1: SectionModelType.simpleForm options: [
- allDbFields 12 text: options:
+ allDbFields 13 options:
] # change.simpleForm1
== page list: PageModelType.list options:
= section filterPanel1: SectionModelType.filterPanel options: [
column user_email: DataType.string "EMail" options: unique
column user_password: DataType.string "User" options: password
column user_role: DataType.reference "Role" options:
- column user_createdat: DataType.dateTime "Erzeugt" options: hidden null doStore
- column user_createdby: DataType.string "Erzeugt von" options: hidden doStore
- column user_changedat: DataType.dateTime "Geändert" options: hidden null doStore
- column user_changedby: DataType.string "Geändert von" options: hidden doStore
+ column user_createdat: DataType.dateTime "Erzeugt" options: hidden null
+ column user_createdby: DataType.string "Erzeugt von" options: hidden
+ column user_changedat: DataType.dateTime "Geändert" options: hidden null
+ column user_changedby: DataType.string "Geändert von" options: hidden
== page create: PageModelType.create options:
= section simpleForm1: SectionModelType.simpleForm options: [
- allDbFields 26 text: options:
+ allDbFields 31 options:
] # create.simpleForm1
== page change: PageModelType.change options:
= section simpleForm1: SectionModelType.simpleForm options: [
- allDbFields 28 text: options:
+ allDbFields 34 options:
] # change.simpleForm1
== page list: PageModelType.list options:
= section filterPanel1: SectionModelType.filterPanel options: [
column configuration_type: DataType.string "Datentyp" options:
column configuration_value: DataType.string "Wert" options:
column configuration_description: DataType.string "Beschreibung" options:
- column configuration_createdat: DataType.dateTime "Erzeugt" options: hidden null doStore
- column configuration_createdby: DataType.string "Erzeugt von" options: hidden doStore
- column configuration_changedat: DataType.dateTime "Geändert" options: hidden null doStore
- column configuration_changedby: DataType.string "Geändert von" options: hidden doStore
+ column configuration_createdat: DataType.dateTime "Erzeugt" options: hidden null
+ column configuration_createdby: DataType.string "Erzeugt von" options: hidden
+ column configuration_changedat: DataType.dateTime "Geändert" options: hidden null
+ column configuration_changedby: DataType.string "Geändert von" options: hidden
== page create: PageModelType.create options:
= section simpleForm1: SectionModelType.simpleForm options: [
- allDbFields '''));
+ allDbFields'''));
/*
expect(dump.contains('''text: options:
] # create.simpleForm1
group('queries', () {
test('list', () async {
final rest = RestPersistence();
- final list = await rest.list(
- module: 'role', sqlName: 'list', params: {':role_name': 'A%'});
+ final list = await rest
+ .list(module: 'role', sqlName: 'list', params: {':role_name': 'A%'});
expect(list, isNotNull);
expect(list.length, equals(1));
expect(list[0].containsKey('role_id'), isTrue);
});
test('list-all', () async {
final rest = RestPersistence();
- final list = await rest.list(
- module: 'role', sqlName: 'list', params: {':role_name': '%'});
+ final list = await rest
+ .list(module: 'role', sqlName: 'list', params: {':role_name': '%'});
expect(list, isNotNull);
expect(list.length, greaterThanOrEqualTo(4));
expect(list[0].containsKey('role_id'), isTrue);
':role_createdby': 'joe'
});
expect(id is int, isTrue);
- final answer2 =
- await rest.update(module: 'role', sqlName: 'update', data: {
+ await rest.update(module: 'role', sqlName: 'update', data: {
':role_id': id,
':role_name': 'dummy2',
':role_priority': 112,
// utility that Flutter provides. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
-
import 'package:dart_bones/dart_bones.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/foundation/diagnostics.dart';
import 'package:flutter/src/widgets/framework.dart' as x;
import 'package:flutter_bones/flutter_bones.dart';
-import 'package:flutter_bones/src/private/bsettings.dart';
import 'package:flutter_bones/src/widget/widget_helper.dart';
import 'package:test/test.dart';
expect(toolTip.child, equals(widget));
});
});
+ /*
group('ModuleController', () {
test('basic', () {
ApplicationData pageData = ApplicationData(
expect(widgets.length, equals(3));
});
});
+ */
}
class MyContext extends BuildContext {