mirror of
https://github.com/Iconica-Development/flutter_availability.git
synced 2025-05-20 13:43:43 +02:00
feat(flutter_availability_data_interface): add serialization to template data
This commit is contained in:
parent
178db2d753
commit
de5bc0b27c
3 changed files with 197 additions and 0 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
// ignore_for_file: Generated using data class generator
|
||||||
/// A model defining the data structure for an availability
|
/// A model defining the data structure for an availability
|
||||||
class AvailabilityModel {
|
class AvailabilityModel {
|
||||||
/// Creates a new availability
|
/// Creates a new availability
|
||||||
|
@ -55,6 +56,22 @@ class AvailabilityBreakModel {
|
||||||
Duration? duration,
|
Duration? duration,
|
||||||
}) : _duration = duration;
|
}) : _duration = duration;
|
||||||
|
|
||||||
|
/// Parses a break from a map.
|
||||||
|
///
|
||||||
|
/// This function is primarily used in the storing of template blobs. For each
|
||||||
|
/// variant of the service it is recommended to implement your own
|
||||||
|
/// serialization layer.
|
||||||
|
factory AvailabilityBreakModel.fromMap(Map<String, dynamic> map) =>
|
||||||
|
AvailabilityBreakModel(
|
||||||
|
startTime:
|
||||||
|
DateTime.fromMillisecondsSinceEpoch((map["startTime"] ?? 0) as int),
|
||||||
|
endTime:
|
||||||
|
DateTime.fromMillisecondsSinceEpoch((map["endTime"] ?? 0) as int),
|
||||||
|
duration: map["duration"] != null
|
||||||
|
? Duration(minutes: map["duration"] as int)
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
|
||||||
/// The start time for this break
|
/// The start time for this break
|
||||||
///
|
///
|
||||||
/// If duration is not the same as the difference between [startTime] and
|
/// If duration is not the same as the difference between [startTime] and
|
||||||
|
@ -102,4 +119,15 @@ class AvailabilityBreakModel {
|
||||||
endTime: endTime ?? this.endTime,
|
endTime: endTime ?? this.endTime,
|
||||||
duration: duration ?? _duration,
|
duration: duration ?? _duration,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Returns a map variant of this object.
|
||||||
|
///
|
||||||
|
/// This is mainly for serialization of template data. Serialization of this
|
||||||
|
/// object for persistance in your own implementation is recommended to be
|
||||||
|
/// done in a separate serialization layer.
|
||||||
|
Map<String, dynamic> toMap() => <String, dynamic>{
|
||||||
|
"startTime": startTime.millisecondsSinceEpoch,
|
||||||
|
"endTime": endTime.millisecondsSinceEpoch,
|
||||||
|
"duration": _duration?.inMinutes,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
||||||
import "package:flutter_availability_data_interface/src/models/availability.dart";
|
import "package:flutter_availability_data_interface/src/models/availability.dart";
|
||||||
|
|
||||||
/// A limited set of different availability template types
|
/// A limited set of different availability template types
|
||||||
|
@ -22,6 +23,26 @@ class AvailabilityTemplateModel {
|
||||||
this.id,
|
this.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
factory AvailabilityTemplateModel.fromType({
|
||||||
|
required String userId,
|
||||||
|
required String name,
|
||||||
|
required int color,
|
||||||
|
required AvailabilityTemplateType templateType,
|
||||||
|
required Map<String, dynamic> data,
|
||||||
|
String? id,
|
||||||
|
}) {
|
||||||
|
var templateData = TemplateData.fromType(templateType, data);
|
||||||
|
|
||||||
|
return AvailabilityTemplateModel(
|
||||||
|
userId: userId,
|
||||||
|
name: name,
|
||||||
|
color: color,
|
||||||
|
templateType: templateType,
|
||||||
|
templateData: templateData,
|
||||||
|
id: id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// The identifier for this template
|
/// The identifier for this template
|
||||||
final String? id;
|
final String? id;
|
||||||
|
|
||||||
|
@ -41,6 +62,8 @@ class AvailabilityTemplateModel {
|
||||||
|
|
||||||
/// The specific data for this template
|
/// The specific data for this template
|
||||||
final TemplateData templateData;
|
final TemplateData templateData;
|
||||||
|
|
||||||
|
Map<String, dynamic> get rawTemplateData => templateData.toMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used as the key for defining week-based templates
|
/// Used as the key for defining week-based templates
|
||||||
|
@ -79,12 +102,24 @@ enum WeekDay {
|
||||||
///
|
///
|
||||||
/// ignore: one_member_abstracts
|
/// ignore: one_member_abstracts
|
||||||
abstract interface class TemplateData {
|
abstract interface class TemplateData {
|
||||||
|
factory TemplateData.fromType(
|
||||||
|
AvailabilityTemplateType type,
|
||||||
|
Map<String, dynamic> data,
|
||||||
|
) =>
|
||||||
|
switch (type) {
|
||||||
|
AvailabilityTemplateType.week => WeekTemplateData.fromMap(data),
|
||||||
|
AvailabilityTemplateType.day => DayTemplateData.fromMap(data)
|
||||||
|
};
|
||||||
|
|
||||||
/// Applies the current template to all days found between [start] and [end],
|
/// Applies the current template to all days found between [start] and [end],
|
||||||
/// inclusive
|
/// inclusive
|
||||||
List<AvailabilityModel> apply({
|
List<AvailabilityModel> apply({
|
||||||
required DateTime start,
|
required DateTime start,
|
||||||
required DateTime end,
|
required DateTime end,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// Serialize the template to representational data
|
||||||
|
Map<String, dynamic> toMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A week based template data structure
|
/// A week based template data structure
|
||||||
|
@ -116,6 +151,36 @@ class WeekTemplateData implements TemplateData {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Parses the template data from a map.
|
||||||
|
///
|
||||||
|
/// This assumes that the structure of the map is the following:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// {
|
||||||
|
/// '0': <String, dynamic>{},
|
||||||
|
/// 'index thats parseable by int and matches with a weekday': {
|
||||||
|
/// // an object that is allowed to be parsed as a DayTemplateData
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
factory WeekTemplateData.fromMap(Map<String, dynamic> data) =>
|
||||||
|
WeekTemplateData(
|
||||||
|
data: {
|
||||||
|
for (var entry in data.entries) ...{
|
||||||
|
WeekDay.values[int.parse(entry.key)]:
|
||||||
|
DayTemplateData.fromMap(entry.value),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
/// returns the map representation of this template data
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toMap() => {
|
||||||
|
for (var entry in _data.entries) ...{
|
||||||
|
entry.key.index.toString(): entry.value.toMap(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
final Map<WeekDay, DayTemplateData> _data;
|
final Map<WeekDay, DayTemplateData> _data;
|
||||||
|
|
||||||
/// retrieves an unmodifiable map for each date.
|
/// retrieves an unmodifiable map for each date.
|
||||||
|
@ -140,6 +205,35 @@ class DayTemplateData implements TemplateData {
|
||||||
required this.breaks,
|
required this.breaks,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// Parses the template data from a map.
|
||||||
|
///
|
||||||
|
/// This assumes that the structure of the map is the following:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// {
|
||||||
|
/// '0': <String, dynamic>{},
|
||||||
|
/// 'index thats parseable by int and matches with a weekday': {
|
||||||
|
/// // an object that is allowed to be parsed as a DayTemplateData
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
factory DayTemplateData.fromMap(Map<String, dynamic> data) {
|
||||||
|
var rawBreaks = data["breaks"] as List?;
|
||||||
|
var breaks = <AvailabilityBreakModel>[
|
||||||
|
if (rawBreaks != null) ...[
|
||||||
|
for (var rawBreak in rawBreaks) ...[
|
||||||
|
AvailabilityBreakModel.fromMap(rawBreak as Map<String, dynamic>),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
return DayTemplateData(
|
||||||
|
startTime: DateTime.parse(data["startTime"]),
|
||||||
|
endTime: DateTime.parse(data["endTime"]),
|
||||||
|
breaks: breaks,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// The start time to apply on a new availability
|
/// The start time to apply on a new availability
|
||||||
final DateTime startTime;
|
final DateTime startTime;
|
||||||
|
|
||||||
|
@ -157,4 +251,15 @@ class DayTemplateData implements TemplateData {
|
||||||
// TODO(Joey): Implement the apply method
|
// TODO(Joey): Implement the apply method
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toMap() => {
|
||||||
|
"startTime": startTime.toIso8601String(),
|
||||||
|
"endTime": endTime.toIso8601String(),
|
||||||
|
"breaks": [
|
||||||
|
for (var breakToSerialize in breaks) ...[
|
||||||
|
breakToSerialize.toMap(),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
||||||
|
import "package:flutter_test/flutter_test.dart";
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group("AvailabilityTemplate", () {
|
||||||
|
group("Serialization", () {
|
||||||
|
test("week template should serialize and deserialize correctly", () {
|
||||||
|
var baseDate = DateTime(1994, 10, 18, 10, 0);
|
||||||
|
|
||||||
|
DayTemplateData createDayTemplateForDay(WeekDay day) {
|
||||||
|
var baseDayDate = baseDate.add(Duration(days: day.index));
|
||||||
|
return DayTemplateData(
|
||||||
|
startTime: baseDayDate,
|
||||||
|
endTime: baseDayDate.add(const Duration(hours: 7)),
|
||||||
|
breaks: [
|
||||||
|
AvailabilityBreakModel(
|
||||||
|
startTime: baseDayDate.add(const Duration(hours: 3)),
|
||||||
|
endTime: baseDate.add(const Duration(hours: 4)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var weektemplate = AvailabilityTemplateModel(
|
||||||
|
userId: "1",
|
||||||
|
name: "test",
|
||||||
|
color: 0xFFAABBCC,
|
||||||
|
templateType: AvailabilityTemplateType.week,
|
||||||
|
templateData: WeekTemplateData(
|
||||||
|
data: {
|
||||||
|
for (var day in WeekDay.values) ...{
|
||||||
|
day: createDayTemplateForDay(day),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
var serialized = weektemplate.rawTemplateData;
|
||||||
|
|
||||||
|
var deserialized = AvailabilityTemplateModel.fromType(
|
||||||
|
userId: weektemplate.userId,
|
||||||
|
name: weektemplate.name,
|
||||||
|
color: weektemplate.color,
|
||||||
|
templateType: weektemplate.templateType,
|
||||||
|
data: serialized,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(deserialized.templateData, isA<WeekTemplateData>());
|
||||||
|
var parsedData = deserialized.templateData as WeekTemplateData;
|
||||||
|
|
||||||
|
expect(parsedData.data.length, equals(7));
|
||||||
|
expect(parsedData.data.entries.first.value, isA<DayTemplateData>());
|
||||||
|
var dayTemplateData = parsedData.data.entries.first.value;
|
||||||
|
|
||||||
|
expect(dayTemplateData.startTime, equals(baseDate));
|
||||||
|
expect(dayTemplateData.breaks.length, equals(1));
|
||||||
|
expect(
|
||||||
|
dayTemplateData.breaks.first.startTime,
|
||||||
|
equals(baseDate.add(const Duration(hours: 3))),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in a new issue