Exhibition-Workflow: Unterschied zwischen den Versionen

Aus Info-Theke
Zur Navigation springen Zur Suche springen
 
(5 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 52: Zeile 52:
</syntaxhighlight>
</syntaxhighlight>


= Wichtige Orte =
= Important Locations =
* Anwendungsmenü: lib/setting/drawer_xxx.dart: Definition route + Icon
* Application menu page: lib/setting/drawer_xxx.dart: Definition route + Icon
* Startroute: lib/page/start_page.dart: globalData.navigate(context, '/Users/list');
* Starting route: lib/page/start_page.dart: globalData.navigate(context, '/Users/list');
 
= Typical Adaptions =
* all *_custom.dart:
** buildFrame(): formular elements (widgets)
** build(): "rows = attendedPage.getRows(...)": column list, column adaptions (onColumnOfRecord)
** requestRecords(): parameters of the database query
 
* list_user_custom.dart:
** buildFrame(): table headers
 
= Handling of a Combobox =
* all *_custom.dart:
<pre>
buildFrame(){
...
  comboRolesFromBackend(attendedPage: attendedPage, onDone: () => setState(() => 1));
  final itemsRoles =
        comboRoles(i18n.trDyn(GlobalTranslations.comboboxSelect), attendedPage);
...
FormItem(
  DropdownButtonFormField<int>(
    value: itemsRoles == null || itemsRoles.length == 1 ? 0 : _fieldData.role,
    items: itemsRoles,
    isExpanded: true,
    decoration: InputDecoration(labelText: i18n.tr('Role')),
    onChanged: (value) => _fieldData.role = value ?? 0,
    ),
  weight: 6),
...
}
class _FieldData {
...
  int role;
...
}
</pre>
 
= I18N =
== Coding ==
<pre>
// in each source file using I18N:
final i18n = I18N();
...
  // Usage in any expression:
  // Simple without parameters:
  final msg = i18n.tr('Please wait');
  // Singular/plural case:
  final msg = i18n.ntr('Hi user', 'Hi users', countUsers);
  // Dynamic key (not a string constant):
  comboUsers(i18n.trDyn(GlobalTranslations.comboboxSelect), ...);
  // String with placeholder(s):
  rc = i18n.trArgs('Not a Date: {0}', '!global', [input]);
</pre>
== Workflow ==
=== For the First Time ===
<pre>
cd $BASE_PROJECT
mkdir -p i18n
tools/i18n_text_parser parse lib i18n
vi i18n/project.i18n.yaml
# Adapt the data in the yaml file
# Than run again:
tools/i18n_text_parser parse lib i18n
tools/i18n_text_parser msg-init i18n '!globals' de_DE
</pre>
* In the directory i18n will be created some *.pot files (one for each module)
* Translate them with babel
 
= Android Configuration =
* android/app/src/debug/AndroidManifest.xml + android/app/src/profile/AndroidManifest.xml:
<pre>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>
</pre>
* android/app/src/main/AndroidManifest.xml:
<pre>
...
    package="de.hamatoma.exhibition">
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />
 
  <application>
...
</pre>
* android/app/build.gradle
<pre>
    defaultConfig {
...
      multiDexEnabled true
    }
...
</pre>
 
=== After the First Time ===
<pre>
tools/i18n_text_parser parse lib i18n
</pre>

Aktuelle Version vom 4. Februar 2022, 21:14 Uhr

Links[Bearbeiten]

Workflow[Bearbeiten]

We use the module "Users" as example

  • Create a metadata description: lib/meta/users_meta.dart
import 'module_meta_data.dart';

class UserMeta extends ModuleMetaData  {
  static UserMeta instance = UserMeta.internal();
  UserMeta.internal() : super('Users',
    [
      PropertyMetaData('id', DataType.reference, ':primary:', 'combo'),
      PropertyMetaData('name', DataType.string, ':notnull:', '', size: 64),
      PropertyMetaData('displayName', DataType.string, ':unique:notnull:', '', size: 32),
      PropertyMetaData('email', DataType.string, ':unique:notnull:', '', size: 255),
      PropertyMetaData('role', DataType.reference, ':notnull:', ''),
      PropertyMetaData('created', DataType.datetime, '', ''),
      PropertyMetaData('createdBy', DataType.string, '', '', size: 32),
      PropertyMetaData('changed', DataType.datetime, '', ''),
      PropertyMetaData('changedBy', DataType.string, '', '', size: 32),
    ],
    tableName: 'loginusers',
  );
  factory UserMeta(){
    return instance;
  }
}
  • Create some source files: (for example: the module "Users")
# precondition: the current directory is the base folder of the dev-app.
mkdir -p lib/meta/users
# The following call works without meta data. It works without recreation of the tool:
./Meta show-modules Users >lib/meta/modules.dart
# Now we need a new instance of the meta_tool (to realize the meta data changes):
./ReCreateMetaTool
./Meta show-data >lib/page/users/user_data.dar
# Show the SQL definition:
./Meta show-table Users
  • Create all source files:
# precondition: the current directory is the base folder of the dev-app.
# The following call works without meta data. It works without recreation of the tool:
./Meta update-modules-names
# Now we need a new instance of the ./Meta (to realize the meta data changes):
./ReCreateMetaTool
./Meta update-modules-files
./Meta update-sql

Important Locations[Bearbeiten]

  • Application menu page: lib/setting/drawer_xxx.dart: Definition route + Icon
  • Starting route: lib/page/start_page.dart: globalData.navigate(context, '/Users/list');

Typical Adaptions[Bearbeiten]

  • all *_custom.dart:
    • buildFrame(): formular elements (widgets)
    • build(): "rows = attendedPage.getRows(...)": column list, column adaptions (onColumnOfRecord)
    • requestRecords(): parameters of the database query
  • list_user_custom.dart:
    • buildFrame(): table headers

Handling of a Combobox[Bearbeiten]

  • all *_custom.dart:
buildFrame(){
...
  comboRolesFromBackend(attendedPage: attendedPage, onDone: () => setState(() => 1));
  final itemsRoles =
        comboRoles(i18n.trDyn(GlobalTranslations.comboboxSelect), attendedPage);
...
FormItem(
  DropdownButtonFormField<int>(
    value: itemsRoles == null || itemsRoles.length == 1 ? 0 : _fieldData.role,
    items: itemsRoles,
    isExpanded: true,
    decoration: InputDecoration(labelText: i18n.tr('Role')),
    onChanged: (value) => _fieldData.role = value ?? 0,
    ),
  weight: 6),
...
}
class _FieldData {
...
  int role;
...
}

I18N[Bearbeiten]

Coding[Bearbeiten]

// in each source file using I18N:
final i18n = I18N();
...
  // Usage in any expression:
  // Simple without parameters:
  final msg = i18n.tr('Please wait');
  // Singular/plural case:
  final msg = i18n.ntr('Hi user', 'Hi users', countUsers);
  // Dynamic key (not a string constant):
  comboUsers(i18n.trDyn(GlobalTranslations.comboboxSelect), ...);
  // String with placeholder(s):
  rc = i18n.trArgs('Not a Date: {0}', '!global', [input]);

Workflow[Bearbeiten]

For the First Time[Bearbeiten]

cd $BASE_PROJECT
mkdir -p i18n
tools/i18n_text_parser parse lib i18n
vi i18n/project.i18n.yaml
# Adapt the data in the yaml file
# Than run again:
tools/i18n_text_parser parse lib i18n
tools/i18n_text_parser msg-init i18n '!globals' de_DE
  • In the directory i18n will be created some *.pot files (one for each module)
  • Translate them with babel

Android Configuration[Bearbeiten]

  • android/app/src/debug/AndroidManifest.xml + android/app/src/profile/AndroidManifest.xml:
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>
  • android/app/src/main/AndroidManifest.xml:
...
    package="de.hamatoma.exhibition">
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />

   <application>
...
  • android/app/build.gradle
    defaultConfig {
...
      multiDexEnabled true
    }
...

After the First Time[Bearbeiten]

tools/i18n_text_parser parse lib i18n