updates to improve navigation of practice activities

pull/1384/head
ggurdin 1 year ago
parent 8fba3b667e
commit b12efe7e80

@ -4058,5 +4058,6 @@
"suggestToSpaceDesc": "Suggested spaces will appear in the chat lists for their parent spaces",
"practice": "Practice",
"noLanguagesSet": "No languages set",
"noActivitiesFound": "No practice activities found for this message"
"noActivitiesFound": "No practice activities found for this message",
"previous": "Previous"
}

@ -569,15 +569,7 @@ class PangeaMessageEvent {
if (l2Code == null) return false;
final List<PracticeActivityEvent> activities = practiceActivities(l2Code!);
if (activities.isEmpty) return false;
// for now, only show the button if the event has no completed activities
// TODO - revert this after adding logic to show next activity
for (final activity in activities) {
if (activity.isComplete) return false;
}
return true;
// if (activities.isEmpty) return false;
// return !activities.every((activity) => activity.isComplete);
return activities.any((activity) => !(activity.isComplete));
}
String? get l2Code =>

@ -27,7 +27,7 @@ class MultipleChoice {
return MultipleChoice(
question: json['question'] as String,
choices: (json['choices'] as List).map((e) => e as String).toList(),
answer: json['answer'] as String,
answer: json['answer'] ?? json['correct_answer'] as String,
);
}

@ -243,9 +243,11 @@ class PracticeActivityModel {
.toList(),
langCode: json['lang_code'] as String,
msgId: json['msg_id'] as String,
activityType: ActivityTypeEnum.values.firstWhere(
(e) => e.string == json['activity_type'],
),
activityType: json['activity_type'] == "multipleChoice"
? ActivityTypeEnum.multipleChoice
: ActivityTypeEnum.values.firstWhere(
(e) => e.string == json['activity_type'],
),
multipleChoice: json['multiple_choice'] != null
? MultipleChoice.fromJson(
json['multiple_choice'] as Map<String, dynamic>,

@ -2,26 +2,24 @@ import 'package:collection/collection.dart';
import 'package:fluffychat/pangea/choreographer/widgets/choice_array.dart';
import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart';
import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_model.dart';
import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_content.dart';
import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity.dart';
import 'package:flutter/material.dart';
class MultipleChoiceActivity extends StatelessWidget {
final MessagePracticeActivityContentState card;
class MultipleChoiceActivityView extends StatelessWidget {
final PracticeActivityContentState controller;
final Function(int) updateChoice;
final bool isActive;
const MultipleChoiceActivity({
const MultipleChoiceActivityView({
super.key,
required this.card,
required this.controller,
required this.updateChoice,
required this.isActive,
});
PracticeActivityEvent get practiceEvent => card.practiceEvent;
PracticeActivityEvent get practiceEvent => controller.practiceEvent;
int? get selectedChoiceIndex => card.selectedChoiceIndex;
bool get submitted => card.recordSubmittedThisSession;
int? get selectedChoiceIndex => controller.selectedChoiceIndex;
@override
Widget build(BuildContext context) {
@ -50,10 +48,7 @@ class MultipleChoiceActivity extends StatelessWidget {
.mapIndexed(
(index, value) => Choice(
text: value,
color: (selectedChoiceIndex == index ||
practiceActivity.multipleChoice!
.isCorrect(index)) &&
submitted
color: selectedChoiceIndex == index
? practiceActivity.multipleChoice!.choiceColor(index)
: null,
isGold: practiceActivity.multipleChoice!.isCorrect(index),

@ -0,0 +1,104 @@
import 'package:fluffychat/pangea/enum/activity_type_enum.dart';
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart';
import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart';
import 'package:fluffychat/pangea/widgets/practice_activity/multiple_choice_activity_view.dart';
import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_card.dart';
import 'package:flutter/material.dart';
class PracticeActivity extends StatefulWidget {
final PracticeActivityEvent practiceEvent;
final PangeaMessageEvent pangeaMessageEvent;
final MessagePracticeActivityCardState controller;
const PracticeActivity({
super.key,
required this.practiceEvent,
required this.pangeaMessageEvent,
required this.controller,
});
@override
PracticeActivityContentState createState() => PracticeActivityContentState();
}
class PracticeActivityContentState extends State<PracticeActivity> {
PracticeActivityEvent get practiceEvent => widget.practiceEvent;
int? selectedChoiceIndex;
bool isSubmitted = false;
@override
void initState() {
super.initState();
setRecord();
}
@override
void didUpdateWidget(covariant PracticeActivity oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.practiceEvent.event.eventId !=
widget.practiceEvent.event.eventId) {
setRecord();
}
}
// sets the record model for the activity
// either a new record model that will be sent after submitting the
// activity or the record model from the user's previous response
void setRecord() {
if (widget.controller.recordEvent?.record == null) {
final String question =
practiceEvent.practiceActivity.multipleChoice!.question;
widget.controller.recordModel =
PracticeActivityRecordModel(question: question);
} else {
widget.controller.recordModel = widget.controller.recordEvent!.record;
// Note that only MultipleChoice activities will have this so we
// probably should move this logic to the MultipleChoiceActivity widget
selectedChoiceIndex =
widget.controller.recordModel?.latestResponse != null
? widget.practiceEvent.practiceActivity.multipleChoice
?.choiceIndex(widget.controller.recordModel!.latestResponse!)
: null;
isSubmitted = widget.controller.recordModel?.latestResponse != null;
}
setState(() {});
}
void updateChoice(int index) {
setState(() {
selectedChoiceIndex = index;
widget.controller.recordModel!.addResponse(
text: widget
.practiceEvent.practiceActivity.multipleChoice!.choices[index],
);
});
}
Widget get activityWidget {
switch (widget.practiceEvent.practiceActivity.activityType) {
case ActivityTypeEnum.multipleChoice:
return MultipleChoiceActivityView(
controller: this,
updateChoice: updateChoice,
isActive: !isSubmitted,
);
default:
return const SizedBox.shrink();
}
}
@override
Widget build(BuildContext context) {
debugPrint(
"MessagePracticeActivityContentState.build with selectedChoiceIndex: $selectedChoiceIndex",
);
return Column(
children: [
activityWidget,
const SizedBox(height: 8),
],
);
}
}

@ -1,15 +1,20 @@
import 'dart:developer';
import 'package:fluffychat/pangea/enum/message_mode_enum.dart';
import 'package:collection/collection.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
import 'package:fluffychat/pangea/matrix_event_wrappers/practice_acitivity_record_event.dart';
import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart';
import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart';
import 'package:fluffychat/pangea/utils/bot_style.dart';
import 'package:fluffychat/pangea/utils/error_handler.dart';
import 'package:fluffychat/pangea/widgets/chat/message_toolbar.dart';
import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_content.dart';
import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:matrix/matrix.dart';
class PracticeActivityCard extends StatefulWidget {
final PangeaMessageEvent pangeaMessageEvent;
@ -27,12 +32,32 @@ class PracticeActivityCard extends StatefulWidget {
}
class MessagePracticeActivityCardState extends State<PracticeActivityCard> {
List<PracticeActivityEvent> practiceActivities = [];
PracticeActivityEvent? practiceEvent;
PracticeActivityRecordModel? recordModel;
bool sending = false;
int get practiceEventIndex => practiceActivities.indexWhere(
(activity) => activity.event.eventId == practiceEvent?.event.eventId,
);
bool get isPrevEnabled =>
practiceEventIndex > 0 &&
practiceActivities.length > (practiceEventIndex - 1);
bool get isNextEnabled =>
practiceEventIndex >= 0 &&
practiceEventIndex < practiceActivities.length - 1;
// the first record for this practice activity
// assosiated with the current user
PracticeActivityRecordEvent? get recordEvent =>
practiceEvent?.userRecords.firstOrNull;
@override
void initState() {
super.initState();
loadInitialData();
setPracticeActivities();
}
String? get langCode {
@ -50,46 +75,106 @@ class MessagePracticeActivityCardState extends State<PracticeActivityCard> {
return langCode;
}
void loadInitialData() {
/// Initalizes the practice activities for the current language
/// and sets the first activity as the current activity
void setPracticeActivities() {
if (langCode == null) return;
updatePracticeActivity();
if (practiceEvent == null) {
debugger(when: kDebugMode);
}
}
void updatePracticeActivity() {
if (langCode == null) return;
final List<PracticeActivityEvent> activities =
practiceActivities =
widget.pangeaMessageEvent.practiceActivities(langCode!);
if (activities.isEmpty) return;
if (practiceActivities.isEmpty) return;
practiceActivities.sort(
(a, b) => a.event.originServerTs.compareTo(b.event.originServerTs),
);
// if the current activity hasn't been set yet, show the first uncompleted activity
// if there is one. If not, show the first activity
final List<PracticeActivityEvent> incompleteActivities =
activities.where((element) => !element.isComplete).toList();
debugPrint("total events: ${activities.length}");
debugPrint("incomplete practice events: ${incompleteActivities.length}");
// TODO update to show next activity
practiceEvent = activities.first;
// // if an incomplete activity is found, show that
// if (incompleteActivities.isNotEmpty) {
// practiceEvent = incompleteActivities.first;
// }
// // if no incomplete activity is found, show the last activity
// else if (activities.isNotEmpty) {
// practiceEvent = activities.last;
// }
practiceActivities.where((element) => !element.isComplete).toList();
practiceEvent ??= incompleteActivities.isNotEmpty
? incompleteActivities.first
: practiceActivities.first;
setState(() {});
}
void showNextActivity() {
if (langCode == null) return;
updatePracticeActivity();
widget.controller.updateMode(MessageMode.practiceActivity);
void navigateActivities({Direction? direction, int? index}) {
final bool enableNavigation = (direction == Direction.f && isNextEnabled) ||
(direction == Direction.b && isPrevEnabled) ||
(index != null && index >= 0 && index < practiceActivities.length);
if (enableNavigation) {
final int newIndex = index ??
(direction == Direction.f
? practiceEventIndex + 1
: practiceEventIndex - 1);
practiceEvent = practiceActivities[newIndex];
setState(() {});
}
}
void sendRecord() {
if (recordModel == null || practiceEvent == null) return;
setState(() => sending = true);
MatrixState.pangeaController.activityRecordController
.send(recordModel!, practiceEvent!)
.catchError((error) {
ErrorHandler.logError(
e: error,
s: StackTrace.current,
data: {
'recordModel': recordModel?.toJson(),
'practiceEvent': practiceEvent?.event.toJson(),
},
);
return null;
}).whenComplete(() => setState(() => sending = false));
}
@override
Widget build(BuildContext context) {
if (practiceEvent == null) {
final Widget navigationButtons = Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Opacity(
opacity: isPrevEnabled ? 1.0 : 0,
child: IconButton(
onPressed: isPrevEnabled
? () => navigateActivities(direction: Direction.b)
: null,
icon: const Icon(Icons.keyboard_arrow_left_outlined),
tooltip: L10n.of(context)!.previous,
),
),
Expanded(
child: Opacity(
opacity: recordEvent == null ? 1.0 : 0.5,
child: sending
? const CircularProgressIndicator.adaptive()
: TextButton(
onPressed: recordEvent == null ? sendRecord : null,
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all<Color>(
AppConfig.primaryColor,
),
),
child: Text(L10n.of(context)!.submit),
),
),
),
Opacity(
opacity: isNextEnabled ? 1.0 : 0,
child: IconButton(
onPressed: isNextEnabled
? () => navigateActivities(direction: Direction.f)
: null,
icon: const Icon(Icons.keyboard_arrow_right_outlined),
tooltip: L10n.of(context)!.next,
),
),
],
);
if (practiceEvent == null || practiceActivities.isEmpty) {
return Text(
L10n.of(context)!.noActivitiesFound,
style: BotStyle.text(context),
@ -99,10 +184,15 @@ class MessagePracticeActivityCardState extends State<PracticeActivityCard> {
// onActivityGenerated: updatePracticeActivity,
// );
}
return PracticeActivityContent(
practiceEvent: practiceEvent!,
pangeaMessageEvent: widget.pangeaMessageEvent,
controller: this,
return Column(
children: [
PracticeActivity(
pangeaMessageEvent: widget.pangeaMessageEvent,
practiceEvent: practiceEvent!,
controller: this,
),
navigationButtons,
],
);
}
}

@ -1,165 +0,0 @@
import 'package:collection/collection.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pangea/enum/activity_type_enum.dart';
import 'package:fluffychat/pangea/matrix_event_wrappers/pangea_message_event.dart';
import 'package:fluffychat/pangea/matrix_event_wrappers/practice_acitivity_record_event.dart';
import 'package:fluffychat/pangea/matrix_event_wrappers/practice_activity_event.dart';
import 'package:fluffychat/pangea/models/practice_activities.dart/practice_activity_record_model.dart';
import 'package:fluffychat/pangea/utils/error_handler.dart';
import 'package:fluffychat/pangea/widgets/practice_activity/multiple_choice_activity.dart';
import 'package:fluffychat/pangea/widgets/practice_activity/practice_activity_card.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
class PracticeActivityContent extends StatefulWidget {
final PracticeActivityEvent practiceEvent;
final PangeaMessageEvent pangeaMessageEvent;
final MessagePracticeActivityCardState controller;
const PracticeActivityContent({
super.key,
required this.practiceEvent,
required this.pangeaMessageEvent,
required this.controller,
});
@override
MessagePracticeActivityContentState createState() =>
MessagePracticeActivityContentState();
}
class MessagePracticeActivityContentState
extends State<PracticeActivityContent> {
int? selectedChoiceIndex;
PracticeActivityRecordModel? recordModel;
bool recordSubmittedThisSession = false;
bool recordSubmittedPreviousSession = false;
PracticeActivityEvent get practiceEvent => widget.practiceEvent;
@override
void initState() {
super.initState();
initalizeActivity();
}
@override
void didUpdateWidget(covariant PracticeActivityContent oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.practiceEvent.event.eventId !=
widget.practiceEvent.event.eventId) {
initalizeActivity();
}
}
void initalizeActivity() {
final PracticeActivityRecordEvent? recordEvent =
widget.practiceEvent.userRecords.firstOrNull;
if (recordEvent?.record == null) {
recordModel = PracticeActivityRecordModel(
question:
widget.practiceEvent.practiceActivity.multipleChoice!.question,
);
} else {
recordModel = recordEvent!.record;
//Note that only MultipleChoice activities will have this so we probably should move this logic to the MultipleChoiceActivity widget
selectedChoiceIndex = recordModel?.latestResponse != null
? widget.practiceEvent.practiceActivity.multipleChoice
?.choiceIndex(recordModel!.latestResponse!)
: null;
recordSubmittedPreviousSession = true;
recordSubmittedThisSession = true;
}
setState(() {});
}
void updateChoice(int index) {
setState(() {
selectedChoiceIndex = index;
recordModel!.addResponse(
text: widget
.practiceEvent.practiceActivity.multipleChoice!.choices[index],
);
});
}
Widget get activityWidget {
switch (widget.practiceEvent.practiceActivity.activityType) {
case ActivityTypeEnum.multipleChoice:
return MultipleChoiceActivity(
card: this,
updateChoice: updateChoice,
isActive:
!recordSubmittedPreviousSession && !recordSubmittedThisSession,
);
default:
return const SizedBox.shrink();
}
}
void sendRecord() {
MatrixState.pangeaController.activityRecordController
.send(
recordModel!,
widget.practiceEvent,
)
.catchError((error) {
ErrorHandler.logError(
e: error,
s: StackTrace.current,
data: {
'recordModel': recordModel?.toJson(),
'practiceEvent': widget.practiceEvent.event.toJson(),
},
);
return null;
}).then((_) => widget.controller.showNextActivity());
setState(() {
recordSubmittedThisSession = true;
});
}
@override
Widget build(BuildContext context) {
debugPrint(
"MessagePracticeActivityContentState.build with selectedChoiceIndex: $selectedChoiceIndex",
);
return Column(
children: [
activityWidget,
const SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Opacity(
opacity: selectedChoiceIndex != null &&
!recordSubmittedThisSession &&
!recordSubmittedPreviousSession
? 1.0
: 0.5,
child: TextButton(
onPressed: () {
if (recordSubmittedThisSession ||
recordSubmittedPreviousSession) {
return;
}
selectedChoiceIndex != null ? sendRecord() : null;
},
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all<Color>(
AppConfig.primaryColor,
),
),
child: Text(L10n.of(context)!.submit),
),
),
],
),
],
);
}
}

@ -863,7 +863,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"be": [
@ -2363,7 +2364,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"bn": [
@ -3859,7 +3861,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"bo": [
@ -5359,7 +5362,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"ca": [
@ -6261,7 +6265,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"cs": [
@ -7245,7 +7250,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"de": [
@ -8112,7 +8118,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"el": [
@ -9563,7 +9570,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"eo": [
@ -10712,7 +10720,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"es": [
@ -10727,7 +10736,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"et": [
@ -11594,7 +11604,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"eu": [
@ -12463,7 +12474,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"fa": [
@ -13469,7 +13481,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"fi": [
@ -14439,7 +14452,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"fil": [
@ -15765,7 +15779,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"fr": [
@ -16770,7 +16785,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"ga": [
@ -17904,7 +17920,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"gl": [
@ -18771,7 +18788,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"he": [
@ -20024,7 +20042,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"hi": [
@ -21517,7 +21536,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"hr": [
@ -22463,7 +22483,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"hu": [
@ -23346,7 +23367,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"ia": [
@ -24832,7 +24854,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"id": [
@ -25705,7 +25728,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"ie": [
@ -26962,7 +26986,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"it": [
@ -27886,7 +27911,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"ja": [
@ -28921,7 +28947,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"ka": [
@ -30275,7 +30302,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"ko": [
@ -31144,7 +31172,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"lt": [
@ -32179,7 +32208,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"lv": [
@ -33054,7 +33084,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"nb": [
@ -34253,7 +34284,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"nl": [
@ -35216,7 +35248,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"pl": [
@ -36188,7 +36221,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"pt": [
@ -37666,7 +37700,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"pt_BR": [
@ -38539,7 +38574,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"pt_PT": [
@ -39739,7 +39775,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"ro": [
@ -40746,7 +40783,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"ru": [
@ -41619,7 +41657,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"sk": [
@ -42885,7 +42924,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"sl": [
@ -44281,7 +44321,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"sr": [
@ -45451,7 +45492,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"sv": [
@ -46355,7 +46397,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"ta": [
@ -47852,7 +47895,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"th": [
@ -49303,7 +49347,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"tr": [
@ -50170,7 +50215,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"uk": [
@ -51074,7 +51120,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"vi": [
@ -52426,7 +52473,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"zh": [
@ -53293,7 +53341,8 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
],
"zh_Hant": [
@ -54441,6 +54490,7 @@
"suggestToSpaceDesc",
"practice",
"noLanguagesSet",
"noActivitiesFound"
"noActivitiesFound",
"previous"
]
}

Loading…
Cancel
Save