import '../model/model_types.dart';
+typedef LineConverter = String Function(String input);
+
class StringHelper {
static final regExpTrue = RegExp(r'^(true|yes|t)$', caseSensitive: false);
static final regExpFalse = RegExp(r'^(false|no|f)$', caseSensitive: false);
static const locale = 'de_DE';
+ /// Copies a range of lines from [input] to the end of [output].
+ /// The range is defined by a start and an end.
+ /// The start can be defined as [startString], [startRegExp] or [startPattern].
+ /// The end can be defined as [endString], [endRegExp] or [endPattern].
+ /// [startString] and [endString] are strings that are substrings of the start/end.
+ /// [startPattern] and [endPattern] are strings representing regular
+ /// expressions defining substrings in the start/end.
+ /// [includeStart]: true: the line containing the start will be copied too.
+ /// [includeEnd]: true: the line containing the end will be copied too.
+ /// [firstIndex] is the first index of [input] to process (searching and
+ /// copying). If [firstIndex] < 0: take it from the end, e.g. -1 means the
+ /// last line of [input].
+ /// [lastIndexIncluded] is the last index to process (searching and copying).
+ /// If [lastIndexIncluded] < 0: index is relative to the end.
+ /// [lastIndexExcluded] is one below the last index to process (searching and copying).
+ /// If [lastIndexExcluded] < 0: index is relative to the end.
+ /// [converter]: null a callback function for modifying the copied lines,
+ /// e.g. (line) => line.toLowerCase()
+ /// Returns [output] (for chaining).
+ static List<String> addRangeToList(List<String> input, List<String> output,
+ {int firstIndex,
+ int lastIndexExcluded,
+ lastIndexIncluded,
+ String startString,
+ RegExp startRegExp,
+ String startPattern,
+ bool includeStart = true,
+ String endString,
+ RegExp endRegExp,
+ String endPattern,
+ bool includeEnd = true,
+ LineConverter converter}) {
+ output ??= [];
+ if (input != null) {
+ var doCopy =
+ startString == null && startRegExp == null && startPattern == null;
+ firstIndex ??= 0;
+ if (firstIndex < 0) {
+ firstIndex =
+ (firstIndex = input.length + firstIndex) < 0 ? 0 : firstIndex;
+ }
+ if (lastIndexExcluded == null) {
+ lastIndexExcluded = lastIndexIncluded == null
+ ? input.length
+ : (lastIndexIncluded < 0
+ ? input.length + lastIndexIncluded
+ : lastIndexIncluded) +
+ 1;
+ }
+ lastIndexExcluded =
+ lastIndexExcluded > input.length ? input.length : lastIndexExcluded;
+ if (startPattern != null) {
+ startRegExp = RegExp(startPattern);
+ }
+ if (endPattern != null) {
+ endRegExp = RegExp(endPattern);
+ }
+ var line;
+ while (firstIndex < lastIndexExcluded) {
+ line = input[firstIndex++];
+ if (!doCopy &&
+ includeStart &&
+ (startString != null && line.contains(startString) ||
+ startRegExp?.firstMatch(line) != null)) {
+ doCopy = true;
+ }
+ if (!includeEnd &&
+ (endString != null && line.contains(endString) ||
+ endRegExp != null && endRegExp.firstMatch(line) != null)) {
+ break;
+ }
+ if (doCopy) {
+ if (converter != null) {
+ line = converter(line);
+ }
+ output.add(line);
+ }
+ if (!doCopy &&
+ (startString != null && line.contains(startString) ||
+ startRegExp?.firstMatch(line) != null)) {
+ doCopy = true;
+ }
+ if (includeEnd &&
+ (endString != null && line.contains(endString) ||
+ endRegExp?.firstMatch(line) != null)) {
+ break;
+ }
+ }
+ }
+ return output;
+ }
+
/// Convert [value] into a string for storing in a database respecting [dataType].
static String asDatabaseString(dynamic value, DataType dataType) {
if (value == null) {
return rc;
}
+ /// Converts a [string] to camelCase with an uppercase first character.
+ static String capitalize(String string) {
+ final rc = string[0].toUpperCase() + string.substring(1);
+ return rc;
+ }
+
/// Converts a [dateTime] into a string.
/// If [dateTime] is null the current date and time is used.
/// If [sortable] is true the result is sortable (year.month.day ...).
return rc;
}
- /// Replaces all placeholders defined by [syntaxPlaceholder] or [regExpPlaceholder]
- /// in [source] and return this result.
- /// [syntaxPlaceholder] or [regExpPlaceholder] must contain a single group
- /// identifying the name of the placeholder.
- /// Example:
- /// replacePlaceholders('Hi ~user~', { "user": "joe"}, syntaxPlaceholder: r'~(\w+)~')
- /// returns "Hi Joe".
- static String replacePlaceholders(
- String source, Map<String, String> placeholders,
- {String syntaxPlaceholder, RegExp regExpPlaceholder}) {
- regExpPlaceholder ??= RegExp(syntaxPlaceholder);
- final rc =
- regExpPlaceholder.allMatches(source).fold(source, (string, match) {
- final name = match.group(1);
- final rc2 = placeholders.containsKey(name)
- ? string.replaceFirst(match.group(0), placeholders[name])
- : string;
- return rc2;
- });
- return rc;
- }
-
/// Returns null or the index of the first match of a [string]
/// or a regular expression defined by [regExp] or a string [pattern].
/// Note: exactly one of [string], [regExp] or [pattern] must be not null.
return rc;
}
+ /// Replaces all placeholders defined by [syntaxPlaceholder] or [regExpPlaceholder]
+ /// in [source] and return this result.
+ /// [syntaxPlaceholder] or [regExpPlaceholder] must contain a single group
+ /// identifying the name of the placeholder.
+ /// Example:
+ /// replacePlaceholders('Hi ~user~', { "user": "joe"}, syntaxPlaceholder: r'~(\w+)~')
+ /// returns "Hi Joe".
+ static String replacePlaceholders(
+ String source, Map<String, String> placeholders,
+ {String syntaxPlaceholder, RegExp regExpPlaceholder}) {
+ regExpPlaceholder ??= RegExp(syntaxPlaceholder);
+ final rc =
+ regExpPlaceholder.allMatches(source).fold(source, (string, match) {
+ final name = match.group(1);
+ final rc2 = placeholders.containsKey(name)
+ ? string.replaceFirst(match.group(0), placeholders[name])
+ : string;
+ return rc2;
+ });
+ return rc;
+ }
+
/// Splits a argument list into an [option] list and a true arguments list.
/// [args]: the argument list to split.
/// [options]: OUT: the options list
}
return rc;
}
-
- /// Converts a [string] to camelCase with an uppercase first character.
- static String capitalize(String string) {
- final rc = string[0].toUpperCase() + string.substring(1);
- return rc;
- }
}
--- /dev/null
+import 'package:dart_bones/dart_bones.dart';
+
+class UrlHelper {
+ static final sep = '/';
+ static final currentDirSep = '.' + sep;
+
+ /// Joins parts to a combined path.
+ /// [first]: first part
+ /// [second]: second part
+ /// [third]: third part
+ static String joinPaths(String first, String second, [String third]) {
+ final rc = StringBuffer(first);
+ var last = first;
+ if (second.isNotEmpty) {
+ if (!first.endsWith(sep)) {
+ rc.write(sep);
+ }
+ if (second.startsWith(currentDirSep)) {
+ rc.write(second.substring(2));
+ } else if (second.startsWith(sep)) {
+ rc.write(second.substring(1));
+ } else {
+ rc.write(second);
+ }
+ last = second;
+ }
+ if (third != null && third.isNotEmpty) {
+ if (!last.endsWith(sep)) {
+ rc.write(sep);
+ }
+ if (third.startsWith(currentDirSep)) {
+ rc.write(third.substring(2));
+ } else if (third.startsWith(sep)) {
+ rc.write(third.substring(1));
+ } else {
+ rc.write(third);
+ }
+ }
+ return rc.toString();
+ }
+
+ /// Returns the filename of the [path] without path.
+ /// Example: base('abc/def.txt') == 'def.txt'
+ static String nodeOf(String path) {
+ final ix = path.lastIndexOf(sep);
+ final rc = ix < 0 ? path : path.substring(ix + 1);
+ return rc;
+ }
+
+ /// Returns the parent directory of the [path].
+ /// Example: dirname('abc/def.txt') == 'abc/'
+ /// [trailingSlash]: if false the trailing slash will not be part of the result
+ static String parentOf(String path, {bool trailingSlash: true}) {
+ final ix = path.lastIndexOf(sep);
+ final rc = ix < 0 ? '' : path.substring(0, ix + (trailingSlash ? 1 : 0));
+ return rc;
+ }
+}
AllDbFieldsModel(SectionModel section, PageModel page, BaseLogger logger)
: super(section, page, ModelTypeBones.allDbFields, null, logger);
- /// Returns the name including the names of the parent
+ /// Returns the name including the names of the parents.
@override
String fullName() => '${section.name}.$name';
return stringBuffer;
}
- /// Returns the name including the names of the parent
+ /// Returns the name including the names of the parents.
@override
String fullName() => '${section?.name}.$name';
return stringBuffer;
}
- /// Returns the name including the names of the parent
+ /// Returns the name including the names of the parents.
@override
String fullName() => '${table.name}.$name';
return stringBuffer;
}
- /// Returns the name including the names of the parent
+ /// Returns the name including the names of the parents.
@override
String fullName() => '${section.name}.$name';
}
}
- /// Returns the name including the names of the parent
+ /// Returns the name including the names of the parents.
@override
String fullName() => '${page.name}.$name';
});
}
- /// Returns the name including the names of the parent
+ /// Returns the name including the names of the parents.
String fullName();
/// Tests whether a given [option] is part of [options].
/// Returns the names of the modules.
List<String> moduleNames() =>
['configuration', 'menu', 'role', 'starter', 'user'];
-
}
--- /dev/null
+import 'package:dart_bones/dart_bones.dart';
+
+import '../helper/string_helper.dart';
+import '../helper/url_helper.dart';
+import 'model_helper.dart';
+import 'module_model.dart';
+import 'page_model.dart';
+
+/// Implements tools for development of flutter_bones applications.
+/// This class is is "web friendly", it does not depend directly on package:io.
+abstract class ModelTool {
+ final BaseLogger logger;
+ final ModelHelper modelHelper;
+ ModelTool(this.modelHelper, this.logger);
+
+ /// Ensures that the [directory] exists. If not it will be created.
+ void ensureDirectory(String directory);
+
+ void exportSql(List<String> args, List<String> options) {
+ String directory;
+ String value;
+ for (var opt in options) {
+ value = StringUtils.stringOption('directory', 'd', opt);
+ if (value != null) {
+ directory = value;
+ continue;
+ }
+ logger.error('unknown option: $opt');
+ }
+ directory ??= 'data';
+ final dirDDL = UrlHelper.joinPaths(directory, 'ddl');
+ final dirREST = UrlHelper.joinPaths(directory, 'rest');
+ ensureDirectory(dirDDL);
+ ensureDirectory(dirREST);
+ if (args.isEmpty) {
+ args = modelHelper.moduleNames();
+ }
+ while (args.isNotEmpty) {
+ final name = args[0];
+ args.removeAt(0);
+ ModuleModel module = modelHelper.moduleByName(name, logger);
+ if (module != null) {
+ module.parse();
+ var filename = UrlHelper.joinPaths(dirDDL, '$name.sql');
+ writeFile(filename, module.exportSqlCreateTable());
+ print('exported: $filename');
+ filename = UrlHelper.joinPaths(dirREST, '$name.yaml');
+ writeFile(filename, module.exportSqlBackend());
+ print('exported: $filename');
+ }
+ }
+ }
+
+ void modifyModule(List<String> args, List<String> options) {
+ String baseDirectory;
+ String value;
+ PageModelType handledPageType;
+ bool overwriteConstructor = false;
+ for (var opt in options) {
+ value = StringUtils.stringOption('directory', 'd', opt);
+ if (value != null) {
+ baseDirectory = value;
+ continue;
+ }
+ value = StringUtils.stringOption('directory', 'd', 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;
+ }
+ continue;
+ }
+ var boolValue =
+ StringUtils.boolOption('overwrite-constructors', 'c', opt);
+ if (boolValue != Bool.UNDEF) {
+ overwriteConstructor = boolValue == Bool.TRUE;
+ continue;
+ }
+ logger.error('unknown option: $opt');
+ }
+ baseDirectory ??= 'lib/src/model';
+ if (args.isEmpty) {
+ args = modelHelper.moduleNames();
+ }
+ final regExpPageType =
+ RegExp(r'const ([a-z]+)([A-Z][a-z]+)PageType = PageModelType\.(\w+)');
+ for (var name in args) {
+ if (name == 'role') {
+ logger.log('module "role" ignored.');
+ }
+ final sourceDir = 'lib/src/page/$name';
+ final files = pathOfDirectory(sourceDir);
+ final pathSafe = safeDirectory(name);
+ for (var file in files) {
+ if (file.endsWith('_controller.dart')) {
+ continue;
+ }
+ final lines = readFile(file);
+ PageModelType pageType;
+ RegExpMatch matcher;
+ final ix =
+ StringHelper.listIndexOf(lines, string: 'PageType = PageModelType');
+ if (ix == null) {
+ logger.log('missing pageType hint in $file');
+ continue;
+ } else {
+ matcher = regExpPageType.firstMatch(lines[ix]);
+ if (matcher == null) {
+ logger.error('cannot recognize page type: ${lines[ix]} in $file');
+ continue;
+ }
+ }
+ final moduleCapital = StringHelper.capitalize(matcher.group(1));
+ final pageNameCapital = matcher.group(2);
+ final pageTypeLower = matcher.group(3);
+ pageType = StringUtils.stringToEnum<PageModelType>(
+ pageTypeLower, PageModelType.values);
+ if (pageType == null) {
+ logger.error('cannot recognize page type: ${lines[ix]} in $file');
+ continue;
+ }
+ if (handledPageType != null && pageType != handledPageType) {
+ continue;
+ }
+ final fnTemplate = UrlHelper.joinPaths(
+ UrlHelper.parentOf(file).replaceAll(name, 'role'),
+ 'role_${StringUtils.enumToString(pageType)}_page.dart');
+ final templateLines = readFile(fnTemplate);
+ if (templateLines.isEmpty) {
+ 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');
+ modifyPage(
+ name,
+ pageType,
+ lines,
+ templateLines,
+ converter,
+ UrlHelper.joinPaths(baseDirectory, name, UrlHelper.nodeOf(file)),
+ overwriteConstructor,
+ pathSafe);
+ }
+ }
+ }
+
+ void modifyPage(
+ String module,
+ PageModelType type,
+ List<String> lines,
+ List<String> templateLines,
+ Function(String) converter,
+ String filename,
+ bool overwriteConstructors,
+ String pathSafe) {
+ final moduleCapital = StringHelper.capitalize(module);
+ ensureDirectory(UrlHelper.parentOf(filename, trailingSlash: false));
+ final output = <String>[];
+ int ix;
+ if (overwriteConstructors) {
+ if (StringHelper.listIndexOf(lines, string: 'EndOfGeneratedCode') !=
+ null) {
+ StringHelper.addRangeToList(lines, output,
+ endString: 'BeginOfGeneratedCode', includeEnd: false);
+ } else {
+ StringHelper.addRangeToList(templateLines, output,
+ endString: 'BeginOfGeneratedCode',
+ includeEnd: false,
+ converter: converter);
+ }
+ StringHelper.addRangeToList(templateLines, output,
+ startString: 'BeginOfGeneratedCode',
+ endString: 'EndOfGeneratedCode',
+ converter: converter);
+ StringHelper.addRangeToList(lines, output,
+ startString: 'EndOfGeneratedCode', includeStart: false);
+ ix = StringHelper.listIndexOf(lines, string: 'EndOfGeneratedCode');
+ // -3: possible empty lines at the end
+ if (ix == null || ix > lines.length - 3) {
+ StringHelper.addRangeToList(templateLines, output,
+ startString: 'EndOfGeneratedCode',
+ includeStart: false,
+ converter: converter);
+ }
+ } else {
+ StringHelper.addRangeToList(lines, output,
+ endString: 'BeginOfGeneratedCode', includeEnd: false);
+ StringHelper.addRangeToList(templateLines, output,
+ startString: 'BeginOfGeneratedCode',
+ endString: 'BeginOfCustomizedVars1',
+ converter: converter);
+ StringHelper.addRangeToList(lines, output,
+ startString: 'BeginOfCustomizedVars1',
+ includeStart: false,
+ endString: 'EndOfCustomizedVars1',
+ includeEnd: false);
+ StringHelper.addRangeToList(templateLines, output,
+ startString: 'EndOfCustomizedVars1',
+ endString: 'BeginOfConstructor1',
+ converter: converter);
+ StringHelper.addRangeToList(lines, output,
+ startString: 'BeginOfConstructor1',
+ includeStart: false,
+ endString: 'EndOfConstructor1',
+ includeEnd: false);
+ StringHelper.addRangeToList(templateLines, output,
+ startString: 'EndOfConstructor1',
+ endString: 'BeginOfCall',
+ converter: converter);
+ StringHelper.addRangeToList(lines, output,
+ startString: 'BeginOfCall',
+ includeStart: false,
+ endString: 'EndOfCall',
+ includeEnd: false);
+ StringHelper.addRangeToList(templateLines, output,
+ startString: 'EndOfCall',
+ endString: 'BeginOfCustomizedVars2',
+ converter: converter);
+ StringHelper.addRangeToList(lines, output,
+ startString: 'BeginOfCustomizedVars2',
+ includeStart: false,
+ endString: 'EndOfCustomizedVars2',
+ includeEnd: false);
+ StringHelper.addRangeToList(templateLines, output,
+ startString: 'EndOfCustomizedVars2',
+ endString: 'BeginOfConstructor2',
+ converter: converter);
+ StringHelper.addRangeToList(lines, output,
+ startString: 'BeginOfConstructor2',
+ includeStart: false,
+ endString: 'EndOfConstructor2',
+ includeEnd: false);
+ StringHelper.addRangeToList(templateLines, output,
+ startString: 'EndOfConstructor2',
+ endString: 'EndOfGeneratedCode',
+ converter: converter);
+ StringHelper.addRangeToList(lines, output,
+ startString: 'EndOfGeneratedCode', includeStart: false);
+ }
+ ensureDirectory(pathSafe);
+ final fnSafe = UrlHelper.joinPaths(pathSafe, UrlHelper.nodeOf(filename));
+ logger.log('saving to $fnSafe');
+ writeFile(fnSafe, lines.join('\n'));
+ logger.log('writing $filename lines: ${output.length}');
+ writeFile(filename, output.join('\n'));
+ }
+
+ List<String> pathOfDirectory(String path);
+
+ /// Reads a [file] into a list of lines.
+ List<String> readFile(String file);
+
+ void run(List<String> args) {
+ final mode = args[0];
+ final options = <String>[];
+ args = StringHelper.splitArgv(args.sublist(1), options);
+ switch (mode) {
+ case 'export-sql':
+ exportSql(args, options);
+ break;
+ case 'modify-module':
+ modifyModule(args, options);
+ break;
+ default:
+ logger.error('unknown mode: $mode');
+ break;
+ }
+ }
+
+ /// Returns the unique name derived from [name] of a directory to save files.
+ String safeDirectory(String name);
+
+ void usage(String error) {
+ print('''usage: main <mode> [<args>]
+<mode>:
+ 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.
+ 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.
+Examples:
+main create-sql role user -d/tmp
+main create-sql --directory=/opt/sql-data
+main modify-pages role --customize-constructors
+main modify-pages --page-type=list
+''');
+ }
+
+ /// Writes a [content] to a file named [filename].
+ void writeFile(String filename, String content);
+}
buffer.write('\n WHERE ${table.name}_id=:${table.name}_id;"\n');
}
- /// Returns the name including the names of the parent
+ /// Returns the name including the names of the parents.
@override
String fullName() => name;
return rc;
}
- /// Returns the name including the names of the parent
+ /// Returns the name including the names of the parents.
@override
String fullName() => '${module.name}.$name';
return rc;
}
- /// Parses the [map]and stores the data in the instance.
+ /// Parses the [map] and stores the data in the instance.
void parse(Map map) {
super.parseBase(map, nameLabel: 'page', required: true);
if (name == null) {
return stringBuffer;
}
- /// Returns the name including the names of the parent
+ /// Returns the name including the names of the parents.
@override
String fullName() =>
section == null ? '${page.name}.$name' : '${section.name}.$name';
'Section: unknown "modelType" ${child["modelType"]} in ${fullName()}');
break;
}
- if (model != null){
+ if (model != null) {
model.parse(child);
}
}
'sectionType', map, SectionModelType.values);
checkSuperfluousAttributes(
map,
- 'buttons children fields modelType section options sectionType'
+ 'buttonBar children fields modelType section options sectionType'
.split(' '));
checkOptionsByRegExpr(regExprOptions);
'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 parent
+ /// Returns the name including the names of the parents.
@override
String fullName() => name;
{
'modelType': 'allDbFields',
},
- ]
+ ],
+ 'buttonBar': [
+ {
+ 'modelType': 'button',
+ 'buttonType': 'custom',
+ 'name': 'new',
+ 'label': 'Neues Startmenü',
+ 'toolTip': 'Erzeugen eines neuen Startmenüs'
+ },
+ ],
}
]
},
MenuModel(BaseLogger logger) : super(mapMenu, logger);
- /// Returns the name including the names of the parent
+ /// Returns the name including the names of the parents.
@override
String fullName() => name;
]
};
- /// Returns the name including the names of the parent
+ /// Returns the name including the names of the parents.
@override
String fullName() => 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 parent
+ /// Returns the name including the names of the parents.
@override
String fullName() => name;
'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'
+ },
+ ],
}
]
},
'options': 'password',
'validators': 'required',
},
+ ],
+ 'buttonBar': [
{
'modelType': 'button',
'buttonType': 'custom',
UserModel(BaseLogger logger) : super(mapUser, logger);
- /// Returns the name including the names of the parent
+ /// Returns the name including the names of the parents.
@override
String fullName() => name;
return stringBuffer;
}
- /// Returns the name including the names of the parent
+ /// Returns the name including the names of the parents.
@override
String fullName() => '${module.name}.$name';
TextModel(SectionModel section, PageModel page, BaseLogger logger)
: super(section, page, ModelTypeBones.text, null, logger);
- /// Returns the name including the names of the parent
+ /// Returns the name including the names of the parents.
@override
String fullName() => '${section.name}.$name';
import '../widget/page_controller_bones.dart';
abstract class FooterBones {
- List<Widget> widgets(PageControllerBones controller);
+ Widget widget(PageControllerBones controller);
}
/// Data class for storing parameter to build a page.
import '../../helper/settings.dart';
import '../../widget/edit_form.dart';
import '../../widget/page_controller_bones.dart';
+import '../../model/page_model.dart';
import '../application_data.dart';
import 'configuration_controller.dart';
+const configurationChangePageModule = 'configuration';
+const configurationChangePageName = 'change';
+const configurationChangePageType = PageModelType.change;
+//! === BeginOfGeneratedCode: Change only in areas marked as customized
+
class ConfigurationChangePage extends StatefulWidget {
final ApplicationData applicationData;
final Map initialRow;
final logger = Settings().logger;
final int primaryId;
- //ConfigurationChangePageState lastState;
-
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
ConfigurationChangePage(this.primaryId, this.applicationData, this.initialRow,
{Key key})
: super(key: key);
+ //! === EndOfConstructor1 ===
+
@override
ConfigurationChangePageState createState() {
+ //! === BeginOfCall ===
final rc =
- ConfigurationChangePageState(primaryId, applicationData, initialRow);
+ ConfigurationChangePageStateCustomized(primaryId, applicationData, initialRow);
+ //! === EndOfCall ===
/// for unittests:
applicationData.lastModuleState = rc;
}
}
-class ConfigurationChangePageState extends State<ConfigurationChangePage>
+abstract class ConfigurationChangePageState extends State<ConfigurationChangePage>
implements RedrawPage {
final ApplicationData applicationData;
final int primaryId;
final Map initialRow;
final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'configuration_change');
+ GlobalKey<FormState>(debugLabel: '$configurationChangePageModule-$configurationChangePageName');
ConfigurationController controller;
- ConfigurationChangePageState(
- this.primaryId, this.applicationData, this.initialRow);
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
+ ConfigurationChangePageState(this.primaryId, this.applicationData, this.initialRow);
+
+ //! === EndOfConstructor2 ===
@override
Widget build(BuildContext context) {
- // controller.buildWidgetList() is called in editForm
+ controller.beginOfBuild(context);
+ //! === BeginOfScaffold ===
return Scaffold(
- appBar: applicationData.appBarBuilder('Konfiguration ändern'),
+ appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
body: EditForm.editForm(
key: _formKey,
pageController: controller,
primaryId: primaryId,
initialRow: initialRow,
));
+ //! === EndOfScaffold ===
}
- @override
- void initState() {
- super.initState();
- controller = ConfigurationController(
- _formKey, this, 'change', context, applicationData);
- controller.initialize();
- }
+ /// 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, 'change', context, applicationData);
+ controller.initialize();
+ customize();
+ }
+
@override
void redraw(RedrawReason reason,
{String customString, RedrawCallbackFunctionSimple callback}) {
});
}
}
+
+//! === EndOfGeneratedCode: Below you can change manually:
+
+class ConfigurationChangePageStateCustomized
+ extends ConfigurationChangePageState {
+ ConfigurationChangePageStateCustomized(
+ int primaryId, ApplicationData applicationData, Map initialRow)
+ : super(primaryId, applicationData, initialRow);
+
+ @override
+ void customize() {
+ // ToDo: write code if needed
+ }
+}
import '../../helper/settings.dart';
import '../../widget/edit_form.dart';
import '../../widget/page_controller_bones.dart';
+import '../../model/page_model.dart';
import '../application_data.dart';
import 'configuration_controller.dart';
+const configurationCreatePageModule = 'configuration';
+const configurationCreatePageName = 'create';
+const configurationCreatePageType = PageModelType.create;
+//! === BeginOfGeneratedCode: Change only in areas marked as customized
+
class ConfigurationCreatePage extends StatefulWidget {
final ApplicationData applicationData;
final logger = Settings().logger;
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
ConfigurationCreatePage(this.applicationData, {Key key}) : super(key: key);
+ //! === EndOfConstructor1 ===
+
@override
ConfigurationCreatePageState createState() {
- final rc = ConfigurationCreatePageState(applicationData);
+ //! === BeginOfCall ===
+ final rc = ConfigurationCreatePageStateCustomized(applicationData);
+ //! === EndOfCall ===
/// for unittests:
applicationData.lastModuleState = rc;
}
}
-class ConfigurationCreatePageState extends State<ConfigurationCreatePage>
+abstract class ConfigurationCreatePageState extends State<ConfigurationCreatePage>
implements RedrawPage {
final ApplicationData applicationData;
final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'configuration_create');
+ GlobalKey<FormState>(debugLabel: '$configurationCreatePageModule-$configurationCreatePageName');
ConfigurationController controller;
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
ConfigurationCreatePageState(this.applicationData);
+ //! === EndOfConstructor2 ===
+
@override
Widget build(BuildContext context) {
- controller.beginOfBuild(context);
+ controller?.beginOfBuild(context);
+ //! === BeginOfScaffold ===
return Scaffold(
- appBar: applicationData.appBarBuilder('Neue Konfiguration'),
+ appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
body: EditForm.editForm(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
));
+ //! === 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, 'create', context, applicationData);
+ controller =
+ ConfigurationController(_formKey, this, configurationCreatePageName, context, applicationData);
controller.initialize();
+ customize();
}
@override
});
}
}
+
+//! === EndOfGeneratedCode: Below you can change manually:
+
+class ConfigurationCreatePageStateCustomized
+ extends ConfigurationCreatePageState {
+ ConfigurationCreatePageStateCustomized(ApplicationData applicationData)
+ : super(applicationData);
+
+ @override
+ void customize() {
+ // ToDo: write code if needed
+ }
+}
import 'package:flutter/material.dart';
+import 'package:flutter_bones/src/widget/view.dart';
import '../../model/page_model.dart';
import '../../widget/list_form.dart';
import '../application_data.dart';
import 'configuration_controller.dart';
+const configurationListPageModule = 'configuration';
+const configurationListPageName = 'list';
+const configurationListPageType = PageModelType.list;
+//! === BeginOfGeneratedCode: Change only in areas marked as customized
+
class ConfigurationListPage extends StatefulWidget {
final ApplicationData applicationData;
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
ConfigurationListPage(this.applicationData, {Key key}) : super(key: key);
+ //! === EndOfConstructor1 ===
+
@override
ConfigurationListPageState createState() {
- // ConfigurationListPageState.setPageData(pageData);
- final rc = ConfigurationListPageState(applicationData);
+ //! === BeginOfCall ===
+ final rc = ConfigurationListPageStateCustomized(applicationData);
+ //! === EndOfCall ===
/// for unittests:
applicationData.lastModuleState = rc;
}
}
-class ConfigurationListPageState extends State<ConfigurationListPage>
+abstract class ConfigurationListPageState extends State<ConfigurationListPage>
implements RedrawPage {
final ApplicationData applicationData;
final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'configuration_list');
+ GlobalKey<FormState>(debugLabel: '$configurationListPageModule-$configurationListPageName');
Iterable<dynamic> rowsDeprecated;
ConfigurationController controller;
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
ConfigurationListPageState(this.applicationData);
+ //! === EndOfConstructor2 ===
+
@override
Widget build(BuildContext context) {
controller.beginOfBuild(context);
+
+ //! === BeginOfScaffold ===
return Scaffold(
- appBar: applicationData.appBarBuilder('Konfigurationen'),
+ appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
body: ListForm.listForm(
key: _formKey,
configuration: applicationData.configuration,
showEditIcon: true,
pageController: controller,
buttons: <Widget>[
- ButtonBar(alignment: MainAxisAlignment.center, children: [
- controller.searchButton(),
- RaisedButton(
- child: Text('Neue Konfiguration'),
- onPressed: () {
- controller.goTo(pageType: PageModelType.create);
- },
- ),
- ]),
+ ButtonBar(
+ alignment: MainAxisAlignment.spaceBetween,
+ children: View().modelsToWidgets(
+ controller.page.sections[0].buttonBar, controller),
+ )
],
filters: controller.modelList,
errorMessage:
applicationData.lastErrorMessage(controller.page.fullName()),
),
);
+ //! === EndOfScaffold ===
}
+ /// Customize the page, e.g. modify the default widget list given by the model
+ void customize();
+
@override
void initState() {
super.initState();
- controller = ConfigurationController(
- _formKey, this, 'list', context, applicationData, redrawCallback:
- (RedrawReason reason,
- {String customString, RedrawCallbackFunctionSimple callback}) {
- switch (reason) {
- case RedrawReason.fetchList:
- controller.buildRows();
- break;
- case RedrawReason.callback:
- callback(RedrawReason.custom, customString: customString);
- setState(() {});
- break;
- default:
- setState(() {});
- break;
- }
- });
+ controller =
+ ConfigurationController(_formKey, this, configurationListPageName, context, applicationData);
controller.initialize();
+ customize();
}
@override
});
}
}
+
+//! === EndOfGeneratedCode: Below you can change manually:
+
+class ConfigurationListPageStateCustomized extends ConfigurationListPageState {
+ ConfigurationListPageStateCustomized(ApplicationData applicationData)
+ : super(applicationData);
+
+ @override
+ void customize() {
+ final button = controller.page.buttonByName('new');
+ button.onPressed = () {
+ controller.goTo(pageType: PageModelType.create);
+ };
+ }
+}
import '../../helper/settings.dart';
import '../../widget/edit_form.dart';
import '../../widget/page_controller_bones.dart';
+import '../../model/page_model.dart';
import '../application_data.dart';
import 'menu_controller.dart';
+const menuChangePageModule = 'menu';
+const menuChangePageName = 'change';
+const menuChangePageType = PageModelType.change;
+//! === BeginOfGeneratedCode: Change only in areas marked as customized
+
class MenuChangePage extends StatefulWidget {
final ApplicationData applicationData;
final Map initialRow;
final logger = Settings().logger;
final int primaryId;
- //MenuChangePageState lastState;
-
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
MenuChangePage(this.primaryId, this.applicationData, this.initialRow,
{Key key})
: super(key: key);
+ //! === EndOfConstructor1 ===
+
@override
MenuChangePageState createState() {
- final rc = MenuChangePageState(primaryId, applicationData, initialRow);
+ //! === BeginOfCall ===
+ final rc =
+ MenuChangePageStateCustomized(primaryId, applicationData, initialRow);
+ //! === EndOfCall ===
/// for unittests:
applicationData.lastModuleState = rc;
}
}
-class MenuChangePageState extends State<MenuChangePage> implements RedrawPage {
+abstract class MenuChangePageState extends State<MenuChangePage>
+ implements RedrawPage {
final ApplicationData applicationData;
final int primaryId;
final Map initialRow;
final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'menu_change');
+ GlobalKey<FormState>(debugLabel: '$menuChangePageModule-$menuChangePageName');
MenuController controller;
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
MenuChangePageState(this.primaryId, this.applicationData, this.initialRow);
+ //! === EndOfConstructor2 ===
+
@override
Widget build(BuildContext context) {
controller.beginOfBuild(context);
- // controller.buildWidgetList() is called in editForm
+ //! === BeginOfScaffold ===
return Scaffold(
- appBar: applicationData.appBarBuilder('Startmenü ändern'),
+ appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
body: EditForm.editForm(
key: _formKey,
pageController: controller,
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,
- 'change',
- context,
- applicationData,
- );
+ controller =
+ MenuController(_formKey, this, 'change', context, applicationData);
controller.initialize();
+ customize();
}
@override
});
}
}
+
+//! === EndOfGeneratedCode: Below you can change manually:
+
+class MenuChangePageStateCustomized extends MenuChangePageState {
+ MenuChangePageStateCustomized(
+ int primaryId, ApplicationData applicationData, Map initialRow)
+ : super(primaryId, applicationData, initialRow);
+
+ @override
+ void customize() {
+ // ToDo: write code if needed
+ }
+}
import '../../helper/settings.dart';
import '../../widget/edit_form.dart';
import '../../widget/page_controller_bones.dart';
+import '../../model/page_model.dart';
import '../application_data.dart';
import 'menu_controller.dart';
+const menuCreatePageModule = 'menu';
+const menuCreatePageName = 'create';
+const menuCreatePageType = PageModelType.create;
+//! === BeginOfGeneratedCode: Change only in areas marked as customized
+
class MenuCreatePage extends StatefulWidget {
final ApplicationData applicationData;
final logger = Settings().logger;
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
MenuCreatePage(this.applicationData, {Key key}) : super(key: key);
+ //! === EndOfConstructor1 ===
+
@override
MenuCreatePageState createState() {
- final rc = MenuCreatePageState(applicationData);
+ //! === BeginOfCall ===
+ final rc = MenuCreatePageStateCustomized(applicationData);
+ //! === EndOfCall ===
/// for unittests:
applicationData.lastModuleState = rc;
}
}
-class MenuCreatePageState extends State<MenuCreatePage> implements RedrawPage {
+abstract class MenuCreatePageState extends State<MenuCreatePage>
+ implements RedrawPage {
final ApplicationData applicationData;
final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'menu_create');
+ GlobalKey<FormState>(debugLabel: '$menuCreatePageModule-$menuCreatePageName');
MenuController controller;
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
MenuCreatePageState(this.applicationData);
+ //! === EndOfConstructor2 ===
+
@override
Widget build(BuildContext context) {
- controller.beginOfBuild(context);
+ controller?.beginOfBuild(context);
+ //! === BeginOfScaffold ===
return Scaffold(
- appBar: applicationData.appBarBuilder('Neues Startmenü'),
+ appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
body: EditForm.editForm(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
));
+ //! === 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, 'create', context, applicationData);
+ MenuController(_formKey, this, menuCreatePageName, context, applicationData);
controller.initialize();
+ customize();
}
@override
});
}
}
+
+//! === EndOfGeneratedCode: Below you can change manually:
+
+class MenuCreatePageStateCustomized extends MenuCreatePageState {
+ MenuCreatePageStateCustomized(ApplicationData applicationData)
+ : super(applicationData);
+
+ @override
+ void customize() {
+ // ToDo: write code if needed
+ }
+}
import 'package:flutter/material.dart';
+import 'package:flutter_bones/flutter_bones.dart';
import '../../model/page_model.dart';
import '../../widget/list_form.dart';
import '../application_data.dart';
import 'menu_controller.dart';
+const menuListPageModule = 'menu';
+const menuListPageName = 'list';
+const menuListPageType = PageModelType.list;
+//! === BeginOfGeneratedCode: Change only in areas marked as customized
+
class MenuListPage extends StatefulWidget {
final ApplicationData applicationData;
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
MenuListPage(this.applicationData, {Key key}) : super(key: key);
+ //! === EndOfConstructor1 ===
+
@override
MenuListPageState createState() {
- // MenuListPageState.setPageData(pageData);
- final rc = MenuListPageState(applicationData);
+ //! === BeginOfCall ===
+ final rc = MenuListPageStateCustomized(applicationData);
+ //! === EndOfCall ===
/// for unittests:
applicationData.lastModuleState = rc;
}
}
-class MenuListPageState extends State<MenuListPage> implements RedrawPage {
+abstract class MenuListPageState extends State<MenuListPage>
+ implements RedrawPage {
final ApplicationData applicationData;
final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'menu_list');
+ GlobalKey<FormState>(debugLabel: '$menuListPageModule-$menuListPageName');
Iterable<dynamic> rowsDeprecated;
MenuController controller;
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
MenuListPageState(this.applicationData);
+ //! === EndOfConstructor2 ===
+
@override
Widget build(BuildContext context) {
controller.beginOfBuild(context);
+
+ //! === BeginOfScaffold ===
return Scaffold(
- appBar: applicationData.appBarBuilder('Startmenüs'),
+ appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
body: ListForm.listForm(
key: _formKey,
configuration: applicationData.configuration,
showEditIcon: true,
pageController: controller,
buttons: <Widget>[
- ButtonBar(alignment: MainAxisAlignment.center, children: [
- controller.searchButton(),
- RaisedButton(
- child: Text('Neues Startmenü'),
- onPressed: () {
- controller.goTo(pageType: PageModelType.create);
- },
- ),
- ]),
+ ButtonBar(
+ alignment: MainAxisAlignment.spaceBetween,
+ children: View().modelsToWidgets(
+ controller.page.sections[0].buttonBar, controller),
+ )
],
filters: controller.modelList,
errorMessage:
applicationData.lastErrorMessage(controller.page.fullName()),
),
);
+ //! === EndOfScaffold ===
}
+ /// Customize the page, e.g. modify the default widget list given by the model
+ void customize();
+
@override
void initState() {
super.initState();
controller =
- MenuController(_formKey, this, 'list', context, applicationData);
+ MenuController(_formKey, this, menuListPageName, context, applicationData);
controller.initialize();
+ customize();
}
@override
});
}
}
+
+//! === EndOfGeneratedCode: Below you can change manually:
+
+class MenuListPageStateCustomized extends MenuListPageState {
+ MenuListPageStateCustomized(ApplicationData applicationData)
+ : super(applicationData);
+
+ @override
+ void customize() {
+ final button = controller.page.buttonByName('new');
+ button.onPressed = () {
+ controller.goTo(pageType: PageModelType.create);
+ };
+ }
+}
import '../../widget/edit_form.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;
//! === BeginOfGeneratedCode: Change only in areas marked as customized
-//! pageType: change
class RoleChangePage extends StatefulWidget {
final ApplicationData applicationData;
final int primaryId;
final Map initialRow;
final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'role_change');
+ GlobalKey<FormState>(debugLabel: '$roleChangePageModule-$roleChangePageName');
RoleController controller;
return Scaffold(
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
- persistentFooterButtons:
- applicationData.footerBuilder().widgets(controller),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
body: EditForm.editForm(
key: _formKey,
pageController: controller,
/// Customize the page, e.g. modify the default widget list given by the model
void customize();
+ @override
void dispose() {
controller.dispose();
super.dispose();
//! === EndOfGeneratedCode: Below you can change manually:
class RoleChangePageStateCustomized extends RoleChangePageState {
- RoleChangePageStateCustomized(int primaryId, ApplicationData applicationData,
- Map initialRow)
+ RoleChangePageStateCustomized(
+ int primaryId, ApplicationData applicationData, Map initialRow)
: super(primaryId, applicationData, initialRow);
@override
import '../../helper/settings.dart';
import '../../widget/edit_form.dart';
import '../../widget/page_controller_bones.dart';
+import '../../model/page_model.dart';
import '../application_data.dart';
import 'role_controller.dart';
+const roleCreatePageModule = 'role';
+const roleCreatePageName = 'create';
+const roleCreatePageType = PageModelType.create;
//! === BeginOfGeneratedCode: Change only in areas marked as customized
-//! pageType: change
class RoleCreatePage extends StatefulWidget {
final ApplicationData applicationData;
final ApplicationData applicationData;
final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'role_create');
+ GlobalKey<FormState>(debugLabel: '$roleCreatePageModule-$roleCreatePageName');
RoleController controller;
return Scaffold(
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
- persistentFooterButtons:
- applicationData.footerBuilder().widgets(controller),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
body: EditForm.editForm(
key: _formKey,
pageController: controller,
/// 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, 'create', context, applicationData);
+ RoleController(_formKey, this, roleCreatePageName, context, applicationData);
controller.initialize();
customize();
}
import 'package:flutter/material.dart';
-import 'package:flutter_bones/flutter_bones.dart';
import '../../model/page_model.dart';
import '../../widget/list_form.dart';
import '../../widget/page_controller_bones.dart';
+import '../../widget/view.dart';
import '../application_data.dart';
import 'role_controller.dart';
+const roleListPageModule = 'role';
+const roleListPageName = 'list';
+const roleListPageType = PageModelType.list;
//! === BeginOfGeneratedCode: Change only in areas marked as customized
-//! pageType: change
class RoleListPage extends StatefulWidget {
final ApplicationData applicationData;
final ApplicationData applicationData;
final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'role_list');
+ GlobalKey<FormState>(debugLabel: '$roleListPageModule-$roleListPageName');
Iterable<dynamic> rowsDeprecated;
RoleController controller;
return Scaffold(
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
- persistentFooterButtons:
- applicationData.footerBuilder().widgets(controller),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
body: ListForm.listForm(
key: _formKey,
configuration: applicationData.configuration,
showEditIcon: true,
pageController: controller,
buttons: <Widget>[
- ButtonBar(alignment: MainAxisAlignment.center,
- children: View().modelsToWidgets(controller.page.sections[0].buttonBar, controller),
- )],
+ ButtonBar(
+ alignment: MainAxisAlignment.spaceBetween,
+ children: View().modelsToWidgets(
+ controller.page.sections[0].buttonBar, controller),
+ )
+ ],
filters: controller.modelList,
errorMessage:
applicationData.lastErrorMessage(controller.page.fullName()),
void initState() {
super.initState();
controller =
- RoleController(_formKey, this, 'list', context, applicationData);
+ RoleController(_formKey, this, roleListPageName, context, applicationData);
controller.initialize();
customize();
}
button.onPressed = () {
controller.goTo(pageType: PageModelType.create);
};
- controller.modelList.addModel(button.name, button);
}
}
import '../../helper/settings.dart';
import '../../widget/edit_form.dart';
import '../../widget/page_controller_bones.dart';
+import '../../model/page_model.dart';
import '../application_data.dart';
import 'starter_controller.dart';
+const starterChangePageModule = 'starter';
+const starterChangePageName = 'change';
+const starterChangePageType = PageModelType.change;
+//! === BeginOfGeneratedCode: Change only in areas marked as customized
+
class StarterChangePage extends StatefulWidget {
final ApplicationData applicationData;
final Map initialRow;
final logger = Settings().logger;
final int primaryId;
- //StarterChangePageState lastState;
-
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
StarterChangePage(this.primaryId, this.applicationData, this.initialRow,
{Key key})
: super(key: key);
+ //! === EndOfConstructor1 ===
+
@override
StarterChangePageState createState() {
- final rc = StarterChangePageState(primaryId, applicationData, initialRow);
+ //! === BeginOfCall ===
+ final rc =
+ StarterChangePageStateCustomized(primaryId, applicationData, initialRow);
+ //! === EndOfCall ===
/// for unittests:
applicationData.lastModuleState = rc;
}
}
-class StarterChangePageState extends State<StarterChangePage>
+abstract class StarterChangePageState extends State<StarterChangePage>
implements RedrawPage {
final ApplicationData applicationData;
final int primaryId;
StarterController controller;
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
StarterChangePageState(this.primaryId, this.applicationData, this.initialRow);
+ //! === EndOfConstructor2 ===
+
@override
Widget build(BuildContext context) {
controller.beginOfBuild(context);
- // controller.buildWidgetList() is called in editForm
+ //! === BeginOfScaffold ===
return Scaffold(
- appBar: applicationData.appBarBuilder('Startmenü ändern'),
+ appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
body: EditForm.editForm(
key: _formKey,
pageController: controller,
primaryId: primaryId,
initialRow: initialRow,
));
+ //! === EndOfScaffold ===
}
+ /// Customize the page, e.g. modify the default widget list given by the model
+ void customize();
+
void dispose() {
controller.dispose();
super.dispose();
@override
void initState() {
super.initState();
- controller = StarterController(
- _formKey,
- this,
- 'change',
- context,
- applicationData,
- );
+ controller =
+ StarterController(_formKey, this, 'change', context, applicationData);
controller.initialize();
+ customize();
}
@override
});
}
}
+
+//! === EndOfGeneratedCode: Below you can change manually:
+
+class StarterChangePageStateCustomized extends StarterChangePageState {
+ StarterChangePageStateCustomized(
+ int primaryId, ApplicationData applicationData, Map initialRow)
+ : super(primaryId, applicationData, initialRow);
+
+ @override
+ void customize() {
+ // ToDo: write code if needed
+ }
+}
import '../../helper/settings.dart';
import '../../widget/edit_form.dart';
import '../../widget/page_controller_bones.dart';
+import '../../model/page_model.dart';
import '../application_data.dart';
import 'starter_controller.dart';
+const starterCreatePageModule = 'starter';
+const starterCreatePageName = 'create';
+const starterCreatePageType = PageModelType.create;
+//! === BeginOfGeneratedCode: Change only in areas marked as customized
+
class StarterCreatePage extends StatefulWidget {
final ApplicationData applicationData;
final logger = Settings().logger;
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
StarterCreatePage(this.applicationData, {Key key}) : super(key: key);
+ //! === EndOfConstructor1 ===
+
@override
StarterCreatePageState createState() {
- final rc = StarterCreatePageState(applicationData);
+ //! === BeginOfCall ===
+ final rc = StarterCreatePageStateCustomized(applicationData);
+ //! === EndOfCall ===
/// for unittests:
applicationData.lastModuleState = rc;
}
}
-class StarterCreatePageState extends State<StarterCreatePage>
+abstract class StarterCreatePageState extends State<StarterCreatePage>
implements RedrawPage {
final ApplicationData applicationData;
final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'starter_create');
+ GlobalKey<FormState>(debugLabel: '$starterCreatePageModule-$starterCreatePageName');
StarterController controller;
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
StarterCreatePageState(this.applicationData);
+ //! === EndOfConstructor2 ===
+
@override
Widget build(BuildContext context) {
- controller.beginOfBuild(context);
+ controller?.beginOfBuild(context);
+ //! === BeginOfScaffold ===
return Scaffold(
- appBar: applicationData.appBarBuilder('Neues Startmenü'),
+ appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
body: EditForm.editForm(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
));
+ //! === 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, 'create', context, applicationData);
+ StarterController(_formKey, this, starterCreatePageName, context, applicationData);
controller.initialize();
+ customize();
}
@override
});
}
}
+
+//! === EndOfGeneratedCode: Below you can change manually:
+
+class StarterCreatePageStateCustomized extends StarterCreatePageState {
+ StarterCreatePageStateCustomized(ApplicationData applicationData)
+ : super(applicationData);
+
+ @override
+ void customize() {
+ // ToDo: write code if needed
+ }
+}
import 'package:flutter/material.dart';
+import 'package:flutter_bones/flutter_bones.dart';
import '../../model/page_model.dart';
import '../../widget/list_form.dart';
import '../application_data.dart';
import 'starter_controller.dart';
+const starterListPageModule = 'starter';
+const starterListPageName = 'list';
+const starterListPageType = PageModelType.list;
+//! === BeginOfGeneratedCode: Change only in areas marked as customized
+
class StarterListPage extends StatefulWidget {
final ApplicationData applicationData;
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
StarterListPage(this.applicationData, {Key key}) : super(key: key);
+ //! === EndOfConstructor1 ===
+
@override
StarterListPageState createState() {
- // StarterListPageState.setPageData(pageData);
- final rc = StarterListPageState(applicationData);
+ //! === BeginOfCall ===
+ final rc = StarterListPageStateCustomized(applicationData);
+ //! === EndOfCall ===
/// for unittests:
applicationData.lastModuleState = rc;
}
}
-class StarterListPageState extends State<StarterListPage>
+abstract class StarterListPageState extends State<StarterListPage>
implements RedrawPage {
final ApplicationData applicationData;
final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'starter_list');
+ GlobalKey<FormState>(debugLabel: '$starterListPageModule-$starterListPageName');
Iterable<dynamic> rowsDeprecated;
StarterController controller;
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
StarterListPageState(this.applicationData);
+ //! === EndOfConstructor2 ===
+
@override
Widget build(BuildContext context) {
controller.beginOfBuild(context);
+
+ //! === BeginOfScaffold ===
return Scaffold(
- appBar: applicationData.appBarBuilder('Programmpunkte'),
- drawer: applicationData.drawerBuilder(context),
- body: ListForm.listForm(
- key: _formKey,
- configuration: applicationData.configuration,
- titles: ListForm.stringsToTitles(controller.page.tableTitles),
- columnNames: controller.page.tableColumns ?? [],
- rows: controller.listRows ?? [],
- showEditIcon: true,
- pageController: controller,
- buttons: <Widget>[
- ButtonBar(alignment: MainAxisAlignment.center, children: [
- controller.searchButton(),
- RaisedButton(
- child: Text('Neuer Programmpunkt'),
- onPressed: () {
- controller.goTo(pageType: PageModelType.create);
- },
- ),
- ]),
- ],
- filters: controller.modelList,
- errorMessage:
- applicationData.lastErrorMessage(controller.page.fullName()),
- ),
- persistentFooterButtons:
- applicationData.footerBuilder().widgets(controller));
+ appBar: applicationData.appBarBuilder(controller.page.title),
+ drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
+ body: ListForm.listForm(
+ key: _formKey,
+ configuration: applicationData.configuration,
+ titles: ListForm.stringsToTitles(controller.page.tableTitles),
+ columnNames: controller.page.tableColumns ?? [],
+ rows: controller.listRows ?? [],
+ showEditIcon: true,
+ pageController: controller,
+ buttons: <Widget>[
+ ButtonBar(
+ alignment: MainAxisAlignment.spaceBetween,
+ children: View().modelsToWidgets(
+ controller.page.sections[0].buttonBar, controller),
+ )
+ ],
+ filters: controller.modelList,
+ errorMessage:
+ applicationData.lastErrorMessage(controller.page.fullName()),
+ ),
+ );
+ //! === EndOfScaffold ===
}
+ /// Customize the page, e.g. modify the default widget list given by the model
+ void customize();
+
@override
void initState() {
super.initState();
controller =
- StarterController(_formKey, this, 'list', context, applicationData);
+ StarterController(_formKey, this, starterListPageName, context, applicationData);
controller.initialize();
+ customize();
}
@override
});
}
}
+
+//! === EndOfGeneratedCode: Below you can change manually:
+
+class StarterListPageStateCustomized extends StarterListPageState {
+ StarterListPageStateCustomized(ApplicationData applicationData)
+ : super(applicationData);
+
+ @override
+ void customize() {
+ final button = controller.page.buttonByName('new');
+ button.onPressed = () {
+ controller.goTo(pageType: PageModelType.create);
+ };
+ }
+}
import '../../model/button_model.dart';
import '../../widget/edit_form.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';
-//! === BeginOfGeneratedCode: Below you can change manually:
-//! pageType: change
+const userChangePageModule = 'user';
+const userChangePageName = 'change';
+const userChangePageType = PageModelType.change;
+//! === BeginOfGeneratedCode: Change only in areas marked as customized
class UserChangePage extends StatefulWidget {
final ApplicationData applicationData;
final int primaryId;
final Map initialRow;
final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'user_change');
+ GlobalKey<FormState>(debugLabel: '$userChangePageModule-$userChangePageName');
UserController controller;
return Scaffold(
appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
- persistentFooterButtons:
- applicationData.footerBuilder().widgets(controller),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
body: EditForm.editForm(
key: _formKey,
pageController: controller,
/// Customize the page, e.g. modify the default widget list given by the model
void customize();
+ @override
void dispose() {
controller.dispose();
super.dispose();
//! === EndOfGeneratedCode: Below you can change manually:
class UserChangePageStateCustomized extends UserChangePageState {
- UserChangePageStateCustomized(int primaryId, ApplicationData applicationData,
- Map initialRow)
+ UserChangePageStateCustomized(
+ int primaryId, ApplicationData applicationData, Map initialRow)
: super(primaryId, applicationData, initialRow);
@override
import '../../helper/settings.dart';
import '../../widget/edit_form.dart';
import '../../widget/page_controller_bones.dart';
+import '../../model/page_model.dart';
import '../application_data.dart';
import 'user_controller.dart';
-//! === BeginOfGeneratedCode: Below you can change manually:
-//! pageType: change
+const userCreatePageModule = 'user';
+const userCreatePageName = 'create';
+const userCreatePageType = PageModelType.create;
+//! === BeginOfGeneratedCode: Change only in areas marked as customized
class UserCreatePage extends StatefulWidget {
final ApplicationData applicationData;
final ApplicationData applicationData;
final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'user_create');
+ GlobalKey<FormState>(debugLabel: '$userCreatePageModule-$userCreatePageName');
UserController controller;
controller?.beginOfBuild(context);
//! === BeginOfScaffold ===
return Scaffold(
- appBar: applicationData.appBarBuilder('Neue Rolle'),
+ appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
- persistentFooterButtons:
- applicationData.footerBuilder().widgets(controller),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
body: EditForm.editForm(
key: _formKey,
pageController: controller,
/// 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();
import '../application_data.dart';
import 'user_controller.dart';
-//! === BeginOfGeneratedCode: Below you can change manually:
-//! pageType: change
+const userListPageModule = 'user';
+const userListPageName = 'list';
+const userListPageType = PageModelType.list;
+//! === BeginOfGeneratedCode: Change only in areas marked as customized
class UserListPage extends StatefulWidget {
final ApplicationData applicationData;
final ApplicationData applicationData;
final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'user_list');
+ GlobalKey<FormState>(debugLabel: '$userListPageModule-$userListPageName');
Iterable<dynamic> rowsDeprecated;
UserController controller;
//! === BeginOfScaffold ===
return Scaffold(
- appBar: applicationData.appBarBuilder('Rollen'),
+ appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
- persistentFooterButtons:
- applicationData.footerBuilder().widgets(controller),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
body: ListForm.listForm(
key: _formKey,
configuration: applicationData.configuration,
showEditIcon: true,
pageController: controller,
buttons: <Widget>[
- ButtonBar(alignment: MainAxisAlignment.center, children: [
- controller.searchButton(),
- RaisedButton(
- child: Text('Neuer Benutzer'),
- onPressed: () {
- controller.goTo(pageType: PageModelType.create);
- },
- ),
- ]),
+ ButtonBar(
+ alignment: MainAxisAlignment.spaceBetween,
+ children: View().modelsToWidgets(
+ controller.page.sections[0].buttonBar, controller),
+ )
],
filters: controller.modelList,
errorMessage:
void initState() {
super.initState();
controller =
- UserController(_formKey, this, 'list', context, applicationData);
+ UserController(_formKey, this, userListPageName, context, applicationData);
controller.initialize();
customize();
}
@override
void customize() {
- // ToDo: write code if needed
+ final button = controller.page.buttonByName('new');
+ button.onPressed = () {
+ controller.goTo(pageType: PageModelType.create);
+ };
}
}
-import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../../helper/settings.dart';
import '../../model/button_model.dart';
import '../../widget/edit_form.dart';
import '../../widget/page_controller_bones.dart';
+import '../../model/page_model.dart';
import '../application_data.dart';
import 'hash.dart';
import 'user_controller.dart';
-// === BeginOfGeneratedCode: Do not change manually
+const userLoginPageModule = 'user';
+const userLoginPageName = 'login';
+const userLoginPageType = PageModelType.create;
+//! === BeginOfGeneratedCode: Change only in areas marked as customized
+
class UserLoginPage extends StatefulWidget {
final ApplicationData applicationData;
final logger = Settings().logger;
- //UserLoginPageState lastState;
-
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
UserLoginPage(this.applicationData, {Key key}) : super(key: key);
+ //! === EndOfConstructor1 ===
+
@override
UserLoginPageState createState() {
+ //! === BeginOfCall ===
final rc = UserLoginPageStateCustomized(applicationData);
+ //! === EndOfCall ===
/// for unittests:
applicationData.lastModuleState = rc;
abstract class UserLoginPageState extends State<UserLoginPage>
implements RedrawPage {
final ApplicationData applicationData;
+
final GlobalKey<FormState> _formKey =
- GlobalKey<FormState>(debugLabel: 'user.login');
+ GlobalKey<FormState>(debugLabel: '$userLoginPageModule-$userLoginPageName');
UserController controller;
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
UserLoginPageState(this.applicationData);
+ //! === EndOfConstructor2 ===
+
@override
Widget build(BuildContext context) {
- controller.beginOfBuild(context);
+ controller?.beginOfBuild(context);
+ //! === BeginOfScaffold ===
return Scaffold(
- appBar: applicationData.appBarBuilder('Anmelden'),
+ appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
body: EditForm.editForm(
key: _formKey,
pageController: controller,
configuration: applicationData.configuration,
- primaryId: 0,
));
+ //! === 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, 'login', context, applicationData);
+ controller = UserController(
+ _formKey, this, userLoginPageName, context, applicationData);
controller.initialize();
customize();
}
});
}
}
-// === EndOfGeneratedCode: Do not change manually
+
+//! === EndOfGeneratedCode: Below you can change manually:
class UserLoginPageStateCustomized extends UserLoginPageState {
UserLoginPageStateCustomized(ApplicationData applicationData)
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
final user = controller.page.fieldByName('user').value;
-
final params = {
':user': user,
};
import '../../model/button_model.dart';
import '../../widget/edit_form.dart';
import '../../widget/page_controller_bones.dart';
+import '../../model/page_model.dart';
import '../application_data.dart';
import 'hash.dart';
import 'user_controller.dart';
+const userPasswordPageModule = 'user';
+const userPasswordPageName = 'password';
+const userPasswordPageType = PageModelType.change;
+//! === BeginOfGeneratedCode: Change only in areas marked as customized
+
class UserPasswordPage extends StatefulWidget {
final ApplicationData applicationData;
final Map initialRow;
final logger = Settings().logger;
final int primaryId;
- final String userName;
-
- //UserPasswordPageState lastState;
+ //! === BeginOfCustomizedVars1 ===
+ final String userName;
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
UserPasswordPage(
this.primaryId, this.userName, this.applicationData, this.initialRow,
{Key key})
: super(key: key);
+ //! === EndOfConstructor1 ===
+
@override
UserPasswordPageState createState() {
- final rc = UserPasswordPageState(primaryId, this.userName, applicationData);
+ //! === BeginOfCall ===
+ final rc = UserPasswordPageStateCustomized(primaryId, this.userName, applicationData, initialRow);
+ //! === EndOfCall ===
/// for unittests:
applicationData.lastModuleState = rc;
}
}
-class UserPasswordPageState extends State<UserPasswordPage>
+abstract class UserPasswordPageState extends State<UserPasswordPage>
implements RedrawPage {
final ApplicationData applicationData;
final int primaryId;
- final String userName;
final GlobalKey<FormState> _formKey =
GlobalKey<FormState>(debugLabel: 'user.password');
+ final Map initialRow;
UserController controller;
- UserPasswordPageState(this.primaryId, this.userName, this.applicationData);
+ //! === BeginOfCustomizedVars2 ===
+ final String userName;
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
+ UserPasswordPageState(this.primaryId, this.userName, this.applicationData, this.initialRow);
+ //! === EndOfConstructor2 ===
@override
Widget build(BuildContext context) {
controller.beginOfBuild(context);
+ //! === BeginOfScaffold ===
return Scaffold(
- appBar: applicationData.appBarBuilder('Passwort ändern'),
+ appBar: applicationData.appBarBuilder(controller.page.title),
drawer: applicationData.drawerBuilder(context),
+ bottomNavigationBar: applicationData.footerBuilder().widget(controller),
body: EditForm.editForm(
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, userPasswordPageName, 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 UserPasswordPageStateCustomized extends UserPasswordPageState {
+ UserPasswordPageStateCustomized(
+ int primaryId, String userName, ApplicationData applicationData, Map initialRow)
+ : super(primaryId, userName, applicationData, initialRow);
+
+ @override
void customize() {
controller.placeholders['user'] = userName;
ButtonModel button = controller.page.buttonByName('store');
}
};
}
-
- void dispose() {
- controller.dispose();
- super.dispose();
- }
-
- @override
- void initState() {
- super.initState();
- controller =
- UserController(_formKey, this, 'password', context, applicationData);
- controller.initialize();
- customize();
- }
-
- @override
- void redraw(RedrawReason reason,
- {String customString, RedrawCallbackFunctionSimple callback}) {
- setState(() {
- controller.afterSetState(reason,
- customString: customString, callback: callback);
- });
- }
}
import 'package:url_launcher/url_launcher.dart';
class BFooter implements FooterBones {
- List<Widget> widgets(PageControllerBones controller) {
- final rc = [
- Row(children: <Widget>[
- InkWell(
- child: Text('Impressum'),
- onTap: () => launch('https://public.hamatoma.de'),
- ),
- SizedBox(
- width: 100,
- ),
- InkWell(
- child: Text('Datenschutz'),
- onTap: () => launch('https://public.hamatoma.de'),
- ),
- SizedBox(
- width: 150,
- ),
- Text('Hallo ${controller.applicationData.currentUserName}'),
- ])
- ];
+ Widget widget(PageControllerBones controller) {
+ final rc = ButtonBar(alignment: MainAxisAlignment.spaceBetween, children: [
+ InkWell(
+ child: Text('Impressum'),
+ onTap: () => launch('https://public.hamatoma.de'),
+ ),
+ // SizedBox(
+ // width: 100,
+ // ),
+ InkWell(
+ child: Text('Datenschutz'),
+ onTap: () => launch('https://public.hamatoma.de'),
+ ),
+ // SizedBox(
+ // width: 150,
+ // ),
+ Text('Hallo ${controller.applicationData.currentUserName}'),
+ ]);
// final rc2 = [
// GridView.count(crossAxisCount: 3, children: [
// Text('a'),
pageController.buildModelList(initialRow);
final widgets = pageController.getWidgets();
final view = View();
- final buttons =
- view.modelsToWidgets(pageController.page.sections[0].buttonBar, pageController);
+ final buttons = view.modelsToWidgets(
+ pageController.page.sections[0].buttonBar, pageController);
return Form(
key: key,
child: Card(
/// Returns a form with the properties given by the [sectionModel]
/// [formKey] identifies the form. Used for form validation and saving.
Form simpleForm(
- {SectionModel sectionModel, PageControllerBones controller, Key formKey}) {
+ {SectionModel sectionModel,
+ PageControllerBones controller,
+ Key formKey}) {
assert(formKey != null);
final padding =
widgetConfiguration.asFloat('form.card.padding', defaultValue: 16.0);
import 'package:dart_bones/dart_bones.dart';
import 'package:flutter_bones_tool/src/model/model_helper.dart';
-import 'package:flutter_bones_tool/src/model_tools.dart';
+import 'package:flutter_bones_tool/src/model/model_tool.dart';
+import 'package:flutter_bones_tool/src/model_tool_io.dart';
void main(List<String> argv) async {
final logger = MemoryLogger(LEVEL_FINE);
final ModelHelper modelHelper = ModelHelper();
- final ModelTools modelTools = ModelTools(modelHelper, logger);
+ final ModelTool modelTools = ModelToolIo(modelHelper, logger);
if (argv.isEmpty) {
argv = ['export-sql'];
}
--- /dev/null
+import 'dart:io';
+
+import 'package:dart_bones/dart_bones.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);
+
+ @override
+ void ensureDirectory(String path) {
+ FileSync.ensureDirectory(path);
+ }
+
+ @override
+ List<String> pathOfDirectory(String path) {
+ final rc = Directory(path).listSync().map((entry) => entry.path).toList();
+ return rc;
+ }
+
+ @override
+ readFile(String file) {
+ final rc = FileSync.fileAsList(file);
+ return rc;
+ }
+
+ @override
+ String safeDirectory(String name) {
+ final rc = FileSync.tempDirectory(
+ name +
+ '.' +
+ (DateTime.now().millisecondsSinceEpoch / 1000 % 86400)
+ .round()
+ .toString(),
+ subDirs: 'model_tools');
+ return rc;
+ }
+
+ @override
+ void writeFile(String filename, String content) {
+ FileSync.toFile(filename, content);
+ }
+}
+++ /dev/null
-import 'dart:io';
-
-import 'package:dart_bones/dart_bones.dart';
-import 'package:flutter_bones_tool/src/model/page_model.dart';
-
-import 'helper/string_helper.dart';
-import 'model/model_helper.dart';
-import 'model/module_model.dart';
-
-class ModelTools {
- final BaseLogger logger;
- final ModelHelper modelHelper;
- ModelTools(this.modelHelper, this.logger);
-
- /// Copies a range of [lines] defined by [start] and [end] markers into [buffer].
- /// [includeStart]: true: the line containing [start] will be copied too.
- /// [includeEnd]: true: the line containing [end] will be copied too.
- /// [replacements]: null or a map with (key, replacement) pairs. All
- /// occurrences of key in the copied lines will be replaced by the replacement.
- /// Returns the count of copied lines.
- int copyToBuffer(List<String> lines, StringBuffer buffer,
- {String start,
- bool includeStart = true,
- String end,
- bool includeEnd = true,
- Map<String, String> replacements}) {
- var mode = start == null ? 'copy' : 'ignore';
- var count = 0;
- for (var line in lines) {
- if (includeStart && start != null && line.contains(start)) {
- mode == 'copy';
- }
- if (!includeEnd && end != null && line.contains(end)) {
- break;
- }
- if (mode == 'copy') {
- if (replacements != null) {
- for (var key in replacements.keys) {
- line = line.replaceAll(key, replacements[key]);
- }
- }
- buffer.write(line);
- buffer.write('\n');
- count++;
- }
- if (start != null && line.contains(start)) {
- mode = 'copy';
- }
- if (end != null && line.contains(end)) {
- break;
- }
- }
- return count;
- }
-
- void exportSql(List<String> args, List<String> options) {
- String directory;
- String value;
- for (var opt in options) {
- value = StringUtils.stringOption('directory', 'd', opt);
- if (value != null) {
- directory = value;
- continue;
- }
- logger.error('unknown option: $opt');
- }
- directory ??= 'data';
- final dirDDL = FileSync.joinPaths(directory, 'ddl');
- final dirREST = FileSync.joinPaths(directory, 'rest');
- FileSync.ensureDirectory(dirDDL);
- FileSync.ensureDirectory(dirREST);
- if (args.isEmpty) {
- args = modelHelper.moduleNames();
- }
- while (args.isNotEmpty) {
- final name = args[0];
- args.removeAt(0);
- ModuleModel module = modelHelper.moduleByName(name, logger);
- if (module != null) {
- module.parse();
- var filename = FileSync.joinPaths(dirDDL, '$name.sql');
- FileSync.toFile(filename, module.exportSqlCreateTable());
- print('exported: $filename');
- filename = FileSync.joinPaths(dirREST, '$name.yaml');
- FileSync.toFile(filename, module.exportSqlBackend());
- print('exported: $filename');
- }
- }
- }
-
- void modifyModule(List<String> args, List<String> options) {
- String baseDirectory;
- String value;
- for (var opt in options) {
- value = StringUtils.stringOption('directory', 'd', opt);
- if (value != null) {
- baseDirectory = value;
- continue;
- }
- logger.error('unknown option: $opt');
- }
- baseDirectory ??= 'lib/src/model';
- if (args.isEmpty) {
- args = modelHelper.moduleNames();
- }
- final regExprFilename = RegExp(r'_(\w+)_page\.dart');
- for (var name in args) {
- if (name == 'role') {
- logger.log('module "role" ignored.');
- }
- final sourceDir = 'lib/src/page/$name';
- logger.log('current directory: ${Directory.current}');
- final files = Directory(sourceDir).listSync();
- final pathSafe = FileSync.tempDirectory(
- name +
- '.' +
- (DateTime.now().millisecondsSinceEpoch / 1000 % 86400)
- .round()
- .toString(),
- subDirs: 'model_tools');
- for (var file in files) {
- final lines = FileSync.fileAsList(file.path);
- final fnTemplate = file.path.replaceAll(name, 'role');
- final templateLines = FileSync.fileAsList(fnTemplate);
- if (templateLines.isEmpty) {
- logger.log('ignoring ${file.path}: no template found');
- continue;
- }
- final matcher = regExprFilename.firstMatch(file.path);
- if (matcher == null) {
- logger.error('cannot recognize page type: ${file.path}');
- continue;
- }
- final pageType = StringUtils.stringToEnum<PageModelType>(
- matcher.group(1), PageModelType.values);
- modifyPage(
- name,
- pageType,
- lines,
- templateLines,
- FileSync.joinPaths(baseDirectory, name, FileSync.nodeOf(file.path)),
- false,
- pathSafe);
- }
- }
- }
-
- void modifyPage(
- String module,
- PageModelType type,
- List<String> lines,
- List<String> templateLines,
- String filename,
- bool customizeConstructors,
- String pathSafe) {
- final moduleCapital = StringHelper.capitalize(module);
- FileSync.ensureDirectory(FileSync.parentOf(filename, trailingSlash: false));
- final buffer = StringBuffer();
- var countTemplate = 0;
- final replacements = <String, String>{
- 'role': module,
- 'Role': moduleCapital
- };
- var countOrigin = 0;
- int ix;
- if (!customizeConstructors) {
- if (StringHelper.listIndexOf(lines, string: 'EndOfGeneratedCode') != null) {
- countOrigin = copyToBuffer(lines, buffer,
- end: 'BeginOfGeneratedCode', includeEnd: false);
- } else {
- countOrigin = copyToBuffer(templateLines, buffer,
- end: 'BeginOfGeneratedCode',
- includeEnd: false,
- replacements: replacements);
- }
- countTemplate = copyToBuffer(templateLines, buffer,
- start: 'BeginOfGeneratedCode',
- end: 'EndOfGeneratedCode',
- replacements: replacements);
- countOrigin = copyToBuffer(lines, buffer,
- start: 'EndOfGeneratedCode', includeStart: false);
- ix = StringHelper.listIndexOf(lines, string: 'EndOfGeneratedCode');
- // -3: possible empty lines at the end
- if (ix == null || ix > lines.length - 3) {
- countTemplate += copyToBuffer(templateLines, buffer,
- start: 'EndOfGeneratedCode',
- includeStart: false,
- replacements: replacements);
- }
- } else {
- //
- }
- FileSync.ensureDirectory(pathSafe);
- final fnSafe = FileSync.joinPaths(pathSafe, FileSync.nodeOf(filename));
- logger.log('saving to $fnSafe');
- FileSync.toFile(fnSafe, lines.join('\n'));
- logger.log('writing $filename lines: $countOrigin + $countTemplate');
- FileSync.toFile(filename, buffer.toString());
- }
-
- void run(List<String> args) {
- final mode = args[0];
- final options = <String>[];
- args = StringHelper.splitArgv(args.sublist(1), options);
- switch (mode) {
- case 'export-sql':
- exportSql(args, options);
- break;
- case 'modify-module':
- modifyModule(args, options);
- break;
- default:
- logger.error('unknown mode: $mode');
- break;
- }
- }
-
- void usage(String error) {
- print('''usage: main <mode> [<args>]
-<mode>:
- 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.
- help
- Display this usage messages.
- modify-module [<module1> [<module2>...]
- Modifies the files of the given modules to renew the generated code.
-Examples:
-main create-sql role user -d/tmp
-main create-sql --directory=/opt/sql-data
-main modify-pages role
-main modify-pages
-''');
- }
-}
# cupertino_icons: ^1.0.0
dev_dependencies:
+ pedantic: ^1.8.0
+ test: ^1.6.0
+ mockito: ^4.1.1
+ test_coverage: ^0.4.2
+ flutter_test:
+ sdk: flutter
# flutter_test:
# sdk: flutter
--- /dev/null
+import 'package:flutter_bones_tool/src/model/model_helper.dart';
+import 'package:flutter_bones_tool/src/model_tool_io.dart';
+import 'package:test/test.dart';
+import 'package:dart_bones/dart_bones.dart';
+
+void main() {
+ final logger = MemoryLogger(LEVEL_FINE);
+ group('modify-modules', () {
+ test('modify-modules-std', () {
+ logger.clear();
+ final helper = ModelHelper();
+ final tool = ModelToolIo(helper, logger);
+ String target = FileSync.tempDirectory('module_tool_test');
+ tool.modifyModule(['user'], ['--directory=$target']);
+ });
+ });
+}
# cupertino_icons: ^1.0.0
dev_dependencies:
- flutter_test:
- sdk: flutter
pedantic: ^1.8.0
test: ^1.6.0
mockito: ^4.1.1
test_coverage: ^0.4.2
-
+ flutter_test:
+ sdk: flutter
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
expect(
StringHelper.replacePlaceholders(
'a: ~aa~ b: ~b c: ~c~ ~d~', {'aa': 'x', 'b': 'y', 'c': 'zz'},
- syntaxPlaceholder: r'~(\w+)~'),
+ syntaxPlaceholder: r'~(\w+)~'),
equals('a: x b: ~b c: zz ~d~'));
});
});
expect(options, equals([]));
});
});
- group('StringList', (){
- test('listIndexOf-string', (){
+ group('StringList', () {
+ test('listIndexOf-string', () {
final list = <String>['a', 'bab', 'cAC'];
expect(StringHelper.listIndexOf(list, string: 'b'), equals(1));
expect(StringHelper.listIndexOf(list, string: 'a'), equals(0));
expect(StringHelper.listIndexOf(list, string: 'x'), isNull);
expect(StringHelper.listIndexOf(null, string: 'x'), isNull);
});
- test('listIndexOf-regEx', (){
+ test('listIndexOf-regEx', () {
final list = <String>['a', 'bab', 'cAC'];
expect(StringHelper.listIndexOf(list, pattern: r'...'), equals(1));
expect(StringHelper.listIndexOf(list, pattern: r'C$'), equals(2));
expect(StringHelper.listIndexOf(list, pattern: 'x'), isNull);
expect(StringHelper.listIndexOf(null, pattern: 'x'), isNull);
- expect(StringHelper.listIndexOf(list, regExp: RegExp(r'a', caseSensitive: false)), equals(0));
+ expect(
+ StringHelper.listIndexOf(list,
+ regExp: RegExp(r'a', caseSensitive: false)),
+ equals(0));
expect(StringHelper.listIndexOf(list, regExp: RegExp(r'd')), isNull);
expect(StringHelper.listIndexOf(null, regExp: RegExp(r'd')), isNull);
});
});
+ group('addRangeToList', () {
+ test('addRangeToList-String', () {
+ List<String> output;
+ final list = <String>['a', '-- bab', 'cAC', '123'];
+ expect(StringHelper.addRangeToList(list, null, endString: 'b').join('\n'),
+ equals('''a
+-- bab'''));
+ expect(
+ StringHelper.addRangeToList(list, output,
+ endString: 'b', includeEnd: false)
+ .join('\n'),
+ equals('''a'''));
+ expect(
+ StringHelper.addRangeToList(list, output, startString: 'C')
+ .join('\n'),
+ equals('''cAC
+123'''));
+ expect(
+ StringHelper.addRangeToList(list, output,
+ startString: 'C', includeStart: false)
+ .join('\n'),
+ equals('''123'''));
+ expect(
+ StringHelper.addRangeToList(list, output,
+ startString: 'b', endString: '2')
+ .join('\n'),
+ equals('''-- bab
+cAC
+123'''));
+ expect(
+ StringHelper.addRangeToList(list, output,
+ startString: 'b',
+ includeStart: false,
+ endString: '2',
+ includeEnd: false)
+ .join('\n'),
+ equals('''cAC'''));
+ });
+ test('addRangeToList-regExp', () {
+ List<String> output;
+ final list = <String>['a', '-- bab', 'cAC', '123'];
+ expect(
+ StringHelper.addRangeToList(list, null, endPattern: 'b').join('\n'),
+ equals('''a
+-- bab'''));
+ expect(
+ StringHelper.addRangeToList(list, output,
+ endPattern: 'b', includeEnd: false)
+ .join('\n'),
+ equals('''a'''));
+ expect(
+ StringHelper.addRangeToList(list, output, startPattern: 'C')
+ .join('\n'),
+ equals('''cAC
+123'''));
+ expect(
+ StringHelper.addRangeToList(list, output,
+ startPattern: '[C]', includeStart: false)
+ .join('\n'),
+ equals('''123'''));
+ expect(
+ StringHelper.addRangeToList(list, output,
+ startPattern: 'b', endPattern: '2')
+ .join('\n'),
+ equals('''-- bab
+cAC
+123'''));
+ expect(
+ StringHelper.addRangeToList(list, output,
+ startPattern: '[b]',
+ includeStart: false,
+ endPattern: r'\d',
+ includeEnd: false)
+ .join('\n'),
+ equals('''cAC'''));
+ });
+ test('addRangeToList-firstIndex', () {
+ List<String> output;
+ final list = <String>['a', '-- bab', 'cAC', '123AC'];
+ expect(
+ StringHelper.addRangeToList(list, null, endString: 'a', firstIndex: 1)
+ .join('\n'),
+ equals('''-- bab'''));
+ expect(
+ StringHelper.addRangeToList(list, output,
+ firstIndex: -1, startString: 'A')
+ .join('\n'),
+ equals('''123AC'''));
+ });
+ test('addRangeToList-lastIndexIncluded', () {
+ List<String> output;
+ final list = <String>['a1', 'a2', 'a3', 'a4'];
+ expect(
+ StringHelper.addRangeToList(list, null,
+ startString: 'a2', lastIndexIncluded: 2)
+ .join('\n'),
+ equals('a2\na3'));
+ expect(
+ StringHelper.addRangeToList(list, output,
+ lastIndexIncluded: -2, startString: 'a3')
+ .join('\n'),
+ equals('a3'));
+ });
+ test('addRangeToList-lastIndexExcluded', () {
+ List<String> output;
+ final list = <String>['a1', 'a2', 'a3', 'a4'];
+ expect(
+ StringHelper.addRangeToList(list, null,
+ startString: 'a2', lastIndexExcluded: 2)
+ .join('\n'),
+ equals('a2'));
+ expect(
+ StringHelper.addRangeToList(list, output,
+ lastIndexExcluded: -2, startString: 'a3')
+ .join('\n'),
+ equals(''));
+ });
+ test('addRangeToList-converter', () {
+ List<String> output;
+ final list = <String>['a1', 'a2', 'a3', 'a4'];
+ expect(
+ StringHelper.addRangeToList(list, null,
+ startRegExp: RegExp('[2-3]'),
+ endRegExp: RegExp(r'[3-4]'),
+ converter: (input) => input.toUpperCase()).join('\n'),
+ equals('A2\nA3'));
+ });
+ });
}
class Demo1 extends ModuleModel {
Demo1(Map<String, dynamic> map, BaseLogger logger) : super(map, logger);
- /// Returns the name including the names of the parent
+ /// Returns the name including the names of the parents.
@override
String fullName() => name;
}
class Demo1 extends ModuleModel {
Demo1(Map<String, dynamic> map, BaseLogger logger) : super(map, logger);
- /// Returns the name including the names of the parent
+ /// Returns the name including the names of the parents.
@override
String fullName() => name;
}
+import 'dart:io';
+
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:test/test.dart';
+import '../../lib/src/model/model_helper.dart' as mh;
+import '../../lib/src/model/model_tool.dart';
+
void main() {
final logger = MemoryLogger(LEVEL_FINE);
group('sql', () {
'''));
});
test('standard_modules', () {
- ModelHelper helper = ModelHelper();
+ final helper = mh.ModelHelper();
logger.clear();
final dir = FileSync.tempDirectory('data', subDirs: 'unittest');
for (var name in helper.moduleNames()) {
});
test('standard_modules-errors', () {
logger.clear();
- final helper = ModelHelper();
+ final helper = mh.ModelHelper();
final module = helper.moduleByName('not-exists', logger);
expect(module, isNull);
expect(logger.contains('unknown standard module: not-exists'), isTrue);
});
});
+ group('modify-modules', () {
+ test('modify-modules-std', () {
+ logger.clear();
+ final helper = mh.ModelHelper();
+ final tool = ModelToolIo(helper, logger);
+ 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(
+ 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));
+ 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));
+ });
+ test('modify-modules-overwrite-constructors', () {
+ logger.clear();
+ final helper = mh.ModelHelper();
+ final tool = ModelToolIo(helper, logger);
+ String target = FileSync.tempDirectory('model_tool_test');
+ tool.modifyModule(
+ ['user'], ['--directory=$target', '--overwrite-constructors']);
+ expect(logger.errors.length, equals(0));
+ expect(tool.fileCache['/tmp/model_tool_test/user/user_change_page.dart'],
+ equals(bodyUserChangePage));
+ expect(
+ 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));
+ });
+ });
+}
+
+final bodyUserChangePage = '''import 'package:flutter/material.dart';
+
+import '../../helper/settings.dart';
+import '../../model/button_model.dart';
+import '../../widget/edit_form.dart';
+import '../../widget/page_controller_bones.dart';
+import '../application_data.dart';
+import 'user_controller.dart';
+import 'user_password_page.dart';
+
+//! === BeginOfGeneratedCode: Change only in areas marked as customized
+//! pageType: change
+
+class UserChangePage extends StatefulWidget {
+ final ApplicationData applicationData;
+ final Map initialRow;
+ final logger = Settings().logger;
+ final int primaryId;
+
+ //! === BeginOfCustomizedVars1 ===
+ //! === EndOfCustomizedVars1 ===
+ //! === BeginOfConstructor1 ===
+ UserChangePage(this.primaryId, this.applicationData, this.initialRow,
+ {Key key})
+ : super(key: key);
+
+ //! === EndOfConstructor1 ===
+
+ @override
+ UserChangePageState createState() {
+ //! === BeginOfCall ===
+ final rc =
+ UserChangePageStateCustomized(primaryId, applicationData, initialRow);
+ //! === EndOfCall ===
+
+ /// for unittests:
+ applicationData.lastModuleState = rc;
+ return rc;
+ }
+}
+
+abstract class UserChangePageState extends State<UserChangePage>
+ implements RedrawPage {
+ final ApplicationData applicationData;
+ final int primaryId;
+ final Map initialRow;
+ final GlobalKey<FormState> _formKey =
+ GlobalKey<FormState>(debugLabel: 'user_change');
+
+ UserController controller;
+
+ //! === BeginOfCustomizedVars2 ===
+ //! === EndOfCustomizedVars2 ===
+ //! === BeginOfConstructor2 ===
+ UserChangePageState(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: EditForm.editForm(
+ 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();
+
+ void dispose() {
+ controller.dispose();
+ super.dispose();
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ controller =
+ UserController(_formKey, this, 'change', 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 UserChangePageStateCustomized extends UserChangePageState {
+ UserChangePageStateCustomized(
+ int primaryId, ApplicationData applicationData, Map initialRow)
+ : super(primaryId, applicationData, initialRow);
+
+ @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)));
+ };
+ }
+}''';
+
+class ModelToolIo extends ModelTool {
+ ModelToolIo(mh.ModelHelper modelHelper, BaseLogger logger)
+ : super(modelHelper, logger);
+
+ final fileCache = <String, String>{};
+ @override
+ void ensureDirectory(String path) {
+ FileSync.ensureDirectory(path);
+ }
+
+ @override
+ List<String> pathOfDirectory(String path) {
+ final rc = Directory(path).listSync().map((entry) => entry.path).toList();
+ return rc;
+ }
+
+ @override
+ readFile(String file) {
+ final rc = FileSync.fileAsList(file);
+ return rc;
+ }
+
+ @override
+ String safeDirectory(String name) {
+ final rc = FileSync.tempDirectory(
+ name +
+ '.' +
+ 12345.0
+ // (DateTime.now().millisecondsSinceEpoch / 1000 % 86400)
+ .round()
+ .toString(),
+ subDirs: 'model_tools');
+ return rc;
+ }
+
+ @override
+ void writeFile(String filename, String content) {
+ fileCache[filename] = content;
+ FileSync.toFile(filename, content);
+ }
}