From 52819db4e155fc04d9511039c8f10a4d81007032 Mon Sep 17 00:00:00 2001 From: Hamatoma Date: Sat, 10 Oct 2020 00:30:27 +0200 Subject: [PATCH] daily work: * +filters, +role_model, +all_db_fields_model * +role_list --- Doc.sh | 2 + lib/app.dart | 29 +++-- lib/flutter_bones.dart | 4 +- lib/src/helper/filters.dart | 103 ++++++++++++++++++ lib/src/helper/settings.dart | 2 +- lib/src/model/all_db_fields_model.dart | 39 +++++++ lib/src/model/column_model.dart | 4 +- lib/src/model/module_model.dart | 56 ++++++++++ lib/src/model/section_model.dart | 4 + lib/src/model/standard/role_model.dart | 99 +++++++++++++++++ .../{module => standard}/user_model.dart | 50 ++++++++- lib/src/model/widget_model.dart | 1 + .../{role_page.dart => role_create_page.dart} | 19 ++-- lib/src/page/role_list_page.dart | 95 ++++++++++++++++ lib/src/tool/db_tool.dart | 79 ++++++++++++++ lib/src/widget/list_form.dart | 99 +++++++++++++++++ lib/src/widget/view.dart | 3 +- test/tool/tool_test.dart | 26 +++++ 18 files changed, 692 insertions(+), 22 deletions(-) create mode 100755 Doc.sh create mode 100644 lib/src/helper/filters.dart create mode 100644 lib/src/model/all_db_fields_model.dart create mode 100644 lib/src/model/standard/role_model.dart rename lib/src/model/{module => standard}/user_model.dart (55%) rename lib/src/page/{role_page.dart => role_create_page.dart} (77%) create mode 100644 lib/src/page/role_list_page.dart create mode 100644 lib/src/tool/db_tool.dart create mode 100644 lib/src/widget/list_form.dart create mode 100644 test/tool/tool_test.dart diff --git a/Doc.sh b/Doc.sh new file mode 100755 index 0000000..8424cf4 --- /dev/null +++ b/Doc.sh @@ -0,0 +1,2 @@ +#! /bin/bash +dartdoc --sdk-dir=/opt/dart-sdk diff --git a/lib/app.dart b/lib/app.dart index d947f36..f345958 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,10 +1,22 @@ +import 'package:dart_bones/dart_bones.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bones/flutter_bones.dart'; +import 'package:flutter_bones/src/page/role_list_page.dart'; import 'package:flutter_bones/src/private/bsettings.dart'; class BoneApp extends StatefulWidget { @override - BoneAppState createState() => BoneAppState(); + BoneAppState createState() { + final mapWidgetData = { + 'form.card.padding': '16.0', + 'form.gap.field_button.height': '16.0', + }; + final logger = MemoryLogger(); + Settings( + logger: logger, + widgetConfiguration: BaseConfiguration(mapWidgetData, logger)); + return BoneAppState(); + } } class BoneAppState extends State { @@ -12,12 +24,12 @@ class BoneAppState extends State { @override Widget build(BuildContext context) { return MaterialApp( - title: 'Virtuelle Fragestunde', + title: 'Test Standardseiten', theme: ThemeData( primarySwatch: Colors.blue, visualDensity: VisualDensity.adaptivePlatformDensity, ), - initialRoute: '/login', + initialRoute: '/role/list', onGenerateRoute: _getRoute, ); } @@ -26,17 +38,18 @@ class BoneAppState extends State { Route _getRoute(RouteSettings settings) { MaterialPageRoute route; - if (settings.name == '/login') { + if (settings.name == '/role/list') { route = MaterialPageRoute( settings: settings, - builder: (BuildContext context) => LoginPage(BSettings.instance.pageData), + builder: (BuildContext context) => + RoleListPage(BSettings.instance.pageData), fullscreenDialog: false, ); } else { route = MaterialPageRoute( - settings: settings, - builder: (BuildContext context) => LoginPage(BSettings.instance.pageData), - fullscreenDialog: false, + settings: settings, + builder: (BuildContext context) => LoginPage(BSettings.instance.pageData), + fullscreenDialog: false, ); } return route; diff --git a/lib/flutter_bones.dart b/lib/flutter_bones.dart index 8d645ba..cf34b7d 100644 --- a/lib/flutter_bones.dart +++ b/lib/flutter_bones.dart @@ -15,12 +15,14 @@ export 'src/model/model_types.dart'; export 'src/model/module_model.dart'; export 'src/model/page_model.dart'; export 'src/model/section_model.dart'; +export 'src/model/standard/role_model.dart'; +export 'src/model/standard/user_model.dart'; export 'src/model/text_field_model.dart'; export 'src/model/text_model.dart'; export 'src/model/widget_model.dart'; export 'src/page/login_page.dart'; export 'src/page/page_data.dart'; -export 'src/page/role_page.dart'; +export 'src/page/role_create_page.dart'; export 'src/page/user_page.dart'; export 'src/widget/raised_button_bone.dart'; export 'src/widget/simple_form.dart'; diff --git a/lib/src/helper/filters.dart b/lib/src/helper/filters.dart new file mode 100644 index 0000000..c31d21a --- /dev/null +++ b/lib/src/helper/filters.dart @@ -0,0 +1,103 @@ +import 'package:dart_bones/dart_bones.dart'; +import 'package:flutter/material.dart'; + +typedef FilterPredicate = bool Function(Map 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 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.startsWidth('*') + ? current.contains(value2.substring(1)) + : 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 Filters { + var filters = []; + final BaseLogger logger; + + Filters(this.logger); + + Filters.ready(this.filters, this.logger); + + void add(FilterItem item) => filters.add(item); + + FilterItem byName(String name) => + filters.firstWhere((element) => element.name == name); + + /// Returns a list of widgets for the filter fields. + List getWidgets() { + final rc = filters.map((filter) { + Widget rc = TextFormField( + 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 row) { + var rc = true; + for (var filter in filters) { + if (!filter.isValid(row)) { + rc = false; + break; + } + } + return rc; + } +} + +enum FilterType { + pattern, + dateFrom, + dateTil, + dateTimeFrom, + dateTimeTil, +} diff --git a/lib/src/helper/settings.dart b/lib/src/helper/settings.dart index 67bb01b..2836e36 100644 --- a/lib/src/helper/settings.dart +++ b/lib/src/helper/settings.dart @@ -14,7 +14,7 @@ class Settings { final BaseLogger logger; - factory Settings(BaseLogger logger, {BaseConfiguration widgetConfiguration}) { + factory Settings({BaseLogger logger, BaseConfiguration widgetConfiguration}) { if (_instance == null) { _instance = Settings.internal( widgetConfiguration == null diff --git a/lib/src/model/all_db_fields_model.dart b/lib/src/model/all_db_fields_model.dart new file mode 100644 index 0000000..72128b3 --- /dev/null +++ b/lib/src/model/all_db_fields_model.dart @@ -0,0 +1,39 @@ +import 'package:dart_bones/dart_bones.dart'; + +import 'page_model.dart'; +import 'section_model.dart'; +import 'widget_model.dart'; + +/// Describes a text widget without user interaction. +class AllDbFieldsModel extends WidgetModel { + static final regExprOptions = RegExp(r'^(unknown)$'); + List options; + String text; + bool isRichText; + final Map map; + + AllDbFieldsModel( + SectionModel section, PageModel page, this.map, BaseLogger logger) + : super(section, page, WidgetModelType.text, logger); + + /// Returns the name including the names of the parent + @override + String fullName() => '${section.name}.allDbFields$id'; + + /// Dumps the internal structure into a [stringBuffer] + StringBuffer dump(StringBuffer stringBuffer) { + stringBuffer + .write(' allDbFields $id text: options: ${options.join(' ')}\n'); + return stringBuffer; + } + + /// Parses the map and stores the data in the instance. + void parse() { + checkSuperfluousAttributes(map, 'options widgetType'.split(' ')); + options = parseOptions('options', map); + checkOptionsByRegExpr(options, regExprOptions); + } + + @override + String widgetName() => 'allDbFields$id'; +} diff --git a/lib/src/model/column_model.dart b/lib/src/model/column_model.dart index f3763a4..92f521f 100644 --- a/lib/src/model/column_model.dart +++ b/lib/src/model/column_model.dart @@ -7,8 +7,8 @@ import 'widget_model.dart'; /// Describes a column of a database table. class ColumnModel extends WidgetModel { - static final regExprOptions = - RegExp(r'^(undef|readonly|disabled|primary|required|unique)$'); + static final regExprOptions = RegExp( + r'^(undef|readonly|disabled|hidden|null|notnull|primary|required|unique)$'); String name; String label; String toolTip; diff --git a/lib/src/model/module_model.dart b/lib/src/model/module_model.dart index 85a40ac..d5fbd23 100644 --- a/lib/src/model/module_model.dart +++ b/lib/src/model/module_model.dart @@ -48,6 +48,62 @@ class ModuleModel extends ModelBase { return stringBuffer; } + /// Exports the SQL statement to create the module tables. + String exportSql() { + StringBuffer buffer = StringBuffer(); + for (var table in tables) { + buffer.write('drop table if exists ${table.name};\n'); + buffer.write('create table ${table.name} (\n'); + for (var column in table.columns) { + String type; + switch (column.dataType) { + case DataType.bool: + type = 'char(1)'; + break; + case DataType.currency: + type = 'int(10)'; + break; + case DataType.date: + type = 'date'; + break; + case DataType.dateTime: + type = 'timestamp'; + break; + case DataType.float: + type = 'double'; + break; + case DataType.int: + type = 'int(10)'; + break; + case DataType.reference: + type = 'int(10)'; + break; + case DataType.string: + if (column.size == null) { + type = 'varchar(255)'; + } else if (column.size <= 255) { + type = 'varchar($column.size})'; + } else if (column.size <= 0xffff) { + type = 'text'; + } else { + type = 'mediumtext'; + } + break; + } + String options = ''; + for (var option in column.options) { + if ('notnull null primary unique'.contains(option)) { + options += ' ' + option; + } + } + buffer.write(' ${column.name} $type$options;\n'); + } + buffer.write(');\n'); + } + final rc = buffer.toString(); + return rc; + } + /// Returns the name including the names of the parent @override String fullName() => name; diff --git a/lib/src/model/section_model.dart b/lib/src/model/section_model.dart index a771ba4..b35f1c5 100644 --- a/lib/src/model/section_model.dart +++ b/lib/src/model/section_model.dart @@ -1,4 +1,5 @@ import 'package:dart_bones/dart_bones.dart'; +import 'package:flutter_bones/src/model/all_db_fields_model.dart'; import 'package:flutter_bones/src/model/db_reference_model.dart'; import 'button_model.dart'; @@ -78,6 +79,9 @@ class SectionModel extends WidgetModel { child['widgetType'].toString(), WidgetModelType.values); WidgetModel widget; switch (widgetType) { + case WidgetModelType.allDbFields: + widget = AllDbFieldsModel(this, page, child, logger); + break; case WidgetModelType.checkbox: widget = CheckboxModel(this, page, child, logger); break; diff --git a/lib/src/model/standard/role_model.dart b/lib/src/model/standard/role_model.dart new file mode 100644 index 0000000..a1ded34 --- /dev/null +++ b/lib/src/model/standard/role_model.dart @@ -0,0 +1,99 @@ +import 'package:dart_bones/dart_bones.dart'; +import 'package:flutter_bones/flutter_bones.dart'; + +class RoleModel extends ModuleModel { + static final model = { + "module": "role", + "tables": [ + { + 'name': 'role', + 'columns': [ + { + 'name': 'role_id', + 'dataType': 'int', + 'label': 'Id', + 'options': 'primary', + }, + { + 'name': 'role_name', + 'dataType': 'string', + 'label': 'Rolle', + 'size': 32, + 'options': 'unique;notnull', + }, + { + 'name': 'role_priority', + 'dataType': 'int', + 'label': 'Priorität', + }, + { + 'name': 'role_created', + 'dataType': 'dateTime', + 'label': 'Erzeugt', + 'options': 'hidden;null', + }, + { + 'name': 'role_changed', + 'dataType': 'dateTime', + 'label': 'Geändert', + 'options': 'hidden;null', + }, + ] + }, + ], + 'pages': [ + { + "name": "create", + "pageType": "create", + "sections": [ + { + "sectionType": "simpleForm", + "children": [ + { + "widgetType": "allDbFields", + } + ] + } + ] + }, + { + "name": "change", + "pageType": "change", + "sections": [ + { + "sectionType": "simpleForm", + "children": [ + { + "widgetType": "allDbFields", + } + ] + } + ] + }, + { + "name": "list", + "pageType": "list", + "sections": [ + { + "sectionType": "filterPanel", + "children": [ + { + "widgetType": "textfield", + "searchMode": "pattern", + } + ] + } + ] + }, + ], + }; + + RoleModel(BaseLogger logger) : super(model, logger); + + /// Returns the name including the names of the parent + @override + String fullName() => name; + + @override + String widgetName() => name; +} diff --git a/lib/src/model/module/user_model.dart b/lib/src/model/standard/user_model.dart similarity index 55% rename from lib/src/model/module/user_model.dart rename to lib/src/model/standard/user_model.dart index 898592c..3411bff 100644 --- a/lib/src/model/module/user_model.dart +++ b/lib/src/model/standard/user_model.dart @@ -4,7 +4,55 @@ import 'package:flutter_bones/flutter_bones.dart'; class UserModel extends ModuleModel { static final model = { "module": "user", - "pages": [ + "tables": [ + { + 'name': 'users', + 'columns': [ + { + 'name': 'user_id', + 'dataType': 'int', + 'label': 'Id', + 'options': 'primary', + }, + { + 'name': 'user_name', + 'dataType': 'string', + 'label': 'User', + 'size': 64, + 'options': 'unique', + }, + { + 'name': 'user_displayname', + 'dataType': 'string', + 'label': 'Anzeigename', + 'size': 32, + 'options': 'unique', + }, + { + 'name': 'user_email', + 'dataType': 'string', + 'label': 'EMail', + 'size': 128, + 'options': 'unique', + }, + { + 'name': 'user_password', + 'dataType': 'string', + 'label': 'User', + 'size': 128, + 'options': 'password', + }, + { + 'name': 'user_role', + 'dataType': 'reference', + 'label': 'Role', + 'foreignKey': 'role.role_id', + 'widgetType': 'combobox', + }, + ] + }, + ], + 'pages': [ { "name": "create", "pageType": "create", diff --git a/lib/src/model/widget_model.dart b/lib/src/model/widget_model.dart index f04d388..269964b 100644 --- a/lib/src/model/widget_model.dart +++ b/lib/src/model/widget_model.dart @@ -26,6 +26,7 @@ abstract class WidgetModel extends ModelBase { } enum WidgetModelType { + allDbFields, button, checkbox, column, diff --git a/lib/src/page/role_page.dart b/lib/src/page/role_create_page.dart similarity index 77% rename from lib/src/page/role_page.dart rename to lib/src/page/role_create_page.dart index d37fea1..cde36c7 100644 --- a/lib/src/page/role_page.dart +++ b/lib/src/page/role_create_page.dart @@ -1,20 +1,23 @@ import 'package:flutter/material.dart'; import 'package:flutter_bones/flutter_bones.dart'; -class RolePage extends StatefulWidget { +class RoleCreatePage extends StatefulWidget { final PageData pageData; - RolePage(this.pageData, { Key key }) : super(key: key); + + RoleCreatePage(this.pageData, {Key key}) : super(key: key); + @override - RolePageState createState() { - // RolePageState.setPageData(pageData); - final rc = RolePageState(pageData); + RoleCreatePageState createState() { + // RoleCreatePageState.setPageData(pageData); + final rc = RoleCreatePageState(pageData); return rc; } } -class RolePageState extends State{ - RolePageState(this.pageData); +class RoleCreatePageState extends State { + RoleCreatePageState(this.pageData); + final PageData pageData; final GlobalKey _formKey = GlobalKey(); @@ -24,7 +27,7 @@ class RolePageState extends State{ Widget build(BuildContext context) { final role = Role(); return Scaffold( - appBar: pageData.appBarBuilder('Rollen'), + appBar: pageData.appBarBuilder('Rollen'), drawer: pageData.drawerBuilder(context), body: SimpleForm.simpleForm( key: _formKey, diff --git a/lib/src/page/role_list_page.dart b/lib/src/page/role_list_page.dart new file mode 100644 index 0000000..bbbb26d --- /dev/null +++ b/lib/src/page/role_list_page.dart @@ -0,0 +1,95 @@ +import 'package:flutter/material.dart'; + +import '../helper/filters.dart'; +import '../helper/settings.dart'; +import '../page/page_data.dart'; +import '../widget/list_form.dart'; + +class RoleListPage extends StatefulWidget { + final PageData pageData; + + RoleListPage(this.pageData, {Key key}) : super(key: key); + + @override + RoleListPageState createState() { + // RoleListPageState.setPageData(pageData); + final rc = RoleListPageState(pageData); + + return rc; + } +} + +class RoleListPageState extends State { + RoleListPageState(this.pageData); + + final PageData pageData; + + final GlobalKey _formKey = GlobalKey(); + static Role currentRole = Role(); + + List> getRows(Filters filters) { + final rows = >[ + { + 'role_id': '1', + 'role_name': 'Administrator', + 'role_priority': '10', + }, + { + 'role_id': '2', + 'role_name': 'Verwalter', + 'role_priority': '20', + }, + { + 'role_id': '3', + 'role_name': 'Benutzer', + 'role_priority': '30', + }, + { + 'role_id': '4', + 'role_name': 'Gast', + 'role_priority': '40', + }, + ]; + final rc = rows.where((row) => filters.isValid(row)).toList(); + return rc; + } + + @override + Widget build(BuildContext context) { + final logger = Settings().logger; + final filters = Filters.ready([ + FilterItem(filterType: FilterType.pattern, label: 'Name'), + ], logger); + return Scaffold( + appBar: pageData.appBarBuilder('Rollen'), + drawer: pageData.drawerBuilder(context), + body: ListForm.listForm( + key: _formKey, + configuration: pageData.configuration, + titles: ListForm.stringsToTitles(';Id;Name;Priorität'), + columnNames: 'role_id role_name role_priority'.split(' '), + rows: getRows(filters), + showEditIcon: true, + buttons: [ + RaisedButton( + onPressed: () => search(context), + child: Text('Suchen'), + ), + ], + filters: filters, + ), + ); + } + + void search(context) async { + if (_formKey.currentState.validate()) { + _formKey.currentState.save(); + } + } +} + +class Role { + int id; + String priority; + String name; +} diff --git a/lib/src/tool/db_tool.dart b/lib/src/tool/db_tool.dart new file mode 100644 index 0000000..984ac4b --- /dev/null +++ b/lib/src/tool/db_tool.dart @@ -0,0 +1,79 @@ +import 'package:dart_bones/dart_bones.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_bones/flutter_bones.dart'; +import 'package:test/test.dart'; + +import '../model/standard/role_model.dart'; +import '../model/standard/user_model.dart'; + +void dummy() { + group('xxx', () { + test('y', () { + Widget text = Text(''); + expect(text, isNotNull); + }); + }); +} + +void main(List argv) async { + final logger = MemoryLogger(LEVEL_FINE); + if (argv.length > 0xffff) { + dummy(); + } + final dbHelper = DbHelper(logger); + if (argv.length == 0) { + logger.error("missing arguments"); + } else { + final mode = argv[0]; + argv.removeAt(0); + switch (mode) { + case 'create-sql': + dbHelper.exportSql(argv); + break; + default: + logger.error('unknown mode: ${argv[0]}'); + break; + } + } + //await tool.main(); +} + +class DbHelper { + final BaseLogger logger; + + DbHelper(this.logger); + + void exportSql(List argv) { + if (argv.length == 0) { + logger.error('missing table'); + } else { + final table = argv[0]; + argv.removeAt(0); + ModuleModel module; + switch (table) { + case 'user': + module = UserModel(logger); + break; + case 'role': + module = RoleModel(logger); + break; + default: + logger.error('unknown table'); + break; + } + final filename = argv.length == 0 ? '$table.sql' : argv[0]; + FileSync.toFile(filename, module.exportSql()); + print('exported: $filename'); + } + } + + void usage(String error) { + print('''usage: dbhelper [] +: + create-sql [] + : 'role', 'user' ... +Examples: +dbhelper create-sql role role.sql +'''); + } +} diff --git a/lib/src/widget/list_form.dart b/lib/src/widget/list_form.dart new file mode 100644 index 0000000..424868f --- /dev/null +++ b/lib/src/widget/list_form.dart @@ -0,0 +1,99 @@ +import 'package:dart_bones/dart_bones.dart'; +import 'package:flutter/material.dart'; + +import '../helper/filters.dart'; + +typedef Function OnEditTap(Map row, int index); + +class ListForm { + /// Converts a string with [titles] into a list of widgets of type Text(). + /// Format of [titles]: first character is the delimiter, e.g. ";Id;Name;" + /// This allows to use different delimiters when the title text + /// contains characters normally used as delimiters. + static List stringsToTitles(String titles) { + final rc = titles + .substring(1) + .split(titles[0]) + .map((String title) => + Text(title, style: TextStyle(fontWeight: FontWeight.bold))) + .toList(); + return rc; + } + + /// Returns a widget with a data table. + /// [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. + static Widget table({ + @required List titles, + @required List columnNames, + @required List> rows, + bool showEditIcon = false, + OnEditTap onEditTap, + }) { + Widget rc = Container( + margin: EdgeInsets.all(2), + child: DataTable( + showCheckboxColumn: true, + showBottomBorder: true, + sortColumnIndex: 1, + columns: titles.map((item) => DataColumn(label: item)).toList(), + rows: rows.map((row) { + final cells = []; + int ix = -1; + for (var key in columnNames) { + ix++; + cells.add(DataCell( + Text(row[key]), + showEditIcon: showEditIcon && ix == 0, + onTap: () => onEditTap == null ? null : onEditTap(row, ix), + )); + } + return DataRow(cells: cells); + }).toList())); + return rc; + } + + /// Returns a widget with a form containing some [filters] and a data table. + /// [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. + static Form listForm( + {@required Key key, + @required Filters filters, + @required List buttons, + @required List titles, + @required List columnNames, + @required List> rows, + bool showEditIcon = false, + OnEditTap onEditTap, + @required BaseConfiguration configuration}) { + final padding = + configuration.asFloat('form.card.padding', defaultValue: 16.0); + return Form( + key: key, + child: Card( + margin: EdgeInsets.symmetric(vertical: padding, horizontal: padding), + child: Padding( + padding: EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0), + child: ListView(children: [ + ...filters.getWidgets(), + SizedBox( + height: configuration.asFloat( + 'form.gap.field_button.height', + defaultValue: 16.0)), + ...buttons, + table( + titles: titles, + columnNames: columnNames, + rows: rows, + showEditIcon: showEditIcon, + onEditTap: onEditTap), + ])), + )); + } +} diff --git a/lib/src/widget/view.dart b/lib/src/widget/view.dart index ec23fb6..b57b2a9 100644 --- a/lib/src/widget/view.dart +++ b/lib/src/widget/view.dart @@ -21,7 +21,7 @@ class View { factory View(BaseLogger logger) { if (_instance == null) { _instance = View.internal(logger); - _instance.settings = Settings(logger); + _instance.settings = Settings(logger: logger); _instance.widgetConfiguration = _instance.settings.widgetConfiguration; } return _instance; @@ -166,6 +166,7 @@ class View { break; case WidgetModelType.table: case WidgetModelType.column: + case WidgetModelType.allDbFields: logger.error('not allowed in section: ${child.fullName()}'); break; } diff --git a/test/tool/tool_test.dart b/test/tool/tool_test.dart new file mode 100644 index 0000000..506f74a --- /dev/null +++ b/test/tool/tool_test.dart @@ -0,0 +1,26 @@ +import 'package:dart_bones/dart_bones.dart'; +import 'package:flutter_bones/flutter_bones.dart'; +import 'package:test/test.dart'; + +void main() { + final logger = MemoryLogger(LEVEL_FINE); + group('sql', () { + test('export-sql', () { + logger.clear(); + final module = RoleModel(logger); + module.parse(); + final content = module.exportSql(); + final errors = logger.errors; + expect(errors.length, equals(0)); + expect(content, equals('''drop table if exists role; +create table role ( + role_id int(10) primary; + role_name varchar(255) unique notnull; + role_priority int(10); + role_created timestamp null; + role_changed timestamp null; +); +''')); + }); + }); +} -- 2.39.5