Thomas Fransolet b87e49d808 Cle d'API sur les routes visiteur, canal VR et contenu immersif
Securite
- RequireAppKey : filtre qui exige une cle d'API valide ou un utilisateur du
  manager. Pose sur les routes de contenu consommees par les apps visiteur
  (Configuration, Section, Resource, SectionMap, SectionEvent, SectionAgenda,
  SectionParcours, SectionQuiz, ApplicationInstance). Un [Authorize] d'action
  ne peut pas assouplir celui de la classe ; seul [AllowAnonymous] le
  court-circuite, et le filtre redevient le controle d'acces. Il ferme
  l'enumeration par identifiant, pas la confidentialite : la cle s'obtient
  par le slug ou le pincode.
- Instance/slug/{slug} rendait le pinCode, l'adresse de facturation, la TVA et
  les quotas a qui lit l'URL du site visiteur. StripCommercialFields est
  desormais applique sur slug et byPin ; isTrialActive reste expose pour le
  filigrane d'essai.
- Device.Create et Device/{id}/detail repondaient 403 a toute tablette depuis
  a452f4a (13/03) : la classe exige InstanceAdmin, une cle ne porte que
  AppRead. Ouverts a la cle, le cloisonnement par instance etait deja ecrit.

Canal VR
- Device.AppType (defaut Tablet, backfill a 1) ; Create resout
  l'ApplicationInstance sur ce type au lieu de Tablet en dur.
- Get filtre optionnellement par appType ; DeviceDetailDTO expose appVersion
  et lastSeen.
- PUT Device/{id}/heartbeat : batterie, version, connexion. Volontairement
  etroit, une app ne peut ni se renommer ni changer d'instance.
- ApiKeyAppType.VrApp en fin d'enum.

Contenu immersif
- ResourceType : Image360 (11), Video360 (12), Model3D (13), en fin d'enum.
- Section Scene3D : un modele GLB et ses points d'interet, en objet manipule
  ou en decor habite. Les points sont des GeoPoint, avec une LocalTransform
  en jsonb (convention glTF) ; CRUD dans SectionScene3DController.
- Instance.HasImmersiveContent : l'add-on ajoute 100 Go au quota de stockage,
  repose apres un changement de plan et retire a la desactivation.
- ImmersiveBackground (owned) sur Configuration et ApplicationInstance, avec
  une image de repli pour les canaux qui ne rendent pas l'immersif.

Export de configuration
- exportVersion (1) et generatedAt : le JSON devient un contrat, lu tel quel
  par l'app Unity.
- Section.ToDTO() n'etant pas virtuelle, l'export ne portait aucun champ
  specifique de sous-type. Passe par SectionFactory.ToDTO, et charge les
  points des Map et des Scene3D.
- Le fond immersif et son repli partent avec les ressources, URL resolues.

Migrations : AddAppTypeToDevice, AddScene3DSectionAndImmersiveAddon,
AddImmersiveBackground.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-13 16:54:10 +02:00

822 lines
38 KiB
C#

using Manager.DTOs;
using ManagerService.Data;
using ManagerService.Data.SubSection;
using ManagerService.DTOs;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
namespace ManagerService.Services
{
public static class SectionFactory
{
/// <summary>
/// Sous-type concret vide, collections initialisées. Section étant abstraite,
/// c'est le seul point d'entrée pour créer une section dont on n'a que le type.
/// </summary>
public static Section CreateEmpty(SectionType type) => type switch
{
SectionType.Agenda => new SectionAgenda
{
AgendaResourceIds = new List<TranslationDTO>(),
EventAgendas = new List<EventAgenda>()
},
SectionType.Article => new SectionArticle
{
ArticleContents = new List<ContentDTO>(),
ArticleContent = new List<TranslationDTO>(),
ArticleAudioIds = new List<TranslationDTO>()
},
SectionType.Event => new SectionEvent
{
Programme = new List<SectionEvent.ProgrammeBlock>()
},
SectionType.Map => new SectionMap
{
MapMapType = MapTypeApp.hybrid,
MapTypeMapbox = MapTypeMapBox.standard,
MapMapProvider = MapProvider.Google,
MapZoom = 18,
MapPoints = new List<GeoPoint>(),
MapCategories = new List<CategorieDTO>()
},
SectionType.Menu => new SectionMenu { MenuSections = new List<Section>() },
SectionType.PDF => new SectionPdf { PDFOrderedTranslationAndResources = new List<OrderedTranslationAndResourceDTO>() },
SectionType.Game => new SectionGame
{
GameMessageDebut = new List<TranslationAndResourceDTO>(),
GameMessageFin = new List<TranslationAndResourceDTO>()
},
SectionType.Quiz => new SectionQuiz { QuizQuestions = new List<QuizQuestion>() },
SectionType.Slider => new SectionSlider { SliderContents = new List<ContentDTO>() },
SectionType.Video => new SectionVideo { VideoSource = "" },
SectionType.Weather => new SectionWeather(),
SectionType.Web => new SectionWeb { WebSource = "" },
SectionType.Parcours => new SectionParcours { GuidedPaths = new List<GuidedPath>() },
SectionType.Scene3D => new SectionScene3D { Points = new List<GeoPoint>() },
_ => throw new NotImplementedException($"Section type not handled: {type}")
};
public static Section Create(JsonElement jsonElement, SectionDTO dto)
{
AgendaDTO agendaDTO = new AgendaDTO();
ArticleDTO articleDTO = new ArticleDTO();
SectionEventDTO sectionEventDTO = new SectionEventDTO();
MapDTO mapDTO = new MapDTO();
MenuDTO menuDTO = new MenuDTO();
PdfDTO pdfDTO = new PdfDTO();
GameDTO puzzleDTO = new GameDTO();
QuizDTO quizDTO = new QuizDTO();
SliderDTO sliderDTO = new SliderDTO();
VideoDTO videoDTO = new VideoDTO();
WeatherDTO weatherDTO = new WeatherDTO();
WebDTO webDTO = new WebDTO();
ParcoursDTO parcoursDTO = new ParcoursDTO();
Scene3DDTO model3DDTO = new Scene3DDTO();
switch (dto.type)
{
case SectionType.Agenda:
agendaDTO = JsonConvert.DeserializeObject<AgendaDTO>(jsonElement.ToString());
break;
case SectionType.Article:
articleDTO = JsonConvert.DeserializeObject<ArticleDTO>(jsonElement.ToString());
break;
case SectionType.Event:
sectionEventDTO = JsonConvert.DeserializeObject<SectionEventDTO>(
jsonElement.ToString(),
new JsonSerializerSettings { Error = (_, args) => args.ErrorContext.Handled = true }
);
break;
case SectionType.Map:
mapDTO = JsonConvert.DeserializeObject<MapDTO>(jsonElement.ToString());
break;
case SectionType.Menu:
menuDTO = JsonConvert.DeserializeObject<MenuDTO>(jsonElement.ToString());
break;
case SectionType.PDF:
pdfDTO = JsonConvert.DeserializeObject<PdfDTO>(jsonElement.ToString());
break;
case SectionType.Game:
puzzleDTO = JsonConvert.DeserializeObject<GameDTO>(jsonElement.ToString());
break;
case SectionType.Quiz:
quizDTO = JsonConvert.DeserializeObject<QuizDTO>(jsonElement.ToString());
break;
case SectionType.Slider:
sliderDTO = JsonConvert.DeserializeObject<SliderDTO>(jsonElement.ToString());
break;
case SectionType.Video:
videoDTO = JsonConvert.DeserializeObject<VideoDTO>(jsonElement.ToString());
break;
case SectionType.Weather:
weatherDTO = JsonConvert.DeserializeObject<WeatherDTO>(jsonElement.ToString());
break;
case SectionType.Web:
webDTO = JsonConvert.DeserializeObject<WebDTO>(jsonElement.ToString());
break;
case SectionType.Parcours:
parcoursDTO = JsonConvert.DeserializeObject<ParcoursDTO>(jsonElement.ToString());
break;
case SectionType.Scene3D:
model3DDTO = JsonConvert.DeserializeObject<Scene3DDTO>(jsonElement.ToString());
break;
}
return dto.type switch
{
SectionType.Agenda => new SectionAgenda
{
Id = dto.id,
DateCreation = dto.dateCreation.Value,
ConfigurationId = dto.configurationId,
InstanceId = dto.instanceId,
Label = dto.label,
Title = dto.title,
Description = dto.description,
Order = dto.order.Value,
ImageId = dto.imageId,
ImageSource = dto.imageSource,
IsSubSection = dto.isSubSection,
ParentId = dto.parentId,
IsBeacon = dto.isBeacon,
BeaconId = dto.beaconId,
Latitude = dto.latitude,
Longitude = dto.longitude,
MeterZoneGPS = dto.meterZoneGPS,
Type = dto.type,
IsOnlineAgenda = agendaDTO.isOnlineAgenda,
AgendaResourceIds = agendaDTO.resourceIds,
AgendaMapProvider = agendaDTO.agendaMapProvider,
//EventAgendas = // TODO specific
},
SectionType.Article => new SectionArticle
{
Id = dto.id,
DateCreation = dto.dateCreation.Value,
ConfigurationId = dto.configurationId,
InstanceId = dto.instanceId,
Label = dto.label,
Title = dto.title,
Description = dto.description,
Order = dto.order.Value,
ImageId = dto.imageId,
ImageSource = dto.imageSource,
IsSubSection = dto.isSubSection,
ParentId = dto.parentId,
IsBeacon = dto.isBeacon,
BeaconId = dto.beaconId,
Latitude = dto.latitude,
Longitude = dto.longitude,
MeterZoneGPS = dto.meterZoneGPS,
Type = dto.type,
ArticleContent = articleDTO.content,
ArticleIsContentTop = articleDTO.isContentTop,
ArticleAudioIds = articleDTO.audioIds,
ArticleIsReadAudioAuto = articleDTO.isReadAudioAuto,
ArticleContents = articleDTO.contents
},
SectionType.Event => new SectionEvent
{
Id = dto.id,
DateCreation = dto.dateCreation.Value,
ConfigurationId = dto.configurationId,
InstanceId = dto.instanceId,
Label = dto.label,
Title = dto.title,
Description = dto.description,
Order = dto.order.Value,
ImageId = dto.imageId,
ImageSource = dto.imageSource,
IsSubSection = dto.isSubSection,
ParentId = dto.parentId,
IsBeacon = dto.isBeacon,
BeaconId = dto.beaconId,
Latitude = dto.latitude,
Longitude = dto.longitude,
MeterZoneGPS = dto.meterZoneGPS,
Type = dto.type,
StartDate = sectionEventDTO.StartDate?.ToUniversalTime(),
EndDate = sectionEventDTO.EndDate?.ToUniversalTime(),
BaseSectionMapId = sectionEventDTO.BaseSectionMapId,
//Programmes = // TODO specific
},
SectionType.Map => new SectionMap
{
Id = dto.id,
DateCreation = dto.dateCreation.Value,
ConfigurationId = dto.configurationId,
InstanceId = dto.instanceId,
Label = dto.label,
Title = dto.title,
Description = dto.description,
Order = dto.order.Value,
ImageId = dto.imageId,
ImageSource = dto.imageSource,
IsSubSection = dto.isSubSection,
ParentId = dto.parentId,
IsBeacon = dto.isBeacon,
BeaconId = dto.beaconId,
Latitude = dto.latitude,
Longitude = dto.longitude,
MeterZoneGPS = dto.meterZoneGPS,
Type = dto.type,
MapZoom = mapDTO.zoom ?? 18,
MapMapType = mapDTO.mapType,
MapTypeMapbox = mapDTO.mapTypeMapbox,
MapMapProvider = mapDTO.mapProvider,
IconResourceId = mapDTO.iconResourceId,
MapCenterLatitude = mapDTO.centerLatitude,
MapCenterLongitude = mapDTO.centerLongitude,
MapCategories = mapDTO.categories,
IsListViewEnabled = mapDTO.isListViewEnabled
},
SectionType.Menu => new SectionMenu
{
Id = dto.id,
DateCreation = dto.dateCreation.Value,
ConfigurationId = dto.configurationId,
InstanceId = dto.instanceId,
Label = dto.label,
Title = dto.title,
Description = dto.description,
Order = dto.order.Value,
ImageId = dto.imageId,
ImageSource = dto.imageSource,
IsSubSection = dto.isSubSection,
ParentId = dto.parentId,
IsBeacon = dto.isBeacon,
BeaconId = dto.beaconId,
Latitude = dto.latitude,
Longitude = dto.longitude,
MeterZoneGPS = dto.meterZoneGPS,
Type = dto.type,
//Sections = ((MenuDTO)dto).sections, // TODO specific
},
SectionType.PDF => new SectionPdf
{
Id = dto.id,
DateCreation = dto.dateCreation.Value,
ConfigurationId = dto.configurationId,
InstanceId = dto.instanceId,
Label = dto.label,
Title = dto.title,
Description = dto.description,
Order = dto.order.Value,
ImageId = dto.imageId,
ImageSource = dto.imageSource,
IsSubSection = dto.isSubSection,
ParentId = dto.parentId,
IsBeacon = dto.isBeacon,
BeaconId = dto.beaconId,
Latitude = dto.latitude,
Longitude = dto.longitude,
MeterZoneGPS = dto.meterZoneGPS,
Type = dto.type,
PDFOrderedTranslationAndResources = pdfDTO.pdfs
},
SectionType.Game => new SectionGame
{
Id = dto.id,
DateCreation = dto.dateCreation.Value,
ConfigurationId = dto.configurationId,
InstanceId = dto.instanceId,
Label = dto.label,
Title = dto.title,
Description = dto.description,
Order = dto.order.Value,
ImageId = dto.imageId,
ImageSource = dto.imageSource,
IsSubSection = dto.isSubSection,
ParentId = dto.parentId,
IsBeacon = dto.isBeacon,
BeaconId = dto.beaconId,
Latitude = dto.latitude,
Longitude = dto.longitude,
MeterZoneGPS = dto.meterZoneGPS,
Type = dto.type,
GameMessageDebut = puzzleDTO.messageDebut,
GameMessageFin = puzzleDTO.messageFin,
GamePuzzleImageId = puzzleDTO.puzzleImageId,
GamePuzzleRows = puzzleDTO.rows,
GamePuzzleCols = puzzleDTO.cols,
GameType = puzzleDTO.gameType,
},
SectionType.Quiz => new SectionQuiz
{
Id = dto.id,
DateCreation = dto.dateCreation.Value,
ConfigurationId = dto.configurationId,
InstanceId = dto.instanceId,
Label = dto.label,
Title = dto.title,
Description = dto.description,
Order = dto.order.Value,
ImageId = dto.imageId,
ImageSource = dto.imageSource,
IsSubSection = dto.isSubSection,
ParentId = dto.parentId,
IsBeacon = dto.isBeacon,
BeaconId = dto.beaconId,
Latitude = dto.latitude,
Longitude = dto.longitude,
MeterZoneGPS = dto.meterZoneGPS,
Type = dto.type,
QuizBadLevel = quizDTO.bad_level,
QuizMediumLevel = quizDTO.medium_level,
QuizGoodLevel = quizDTO.good_level,
QuizGreatLevel = quizDTO.great_level,
//Questions = ((QuizDTO)dto).questions, // TODO specific
},
SectionType.Slider => new SectionSlider
{
Id = dto.id,
DateCreation = dto.dateCreation.Value,
ConfigurationId = dto.configurationId,
InstanceId = dto.instanceId,
Label = dto.label,
Title = dto.title,
Description = dto.description,
Order = dto.order.Value,
ImageId = dto.imageId,
ImageSource = dto.imageSource,
IsSubSection = dto.isSubSection,
ParentId = dto.parentId,
IsBeacon = dto.isBeacon,
BeaconId = dto.beaconId,
Latitude = dto.latitude,
Longitude = dto.longitude,
MeterZoneGPS = dto.meterZoneGPS,
Type = dto.type,
SliderContents = sliderDTO.contents, // TODO TEST
},
SectionType.Video => new SectionVideo
{
Id = dto.id,
DateCreation = dto.dateCreation.Value,
ConfigurationId = dto.configurationId,
InstanceId = dto.instanceId,
Label = dto.label,
Title = dto.title,
Description = dto.description,
Order = dto.order.Value,
ImageId = dto.imageId,
ImageSource = dto.imageSource,
IsSubSection = dto.isSubSection,
ParentId = dto.parentId,
IsBeacon = dto.isBeacon,
BeaconId = dto.beaconId,
Latitude = dto.latitude,
Longitude = dto.longitude,
MeterZoneGPS = dto.meterZoneGPS,
Type = dto.type,
VideoSource = videoDTO.source,
},
SectionType.Weather => new SectionWeather
{
Id = dto.id,
DateCreation = dto.dateCreation.Value,
ConfigurationId = dto.configurationId,
InstanceId = dto.instanceId,
Label = dto.label,
Title = dto.title,
Description = dto.description,
Order = dto.order.Value,
ImageId = dto.imageId,
ImageSource = dto.imageSource,
IsSubSection = dto.isSubSection,
ParentId = dto.parentId,
IsBeacon = dto.isBeacon,
BeaconId = dto.beaconId,
Latitude = dto.latitude,
Longitude = dto.longitude,
MeterZoneGPS = dto.meterZoneGPS,
Type = dto.type,
WeatherCity = weatherDTO.city,
WeatherUpdatedDate = weatherDTO.updatedDate,
WeatherResult = weatherDTO.result
},
SectionType.Web => new SectionWeb
{
Id = dto.id,
DateCreation = dto.dateCreation.Value,
ConfigurationId = dto.configurationId,
InstanceId = dto.instanceId,
Label = dto.label,
Title = dto.title,
Description = dto.description,
Order = dto.order.Value,
ImageId = dto.imageId,
ImageSource = dto.imageSource,
IsSubSection = dto.isSubSection,
ParentId = dto.parentId,
IsBeacon = dto.isBeacon,
BeaconId = dto.beaconId,
Latitude = dto.latitude,
Longitude = dto.longitude,
MeterZoneGPS = dto.meterZoneGPS,
Type = dto.type,
WebSource = webDTO.source,
},
SectionType.Parcours => new SectionParcours
{
Id = dto.id,
DateCreation = dto.dateCreation.Value,
ConfigurationId = dto.configurationId,
InstanceId = dto.instanceId,
Label = dto.label,
Title = dto.title,
Description = dto.description,
Order = dto.order.Value,
ImageId = dto.imageId,
ImageSource = dto.imageSource,
IsSubSection = dto.isSubSection,
ParentId = dto.parentId,
IsBeacon = dto.isBeacon,
BeaconId = dto.beaconId,
Latitude = dto.latitude,
Longitude = dto.longitude,
MeterZoneGPS = dto.meterZoneGPS,
Type = dto.type,
ShowMap = parcoursDTO.showMap,
BaseSectionMapId = parcoursDTO.baseSectionMapId,
},
SectionType.Scene3D => new SectionScene3D
{
Id = dto.id,
DateCreation = dto.dateCreation.Value,
ConfigurationId = dto.configurationId,
InstanceId = dto.instanceId,
Label = dto.label,
Title = dto.title,
Description = dto.description,
Order = dto.order.Value,
ImageId = dto.imageId,
ImageSource = dto.imageSource,
IsSubSection = dto.isSubSection,
ParentId = dto.parentId,
IsBeacon = dto.isBeacon,
BeaconId = dto.beaconId,
Latitude = dto.latitude,
Longitude = dto.longitude,
MeterZoneGPS = dto.meterZoneGPS,
Type = dto.type,
Model3DResourceId = model3DDTO.model3DResourceId,
Model3DSource = model3DDTO.model3DSource,
Mode = model3DDTO.mode,
// Les points arrivent par l'éditeur de points, pas par la création de
// la section — comme pour une Map.
},
_ => throw new NotImplementedException("Section type not handled")
};
}
public static object ToDTO(Section section)
{
// TODO retrieve specific elements ?
return section switch
{
SectionAgenda agenda => new AgendaDTO
{
id = agenda.Id,
dateCreation = agenda.DateCreation,
configurationId = agenda.ConfigurationId,
instanceId = agenda.InstanceId,
label = agenda.Label,
title = agenda.Title,
description = agenda.Description,
order = agenda.Order,
imageId = agenda.ImageId,
imageSource = agenda.ImageSource,
isActive = agenda.IsActive,
isSubSection = agenda.IsSubSection,
parentId = agenda.ParentId,
isBeacon = agenda.IsBeacon,
beaconId = agenda.BeaconId,
latitude = agenda.Latitude,
longitude = agenda.Longitude,
meterZoneGPS = agenda.MeterZoneGPS,
type = agenda.Type,
isOnlineAgenda = agenda.IsOnlineAgenda,
resourceIds = agenda.AgendaResourceIds,
agendaMapProvider = agenda.AgendaMapProvider,
// events => TODO specific
},
SectionArticle article => new ArticleDTO
{
id = article.Id,
dateCreation = article.DateCreation,
configurationId = article.ConfigurationId,
instanceId = article.InstanceId,
label = article.Label,
title = article.Title,
description = article.Description,
order = article.Order,
imageId = article.ImageId,
imageSource = article.ImageSource,
isActive = article.IsActive,
isSubSection = article.IsSubSection,
parentId = article.ParentId,
isBeacon = article.IsBeacon,
beaconId = article.BeaconId,
latitude = article.Latitude,
longitude = article.Longitude,
meterZoneGPS = article.MeterZoneGPS,
type = article.Type,
content = article.ArticleContent,
isContentTop = article.ArticleIsContentTop,
audioIds = article.ArticleAudioIds,
isReadAudioAuto = article.ArticleIsReadAudioAuto,
contents = article.ArticleContents
},
SectionEvent sectionEvent => new SectionEventDTO
{
id = sectionEvent.Id,
dateCreation = sectionEvent.DateCreation,
configurationId = sectionEvent.ConfigurationId,
instanceId = sectionEvent.InstanceId,
label = sectionEvent.Label,
title = sectionEvent.Title,
description = sectionEvent.Description,
order = sectionEvent.Order,
imageId = sectionEvent.ImageId,
imageSource = sectionEvent.ImageSource,
isActive = sectionEvent.IsActive,
isSubSection = sectionEvent.IsSubSection,
parentId = sectionEvent.ParentId,
isBeacon = sectionEvent.IsBeacon,
beaconId = sectionEvent.BeaconId,
latitude = sectionEvent.Latitude,
longitude = sectionEvent.Longitude,
meterZoneGPS = sectionEvent.MeterZoneGPS,
type = sectionEvent.Type,
StartDate = sectionEvent.StartDate?.Year > 1000 ? sectionEvent.StartDate : null,
EndDate = sectionEvent.EndDate?.Year > 1000 ? sectionEvent.EndDate : null,
BaseSectionMapId = sectionEvent.BaseSectionMapId,
GlobalMapAnnotations = sectionEvent.GlobalMapAnnotations?.Select(ma => ma.ToDTO()).ToList() ?? new(),
// Programme TODO specific
},
SectionMap map => new MapDTO
{
id = map.Id,
dateCreation = map.DateCreation,
configurationId = map.ConfigurationId,
instanceId = map.InstanceId,
label = map.Label,
title = map.Title,
description = map.Description,
order = map.Order,
imageId = map.ImageId,
imageSource = map.ImageSource,
isActive = map.IsActive,
isSubSection = map.IsSubSection,
parentId = map.ParentId,
isBeacon = map.IsBeacon,
beaconId = map.BeaconId,
latitude = map.Latitude,
longitude = map.Longitude,
meterZoneGPS = map.MeterZoneGPS,
type = map.Type,
zoom = map.MapZoom,
mapType = map.MapMapType,
mapTypeMapbox = map.MapTypeMapbox,
mapProvider = map.MapMapProvider,
iconResourceId = map.IconResourceId,
centerLatitude = map.MapCenterLatitude,
centerLongitude = map.MapCenterLongitude,
categories = map.MapCategories,
isListViewEnabled = map.IsListViewEnabled,
//points = null // map.MapPoints // TODO specific
},
SectionMenu menu => new MenuDTO
{
id = menu.Id,
dateCreation = menu.DateCreation,
configurationId = menu.ConfigurationId,
instanceId = menu.InstanceId,
label = menu.Label,
title = menu.Title,
description = menu.Description,
order = menu.Order,
imageId = menu.ImageId,
imageSource = menu.ImageSource,
isActive = menu.IsActive,
isSubSection = menu.IsSubSection,
parentId = menu.ParentId,
isBeacon = menu.IsBeacon,
beaconId = menu.BeaconId,
latitude = menu.Latitude,
longitude = menu.Longitude,
meterZoneGPS = menu.MeterZoneGPS,
type = menu.Type,
sections = null // menu.Sections, // TODO specific
},
SectionPdf pdf => new PdfDTO
{
id = pdf.Id,
dateCreation = pdf.DateCreation,
configurationId = pdf.ConfigurationId,
instanceId = pdf.InstanceId,
label = pdf.Label,
title = pdf.Title,
description = pdf.Description,
order = pdf.Order,
imageId = pdf.ImageId,
imageSource = pdf.ImageSource,
isActive = pdf.IsActive,
isSubSection = pdf.IsSubSection,
parentId = pdf.ParentId,
isBeacon = pdf.IsBeacon,
beaconId = pdf.BeaconId,
latitude = pdf.Latitude,
longitude = pdf.Longitude,
meterZoneGPS = pdf.MeterZoneGPS,
type = pdf.Type,
pdfs = pdf.PDFOrderedTranslationAndResources
},
SectionGame game => new GameDTO
{
id = game.Id,
dateCreation = game.DateCreation,
configurationId = game.ConfigurationId,
instanceId = game.InstanceId,
label = game.Label,
title = game.Title,
description = game.Description,
order = game.Order,
imageId = game.ImageId,
imageSource = game.ImageSource,
isActive = game.IsActive,
isSubSection = game.IsSubSection,
parentId = game.ParentId,
isBeacon = game.IsBeacon,
beaconId = game.BeaconId,
latitude = game.Latitude,
longitude = game.Longitude,
meterZoneGPS = game.MeterZoneGPS,
type = game.Type,
messageDebut = game.GameMessageDebut,
messageFin = game.GameMessageFin,
puzzleImage = game.GamePuzzleImage?.ToDTO(),
puzzleImageId = game.GamePuzzleImageId,
gameType = game.GameType,
rows = game.GamePuzzleRows,
cols = game.GamePuzzleCols
},
SectionQuiz quiz => new QuizDTO
{
id = quiz.Id,
dateCreation = quiz.DateCreation,
configurationId = quiz.ConfigurationId,
instanceId = quiz.InstanceId,
label = quiz.Label,
title = quiz.Title,
description = quiz.Description,
order = quiz.Order,
imageId = quiz.ImageId,
imageSource = quiz.ImageSource,
isActive = quiz.IsActive,
isSubSection = quiz.IsSubSection,
parentId = quiz.ParentId,
isBeacon = quiz.IsBeacon,
beaconId = quiz.BeaconId,
latitude = quiz.Latitude,
longitude = quiz.Longitude,
meterZoneGPS = quiz.MeterZoneGPS,
type = quiz.Type,
bad_level = quiz.QuizBadLevel,
medium_level = quiz.QuizMediumLevel,
good_level = quiz.QuizGoodLevel,
great_level = quiz.QuizGreatLevel,
questions = null // quiz.Questions, // TODO specific
},
SectionSlider slider => new SliderDTO
{
id = slider.Id,
dateCreation = slider.DateCreation,
configurationId = slider.ConfigurationId,
instanceId = slider.InstanceId,
label = slider.Label,
title = slider.Title,
description = slider.Description,
order = slider.Order,
imageId = slider.ImageId,
imageSource = slider.ImageSource,
isActive = slider.IsActive,
isSubSection = slider.IsSubSection,
parentId = slider.ParentId,
isBeacon = slider.IsBeacon,
beaconId = slider.BeaconId,
latitude = slider.Latitude,
longitude = slider.Longitude,
meterZoneGPS = slider.MeterZoneGPS,
type = slider.Type,
contents = slider.SliderContents
},
SectionVideo video => new VideoDTO
{
id = video.Id,
dateCreation = video.DateCreation,
configurationId = video.ConfigurationId,
instanceId = video.InstanceId,
label = video.Label,
title = video.Title,
description = video.Description,
order = video.Order,
imageId = video.ImageId,
imageSource = video.ImageSource,
isActive = video.IsActive,
isSubSection = video.IsSubSection,
parentId = video.ParentId,
isBeacon = video.IsBeacon,
beaconId = video.BeaconId,
latitude = video.Latitude,
longitude = video.Longitude,
meterZoneGPS = video.MeterZoneGPS,
type = video.Type,
source = video.VideoSource
},
SectionWeather weather => new WeatherDTO
{
id = weather.Id,
dateCreation = weather.DateCreation,
configurationId = weather.ConfigurationId,
instanceId = weather.InstanceId,
label = weather.Label,
title = weather.Title,
description = weather.Description,
order = weather.Order,
imageId = weather.ImageId,
imageSource = weather.ImageSource,
isActive = weather.IsActive,
isSubSection = weather.IsSubSection,
parentId = weather.ParentId,
isBeacon = weather.IsBeacon,
beaconId = weather.BeaconId,
latitude = weather.Latitude,
longitude = weather.Longitude,
meterZoneGPS = weather.MeterZoneGPS,
type = weather.Type,
city = weather.WeatherCity,
updatedDate = weather.WeatherUpdatedDate,
result = weather.WeatherResult
},
SectionWeb web => new WebDTO
{
id = web.Id,
dateCreation = web.DateCreation,
configurationId = web.ConfigurationId,
instanceId = web.InstanceId,
label = web.Label,
title = web.Title,
description = web.Description,
order = web.Order,
imageId = web.ImageId,
imageSource = web.ImageSource,
isActive = web.IsActive,
isSubSection = web.IsSubSection,
parentId = web.ParentId,
isBeacon = web.IsBeacon,
beaconId = web.BeaconId,
latitude = web.Latitude,
longitude = web.Longitude,
meterZoneGPS = web.MeterZoneGPS,
type = web.Type,
source = web.WebSource
},
SectionParcours parcours => new ParcoursDTO
{
id = parcours.Id,
dateCreation = parcours.DateCreation,
configurationId = parcours.ConfigurationId,
instanceId = parcours.InstanceId,
label = parcours.Label,
title = parcours.Title,
description = parcours.Description,
order = parcours.Order,
imageId = parcours.ImageId,
imageSource = parcours.ImageSource,
isActive = parcours.IsActive,
isSubSection = parcours.IsSubSection,
parentId = parcours.ParentId,
isBeacon = parcours.IsBeacon,
beaconId = parcours.BeaconId,
latitude = parcours.Latitude,
longitude = parcours.Longitude,
meterZoneGPS = parcours.MeterZoneGPS,
type = parcours.Type,
showMap = parcours.ShowMap,
baseSectionMapId = parcours.BaseSectionMapId,
// guidedPaths chargés spécifiquement dans GetFromConfigurationDetail
},
SectionScene3D model => model.ToDTO(),
_ => throw new NotImplementedException("Section type not handled")
};
}
}
}