Commit 614da72
Changed files (5)
lib
components
model
export_import
storage
lib/components/dialoges/add_export_column_dialoge.dart
@@ -99,6 +99,7 @@ class _AddExportColumnDialogeState extends State<AddExportColumnDialoge> {
onSaved: (value) => setState(() {formatPattern = value!;}),
),
const SizedBox(height: 8,),
+ // TODO: add switcher to allow creating TimeColumn
Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
lib/model/export_import/column.dart
@@ -215,8 +215,6 @@ class BuildInColumn extends ExportColumn {
RowDataFieldType? get restoreAbleType => _formatter.restoreAbleType;
}
-// TODO: add class for formattedTimestamp
-
/// Class for storing data of user added columns.
class UserColumn extends ExportColumn {
/// Create a object that handles export behavior for data in a column.
@@ -232,10 +230,10 @@ class UserColumn extends ExportColumn {
UserColumn.explicit(this.internalIdentifier, this.csvTitle, String formatPattern):
formatter = ScriptedFormatter(formatPattern);
- @override
/// Unique identifier of userColumn.
///
/// Is automatically prefixed with `userColumn.` to avoid name collisions with build-ins.
+ @override
final String internalIdentifier;
@override
@@ -260,6 +258,49 @@ class UserColumn extends ExportColumn {
RowDataFieldType? get restoreAbleType => formatter.restoreAbleType;
}
+class TimeColumn extends ExportColumn {
+ /// Create a formatter that converts between [String]s and [DateTime]s through a format pattern
+ ///
+ /// [internalIdentifier] is automatically prefixed with 'userColumn.' during object creation.
+ TimeColumn(this.csvTitle, this.formatPattern):
+ internalIdentifier = 'timeFormatter.$csvTitle';
+
+ /// UserColumn constructor that does not change the [internalIdentifier].
+ TimeColumn.explicit(this.internalIdentifier, this.csvTitle, this.formatPattern);
+
+ ScriptedTimeFormatter? _formatter;
+
+ @override
+ final String csvTitle;
+
+ @override
+ (RowDataFieldType, dynamic)? decode(String pattern) {
+ _formatter ??= ScriptedTimeFormatter(formatPattern);
+ return _formatter!.decode(pattern);
+ }
+
+ @override
+ String encode(BloodPressureRecord record) {
+ _formatter ??= ScriptedTimeFormatter(formatPattern);
+ return _formatter!.encode(record);
+ }
+
+ @override
+ final String formatPattern;
+
+ /// Unique identifier of userColumn.
+ ///
+ /// Is automatically prefixed with `timeFormatter.` to avoid name collisions with build-ins.
+ @override
+ final String internalIdentifier;
+
+ @override
+ RowDataFieldType? get restoreAbleType => RowDataFieldType.timestamp;
+
+ @override
+ String userTitle(AppLocalizations localizations) => csvTitle;
+
+}
/// Interface for converters that allow formatting and provide metadata.
sealed class ExportColumn implements Formatter {
lib/model/export_import/record_formatter.dart
@@ -7,7 +7,6 @@ import 'package:intl/intl.dart';
/// Class to serialize and deserialize [BloodPressureRecord] values.
abstract interface class Formatter {
/// Pattern that a user can use to achieve the effect of [convertToCsvValue].
- // TODO: consider making this implementer specific later in the development process
String? get formatPattern;
/// Creates a string representation of the record.
@@ -161,4 +160,38 @@ class ScriptedFormatter implements Formatter {
return _restoreAbleType;
}
+}
+
+/// Record formatter to format encode and decode formatted timestamps.
+///
+/// Where possible the direct timestamp should be used as this may reduce
+/// accuracy of timestamps.
+///
+/// This class is mainly a wrapper around [DateFormat].
+class ScriptedTimeFormatter implements Formatter {
+ /// Creates a new scripted time formatter from a format pattern.
+ ///
+ /// The pattern follows the ICU style like [DateFormat].
+ ScriptedTimeFormatter(String newPattern):
+ timeFormatter = DateFormat(newPattern);
+
+ final DateFormat timeFormatter;
+
+ @override
+ (RowDataFieldType, dynamic)? decode(String pattern) {
+ try {
+ return (RowDataFieldType.timestamp, timeFormatter.parseLoose(pattern));
+ } on FormatException {
+ return null;
+ }
+ }
+
+ @override
+ String encode(BloodPressureRecord record) => timeFormatter.format(record.creationTime);
+
+ @override
+ String? get formatPattern => timeFormatter.pattern;
+
+ @override
+ RowDataFieldType? get restoreAbleType => RowDataFieldType.timestamp;
}
\ No newline at end of file
lib/model/storage/export_columns_store.dart
@@ -91,6 +91,15 @@ class ExportColumnsManager extends ChangeNotifier { // TODO: separate ExportColu
case BuildInColumn():
case NativeColumn():
assert(false, 'User is currently not able to create these columns.');
+ break;
+ case TimeColumn():
+ columns.add({
+ 't': 1, // class type
+ 'id': c.internalIdentifier,
+ 'csvTitle': c.csvTitle,
+ 'formatPattern': c.formatPattern
+ });
+ break;
}
}
return jsonEncode({
@@ -107,6 +116,9 @@ class ExportColumnsManager extends ChangeNotifier { // TODO: separate ExportColu
case 0:
manager.addOrUpdate(UserColumn.explicit(c['id'], c['csvTitle'], c['formatString']));
break;
+ case 1:
+ manager.addOrUpdate(TimeColumn.explicit(c['id'], c['csvTitle'], c['formatPattern']));
+ break;
default:
assert(false, 'Unexpected column type ${c['t']}.');
}