mirror of
https://github.com/wger-project/flutter.git
synced 2026-02-18 00:17:48 +01:00
Update models due to changes in exercise api response changes
This commit is contained in:
@@ -78,7 +78,7 @@ class ExerciseDatabase extends _$ExerciseDatabase {
|
||||
|
||||
/// Note that this needs to be bumped if the JSON response from the server changes
|
||||
@override
|
||||
int get schemaVersion => 1;
|
||||
int get schemaVersion => 2;
|
||||
|
||||
/// There is not really a migration strategy. If we bump the version
|
||||
/// number, delete everything and recreate the new tables. The provider
|
||||
|
||||
@@ -25,15 +25,16 @@ class Alias {
|
||||
@JsonKey(required: true)
|
||||
final int? id;
|
||||
|
||||
@JsonKey(name: 'exercise')
|
||||
final int? exerciseId;
|
||||
@JsonKey(name: 'translation')
|
||||
final int? translationId;
|
||||
|
||||
@JsonKey(required: true)
|
||||
final String alias;
|
||||
|
||||
const Alias({this.id, required this.exerciseId, required this.alias});
|
||||
const Alias({this.id, required this.translationId, required this.alias});
|
||||
|
||||
// Boilerplate
|
||||
factory Alias.fromJson(Map<String, dynamic> json) => _$AliasFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$AliasToJson(this);
|
||||
}
|
||||
|
||||
@@ -13,13 +13,13 @@ Alias _$AliasFromJson(Map<String, dynamic> json) {
|
||||
);
|
||||
return Alias(
|
||||
id: (json['id'] as num?)?.toInt(),
|
||||
exerciseId: (json['exercise'] as num?)?.toInt(),
|
||||
translationId: (json['translation'] as num?)?.toInt(),
|
||||
alias: json['alias'] as String,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$AliasToJson(Alias instance) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'exercise': instance.exerciseId,
|
||||
'translation': instance.translationId,
|
||||
'alias': instance.alias,
|
||||
};
|
||||
|
||||
@@ -25,19 +25,20 @@ class Comment {
|
||||
@JsonKey(required: true)
|
||||
final int id;
|
||||
|
||||
@JsonKey(name: 'exercise')
|
||||
final int exerciseId;
|
||||
@JsonKey(name: 'translation')
|
||||
final int translationId;
|
||||
|
||||
@JsonKey(required: true)
|
||||
final String comment;
|
||||
|
||||
const Comment({
|
||||
required this.id,
|
||||
required this.exerciseId,
|
||||
required this.translationId,
|
||||
required this.comment,
|
||||
});
|
||||
|
||||
// Boilerplate
|
||||
factory Comment.fromJson(Map<String, dynamic> json) => _$CommentFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$CommentToJson(this);
|
||||
}
|
||||
|
||||
@@ -13,13 +13,13 @@ Comment _$CommentFromJson(Map<String, dynamic> json) {
|
||||
);
|
||||
return Comment(
|
||||
id: (json['id'] as num).toInt(),
|
||||
exerciseId: (json['exercise'] as num).toInt(),
|
||||
translationId: (json['translation'] as num).toInt(),
|
||||
comment: json['comment'] as String,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$CommentToJson(Comment instance) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'exercise': instance.exerciseId,
|
||||
'translation': instance.translationId,
|
||||
'comment': instance.comment,
|
||||
};
|
||||
|
||||
@@ -28,8 +28,8 @@ class ExerciseImage {
|
||||
@JsonKey(required: true)
|
||||
final String uuid;
|
||||
|
||||
@JsonKey(required: true, name: 'exercise_base')
|
||||
final int exerciseBaseId;
|
||||
@JsonKey(required: true, name: 'exercise')
|
||||
final int exerciseId;
|
||||
|
||||
@JsonKey(required: true, name: 'image')
|
||||
final String url;
|
||||
@@ -40,13 +40,14 @@ class ExerciseImage {
|
||||
const ExerciseImage({
|
||||
required this.id,
|
||||
required this.uuid,
|
||||
required this.exerciseBaseId,
|
||||
required this.exerciseId,
|
||||
required this.url,
|
||||
required this.isMain,
|
||||
});
|
||||
|
||||
// Boilerplate
|
||||
factory ExerciseImage.fromJson(Map<String, dynamic> json) => _$ExerciseImageFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$ExerciseImageToJson(this);
|
||||
|
||||
@override
|
||||
|
||||
@@ -9,12 +9,12 @@ part of 'image.dart';
|
||||
ExerciseImage _$ExerciseImageFromJson(Map<String, dynamic> json) {
|
||||
$checkKeys(
|
||||
json,
|
||||
requiredKeys: const ['id', 'uuid', 'exercise_base', 'image'],
|
||||
requiredKeys: const ['id', 'uuid', 'exercise', 'image'],
|
||||
);
|
||||
return ExerciseImage(
|
||||
id: (json['id'] as num).toInt(),
|
||||
uuid: json['uuid'] as String,
|
||||
exerciseBaseId: (json['exercise_base'] as num).toInt(),
|
||||
exerciseId: (json['exercise'] as num).toInt(),
|
||||
url: json['image'] as String,
|
||||
isMain: json['is_main'] as bool? ?? false,
|
||||
);
|
||||
@@ -23,7 +23,7 @@ ExerciseImage _$ExerciseImageFromJson(Map<String, dynamic> json) {
|
||||
Map<String, dynamic> _$ExerciseImageToJson(ExerciseImage instance) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'uuid': instance.uuid,
|
||||
'exercise_base': instance.exerciseBaseId,
|
||||
'exercise': instance.exerciseId,
|
||||
'image': instance.url,
|
||||
'is_main': instance.isMain,
|
||||
};
|
||||
|
||||
@@ -42,7 +42,7 @@ class Translation extends Equatable {
|
||||
@JsonKey(required: true, name: 'created')
|
||||
final DateTime? created;
|
||||
|
||||
@JsonKey(required: true, name: 'exercise_base')
|
||||
@JsonKey(required: true, name: 'exercise')
|
||||
late int? exerciseId;
|
||||
|
||||
@JsonKey(required: true)
|
||||
|
||||
@@ -9,15 +9,7 @@ part of 'translation.dart';
|
||||
Translation _$TranslationFromJson(Map<String, dynamic> json) {
|
||||
$checkKeys(
|
||||
json,
|
||||
requiredKeys: const [
|
||||
'id',
|
||||
'uuid',
|
||||
'language',
|
||||
'created',
|
||||
'exercise_base',
|
||||
'name',
|
||||
'description'
|
||||
],
|
||||
requiredKeys: const ['id', 'uuid', 'language', 'created', 'exercise', 'name', 'description'],
|
||||
);
|
||||
return Translation(
|
||||
id: (json['id'] as num?)?.toInt(),
|
||||
@@ -25,7 +17,7 @@ Translation _$TranslationFromJson(Map<String, dynamic> json) {
|
||||
created: json['created'] == null ? null : DateTime.parse(json['created'] as String),
|
||||
name: json['name'] as String,
|
||||
description: json['description'] as String,
|
||||
exerciseId: (json['exercise_base'] as num?)?.toInt(),
|
||||
exerciseId: (json['exercise'] as num?)?.toInt(),
|
||||
)
|
||||
..languageId = (json['language'] as num).toInt()
|
||||
..notes = (json['notes'] as List<dynamic>)
|
||||
@@ -41,7 +33,7 @@ Map<String, dynamic> _$TranslationToJson(Translation instance) => <String, dynam
|
||||
'uuid': instance.uuid,
|
||||
'language': instance.languageId,
|
||||
'created': instance.created?.toIso8601String(),
|
||||
'exercise_base': instance.exerciseId,
|
||||
'exercise': instance.exerciseId,
|
||||
'name': instance.name,
|
||||
'description': instance.description,
|
||||
};
|
||||
|
||||
@@ -32,8 +32,8 @@ class Video {
|
||||
@JsonKey(name: 'video', required: true)
|
||||
final String url;
|
||||
|
||||
@JsonKey(name: 'exercise_base', required: true)
|
||||
final int base;
|
||||
@JsonKey(name: 'exercise', required: true)
|
||||
final int exerciseId;
|
||||
|
||||
@JsonKey(required: true)
|
||||
final int size;
|
||||
@@ -62,7 +62,7 @@ class Video {
|
||||
const Video({
|
||||
required this.id,
|
||||
required this.uuid,
|
||||
required this.base,
|
||||
required this.exerciseId,
|
||||
required this.size,
|
||||
required this.url,
|
||||
required this.duration,
|
||||
@@ -76,5 +76,6 @@ class Video {
|
||||
|
||||
// Boilerplate
|
||||
factory Video.fromJson(Map<String, dynamic> json) => _$VideoFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$VideoToJson(this);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ Video _$VideoFromJson(Map<String, dynamic> json) {
|
||||
'id',
|
||||
'uuid',
|
||||
'video',
|
||||
'exercise_base',
|
||||
'exercise',
|
||||
'size',
|
||||
'duration',
|
||||
'width',
|
||||
@@ -27,7 +27,7 @@ Video _$VideoFromJson(Map<String, dynamic> json) {
|
||||
return Video(
|
||||
id: (json['id'] as num).toInt(),
|
||||
uuid: json['uuid'] as String,
|
||||
base: (json['exercise_base'] as num).toInt(),
|
||||
exerciseId: (json['exercise'] as num).toInt(),
|
||||
size: (json['size'] as num).toInt(),
|
||||
url: json['video'] as String,
|
||||
duration: stringToNum(json['duration'] as String?),
|
||||
@@ -44,7 +44,7 @@ Map<String, dynamic> _$VideoToJson(Video instance) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'uuid': instance.uuid,
|
||||
'video': instance.url,
|
||||
'exercise_base': instance.base,
|
||||
'exercise': instance.exerciseId,
|
||||
'size': instance.size,
|
||||
'duration': numToString(instance.duration),
|
||||
'width': instance.width,
|
||||
|
||||
@@ -37,7 +37,7 @@ class AddExerciseProvider with ChangeNotifier {
|
||||
List<Muscle> _primaryMuscles = [];
|
||||
List<Muscle> _secondaryMuscles = [];
|
||||
|
||||
static const _exerciseBaseUrlPath = 'exercise-base';
|
||||
static const _exerciseUrlPath = 'exercise-base';
|
||||
static const _imagesUrlPath = 'exerciseimage';
|
||||
static const _exerciseTranslationUrlPath = 'exercise-translation';
|
||||
static const _exerciseAliasPath = 'exercisealias';
|
||||
@@ -215,13 +215,13 @@ class AddExerciseProvider with ChangeNotifier {
|
||||
}
|
||||
|
||||
Future<Exercise> addExerciseBase() async {
|
||||
final Uri postUri = baseProvider.makeUrl(_exerciseBaseUrlPath);
|
||||
final Uri postUri = baseProvider.makeUrl(_exerciseUrlPath);
|
||||
|
||||
final Map<String, dynamic> newBaseMap = await baseProvider.post(exercise.toJson(), postUri);
|
||||
final Exercise newExerciseBase = Exercise.fromJson(newBaseMap);
|
||||
final Exercise newExercise = Exercise.fromJson(newBaseMap);
|
||||
notifyListeners();
|
||||
|
||||
return newExerciseBase;
|
||||
return newExercise;
|
||||
}
|
||||
|
||||
Future<Variation> addVariation() async {
|
||||
@@ -235,13 +235,13 @@ class AddExerciseProvider with ChangeNotifier {
|
||||
return newVariation;
|
||||
}
|
||||
|
||||
Future<void> addImages(Exercise base) async {
|
||||
Future<void> addImages(Exercise exercise) async {
|
||||
for (final image in _exerciseImages) {
|
||||
final request = http.MultipartRequest('POST', baseProvider.makeUrl(_imagesUrlPath));
|
||||
request.headers.addAll(baseProvider.getDefaultHeaders(includeAuth: true));
|
||||
|
||||
request.files.add(await http.MultipartFile.fromPath('image', image.path));
|
||||
request.fields['exercise_base'] = base.id!.toString();
|
||||
request.fields['exercise'] = exercise.id!.toString();
|
||||
request.fields['style'] = EXERCISE_IMAGE_ART_STYLE.PHOTO.index.toString();
|
||||
|
||||
await request.send();
|
||||
@@ -261,7 +261,7 @@ class AddExerciseProvider with ChangeNotifier {
|
||||
}
|
||||
|
||||
Future<Alias> addExerciseAlias(String name, int exerciseId) async {
|
||||
final alias = Alias(exerciseId: exerciseId, alias: name);
|
||||
final alias = Alias(translationId: exerciseId, alias: name);
|
||||
final Uri postUri = baseProvider.makeUrl(_exerciseAliasPath);
|
||||
|
||||
final Alias newAlias = Alias.fromJson(await baseProvider.post(alias.toJson(), postUri));
|
||||
|
||||
@@ -27,15 +27,15 @@ class ExerciseDetailScreen extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final exerciseBase = ModalRoute.of(context)!.settings.arguments as Exercise;
|
||||
final exercise = ModalRoute.of(context)!.settings.arguments as Exercise;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(exerciseBase.getTranslation(Localizations.localeOf(context).languageCode).name),
|
||||
title: Text(exercise.getTranslation(Localizations.localeOf(context).languageCode).name),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: ExerciseDetail(exerciseBase),
|
||||
child: ExerciseDetail(exercise),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -267,8 +267,8 @@ class MockAddExerciseProvider extends _i1.Mock implements _i8.AddExerciseProvide
|
||||
) as _i14.Future<_i5.Variation>);
|
||||
|
||||
@override
|
||||
_i14.Future<void> addImages(_i3.Exercise? base) => (super.noSuchMethod(
|
||||
Invocation.method(#addImages, [base]),
|
||||
_i14.Future<void> addImages(_i3.Exercise? exercise) => (super.noSuchMethod(
|
||||
Invocation.method(#addImages, [exercise]),
|
||||
returnValue: _i14.Future<void>.value(),
|
||||
returnValueForMissingStub: _i14.Future<void>.value(),
|
||||
) as _i14.Future<void>);
|
||||
|
||||
@@ -79,7 +79,7 @@ void main() {
|
||||
final Map<String, dynamic> tLanguageMap = jsonDecode(
|
||||
fixture('exercises/language_entries.json'),
|
||||
);
|
||||
final Map<String, dynamic> tExerciseBaseInfoMap = jsonDecode(
|
||||
final Map<String, dynamic> tExerciseInfoMap = jsonDecode(
|
||||
fixture('exercises/exercisebaseinfo_response.json'),
|
||||
);
|
||||
|
||||
@@ -120,12 +120,12 @@ void main() {
|
||||
// Mock base info response
|
||||
when(mockBaseProvider.makeUrl(exerciseBaseInfoUrl)).thenReturn(tExerciseInfoUri);
|
||||
when(mockBaseProvider.fetch(tExerciseInfoUri)).thenAnswer(
|
||||
(_) => Future.value(tExerciseBaseInfoMap),
|
||||
(_) => Future.value(tExerciseInfoMap),
|
||||
);
|
||||
|
||||
when(mockBaseProvider.makeUrl(exerciseBaseInfoUrl, id: 9)).thenReturn(tExerciseInfoDetailUri);
|
||||
when(mockBaseProvider.fetch(tExerciseInfoDetailUri)).thenAnswer(
|
||||
(_) => Future.value(tExerciseBaseInfoMap),
|
||||
(_) => Future.value(tExerciseInfoMap),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -392,9 +392,9 @@ void main() {
|
||||
|
||||
await database.into(database.exercises).insert(
|
||||
ExercisesCompanion.insert(
|
||||
id: tExerciseBaseInfoMap['id'],
|
||||
data: json.encode(tExerciseBaseInfoMap),
|
||||
lastUpdate: DateTime.parse(tExerciseBaseInfoMap['last_update_global']),
|
||||
id: tExerciseInfoMap['id'],
|
||||
data: json.encode(tExerciseInfoMap),
|
||||
lastUpdate: DateTime.parse(tExerciseInfoMap['last_update_global']),
|
||||
lastFetched: DateTime.now(),
|
||||
),
|
||||
);
|
||||
@@ -424,9 +424,9 @@ void main() {
|
||||
provider.languages = testLanguages;
|
||||
await database.into(database.exercises).insert(
|
||||
ExercisesCompanion.insert(
|
||||
id: tExerciseBaseInfoMap['id'],
|
||||
data: json.encode(tExerciseBaseInfoMap),
|
||||
lastUpdate: DateTime.parse(tExerciseBaseInfoMap['last_update_global']),
|
||||
id: tExerciseInfoMap['id'],
|
||||
data: json.encode(tExerciseInfoMap),
|
||||
lastUpdate: DateTime.parse(tExerciseInfoMap['last_update_global']),
|
||||
lastFetched: DateTime.now().subtract(const Duration(hours: 1)),
|
||||
),
|
||||
);
|
||||
@@ -449,9 +449,9 @@ void main() {
|
||||
provider.languages = testLanguages;
|
||||
await database.into(database.exercises).insert(
|
||||
ExercisesCompanion.insert(
|
||||
id: tExerciseBaseInfoMap['id'],
|
||||
data: json.encode(tExerciseBaseInfoMap),
|
||||
lastUpdate: DateTime.parse(tExerciseBaseInfoMap['last_update_global']),
|
||||
id: tExerciseInfoMap['id'],
|
||||
data: json.encode(tExerciseInfoMap),
|
||||
lastUpdate: DateTime.parse(tExerciseInfoMap['last_update_global']),
|
||||
lastFetched: DateTime.now().subtract(const Duration(days: 10)),
|
||||
),
|
||||
);
|
||||
@@ -475,7 +475,7 @@ void main() {
|
||||
test('fetching a known exercise - needed API refresh - new data from API', () async {
|
||||
// Arrange
|
||||
provider.languages = testLanguages;
|
||||
final newData = Map.from(tExerciseBaseInfoMap);
|
||||
final newData = Map.from(tExerciseInfoMap);
|
||||
newData['uuid'] = 'bf6d5557-1c49-48fd-922e-75d11f81d4eb';
|
||||
|
||||
await database.into(database.exercises).insert(
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
{
|
||||
"id": 1,
|
||||
"uuid": "1f5d2b2f-d4ea-4eeb-9377-56176465e08d",
|
||||
"exercise_base": 9,
|
||||
"exercise": 9,
|
||||
"image": "http://localhost:8000/media/exercise-images/9/1f5d2b2f-d4ea-4eeb-9377-56176465e08d.jpg",
|
||||
"is_main": true,
|
||||
"status": "2",
|
||||
@@ -78,7 +78,7 @@
|
||||
{
|
||||
"id": 2,
|
||||
"uuid": "ab645585-26ef-4992-a9ec-15425687ece9",
|
||||
"exercise_base": 9,
|
||||
"exercise": 9,
|
||||
"image": "http://localhost:8000/media/exercise-images/9/ab645585-26ef-4992-a9ec-15425687ece9.jpg",
|
||||
"is_main": false,
|
||||
"status": "2",
|
||||
@@ -87,7 +87,7 @@
|
||||
{
|
||||
"id": 3,
|
||||
"uuid": "d8aa5990-bb47-4111-9823-e2fbd98fe07f",
|
||||
"exercise_base": 9,
|
||||
"exercise": 9,
|
||||
"image": "http://localhost:8000/media/exercise-images/9/d8aa5990-bb47-4111-9823-e2fbd98fe07f.jpg",
|
||||
"is_main": false,
|
||||
"status": "2",
|
||||
@@ -96,7 +96,7 @@
|
||||
{
|
||||
"id": 4,
|
||||
"uuid": "49a159e1-1e00-409a-81c9-b4d4489fbd67",
|
||||
"exercise_base": 9,
|
||||
"exercise": 9,
|
||||
"image": "http://localhost:8000/media/exercise-images/9/49a159e1-1e00-409a-81c9-b4d4489fbd67.jpg",
|
||||
"is_main": false,
|
||||
"status": "2",
|
||||
@@ -107,8 +107,8 @@
|
||||
{
|
||||
"id": 2,
|
||||
"uuid": "63e996e9-a772-4ca5-9d09-8b4be03f6be4",
|
||||
"exercise_base": 258,
|
||||
"exercise_base_uuid": "6260e3aa-e46b-4b4b-8ada-58bfd0922d3a",
|
||||
"exercise": 258,
|
||||
"exercise_uuid": "6260e3aa-e46b-4b4b-8ada-58bfd0922d3a",
|
||||
"video": "http://localhost:8000/media/exercise-video/258/63e996e9-a772-4ca5-9d09-8b4be03f6be4.MOV",
|
||||
"is_main": false,
|
||||
"size": 0,
|
||||
@@ -136,22 +136,22 @@
|
||||
}
|
||||
],
|
||||
"name": "2 Handed Kettlebell Swing",
|
||||
"exercise_base": 9,
|
||||
"exercise": 9,
|
||||
"description": "<p>Two Handed Russian Style Kettlebell swing</p>\n<p> </p>\n<p><strong style=\"\">Pizza</strong> (Italian: [ˈpittsa], Neapolitan: [ˈpittsə]) is a dish of Italian origin consisting of a usually round, flat base of leavened wheat-based dough topped with tomatoes, cheese, and often various other ingredients (such as anchovies, mushrooms, onions, olives, pineapple, meat, etc.), which is then baked at a high temperature, traditionally in a wood-fired oven.[1] A small pizza is sometimes called a pizzetta. A person who makes pizza is known as a <strong style=\"\">pizzaiolo</strong>.</p>",
|
||||
"notes": [
|
||||
{
|
||||
"id": 134,
|
||||
"exercise": 345,
|
||||
"translation": 345,
|
||||
"comment": "it's important to do the exercise correctly"
|
||||
},
|
||||
{
|
||||
"id": 135,
|
||||
"exercise": 345,
|
||||
"translation": 345,
|
||||
"comment": "put a lot of effort into this exercise"
|
||||
},
|
||||
{
|
||||
"id": 136,
|
||||
"exercise": 345,
|
||||
"translation": 345,
|
||||
"comment": "have fun"
|
||||
}
|
||||
],
|
||||
@@ -178,17 +178,17 @@
|
||||
}
|
||||
],
|
||||
"name": "Kettlebell Con Dos Manos",
|
||||
"exercise_base": 9,
|
||||
"exercise": 9,
|
||||
"description": "<p>Cualquier descripción aquí...</p>\n<p>La <em style=\"\"><strong>pizza</strong></em> es una preparación culinaria que consiste en un pan plano, habitualmente de forma circular, elaborado con harina de trigo, levadura, agua y sal (a veces aceite de oliva) que tradicionalmente se cubre con salsa de tomate y mozzarella y se hornea a alta temperatura en un horno de leña.234 El lugar donde se venden pizzas se denomina «pizzería» y al obrador, «pizzero» (<em style=\"\">pizzaiolo</em> en italiano). Aunque se considera que su origen está en la gastronomía italiana,3 particularmente la napolitana,2 su consumo está extendido a casi todos los países del mundo con diversas variantes locales, que incorporan distintos ingredientes para cubrir la masa.1 Junto con la hamburguesa, la pizza está considerada la comida más difundida del mundo,56 como consecuencia de la diáspora italiana que se estableció en América a lo largo del siglo xx principalmente en Nueva York,3 Buenos Aires o Chicago.78</p>",
|
||||
"notes": [
|
||||
{
|
||||
"id": 137,
|
||||
"exercise": 856,
|
||||
"translation": 856,
|
||||
"comment": "haz el ejercicio correctamente"
|
||||
},
|
||||
{
|
||||
"id": 138,
|
||||
"exercise": 856,
|
||||
"translation": 856,
|
||||
"comment": "pasatelo bien!"
|
||||
}
|
||||
],
|
||||
@@ -209,12 +209,12 @@
|
||||
"uuid": "2fe5f04b-5c9d-448c-a973-3fad6ddd4f74",
|
||||
"aliases": [],
|
||||
"name": "Zweihändiges Kettlebell",
|
||||
"exercise_base": 9,
|
||||
"exercise": 9,
|
||||
"description": "<p>Irgendeine Beschreibung hier...</p>\n<p>Eine <strong style=\"\">Pizza</strong> (Aussprache [ˈpɪtsa], ital. [ˈpitːsa], deutscher Plural: <em style=\"\">die Pizzas</em> oder <em style=\"\">die Pizzen</em>[1]) ist ein vor dem Backen würzig belegtes Fladenbrot aus einfachem Hefeteig aus der italienischen Küche. Die heutige international verbreitete Variante mit Tomatensauce und Käse als Basis stammt vermutlich aus Neapel. 2017 wurde die neapolitanische Kunst des Pizzabäckers (<em style=\"\">Art of Neapolitan ‘Pizzaiuolo’</em>) von der UNESCO in die repräsentative Liste des immateriellen Kulturerbes der Menschheit aufgenommen.[2]</p>",
|
||||
"notes": [
|
||||
{
|
||||
"id": 139,
|
||||
"exercise": 855,
|
||||
"translation": 855,
|
||||
"comment": "mach die Übung richtig"
|
||||
}
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user