]> gitweb.hamatoma.de Git - exhibition.git/commitdiff
Helper, Validators, AttendedPage
authorHamatoma <author.hamatoma.de>
Mon, 31 Jan 2022 17:50:45 +0000 (18:50 +0100)
committerHamatoma <author.hamatoma.de>
Mon, 31 Jan 2022 18:18:45 +0000 (19:18 +0100)
* helper: new: weekDaysLongEnglish..weekDaysShortGerman
* validator: Refactoring: _regExprX -> _regExpX
* AttendedPage:
** new: DbColumnChanger
** getRecord() + getRows(): new parameter dbColumnChanger

lib/base/helper.dart
lib/base/validators.dart
lib/widget/attended_page.dart
rest_server/data/sql/precedence/users.sql.yaml [new file with mode: 0644]
test/validators_test.dart

index f5f69a29fe0e874a002f99a6e8019621f4064d85..0d64e700e2cd0668b268ab599218503d1820788c 100644 (file)
@@ -12,6 +12,7 @@ final i18n = I18N();
 final regExprDateSortable = RegExp(r'(\d{4})[-.](\d\d?)[.-](\d\d?)');
 final regExprDateStandard = RegExp(r'(\d\d?)[-.](\d\d?)[.-](\d{4})');
 final regExprDateTimeSortable =
+    // ........1.....1....2.....2....3.....3.4..5.....5.6.....67.8.....87.4
     RegExp(r'(\d{4})[-.](\d\d?)[.-](\d\d?)?(\D(\d\d?):(\d\d?)(:(\d\d?))?)?');
 final regExprDateTimeStandard =
     // ......1.....1....2.....2....3.....34..5.....5.6.....67.8.....87.4
@@ -22,7 +23,47 @@ final standardDateTimeFormat = DateFormat('dd.MM.yyyy HH:mm');
 
 final standardDateTimeFormatSeconds = DateFormat('dd.MM.yyyy HH:mm:ss');
 
-// ..................................1.....1....2.....2....3....3.4.5.....5.6.....67.....7.4
+const weekDaysLongEnglish = [
+  '<undef>',
+  'Monday',
+  'Tuesday',
+  'Wednesday',
+  'Thursday',
+  'Friday',
+  'Saturday',
+  'Sunday'
+];
+const weekDaysShortEnglish = [
+  '<undef>',
+  'Mo',
+  'Tue',
+  'Wed',
+  'Thu',
+  'Fri',
+  'Sat',
+  'Sun'
+];
+const weekDaysLongGerman = [
+  '<undef>',
+  'Montag',
+  'Dienstag',
+  'Mittwoch',
+  'Donnerstag',
+  'Freitag',
+  'Samstag',
+  'Sonntag'
+];
+const weekDaysShortGerman = [
+  '<undef>',
+  'Mo',
+  'Di',
+  'Mi',
+  'Do',
+  'Fr',
+  'Sa',
+  'So'
+];
+
 /// Handles the [input] as a pattern in a filter list:
 ///
 /// Appends '*' if input does not end with a '*'.
index 97bae759d2a1ac9353f50a7c578051d24f248759..547bb7831a7e635e91f633256fdbf7e747624d71 100644 (file)
@@ -1,16 +1,72 @@
 import 'package:dart_bones/dart_bones.dart';
+import 'defines.dart';
+import 'helper.dart';
 
 import 'i18n.dart';
 
 final i18n = I18N();
 
-final _regExprEMailChar = RegExp(r'[\/ "!$%&()?;:,*<>|^°{}\[\]\\=]');
+final _regExpEMailChar = RegExp(r'[\/ "!$%&()?;:,*<>|^°{}\[\]\\=]');
 
-final _regExprEMailFormat = RegExp(r'^[^@]+@[^@]+\.[a-zA-Z]+$');
+final _regExpEMailFormat = RegExp(r'^[^@]+@[^@]+\.[a-zA-Z]+$');
 
-final _regExprTime = RegExp(r'^(\d{1,2})(:(\d{1,2}))?$');
+final _regExpDate = RegExp(r'^(\d{1,4})[.-](\d{1,2})[.-](\d{1,4})?$');
+final _regExpTime = RegExp(r'^(\d{1,2})(:(\d{1,2}))?$');
 
-final _regExprNat = RegExp(r'^\d+$');
+final _regExpNat = RegExp(r'^\d+$');
+
+/// Tests whether the [input] is a date, e.g. "1.02.2021".
+///
+/// [input]: string to test
+///
+/// [mayBeEmpty]: true: input may be null or empty
+/// false: if input is empty an error is returned
+String? isDate(String? input,
+    {bool mayBeEmpty = false, bool placeholderAllowed = true}) {
+  String? rc;
+  RegExpMatch? match;
+  if (input == null || input.isEmpty) {
+    if (!mayBeEmpty) {
+      rc = i18n.tr('Nothing is not a date');
+    }
+  } else if (!placeholderAllowed || input != '*') {
+    if ((match = _regExpDate.firstMatch(input)) == null) {
+      rc = i18n.trArgs(
+          'Not a Date: {0} Examples: 1.2.2021 2021-01-22', '!global', [input]);
+    } else {
+      int first = int.parse(match!.group(1)!);
+      int second = int.parse(match.group(2)!);
+      int third = int.parse(match.group(3)!);
+      if (second < 1 || second > 12) {
+        rc = i18n.trArgs('Wrong month in: {0}: 1..12', '!global', [input]);
+      } else {
+        int year = first;
+        int month = second;
+        int day = third;
+        if (third > 1900 && first < 32) {
+          year = third;
+          day = first;
+        }
+        if (year < 1900 || year > 2100) {
+          rc =
+              i18n.trArgs('Wrong year in: {0}: 1900..2100', '!global', [input]);
+        } else if (month > 12) {
+          rc = i18n.trArgs('Wrong month in: {0}: 1..12', '!global', [input]);
+        } else if (day > 31) {
+          rc = i18n.trArgs('Wrong day in: {0}: 1..31', '!global', [input]);
+        } else {
+          final date2 = fromString(input, dataType: DataType.date);
+          if (int.parse(asString(date2, dateOnly: true).substring(0, 2)) !=
+              day) {
+            rc =
+                i18n.trArgs('Day too large for month: {0}', '!global', [input]);
+          }
+        }
+      }
+    }
+  }
+  return rc;
+}
 
 /// Tests whether [input] is an correct email address.
 ///
@@ -20,13 +76,13 @@ String? isEmail(String? input) {
   if (input == null) {
     rc = i18n.tr('null is not an email');
   } else {
-    RegExpMatch? match = _regExprEMailChar.firstMatch(input);
+    RegExpMatch? match = _regExpEMailChar.firstMatch(input);
     if (countChar(input, '@') > 1) {
       rc = i18n.tr('too many "@" in email address: ') + input;
     } else if (match != null) {
       rc = i18n.trArgs('Illegal character "{0}" in email address', '!global',
           [match.group(0)!]);
-    } else if (_regExprEMailFormat.firstMatch(input) == null) {
+    } else if (_regExpEMailFormat.firstMatch(input) == null) {
       rc = i18n.tr('Not an email address: ') + input;
     }
   }
@@ -53,7 +109,7 @@ String? isNat(String? input) {
   if (input == null) {
     rc = i18n.tr('null is not a not negative integer');
   } else {
-    RegExpMatch? match = _regExprNat.firstMatch(input);
+    RegExpMatch? match = _regExpNat.firstMatch(input);
     if (match == null) {
       rc = i18n.trArgs(
           'Not negative integer expected, not: {0}', '!global', [input]);
@@ -71,7 +127,7 @@ String? isTime(String? input, {bool mayBeEmpty = false}) {
       rc = i18n.tr('Nothing is not a time');
     }
   } else {
-    if ((match = _regExprTime.firstMatch(input)) == null) {
+    if ((match = _regExpTime.firstMatch(input)) == null) {
       rc = i18n
           .trArgs('Not a time: {0} Examples: 10 or 9:44 ', '!global', [input]);
     } else if (int.parse(match!.group(1)!) >= 24) {
index 5c4005ba3ef48d5f957c96036d6f35adc9331180..efd25460c678cee63940584f6a03ae86098becd8 100644 (file)
@@ -1,7 +1,7 @@
-import 'package:exhibition/base/defines.dart';
 import 'package:flutter/material.dart';
 import 'package:synchronized/synchronized.dart';
 
+import '../../base/defines.dart';
 import '../../base/helper.dart';
 import '../../base/i18n.dart';
 import '../../persistence/persistence.dart';
@@ -11,6 +11,14 @@ import '../meta/module_meta_data.dart';
 
 final i18n = I18N();
 
+/// This function can modify a column of a record.
+/// [column] is the name of the column.
+/// [index] is the index of the column in the record: 0..N-1.
+/// [value] is the current value of the column.
+/// [record] is the whole record.
+typedef DbColumnChanger = dynamic Function(
+    String column, int index, dynamic value, JsonMap? record);
+
 /// Links some instances belonging to a module page (given as
 /// member "statefulWidget").
 ///
@@ -170,7 +178,8 @@ class AttendedPage extends ChangeNotifier {
       {required int primaryKey,
       required String what,
       required Map<String, dynamic> parameters,
-      required Function() onDone}) {
+      required Function() onDone,
+      DbColumnChanger? dbColumnChanger}) {
     JsonMap? rc;
     String name = 'record';
     if (!pageStates.dbDataState.hasEntry(name)) {
@@ -188,6 +197,12 @@ class AttendedPage extends ChangeNotifier {
         rc = dbData.singleRecord!;
       }
     }
+    if (dbColumnChanger != null && rc != null) {
+      int ix = -1;
+      for (var column in rc.keys) {
+        rc[column] = dbColumnChanger(column, ++ix, rc[column], rc);
+      }
+    }
     return rc;
   }
 
@@ -200,12 +215,14 @@ class AttendedPage extends ChangeNotifier {
       required String columnList,
       required Function() onDone, //@ToDo: remove
       required String routeEdit,
-      required BuildContext context}) {
+      required BuildContext context,
+      DbColumnChanger? dbColumnChanger}) {
     List<DataRow>? rc;
     if (dbData.recordList != null) {
       rc = <DataRow>[];
       for (var record in dbData.recordList!) {
         final cells = <DataCell>[];
+        int ix = -1;
         for (var column in columnList.split(';')) {
           final primaryKey = moduleMetaData.primaryOf()?.columnName;
           String value;
@@ -215,7 +232,10 @@ class AttendedPage extends ChangeNotifier {
           } else {
             value = dbValueToString(record[column], property.dataType);
           }
-          cells.add(DataCell(Text(value), onTap: () {
+          if (dbColumnChanger != null) {
+            value = dbColumnChanger(column, ++ix, value, record);
+          }
+          cells.add(DataCell(Text(value == 'null' ? '' : value), onTap: () {
             globalData.navigate(context, routeEdit + ';${record[primaryKey]}');
           }));
         }
diff --git a/rest_server/data/sql/precedence/users.sql.yaml b/rest_server/data/sql/precedence/users.sql.yaml
new file mode 100644 (file)
index 0000000..0963352
--- /dev/null
@@ -0,0 +1,25 @@
+---
+# Customized SQL statements of the module "Users":
+
+module: Users
+list:
+  type: list
+  parameters: [":text",":role"]
+  order: "user_id"
+  sql: |
+    SELECT
+    t0.*,t1.role_name AS role
+    FROM users t0
+    JOIN roles t1 ON t1.role_id=t0.user_role
+    WHERE
+    (:text='' OR user_name like :text
+      OR user_displayname like :text OR user_email like :text
+      OR role_name like :text)
+      AND (:role=0 OR :role=user_role)
+insert:
+  type: insert
+  parameters: [":name",":displayName",":email",":role",":createdBy"]
+  sql: |
+    INSERT INTO users(user_name,user_displayname,user_email,user_role,
+      user_status,user_createdby,user_createdat)
+    VALUES(:name,:displayName,:email,:role,1,:createdBy,NOW());
index a7c7a48f4b3995619a92c1e51fdd4f1dd15ee04f..f02cbfd9ac01b5a161fc70f6ba0ce5db0f5196f4 100644 (file)
@@ -59,4 +59,17 @@ void main() {
     expect(notEmpty(''), isNotNull);
     expect(notEmpty(null), isNotNull);
   });
+  test('isDate', () {
+    expect(isDate('1.2.2021'), isNull);
+    expect(isDate('01.02.2021'), isNull);
+    expect(isDate('2001.02.28'), isNull);
+    expect(isDate('2001.2.8'), isNull);
+    expect(isDate('1-2-2021'), isNull);
+    expect(isDate('01-02-2021'), isNull);
+    expect(isDate('2001-02-28'), isNull);
+    expect(isDate('2001-2-8'), isNull);
+    expect(isDate('02.2.8'), matches('1900..2100'));
+    expect(isDate('2002.13.8'), matches(RegExp(r'.*1[.][.]12')));
+    expect(isDate('2002.1.32'), isNotNull);
+  });
 }