if [ $(id -u) = 0 ]; then
echo "+++ not working as root"
else
-flutter test --coverage
-rm -Rf coverage/html/*
-genhtml --show-details --output-directory=coverage/html coverage/lcov.info
+ file=test/coverage_helper_test.dart
+ PACKAGE=flutter_bones
+ echo "// Helper file to make coverage work for all dart files\n" > $file
+ echo "// ignore_for_file: unused_import" >> $file
+ find lib -not -name '*.g.dart' -name '*.dart' | grep -v 'generated_plugin_registrant' | cut -c4- \
+ | awk -v package=$PACKAGE '{printf "import '\''package:%s%s'\'';\n", package, $1}' >> $file
+ echo "\nvoid main(){}" >> $file
+ flutter test --coverage
+ rm -Rf coverage/html/*
+ genhtml --show-details --output-directory=coverage/html coverage/lcov.info
fi
#! /bin/bash
-MODULE=$1
-if [ -z "$MODULE" ]; then
- echo "Missing module name"
- echo "example: $0 menu"
-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
+dart run model_tool/lib/main.dart create-module $*
+
sql: "SELECT u.*, r.* FROM user u
LEFT JOIN role r ON u.user_role=r.role_id
WHERE (user_name=:user or user_email=:user);"
+ - name: list
+ type: list
+ options: override
+ sql: "SELECT t0.*,t1.role_name as user_role, role_priority FROM user t0
+ LEFT JOIN role t1 on t1.role_id=t0.user_role
+ WHERE user_name like :user_name AND (:user_role IS NULL OR user_role=:user_role)"
import 'src/page/starter/starter_list_page.dart';
import 'src/page/starter/starter_create_page.dart';
import 'src/private/bsettings.dart';
+import 'src/widget/utilities.dart';
class BoneApp extends StatefulWidget {
@override
BoneAppState createState() {
final logger = MemoryLogger(LEVEL_FINE);
BSettings.create(logger);
+ utilities = Utilities(logger);
final mapWidgetData = <String, dynamic>{
'form.card.padding': '16.0',
'form.gap.field_button.height': '16.0',
export 'src/model/module_model.dart';
export 'src/model/page_model.dart';
export 'src/model/section_model.dart';
-export 'src/model/standard/configuration_model.dart';
-export 'src/model/standard/menu_model.dart';
-export 'src/model/standard/role_model.dart';
-export 'src/model/standard/user_model.dart';
+export 'src/model/module/configuration_model.dart';
+export 'src/model/module/menu_model.dart';
+export 'src/model/module/role_model.dart';
+export 'src/model/module/starter_model.dart';
+export 'src/model/module/user_model.dart';
export 'src/model/text_field_model.dart';
export 'src/model/text_model.dart';
export 'src/model/widget_model.dart';
value = DateFormat('yyyy-MM-dd').format(value);
break;
case DataType.bool:
- value = value ? 'T' : 'F';
+ value = value is String ? value : (value ? 'T' : 'F');
break;
default:
value = value.toString();
-import 'package:dart_bones/dart_bones.dart';
-
class UrlHelper {
static final sep = '/';
static final currentDirSep = '.' + sep;
+ /// Returns the extension of the [path].
+ /// The extension is the part behind the last '.'.
+ /// If the only '.' is at the top, the result is '' otherwise the the last part with '.'.
+ static String extensionOf(String path) {
+ var rc = '';
+ final ix = path.lastIndexOf('.');
+ final ixSlash = path.lastIndexOf(sep);
+ if (ix > 0 && (ixSlash < 0 || ix > ixSlash + 1)) {
+ rc = path.substring(ix);
+ }
+ return rc;
+ }
+
+ /// Returns the extension of the [path].
+ /// The extension is the part behind the last '.'.
+ /// If the only '.' is at the top, the result is '' otherwise the the last part with '.'.
+ static String filenameOf(String path) {
+ var rc = '';
+ final ix = path.lastIndexOf('.');
+ final ixSlash = path.lastIndexOf(sep);
+ if (ixSlash < 0) {
+ if (ix <= 0) {
+ rc = path;
+ } else {
+ rc = path.substring(0, ix);
+ }
+ } else {
+ if (ix <= ixSlash + 1) {
+ rc = path.substring(ixSlash + 1);
+ } else if (ix > ixSlash + 1) {
+ rc = path.substring(ixSlash + 1, ix);
+ }
+ }
+ return rc;
+ }
+
/// Joins parts to a combined path.
/// [first]: first part
/// [second]: second part
import 'package:dart_bones/dart_bones.dart';
import 'module_model.dart';
-import 'standard/role_model.dart';
-import 'standard/user_model.dart';
-import 'standard/menu_model.dart';
-import 'standard/starter_model.dart';
-import 'standard/configuration_model.dart';
+import 'module/role_model.dart';
+import 'module/user_model.dart';
+import 'module/menu_model.dart';
+import 'module/starter_model.dart';
+import 'module/configuration_model.dart';
class ModelHelper {
/// Returns an instance of a module given by [name].
}
/// Returns the names of the modules.
- List<String> moduleNames() =>
- ['configuration', 'menu', 'role', 'starter', 'user'];
+ List<String> moduleNames() => [
+ 'configuration',
+ 'menu',
+ 'role',
+ 'starter',
+ 'user',
+ ];
}
final ModelHelper modelHelper;
ModelTool(this.modelHelper, this.logger);
+ void createModule(List<String> args, List<String> options) {
+ try {
+ String baseDirectory;
+ String value;
+ PageModelType handledPageType;
+ for (var opt in options) {
+ value = StringUtils.stringOption('directory', 'd', opt);
+ if (value != null) {
+ baseDirectory = value;
+ continue;
+ }
+ value = StringUtils.stringOption('page-type', 't', opt);
+ if (value != null) {
+ handledPageType = StringUtils.stringToEnum<PageModelType>(
+ value, PageModelType.values);
+ if (handledPageType == null) {
+ throw FormatException('unknown page type $value in $opt');
+ }
+ continue;
+ }
+ logger.error('unknown option: $opt');
+ }
+ baseDirectory ??= 'lib/src';
+ if (args.isEmpty) {
+ args = modelHelper.moduleNames();
+ }
+ var fnTemplate = 'lib/src/model/module/role_model.dart';
+ var templateLines = readFile(fnTemplate);
+ if (templateLines.isEmpty) {
+ logger.error('missing $fnTemplate. Wrong current directory?');
+ } else if (args.length < 1) {
+ logger.error('too few arguments');
+ throw FormatException('too few arguments');
+ } else {
+ final moduleName = args[0];
+ final pageName = args.length > 1 ? args[1] : null;
+ if (RegExp(r'^\w+$').firstMatch(moduleName) == null) {
+ throw FormatException(
+ 'invalid character(s) in module name: $moduleName');
+ }
+ if (pageName != null && RegExp(r'^\w+$').firstMatch(pageName) == null) {
+ throw FormatException(
+ 'invalid character(s) in page name: $moduleName');
+ }
+ if (pageName != null && handledPageType == null) {
+ throw FormatException('having page name but no page type');
+ }
+ final moduleCapital = StringHelper.capitalize(moduleName);
+ final converter = (String line) => line
+ .replaceAll('Role', moduleCapital)
+ .replaceAll('role', moduleName)
+ .replaceAll('Rollen', '!!!${moduleCapital}s')
+ .replaceAll('Rolle', '!!$moduleCapital');
+ List<String> output = [];
+ String fnOutput;
+ // Create the module model:
+ StringHelper.addRangeToList(templateLines, output,
+ converter: converter);
+ fnOutput = UrlHelper.joinPaths(
+ baseDirectory, 'module/standard', '${moduleName}_model.dart');
+ writeFile(fnOutput, output.join('\n'),
+ mayExist: false, ensureDirectory: true);
+ // Create the controller:
+ fnTemplate = 'lib/src/model/module/role_controller.dart';
+ templateLines = readFile(fnTemplate);
+ StringHelper.addRangeToList(templateLines, output,
+ converter: converter);
+ fnOutput = UrlHelper.joinPaths(
+ baseDirectory, 'module/standard', '${moduleName}_model.dart');
+ writeFile(fnOutput, output.join('\n'),
+ mayExist: false, ensureDirectory: true);
+ // Create the pages:
+ List<String> names;
+ List<PageModelType> types;
+ if (pageName != null) {
+ names = [pageName];
+ types = [handledPageType];
+ } else {
+ names = ['create', 'change', 'delete', 'list'];
+ types = [
+ PageModelType.create,
+ PageModelType.change,
+ PageModelType.delete,
+ PageModelType.list
+ ];
+ }
+ for (var ix = 0; ix < names.length; ix++) {
+ createPage(baseDirectory, moduleName, names[ix], types[ix]);
+ }
+ }
+ } on FormatException catch (exc) {
+ logger.error(exc.toString());
+ }
+ }
+
+ /// Creates a page named [pageName] of [pageType] in the [baseDirectory].
+ void createPage(String baseDirectory, String moduleName, String pageName,
+ PageModelType pageType) {
+ final typeString = StringUtils.enumToString(pageType);
+ final fnTemplate = 'lib/src/page/role/role_${typeString}_page.dart';
+ final templateLines = readFile(fnTemplate);
+ if (templateLines.isEmpty) {
+ logger.error('missing $fnTemplate');
+ } else {
+ final output = <String>[];
+ final pageTypeCapital = StringHelper.capitalize(typeString);
+ final moduleCapital = StringHelper.capitalize(moduleName);
+ final pageNameCapital = StringHelper.capitalize(pageName);
+ final converter = (String line) => line
+ .replaceAll('Role${pageTypeCapital}Page',
+ '$moduleCapital${pageNameCapital}Page')
+ .replaceAll('RoleController', '${moduleCapital}Controller')
+ .replaceAll('role$pageNameCapital', '$moduleName$pageNameCapital')
+ .replaceAll('role$pageTypeCapital', '$moduleName$pageNameCapital')
+ .replaceAll('Role', moduleCapital)
+ .replaceAll('role', moduleName);
+ StringHelper.addRangeToList(templateLines, output, converter: converter);
+ final fnOutput = UrlHelper.joinPaths(
+ baseDirectory, moduleName, '${moduleName}_${pageName}_page.dart');
+ writeFile(fnOutput, output.join('\n'),
+ ensureDirectory: true, mayExist: false);
+ }
+ }
+
/// Ensures that the [directory] exists. If not it will be created.
void ensureDirectory(String directory);
baseDirectory = value;
continue;
}
- value = StringUtils.stringOption('directory', 'd', opt);
+ value = StringUtils.stringOption('page-type', 't', opt);
if (value != null) {
handledPageType = StringUtils.stringToEnum<PageModelType>(
value, PageModelType.values);
if (handledPageType == null) {
- logger.error('unknown page type $value in $opt');
- logger.error('aborting command');
- throw FormatException('invalid option $opt');
- break;
+ throw FormatException('unknown page type $value in $opt');
}
continue;
}
for (var name in args) {
if (name == 'role') {
logger.log('module "role" ignored.');
+ continue;
}
final sourceDir = 'lib/src/page/$name';
final files = pathOfDirectory(sourceDir);
'role_${StringUtils.enumToString(pageType)}_page.dart');
final templateLines = readFile(fnTemplate);
if (templateLines.isEmpty) {
- logger.log('ignoring ${file}: no template found');
+ logger.log('ignoring $file: no template found');
continue;
}
final pageTypeCapital = StringHelper.capitalize(pageTypeLower);
- final classFragment = 'Role$pageTypeCapital';
final converter = (String line) => line
.replaceAll('Role${pageTypeCapital}Page',
'$moduleCapital${pageNameCapital}Page')
.replaceAll('RoleController', '${moduleCapital}Controller')
- .replaceAll(
- 'role$pageNameCapital', '$name$pageNameCapital');
+ .replaceAll('role$pageNameCapital', '$name$pageNameCapital')
+ .replaceAll('role$pageTypeCapital', '$name$pageNameCapital');
modifyPage(
name,
pageType,
String filename,
bool overwriteConstructors,
String pathSafe) {
- final moduleCapital = StringHelper.capitalize(module);
ensureDirectory(UrlHelper.parentOf(filename, trailingSlash: false));
final output = <String>[];
int ix;
case 'modify-module':
modifyModule(args, options);
break;
+ case 'create-module':
+ createModule(args, options);
+ break;
default:
logger.error('unknown mode: $mode');
break;
void usage(String error) {
print('''usage: main <mode> [<args>]
<mode>:
+ create-module <moduleName> [<opts>]
+ Modifies the files of the given modules to renew the generated code.
+ <opt>:
+ -d<dir> or --directory=<dir>:
+ The base directory used for the created files.
+ --page-type=<type>
+ Creates only the file with this type: 'create', 'change', 'list', 'custom'
create-sql [<module1> [<module2>...] [<opt>]
Generates the DDL ("create table...") statements and the yaml files
describing the insert... SQL statements.
<moduleN>: 'role', 'user' ...
<opt>:
-d<dir> or --directory=<dir>:
- the base directory used for the exported files.
+ The base directory used for the exported files.
help
Display this usage messages.
modify-module [<module1> [<module2>...] [<opts>]
Modifies the files of the given modules to renew the generated code.
- <opt>:
- --page-type=<type>
- Modify only files with this type: 'create', 'change', 'list', 'custom'
- --override-constructors
- Parts of the constructors will be taken from the template.
- Can destroy customized code! Needed if there are changed customized areas.
+ <opt>:
+ -d<dir> or --directory=<dir>:
+ The base directory used for the modified files.
+ --page-type=<type>
+ Modify only files with this type: 'create', 'change', 'list', 'custom'
+ --override-constructors
+ Parts of the constructors will be taken from the template.
+ Can destroy customized code! Needed if there are changed customized areas.
Examples:
+main create-module address
+main create-module address compare --page-type=custom
main create-sql role user -d/tmp
main create-sql --directory=/opt/sql-data
main modify-pages role --customize-constructors
}
/// Writes a [content] to a file named [filename].
- void writeFile(String filename, String content);
+ void writeFile(String filename, String content,
+ {bool mayExist, bool ensureDirectory});
}
--- /dev/null
+import 'package:dart_bones/dart_bones.dart';
+
+import '../module_model.dart';
+
+///
+class ConfigurationModel extends ModuleModel {
+ static final yamlMap = <String, dynamic>{
+ //
+ 'module': 'configuration',
+ 'tables': [
+ {
+ // configuration_id | configuration_scope | configuration_property | configuration_order | configuration_type
+ // | configuration_value | configuration_description
+ 'table': 'configuration',
+ 'columns': [
+ {
+ 'column': 'configuration_id',
+ 'dataType': 'int',
+ 'label': 'Id',
+ 'options': 'primary',
+ },
+ {
+ 'column': 'configuration_scope',
+ 'dataType': 'string',
+ 'label': 'Bereich',
+ 'size': 64,
+ 'options': 'notnull',
+ 'validators': r'required regExpr=i/^\w+$',
+ 'validatorsText':
+ 'regExpr=Nur Buchstaben, Ziffern und Unterstrich erlaubt',
+ },
+ {
+ 'column': 'configuration_property',
+ 'dataType': 'string',
+ 'size': 64,
+ 'label': 'Eigenschaft',
+ },
+ {
+ 'column': 'configuration_order',
+ 'dataType': 'int',
+ 'label': 'Reihe',
+ },
+ {
+ 'column': 'configuration_type',
+ 'dataType': 'string',
+ 'size': 16,
+ 'label': 'Datentyp',
+ 'listType': 'explicite',
+ 'texts': ';bool;date;float;int;string',
+ 'validators': 'required',
+ },
+ {
+ 'column': 'configuration_value',
+ 'dataType': 'string',
+ 'size': 255,
+ 'label': 'Wert',
+ },
+ {
+ 'column': 'configuration_description',
+ 'dataType': 'string',
+ 'size': 255,
+ 'label': 'Beschreibung',
+ },
+ ]
+ },
+ ],
+ 'pages': [
+ {
+ 'page': 'create',
+ 'title': 'Konfiguration hinzufügen',
+ 'pageType': 'create',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'allDbFields',
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'page': 'change',
+ 'title': 'Konfiguration ändern',
+ 'pageType': 'change',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'allDbFields',
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'page': 'delete',
+ 'title': 'Konfiguration löschen',
+ 'pageType': 'delete',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'allDbFields',
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'page': 'list',
+ 'title': 'Konfiguration',
+ 'pageType': 'list',
+ 'tableColumns':
+ 'configuration_id configuration_scope configuration_property configuration_order configuration_value configuration_type',
+ 'tableTitles': ';Id;Bereich;Eigenschaft;Reihe;Wert;Typ',
+ 'sections': [
+ {
+ 'sectionType': 'filterPanel',
+ 'children': [
+ {
+ 'name': 'configuration_scope',
+ 'label': 'Bereich',
+ 'modelType': 'textField',
+ 'filterType': 'pattern',
+ //'options': 'undef',
+ },
+ {
+ 'name': 'configuration_property',
+ 'label': 'Eigenschaft',
+ 'modelType': 'textField',
+ 'filterType': 'pattern',
+ },
+ ],
+ 'buttonBar': [
+ {
+ 'modelType': 'button',
+ 'buttonType': 'custom',
+ 'name': 'new',
+ 'label': 'Neue Konfiguration',
+ 'toolTip': 'Erzeugen einer neuen Konfiguration'
+ },
+ ],
+ }
+ ]
+ },
+ ],
+ };
+
+ ConfigurationModel(BaseLogger logger) : super(yamlMap, logger);
+
+ /// Returns the name including the names of the parents.
+ @override
+ String fullName() => name;
+
+ @override
+ String widgetName() => name;
+}
--- /dev/null
+import 'package:dart_bones/dart_bones.dart';
+
+import '../module_model.dart';
+
+class MenuModel extends ModuleModel {
+ static final mapMenu = <String, dynamic>{
+ 'module': 'menu',
+ 'tables': [
+ {
+ 'table': 'menu',
+ 'columns': [
+ {
+ 'column': 'menu_id',
+ 'dataType': 'int',
+ 'label': 'Id',
+ 'options': 'primary',
+ },
+ {
+ 'column': 'menu_role',
+ 'dataType': 'reference',
+ 'label': 'Rolle',
+ 'foreignKey': 'role.role_id role_name',
+ 'listType': 'dbColumn',
+ 'listOption': 'all.role.list;role_name role_id;',
+ },
+ {
+ 'column': 'menu_starter',
+ 'dataType': 'reference',
+ 'label': 'Programmpunkt',
+ 'foreignKey': 'starter.starter_id starter_name',
+ 'listType': 'dbColumn',
+ 'listOption': 'all.starter.list;starter_name starter_id;',
+ },
+ ]
+ },
+ ],
+ 'pages': [
+ {
+ 'page': 'create',
+ 'title': 'Startmenü hinzufügen',
+ 'pageType': 'create',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'allDbFields',
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'page': 'change',
+ 'title': 'Startmenü ändern',
+ 'pageType': 'change',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'allDbFields',
+ },
+ ],
+ 'buttonBar': [
+ {
+ 'modelType': 'button',
+ 'buttonType': 'custom',
+ 'name': 'new',
+ 'label': 'Neues Startmenü',
+ 'toolTip': 'Erzeugen eines neuen Startmenüs'
+ },
+ ],
+ }
+ ]
+ },
+ {
+ 'page': 'delete',
+ 'title': 'Startmenü löschen',
+ 'pageType': 'delete',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'allDbFields',
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'page': 'list',
+ 'title': 'Startmenü',
+ 'pageType': 'list',
+ 'tableColumns': 'menu_id menu_role menu_order menu_name',
+ 'tableTitles': ';Id;Rolle;Reihe;Programmpunkt',
+ 'sections': [
+ {
+ 'sectionType': 'filterPanel',
+ 'children': [
+ {
+ 'modelType': 'dbReference',
+ 'filterType': 'pattern',
+ 'name': 'menu_role',
+ 'column': 'menu_role',
+ 'toolTip':
+ 'Filter bezüglich der Rolle der anzuzeigenden Einträge.'
+ },
+ ],
+ 'buttonBar': [
+ {
+ 'modelType': 'button',
+ 'buttonType': 'custom',
+ 'name': 'new',
+ 'label': 'Neues Startmenü',
+ 'toolTip': 'Erzeugen eines Startmenüs'
+ },
+ ],
+ }
+ ]
+ },
+ ]
+ };
+
+ MenuModel(BaseLogger logger) : super(mapMenu, logger);
+
+ /// Returns the name including the names of the parents.
+ @override
+ String fullName() => name;
+
+ @override
+ String widgetName() => name;
+}
--- /dev/null
+import 'package:dart_bones/dart_bones.dart';
+
+import '../module_model.dart';
+
+class RoleModel extends ModuleModel {
+ RoleModel(BaseLogger logger) : super(yamlMap, logger);
+
+ static final yamlMap = <String, dynamic>{
+ 'module': 'role',
+ 'tables': [
+ {
+ 'table': 'role',
+ 'columns': [
+ {
+ 'column': 'role_id',
+ 'dataType': 'int',
+ 'label': 'Id',
+ 'options': 'primary',
+ },
+ {
+ 'column': 'role_name',
+ 'dataType': 'string',
+ 'label': 'Rolle',
+ 'size': 32,
+ 'options': 'unique notnull',
+ },
+ {
+ 'column': 'role_priority',
+ 'dataType': 'int',
+ 'label': 'Priorität',
+ 'validators': 'required minInt=1 maxInt=99',
+ },
+ {
+ 'column': 'role_active',
+ 'dataType': 'bool',
+ 'label': 'Aktiv',
+ },
+ ]
+ },
+ ],
+ 'pages': [
+ {
+ 'page': 'create',
+ 'title': 'Rolle hinzufügen',
+ 'pageType': 'create',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'allDbFields',
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'page': 'change',
+ 'title': 'Rolle ändern',
+ 'pageType': 'change',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'allDbFields',
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'page': 'delete',
+ 'title': 'Rolle löschen',
+ 'pageType': 'delete',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'allDbFields',
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'page': 'list',
+ 'title': 'Rollen',
+ 'pageType': 'list',
+ 'tableColumns': 'role_id role_name role_priority',
+ 'tableTitles': ';Id;Rolle;Priorität',
+ 'sections': [
+ {
+ 'sectionType': 'filterPanel',
+ 'children': [
+ {
+ 'modelType': 'textField',
+ 'filterType': 'pattern',
+ 'name': 'role_name',
+ 'label': 'Name',
+ 'toolTip':
+ 'Suchmuster des Rollennamens: Joker: "*" (beliebiger Text), z.B. "*min*"'
+ },
+ ],
+ 'buttonBar': [
+ {
+ 'modelType': 'button',
+ 'buttonType': 'custom',
+ 'name': 'new',
+ 'label': 'Neue Rolle',
+ 'toolTip': 'Erzeugen einer neuen Rolle'
+ },
+ ],
+ }
+ ],
+ },
+ ]
+ };
+
+ /// Returns the name including the names of the parents.
+ @override
+ String fullName() => name;
+
+ @override
+ String widgetName() => name;
+}
--- /dev/null
+import 'package:dart_bones/dart_bones.dart';
+
+import '../module_model.dart';
+
+class StarterModel extends ModuleModel {
+ static final mapStarter = <String, dynamic>{
+ 'module': 'starter',
+ 'tables': [
+ {
+ 'table': 'starter',
+ 'columns': [
+ {
+ 'column': 'starter_id',
+ 'dataType': 'int',
+ 'label': 'Id',
+ 'options': 'primary',
+ },
+ {
+ 'column': 'starter_name',
+ 'dataType': 'string',
+ 'label': 'Name',
+ 'size': 64,
+ 'options': 'unique notnull',
+ },
+ {
+ 'column': 'starter_icon',
+ 'dataType': 'reference',
+ 'label': 'Bild',
+ 'foreignKey': 'configuration.configuration_id configuration_value',
+ 'listType': 'configuration',
+ 'listOption':
+ 'std.scope.icons;configuration_value configuration_id;',
+ },
+ ]
+ },
+ ],
+ 'pages': [
+ {
+ 'page': 'create',
+ 'title': 'Programmpunkt hinzufügen',
+ 'pageType': 'create',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'allDbFields',
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'page': 'change',
+ 'title': 'Programmpunkt hinzufügen',
+ 'pageType': 'change',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'allDbFields',
+ },
+ ]
+ }
+ ]
+ },
+ {
+ 'page': 'delete',
+ 'title': 'Programmpunkt löschen',
+ 'pageType': 'delete',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'allDbFields',
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'page': 'list',
+ 'title': 'Programmpunkte',
+ 'pageType': 'list',
+ 'tableColumns': 'starter_id starter_name starter_icon',
+ 'tableTitles': ';Id;Name;Bild',
+ 'sections': [
+ {
+ 'sectionType': 'filterPanel',
+ 'children': [
+ {
+ 'modelType': 'dbReference',
+ 'filterType': 'pattern',
+ 'name': 'starter_name',
+ 'column': 'starter_name',
+ 'toolTip':
+ 'Filter bezüglich des Namens der anzuzeigenden Einträge: Joker "*" (beliebiger String) ist erlaubt.'
+ },
+ ],
+ 'buttonBar': [
+ {
+ 'modelType': 'button',
+ 'buttonType': 'custom',
+ 'name': 'new',
+ 'label': 'Neuer Programmpunkt',
+ 'toolTip': 'Erzeugen eines neuen Programmpunkts'
+ },
+ ],
+ }
+ ]
+ },
+ ]
+ };
+
+ StarterModel(BaseLogger logger) : super(mapStarter, logger);
+
+ /// Returns the name including the names of the parents.
+ @override
+ String fullName() => name;
+
+ @override
+ String widgetName() => name;
+}
--- /dev/null
+import 'package:dart_bones/dart_bones.dart';
+
+import '../module_model.dart';
+
+class UserModel extends ModuleModel {
+ static final mapUser = <String, dynamic>{
+ 'module': 'user',
+ '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_displayname',
+ 'dataType': 'string',
+ 'label': 'Anzeigename',
+ 'size': 32,
+ 'options': 'unique notnull',
+ },
+ {
+ 'column': 'user_email',
+ 'dataType': 'string',
+ 'label': 'EMail',
+ 'size': 128,
+ 'options': 'unique notnull',
+ 'validators': 'email',
+ },
+ {
+ 'column': 'user_password',
+ 'dataType': 'string',
+ 'label': 'Passwort',
+ 'size': 128,
+ 'options': 'password hidden',
+ },
+ {
+ 'column': 'user_role',
+ 'dataType': 'reference',
+ 'label': 'Rolle',
+ 'foreignKey': 'role.role_id role_name',
+ 'listType': 'dbColumn',
+ 'listOption': 'all.role.list;role_name role_id;:role_name=%',
+ 'options': 'undef',
+ 'defaultValue': '4',
+ },
+ ]
+ },
+ ],
+ 'pages': [
+ {
+ 'page': 'create',
+ 'title': 'Benutzer hinzufügen',
+ 'pageType': 'create',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'allDbFields',
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'page': 'change',
+ 'title': 'Benutzer ändern',
+ 'pageType': 'change',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'allDbFields',
+ },
+ ],
+ 'buttonBar': [
+ {
+ 'modelType': 'button',
+ 'name': 'set_password',
+ 'label': 'Passwort ändern',
+ 'buttonType': 'custom',
+ },
+ ]
+ }
+ ]
+ },
+ {
+ 'page': 'password',
+ 'title': 'Passwort ändern',
+ 'pageType': 'change',
+ 'sql': 'update_pw',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'text',
+ 'text': 'Ändern des Passworts von Benutzer ~user~',
+ 'options': 'placeholder h3'
+ },
+ {
+ 'modelType': 'textField',
+ 'name': 'user_password',
+ 'label': 'Passwort',
+ 'options': 'password',
+ 'validators': 'required',
+ },
+ {
+ 'modelType': 'textField',
+ 'name': 'repetition',
+ 'label': 'Wiederholung',
+ 'options': 'password',
+ 'validators': 'required equals=user_password'
+ },
+ ]
+ }
+ ]
+ },
+ {
+ 'page': 'delete',
+ 'title': 'Benutzer löschen',
+ 'pageType': 'delete',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'allDbFields',
+ }
+ ]
+ }
+ ]
+ },
+ {
+ 'page': 'list',
+ 'title': 'Benutzer',
+ 'pageType': 'list',
+ 'tableColumns':
+ 'user_id user_name user_displayname user_email user_role',
+ 'tableTitles': ';Id;Name;Anzeigename;EMail;Rolle',
+ 'sections': [
+ {
+ 'sectionType': 'filterPanel',
+ 'children': [
+ {
+ 'modelType': 'dbReference',
+ 'filterType': 'pattern',
+ 'name': 'user_name',
+ 'column': 'user_name',
+ 'toolTip':
+ 'Filter bezüglich des Namens der anzuzeigenden Einträge: Joker "*" (beliebiger String) ist erlaubt.'
+ },
+ {
+ 'modelType': 'dbReference',
+ 'name': 'user_role',
+ 'filterType': 'equals',
+ 'column': 'user_role',
+ 'toolTip':
+ 'Filter bezüglich der Rolle der anzuzeigenden Einträge. "-" bedeutet keine Einschränkung',
+ }
+ ],
+ 'buttonBar': [
+ {
+ 'modelType': 'button',
+ 'buttonType': 'custom',
+ 'name': 'new',
+ 'label': 'Neuer Benutzer',
+ 'toolTip': 'Erzeugen eines neuen Benutzers'
+ },
+ ],
+ }
+ ]
+ },
+ {
+ 'page': 'login',
+ 'title': 'Anmelden',
+ 'pageType': 'change',
+ 'options': 'noAutoButton',
+ 'sections': [
+ {
+ 'sectionType': 'simpleForm',
+ 'children': [
+ {
+ 'modelType': 'textField',
+ 'name': 'user',
+ 'label': 'Benutzer oder EMail',
+ 'validators': 'required',
+ },
+ {
+ 'modelType': 'textField',
+ 'name': 'password',
+ 'label': 'Password',
+ 'options': 'password',
+ 'validators': 'required',
+ },
+ ],
+ 'buttonBar': [
+ {
+ 'modelType': 'button',
+ 'buttonType': 'custom',
+ 'name': 'login',
+ 'label': 'Anmelden',
+ },
+ ]
+ }
+ ]
+ },
+ ]
+ };
+
+ UserModel(BaseLogger logger) : super(mapUser, logger);
+
+ /// Returns the name including the names of the parents.
+ @override
+ String fullName() => name;
+
+ @override
+ String widgetName() => name;
+}
import 'package:dart_bones/dart_bones.dart';
+import 'package:flutter_bones/src/widget/page_controller_bones.dart';
import '../helper/name_builder.dart';
import 'button_model.dart';
typedef FilterWidget = bool Function(WidgetModel item);
+/// Returns whether the task specified by [task] and [parameter] can be
+/// granted.
+/// The type of [parameter] depends of the task:
+/// Example: in list pages: TaskRight.edit/delete: parameter is the record of
+/// the table row.
+typedef TaskRightCallback = bool Function(TaskRight task, dynamic parameter);
+
/// Represents one screen of the module.
class PageModel extends ModelBase {
static final regExprOptions = RegExp(r'^(noAutoButton)$');
final buttonsDeprecated = <ButtonModel>[];
final widgetsDeprecated = <WidgetModel>[];
final models = <String, WidgetModel>{};
+ TaskRightCallback taskRightCallback;
String sql;
String title;
List<String> tableTitles;
final name = model.name;
if (models.containsKey(name)) {
logger.error('model ${model.fullName()} already defined: ' +
- fieldByName(name).fullName());
+ models[name].fullName());
} else {
models[model.name] = model;
}
}
if (!options.contains('noAutoButton')) {
- final section = sections[0];
+ final section = sections.isEmpty ? null : sections[0];
switch (pageModelType) {
case PageModelType.list:
if (buttonByName('search', required: false) == null) {
final model = ButtonModel.direct(section, this, 'search', 'Suchen',
ButtonModelType.search, [], logger);
addModel(model);
- sections[0].buttonBar.insert(0, model);
+ if (sections.isEmpty) {
+ logger.error('missing section in ${fullName()}');
+ } else {
+ sections[0].buttonBar.insert(0, model);
+ }
}
break;
case PageModelType.create:
case PageModelType.change:
+ case PageModelType.delete:
if (buttonByName('cancel', required: false) == null) {
final model = ButtonModel.direct(section, this, 'cancel', 'Abbruch',
ButtonModelType.cancel, [], logger);
addModel(model);
- sections[0].buttonBar.insert(0, model);
+ if (sections.isEmpty) {
+ logger.error('missing sections in ${fullName()}');
+ } else {
+ sections[0].buttonBar.insert(0, model);
+ }
}
- if (buttonByName('store', required: false) == null) {
- final model = ButtonModel.direct(section, this, 'store',
- 'Speichern', ButtonModelType.store, [], logger);
+ final buttonName =
+ pageModelType == PageModelType.delete ? 'delete' : 'store';
+ final buttonText =
+ pageModelType == PageModelType.delete ? 'Löschen' : 'Speichern';
+
+ if (buttonByName(buttonName, required: false) == null) {
+ final model = ButtonModel.direct(section, this, buttonName,
+ buttonText, ButtonModelType.store, [], logger);
addModel(model);
- sections[0].buttonBar.insert(0, model);
+ if (sections.isEmpty) {
+ logger.error('missing sections in ${fullName()}');
+ } else {
+ sections[0].buttonBar.insert(0, model);
+ }
}
break;
default:
enum PageModelType {
change,
create,
+ custom,
delete,
list,
- overview,
}
+++ /dev/null
-import 'package:dart_bones/dart_bones.dart';
-
-import '../module_model.dart';
-
-///
-class ConfigurationModel extends ModuleModel {
- static final yamlMap = <String, dynamic>{
- //
- 'module': 'configuration',
- 'tables': [
- {
- // configuration_id | configuration_scope | configuration_property | configuration_order | configuration_type
- // | configuration_value | configuration_description
- 'table': 'configuration',
- 'columns': [
- {
- 'column': 'configuration_id',
- 'dataType': 'int',
- 'label': 'Id',
- 'options': 'primary',
- },
- {
- 'column': 'configuration_scope',
- 'dataType': 'string',
- 'label': 'Bereich',
- 'size': 64,
- 'options': 'notnull',
- 'validators': r'required regExpr=i/^\w+$',
- 'validatorsText':
- 'regExpr=Nur Buchstaben, Ziffern und Unterstrich erlaubt',
- },
- {
- 'column': 'configuration_property',
- 'dataType': 'string',
- 'size': 64,
- 'label': 'Eigenschaft',
- },
- {
- 'column': 'configuration_order',
- 'dataType': 'int',
- 'label': 'Reihe',
- },
- {
- 'column': 'configuration_type',
- 'dataType': 'string',
- 'size': 16,
- 'label': 'Datentyp',
- 'listType': 'explicite',
- 'texts': ';bool;date;float;int;string',
- 'validators': 'required',
- },
- {
- 'column': 'configuration_value',
- 'dataType': 'string',
- 'size': 255,
- 'label': 'Wert',
- },
- {
- 'column': 'configuration_description',
- 'dataType': 'string',
- 'size': 255,
- 'label': 'Beschreibung',
- },
- ]
- },
- ],
- 'pages': [
- {
- 'page': 'create',
- 'title': 'Konfiguration hinzufügen',
- 'pageType': 'create',
- 'sections': [
- {
- 'sectionType': 'simpleForm',
- 'children': [
- {
- 'modelType': 'allDbFields',
- }
- ]
- }
- ]
- },
- {
- 'page': 'change',
- 'title': 'Konfiguration ändern',
- 'pageType': 'change',
- 'sections': [
- {
- 'sectionType': 'simpleForm',
- 'children': [
- {
- 'modelType': 'allDbFields',
- }
- ]
- }
- ]
- },
- {
- 'page': 'list',
- 'title': 'Konfiguration',
- 'pageType': 'list',
- 'tableColumns':
- 'configuration_id configuration_scope configuration_property configuration_order configuration_value configuration_type',
- 'tableTitles': ';Id;Bereich;Eigenschaft;Reihe;Wert;Typ',
- 'sections': [
- {
- 'sectionType': 'filterPanel',
- 'children': [
- {
- 'name': 'configuration_scope',
- 'label': 'Bereich',
- 'modelType': 'textField',
- 'filterType': 'pattern',
- //'options': 'undef',
- },
- {
- 'name': 'configuration_property',
- 'label': 'Eigenschaft',
- 'modelType': 'textField',
- 'filterType': 'pattern',
- },
- ],
- 'buttonBar': [
- {
- 'modelType': 'button',
- 'buttonType': 'custom',
- 'name': 'new',
- 'label': 'Neue Konfiguration',
- 'toolTip': 'Erzeugen einer neuen Konfiguration'
- },
- ],
- }
- ]
- },
- ],
- };
-
- ConfigurationModel(BaseLogger logger) : super(yamlMap, logger);
-
- /// Returns the name including the names of the parents.
- @override
- String fullName() => name;
-
- @override
- String widgetName() => name;
-}
+++ /dev/null
-import 'package:dart_bones/dart_bones.dart';
-
-import '../module_model.dart';
-
-class MenuModel extends ModuleModel {
- static final mapMenu = <String, dynamic>{
- 'module': 'menu',
- 'tables': [
- {
- 'table': 'menu',
- 'columns': [
- {
- 'column': 'menu_id',
- 'dataType': 'int',
- 'label': 'Id',
- 'options': 'primary',
- },
- {
- 'column': 'menu_role',
- 'dataType': 'reference',
- 'label': 'Rolle',
- 'foreignKey': 'role.role_id role_name',
- 'listType': 'dbColumn',
- 'listOption': 'all.role.list;role_name role_id;',
- },
- {
- 'column': 'menu_starter',
- 'dataType': 'reference',
- 'label': 'Programmpunkt',
- 'foreignKey': 'starter.starter_id starter_name',
- 'listType': 'dbColumn',
- 'listOption': 'all.starter.list;starter_name starter_id;',
- },
- ]
- },
- ],
- 'pages': [
- {
- 'page': 'create',
- 'title': 'Startmenü hinzufügen',
- 'pageType': 'create',
- 'sections': [
- {
- 'sectionType': 'simpleForm',
- 'children': [
- {
- 'modelType': 'allDbFields',
- }
- ]
- }
- ]
- },
- {
- 'page': 'change',
- 'title': 'Startmenü ändern',
- 'pageType': 'change',
- 'sections': [
- {
- 'sectionType': 'simpleForm',
- 'children': [
- {
- 'modelType': 'allDbFields',
- },
- ],
- 'buttonBar': [
- {
- 'modelType': 'button',
- 'buttonType': 'custom',
- 'name': 'new',
- 'label': 'Neues Startmenü',
- 'toolTip': 'Erzeugen eines neuen Startmenüs'
- },
- ],
- }
- ]
- },
- {
- 'page': 'list',
- 'title': 'Startmenü',
- 'pageType': 'list',
- 'tableColumns': 'menu_id menu_role menu_order menu_name',
- 'tableTitles': ';Id;Rolle;Reihe;Programmpunkt',
- 'sections': [
- {
- 'sectionType': 'filterPanel',
- 'children': [
- {
- 'modelType': 'dbReference',
- 'filterType': 'pattern',
- 'name': 'menu_role',
- 'column': 'menu_role',
- 'toolTip':
- 'Filter bezüglich der Rolle der anzuzeigenden Einträge.'
- },
- ]
- }
- ]
- },
- ]
- };
-
- MenuModel(BaseLogger logger) : super(mapMenu, logger);
-
- /// Returns the name including the names of the parents.
- @override
- String fullName() => name;
-
- @override
- String widgetName() => name;
-}
+++ /dev/null
-import 'package:dart_bones/dart_bones.dart';
-
-import '../module_model.dart';
-
-class RoleModel extends ModuleModel {
- RoleModel(BaseLogger logger) : super(yamlMap, logger);
-
- static final yamlMap = <String, dynamic>{
- 'module': 'role',
- 'tables': [
- {
- 'table': 'role',
- 'columns': [
- {
- 'column': 'role_id',
- 'dataType': 'int',
- 'label': 'Id',
- 'options': 'primary',
- },
- {
- 'column': 'role_name',
- 'dataType': 'string',
- 'label': 'Rolle',
- 'size': 32,
- 'options': 'unique notnull',
- },
- {
- 'column': 'role_priority',
- 'dataType': 'int',
- 'label': 'Priorität',
- 'validators': 'required minInt=1 maxInt=99',
- },
- {
- 'column': 'role_active',
- 'dataType': 'bool',
- 'label': 'Aktiv',
- },
- ]
- },
- ],
- 'pages': [
- {
- 'page': 'create',
- 'title': 'Rolle hinzufügen',
- 'pageType': 'create',
- 'sections': [
- {
- 'sectionType': 'simpleForm',
- 'children': [
- {
- 'modelType': 'allDbFields',
- }
- ]
- }
- ]
- },
- {
- 'page': 'change',
- 'title': 'Rolle ändern',
- 'pageType': 'change',
- 'sections': [
- {
- 'sectionType': 'simpleForm',
- 'children': [
- {
- 'modelType': 'allDbFields',
- }
- ]
- }
- ]
- },
- {
- 'page': 'list',
- 'title': 'Rollen',
- 'pageType': 'list',
- 'tableColumns': 'role_id role_name role_priority',
- 'tableTitles': ';Id;Rolle;Priorität',
- 'sections': [
- {
- 'sectionType': 'filterPanel',
- 'children': [
- {
- 'modelType': 'textField',
- 'filterType': 'pattern',
- 'name': 'role_name',
- 'label': 'Name',
- 'toolTip':
- 'Suchmuster des Rollennamens: Joker: "*" (beliebiger Text), z.B. "*min*"'
- },
- ],
- 'buttonBar': [
- {
- 'modelType': 'button',
- 'buttonType': 'custom',
- 'name': 'new',
- 'label': 'Neue Rolle',
- 'toolTip': 'Erzeugen einer neuen Rolle'
- },
- ],
- }
- ],
- }
- ]
- };
-
- /// Returns the name including the names of the parents.
- @override
- String fullName() => name;
-
- @override
- String widgetName() => name;
-}
+++ /dev/null
-import 'package:dart_bones/dart_bones.dart';
-
-import '../module_model.dart';
-
-class StarterModel extends ModuleModel {
- static final mapStarter = <String, dynamic>{
- 'module': 'starter',
- 'tables': [
- {
- 'table': 'starter',
- 'columns': [
- {
- 'column': 'starter_id',
- 'dataType': 'int',
- 'label': 'Id',
- 'options': 'primary',
- },
- {
- 'column': 'starter_name',
- 'dataType': 'string',
- 'label': 'Name',
- 'size': 64,
- 'options': 'unique notnull',
- },
- {
- 'column': 'starter_icon',
- 'dataType': 'reference',
- 'label': 'Bild',
- 'foreignKey': 'configuration.configuration_id configuration_value',
- 'listType': 'configuration',
- 'listOption':
- 'std.scope.icons;configuration_value configuration_id;',
- },
- ]
- },
- ],
- 'pages': [
- {
- 'page': 'create',
- 'title': 'Programmpunkt hinzufügen',
- 'pageType': 'create',
- 'sections': [
- {
- 'sectionType': 'simpleForm',
- 'children': [
- {
- 'modelType': 'allDbFields',
- }
- ]
- }
- ]
- },
- {
- 'page': 'change',
- 'title': 'Programmpunkt hinzufügen',
- 'pageType': 'change',
- 'sections': [
- {
- 'sectionType': 'simpleForm',
- 'children': [
- {
- 'modelType': 'allDbFields',
- },
- ]
- }
- ]
- },
- {
- 'page': 'list',
- 'title': 'Programmpunkte',
- 'pageType': 'list',
- 'tableColumns': 'starter_id starter_name starter_icon',
- 'tableTitles': ';Id;Name;Bild',
- 'sections': [
- {
- 'sectionType': 'filterPanel',
- 'children': [
- {
- 'modelType': 'dbReference',
- 'filterType': 'pattern',
- 'name': 'starter_name',
- 'column': 'starter_name',
- 'toolTip':
- 'Filter bezüglich des Namens der anzuzeigenden Einträge: Joker "*" (beliebiger String) ist erlaubt.'
- },
- ],
- 'buttonBar': [
- {
- 'modelType': 'button',
- 'buttonType': 'custom',
- 'name': 'new',
- 'label': 'Neuer Programmpunkt',
- 'toolTip': 'Erzeugen eines neuen Programmpunkts'
- },
- ],
- }
- ]
- },
- ]
- };
-
- StarterModel(BaseLogger logger) : super(mapStarter, logger);
-
- /// Returns the name including the names of the parents.
- @override
- String fullName() => name;
-
- @override
- String widgetName() => name;
-}
+++ /dev/null
-import 'package:dart_bones/dart_bones.dart';
-
-import '../module_model.dart';
-
-class UserModel extends ModuleModel {
- static final mapUser = <String, dynamic>{
- 'module': 'user',
- '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_displayname',
- 'dataType': 'string',
- 'label': 'Anzeigename',
- 'size': 32,
- 'options': 'unique notnull',
- },
- {
- 'column': 'user_email',
- 'dataType': 'string',
- 'label': 'EMail',
- 'size': 128,
- 'options': 'unique notnull',
- 'validators': 'email',
- },
- {
- 'column': 'user_password',
- 'dataType': 'string',
- 'label': 'Passwort',
- 'size': 128,
- 'options': 'password hidden',
- },
- {
- 'column': 'user_role',
- 'dataType': 'reference',
- 'label': 'Rolle',
- 'foreignKey': 'role.role_id role_name',
- 'listType': 'dbColumn',
- 'listOption': 'all.role.list;role_name role_id;:role_name=%',
- 'options': 'undef',
- 'defaultValue': '4',
- },
- ]
- },
- ],
- 'pages': [
- {
- 'page': 'create',
- 'title': 'Benutzer hinzufügen',
- 'pageType': 'create',
- 'sections': [
- {
- 'sectionType': 'simpleForm',
- 'children': [
- {
- 'modelType': 'allDbFields',
- }
- ]
- }
- ]
- },
- {
- 'page': 'change',
- 'title': 'Benutzer ändern',
- 'pageType': 'change',
- 'sections': [
- {
- 'sectionType': 'simpleForm',
- 'children': [
- {
- 'modelType': 'allDbFields',
- },
- {
- 'modelType': 'button',
- 'name': 'set_password',
- 'label': 'Passwort ändern',
- 'buttonType': 'custom',
- },
- ]
- }
- ]
- },
- {
- 'page': 'password',
- 'title': 'Passwort ändern',
- 'pageType': 'change',
- 'sql': 'update_pw',
- 'sections': [
- {
- 'sectionType': 'simpleForm',
- 'children': [
- {
- 'modelType': 'text',
- 'text': 'Ändern des Passworts von Benutzer ~user~',
- 'options': 'placeholder h3'
- },
- {
- 'modelType': 'textField',
- 'name': 'user_password',
- 'label': 'Passwort',
- 'options': 'password',
- 'validators': 'required',
- },
- {
- 'modelType': 'textField',
- 'name': 'repetition',
- 'label': 'Wiederholung',
- 'options': 'password',
- 'validators': 'required equals=user_password'
- },
- ]
- }
- ]
- },
- {
- 'page': 'list',
- 'title': 'Benutzer',
- 'pageType': 'list',
- 'tableColumns':
- 'user_id user_name user_displayname user_email user_role',
- 'tableTitles': ';Id;Name;Anzeigename;EMail;Rolle',
- 'sections': [
- {
- 'sectionType': 'filterPanel',
- 'children': [
- {
- 'modelType': 'dbReference',
- 'filterType': 'pattern',
- 'name': 'user_name',
- 'column': 'user_name',
- 'toolTip':
- 'Filter bezüglich des Namens der anzuzeigenden Einträge: Joker "*" (beliebiger String) ist erlaubt.'
- },
- {
- 'modelType': 'dbReference',
- 'name': 'user_role',
- 'filterType': 'equals',
- 'column': 'user_role',
- 'toolTip':
- 'Filter bezüglich der Rolle der anzuzeigenden Einträge. "-" bedeutet keine Einschränkung',
- }
- ],
- 'buttonBar': [
- {
- 'modelType': 'button',
- 'buttonType': 'custom',
- 'name': 'new',
- 'label': 'Neuer Benutzer',
- 'toolTip': 'Erzeugen eines neuen Benutzers'
- },
- ],
- }
- ]
- },
- {
- 'page': 'login',
- 'title': 'Anmelden',
- 'pageType': 'change',
- 'options': 'noAutoButton',
- 'sections': [
- {
- 'sectionType': 'simpleForm',
- 'children': [
- {
- 'modelType': 'textField',
- 'name': 'user',
- 'label': 'Benutzer oder EMail',
- 'validators': 'required',
- },
- {
- 'modelType': 'textField',
- 'name': 'password',
- 'label': 'Password',
- 'options': 'password',
- 'validators': 'required',
- },
- ],
- 'buttonBar': [
- {
- 'modelType': 'button',
- 'buttonType': 'custom',
- 'name': 'login',
- 'label': 'Anmelden',
- },
- ]
- }
- ]
- },
- ]
- };
-
- UserModel(BaseLogger logger) : super(mapUser, logger);
-
- /// Returns the name including the names of the parents.
- @override
- String fullName() => name;
-
- @override
- String widgetName() => name;
-}
import 'package:flutter/material.dart';
import '../../helper/settings.dart';
-import '../../widget/edit_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../../model/page_model.dart';
import '../application_data.dart';
@override
ConfigurationChangePageState createState() {
//! === BeginOfCall ===
- final rc =
- ConfigurationChangePageStateCustomized(primaryId, applicationData, initialRow);
+ final rc = ConfigurationChangePageStateCustomized(
+ primaryId, applicationData, initialRow);
//! === EndOfCall ===
/// for unittests:
}
}
-abstract class ConfigurationChangePageState extends State<ConfigurationChangePage>
- implements RedrawPage {
+abstract class ConfigurationChangePageState
+ extends State<ConfigurationChangePage> implements RedrawPage {
final ApplicationData applicationData;
final int primaryId;
final Map initialRow;
- final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: '$configurationChangePageModule-$configurationChangePageName');
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel:
+ '$configurationChangePageModule-$configurationChangePageName');
ConfigurationController controller;
//! === BeginOfCustomizedVars2 ===
//! === EndOfCustomizedVars2 ===
//! === BeginOfConstructor2 ===
- ConfigurationChangePageState(this.primaryId, this.applicationData, this.initialRow);
+ ConfigurationChangePageState(
+ this.primaryId, this.applicationData, this.initialRow);
//! === EndOfConstructor2 ===
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
bottomNavigationBar: applicationData.footerBuilder().widget(controller),
- body: EditForm.editForm(
+ body: formDialog(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
@override
void initState() {
super.initState();
- controller =
- ConfigurationController(_formKey, this, 'change', context, applicationData);
+ controller = ConfigurationController(
+ _formKey, this, configurationChangePageName, context, applicationData);
controller.initialize();
customize();
}
import 'package:flutter/material.dart';
import '../../helper/settings.dart';
-import '../../model/standard/configuration_model.dart';
+import '../../model/module/configuration_model.dart';
import '../../widget/page_controller_bones.dart';
import '../application_data.dart';
import 'configuration_change_page.dart';
+import 'configuration_delete_page.dart';
class ConfigurationController extends PageControllerBones {
/// Controller for a page named [pageName].
builder: (context) =>
ConfigurationChangePage(id, applicationData, row)));
}
+
+ @override
+ void startDelete(int id, Map row) {
+ applicationData.pushCaller(this);
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (context) =>
+ ConfigurationDeletePage(id, applicationData, row)));
+ }
}
import 'package:flutter/material.dart';
import '../../helper/settings.dart';
-import '../../widget/edit_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../../model/page_model.dart';
import '../application_data.dart';
}
}
-abstract class ConfigurationCreatePageState extends State<ConfigurationCreatePage>
- implements RedrawPage {
+abstract class ConfigurationCreatePageState
+ extends State<ConfigurationCreatePage> implements RedrawPage {
final ApplicationData applicationData;
- final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: '$configurationCreatePageModule-$configurationCreatePageName');
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel:
+ '$configurationCreatePageModule-$configurationCreatePageName');
ConfigurationController controller;
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
bottomNavigationBar: applicationData.footerBuilder().widget(controller),
- body: EditForm.editForm(
+ body: formDialog(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
@override
void initState() {
super.initState();
- controller =
- ConfigurationController(_formKey, this, configurationCreatePageName, context, applicationData);
+ controller = ConfigurationController(
+ _formKey, this, configurationCreatePageName, context, applicationData);
controller.initialize();
customize();
}
--- /dev/null
+import 'package:flutter/material.dart';
+
+import '../../helper/settings.dart';
+import '../../widget/dialog_bones.dart';
+import '../../widget/page_controller_bones.dart';
+import '../application_data.dart';
+import '../../model/page_model.dart';
+import 'configuration_controller.dart';
+
+const configurationDeletePageModule = 'configuration';
+const configurationDeletePageName = 'delete';
+const configurationDeletePageType = PageModelType.delete;
+//! === BeginOfGeneratedCode: Delete only in areas marked as customized
+
+class ConfigurationDeletePage extends StatefulWidget {
+ final ApplicationData applicationData;
+ final Map initialRow;
+ final logger = Settings().logger;
+ final int primaryId;
+
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
+ ConfigurationDeletePage(this.primaryId, this.applicationData, this.initialRow,
+ {Key key})
+ : super(key: key);
+
+ //! === EndOfConstructor1 ===
+
+ @override
+ ConfigurationDeletePageState createState() {
+ //! === BeginOfCall ===
+ final rc = ConfigurationDeletePageStateCustomized(
+ primaryId, applicationData, initialRow);
+ //! === EndOfCall ===
+
+ /// for unittests:
+ applicationData.lastModuleState = rc;
+ return rc;
+ }
+}
+
+abstract class ConfigurationDeletePageState
+ extends State<ConfigurationDeletePage> implements RedrawPage {
+ final ApplicationData applicationData;
+ final int primaryId;
+ final Map initialRow;
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel:
+ '$configurationDeletePageModule-$configurationDeletePageName');
+
+ ConfigurationController controller;
+
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
+ ConfigurationDeletePageState(
+ this.primaryId, this.applicationData, this.initialRow);
+
+ //! === EndOfConstructor2 ===
+
+ @override
+ Widget build(BuildContext context) {
+ controller.beginOfBuild(context);
+ //! === BeginOfScaffold ===
+ return Scaffold(
+ appBar: applicationData.appBarBuilder(controller.page.title),
+ drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
+ body: formDialog(
+ key: _formKey,
+ pageController: controller,
+ configuration: applicationData.configuration,
+ primaryId: primaryId,
+ initialRow: initialRow,
+ ));
+ //! === EndOfScaffold ===
+ }
+
+ /// Customize the page, e.g. modify the default widget list given by the model
+ void customize();
+
+ @override
+ void dispose() {
+ controller.dispose();
+ super.dispose();
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ controller = ConfigurationController(
+ _formKey, this, configurationDeletePageName, context, applicationData);
+ controller.initialize();
+ customize();
+ }
+
+ @override
+ void redraw(RedrawReason reason,
+ {String customString, RedrawCallbackFunctionSimple callback}) {
+ setState(() {
+ controller.afterSetState(reason,
+ customString: customString, callback: callback);
+ });
+ }
+}
+
+//! === EndOfGeneratedCode: Below you can change manually:
+
+class ConfigurationDeletePageStateCustomized
+ extends ConfigurationDeletePageState {
+ ConfigurationDeletePageStateCustomized(
+ int primaryId, ApplicationData applicationData, Map initialRow)
+ : super(primaryId, applicationData, initialRow);
+
+ @override
+ void customize() {
+ // ToDo: write code if needed
+ }
+}
import 'package:flutter_bones/src/widget/view.dart';
import '../../model/page_model.dart';
-import '../../widget/list_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../application_data.dart';
import 'configuration_controller.dart';
implements RedrawPage {
final ApplicationData applicationData;
- final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: '$configurationListPageModule-$configurationListPageName');
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$configurationListPageModule-$configurationListPageName');
Iterable<dynamic> rowsDeprecated;
ConfigurationController controller;
titles: ListForm.stringsToTitles(controller.page.tableTitles),
columnNames: controller.page.tableColumns ?? [],
rows: controller.listRows ?? [],
- showEditIcon: true,
+ showDeleteIcon: controller.rightOf(
+ configurationListPageModule,
+ configurationListPageName,
+ configurationListPageType,
+ TaskRight.listEdit),
+ showEditIcon: controller.rightOf(
+ configurationListPageModule,
+ configurationListPageName,
+ configurationListPageType,
+ TaskRight.listDelete),
pageController: controller,
buttons: <Widget>[
ButtonBar(
@override
void initState() {
super.initState();
- controller =
- ConfigurationController(_formKey, this, configurationListPageName, context, applicationData);
+ controller = ConfigurationController(
+ _formKey, this, configurationListPageName, context, applicationData);
controller.initialize();
customize();
}
import 'package:flutter/material.dart';
import '../../helper/settings.dart';
-import '../../widget/edit_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../../model/page_model.dart';
import '../application_data.dart';
final ApplicationData applicationData;
final int primaryId;
final Map initialRow;
- final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: '$menuChangePageModule-$menuChangePageName');
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$menuChangePageModule-$menuChangePageName');
MenuController controller;
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
bottomNavigationBar: applicationData.footerBuilder().widget(controller),
- body: EditForm.editForm(
+ body: formDialog(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
@override
void initState() {
super.initState();
- controller =
- MenuController(_formKey, this, 'change', context, applicationData);
+ controller = MenuController(
+ _formKey, this, menuChangePageName, context, applicationData);
controller.initialize();
customize();
}
import 'package:flutter/material.dart';
import '../../helper/settings.dart';
-import '../../model/standard/menu_model.dart';
+import '../../model/module/menu_model.dart';
import '../../widget/page_controller_bones.dart';
import '../application_data.dart';
import 'menu_change_page.dart';
+import 'menu_delete_page.dart';
class MenuController extends PageControllerBones {
/// Controller for a page named [pageName].
MaterialPageRoute(
builder: (context) => MenuChangePage(id, applicationData, row)));
}
+
+ @override
+ void startDelete(int id, Map row) {
+ applicationData.pushCaller(this);
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (context) => MenuDeletePage(id, applicationData, row)));
+ }
}
import 'package:flutter/material.dart';
import '../../helper/settings.dart';
-import '../../widget/edit_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../../model/page_model.dart';
import '../application_data.dart';
implements RedrawPage {
final ApplicationData applicationData;
- final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: '$menuCreatePageModule-$menuCreatePageName');
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$menuCreatePageModule-$menuCreatePageName');
MenuController controller;
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
bottomNavigationBar: applicationData.footerBuilder().widget(controller),
- body: EditForm.editForm(
+ body: formDialog(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
@override
void initState() {
super.initState();
- controller =
- MenuController(_formKey, this, menuCreatePageName, context, applicationData);
+ controller = MenuController(
+ _formKey, this, menuCreatePageName, context, applicationData);
controller.initialize();
customize();
}
--- /dev/null
+import 'package:flutter/material.dart';
+
+import '../../helper/settings.dart';
+import '../../widget/dialog_bones.dart';
+import '../../widget/page_controller_bones.dart';
+import '../application_data.dart';
+import '../../model/page_model.dart';
+import 'menu_controller.dart';
+
+const menuDeletePageModule = 'menu';
+const menuDeletePageName = 'delete';
+const menuDeletePageType = PageModelType.delete;
+//! === BeginOfGeneratedCode: Delete only in areas marked as customized
+
+class MenuDeletePage extends StatefulWidget {
+ final ApplicationData applicationData;
+ final Map initialRow;
+ final logger = Settings().logger;
+ final int primaryId;
+
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
+ MenuDeletePage(this.primaryId, this.applicationData, this.initialRow,
+ {Key key})
+ : super(key: key);
+
+ //! === EndOfConstructor1 ===
+
+ @override
+ MenuDeletePageState createState() {
+ //! === BeginOfCall ===
+ final rc =
+ MenuDeletePageStateCustomized(primaryId, applicationData, initialRow);
+ //! === EndOfCall ===
+
+ /// for unittests:
+ applicationData.lastModuleState = rc;
+ return rc;
+ }
+}
+
+abstract class MenuDeletePageState extends State<MenuDeletePage>
+ implements RedrawPage {
+ final ApplicationData applicationData;
+ final int primaryId;
+ final Map initialRow;
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$menuDeletePageModule-$menuDeletePageName');
+
+ MenuController controller;
+
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
+ MenuDeletePageState(this.primaryId, this.applicationData, this.initialRow);
+
+ //! === EndOfConstructor2 ===
+
+ @override
+ Widget build(BuildContext context) {
+ controller.beginOfBuild(context);
+ //! === BeginOfScaffold ===
+ return Scaffold(
+ appBar: applicationData.appBarBuilder(controller.page.title),
+ drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
+ body: formDialog(
+ key: _formKey,
+ pageController: controller,
+ configuration: applicationData.configuration,
+ primaryId: primaryId,
+ initialRow: initialRow,
+ ));
+ //! === EndOfScaffold ===
+ }
+
+ /// Customize the page, e.g. modify the default widget list given by the model
+ void customize();
+
+ @override
+ void dispose() {
+ controller.dispose();
+ super.dispose();
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ controller = MenuController(
+ _formKey, this, menuDeletePageName, context, applicationData);
+ controller.initialize();
+ customize();
+ }
+
+ @override
+ void redraw(RedrawReason reason,
+ {String customString, RedrawCallbackFunctionSimple callback}) {
+ setState(() {
+ controller.afterSetState(reason,
+ customString: customString, callback: callback);
+ });
+ }
+}
+
+//! === EndOfGeneratedCode: Below you can change manually:
+
+class MenuDeletePageStateCustomized extends MenuDeletePageState {
+ MenuDeletePageStateCustomized(
+ int primaryId, ApplicationData applicationData, Map initialRow)
+ : super(primaryId, applicationData, initialRow);
+
+ @override
+ void customize() {
+ // ToDo: write code if needed
+ }
+}
import 'package:flutter_bones/flutter_bones.dart';
import '../../model/page_model.dart';
-import '../../widget/list_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../application_data.dart';
import 'menu_controller.dart';
titles: ListForm.stringsToTitles(controller.page.tableTitles),
columnNames: controller.page.tableColumns ?? [],
rows: controller.listRows ?? [],
- showEditIcon: true,
+ showDeleteIcon: controller.rightOf(menuListPageModule, menuListPageName,
+ menuListPageType, TaskRight.listEdit),
+ showEditIcon: controller.rightOf(menuListPageModule, menuListPageName,
+ menuListPageType, TaskRight.listDelete),
pageController: controller,
buttons: <Widget>[
ButtonBar(
@override
void initState() {
super.initState();
- controller =
- MenuController(_formKey, this, menuListPageName, context, applicationData);
+ controller = MenuController(
+ _formKey, this, menuListPageName, context, applicationData);
controller.initialize();
customize();
}
import 'package:flutter/material.dart';
import '../../helper/settings.dart';
-import '../../widget/edit_form.dart';
+import '../../model/page_model.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../application_data.dart';
-import '../../model/page_model.dart';
import 'role_controller.dart';
const roleChangePageModule = 'role';
-const roleChangePageName = 'create';
-const roleChangePageType = PageModelType.create;
+const roleChangePageName = 'change';
+const roleChangePageType = PageModelType.change;
//! === BeginOfGeneratedCode: Change only in areas marked as customized
class RoleChangePage extends StatefulWidget {
final ApplicationData applicationData;
final int primaryId;
final Map initialRow;
- final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: '$roleChangePageModule-$roleChangePageName');
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$roleChangePageModule-$roleChangePageName');
RoleController controller;
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
bottomNavigationBar: applicationData.footerBuilder().widget(controller),
- body: EditForm.editForm(
+ body: formDialog(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
@override
void initState() {
super.initState();
- controller =
- RoleController(_formKey, this, 'change', context, applicationData);
+ controller = RoleController(
+ _formKey, this, roleChangePageName, context, applicationData);
controller.initialize();
customize();
}
//! === EndOfGeneratedCode: Below you can change manually:
-class RoleChangePageStateCustomized extends RoleChangePageState {
+class RoleChangePageStateCustomized extends RoleChangePageState
+ implements SingleRecordPage {
RoleChangePageStateCustomized(
int primaryId, ApplicationData applicationData, Map initialRow)
: super(primaryId, applicationData, initialRow);
void customize() {
// ToDo: write code if needed
}
+
+ @override
+ int getPrimaryKey() {
+ return primaryId;
+ }
}
import 'package:flutter/material.dart';
import '../../helper/settings.dart';
-import '../../model/standard/role_model.dart';
+import '../../model/module/role_model.dart';
import '../../widget/page_controller_bones.dart';
import '../application_data.dart';
import 'role_change_page.dart';
+import 'role_delete_page.dart';
class RoleController extends PageControllerBones {
/// Controller for a page named [pageName].
MaterialPageRoute(
builder: (context) => RoleChangePage(id, applicationData, row)));
}
+
+ @override
+ void startDelete(int id, Map row) {
+ applicationData.pushCaller(this);
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (context) => RoleDeletePage(id, applicationData, row)));
+ }
}
import 'package:flutter/material.dart';
import '../../helper/settings.dart';
-import '../../widget/edit_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../../model/page_model.dart';
import '../application_data.dart';
implements RedrawPage {
final ApplicationData applicationData;
- final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: '$roleCreatePageModule-$roleCreatePageName');
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$roleCreatePageModule-$roleCreatePageName');
RoleController controller;
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
bottomNavigationBar: applicationData.footerBuilder().widget(controller),
- body: EditForm.editForm(
+ body: formDialog(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
@override
void initState() {
super.initState();
- controller =
- RoleController(_formKey, this, roleCreatePageName, context, applicationData);
+ controller = RoleController(
+ _formKey, this, roleCreatePageName, context, applicationData);
controller.initialize();
customize();
}
--- /dev/null
+import 'package:flutter/material.dart';
+
+import '../../helper/settings.dart';
+import '../../model/page_model.dart';
+import '../../widget/page_controller_bones.dart';
+import '../application_data.dart';
+import 'role_controller.dart';
+
+const roleCustomPageModule = 'role';
+const roleCustomPageName = 'custom';
+const roleCustomPageType = PageModelType.custom;
+//! === BeginOfGeneratedCode: Change only in areas marked as customized
+
+class RoleCustomPage extends StatefulWidget {
+ final ApplicationData applicationData;
+ final logger = Settings().logger;
+
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
+ RoleCustomPage(this.applicationData, {Key key}) : super(key: key);
+
+ //! === EndOfConstructor1 ===
+
+ @override
+ RoleCustomPageState createState() {
+ //! === BeginOfCall ===
+ final rc = RoleCustomPageStateCustomized(applicationData);
+ //! === EndOfCall ===
+
+ /// for unittests:
+ applicationData.lastModuleState = rc;
+ return rc;
+ }
+}
+
+abstract class RoleCustomPageState extends State<RoleCustomPage>
+ implements RedrawPage {
+ final ApplicationData applicationData;
+
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$roleCustomPageModule-$roleCustomPageName');
+
+ RoleController controller;
+
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
+ RoleCustomPageState(this.applicationData);
+
+ //! === EndOfConstructor2 ===
+
+ @override
+ Widget build(BuildContext context) {
+ controller?.beginOfBuild(context);
+ return buildScaffold(context);
+ }
+
+ // Builds the widget tree of the page.
+ Widget buildScaffold(BuildContext context);
+
+ /// Customize the page, e.g. modify the default widget list given by the model
+ void customize();
+
+ @override
+ void dispose() {
+ controller.dispose();
+ super.dispose();
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ controller = RoleController(
+ _formKey, this, roleCustomPageName, context, applicationData);
+ controller.initialize();
+ customize();
+ }
+
+ @override
+ void redraw(RedrawReason reason,
+ {String customString, RedrawCallbackFunctionSimple callback}) {
+ setState(() {
+ controller.afterSetState(reason,
+ customString: customString, callback: callback);
+ });
+ }
+}
+
+//! === EndOfGeneratedCode: Below you can change manually:
+
+class RoleCustomPageStateCustomized extends RoleCustomPageState {
+ RoleCustomPageStateCustomized(ApplicationData applicationData)
+ : super(applicationData);
+
+ @override
+ Widget buildScaffold(BuildContext context) {
+ // ToDo: write code
+ return Scaffold(
+ appBar: applicationData.appBarBuilder(controller.page.title),
+ drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
+ body: Text('Hello world'));
+ }
+
+ @override
+ void customize() {
+ // ToDo: write code if needed
+ }
+}
--- /dev/null
+import 'package:flutter/material.dart';
+
+import '../../helper/settings.dart';
+import '../../model/page_model.dart';
+import '../../widget/dialog_bones.dart';
+import '../../widget/page_controller_bones.dart';
+import '../application_data.dart';
+import 'role_controller.dart';
+
+const roleDeletePageModule = 'role';
+const roleDeletePageName = 'delete';
+const roleDeletePageType = PageModelType.delete;
+//! === BeginOfGeneratedCode: Delete only in areas marked as customized
+
+class RoleDeletePage extends StatefulWidget {
+ final ApplicationData applicationData;
+ final Map initialRow;
+ final logger = Settings().logger;
+ final int primaryId;
+
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
+ RoleDeletePage(this.primaryId, this.applicationData, this.initialRow,
+ {Key key})
+ : super(key: key);
+
+ //! === EndOfConstructor1 ===
+
+ @override
+ RoleDeletePageState createState() {
+ //! === BeginOfCall ===
+ final rc =
+ RoleDeletePageStateCustomized(primaryId, applicationData, initialRow);
+ //! === EndOfCall ===
+
+ /// for unittests:
+ applicationData.lastModuleState = rc;
+ return rc;
+ }
+}
+
+abstract class RoleDeletePageState extends State<RoleDeletePage>
+ implements RedrawPage {
+ final ApplicationData applicationData;
+ final int primaryId;
+ final Map initialRow;
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$roleDeletePageModule-$roleDeletePageName');
+
+ RoleController controller;
+
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
+ RoleDeletePageState(this.primaryId, this.applicationData, this.initialRow);
+
+ //! === EndOfConstructor2 ===
+
+ @override
+ Widget build(BuildContext context) {
+ controller.beginOfBuild(context);
+ //! === BeginOfScaffold ===
+ return Scaffold(
+ appBar: applicationData.appBarBuilder(controller.page.title),
+ drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
+ body: formDialog(
+ key: _formKey,
+ pageController: controller,
+ configuration: applicationData.configuration,
+ primaryId: primaryId,
+ initialRow: initialRow,
+ ));
+ //! === EndOfScaffold ===
+ }
+
+ /// Customize the page, e.g. modify the default widget list given by the model
+ void customize();
+
+ @override
+ void dispose() {
+ controller.dispose();
+ super.dispose();
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ controller = RoleController(
+ _formKey, this, roleDeletePageName, context, applicationData);
+ controller.initialize();
+ customize();
+ }
+
+ @override
+ void redraw(RedrawReason reason,
+ {String customString, RedrawCallbackFunctionSimple callback}) {
+ setState(() {
+ controller.afterSetState(reason,
+ customString: customString, callback: callback);
+ });
+ }
+}
+
+//! === EndOfGeneratedCode: Below you can change manually:
+
+class RoleDeletePageStateCustomized extends RoleDeletePageState
+ implements SingleRecordPage {
+ RoleDeletePageStateCustomized(
+ int primaryId, ApplicationData applicationData, Map initialRow)
+ : super(primaryId, applicationData, initialRow);
+
+ @override
+ void customize() {
+ // ToDo: write code if needed
+ }
+ @override
+ int getPrimaryKey() {
+ return primaryId;
+ }
+}
import 'package:flutter/material.dart';
+import 'package:flutter_bones/src/widget/utilities.dart';
import '../../model/page_model.dart';
-import '../../widget/list_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../../widget/view.dart';
import '../application_data.dart';
titles: ListForm.stringsToTitles(controller.page.tableTitles),
columnNames: controller.page.tableColumns ?? [],
rows: controller.listRows ?? [],
- showEditIcon: true,
+ showDeleteIcon: controller.rightOf(roleListPageModule, roleListPageName,
+ roleListPageType, TaskRight.listEdit),
+ showEditIcon: controller.rightOf(roleListPageModule, roleListPageName,
+ roleListPageType, TaskRight.listDelete),
pageController: controller,
buttons: <Widget>[
ButtonBar(
@override
void initState() {
super.initState();
- controller =
- RoleController(_formKey, this, roleListPageName, context, applicationData);
+ controller = RoleController(
+ _formKey, this, roleListPageName, context, applicationData);
controller.initialize();
customize();
}
button.onPressed = () {
controller.goTo(pageType: PageModelType.create);
};
+ controller.page.taskRightCallback =
+ utilities.rightsOfRoleListPage(controller);
}
}
import 'package:flutter/material.dart';
import '../../helper/settings.dart';
-import '../../widget/edit_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../../model/page_model.dart';
import '../application_data.dart';
@override
StarterChangePageState createState() {
//! === BeginOfCall ===
- final rc =
- StarterChangePageStateCustomized(primaryId, applicationData, initialRow);
+ final rc = StarterChangePageStateCustomized(
+ primaryId, applicationData, initialRow);
//! === EndOfCall ===
/// for unittests:
final ApplicationData applicationData;
final int primaryId;
final Map initialRow;
- final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'starter_change');
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$starterChangePageModule-$starterChangePageName');
StarterController controller;
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
bottomNavigationBar: applicationData.footerBuilder().widget(controller),
- body: EditForm.editForm(
+ body: formDialog(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
/// Customize the page, e.g. modify the default widget list given by the model
void customize();
+ @override
void dispose() {
controller.dispose();
super.dispose();
@override
void initState() {
super.initState();
- controller =
- StarterController(_formKey, this, 'change', context, applicationData);
+ controller = StarterController(
+ _formKey, this, starterChangePageName, context, applicationData);
controller.initialize();
customize();
}
import 'package:flutter/material.dart';
import '../../helper/settings.dart';
-import '../../model/standard/starter_model.dart';
+import '../../model/module/starter_model.dart';
import '../../widget/page_controller_bones.dart';
import '../application_data.dart';
import 'starter_change_page.dart';
+import 'starter_delete_page.dart';
class StarterController extends PageControllerBones {
/// Controller for a page named [pageName].
MaterialPageRoute(
builder: (context) => StarterChangePage(id, applicationData, row)));
}
+
+ @override
+ void startDelete(int id, Map row) {
+ applicationData.pushCaller(this);
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (context) => StarterDeletePage(id, applicationData, row)));
+ }
}
import 'package:flutter/material.dart';
import '../../helper/settings.dart';
-import '../../widget/edit_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../../model/page_model.dart';
import '../application_data.dart';
implements RedrawPage {
final ApplicationData applicationData;
- final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: '$starterCreatePageModule-$starterCreatePageName');
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$starterCreatePageModule-$starterCreatePageName');
StarterController controller;
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
bottomNavigationBar: applicationData.footerBuilder().widget(controller),
- body: EditForm.editForm(
+ body: formDialog(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
@override
void initState() {
super.initState();
- controller =
- StarterController(_formKey, this, starterCreatePageName, context, applicationData);
+ controller = StarterController(
+ _formKey, this, starterCreatePageName, context, applicationData);
controller.initialize();
customize();
}
--- /dev/null
+import 'package:flutter/material.dart';
+
+import '../../helper/settings.dart';
+import '../../widget/dialog_bones.dart';
+import '../../widget/page_controller_bones.dart';
+import '../application_data.dart';
+import '../../model/page_model.dart';
+import 'starter_controller.dart';
+
+const starterDeletePageModule = 'starter';
+const starterDeletePageName = 'delete';
+const starterDeletePageType = PageModelType.delete;
+//! === BeginOfGeneratedCode: Delete only in areas marked as customized
+
+class StarterDeletePage extends StatefulWidget {
+ final ApplicationData applicationData;
+ final Map initialRow;
+ final logger = Settings().logger;
+ final int primaryId;
+
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
+ StarterDeletePage(this.primaryId, this.applicationData, this.initialRow,
+ {Key key})
+ : super(key: key);
+
+ //! === EndOfConstructor1 ===
+
+ @override
+ StarterDeletePageState createState() {
+ //! === BeginOfCall ===
+ final rc = StarterDeletePageStateCustomized(
+ primaryId, applicationData, initialRow);
+ //! === EndOfCall ===
+
+ /// for unittests:
+ applicationData.lastModuleState = rc;
+ return rc;
+ }
+}
+
+abstract class StarterDeletePageState extends State<StarterDeletePage>
+ implements RedrawPage {
+ final ApplicationData applicationData;
+ final int primaryId;
+ final Map initialRow;
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$starterDeletePageModule-$starterDeletePageName');
+
+ StarterController controller;
+
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
+ StarterDeletePageState(this.primaryId, this.applicationData, this.initialRow);
+
+ //! === EndOfConstructor2 ===
+
+ @override
+ Widget build(BuildContext context) {
+ controller.beginOfBuild(context);
+ //! === BeginOfScaffold ===
+ return Scaffold(
+ appBar: applicationData.appBarBuilder(controller.page.title),
+ drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
+ body: formDialog(
+ key: _formKey,
+ pageController: controller,
+ configuration: applicationData.configuration,
+ primaryId: primaryId,
+ initialRow: initialRow,
+ ));
+ //! === EndOfScaffold ===
+ }
+
+ /// Customize the page, e.g. modify the default widget list given by the model
+ void customize();
+
+ @override
+ void dispose() {
+ controller.dispose();
+ super.dispose();
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ controller = StarterController(
+ _formKey, this, starterDeletePageName, context, applicationData);
+ controller.initialize();
+ customize();
+ }
+
+ @override
+ void redraw(RedrawReason reason,
+ {String customString, RedrawCallbackFunctionSimple callback}) {
+ setState(() {
+ controller.afterSetState(reason,
+ customString: customString, callback: callback);
+ });
+ }
+}
+
+//! === EndOfGeneratedCode: Below you can change manually:
+
+class StarterDeletePageStateCustomized extends StarterDeletePageState {
+ StarterDeletePageStateCustomized(
+ int primaryId, ApplicationData applicationData, Map initialRow)
+ : super(primaryId, applicationData, initialRow);
+
+ @override
+ void customize() {
+ // ToDo: write code if needed
+ }
+}
import 'package:flutter_bones/flutter_bones.dart';
import '../../model/page_model.dart';
-import '../../widget/list_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../application_data.dart';
import 'starter_controller.dart';
implements RedrawPage {
final ApplicationData applicationData;
- final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: '$starterListPageModule-$starterListPageName');
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$starterListPageModule-$starterListPageName');
Iterable<dynamic> rowsDeprecated;
StarterController controller;
titles: ListForm.stringsToTitles(controller.page.tableTitles),
columnNames: controller.page.tableColumns ?? [],
rows: controller.listRows ?? [],
- showEditIcon: true,
+ showDeleteIcon: controller.rightOf(starterListPageModule,
+ starterListPageName, starterListPageType, TaskRight.listEdit),
+ showEditIcon: controller.rightOf(starterListPageModule,
+ starterListPageName, starterListPageType, TaskRight.listDelete),
pageController: controller,
buttons: <Widget>[
ButtonBar(
@override
void initState() {
super.initState();
- controller =
- StarterController(_formKey, this, starterListPageName, context, applicationData);
+ controller = StarterController(
+ _formKey, this, starterListPageName, context, applicationData);
controller.initialize();
customize();
}
import '../../helper/settings.dart';
import '../../model/button_model.dart';
-import '../../widget/edit_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../../model/page_model.dart';
import '../application_data.dart';
final ApplicationData applicationData;
final int primaryId;
final Map initialRow;
- final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: '$userChangePageModule-$userChangePageName');
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$userChangePageModule-$userChangePageName');
UserController controller;
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
bottomNavigationBar: applicationData.footerBuilder().widget(controller),
- body: EditForm.editForm(
+ body: formDialog(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
@override
void initState() {
super.initState();
- controller =
- UserController(_formKey, this, 'change', context, applicationData);
+ controller = UserController(
+ _formKey, this, userChangePageName, context, applicationData);
controller.initialize();
customize();
}
@override
void customize() {
ButtonModel button = controller.page.buttonByName('set_password');
- button?.onPressed = () {
- String userName = controller.page.fieldByName('user_name').value;
- applicationData.pushCaller(controller);
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (context) => UserPasswordPage(
- primaryId, userName, applicationData, null)));
- };
+ if (applicationData.currentRolePriority > 20) {
+ if (!button.hasOption('disabled')) {
+ button.options.add('disabled');
+ }
+ } else {
+ button?.onPressed = () {
+ String userName = controller.page.fieldByName('user_name').value;
+ applicationData.pushCaller(controller);
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (context) => UserPasswordPage(
+ primaryId, userName, applicationData, null)));
+ };
+ }
}
}
import 'package:flutter/material.dart';
import '../../helper/settings.dart';
-import '../../model/standard/user_model.dart';
+import '../../model/module/user_model.dart';
import '../../widget/page_controller_bones.dart';
import '../application_data.dart';
import 'user_change_page.dart';
+import 'user_delete_page.dart';
class UserController extends PageControllerBones {
/// Controller for a page named [pageName].
MaterialPageRoute(
builder: (context) => UserChangePage(id, applicationData, row)));
}
+
+ @override
+ void startDelete(int id, Map row) {
+ applicationData.pushCaller(this);
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (context) => UserDeletePage(id, applicationData, row)));
+ }
}
import 'package:flutter/material.dart';
import '../../helper/settings.dart';
-import '../../widget/edit_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../../model/page_model.dart';
import '../application_data.dart';
implements RedrawPage {
final ApplicationData applicationData;
- final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: '$userCreatePageModule-$userCreatePageName');
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$userCreatePageModule-$userCreatePageName');
UserController controller;
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
bottomNavigationBar: applicationData.footerBuilder().widget(controller),
- body: EditForm.editForm(
+ body: formDialog(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
@override
void initState() {
super.initState();
- controller =
- UserController(_formKey, this, 'create', context, applicationData);
+ controller = UserController(
+ _formKey, this, userCreatePageName, context, applicationData);
controller.initialize();
customize();
}
--- /dev/null
+import 'package:flutter/material.dart';
+
+import '../../helper/settings.dart';
+import '../../widget/dialog_bones.dart';
+import '../../widget/page_controller_bones.dart';
+import '../application_data.dart';
+import '../../model/page_model.dart';
+import 'user_controller.dart';
+
+const userDeletePageModule = 'user';
+const userDeletePageName = 'delete';
+const userDeletePageType = PageModelType.delete;
+//! === BeginOfGeneratedCode: Delete only in areas marked as customized
+
+class UserDeletePage extends StatefulWidget {
+ final ApplicationData applicationData;
+ final Map initialRow;
+ final logger = Settings().logger;
+ final int primaryId;
+
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
+ UserDeletePage(this.primaryId, this.applicationData, this.initialRow,
+ {Key key})
+ : super(key: key);
+
+ //! === EndOfConstructor1 ===
+
+ @override
+ UserDeletePageState createState() {
+ //! === BeginOfCall ===
+ final rc =
+ UserDeletePageStateCustomized(primaryId, applicationData, initialRow);
+ //! === EndOfCall ===
+
+ /// for unittests:
+ applicationData.lastModuleState = rc;
+ return rc;
+ }
+}
+
+abstract class UserDeletePageState extends State<UserDeletePage>
+ implements RedrawPage {
+ final ApplicationData applicationData;
+ final int primaryId;
+ final Map initialRow;
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$userDeletePageModule-$userDeletePageName');
+
+ UserController controller;
+
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
+ UserDeletePageState(this.primaryId, this.applicationData, this.initialRow);
+
+ //! === EndOfConstructor2 ===
+
+ @override
+ Widget build(BuildContext context) {
+ controller.beginOfBuild(context);
+ //! === BeginOfScaffold ===
+ return Scaffold(
+ appBar: applicationData.appBarBuilder(controller.page.title),
+ drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
+ body: formDialog(
+ key: _formKey,
+ pageController: controller,
+ configuration: applicationData.configuration,
+ primaryId: primaryId,
+ initialRow: initialRow,
+ ));
+ //! === EndOfScaffold ===
+ }
+
+ /// Customize the page, e.g. modify the default widget list given by the model
+ void customize();
+
+ @override
+ void dispose() {
+ controller.dispose();
+ super.dispose();
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ controller = UserController(
+ _formKey, this, userDeletePageName, context, applicationData);
+ controller.initialize();
+ customize();
+ }
+
+ @override
+ void redraw(RedrawReason reason,
+ {String customString, RedrawCallbackFunctionSimple callback}) {
+ setState(() {
+ controller.afterSetState(reason,
+ customString: customString, callback: callback);
+ });
+ }
+}
+
+//! === EndOfGeneratedCode: Below you can change manually:
+
+class UserDeletePageStateCustomized extends UserDeletePageState {
+ UserDeletePageStateCustomized(
+ int primaryId, ApplicationData applicationData, Map initialRow)
+ : super(primaryId, applicationData, initialRow);
+
+ @override
+ void customize() {
+ // ToDo: write code if needed
+ }
+}
import 'package:flutter_bones/flutter_bones.dart';
import '../../model/page_model.dart';
-import '../../widget/list_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../application_data.dart';
import 'user_controller.dart';
titles: ListForm.stringsToTitles(controller.page.tableTitles),
columnNames: controller.page.tableColumns ?? [],
rows: controller.listRows ?? [],
- showEditIcon: true,
+ showDeleteIcon: controller.rightOf(userListPageModule, userListPageName,
+ userListPageType, TaskRight.listEdit),
+ showEditIcon: controller.rightOf(userListPageModule, userListPageName,
+ userListPageType, TaskRight.listDelete),
pageController: controller,
buttons: <Widget>[
ButtonBar(
@override
void initState() {
super.initState();
- controller =
- UserController(_formKey, this, userListPageName, context, applicationData);
+ controller = UserController(
+ _formKey, this, userListPageName, context, applicationData);
controller.initialize();
customize();
}
button.onPressed = () {
controller.goTo(pageType: PageModelType.create);
};
+ controller.page.taskRightCallback = (task, parameter) {
+ final row = parameter as Map;
+ return row['role_priority'] >=
+ controller.applicationData.currentRolePriority;
+ };
}
}
import '../../helper/settings.dart';
import '../../model/button_model.dart';
-import '../../widget/edit_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../../model/page_model.dart';
import '../application_data.dart';
implements RedrawPage {
final ApplicationData applicationData;
- final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: '$userLoginPageModule-$userLoginPageName');
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$userLoginPageModule-$userLoginPageName');
UserController controller;
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
bottomNavigationBar: applicationData.footerBuilder().widget(controller),
- body: EditForm.editForm(
+ body: formDialog(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
import '../../helper/settings.dart';
import '../../model/button_model.dart';
-import '../../widget/edit_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
import '../../model/page_model.dart';
import '../application_data.dart';
@override
UserPasswordPageState createState() {
//! === BeginOfCall ===
- final rc = UserPasswordPageStateCustomized(primaryId, this.userName, applicationData, initialRow);
+ final rc = UserPasswordPageStateCustomized(
+ primaryId, this.userName, applicationData, initialRow);
//! === EndOfCall ===
/// for unittests:
implements RedrawPage {
final ApplicationData applicationData;
final int primaryId;
- final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'user.password');
final Map initialRow;
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$userPasswordPageModule-$userPasswordPageName');
UserController controller;
final String userName;
//! === EndOfCustomizedVars2 ===
//! === BeginOfConstructor2 ===
- UserPasswordPageState(this.primaryId, this.userName, this.applicationData, this.initialRow);
+ UserPasswordPageState(
+ this.primaryId, this.userName, this.applicationData, this.initialRow);
//! === EndOfConstructor2 ===
@override
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
bottomNavigationBar: applicationData.footerBuilder().widget(controller),
- body: EditForm.editForm(
+ body: formDialog(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
@override
void initState() {
super.initState();
- controller =
- UserController(_formKey, this, userPasswordPageName, context, applicationData);
+ controller = UserController(
+ _formKey, this, userPasswordPageName, context, applicationData);
controller.initialize();
customize();
}
//! === EndOfGeneratedCode: Below you can change manually:
class UserPasswordPageStateCustomized extends UserPasswordPageState {
- UserPasswordPageStateCustomized(
- int primaryId, String userName, ApplicationData applicationData, Map initialRow)
+ UserPasswordPageStateCustomized(int primaryId, String userName,
+ ApplicationData applicationData, Map initialRow)
: super(primaryId, userName, applicationData, initialRow);
@override
--- /dev/null
+import 'package:dart_bones/dart_bones.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bones/src/widget/page_controller_bones.dart';
+
+import '../helper/string_helper.dart';
+import 'model_list.dart';
+import 'page_controller_bones.dart';
+import 'view.dart';
+
+typedef Function OnEditTap(Map<String, dynamic> row, int index);
+
+abstract class TableCallbackController {
+ OnEditTap getOnEditTap(String customString,
+ TableCallbackController controller, Map<String, dynamic> row);
+}
+
+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<Widget> stringsToTitles(List<String> titles) {
+ final rc = titles
+ .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 additional first column.
+ /// If [sortIndex] is not null the rows will be sorted by this index.
+ static Widget table({
+ @required List<Widget> titles,
+ @required List<String> columnNames,
+ @required PageControllerBones controller,
+ @required Iterable<dynamic> rows,
+ bool showEditIcon = false,
+ bool showDeleteIcon = false,
+ int sortIndex,
+ TableCallbackController tableCallbackController,
+ String customString,
+ }) {
+ if (titles.length != columnNames.length) {
+ controller.moduleModel.logger.error(
+ 'titles.length != columnNames.length: ${titles.length}/${columnNames.length}');
+ }
+ final titles2 = titles.map((item) => DataColumn(label: item)).toList();
+ if (showEditIcon) {
+ titles2.insert(0, DataColumn(label: SizedBox(width: 1)));
+ sortIndex = sortIndex == null ? null : sortIndex + 1;
+ }
+ if (showDeleteIcon) {
+ titles2.add(DataColumn(label: SizedBox(width: 1)));
+ }
+ final taskRightCallBack = controller.page.taskRightCallback;
+ Widget rc = Container(
+ margin: EdgeInsets.all(2),
+ child: DataTable(
+ showCheckboxColumn: true,
+ showBottomBorder: true,
+ sortColumnIndex: sortIndex,
+ columns: titles2,
+ rows: rows.map((row) {
+ final cells = <DataCell>[];
+ if (showEditIcon) {
+ final canEdit = taskRightCallBack == null
+ ? true
+ : taskRightCallBack(TaskRight.listEdit, row);
+ cells.add(DataCell(SizedBox(width: 1), showEditIcon: canEdit,
+ onTap: () {
+ if (canEdit) {
+ controller.onEditTap(customString, controller, row);
+ }
+ }));
+ }
+ for (var key in columnNames) {
+ cells.add(DataCell(
+ Text(StringHelper.asString(row[key], nullString: '')),
+ ));
+ }
+ if (showDeleteIcon) {
+ final canDelete = taskRightCallBack == null
+ ? true
+ : taskRightCallBack(TaskRight.listDelete, row);
+ cells.add(canDelete
+ ? DataCell(
+ Tooltip(
+ message: 'Endgültiges Löschen des Eintrags',
+ child: Icon(
+ Icons.delete_forever_outlined,
+ semanticLabel: 'Eintrag löschen',
+ )),
+ onTap: () => controller.onDeleteTap(
+ customString, controller, row))
+ : DataCell(Tooltip(
+ message: 'Löschen nicht erlaubt',
+ child: Icon(Icons.delete_rounded))));
+ }
+ 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.
+ /// If [errorMessage] is not null this message will be shown.
+ static Form listForm(
+ {@required Key key,
+ @required ModelList filters,
+ @required List<Widget> buttons,
+ @required List<Widget> titles,
+ @required List<String> columnNames,
+ @required Iterable<dynamic> rows,
+ bool showDeleteIcon = false,
+ bool showEditIcon = false,
+ String errorMessage,
+ PageControllerBones pageController,
+ @required BaseConfiguration configuration,
+ String customString}) {
+ final padding =
+ configuration.asFloat('form.card.padding', defaultValue: 16.0);
+
+ final view = View(pageController.moduleModel.logger);
+ final widgets = <Widget>[
+ ...view.modelsToWidgets(filters.models, pageController),
+ SizedBox(
+ height: configuration.asFloat('form.gap.field_button.height',
+ defaultValue: 16.0)),
+ ...buttons
+ ];
+ if (errorMessage != null) {
+ widgets.add(View().errorMessage(errorMessage));
+ }
+ widgets.add(table(
+ titles: titles,
+ columnNames: columnNames,
+ rows: rows,
+ showDeleteIcon: showDeleteIcon,
+ showEditIcon: showEditIcon,
+ controller: pageController,
+ customString: customString,
+ ));
+ 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: widgets)),
+ ));
+ }
+}
+
+/// Returns a widget with a form containing at least some input fields
+/// and a save/cancel button.
+/// a change page.
+/// [page] is the name of the page in the model.
+Form formDialog({
+ @required Key key,
+ @required PageControllerBones pageController,
+ @required BaseConfiguration configuration,
+ int primaryId,
+ Map initialRow,
+}) {
+ final padding =
+ configuration.asFloat('form.card.padding', defaultValue: 16.0);
+ pageController.buildModelList(initialRow);
+ final widgets = pageController.getWidgets();
+ final view = View();
+ final buttons = view.modelsToWidgets(
+ pageController.page.sections[0].buttonBar, pageController);
+ 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: <Widget>[
+ ...widgets,
+ SizedBox(
+ height: configuration.asFloat(
+ 'form.gap.field_button.height',
+ defaultValue: 16.0)),
+ ButtonBar(
+ children: buttons,
+ ),
+ ],
+ ))),
+ );
+}
+++ /dev/null
-import 'package:dart_bones/dart_bones.dart';
-import 'package:flutter/material.dart';
-
-import 'page_controller_bones.dart';
-import 'view.dart';
-
-typedef Function OnEditTap(Map<String, dynamic> row, int index);
-
-/// Contains helper functions for creating/changing data of a model based module.
-class EditForm {
- /// Returns a widget with a form containing at least some input fields
- /// and a save/cancel button.
- /// a change page.
- /// [page] is the name of the page in the model.
- static Form editForm({
- @required Key key,
- @required PageControllerBones pageController,
- @required BaseConfiguration configuration,
- int primaryId,
- Map initialRow,
- }) {
- final padding =
- configuration.asFloat('form.card.padding', defaultValue: 16.0);
- pageController.buildModelList(initialRow);
- final widgets = pageController.getWidgets();
- final view = View();
- final buttons = view.modelsToWidgets(
- pageController.page.sections[0].buttonBar, pageController);
- 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: <Widget>[
- ...widgets,
- SizedBox(
- height: configuration.asFloat(
- 'form.gap.field_button.height',
- defaultValue: 16.0)),
- ButtonBar(
- children: buttons,
- ),
- ],
- ))),
- );
- }
-}
+++ /dev/null
-import 'package:dart_bones/dart_bones.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bones/src/widget/page_controller_bones.dart';
-
-import '../helper/string_helper.dart';
-import 'model_list.dart';
-import 'page_controller_bones.dart';
-import 'view.dart';
-
-typedef Function OnEditTap(Map<String, dynamic> row, int index);
-
-abstract class TableCallbackController {
- OnEditTap getOnEditTap(String customString,
- TableCallbackController controller, Map<String, dynamic> row);
-}
-
-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<Widget> stringsToTitles(List<String> titles) {
- final rc = titles
- .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 additional first column.
- /// If [sortIndex] is not null the rows will be sorted by this index.
- static Widget table({
- @required List<Widget> titles,
- @required List<String> columnNames,
- @required PageControllerBones controller,
- @required Iterable<dynamic> rows,
- bool showEditIcon = false,
- int sortIndex,
- TableCallbackController tableCallbackController,
- String customString,
- }) {
- if (titles.length != columnNames.length) {
- controller.moduleModel.logger.error(
- 'titles.length != columnNames.length: ${titles.length}/${columnNames.length}');
- }
- final titles2 = titles.map((item) => DataColumn(label: item)).toList();
- if (showEditIcon) {
- titles2.insert(0, DataColumn(label: SizedBox(width: 1)));
- sortIndex = sortIndex == null ? null : sortIndex + 1;
- }
- Widget rc = Container(
- margin: EdgeInsets.all(2),
- child: DataTable(
- showCheckboxColumn: true,
- showBottomBorder: true,
- sortColumnIndex: sortIndex,
- columns: titles2,
- rows: rows.map((row) {
- final cells = <DataCell>[];
- if (showEditIcon) {
- cells.add(
- DataCell(SizedBox(width: 1), showEditIcon: true, onTap: () {
- controller.onEditTap(customString, controller, row);
- }));
- }
- for (var key in columnNames) {
- cells.add(DataCell(
- Text(StringHelper.asString(row[key], nullString: '')),
- ));
- }
- 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.
- /// If [errorMessage] is not null this message will be shown.
- static Form listForm(
- {@required Key key,
- @required ModelList filters,
- @required List<Widget> buttons,
- @required List<Widget> titles,
- @required List<String> columnNames,
- @required Iterable<dynamic> rows,
- bool showEditIcon = false,
- String errorMessage,
- PageControllerBones pageController,
- @required BaseConfiguration configuration,
- String customString}) {
- final padding =
- configuration.asFloat('form.card.padding', defaultValue: 16.0);
-
- final view = View(pageController.moduleModel.logger);
- final widgets = <Widget>[
- ...view.modelsToWidgets(filters.models, pageController),
- SizedBox(
- height: configuration.asFloat('form.gap.field_button.height',
- defaultValue: 16.0)),
- ...buttons
- ];
- if (errorMessage != null) {
- widgets.add(View().errorMessage(errorMessage));
- }
- widgets.add(table(
- titles: titles,
- columnNames: columnNames,
- rows: rows,
- showEditIcon: showEditIcon,
- controller: pageController,
- customString: customString,
- ));
- 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: widgets)),
- ));
- }
-}
int refreshCounter = 0;
final placeholders = <String, String>{};
- /// Opens another page.
- /// Use exactly one of the parameter:
- /// [pageType]: in this case the route will be constructed
- /// [route]: the route of the new page, e.g. '/role/change'
- void goTo({PageModelType pageType, String route}) {
- applicationData.pushCaller(this);
- if (pageType != null) {
- route = '/${moduleModel.name}/${StringUtils.enumToString(pageType)}';
- }
- Navigator.pushNamed(context, route);
- }
-
PageControllerBones(this.globalKey, this.parent, this.moduleModel,
this.pageName, this.context, this.applicationData,
[this.redrawCallback]);
+ ThemeData get themeData => Theme.of(context);
+
void afterSetState(RedrawReason reason,
{String customString, RedrawCallbackFunctionSimple callback}) {
if (callback != null) {
}
}
- Future<ComboboxData> buildComboboxDataFromPersistence(
- ComboBaseModel model) async {
- final rc = await applicationData.persistenceCache.comboboxAsync(
- model.listType, model.listOption,
- hasUndef: model.hasOption('undef'));
- return rc;
- }
-
/// This method should be called in each stateful widget of a page in the
/// build() method.
void beginOfBuild(BuildContext context) {
}
}
+ Future<ComboboxData> buildComboboxDataFromPersistence(
+ ComboBaseModel model) async {
+ final rc = await applicationData.persistenceCache.comboboxAsync(
+ model.listType, model.listOption,
+ hasUndef: model.hasOption('undef'));
+ return rc;
+ }
+
+ /// Prepares the widgetList: builds the widgets of the page.
+ /// [initialRow] is null or a map with the field values,
+ /// e.g. { 'role_name': 'admin', ...}
+ void buildModelList([Map initialRow]) {
+ modelList.clear();
+ page.sections[0].children.forEach((model) {
+ if (initialRow != null && model is FieldModel) {
+ model.valueFromRow(initialRow);
+ }
+ final name = model is FieldModel ? model.name : null;
+ final value =
+ initialRow == null || name == null ? null : initialRow[name];
+ if (model is FieldModel) {
+ model.value = value;
+ }
+ completeModels(model);
+ modelList.addModel(name, model);
+ });
+ page.sections[0].children.forEach((element) {
+ if (element is FieldModel) {
+ prepareModel(element);
+ }
+ });
+ }
+
/// Retrieves the rows shown in the list page.
void buildRows() {
final persistence = applicationData.persistence;
return rc;
}
- /// Prepares the widgetList: builds the widgets of the page.
- /// [initialRow] is null or a map with the field values,
- /// e.g. { 'role_name': 'admin', ...}
- void buildModelList([Map initialRow]) {
- modelList.clear();
- page.sections[0].children.forEach((model) {
- if (initialRow != null && model is FieldModel) {
- model.valueFromRow(initialRow);
- }
- final name = model is FieldModel ? model.name : null;
- final value =
- initialRow == null || name == null ? null : initialRow[name];
- if (model is FieldModel) {
- model.value = value;
- }
- completeModels(model);
- modelList.addModel(name, model);
- });
- page.sections[0].children.forEach((element) {
- if (element is FieldModel) {
- prepareModel(element);
- }
- });
- }
-
/// Completes the widgets asynchronously if needed.
void completeAsync() {
waitForCompletion = completeModelsAsync();
}
};
break;
+ case 'delete':
+ rc = () {
+ if (globalKey.currentState.validate()) {
+ final id = (parent as SingleRecordPage).getPrimaryKey();
+ applicationData.persistence
+ .delete(module: moduleModel.name, id: id)
+ .then((id) {
+ applicationData.callerRedraw(RedrawReason.fetchList);
+ applicationData.popCaller();
+ Navigator.pop(controller.getContext());
+ });
+ }
+ };
+ break;
case 'cancel':
rc = () {
applicationData.popCaller();
return rc ?? [];
}
- ThemeData get themeData => Theme.of(context);
+ /// Opens another page.
+ /// Use exactly one of the parameter:
+ /// [pageType]: in this case the route will be constructed
+ /// [route]: the route of the new page, e.g. '/role/change'
+ void goTo({PageModelType pageType, String route}) {
+ applicationData.pushCaller(this);
+ if (pageType != null) {
+ route = '/${moduleModel.name}/${StringUtils.enumToString(pageType)}';
+ }
+ Navigator.pushNamed(context, route);
+ }
/// Initializes the controller when the instance is complete constructed,
/// e.g. ModuleModel.parse() is called.
});
}
+ onDeleteTap(String customString, PageControllerBones controller, Map row) {
+ ColumnModel primary = moduleModel.mainTable().primary;
+ final id = row[primary.name];
+ applicationData.persistence
+ .recordById(module: moduleModel.name, id: id)
+ .then((row) => startDelete(id, row));
+ }
+
onEditTap(String customString, PageControllerBones controller, Map row) {
ColumnModel primary = moduleModel.mainTable().primary;
final id = row[primary.name];
Navigator.pushNamed(context, route);
}
+ /// Returns whether the current user has the right to do the [task].
+ /// [module], [pageName] and [pageType] specify the location of the task.
+ bool rightOf(
+ String module, String pageName, PageModelType pageType, TaskRight task) {
+ bool rc;
+ switch (task) {
+ case TaskRight.listEdit:
+ case TaskRight.listDelete:
+ if (module == 'role' || module == 'user' || module == 'configuration') {
+ rc = applicationData.currentRolePriority <= 20;
+ } else {
+ rc = applicationData.currentRolePriority <= 30;
+ }
+ break;
+ default:
+ rc = false;
+ break;
+ }
+ return rc;
+ }
+
/// Returns a standard search button for the list page.
Widget searchButton() {
final rc = View(moduleModel.logger)
'missing override of startChange() in ${moduleModel.fullName()}');
}
+ /// Starts the change page to edit the record with primary key [id].
+ /// [row] contains the db record of [id].
+ void startDelete(int id, Map row) {
+ moduleModel.logger.error(
+ 'missing override of startDelete() in ${moduleModel.fullName()}');
+ }
+
/// Returns the [TextEditingController] instance of a [TextFormField] assigned
/// to a model named [name].
TextEditingController textController(String name) {
redraw,
setError,
}
+
+abstract class SingleRecordPage {
+ /// Returns the primary key of the record displayed by the page:
+ int getPrimaryKey();
+}
+
+enum TaskRight {
+ custom1,
+ custom2,
+ custom3,
+ listEdit,
+ listDelete,
+}
--- /dev/null
+import 'package:dart_bones/dart_bones.dart';
+import 'page_controller_bones.dart';
+import '../model/page_model.dart';
+
+Utilities utilities;
+
+class Utilities {
+ BaseLogger logger;
+ Utilities(this.logger);
+ TaskRightCallback rightsOfRoleListPage(PageControllerBones controller) {
+ return (TaskRight task, dynamic parameter) {
+ final row = parameter as Map;
+ final rc = (task != TaskRight.listDelete && task != TaskRight.listEdit ||
+ controller.applicationData.currentRolePriority <=
+ row['role_priority']) &&
+ (task != TaskRight.listDelete || row['role_name'] != 'Administrator');
+ return rc;
+ };
+ }
+}
if (model != null && model.data?.waitState == WaitState.ready) {
rc = comboboxRaw(model, controller, initialValue);
} else {
+ controller.waitForCompletion = null;
rc = FutureBuilder<bool>(
future: controller.waitForCompletion,
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
import 'dart:io';
import 'package:dart_bones/dart_bones.dart';
+import 'package:flutter_bones_tool/src/helper/url_helper.dart';
import 'package:flutter_bones_tool/src/model/model_helper.dart';
import 'package:flutter_bones_tool/src/model/model_tool.dart';
/// Completes the ModelTool with io specific functionality.
class ModelToolIo extends ModelTool {
ModelToolIo(ModelHelper modelHelper, BaseLogger logger)
- : super(modelHelper, logger);
+ : super(modelHelper, logger) {
+ FileSync.setLogger(logger);
+ }
@override
void ensureDirectory(String path) {
}
@override
- void writeFile(String filename, String content) {
- FileSync.toFile(filename, content);
+ void writeFile(String filename, String content,
+ {bool mayExist, bool ensureDirectory}) {
+ if (ensureDirectory == null || ensureDirectory) {
+ FileSync.ensureDirectory(
+ UrlHelper.parentOf(filename, trailingSlash: false));
+ }
+ if (mayExist != null && !mayExist && FileSync.isFile(filename)) {
+ logger.error('$filename already exists');
+ } else {
+ FileSync.toFile(filename, content);
+ }
}
}
equals(''));
});
test('addRangeToList-converter', () {
- List<String> output;
final list = <String>['a1', 'a2', 'a3', 'a4'];
expect(
StringHelper.addRangeToList(list, null,
--- /dev/null
+import 'package:dart_bones/dart_bones.dart';
+import 'package:flutter_bones/src/helper/url_helper.dart';
+import 'package:test/test.dart';
+
+void main() {
+ final logger = MemoryLogger(LEVEL_FINE);
+ group('filename', () {
+ logger.log('start');
+ test('joinPath', () {
+ expect(UrlHelper.joinPaths('/a', '/b'), equals('/a/b'));
+ expect(UrlHelper.joinPaths('/a/', '/b'), equals('/a/b'));
+ expect(UrlHelper.joinPaths('/a/', 'b'), equals('/a/b'));
+ expect(UrlHelper.joinPaths('/a', ''), equals('/a'));
+ expect(UrlHelper.joinPaths('/a', '/b', '/c'), equals('/a/b/c'));
+ expect(UrlHelper.joinPaths('/a', './b', './c'), equals('/a/b/c'));
+ expect(UrlHelper.joinPaths('/a/', '/b/', '/c'), equals('/a/b/c'));
+ expect(UrlHelper.joinPaths('/a/', '/b/', 'c'), equals('/a/b/c'));
+ expect(UrlHelper.joinPaths('/a/', '', 'c'), equals('/a/c'));
+ });
+ });
+ test('nodeOf', () {
+ expect(UrlHelper.nodeOf('abc.de'), equals('abc.de'));
+ expect(UrlHelper.nodeOf('path/a'), equals('a'));
+ expect(UrlHelper.nodeOf('/base/in/path/abc.de'), equals('abc.de'));
+ });
+ test('parentOf', () {
+ expect(UrlHelper.parentOf('abc.de'), equals(''));
+ expect(UrlHelper.parentOf('path/a'), equals('path/'));
+ expect(UrlHelper.parentOf('path/a', trailingSlash: false), equals('path'));
+ expect(UrlHelper.parentOf('/', trailingSlash: false), equals(''));
+ expect(
+ UrlHelper.parentOf('/base/in/path/abc.de'), equals('/base/in/path/'));
+ });
+ test('extensionOf', () {
+ expect(UrlHelper.extensionOf('abc.blub.de'), equals('.de'));
+ expect(UrlHelper.extensionOf('.de'), equals(''));
+ expect(UrlHelper.extensionOf('path/a'), equals(''));
+ expect(UrlHelper.extensionOf('/base/in.path/abc.de'), equals('.de'));
+ expect(UrlHelper.extensionOf('/base/in.path/.de'), equals(''));
+ });
+ test('filenameOf', () {
+ expect(UrlHelper.filenameOf('abc.blub.de'), equals('abc.blub'));
+ expect(UrlHelper.filenameOf('.de'), equals('.de'));
+ expect(UrlHelper.filenameOf('path/a'), equals('a'));
+ expect(UrlHelper.filenameOf('/base/in.path/abc.de'), equals('abc'));
+ expect(UrlHelper.filenameOf('/base/in.path/.de'), equals('.de'));
+ });
+}
column role_changedby: DataType.string "Geändert von" options: hidden
== page create: PageModelType.create options:
= section section1: SectionModelType.simpleForm options: [
- textField user: "User" options: required unique primary notnull unique
+ textField user: "User" options: required unique primary notnull
textField role: "Id" options: primary notnull unique
button buttonStore: label: Save options: Save
] # create.section1
{
'page': 'create',
'pageType': 'create',
+ 'title': 'Demo',
'sections': [
{
'sectionType': 'simpleForm',
] # create.section1
== page change: PageModelType.change options:
= section section1: SectionModelType.simpleForm options: [
+ textField user_id: "Id" options: primary notnull unique readonly
+ textField user_name: "User" options: unique notnull
+ textField user_role: "Role" options:
allDbFields allDbFields1 options:
] # change.section1
'''));
page.buttonByName('unknown');
page.fieldByName('nothing');
final errors = logger.errors;
- expect(errors.length, equals(7));
+ expect(errors.length, equals(8));
expect(errors.contains('missing column user_name in table demo1.user'),
isTrue);
expect(
errors.contains('different sizes of tableTitles/tableColumns: 2/1'),
isTrue);
- expect(errors.contains('button null.a already defined: null.a'),
+ expect(errors.contains('model null.a already defined: null.a'),
isTrue);
expect(errors.contains('missing button unknown in page demo1.list'),
isTrue);
expect(errors.contains('missing field nothing in page demo1.list'),
isTrue);
- expect(errors.contains('field list.n already defined: list.n'),
+ expect(errors.contains('model list.n already defined: list.n'),
isTrue);
});
test('missing-section', () {
'pages': [
{
"page": "list",
+ 'title': 'Demo',
"pageType": "list",
},
],
final page = module.pageByName('list');
expect(page, isNotNull);
final errors = logger.errors;
- expect(errors.length, equals(1));
+ expect(errors.length, equals(2));
expect(errors.contains('missing sections in page demo1.list'),
isTrue);
});
final page = module.pageByName('list');
expect(page, isNotNull);
final errors = logger.errors;
- expect(errors.length, equals(1));
+ expect(errors.length, equals(3));
expect(errors.contains('"sections" is not an array in demo1.list: wrong'),
isTrue);
});
module.parse();
final page = module.pageByName('list');
final errors = logger.errors;
- expect(errors.length, equals(2));
+ expect(errors.length, equals(5));
expect(errors.contains(
'tableTitles and tableColumns are only meaningful in list pages: demo1.list'),
isTrue);
module.parse();
final page = module.pageByName('list');
final errors = logger.errors;
- expect(errors.length, equals(1));
+ expect(errors.length, equals(4));
expect(errors.contains('curious item in section list of demo1.list: []'),
isTrue);
expect(page.fullName() + page.widgetName(), equals('demo1.listlist'));
] # create.section1
== page change: PageModelType.change options:
= section section1: SectionModelType.simpleForm options: [
+ textField user_id: "Id" options: primary notnull unique readonly
+ textField user_name: "User" options: unique notnull
+ textField user_role: "Role" options:
allDbFields allDbFields1 options:
] # change.section1
'''));
] # create.section1
== page change: PageModelType.change options:
= section section1: SectionModelType.simpleForm options: [
+ textField user_id: "Id" options: primary notnull unique readonly
+ textField user_name: "User" options: unique notnull
+ textField user_role: "Role" options:
allDbFields allDbFields1 options:
] # change.section1
'''));
expect(errors.length, equals(0));
final page = module.pageByName('change');
expect(page, isNotNull);
- expect(page.models.values.length, equals(3));
+ expect(page.models.values.length, equals(6));
expect(page.hasField('user_id'), isTrue);
expect(page.hasField('user_name'), isTrue);
expect(page.hasField('user_role'), isTrue);
final module = ModuleModel(map, logger);
module.parse();
final errors = logger.errors;
- expect(errors.length, equals(1));
+ expect(errors.length, equals(2));
expect(errors.contains('missing children in list.section1'),
isTrue);
});
final module = ModuleModel(map, logger);
module.parse();
final errors = logger.errors;
- expect(errors.length, equals(1));
+ expect(errors.length, equals(2));
expect(errors.contains('"children" is not a list in list.section1: a'),
isTrue);
});
final module = ModuleModel(map, logger);
module.parse();
final errors = logger.errors;
- expect(errors.length, equals(1));
+ expect(errors.length, equals(2));
expect(errors.contains('child 1 of "children" is not a map in list.section1: []'),
isTrue);
});
final module = ModuleModel(map, logger);
module.parse();
final errors = logger.errors;
- expect(errors.length, equals(1));
+ expect(errors.length, equals(2));
expect(errors.contains('child 1 of "children" does not have "modelType" in list.section1: {}'),
isTrue);
});
final module = ModuleModel(map, logger);
module.parse();
final errors = logger.errors;
- expect(errors.length, equals(1));
+ expect(errors.length, equals(2));
expect(errors.contains('Section: unknown "modelType" in list.section1'),
isTrue);
});
'pages': [
{
'page': 'create',
+ 'title': 'Demo',
'pageType': 'create',
'sections': [
{
{
'page': 'change',
'pageType': 'change',
+ 'title': 'Demo-Change',
'sections': [
{
'sectionType': 'simpleForm',
column role_changedby: DataType.string "Geändert von" options: hidden
== page create: PageModelType.create options:
= section section1: SectionModelType.simpleForm options: [
+ textField role_name: "Rolle" options: unique notnull
+ textField role_priority: "Priorität" options:
+ textField role_active: "Aktiv" options:
allDbFields allDbFields1 options:
] # create.section1
== page change: PageModelType.change options:
= section section1: SectionModelType.simpleForm options: [
+ textField role_id: "Id" options: primary notnull unique readonly
+ textField role_name: "Rolle" options: unique notnull
+ textField role_priority: "Priorität" options:
+ textField role_active: "Aktiv" options:
allDbFields allDbFields1 options:
] # change.section1
== page list: PageModelType.list options:
column user_changedby: DataType.string "Geändert von" options: hidden
== page create: PageModelType.create options:
= section section1: SectionModelType.simpleForm options: [
+ textField user_name: "User" options: unique notnull
+ textField user_displayname: "Anzeigename" options: unique notnull
+ textField user_email: "EMail" options: unique notnull
+ textField user_role: "Rolle" options: undef
allDbFields allDbFields1 options:
] # create.section1
== page change: PageModelType.change options:
= section section1: SectionModelType.simpleForm options: [
+ textField user_id: "Id" options: primary notnull unique readonly
+ textField user_name: "User" options: unique notnull
+ textField user_displayname: "Anzeigename" options: unique notnull
+ textField user_email: "EMail" options: unique notnull
+ textField user_role: "Rolle" options: undef
allDbFields allDbFields1 options:
button set_password: label: Passwort ändern options: Passwort ändern
] # change.section1
] # password.section1
== page list: PageModelType.list options:
= section section1: SectionModelType.filterPanel options: [
- textField user_name: "User" options: unique notnull
+ textField user_name: "User" options:
textField user_role: "Rolle" options: undef
] # list.section1
== page login: PageModelType.change options: noAutoButton
= section section1: SectionModelType.simpleForm options: [
textField user: options:
textField password: options: password
- button login: label: Anmelden options: Anmelden
] # login.section1
'''));
});
column configuration_changedby: DataType.string "Geändert von" options: hidden
== page create: PageModelType.create options:
= section section1: SectionModelType.simpleForm options: [
+ textField configuration_scope: "Bereich" options: notnull
+ textField configuration_property: "Eigenschaft" options:
+ textField configuration_order: "Reihe" options:
+ textField configuration_type: "Datentyp" options:
+ textField configuration_value: "Wert" options:
+ textField configuration_description: "Beschreibung" options:
allDbFields allDbFields1 options:
] # create.section1
== page change: PageModelType.change options:
= section section1: SectionModelType.simpleForm options: [
+ textField configuration_id: "Id" options: primary notnull unique readonly
+ textField configuration_scope: "Bereich" options: notnull
+ textField configuration_property: "Eigenschaft" options:
+ textField configuration_order: "Reihe" options:
+ textField configuration_type: "Datentyp" options:
+ textField configuration_value: "Wert" options:
+ textField configuration_description: "Beschreibung" options:
allDbFields allDbFields1 options:
] # change.section1
== page list: PageModelType.list options:
expect(dump, equals('''= module menu: options:
== table menu: options:
column menu_id: DataType.int "Id" options: primary notnull unique
- column menu_name: DataType.string "Name" options: unique notnull
- column menu_icon: DataType.reference "Bild" options:
+ column menu_role: DataType.reference "Rolle" options:
+ column menu_starter: DataType.reference "Programmpunkt" options:
column menu_createdat: DataType.dateTime "Erzeugt" options: hidden null
column menu_createdby: DataType.string "Erzeugt von" options: hidden
column menu_changedat: DataType.dateTime "Geändert" options: hidden null
column menu_changedby: DataType.string "Geändert von" options: hidden
== page create: PageModelType.create options:
= section section1: SectionModelType.simpleForm options: [
+ textField menu_role: "Rolle" options:
+ textField menu_starter: "Programmpunkt" options:
allDbFields allDbFields1 options:
] # create.section1
== page change: PageModelType.change options:
= section section1: SectionModelType.simpleForm options: [
+ textField menu_id: "Id" options: primary notnull unique readonly
+ textField menu_role: "Rolle" options:
+ textField menu_starter: "Programmpunkt" options:
allDbFields allDbFields1 options:
] # change.section1
== page list: PageModelType.list options:
= section section1: SectionModelType.filterPanel options: [
- textField menu_name: "Name" options: unique notnull
+ textField menu_role: "Rolle" options:
] # list.section1
'''));
});
+ test('starter', () {
+ ModelBase.lastId = 0;
+ logger.clear();
+ final module = StarterModel(logger);
+ module.parse();
+ expect(module.fullName(), equals('starter'));
+ expect(module.widgetName(), equals('starter'));
+ final errors = logger.errors;
+ expect(errors.length, equals(0));
+ expect(module.dump(StringBuffer()).toString().length, 1377);
+
});
+});
}
import 'package:dart_bones/dart_bones.dart';
import 'package:flutter_bones/flutter_bones.dart';
-import 'package:flutter_bones/src/model/model_helper.dart';
+import 'package:flutter_bones/src/helper/url_helper.dart';
import 'package:test/test.dart';
import '../../lib/src/model/model_helper.dart' as mh;
void main() {
final logger = MemoryLogger(LEVEL_FINE);
+ final configuration =
+ Configuration('/etc/flutter_bones', 'flutter_bones', logger);
+ setUpAll(() {
+ final directory = configuration.asString('baseDirectory', section: 'test');
+ if (directory == null) {
+ logger.error('missing baseDirectory in ' + configuration.filename);
+ } else {
+ FileSync.chdir(directory);
+ }
+ });
group('sql', () {
test('exportSqlCreateTablel', () {
logger.clear();
String target = FileSync.tempDirectory('model_tool_test');
tool.modifyModule([], ['--directory=$target']);
expect(logger.errors.length, equals(0));
- expect(tool.fileCache['/tmp/model_tool_test/user/user_change_page.dart'],
- equals(bodyUserChangePage));
- expect(
+ final value =
+ tool.fileCache['/tmp/model_tool_test/user/user_change_page.dart'];
+ expect(value, equals(bodyUserChangePage));
+ final expected = 'user-create: ' +
tool.fileCache['/tmp/model_tool_test/user/user_create_page.dart']
- .length,
- equals(2756));
- expect(
- tool.fileCache['/tmp/model_tool_test/user/user_list_page.dart']
- .length,
- equals(3455));
- expect(
- tool.fileCache['/tmp/model_tool_test/configuration/configuration_create_page.dart']
- .length,
- equals(2885));
+ .length
+ .toString() +
+ ' user-list: ' +
+ tool.fileCache['/tmp/model_tool_test/user/user_list_page.dart'].length
+ .toString() +
+ ' config-create: ' +
+ tool
+ .fileCache[
+ '/tmp/model_tool_test/configuration/configuration_create_page.dart']
+ .length
+ .toString() +
+ ' config-change: ' +
+ tool
+ .fileCache[
+ '/tmp/model_tool_test/configuration/configuration_change_page.dart']
+ .length
+ .toString() +
+ ' config-list: ' +
+ tool
+ .fileCache[
+ '/tmp/model_tool_test/configuration/configuration_list_page.dart']
+ .length
+ .toString();
expect(
- tool.fileCache['/tmp/model_tool_test/configuration/configuration_change_page.dart']
- .length,
- equals(3285));
- expect(
- tool.fileCache['/tmp/model_tool_test/configuration/configuration_list_page.dart']
- .length,
- equals(3583));
+ expected,
+ equals(
+ 'user-create: 3017 user-list: 4014 config-create: 3200 config-change: 3537 config-list: 4063'));
});
test('modify-modules-overwrite-constructors', () {
logger.clear();
expect(logger.errors.length, equals(0));
expect(tool.fileCache['/tmp/model_tool_test/user/user_change_page.dart'],
equals(bodyUserChangePage));
- expect(
+ final expected = 'user-create: ' +
tool.fileCache['/tmp/model_tool_test/user/user_create_page.dart']
- .length,
- equals(2756));
- expect(
- tool.fileCache['/tmp/model_tool_test/user/user_list_page.dart']
- .length,
- equals(3455));
+ .length
+ .toString() +
+ ' user-list: ' +
+ tool.fileCache['/tmp/model_tool_test/user/user_list_page.dart'].length
+ .toString();
+ expect(expected, equals('user-create: 3017 user-list: 4014'));
+ });
+ });
+ group('create-module', () {
+ test('create-module-single', () {
+ logger.clear();
+ final helper = mh.ModelHelper();
+ final tool = ModelToolIo(helper, logger);
+ String target = FileSync.tempDirectory('model_tool_test');
+ FileSync.clearDirectory(target);
+ tool.createModule(
+ ['demo', 'admin'], ['--page-type=list', '--directory=$target']);
+ expect(logger.errors.length, equals(1));
+ final expected = tool.fileCache['/tmp/model_tool_test/demo/demo_admin_page.dart']
+ .length.toString();
+ expect(expected, equals('3974'));
+ });
+ test('create-module-all', () {
+ logger.clear();
+ final helper = mh.ModelHelper();
+ final tool = ModelToolIo(helper, logger);
+ String target = FileSync.tempDirectory('model_tool_test');
+ FileSync.clearDirectory(target);
+ tool.createModule(['demo'], ['--directory=$target']);
+ expect(logger.errors.length, equals(1));
+ final expected = 'change: ' +
+ tool.fileCache['/tmp/model_tool_test/demo/demo_change_page.dart']
+ .length
+ .toString() +
+ ' create: ' +
+ tool.fileCache['/tmp/model_tool_test/demo/demo_create_page.dart']
+ .length
+ .toString() +
+ ' list: ' +
+ tool.fileCache['/tmp/model_tool_test/demo/demo_list_page.dart'].length
+ .toString();
+ expect(expected, equals('change: 3440 create: 3017 list: 3951'));
});
});
}
-final bodyUserChangePage = '''import 'package:flutter/material.dart';
+final bodyUserChangePage = r'''import 'package:flutter/material.dart';
import '../../helper/settings.dart';
import '../../model/button_model.dart';
-import '../../widget/edit_form.dart';
+import '../../widget/dialog_bones.dart';
import '../../widget/page_controller_bones.dart';
+import '../../model/page_model.dart';
import '../application_data.dart';
import 'user_controller.dart';
import 'user_password_page.dart';
+const userChangePageModule = 'user';
+const userChangePageName = 'change';
+const userChangePageType = PageModelType.change;
//! === BeginOfGeneratedCode: Change only in areas marked as customized
-//! pageType: change
class UserChangePage extends StatefulWidget {
final ApplicationData applicationData;
final ApplicationData applicationData;
final int primaryId;
final Map initialRow;
- final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'user_change');
+ final GlobalKey<FormState> _formKey = GlobalKey<FormState>(
+ debugLabel: '$userChangePageModule-$userChangePageName');
UserController controller;
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
bottomNavigationBar: applicationData.footerBuilder().widget(controller),
- body: EditForm.editForm(
+ body: formDialog(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
/// Customize the page, e.g. modify the default widget list given by the model
void customize();
+ @override
void dispose() {
controller.dispose();
super.dispose();
@override
void initState() {
super.initState();
- controller =
- UserController(_formKey, this, 'change', context, applicationData);
+ controller = UserController(
+ _formKey, this, userChangePageName, context, applicationData);
controller.initialize();
customize();
}
@override
void customize() {
ButtonModel button = controller.page.buttonByName('set_password');
- button?.onPressed = () {
- String userName = controller.page.fieldByName('user_name').value;
- applicationData.pushCaller(controller);
- Navigator.push(
- context,
- MaterialPageRoute(
- builder: (context) => UserPasswordPage(
- primaryId, userName, applicationData, null)));
- };
+ if (applicationData.currentRolePriority > 20) {
+ if (! button.hasOption('disabled')) {
+ button.options.add('disabled');
+ }
+ } else {
+ button?.onPressed = () {
+ String userName = controller.page
+ .fieldByName('user_name')
+ .value;
+ applicationData.pushCaller(controller);
+ Navigator.push(
+ context,
+ MaterialPageRoute(
+ builder: (context) =>
+ UserPasswordPage(
+ primaryId, userName, applicationData, null)));
+ };
+ }
}
}''';
}
@override
- void writeFile(String filename, String content) {
+ bool writeFile(String filename, String content,
+ {bool mayExist, bool ensureDirectory}) {
+ bool rc = true;
fileCache[filename] = content;
- FileSync.toFile(filename, content);
+ if (ensureDirectory == null || ensureDirectory) {
+ FileSync.ensureDirectory(
+ UrlHelper.parentOf(filename, trailingSlash: false));
+ }
+ if (mayExist != null && !mayExist && FileSync.isFile(filename)) {
+ logger.error('$filename already exists');
+ rc = false;
+ } else {
+ FileSync.toFile(filename, content);
+ }
+ return rc;
}
}