diff --git a/lib/Screens/Configurations/Section/SubSection/Agenda/agenda_config.dart b/lib/Screens/Configurations/Section/SubSection/Agenda/agenda_config.dart index 77f79b4..0a9f7a8 100644 --- a/lib/Screens/Configurations/Section/SubSection/Agenda/agenda_config.dart +++ b/lib/Screens/Configurations/Section/SubSection/Agenda/agenda_config.dart @@ -497,6 +497,18 @@ class _AgendaConfigState extends State { }); }, ), + if (agendaDTO.agendaMapProvider != null) + // Voir map_config.dart : réglage mobile/tablette, le web garde Leaflet. + Padding( + padding: const EdgeInsets.only(top: 4, bottom: 8), + child: Text( + AppLocalizations.of(context)!.mapProviderMobileOnlyNote, + style: TextStyle( + fontSize: 12, + fontStyle: FontStyle.italic, + color: Colors.grey[600]), + ), + ), if (agendaDTO.isOnlineAgenda == true) MultiStringInputContainer( label: AppLocalizations.of(context)!.jsonFilesLabel, diff --git a/lib/Screens/Configurations/Section/SubSection/Map/map_config.dart b/lib/Screens/Configurations/Section/SubSection/Map/map_config.dart index 2a9d366..0a92673 100644 --- a/lib/Screens/Configurations/Section/SubSection/Map/map_config.dart +++ b/lib/Screens/Configurations/Section/SubSection/Map/map_config.dart @@ -642,6 +642,21 @@ class _MapConfigState extends State { isSmall: true), ], ), + const SizedBox(height: 8), + // Décision du 2026-08-11 (lot E, W1) : visitapp-web reste sur Leaflet. + // Le champ ne peut pas être masqué pour le web — il est porté par la + // section, et une même configuration est servie au mobile comme au web. + // On le dit donc au client au lieu de le laisser croire le contraire. + Align( + alignment: Alignment.centerLeft, + child: Text( + AppLocalizations.of(context)!.mapProviderMobileOnlyNote, + style: TextStyle( + fontSize: 12, + fontStyle: FontStyle.italic, + color: Colors.grey[600]), + ), + ), const SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, diff --git a/lib/Screens/Configurations/Section/SubSection/Parcours/showNewOrUpdateGuidedStep.dart b/lib/Screens/Configurations/Section/SubSection/Parcours/showNewOrUpdateGuidedStep.dart index 0edd4b4..573d79d 100644 --- a/lib/Screens/Configurations/Section/SubSection/Parcours/showNewOrUpdateGuidedStep.dart +++ b/lib/Screens/Configurations/Section/SubSection/Parcours/showNewOrUpdateGuidedStep.dart @@ -18,6 +18,15 @@ import 'package:manager_app/l10n/app_localizations.dart'; import 'package:provider/provider.dart'; import 'showNewOrUpdateQuizQuestion.dart'; +/// Médias acceptés sur une étape de parcours. Le PDF s'ajoute aux types du +/// slider : une étape peut porter un plan, une partition, un fac-similé. +/// Le rendu visiteur correspondant vit dans `CachedCustomResource` +/// (mymuseum-visitapp) et `ResourceViewer.tsx` (visitapp-web). +const kGuidedStepResourceTypes = [ + ...kSliderContentResourceTypes, + ResourceType.Pdf, +]; + void showNewOrUpdateGuidedStep( BuildContext context, GuidedStepDTO? step, @@ -248,7 +257,10 @@ void showNewOrUpdateGuidedStep( IconButton( icon: Icon(Icons.add_circle_outline, color: kSuccess), onPressed: () async { - final result = await showNewOrUpdateContentSlider(null, appCtx, context, true, false); + final result = await showNewOrUpdateContentSlider( + null, appCtx, context, true, false, + resourceTypes: kGuidedStepResourceTypes, + ); if (result != null) { setState(() { result.order = workingStep.contents!.length; @@ -438,7 +450,7 @@ void showNewOrUpdateGuidedStep( textStyle: TextStyle(fontSize: 14), ), subtitle: Text( - "Type: ${question.validationQuestionType?.value == 2 ? 'Puzzle' : question.validationQuestionType?.value == 1 ? 'QCM' : 'Texte'}"), + "Type: ${question.validationQuestionType == QuestionType.puzzle ? 'Puzzle' : question.validationQuestionType == QuestionType.multipleChoice ? 'QCM' : 'Texte'}"), ); }, actions: [ diff --git a/lib/Screens/Configurations/Section/SubSection/Parcours/showNewOrUpdateQuizQuestion.dart b/lib/Screens/Configurations/Section/SubSection/Parcours/showNewOrUpdateQuizQuestion.dart index 7d3bec8..1365eb3 100644 --- a/lib/Screens/Configurations/Section/SubSection/Parcours/showNewOrUpdateQuizQuestion.dart +++ b/lib/Screens/Configurations/Section/SubSection/Parcours/showNewOrUpdateQuizQuestion.dart @@ -54,7 +54,7 @@ void showNewOrUpdateQuizQuestion( id: 0, label: _fromTranslationList(workingLabel), responses: workingResponses, - validationQuestionType: QuestionType.number0, + validationQuestionType: QuestionType.simple, order: question?.order ?? 0, guidedStepId: question?.guidedStepId ?? stepId, ); @@ -163,13 +163,13 @@ void showNewOrUpdateQuizQuestion( value: workingQuestion.validationQuestionType, items: [ DropdownMenuItem( - value: QuestionType.number0, + value: QuestionType.simple, child: Text("Simple (texte attendu)")), DropdownMenuItem( - value: QuestionType.number1, + value: QuestionType.multipleChoice, child: Text("Choix multiples (QCM)")), DropdownMenuItem( - value: QuestionType.number2, + value: QuestionType.puzzle, child: Text("Puzzle")), ], onChanged: (val) => setState(() { @@ -182,7 +182,7 @@ void showNewOrUpdateQuizQuestion( // Type 0 : Simple texte // ========================================= if (workingQuestion.validationQuestionType == - QuestionType.number0) ...[ + QuestionType.simple) ...[ Divider(height: 24), Text(AppLocalizations.of(context)!.expectedAnswerLabel, style: TextStyle(fontWeight: FontWeight.bold)), @@ -245,7 +245,7 @@ void showNewOrUpdateQuizQuestion( // Type 1 : QCM // ========================================= if (workingQuestion.validationQuestionType == - QuestionType.number1) ...[ + QuestionType.multipleChoice) ...[ Divider(height: 24), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -349,7 +349,7 @@ void showNewOrUpdateQuizQuestion( // Type 2 : Puzzle // ========================================= if (workingQuestion.validationQuestionType == - QuestionType.number2) ...[ + QuestionType.puzzle) ...[ Divider(height: 24), Text("Configuration du Puzzle", style: TextStyle(fontWeight: FontWeight.bold)), diff --git a/lib/Screens/Configurations/Section/SubSection/Slider/new_update_image_slider.dart b/lib/Screens/Configurations/Section/SubSection/Slider/new_update_image_slider.dart index 32c3f89..c51da38 100644 --- a/lib/Screens/Configurations/Section/SubSection/Slider/new_update_image_slider.dart +++ b/lib/Screens/Configurations/Section/SubSection/Slider/new_update_image_slider.dart @@ -8,7 +8,22 @@ import 'package:manager_app/constants.dart'; import 'package:manager_app/l10n/app_localizations.dart'; import 'package:manager_api_new/api.dart'; -Future showNewOrUpdateContentSlider(ContentDTO? inputContentDTO, AppContext appContext, BuildContext context, bool showTitle, bool showDescription) async { +/// Types de ressource proposés par défaut pour un contenu de slider. +const kSliderContentResourceTypes = [ + ResourceType.Image, + ResourceType.ImageUrl, + ResourceType.Video, + ResourceType.VideoUrl, + ResourceType.Audio, +]; + +Future showNewOrUpdateContentSlider( + ContentDTO? inputContentDTO, + AppContext appContext, + BuildContext context, + bool showTitle, + bool showDescription, + {List resourceTypes = kSliderContentResourceTypes}) async { ContentDTO contentDTO = new ContentDTO(); if (inputContentDTO != null) { @@ -64,7 +79,7 @@ Future showNewOrUpdateContentSlider(ContentDTO? inputContentDTO, Ap initialValue: contentDTO.resourceId, color: kPrimaryColor, fontSize: 20, - inResourceTypes: [ResourceType.Image, ResourceType.ImageUrl, ResourceType.Video, ResourceType.VideoUrl, ResourceType.Audio], + inResourceTypes: resourceTypes, onChanged: (ResourceDTO resource) { if(resource.id == null) { contentDTO.resourceId = null; diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 2a9e993..d24a172 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -684,5 +684,6 @@ "annotationsLabel": "Annotations", "discardPathChangesConfirm": "This path has unsaved changes, along with its steps and their questions. Discard these changes?", "discardStepChangesConfirm": "This step has unsaved changes, along with its questions. Discard these changes?", - "discardQuestionChangesConfirm": "This question has unsaved changes, along with its answers. Discard these changes?" + "discardQuestionChangesConfirm": "This question has unsaved changes, along with its answers. Discard these changes?", + "mapProviderMobileOnlyNote": "The map provider and type apply to the mobile and tablet apps. The web app always renders its own map." } diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index fa6b9e4..337c170 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -684,5 +684,6 @@ "annotationsLabel": "Annotations", "discardPathChangesConfirm": "Ce parcours contient des modifications non enregistrées, ainsi que ses étapes et leurs questions. Abandonner ces modifications ?", "discardStepChangesConfirm": "Cette étape contient des modifications non enregistrées, ainsi que ses questions. Abandonner ces modifications ?", - "discardQuestionChangesConfirm": "Cette question contient des modifications non enregistrées, ainsi que ses réponses. Abandonner ces modifications ?" + "discardQuestionChangesConfirm": "Cette question contient des modifications non enregistrées, ainsi que ses réponses. Abandonner ces modifications ?", + "mapProviderMobileOnlyNote": "Le fournisseur et le type de carte s'appliquent aux applications mobile et tablette. L'application web affiche toujours sa propre carte." } diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index d702094..15844fd 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -3315,6 +3315,12 @@ abstract class AppLocalizations { /// In fr, this message translates to: /// **'Cette question contient des modifications non enregistrées, ainsi que ses réponses. Abandonner ces modifications ?'** String get discardQuestionChangesConfirm; + + /// No description provided for @mapProviderMobileOnlyNote. + /// + /// In fr, this message translates to: + /// **'Le fournisseur et le type de carte s\'appliquent aux applications mobile et tablette. L\'application web affiche toujours sa propre carte.'** + String get mapProviderMobileOnlyNote; } class _AppLocalizationsDelegate diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 9439e2e..4149ec5 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -1756,4 +1756,8 @@ class AppLocalizationsEn extends AppLocalizations { @override String get discardQuestionChangesConfirm => 'This question has unsaved changes, along with its answers. Discard these changes?'; + + @override + String get mapProviderMobileOnlyNote => + 'The map provider and type apply to the mobile and tablet apps. The web app always renders its own map.'; } diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index dbc9813..4c0c6b9 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -1794,4 +1794,8 @@ class AppLocalizationsFr extends AppLocalizations { @override String get discardQuestionChangesConfirm => 'Cette question contient des modifications non enregistrées, ainsi que ses réponses. Abandonner ces modifications ?'; + + @override + String get mapProviderMobileOnlyNote => + 'Le fournisseur et le type de carte s\'appliquent aux applications mobile et tablette. L\'application web affiche toujours sa propre carte.'; } diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index a7d10b1..47e65b1 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -1773,4 +1773,8 @@ class AppLocalizationsNl extends AppLocalizations { @override String get discardQuestionChangesConfirm => 'Deze vraag heeft niet-opgeslagen wijzigingen, samen met de antwoorden. Deze wijzigingen weggooien?'; + + @override + String get mapProviderMobileOnlyNote => + 'De kaartprovider en het kaarttype gelden voor de mobiele en tablet-apps. De web-app toont altijd zijn eigen kaart.'; } diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb index 0f4098e..98094be 100644 --- a/lib/l10n/app_nl.arb +++ b/lib/l10n/app_nl.arb @@ -684,5 +684,6 @@ "annotationsLabel": "Annotaties", "discardPathChangesConfirm": "Deze route heeft niet-opgeslagen wijzigingen, samen met de stappen en hun vragen. Deze wijzigingen weggooien?", "discardStepChangesConfirm": "Deze stap heeft niet-opgeslagen wijzigingen, samen met de vragen. Deze wijzigingen weggooien?", - "discardQuestionChangesConfirm": "Deze vraag heeft niet-opgeslagen wijzigingen, samen met de antwoorden. Deze wijzigingen weggooien?" + "discardQuestionChangesConfirm": "Deze vraag heeft niet-opgeslagen wijzigingen, samen met de antwoorden. Deze wijzigingen weggooien?", + "mapProviderMobileOnlyNote": "De kaartprovider en het kaarttype gelden voor de mobiele en tablet-apps. De web-app toont altijd zijn eigen kaart." } diff --git a/manager_api_new/lib/model/question_type.dart b/manager_api_new/lib/model/question_type.dart index d931d30..36dea84 100644 --- a/manager_api_new/lib/model/question_type.dart +++ b/manager_api_new/lib/model/question_type.dart @@ -27,6 +27,14 @@ class QuestionType { static const number1 = QuestionType._(1); static const number2 = QuestionType._(2); + // Ajouts manuels : le générateur nomme les valeurs number0/1/2, ce qui poussait + // le front à comparer des entiers bruts. Ces alias portent les noms de l'enum + // serveur (`QuizQuestion.QuestionType` : Simple, MultipleChoice, Puzzle). + // `values` n'est pas modifié — ce sont les mêmes trois valeurs, pas de nouvelles. + static const simple = number0; + static const multipleChoice = number1; + static const puzzle = number2; + /// List of all possible values in this [enum][QuestionType]. static const values = [ number0,