From 3449361b7620f53d078254254cc9c1236e408026 Mon Sep 17 00:00:00 2001 From: Thomas Fransolet Date: Thu, 18 Sep 2025 23:22:34 +0200 Subject: [PATCH] WIP mobile app view config + updates input container (text form field) + update service generation --- .../color_picker_input_container.dart | 102 +- ...ti_select_dropdown_language_container.dart | 96 +- .../multi_string_input_container.dart | 137 +-- lib/Components/reorderable_custom_list.dart | 100 ++ lib/Components/resource_input_container.dart | 225 ++--- .../segmented_enum_input_container.dart | 97 ++ .../single_choice_input_container.dart | 66 ++ .../add_configuration_link_popup.dart | 12 +- .../app_configuration_link_screen.dart | 918 ++++++++++++++++-- .../SubSection/Map/new_update_categorie.dart | 2 +- lib/Screens/Kiosk_devices/device_element.dart | 24 +- lib/Screens/Kiosk_devices/kiosk_screen.dart | 81 +- lib/Screens/login_screen.dart | 13 +- lib/api/openApiTest.dart | 2 +- lib/api/swagger.yaml | 404 +++++--- lib/main.dart | 284 +++--- manager_api_new/.openapi-generator/FILES | 2 + manager_api_new/README.md | 5 +- manager_api_new/doc/ApplicationInstanceApi.md | 44 + manager_api_new/doc/ApplicationInstanceDTO.md | 3 + .../ApplicationInstanceDTOSectionEventDTO.md | 37 + manager_api_new/doc/SectionApi.md | 46 + manager_api_new/lib/api.dart | 1 + .../lib/api/application_instance_api.dart | 58 ++ manager_api_new/lib/api/section_api.dart | 72 ++ manager_api_new/lib/api_client.dart | 2 + .../lib/model/app_configuration_link_dto.dart | 4 +- .../lib/model/application_instance_dto.dart | 46 +- ...cation_instance_dto_section_event_dto.dart | 409 ++++++++ manager_api_new/lib/model/section_type.dart | 8 +- ...n_instance_dto_section_event_dto_test.dart | 134 +++ 31 files changed, 2713 insertions(+), 721 deletions(-) create mode 100644 lib/Components/reorderable_custom_list.dart create mode 100644 lib/Components/segmented_enum_input_container.dart create mode 100644 lib/Components/single_choice_input_container.dart create mode 100644 manager_api_new/doc/ApplicationInstanceDTOSectionEventDTO.md create mode 100644 manager_api_new/lib/model/application_instance_dto_section_event_dto.dart create mode 100644 manager_api_new/test/application_instance_dto_section_event_dto_test.dart diff --git a/lib/Components/color_picker_input_container.dart b/lib/Components/color_picker_input_container.dart index 0ccdaad..de8f8c9 100644 --- a/lib/Components/color_picker_input_container.dart +++ b/lib/Components/color_picker_input_container.dart @@ -1,4 +1,3 @@ -import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:manager_app/Components/color_picker.dart'; @@ -7,11 +6,12 @@ class ColorPickerInputContainer extends StatefulWidget { final String label; final double fontSize; final ValueChanged onChanged; + const ColorPickerInputContainer({ Key? key, this.color, required this.label, - this.fontSize = 25, + this.fontSize = 18, required this.onChanged, }) : super(key: key); @@ -20,78 +20,60 @@ class ColorPickerInputContainer extends StatefulWidget { } class _ColorPickerInputContainerState extends State { - Color? colorVar; + late Color colorVar; @override void initState() { - setState(() { - try { - colorVar = widget.color == null || widget.color!.isEmpty ? new Color(0x12345678) : new Color(int.parse(widget.color!.split('(0x')[1].split(')')[0], radix: 16)); - } catch(e) { - colorVar = new Color(0x12345678); - } - }); super.initState(); + try { + colorVar = widget.color == null || widget.color!.isEmpty + ? Colors.grey + : Color(int.parse(widget.color!.split('(0x')[1].split(')')[0], radix: 16)); + } catch (e) { + colorVar = Colors.grey; + } } + @override Widget build(BuildContext context) { - - return Container( - child: Row( - children: [ - Align( - alignment: AlignmentDirectional.centerStart, - child: AutoSizeText( - widget.label, - style: TextStyle(fontSize: widget.fontSize, fontWeight: FontWeight.w300), - maxLines: 2, - maxFontSize: widget.fontSize, - textAlign: TextAlign.center, - ) + return FormField( + initialValue: colorVar, + builder: (state) { + return InputDecorator( + decoration: InputDecoration( + labelText: widget.label, + border: OutlineInputBorder(borderRadius: BorderRadius.circular(10)), + contentPadding: EdgeInsets.symmetric(horizontal: 25, vertical: 20), ), - Padding( - padding: const EdgeInsets.all(10.0), - child: InkWell( - onTap: () { - showColorPicker( - colorVar!, - (Color color) { - setState(() { - colorVar = color; - }); - widget.onChanged(colorToString(color)); - }, - context - ); - }, - child: Container( - width: 50, - height: 50, - decoration: BoxDecoration( - color: colorVar, - borderRadius: BorderRadius.circular(50), - ), + child: InkWell( + onTap: () { + showColorPicker(colorVar, (Color color) { + setState(() { + colorVar = color; + }); + widget.onChanged(colorToString(color)); + }, context); + }, + child: Container( + width: 50, + height: 50, + decoration: BoxDecoration( + color: colorVar, + borderRadius: BorderRadius.circular(10), + border: Border.all(color: Colors.black26), ), ), ), - ], - ), + ); + }, ); } String colorToString(Color color) { - int a = (color.a * 255).round(); - int r = (color.r * 255).round(); - int g = (color.g * 255).round(); - int b = (color.b * 255).round(); - - final aHex = a.toRadixString(16).padLeft(2, '0'); - final rHex = r.toRadixString(16).padLeft(2, '0'); - final gHex = g.toRadixString(16).padLeft(2, '0'); - final bHex = b.toRadixString(16).padLeft(2, '0'); - + final aHex = color.alpha.toRadixString(16).padLeft(2, '0'); + final rHex = color.red.toRadixString(16).padLeft(2, '0'); + final gHex = color.green.toRadixString(16).padLeft(2, '0'); + final bHex = color.blue.toRadixString(16).padLeft(2, '0'); return 'Color(0x$aHex$rHex$gHex$bHex)'; } - - -} \ No newline at end of file +} diff --git a/lib/Components/multi_select_dropdown_language_container.dart b/lib/Components/multi_select_dropdown_language_container.dart index 132caea..83f627d 100644 --- a/lib/Components/multi_select_dropdown_language_container.dart +++ b/lib/Components/multi_select_dropdown_language_container.dart @@ -1,11 +1,6 @@ -import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; +import 'package:multi_select_flutter/multi_select_flutter.dart'; import 'package:manager_app/constants.dart'; -import 'package:multi_select_flutter/chip_display/multi_select_chip_display.dart'; -import 'package:multi_select_flutter/dialog/multi_select_dialog_field.dart'; -import 'package:multi_select_flutter/util/multi_select_item.dart'; -import 'package:multi_select_flutter/util/multi_select_list_type.dart'; - class MultiSelectDropdownLanguageContainer extends StatelessWidget { final Color color; @@ -16,7 +11,8 @@ class MultiSelectDropdownLanguageContainer extends StatelessWidget { final bool isMultiple; final bool isAtLeastOne; final double fontSize; - final ValueChanged> onChanged; + final ValueChanged> onChanged; + const MultiSelectDropdownLanguageContainer({ Key? key, this.color = kSecond, @@ -26,56 +22,62 @@ class MultiSelectDropdownLanguageContainer extends StatelessWidget { required this.initialValue, required this.isMultiple, this.isAtLeastOne = false, - this.fontSize = 25, + this.fontSize = 18, required this.onChanged, }) : super(key: key); @override Widget build(BuildContext context) { - Size size = MediaQuery.of(context).size; - return Container( - child: Row( - children: [ - Align( - alignment: AlignmentDirectional.centerStart, - child: AutoSizeText( - label, - style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.w300), - maxLines: 2, - maxFontSize: fontSize, - textAlign: TextAlign.center, - ) + return FormField>( + initialValue: initialValue, + builder: (state) { + return InputDecorator( + decoration: InputDecoration( + labelText: label, + border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)), + contentPadding: EdgeInsets.symmetric(horizontal: 25, vertical: 20), ), - Padding( - padding: const EdgeInsets.all(10.0), - child: Container( - width: size.width *0.2, - child: MultiSelectDialogField( + child: Builder( + builder: (context) { + return MultiSelectDialogField( items: values.map((e) => MultiSelectItem(e, e)).toList(), listType: MultiSelectListType.LIST, - cancelText: Text("Annuler"), - initialValue: initialValue, - buttonText: Text("Sélectionner"), - checkColor: Colors.white, - searchable: true, - chipDisplay: MultiSelectChipDisplay.none(), - selectedColor: kPrimaryColor, + initialValue: state.value ?? [], + buttonText: Text( + (state.value == null || state.value!.isEmpty) + ? "Aucune sélection" + : _buildSummary(state.value!), + ), title: Text(labelHint), - dialogHeight: size.height *0.4, - dialogWidth: size.width *0.2, - onSelectionChanged: (selectedList) { - onChanged(selectedList); + searchable: true, + selectedColor: kPrimaryColor, + checkColor: Colors.white, + chipDisplay: MultiSelectChipDisplay.none(), + dialogHeight: MediaQuery.of(context).size.height * 0.4, + dialogWidth: MediaQuery.of(context).size.width * 0.6, + onConfirm: (selected) { + if (isAtLeastOne && selected.isEmpty) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text("Au moins une valeur doit être sélectionnée"), + ), + ); + } else { + onChanged(selected.cast()); + state.didChange(selected); + } }, - onConfirm: (List test) - { - print("onConfirm MultiSelectDialogField"); - print(test); - }, - ), - ), + ); + }, ), - ], - ), + ); + }, ); } -} \ No newline at end of file + + String _buildSummary(List selected) { + if (selected.isEmpty) return "Aucune sélection"; + if (selected.length <= 5) return selected.join(", "); + return "${selected.length} sélectionnés"; + } +} diff --git a/lib/Components/multi_string_input_container.dart b/lib/Components/multi_string_input_container.dart index 2fc961d..f54c516 100644 --- a/lib/Components/multi_string_input_container.dart +++ b/lib/Components/multi_string_input_container.dart @@ -1,27 +1,27 @@ import 'dart:convert'; - -import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; +import 'package:manager_api_new/api.dart'; import 'package:manager_app/Components/multi_input_modal.dart'; import 'package:manager_app/Components/multi_string_input_html_modal.dart'; import 'package:manager_app/Models/managerContext.dart'; import 'package:manager_app/app_context.dart'; import 'package:manager_app/constants.dart'; -import 'package:manager_api_new/api.dart'; import 'package:provider/provider.dart'; +import 'package:auto_size_text/auto_size_text.dart'; class MultiStringInputContainer extends StatelessWidget { final Color color; final String label; final String modalLabel; final List initialValue; - final Function onGetResult; + final Function(List) onGetResult; final int maxLines; final bool isTitle; final List? resourceTypes; final bool isHTML; final double fontSize; final bool isMandatory; + const MultiStringInputContainer({ Key? key, this.color = kSecond, @@ -31,79 +31,84 @@ class MultiStringInputContainer extends StatelessWidget { required this.onGetResult, required this.maxLines, required this.isTitle, - this.resourceTypes = null, + this.resourceTypes, this.isHTML = false, - this.fontSize = 25, + this.fontSize = 18, this.isMandatory = true, }) : super(key: key); @override Widget build(BuildContext context) { final appContext = Provider.of(context); - ManagerAppContext managerAppContext = appContext.getContext(); + final managerAppContext = appContext.getContext(); - Size size = MediaQuery.of(context).size; - return Container( - child: Row( - children: [ - Align( - alignment: AlignmentDirectional.centerStart, - child: AutoSizeText( - label, - style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.w300), - maxLines: 2, - maxFontSize: fontSize, - textAlign: TextAlign.center, - ) + return FormField>( + initialValue: initialValue, + builder: (state) { + return InputDecorator( + decoration: InputDecoration( + labelText: label, + border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)), + contentPadding: EdgeInsets.symmetric(horizontal: 25, vertical: 20), ), - Padding( - padding: const EdgeInsets.all(10.0), + child: InkWell( + onTap: () { + List newValues = []; + List initials = initialValue; + + // Préparer les valeurs pour toutes les langues + managerAppContext.selectedConfiguration!.languages!.forEach((lang) { + if (initials.any((iv) => iv.language == lang)) { + newValues.add(TranslationDTO.fromJson( + jsonDecode(jsonEncode(initials.firstWhere((e) => e.language == lang)))!)!); + } else { + newValues.add(TranslationDTO(language: lang, value: "")); + } + }); + + if (isHTML) { + showMultiStringInputHTML( + label, + modalLabel, + isTitle, + initials, + newValues, + onGetResult, + maxLines, + resourceTypes, + context, + isMandatory, + ); + } else { + showMultiStringInput( + label, + modalLabel, + isTitle, + initials, + newValues, + onGetResult, + maxLines, + resourceTypes, + context, + ); + } + }, child: Container( - width: size.width *0.15, - child: InkWell( - onTap: () { - List newValues = []; - - List initials = initialValue; - - managerAppContext.selectedConfiguration!.languages!.forEach((value) { - if(initials.map((iv) => iv.language).contains(value)) { - newValues.add(TranslationDTO.fromJson(jsonDecode(jsonEncode(initials.firstWhere((element) => element.language == value)))!)!); - } else { - // New language - newValues.add(TranslationDTO(language: value, value: "")); - } - }); - - if(isHTML) { - showMultiStringInputHTML(label, modalLabel, isTitle, initials, newValues, onGetResult, maxLines, resourceTypes, context, isMandatory); - } else { - showMultiStringInput(label, modalLabel, isTitle, initials, newValues, onGetResult, maxLines, resourceTypes, context); - } - - }, - child: Container( - constraints: BoxConstraints(maxHeight: 60), - decoration: BoxDecoration( - color: color, - borderRadius: BorderRadius.circular(50), - ), - child: Padding( - padding: const EdgeInsets.only(left: 5, right: 5, top: 15, bottom: 15), - child: Center( - child: AutoSizeText( - resourceTypes == null ? "Changer traductions" : "Changer ressources", - style: TextStyle(color: kWhite), - maxLines: 2, - ) - ), - ) - ), + height: 50, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(50), ), + alignment: Alignment.center, + child: AutoSizeText( + resourceTypes == null ? "Changer traductions" : "Changer ressources", + style: TextStyle(color: kWhite, fontSize: fontSize), + maxLines: 1, + ), + ), ), - ), - ], - ), + ); + }, ); } -} \ No newline at end of file +} diff --git a/lib/Components/reorderable_custom_list.dart b/lib/Components/reorderable_custom_list.dart new file mode 100644 index 0000000..99e4a96 --- /dev/null +++ b/lib/Components/reorderable_custom_list.dart @@ -0,0 +1,100 @@ +import 'package:flutter/material.dart'; + +/// Composant générique pour réordonner une liste avec heading et actions +class ReorderableCustomList extends StatefulWidget { + final List items; + final ValueChanged> onChanged; + final Widget Function(BuildContext context, int index, T item) itemBuilder; + + /// Liste d’actions (icônes) par item, ex: delete, edit + final List? actions; + + final EdgeInsets? padding; + final bool shrinkWrap; + + const ReorderableCustomList({ + Key? key, + required this.items, + required this.onChanged, + required this.itemBuilder, + this.actions, + this.padding, + this.shrinkWrap = false, + }) : super(key: key); + + @override + State> createState() => _ReorderableCustomListState(); +} + +class _ReorderableCustomListState extends State> { + late List itemsMiddle; + + @override + void initState() { + super.initState(); + itemsMiddle = List.from(widget.items); + } + + void _onReorder(int oldIndex, int newIndex) { + setState(() { + if (newIndex > oldIndex) newIndex -= 1; + + final T item = itemsMiddle.removeAt(oldIndex); + itemsMiddle.insert(newIndex, item); + + widget.onChanged(itemsMiddle); + }); + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + ReorderableListView.builder( + shrinkWrap: widget.shrinkWrap, + physics: const NeverScrollableScrollPhysics(), + padding: widget.padding, + itemCount: itemsMiddle.length, + buildDefaultDragHandles: false, + onReorder: _onReorder, + itemBuilder: (context, index) { + final item = itemsMiddle[index]; + return Container( + key: ValueKey(item), + margin: const EdgeInsets.symmetric(vertical: 4), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey.shade300), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + ReorderableDragStartListener( + index: index, + child: const Padding( + padding: EdgeInsets.all(8.0), + child: Icon(Icons.drag_handle, color: Colors.grey), + ), + ), + + // Contenu de l’item + Expanded( + child: widget.itemBuilder(context, index, item), + ), + + // Actions personnalisées + if (widget.actions != null) + Row( + children: widget.actions! + .map((builder) => builder(context, index, item)) + .toList(), + ), + ], + ), + ); + }, + ), + ], + ); + } +} diff --git a/lib/Components/resource_input_container.dart b/lib/Components/resource_input_container.dart index 6989d38..904e456 100644 --- a/lib/Components/resource_input_container.dart +++ b/lib/Components/resource_input_container.dart @@ -1,11 +1,9 @@ -import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; -import 'package:manager_app/Components/common_loader.dart'; +import 'package:manager_api_new/api.dart'; +import 'package:manager_app/constants.dart'; import 'package:manager_app/Models/managerContext.dart'; import 'package:manager_app/app_context.dart'; -import 'package:manager_app/constants.dart'; import 'package:manager_app/Screens/Resources/select_resource_modal.dart'; -import 'package:manager_api_new/api.dart'; import 'package:provider/provider.dart'; class ResourceInputContainer extends StatefulWidget { @@ -14,10 +12,11 @@ class ResourceInputContainer extends StatefulWidget { final String? initialValue; final ValueChanged onChanged; final BoxFit imageFit; - final bool isSmall; final double fontSize; final List inResourceTypes; + final bool isSmall; final bool isLanguageTab; + const ResourceInputContainer({ Key? key, this.color = kSecond, @@ -25,10 +24,10 @@ class ResourceInputContainer extends StatefulWidget { this.initialValue, required this.onChanged, this.imageFit = BoxFit.cover, - this.isSmall = false, - this.fontSize = 25, + this.fontSize = 18, this.inResourceTypes = const [ResourceType.Image, ResourceType.ImageUrl], - this.isLanguageTab = false + this.isSmall = false, + this.isLanguageTab = false, }) : super(key: key); @override @@ -46,145 +45,89 @@ class _ResourceInputContainerState extends State { @override Widget build(BuildContext context) { - if(widget.isLanguageTab) { + final appContext = Provider.of(context); + + if (widget.isLanguageTab) { resourceIdToShow = widget.initialValue; } - return Container( - child: Row( - children: [ - Align( - alignment: AlignmentDirectional.centerStart, - child: AutoSizeText( - widget.label, - style: TextStyle(fontSize: widget.fontSize, fontWeight: FontWeight.w300), - maxLines: 2, - maxFontSize: widget.fontSize, - textAlign: TextAlign.center, - ) + return FormField( + initialValue: resourceIdToShow, + builder: (state) { + return InputDecorator( + decoration: InputDecoration( + labelText: widget.label, + border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)), + contentPadding: EdgeInsets.symmetric(horizontal: 25, vertical: 20), ), - Container( - //color: widget.isSmall ? Colors.cyanAccent: Colors.red, - child: Padding( - padding: EdgeInsets.only(left: widget.isSmall ? 5 : 10, top: 10, bottom: 10), - child: Container( - width: 90, - height: 90, - child: InkWell( - onTap: () async { - ResourceDTO? result = await showSelectResourceModal( - "Sélectionner une ressource", - 1, - widget.inResourceTypes, - context, - true, // IS SELECT - true, // IS ADD FALSE only for geopoint for now - true // IS REMOVE BUTTON - ); - - if (result != null) { - setState(() { - resourceIdToShow = result.id != null ? result.id : null; - }); - widget.onChanged(result); - } - }, - child: getElement(widget.initialValue, context, widget.isSmall), - ), - ), - ), - ), - ], - ), - ); - } - - getElement(String? initialValue, BuildContext context, bool isSmall) { - if (resourceIdToShow != null) { - Size size = MediaQuery.of(context).size; - final appContext = Provider.of(context); - return FutureBuilder( - future: getResource(resourceIdToShow!, appContext), - builder: (context, AsyncSnapshot snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - if (snapshot.data != null) { - ResourceDTO resourceDTO = snapshot.data!; - return Container( - decoration: boxDecoration(snapshot.data, appContext), - child: Center( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text(resourceDTO.type == ResourceType.Image || resourceDTO.type == ResourceType.ImageUrl ? "" : resourceDTO.label!), - ), - ) - ); - } else { - return Center( - child: Container( - decoration: boxDecoration(null, appContext), - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text("Aucune ressource"), - ) - ) - ); - } - - } else if (snapshot.connectionState == ConnectionState.none) { - return Text("No data"); - } else { - return Center( - child: Container( - height: size.height * 0.1, - child: CommonLoader() - ) + child: InkWell( + onTap: () async { + ResourceDTO? result = await showSelectResourceModal( + "Sélectionner une ressource", + 1, + widget.inResourceTypes, + context, + true, + true, + true, ); - } - } - ); - } else { - return Container( - decoration: BoxDecoration( - color: widget.color, - borderRadius: BorderRadius.circular(20), - ), - child: Padding( - padding: const EdgeInsets.only(left: 5, right: 5, top: 15, bottom: 15), - child: Center( - child: AutoSizeText( - "Choisir", - style: TextStyle(color: kWhite), - maxLines: 1, - ) + + if (result != null) { + setState(() { + resourceIdToShow = result.id; + }); + widget.onChanged(result); + } + }, + child: Container( + height: widget.isSmall ? 35 : 100, + width: widget.isSmall ? 60 : double.infinity, + alignment: Alignment.center, + decoration: BoxDecoration( + color: resourceIdToShow == null ? widget.color : Colors.transparent, + borderRadius: BorderRadius.circular(10), ), - ) + child: resourceIdToShow == null + ? Text( + "Choisir", + style: TextStyle(color: kWhite, fontSize: widget.fontSize), + maxLines: 1, + ) + : FutureBuilder( + future: (appContext.getContext() as ManagerAppContext) + .clientAPI! + .resourceApi! + .resourceGetDetail(resourceIdToShow!), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return SizedBox( + width: 24, + height: 24, + child: CircularProgressIndicator(strokeWidth: 2), + ); + } else if (snapshot.hasError || snapshot.data == null) { + return Text( + "Erreur", + style: TextStyle(color: kWhite, fontSize: widget.fontSize), + maxLines: 1, + ); + } else { + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + image: DecorationImage( + fit: widget.imageFit, + image: NetworkImage(snapshot.data!.url!), + ), + ), + ); + } + }, + ), + ), + ), ); - } - } - - Future getResource(String resourceIdToShow, dynamic appContext) async { - ResourceDTO? resource = await (appContext.getContext() as ManagerAppContext).clientAPI!.resourceApi!.resourceGetDetail(resourceIdToShow); - return resource; - } - - boxDecoration(ResourceDTO? resourceDTO, AppContext appContext) { - return BoxDecoration( - shape: BoxShape.rectangle, - color: kWhite, - borderRadius: BorderRadius.circular(30.0), - image: resourceDTO != null ? resourceDTO.type != null && (resourceDTO.type == ResourceType.Image || resourceDTO.type == ResourceType.ImageUrl)? new DecorationImage( - fit: widget.imageFit, - image: new NetworkImage( - resourceDTO.url!, // TODO handle multiple type of content - ), - ) : null : null, - boxShadow: [ - BoxShadow( - spreadRadius: 0.5, - blurRadius: 1, - offset: Offset(0, 1.5), // changes position of shadow - ), - ], + }, ); } -} \ No newline at end of file +} diff --git a/lib/Components/segmented_enum_input_container.dart b/lib/Components/segmented_enum_input_container.dart new file mode 100644 index 0000000..00df92a --- /dev/null +++ b/lib/Components/segmented_enum_input_container.dart @@ -0,0 +1,97 @@ +import 'package:flutter/material.dart'; +import 'package:manager_app/constants.dart'; + +class SegmentedEnumInputContainer extends StatefulWidget { + final String label; + final T selected; + final List values; + final Map> inputValues; // {'label': String, 'icon': IconData} + final ValueChanged onChanged; + final double borderRadius; + final Color selectedColor; + final Color unselectedColor; + final Color textColor; + + const SegmentedEnumInputContainer({ + Key? key, + required this.label, + required this.selected, + required this.values, + required this.inputValues, + required this.onChanged, + this.borderRadius = 12, + this.selectedColor = kPrimaryColor, + this.unselectedColor = kSecond, + this.textColor = Colors.white, + }) : super(key: key); + + @override + _SegmentedEnumInputContainerState createState() => + _SegmentedEnumInputContainerState(); +} + +class _SegmentedEnumInputContainerState + extends State> { + late T selectedValue; + + @override + void initState() { + super.initState(); + selectedValue = widget.selected; + } + + @override + Widget build(BuildContext context) { + return FormField( + initialValue: selectedValue, + builder: (state) { + return InputDecorator( + decoration: InputDecoration( + labelText: widget.label, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(widget.borderRadius)), + contentPadding: EdgeInsets.symmetric(horizontal: 25, vertical: 20), + ), + child: Row( + children: widget.values.map((v) { + bool isSelected = v == selectedValue; + final data = widget.inputValues[v]!; + return Expanded( + child: GestureDetector( + onTap: () { + setState(() { + selectedValue = v; + state.didChange(v); + }); + widget.onChanged(v); + }, + child: AnimatedContainer( + duration: Duration(milliseconds: 250), + margin: EdgeInsets.symmetric(horizontal: 4), + padding: EdgeInsets.symmetric(vertical: 10), + decoration: BoxDecoration( + color: isSelected ? widget.selectedColor : kSecond, + borderRadius: BorderRadius.circular(widget.borderRadius), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(data['icon'], color: widget.textColor), + SizedBox(width: 4), + Text( + data['label'], + style: TextStyle( + color: widget.textColor, fontWeight: FontWeight.w400), + ), + ], + ), + ), + ), + ); + }).toList(), + ), + ); + }, + ); + } +} diff --git a/lib/Components/single_choice_input_container.dart b/lib/Components/single_choice_input_container.dart new file mode 100644 index 0000000..fbe1f5e --- /dev/null +++ b/lib/Components/single_choice_input_container.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; +import 'package:manager_api_new/api.dart'; +import 'package:manager_app/constants.dart'; + +class SingleChoiceInputContainer extends StatelessWidget { + final String label; + final T? selected; + final List values; + final ValueChanged onChanged; + final double borderRadius; + final Color selectedColor; + final Color textColor; + + const SingleChoiceInputContainer({ + Key? key, + required this.label, + required this.selected, + required this.values, + required this.onChanged, + this.borderRadius = 12, + this.selectedColor = kPrimaryColor, + this.textColor = kWhite, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return FormField( + initialValue: selected, + builder: (state) { + return InputDecorator( + decoration: InputDecoration( + labelText: label, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(borderRadius), + ), + contentPadding: + const EdgeInsets.symmetric(horizontal: 25, vertical: 20), + ), + child: DropdownButtonHideUnderline( + child: DropdownButton( + value: selected, + isExpanded: true, + // todo handle view + items: values.map((v) { + return DropdownMenuItem( + value: v, + child: Row( + children: [ + Text((v as SectionEventDTO).label ?? ""), // TODO Update to handle more types ! + ], + ), + ); + }).toList(), + onChanged: (value) { + if (value != null) { + onChanged(value); + state.didChange(value); + } + }, + ), + ), + ); + }, + ); + } +} diff --git a/lib/Screens/Applications/add_configuration_link_popup.dart b/lib/Screens/Applications/add_configuration_link_popup.dart index 7516cce..4dda236 100644 --- a/lib/Screens/Applications/add_configuration_link_popup.dart +++ b/lib/Screens/Applications/add_configuration_link_popup.dart @@ -36,7 +36,7 @@ dynamic showAddConfigurationLink (BuildContext mainContext, AppContext appContex width: size.width * 0.5, constraints: const BoxConstraints(minHeight: 250, minWidth: 250), child: configurations.length == 0 ? Center(child: Text("Aucun élément à afficher")) : ListView.builder( - padding: const EdgeInsets.all(25), + padding: const EdgeInsets.all(20), itemCount: configurations.length, itemBuilder: (context, index) { final configuration = configurations[index]; @@ -47,19 +47,19 @@ dynamic showAddConfigurationLink (BuildContext mainContext, AppContext appContex borderRadius: BorderRadius.circular(16), ), elevation: 4, - margin: const EdgeInsets.symmetric(vertical: 8), + margin: const EdgeInsets.symmetric(vertical: 4), color: isSelected ? kPrimaryColor.withValues(alpha: 0.2) : null, child: ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 35, vertical: 12), leading: Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.all(0.0), child: Container( - height: 35, - width: 35, + height: 50, + width: 50, decoration: BoxDecoration( shape: BoxShape.rectangle, color: kWhite, - borderRadius: BorderRadius.circular(30.0), + borderRadius: BorderRadius.circular(10.0), image: configuration.imageId != null ? DecorationImage( fit: BoxFit.cover, diff --git a/lib/Screens/Applications/app_configuration_link_screen.dart b/lib/Screens/Applications/app_configuration_link_screen.dart index 3ab219c..0fae0be 100644 --- a/lib/Screens/Applications/app_configuration_link_screen.dart +++ b/lib/Screens/Applications/app_configuration_link_screen.dart @@ -1,8 +1,17 @@ +import 'dart:convert'; + import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; +import 'package:manager_app/Components/color_picker_input_container.dart'; import 'package:manager_app/Components/common_loader.dart'; import 'package:manager_app/Components/confirmation_dialog.dart'; import 'package:manager_app/Components/message_notification.dart'; +import 'package:manager_app/Components/multi_select_dropdown_language_container.dart'; +import 'package:manager_app/Components/multi_string_input_container.dart'; +import 'package:manager_app/Components/reorderable_custom_list.dart'; +import 'package:manager_app/Components/resource_input_container.dart'; +import 'package:manager_app/Components/segmented_enum_input_container.dart'; +import 'package:manager_app/Components/single_choice_input_container.dart'; import 'package:manager_app/Models/managerContext.dart'; import 'package:manager_app/Screens/Applications/add_configuration_link_popup.dart'; import 'package:manager_app/Screens/Applications/phone_mockup.dart'; @@ -26,6 +35,440 @@ class _AppConfigurationLinkScreenState extends State Size size = MediaQuery.of(context).size; ManagerAppContext managerAppContext = appContext.getContext() as ManagerAppContext; + _generalInfoCard() { + return Card( + margin: const EdgeInsets.symmetric(vertical: 8), + color: kSecond, + elevation: 2, + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Informations générales", style: Theme.of(context).textTheme.titleMedium), + SizedBox(height: 8), + Wrap( + spacing: 16, + runSpacing: 16, + /*GridView.count( + crossAxisCount: size.width > 800 ? 2 : 1, + crossAxisSpacing: 8, + mainAxisSpacing: 8, + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + childAspectRatio: 3,*/ + children: [ + // Titre affiché main + /*SizedBox( + width: 300, + child: MultiStringInputContainer( + label: "Titre affiché:", + modalLabel: "Titre", + color: kPrimaryColor, + initialValue: [], + onGetResult: (value) { + /*if (sectionDTO.title! != value) { + sectionDTO.title = value; + save(true, appContext); + }*/ + }, + maxLines: 1, + isHTML: true, + isTitle: true, + ), + ),*/ + // Image principale + SizedBox( + width: 300, + child: ResourceInputContainer( + label: "Image principale :", + initialValue: widget.applicationInstanceDTO.mainImageId, + color: kPrimaryColor, + imageFit: BoxFit.fitHeight, + onChanged: (ResourceDTO resource) { + if(resource.id == null) { + widget.applicationInstanceDTO.mainImageId = null; + widget.applicationInstanceDTO.mainImageUrl = null; + } else { + widget.applicationInstanceDTO.mainImageId = resource.id; + widget.applicationInstanceDTO.mainImageUrl = resource.url; + } + }, + ), + ), + // Image Loader + SizedBox( + width: 300, + child: ResourceInputContainer( + label: "Loader :", + initialValue: widget.applicationInstanceDTO.loaderImageId, + color: kPrimaryColor, + imageFit: BoxFit.fitHeight, + onChanged: (ResourceDTO resource) { + if(resource.id == null) { + widget.applicationInstanceDTO.loaderImageId = null; + widget.applicationInstanceDTO.loaderImageUrl = null; + } else { + widget.applicationInstanceDTO.loaderImageId = resource.id; + widget.applicationInstanceDTO.loaderImageUrl = resource.url; + } + }, + ), + ), + // Primary color + SizedBox( + width: 300, + child: ColorPickerInputContainer( + label: "Couleur principale :", + fontSize: 20, + color: widget.applicationInstanceDTO.primaryColor, + onChanged: (value) { + widget.applicationInstanceDTO.primaryColor = value; + }, + ), + ), + // Secondary color + SizedBox( + width: 300, + child: ColorPickerInputContainer( + label: "Couleur secondaire :", + fontSize: 20, + color: widget.applicationInstanceDTO.secondaryColor, + onChanged: (value) { + widget.applicationInstanceDTO.secondaryColor = value; + }, + ), + ), + // Layout (Grid or Mansonry) + SizedBox( + width: 300, + child: SegmentedEnumInputContainer( + label: "Affichage :", + selected: LayoutMainPageType.MasonryGrid, + values: LayoutMainPageType.values, + inputValues: { LayoutMainPageType.SimpleGrid: {'label': 'Grille', 'icon': Icons.grid_view}, LayoutMainPageType.MasonryGrid : {'label': 'Masonry', 'icon': Icons.view_quilt }}, + onChanged: (value) { + var tempOutput = value; + widget.applicationInstanceDTO.layoutMainPage = tempOutput; + //print(configurationDTO.languages); + }, + ) + ), + // Langues + SizedBox( + width: 300, + child: MultiSelectDropdownLanguageContainer( + label: "Langues :", + initialValue: widget.applicationInstanceDTO.languages != null ? widget.applicationInstanceDTO.languages!: [], + values: languages, + isMultiple: true, + fontSize: 20, + isAtLeastOne: true, + onChanged: (value) { + var tempOutput = new List.from(value); + widget.applicationInstanceDTO.languages = tempOutput; + //print(configurationDTO.languages); + }, + ), + ), + // Highlight / Event principal + SizedBox( + width: 300, + child: FutureBuilder( + future: getSectionEvents(appContext, widget.applicationInstanceDTO), + builder: (context, snapshot) { + var rawList = snapshot.data; + var rawSubsections = jsonDecode(jsonEncode(snapshot.data)); + rawSubsections = rawSubsections?.map((json) => SectionEventDTO.fromJson(json)).toList(); + List? sectionEvents = rawSubsections?.whereType().toList(); + + return SingleChoiceInputContainer( + label: "Evènement à l'affiche :", + selected: widget.applicationInstanceDTO.sectionEventDTO, + values: sectionEvents != null ? sectionEvents.toList() : [], + onChanged: (SectionEventDTO sectionEvent) { + print("Sélectionné: $sectionEvent"); + print(sectionEvent.label); + print(sectionEvent.id); + widget.applicationInstanceDTO.sectionEventId = sectionEvent.id; + }, + ); + } + ) + ), + ], + ) // tes champs + ], + ), + ), + ); + } + + _phoneConfigCard(List? appConfigurationLinks) { + return Card( + margin: const EdgeInsets.symmetric(vertical: 8), + color: kSecond, + elevation: 2, + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("Configurations sur le téléphone", style: Theme.of(context).textTheme.titleMedium), + SizedBox(height: 8), + appConfigurationLinks != null ? SingleChildScrollView( + child: Stack( + children: [ + Container( + height: size.height * 0.6, + width: size.width * 0.8, + constraints: BoxConstraints( + minHeight: 300, + minWidth: 300, + maxHeight: 500 + ), + color: Colors.blue, + child: ReorderableCustomList( + items: appConfigurationLinks, + shrinkWrap: true, + onChanged: (updatedList) async { + int order = 0; + // update order manually + for(var item in updatedList) { + item.order = order; + order++; + } + // TODO use order put method + var result = await updateAppConfigurationOrder(appContext, updatedList); + setState(() { + // for refresh + }); + }, + actions: [ + /*(BuildContext context, int index, AppConfigurationLinkDTO link) { + return Container( + height: 50, + width: 50, + child: InkWell( + onTap: () async { + try { + var applicationInstance = widget.applicationInstanceDTO; + applicationInstance. + var applicationLink = await updateApplicationInstance(appContext, widget.applicationInstanceDTO); + if(applicationLink != null) { + if(newValue) { + showNotification(kSuccess, kWhite, "Configuration activée avec succès", context, null); + } else { + showNotification(kSuccess, kWhite, "Configuration désactivée avec succès", context, null); + } + setState(() { + link.isActive = applicationLink.isActive; + }); + } + } catch (e) { + showNotification(kError, kWhite, "Une erreur est survenue", context, null); + } + }, + child: Icon(Icons.star, color: kError, size: 25), + ), + ); + },*/ + (BuildContext context, int index, AppConfigurationLinkDTO link) { + return Container( + height: 50, + width: 70, + child: Switch( + activeThumbColor: kPrimaryColor, + inactiveThumbColor: kBodyTextColor, + inactiveTrackColor: kSecond, + hoverColor: kPrimaryColor.withValues(alpha: 0.2), + value: link.isActive ?? false, + onChanged: (bool newValue) async { + try { + link.isActive = newValue; + var applicationLink = await updateApplicationLink(appContext, link); + if(applicationLink != null) { + if(newValue) { + showNotification(kSuccess, kWhite, "Configuration activée avec succès", context, null); + } else { + showNotification(kSuccess, kWhite, "Configuration désactivée avec succès", context, null); + } + setState(() { + link.isActive = applicationLink.isActive; + }); + } + } catch (e) { + showNotification(kError, kWhite, "Une erreur est survenue", context, null); + } + }, + ), + ); + }, + (BuildContext context, int index, AppConfigurationLinkDTO link) { + return Container( + height: 50, + width: 50, + child: InkWell( + onTap: () async { + showConfirmationDialog( + "Êtes-vous sûr de vouloir retirer cette configuration de l'application ?", + () {}, + () async { + try { + var result = await deleteConfigurationToApp(appContext, link, widget.applicationInstanceDTO); + + showNotification(kSuccess, kWhite, "La configuration a été retirée de l'application avec succès", context, null); + + setState(() { + // for refresh ui + }); + } catch(e) { + showNotification(kError, kWhite, 'Une erreur est survenue lors du retrait de la configuration', context, null); + } + }, + context + ); + }, + child: Icon(Icons.delete, color: kError, size: 25), + ), + ); + }, + ], + padding: const EdgeInsets.all(8), + itemBuilder: (context, index, appConfigurationLink) { + return Container( + decoration: BoxDecoration( + + ), + margin: const EdgeInsets.symmetric(vertical: 3), + padding: const EdgeInsets.all(8), + child: Row( + children: [ + if(appConfigurationLink.configuration!.imageId != null) + Container( + width: 50, + height: 50, + decoration: BoxDecoration( + color: kSecond.withValues(alpha: 0.65), + borderRadius: BorderRadius.circular(8.0), + image: DecorationImage( + fit: BoxFit.cover, + image: NetworkImage(appConfigurationLink.configuration!.imageSource!) + ), + ) + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text(appConfigurationLink.configuration?.label ?? ""), + ), + ], + ), + ); + }, + ), + ), + Positioned( + bottom: 20, + right: 20, + child: InkWell( + onTap: () async { + // Show configuration selector to link with ! + var result = await showAddConfigurationLink(context, appContext, managerAppContext.instanceDTO!, appConfigurationLinks.map((acl) => acl.configurationId!).toList() ?? []); + if(result != null) { + for(var configurationId in result) { + AppConfigurationLinkDTO appConfigurationLinkDTO = AppConfigurationLinkDTO( + applicationInstanceId: widget.applicationInstanceDTO.id, + configurationId: configurationId, + isActive: true, + isDate: false, + isHour: false, + isSectionImageBackground: false, + layoutMainPage: LayoutMainPageType.SimpleGrid + ); + await addConfigurationToApp(appContext, appConfigurationLinkDTO, widget.applicationInstanceDTO); + } + setState(() { + // Refresh ui + }); + } + }, + child: Container( + height: 85, + width: 85, + decoration: BoxDecoration( + color: kSuccess, + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Icon(Icons.add, size: 25, color: kWhite), + ) + ), + ), + ), + /*PhoneMockup( + child: Center( + child: GridView.builder( + shrinkWrap: true, + gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: crossAxisCount), + itemCount: appConfigurationLinks.length, + itemBuilder: (BuildContext context, int index) { + AppConfigurationLinkDTO appConfigurationLink = appConfigurationLinks[index]; + return Container( + decoration: BoxDecoration( + color: Colors.green, + ), + padding: const EdgeInsets.all(15), + margin: EdgeInsets.symmetric(vertical: 15, horizontal: 15), + child: Stack( + children: [ + Align( + alignment: Alignment.center, + child: Text(appConfigurationLink.configuration!.label!), + ), + Positioned( + right: 0, + bottom: 0, + child: InkWell( + onTap: () async { + showConfirmationDialog( + "Êtes-vous sûr de vouloir retirer cette configuration de l'application ?", + () {}, + () async { + try { + var result = await deleteConfigurationToApp(appContext, appConfigurationLink, widget.applicationInstanceDTO); + + showNotification(kSuccess, kWhite, "La configuration a été retirée de l'application avec succès", context, null); + + setState(() { + // for refresh ui + }); + } catch(e) { + showNotification(kError, kWhite, 'Une erreur est survenue lors du retrait de la configuration', context, null); + } + }, + context + ); + }, + child: Icon(Icons.delete, color: kError, size: 25), + ) + ) + ], + ), + ); + } + ), + ), + ),*/ + ], + ), + ): Center(child: Text("No data")), + ], + ), + ), + ); + } + return FutureBuilder( future: getAppConfigurationLink(appContext, widget.applicationInstanceDTO), builder: (context, AsyncSnapshot snapshot) { @@ -36,90 +479,392 @@ class _AppConfigurationLinkScreenState extends State final itemWidth = 175; final crossAxisCount = (screenWidth / itemWidth).floor().clamp(1, 6); - return Container( - child: Align( - alignment: AlignmentDirectional.topCenter, - child: appConfigurationLinks != null ? SingleChildScrollView( - child: Column( - children: [ - InkWell( - onTap: () async { - // Show configuration selector to link with ! - var result = await showAddConfigurationLink(context, appContext, managerAppContext.instanceDTO!, appConfigurationLinks.map((acl) => acl.configurationId!).toList() ?? []); - if(result != null) { - for(var configurationId in result) { - AppConfigurationLinkDTO appConfigurationLinkDTO = AppConfigurationLinkDTO(applicationInstanceId: widget.applicationInstanceDTO.id, configurationId: configurationId, isActive: true); - await addConfigurationToApp(appContext, appConfigurationLinkDTO, widget.applicationInstanceDTO); - } - setState(() { - // Refresh ui - }); - } - }, - child: Container( - height: 50, - width: 50, + + return Column( + children: [ + // autres widgets au-dessus si nécessaire + Expanded( + child: SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + _generalInfoCard(), + _phoneConfigCard(appConfigurationLinks), + ], + ), + ), + ), + ], + ); + + return Align( + alignment: AlignmentDirectional.topCenter, + child: Container( + color: Colors.pink, + width: size.width * 0.85, + height: size.height * 0.65, + constraints: BoxConstraints(minWidth: 200, minHeight: 200), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Align( + alignment: AlignmentDirectional.centerStart, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text("Informations générales"), + ) + ), + Align( + alignment: AlignmentDirectional.centerStart, + child: Container( + child: Column( + children: [ + // Titre affiché main + /*MultiStringInputContainer( + label: "Titre affiché:", + modalLabel: "Titre", color: kPrimaryColor, - child: Text("ADD CONFIG TO APP") - ), - ), - PhoneMockup( - child: Center( - child: GridView.builder( + initialValue: widget.applicationInstanceDTO.title, + onGetResult: (value) { + if (sectionDTO.title! != value) { + sectionDTO.title = value; + save(true, appContext); + } + }, + maxLines: 1, + isHTML: true, + isTitle: true, + ),*/ + // Image principale + ResourceInputContainer( + label: "Image principale :", + initialValue: widget.applicationInstanceDTO.mainImageId, + color: kPrimaryColor, + onChanged: (ResourceDTO resource) { + if(resource.id == null) { + widget.applicationInstanceDTO.mainImageId = null; + widget.applicationInstanceDTO.mainImageUrl = null; + } else { + widget.applicationInstanceDTO.mainImageId = resource.id; + widget.applicationInstanceDTO.mainImageUrl = resource.url; + } + }, + ), + // Image Loader + ResourceInputContainer( + label: "Loader :", + initialValue: widget.applicationInstanceDTO.loaderImageId, + color: kPrimaryColor, + onChanged: (ResourceDTO resource) { + if(resource.id == null) { + widget.applicationInstanceDTO.loaderImageId = null; + widget.applicationInstanceDTO.loaderImageUrl = null; + } else { + widget.applicationInstanceDTO.loaderImageId = resource.id; + widget.applicationInstanceDTO.loaderImageUrl = resource.url; + } + }, + ), + // Primary color + ColorPickerInputContainer( + label: "Couleur principale :", + fontSize: 20, + color: widget.applicationInstanceDTO.primaryColor, + onChanged: (value) { + widget.applicationInstanceDTO.primaryColor = value; + }, + ), + // Secondary color + ColorPickerInputContainer( + label: "Couleur secondaire :", + fontSize: 20, + color: widget.applicationInstanceDTO.secondaryColor, + onChanged: (value) { + widget.applicationInstanceDTO.secondaryColor = value; + }, + ), + // Layout (Grid or Mansonry) + Text('Todo Type selector Grid or Mansonry'), + // Langues + MultiSelectDropdownLanguageContainer( + label: "Langues :", + initialValue: widget.applicationInstanceDTO.languages != null ? widget.applicationInstanceDTO.languages!: [], + values: languages, + isMultiple: true, + fontSize: 20, + isAtLeastOne: true, + onChanged: (value) { + var tempOutput = new List.from(value); + widget.applicationInstanceDTO.languages = tempOutput; + //print(configurationDTO.languages); + }, + ), + // Highlight / Event principal -> Remplace l'image principale + Text('Todo, event section selector') + ], + ), // Elements + ), + ), + Align( + alignment: AlignmentDirectional.centerStart, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text("Configurations sur le téléphone"), + ) + ), + Align( + alignment: AlignmentDirectional.topCenter, + child: appConfigurationLinks != null ? SingleChildScrollView( + child: Stack( + children: [ + Container( + height: size.height * 0.6, + width: size.width * 0.8, + constraints: BoxConstraints( + minHeight: 300, + minWidth: 300, + maxHeight: 500 + ), + color: Colors.blue, + child: ReorderableCustomList( + items: appConfigurationLinks, shrinkWrap: true, - gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: crossAxisCount), - itemCount: appConfigurationLinks.length, - itemBuilder: (BuildContext context, int index) { - AppConfigurationLinkDTO appConfigurationLink = appConfigurationLinks[index]; + onChanged: (updatedList) async { + int order = 0; + // update order manually + for(var item in updatedList) { + item.order = order; + order++; + } + // TODO use order put method + var result = await updateAppConfigurationOrder(appContext, updatedList); + setState(() { + // for refresh + }); + }, + actions: [ + /*(BuildContext context, int index, AppConfigurationLinkDTO link) { + return Container( + height: 50, + width: 50, + child: InkWell( + onTap: () async { + try { + var applicationInstance = widget.applicationInstanceDTO; + applicationInstance. + var applicationLink = await updateApplicationInstance(appContext, widget.applicationInstanceDTO); + if(applicationLink != null) { + if(newValue) { + showNotification(kSuccess, kWhite, "Configuration activée avec succès", context, null); + } else { + showNotification(kSuccess, kWhite, "Configuration désactivée avec succès", context, null); + } + setState(() { + link.isActive = applicationLink.isActive; + }); + } + } catch (e) { + showNotification(kError, kWhite, "Une erreur est survenue", context, null); + } + }, + child: Icon(Icons.star, color: kError, size: 25), + ), + ); + },*/ + (BuildContext context, int index, AppConfigurationLinkDTO link) { + return Container( + height: 50, + width: 70, + child: Switch( + activeThumbColor: kPrimaryColor, + inactiveThumbColor: kBodyTextColor, + inactiveTrackColor: kSecond, + hoverColor: kPrimaryColor.withValues(alpha: 0.2), + value: link.isActive ?? false, + onChanged: (bool newValue) async { + try { + link.isActive = newValue; + var applicationLink = await updateApplicationLink(appContext, link); + if(applicationLink != null) { + if(newValue) { + showNotification(kSuccess, kWhite, "Configuration activée avec succès", context, null); + } else { + showNotification(kSuccess, kWhite, "Configuration désactivée avec succès", context, null); + } + setState(() { + link.isActive = applicationLink.isActive; + }); + } + } catch (e) { + showNotification(kError, kWhite, "Une erreur est survenue", context, null); + } + }, + ), + ); + }, + (BuildContext context, int index, AppConfigurationLinkDTO link) { + return Container( + height: 50, + width: 50, + child: InkWell( + onTap: () async { + showConfirmationDialog( + "Êtes-vous sûr de vouloir retirer cette configuration de l'application ?", + () {}, + () async { + try { + var result = await deleteConfigurationToApp(appContext, link, widget.applicationInstanceDTO); + + showNotification(kSuccess, kWhite, "La configuration a été retirée de l'application avec succès", context, null); + + setState(() { + // for refresh ui + }); + } catch(e) { + showNotification(kError, kWhite, 'Une erreur est survenue lors du retrait de la configuration', context, null); + } + }, + context + ); + }, + child: Icon(Icons.delete, color: kError, size: 25), + ), + ); + }, + ], + padding: const EdgeInsets.all(8), + itemBuilder: (context, index, appConfigurationLink) { return Container( decoration: BoxDecoration( - color: Colors.green, + ), - padding: const EdgeInsets.all(15), - margin: EdgeInsets.symmetric(vertical: 15, horizontal: 15), - child: Stack( + margin: const EdgeInsets.symmetric(vertical: 3), + padding: const EdgeInsets.all(8), + child: Row( children: [ - Align( - alignment: Alignment.center, - child: Text(appConfigurationLink.configuration!.label!), - ), - Positioned( - right: 0, - bottom: 0, - child: InkWell( - onTap: () async { - showConfirmationDialog( - "Êtes-vous sûr de vouloir retirer cette configuration de l'application ?", - () {}, - () async { - try { - var result = await deleteConfigurationToApp(appContext, appConfigurationLink, widget.applicationInstanceDTO); - - showNotification(kSuccess, kWhite, "La configuration a été retirée de l'application avec succès", context, null); - - setState(() { - // for refresh ui - }); - } catch(e) { - showNotification(kError, kWhite, 'Une erreur est survenue lors du retrait de la configuration', context, null); - } - }, - context - ); - }, - child: Icon(Icons.delete, color: kError, size: 25), + if(appConfigurationLink.configuration!.imageId != null) + Container( + width: 50, + height: 50, + decoration: BoxDecoration( + color: kSecond.withValues(alpha: 0.65), + borderRadius: BorderRadius.circular(8.0), + image: DecorationImage( + fit: BoxFit.cover, + image: NetworkImage(appConfigurationLink.configuration!.imageSource!) + ), ) - ) + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text(appConfigurationLink.configuration?.label ?? ""), + ), ], ), ); - } + }, + ), ), - ), + Positioned( + bottom: 20, + right: 20, + child: InkWell( + onTap: () async { + // Show configuration selector to link with ! + var result = await showAddConfigurationLink(context, appContext, managerAppContext.instanceDTO!, appConfigurationLinks.map((acl) => acl.configurationId!).toList() ?? []); + if(result != null) { + for(var configurationId in result) { + AppConfigurationLinkDTO appConfigurationLinkDTO = AppConfigurationLinkDTO( + applicationInstanceId: widget.applicationInstanceDTO.id, + configurationId: configurationId, + isActive: true, + isDate: false, + isHour: false, + isSectionImageBackground: false, + layoutMainPage: LayoutMainPageType.SimpleGrid + ); + await addConfigurationToApp(appContext, appConfigurationLinkDTO, widget.applicationInstanceDTO); + } + setState(() { + // Refresh ui + }); + } + }, + child: Container( + height: 85, + width: 85, + decoration: BoxDecoration( + color: kSuccess, + borderRadius: BorderRadius.circular(8.0), + ), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Icon(Icons.add, size: 25, color: kWhite), + ) + ), + ), + ), + /*PhoneMockup( + child: Center( + child: GridView.builder( + shrinkWrap: true, + gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: crossAxisCount), + itemCount: appConfigurationLinks.length, + itemBuilder: (BuildContext context, int index) { + AppConfigurationLinkDTO appConfigurationLink = appConfigurationLinks[index]; + return Container( + decoration: BoxDecoration( + color: Colors.green, + ), + padding: const EdgeInsets.all(15), + margin: EdgeInsets.symmetric(vertical: 15, horizontal: 15), + child: Stack( + children: [ + Align( + alignment: Alignment.center, + child: Text(appConfigurationLink.configuration!.label!), + ), + Positioned( + right: 0, + bottom: 0, + child: InkWell( + onTap: () async { + showConfirmationDialog( + "Êtes-vous sûr de vouloir retirer cette configuration de l'application ?", + () {}, + () async { + try { + var result = await deleteConfigurationToApp(appContext, appConfigurationLink, widget.applicationInstanceDTO); + + showNotification(kSuccess, kWhite, "La configuration a été retirée de l'application avec succès", context, null); + + setState(() { + // for refresh ui + }); + } catch(e) { + showNotification(kError, kWhite, 'Une erreur est survenue lors du retrait de la configuration', context, null); + } + }, + context + ); + }, + child: Icon(Icons.delete, color: kError, size: 25), + ) + ) + ], + ), + ); + } + ), + ), + ),*/ + ], ), - ], - ), - ): Center(child: Text("No data")), + ): Center(child: Text("No data")), + ), + ], + ), ), ); } else if (snapshot.connectionState == ConnectionState.none) { @@ -132,8 +877,6 @@ class _AppConfigurationLinkScreenState extends State ) ); } - - } ); } @@ -159,7 +902,19 @@ Future?> getAppConfigurationLink(AppContext appCon return null; } +} +Future?> getSectionEvents(AppContext appContext, ApplicationInstanceDTO applicationInstanceDTO) async { + try{ + final rawList = await (appContext.getContext() as ManagerAppContext).clientAPI!.sectionApi!.sectionGetAllFromType(instanceId: applicationInstanceDTO.instanceId!, sectionType: SectionType.Event.toString()); + + if(rawList == null) { return [];} + var sections = rawList.map((json) => SectionEventDTO.fromJson(json)!).toList(); + return sections ?? []; + } catch(e) { + + return null; + } } @@ -168,6 +923,21 @@ Future addConfigurationToApp(AppContext appContext, Ap return appConfigurationsLink; } +Future updateApplicationInstance(AppContext appContext, ApplicationInstanceDTO applicationInstanceDTO) async { + ApplicationInstanceDTO? result = await (appContext.getContext() as ManagerAppContext).clientAPI!.applicationInstanceApi!.applicationInstanceUpdate(applicationInstanceDTO); + return result; +} + +Future?> updateAppConfigurationOrder(AppContext appContext, List appConfigurationLinks) async { + List? appConfigurationsLinks = await (appContext.getContext() as ManagerAppContext).clientAPI!.applicationInstanceApi!.applicationInstanceUpdateApplicationLinkOrder(appConfigurationLinks); + return appConfigurationsLinks; +} + +Future updateApplicationLink(AppContext appContext, AppConfigurationLinkDTO appConfigurationLinkDTO) async { + AppConfigurationLinkDTO? result = await (appContext.getContext() as ManagerAppContext).clientAPI!.applicationInstanceApi!.applicationInstanceUpdateApplicationLink(appConfigurationLinkDTO); + return result; +} + Future deleteConfigurationToApp(AppContext appContext, AppConfigurationLinkDTO appConfigurationLink, ApplicationInstanceDTO applicationInstanceDTO) async { var result = await (appContext.getContext() as ManagerAppContext).clientAPI!.applicationInstanceApi!.applicationInstanceDeleteAppConfigurationLink(applicationInstanceDTO.id!, appConfigurationLink.id!); return result; diff --git a/lib/Screens/Configurations/Section/SubSection/Map/new_update_categorie.dart b/lib/Screens/Configurations/Section/SubSection/Map/new_update_categorie.dart index 64b6972..05ab9e0 100644 --- a/lib/Screens/Configurations/Section/SubSection/Map/new_update_categorie.dart +++ b/lib/Screens/Configurations/Section/SubSection/Map/new_update_categorie.dart @@ -89,7 +89,7 @@ Future showNewOrUpdateCategory(CategorieDTO? inputCategorieDTO, A categorieDTO.resourceDTO = resource; } }, - isSmall: true + //isSmall: true ), ), ], diff --git a/lib/Screens/Kiosk_devices/device_element.dart b/lib/Screens/Kiosk_devices/device_element.dart index 837ac4d..4599702 100644 --- a/lib/Screens/Kiosk_devices/device_element.dart +++ b/lib/Screens/Kiosk_devices/device_element.dart @@ -23,6 +23,13 @@ class DeviceElement extends StatefulWidget { } class _DeviceElementState extends State { + late DeviceDTO? updatedDevice; + + @override + void initState() { + updatedDevice = widget.deviceDTO; + super.initState(); + } @override Widget build(BuildContext context) { @@ -66,7 +73,7 @@ class _DeviceElementState extends State { ), Center( child: Text( - widget.appConfigurationLinkDTO.configuration != null ? widget.appConfigurationLinkDTO.configuration!.label! : "Aucune configuration", + updatedDevice?.configuration != null ? updatedDevice?.configuration! ?? "Aucune configuration" : "Aucune configuration", style: new TextStyle(fontSize: 20), maxLines: 1, ), @@ -81,14 +88,14 @@ class _DeviceElementState extends State { "Mettre à jour la tablette", widget.deviceDTO, widget.appConfigurationLinkDTO, - (DeviceDTO outputDevice, AppConfigurationLinkDTO outputAppConfig) { - // For refresh + (DeviceDTO outputDevice, AppConfigurationLinkDTO outputAppConfig) async { + var deviceDTO = outputDevice; + + // Update device main info + var result = await updateMainInfos(deviceDTO, outputAppConfig, appContext); + setState(() { - //print("output"); - //print(outputDevice); - var deviceDTO = outputDevice; - // Update device main info - updateMainInfos(deviceDTO, outputAppConfig, appContext); + updatedDevice = result; }); }, 1, @@ -108,6 +115,7 @@ class _DeviceElementState extends State { DeviceDTO? device = await managerAppContext.clientAPI!.deviceApi!.deviceUpdateMainInfos(deviceToUpdate); + appConfigurationToUpdate.configurationId = deviceToUpdate.configurationId; appConfigurationToUpdate.layoutMainPage = LayoutMainPageType.SimpleGrid; // Hardcoded for now as not supported AppConfigurationLinkDTO? result = await managerAppContext.clientAPI!.applicationInstanceApi!.applicationInstanceUpdateApplicationLink(appConfigurationToUpdate); diff --git a/lib/Screens/Kiosk_devices/kiosk_screen.dart b/lib/Screens/Kiosk_devices/kiosk_screen.dart index cf4a2bf..0b9d566 100644 --- a/lib/Screens/Kiosk_devices/kiosk_screen.dart +++ b/lib/Screens/Kiosk_devices/kiosk_screen.dart @@ -43,44 +43,55 @@ class _KioskScreenState extends State { ), ), ), - FutureBuilder( - future: getAppConfigurationLink(appContext, widget.applicationInstanceDTO), - builder: (context, AsyncSnapshot snapshot) { + Column( + children: [ + Align( + alignment: Alignment.centerLeft, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text("Tablettes"), + ) + ), + FutureBuilder( + future: getAppConfigurationLink(appContext, widget.applicationInstanceDTO), + builder: (context, AsyncSnapshot snapshot) { - List? appConfigurationLinks = snapshot.data; + List? appConfigurationLinks = snapshot.data; - if (snapshot.connectionState == ConnectionState.done && appConfigurationLinks != null) { - final screenWidth = MediaQuery.of(context).size.width; - final itemWidth = 175; - final crossAxisCount = (screenWidth / itemWidth).floor().clamp(1, 6); + if (snapshot.connectionState == ConnectionState.done && appConfigurationLinks != null) { + final screenWidth = MediaQuery.of(context).size.width; + final itemWidth = 175; + final crossAxisCount = (screenWidth / itemWidth).floor().clamp(1, 6); - return GridView.builder( - shrinkWrap: true, - gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: crossAxisCount), - itemCount: appConfigurationLinks.length, - itemBuilder: (BuildContext context, int index) { - return Container( - decoration: boxDecoration(), - padding: const EdgeInsets.all(10), - margin: EdgeInsets.symmetric(vertical: 10, horizontal: 10), - child: Align( - alignment: Alignment.center, - child: DeviceElement(deviceDTO: appConfigurationLinks[index].device!, appConfigurationLinkDTO: appConfigurationLinks[index]), //getElement() - ), - ); - } - ); - } else if (snapshot.connectionState == ConnectionState.none || appConfigurationLinks == null) { - return Text("No data"); - } else { - return Center( - child: Container( - height: size.height * 0.2, - child: CommonLoader() - ) - ); - } - } + return GridView.builder( + shrinkWrap: true, + gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: crossAxisCount), + itemCount: appConfigurationLinks.length, + itemBuilder: (BuildContext context, int index) { + return Container( + decoration: boxDecoration(), + padding: const EdgeInsets.all(10), + margin: EdgeInsets.symmetric(vertical: 10, horizontal: 10), + child: Align( + alignment: Alignment.center, + child: DeviceElement(deviceDTO: appConfigurationLinks[index].device!, appConfigurationLinkDTO: appConfigurationLinks[index]), //getElement() + ), + ); + } + ); + } else if (snapshot.connectionState == ConnectionState.none || appConfigurationLinks == null) { + return Text("No data"); + } else { + return Center( + child: Container( + height: size.height * 0.2, + child: CommonLoader() + ) + ); + } + } + ), + ], ), ], ), diff --git a/lib/Screens/login_screen.dart b/lib/Screens/login_screen.dart index be55531..abe2d1e 100644 --- a/lib/Screens/login_screen.dart +++ b/lib/Screens/login_screen.dart @@ -260,12 +260,6 @@ class _LoginScreenState extends State { initInstance(appContext.getContext()); - // ==> We need to work with route or something else like pop-up (pop up is nice) to make it works ! - /*if(mounted && appContext != null && this.token != null) - { - this.authenticateTRY(appContext, false); - }*/ - return Scaffold( key: loginKey, body: Center( @@ -273,6 +267,7 @@ class _LoginScreenState extends State { child: Container( height: size.height *0.7, width: size.width *0.4, + constraints: BoxConstraints(minWidth: 400, minHeight: 600), decoration: BoxDecoration( color: kWhite, borderRadius: BorderRadius.circular(8.0), @@ -343,8 +338,9 @@ class _LoginScreenState extends State { child: AutofillGroup( child: Column( children: [ - SizedBox( + Container( width: size.width*0.2, + constraints: BoxConstraints(minWidth: 250, maxWidth: 400), child: RoundedInputField( hintText: "E-mail", autofill: AutofillHints.email, @@ -356,8 +352,9 @@ class _LoginScreenState extends State { isEmail: true, ), ), - SizedBox( + Container( width: size.width*0.2, + constraints: BoxConstraints(minWidth: 250, maxWidth: 400), child: RoundedPasswordField( initialValue: password, onChanged: (value) { diff --git a/lib/api/openApiTest.dart b/lib/api/openApiTest.dart index 92888e3..4c6d984 100644 --- a/lib/api/openApiTest.dart +++ b/lib/api/openApiTest.dart @@ -1,4 +1,4 @@ -// Openapi Generator last run: : 2025-08-14T22:13:12.782467 +// Openapi Generator last run: : 2025-09-18T22:38:26.708661 import 'package:openapi_generator_annotations/openapi_generator_annotations.dart'; @Openapi( diff --git a/lib/api/swagger.yaml b/lib/api/swagger.yaml index 07112a0..38fb79e 100644 --- a/lib/api/swagger.yaml +++ b/lib/api/swagger.yaml @@ -4,7 +4,7 @@ "info": { "title": "Manager Service", "description": "API Manager Service", - "version": "Version Alpha" + "version": "Version Alpha 1.1" }, "servers": [ { @@ -564,6 +564,79 @@ ] } }, + "/api/ApplicationInstance/application-link/order": { + "put": { + "tags": [ + "ApplicationInstance" + ], + "operationId": "ApplicationInstance_UpdateApplicationLinkOrder", + "requestBody": { + "x-name": "appConfigurationLinkDTOs", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AppConfigurationLinkDTO" + } + } + } + }, + "required": true, + "x-position": 1 + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AppConfigurationLinkDTO" + } + } + } + } + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + }, + "security": [ + { + "bearer": [] + } + ] + } + }, "/api/ApplicationInstance/{applicationInstanceId}/application-link/{appConfigurationLinkId}": { "delete": { "tags": [ @@ -2719,6 +2792,74 @@ ] } }, + "/api/Section/detail": { + "get": { + "tags": [ + "Section" + ], + "operationId": "Section_GetAllFromType", + "parameters": [ + { + "name": "instanceId", + "in": "query", + "schema": { + "type": "string", + "nullable": true + }, + "x-position": 1 + }, + { + "name": "sectionType", + "in": "query", + "schema": { + "type": "string", + "nullable": true + }, + "x-position": 2 + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SectionDTO" + } + } + } + } + }, + "500": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + }, + "400": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + } + }, + "security": [ + { + "bearer": [] + } + ] + } + }, "/api/Section/configuration/{id}": { "get": { "tags": [ @@ -5459,12 +5600,27 @@ "type": "string", "nullable": true }, + "layoutMainPage": { + "$ref": "#/components/schemas/LayoutMainPageType" + }, "languages": { "type": "array", "nullable": true, "items": { "type": "string" } + }, + "sectionEventId": { + "type": "string", + "nullable": true + }, + "sectionEventDTO": { + "nullable": true, + "oneOf": [ + { + "$ref": "#/components/schemas/SectionEventDTO" + } + ] } } }, @@ -6796,6 +6952,129 @@ } } }, + "SectionEventDTO": { + "allOf": [ + { + "$ref": "#/components/schemas/SectionDTO" + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "startDate": { + "type": "string", + "format": "date-time" + }, + "endDate": { + "type": "string", + "format": "date-time" + }, + "parcoursIds": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "programme": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/ProgrammeBlock" + } + } + } + } + ] + }, + "SectionDTO": { + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "nullable": true + }, + "label": { + "type": "string", + "nullable": true + }, + "title": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/TranslationDTO" + } + }, + "description": { + "type": "array", + "nullable": true, + "items": { + "$ref": "#/components/schemas/TranslationDTO" + } + }, + "isActive": { + "type": "boolean" + }, + "imageId": { + "type": "string", + "nullable": true + }, + "imageSource": { + "type": "string", + "nullable": true + }, + "configurationId": { + "type": "string", + "nullable": true + }, + "isSubSection": { + "type": "boolean" + }, + "parentId": { + "type": "string", + "nullable": true + }, + "type": { + "$ref": "#/components/schemas/SectionType" + }, + "dateCreation": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "order": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "instanceId": { + "type": "string", + "nullable": true + }, + "latitude": { + "type": "string", + "nullable": true + }, + "longitude": { + "type": "string", + "nullable": true + }, + "meterZoneGPS": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "isBeacon": { + "type": "boolean" + }, + "beaconId": { + "type": "integer", + "format": "int32", + "nullable": true + } + } + }, "AppConfigurationLinkDTO": { "type": "object", "additionalProperties": false, @@ -7033,94 +7312,6 @@ } ] }, - "SectionDTO": { - "type": "object", - "additionalProperties": false, - "properties": { - "id": { - "type": "string", - "nullable": true - }, - "label": { - "type": "string", - "nullable": true - }, - "title": { - "type": "array", - "nullable": true, - "items": { - "$ref": "#/components/schemas/TranslationDTO" - } - }, - "description": { - "type": "array", - "nullable": true, - "items": { - "$ref": "#/components/schemas/TranslationDTO" - } - }, - "isActive": { - "type": "boolean" - }, - "imageId": { - "type": "string", - "nullable": true - }, - "imageSource": { - "type": "string", - "nullable": true - }, - "configurationId": { - "type": "string", - "nullable": true - }, - "isSubSection": { - "type": "boolean" - }, - "parentId": { - "type": "string", - "nullable": true - }, - "type": { - "$ref": "#/components/schemas/SectionType" - }, - "dateCreation": { - "type": "string", - "format": "date-time", - "nullable": true - }, - "order": { - "type": "integer", - "format": "int32", - "nullable": true - }, - "instanceId": { - "type": "string", - "nullable": true - }, - "latitude": { - "type": "string", - "nullable": true - }, - "longitude": { - "type": "string", - "nullable": true - }, - "meterZoneGPS": { - "type": "integer", - "format": "int32", - "nullable": true - }, - "isBeacon": { - "type": "boolean" - }, - "beaconId": { - "type": "integer", - "format": "int32", - "nullable": true - } - } - }, "ResourceDTO": { "type": "object", "additionalProperties": false, @@ -8119,41 +8310,6 @@ } ] }, - "SectionEventDTO": { - "allOf": [ - { - "$ref": "#/components/schemas/SectionDTO" - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "startDate": { - "type": "string", - "format": "date-time" - }, - "endDate": { - "type": "string", - "format": "date-time" - }, - "parcoursIds": { - "type": "array", - "nullable": true, - "items": { - "type": "string" - } - }, - "programme": { - "type": "array", - "nullable": true, - "items": { - "$ref": "#/components/schemas/ProgrammeBlock" - } - } - } - } - ] - }, "GuidedPathDTO": { "type": "object", "additionalProperties": false, diff --git a/lib/main.dart b/lib/main.dart index b97a331..5c94295 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -47,127 +47,130 @@ Future main() async { usePathUrlStrategy(); runApp( - MaterialApp( - home: FutureBuilder( - future: getInstanceInfo(managerAppContext), - builder: (context, asyncSnapshot) { - if (asyncSnapshot.connectionState == ConnectionState.done) { - var instanceDTO = asyncSnapshot.data; - managerAppContext.instanceId = instanceDTO?.id; - managerAppContext.instanceDTO = instanceDTO; + ChangeNotifierProvider( + create: (_) => AppContext(managerAppContext), + child: MaterialApp( + home: FutureBuilder( + future: getInstanceInfo(managerAppContext), + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == ConnectionState.done) { + var instanceDTO = asyncSnapshot.data; + managerAppContext.instanceId = instanceDTO?.id; + managerAppContext.instanceDTO = instanceDTO; - String initialRoute = currentPath!.isNotEmpty ? currentPath : '/login'; + String initialRoute = currentPath!.isNotEmpty ? currentPath : '/login'; - var _router = GoRouter( - initialLocation: initialRoute, - redirect: (context, state) { - var instanceId = managerAppContext.instanceId; - if (instanceId == null && state.fullPath != '/login') { - return '/login'; - } - - - if (instanceId != null) { - if(state.fullPath == '/login' || state.fullPath == "") { - if(managerAppContext.instanceDTO!.isMobile!) { - return '/main/mobile'; - } - if(managerAppContext.instanceDTO!.isTablet!) { - return '/main/tablet'; - } - if(managerAppContext.instanceDTO!.isWeb!) { - return '/main/web'; - } - if(managerAppContext.instanceDTO!.isVR!) { - return '/main/vr'; - } + var _router = GoRouter( + initialLocation: initialRoute, + redirect: (context, state) { + var instanceId = managerAppContext.instanceId; + if (instanceId == null && state.fullPath != '/login') { + return '/login'; } - return state.matchedLocation; - } - return null; - }, - routes: [ - GoRoute( - path: '/login', - builder: (context, state) => LoginScreen(), + + if (instanceId != null) { + if(state.fullPath == '/login' || state.fullPath == "") { + if(managerAppContext.instanceDTO!.isMobile!) { + return '/main/mobile'; + } + if(managerAppContext.instanceDTO!.isTablet!) { + return '/main/tablet'; + } + if(managerAppContext.instanceDTO!.isWeb!) { + return '/main/web'; + } + if(managerAppContext.instanceDTO!.isVR!) { + return '/main/vr'; + } + } + return state.matchedLocation; + } + + return null; + }, + routes: [ + GoRoute( + path: '/login', + builder: (context, state) => LoginScreen(), + ), + GoRoute( + path: '/main/:view', + builder: (context, state) { + final view = state.pathParameters['view']; + return MainScreen( + instance: managerAppContext.instanceDTO!, + view: view, + ); + }, + ), + GoRoute( + path: '/policy', + builder: (context, state) => PolicyScreen(), + ), + GoRoute( + path: '/policy/mdlf', + builder: (context, state) => PolicyScreen(param: "mdlf"), + ), + GoRoute( + path: '/policy/fort', + builder: (context, state) => PolicyScreen(param: "fort"), + ), + ], + errorBuilder: (context, state) => MaterialApp( + home: Scaffold( + body: Center( + child: SizedBox( + width: MediaQuery.of(context).size.width * 0.85, + child: Text( + "404 - Cette page n'existe pas", + textAlign: TextAlign.center, + style: TextStyle(color: kPrimaryColor, fontSize: 20.0), + ), + ), + ), + ), ), - GoRoute( - path: '/main/:view', - builder: (context, state) { - final view = state.pathParameters['view']; - return MainScreen( - instance: managerAppContext.instanceDTO!, - view: view, - ); - }, - ), - GoRoute( - path: '/policy', - builder: (context, state) => PolicyScreen(), - ), - GoRoute( - path: '/policy/mdlf', - builder: (context, state) => PolicyScreen(param: "mdlf"), - ), - GoRoute( - path: '/policy/fort', - builder: (context, state) => PolicyScreen(param: "fort"), - ), - ], - errorBuilder: (context, state) => MaterialApp( + ); + + return MyApp( + session: session, + managerAppContext: managerAppContext, + router: _router + ); + } else if (asyncSnapshot.connectionState == ConnectionState.none) { + return MaterialApp( home: Scaffold( body: Center( child: SizedBox( width: MediaQuery.of(context).size.width * 0.85, child: Text( - "404 - Cette page n'existe pas", + "No data", textAlign: TextAlign.center, style: TextStyle(color: kPrimaryColor, fontSize: 20.0), ), ), ), ), - ), - ); - - return MyApp( - session: session, - managerAppContext: managerAppContext, - router: _router - ); - } else if (asyncSnapshot.connectionState == ConnectionState.none) { - return MaterialApp( - home: Scaffold( - body: Center( - child: SizedBox( - width: MediaQuery.of(context).size.width * 0.85, - child: Text( - "No data", - textAlign: TextAlign.center, - style: TextStyle(color: kPrimaryColor, fontSize: 20.0), + ); + } else { + return MaterialApp( + home: Scaffold( + body: Center( + child: SizedBox( + width: MediaQuery.of(context).size.width * 0.85, + child: Container( + height: 250, + child: CommonLoader() + ), ), ), ), - ), - ); - } else { - return MaterialApp( - home: Scaffold( - body: Center( - child: SizedBox( - width: MediaQuery.of(context).size.width * 0.85, - child: Container( - height: 250, - child: CommonLoader() - ), - ), - ), - ), - ); + ); + } } - } - ), + ), + ), ) ); } @@ -220,47 +223,44 @@ class _MyAppState extends State { @override Widget build(BuildContext context) { - return ChangeNotifierProvider( - create: (_) => AppContext(widget.managerAppContext), - child: MaterialApp.router( - routerConfig: widget.router, - key: mainKey, - builder: (context, child) => ResponsiveBreakpoints.builder( - child: child!, - breakpoints: [ - const Breakpoint(start: 0, end: 450, name: MOBILE), - const Breakpoint(start: 451, end: 800, name: TABLET), - const Breakpoint(start: 801, end: 1920, name: DESKTOP), - const Breakpoint(start: 1921, end: double.infinity, name: '4K'), - ], - ), - scrollBehavior: MyCustomScrollBehavior(), - debugShowCheckedModeBanner: false, - title: 'MyInfoMate - Manager', - //initialRoute: widget.initialRoute, - /*supportedLocales: [ - const Locale('en', 'US'), - //const Locale('fr', 'FR'), - ],*/ - theme: ThemeData( - primarySwatch: Colors.blue, - primaryColor: kPrimaryColor, - scaffoldBackgroundColor: kBackgroundColor, - //fontFamily: "Vollkorn", - textTheme: TextTheme(bodyLarge: TextStyle(color: kBodyTextColor)), - visualDensity: VisualDensity.adaptivePlatformDensity, - ), - /*routes: { - '/login': (context) => LoginScreen(session: widget.session), - '/main': (context) => MainScreen(), - '/policy': (context) => PolicyScreen(), - '/policy/mdlf': (context) => PolicyScreen(param: "mdlf"), - '/policy/fort': (context) => PolicyScreen(param: "fort"), - }, - onUnknownRoute: (settings) => MaterialPageRoute( - builder: (context) => Container(child: Center(child: Text("Not found"))), - ),*/ - ), + return MaterialApp.router( + routerConfig: widget.router, + key: mainKey, + builder: (context, child) => ResponsiveBreakpoints.builder( + child: child!, + breakpoints: [ + const Breakpoint(start: 0, end: 550, name: MOBILE), + const Breakpoint(start: 550, end: 800, name: TABLET), + const Breakpoint(start: 801, end: 1920, name: DESKTOP), + const Breakpoint(start: 1921, end: double.infinity, name: '4K'), + ], + ), + scrollBehavior: MyCustomScrollBehavior(), + debugShowCheckedModeBanner: false, + title: 'MyInfoMate - Manager', + //initialRoute: widget.initialRoute, + /*supportedLocales: [ + const Locale('en', 'US'), + //const Locale('fr', 'FR'), + ],*/ + theme: ThemeData( + primarySwatch: Colors.blue, + primaryColor: kPrimaryColor, + scaffoldBackgroundColor: kBackgroundColor, + //fontFamily: "Vollkorn", + textTheme: TextTheme(bodyLarge: TextStyle(color: kBodyTextColor)), + visualDensity: VisualDensity.adaptivePlatformDensity, + ), + /*routes: { + '/login': (context) => LoginScreen(session: widget.session), + '/main': (context) => MainScreen(), + '/policy': (context) => PolicyScreen(), + '/policy/mdlf': (context) => PolicyScreen(param: "mdlf"), + '/policy/fort': (context) => PolicyScreen(param: "fort"), + }, + onUnknownRoute: (settings) => MaterialPageRoute( + builder: (context) => Container(child: Center(child: Text("Not found"))), + ),*/ ); } } diff --git a/manager_api_new/.openapi-generator/FILES b/manager_api_new/.openapi-generator/FILES index ffa7adc..2ad2abb 100644 --- a/manager_api_new/.openapi-generator/FILES +++ b/manager_api_new/.openapi-generator/FILES @@ -15,6 +15,7 @@ doc/AppType.md doc/ApplicationInstance.md doc/ApplicationInstanceApi.md doc/ApplicationInstanceDTO.md +doc/ApplicationInstanceDTOSectionEventDTO.md doc/ApplicationInstanceSectionEvent.md doc/ArticleDTO.md doc/AuthenticationApi.md @@ -165,6 +166,7 @@ lib/model/app_configuration_link_dto_device.dart lib/model/app_type.dart lib/model/application_instance.dart lib/model/application_instance_dto.dart +lib/model/application_instance_dto_section_event_dto.dart lib/model/application_instance_section_event.dart lib/model/article_dto.dart lib/model/categorie_dto.dart diff --git a/manager_api_new/README.md b/manager_api_new/README.md index ea6b18b..fedbf90 100644 --- a/manager_api_new/README.md +++ b/manager_api_new/README.md @@ -3,7 +3,7 @@ API Manager Service This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: -- API version: Version Alpha +- API version: Version Alpha 1.1 - Generator version: 7.9.0 - Build package: org.openapitools.codegen.languages.DartClientCodegen @@ -70,6 +70,7 @@ Class | Method | HTTP request | Description *ApplicationInstanceApi* | [**applicationInstanceGetAllApplicationLinkFromApplicationInstance**](doc//ApplicationInstanceApi.md#applicationinstancegetallapplicationlinkfromapplicationinstance) | **GET** /api/ApplicationInstance/{applicationInstanceId}/application-link | *ApplicationInstanceApi* | [**applicationInstanceUpdate**](doc//ApplicationInstanceApi.md#applicationinstanceupdate) | **PUT** /api/ApplicationInstance | *ApplicationInstanceApi* | [**applicationInstanceUpdateApplicationLink**](doc//ApplicationInstanceApi.md#applicationinstanceupdateapplicationlink) | **PUT** /api/ApplicationInstance/application-link | +*ApplicationInstanceApi* | [**applicationInstanceUpdateApplicationLinkOrder**](doc//ApplicationInstanceApi.md#applicationinstanceupdateapplicationlinkorder) | **PUT** /api/ApplicationInstance/application-link/order | *AuthenticationApi* | [**authenticationAuthenticateWithForm**](doc//AuthenticationApi.md#authenticationauthenticatewithform) | **POST** /api/Authentication/Token | *AuthenticationApi* | [**authenticationAuthenticateWithJson**](doc//AuthenticationApi.md#authenticationauthenticatewithjson) | **POST** /api/Authentication/Authenticate | *ConfigurationApi* | [**configurationCreate**](doc//ConfigurationApi.md#configurationcreate) | **POST** /api/Configuration | @@ -105,6 +106,7 @@ Class | Method | HTTP request | Description *SectionApi* | [**sectionGet**](doc//SectionApi.md#sectionget) | **GET** /api/Section | *SectionApi* | [**sectionGetAgendaDTO**](doc//SectionApi.md#sectiongetagendadto) | **GET** /api/Section/AgendaDTO | *SectionApi* | [**sectionGetAllBeaconsForInstance**](doc//SectionApi.md#sectiongetallbeaconsforinstance) | **GET** /api/Section/beacons/{instanceId} | +*SectionApi* | [**sectionGetAllFromType**](doc//SectionApi.md#sectiongetallfromtype) | **GET** /api/Section/detail | *SectionApi* | [**sectionGetAllSectionSubSections**](doc//SectionApi.md#sectiongetallsectionsubsections) | **GET** /api/Section/{id}/subsections | *SectionApi* | [**sectionGetArticleDTO**](doc//SectionApi.md#sectiongetarticledto) | **GET** /api/Section/ArticleDTO | *SectionApi* | [**sectionGetDetail**](doc//SectionApi.md#sectiongetdetail) | **GET** /api/Section/{id} | @@ -173,6 +175,7 @@ Class | Method | HTTP request | Description - [AppType](doc//AppType.md) - [ApplicationInstance](doc//ApplicationInstance.md) - [ApplicationInstanceDTO](doc//ApplicationInstanceDTO.md) + - [ApplicationInstanceDTOSectionEventDTO](doc//ApplicationInstanceDTOSectionEventDTO.md) - [ApplicationInstanceSectionEvent](doc//ApplicationInstanceSectionEvent.md) - [ArticleDTO](doc//ArticleDTO.md) - [CategorieDTO](doc//CategorieDTO.md) diff --git a/manager_api_new/doc/ApplicationInstanceApi.md b/manager_api_new/doc/ApplicationInstanceApi.md index 6a40999..bb036d2 100644 --- a/manager_api_new/doc/ApplicationInstanceApi.md +++ b/manager_api_new/doc/ApplicationInstanceApi.md @@ -17,6 +17,7 @@ Method | HTTP request | Description [**applicationInstanceGetAllApplicationLinkFromApplicationInstance**](ApplicationInstanceApi.md#applicationinstancegetallapplicationlinkfromapplicationinstance) | **GET** /api/ApplicationInstance/{applicationInstanceId}/application-link | [**applicationInstanceUpdate**](ApplicationInstanceApi.md#applicationinstanceupdate) | **PUT** /api/ApplicationInstance | [**applicationInstanceUpdateApplicationLink**](ApplicationInstanceApi.md#applicationinstanceupdateapplicationlink) | **PUT** /api/ApplicationInstance/application-link | +[**applicationInstanceUpdateApplicationLinkOrder**](ApplicationInstanceApi.md#applicationinstanceupdateapplicationlinkorder) | **PUT** /api/ApplicationInstance/application-link/order | # **applicationInstanceAddConfigurationToApplicationInstance** @@ -367,3 +368,46 @@ Name | Type | Description | Notes [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +# **applicationInstanceUpdateApplicationLinkOrder** +> List applicationInstanceUpdateApplicationLinkOrder(appConfigurationLinkDTO) + + + +### Example +```dart +import 'package:manager_api_new/api.dart'; +// TODO Configure OAuth2 access token for authorization: bearer +//defaultApiClient.getAuthentication('bearer').accessToken = 'YOUR_ACCESS_TOKEN'; + +final api_instance = ApplicationInstanceApi(); +final appConfigurationLinkDTO = [List()]; // List | + +try { + final result = api_instance.applicationInstanceUpdateApplicationLinkOrder(appConfigurationLinkDTO); + print(result); +} catch (e) { + print('Exception when calling ApplicationInstanceApi->applicationInstanceUpdateApplicationLinkOrder: $e\n'); +} +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **appConfigurationLinkDTO** | [**List**](AppConfigurationLinkDTO.md)| | + +### Return type + +[**List**](AppConfigurationLinkDTO.md) + +### Authorization + +[bearer](../README.md#bearer) + +### HTTP request headers + + - **Content-Type**: application/json + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/manager_api_new/doc/ApplicationInstanceDTO.md b/manager_api_new/doc/ApplicationInstanceDTO.md index 1f3c9e7..f71507b 100644 --- a/manager_api_new/doc/ApplicationInstanceDTO.md +++ b/manager_api_new/doc/ApplicationInstanceDTO.md @@ -18,7 +18,10 @@ Name | Type | Description | Notes **loaderImageUrl** | **String** | | [optional] **primaryColor** | **String** | | [optional] **secondaryColor** | **String** | | [optional] +**layoutMainPage** | [**LayoutMainPageType**](LayoutMainPageType.md) | | [optional] **languages** | **List** | | [optional] [default to const []] +**sectionEventId** | **String** | | [optional] +**sectionEventDTO** | [**ApplicationInstanceDTOSectionEventDTO**](ApplicationInstanceDTOSectionEventDTO.md) | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/manager_api_new/doc/ApplicationInstanceDTOSectionEventDTO.md b/manager_api_new/doc/ApplicationInstanceDTOSectionEventDTO.md new file mode 100644 index 0000000..a342413 --- /dev/null +++ b/manager_api_new/doc/ApplicationInstanceDTOSectionEventDTO.md @@ -0,0 +1,37 @@ +# manager_api_new.model.ApplicationInstanceDTOSectionEventDTO + +## Load the model package +```dart +import 'package:manager_api_new/api.dart'; +``` + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**id** | **String** | | [optional] +**label** | **String** | | [optional] +**title** | [**List**](TranslationDTO.md) | | [optional] [default to const []] +**description** | [**List**](TranslationDTO.md) | | [optional] [default to const []] +**isActive** | **bool** | | [optional] +**imageId** | **String** | | [optional] +**imageSource** | **String** | | [optional] +**configurationId** | **String** | | [optional] +**isSubSection** | **bool** | | [optional] +**parentId** | **String** | | [optional] +**type** | [**SectionType**](SectionType.md) | | [optional] +**dateCreation** | [**DateTime**](DateTime.md) | | [optional] +**order** | **int** | | [optional] +**instanceId** | **String** | | [optional] +**latitude** | **String** | | [optional] +**longitude** | **String** | | [optional] +**meterZoneGPS** | **int** | | [optional] +**isBeacon** | **bool** | | [optional] +**beaconId** | **int** | | [optional] +**startDate** | [**DateTime**](DateTime.md) | | [optional] +**endDate** | [**DateTime**](DateTime.md) | | [optional] +**parcoursIds** | **List** | | [optional] [default to const []] +**programme** | [**List**](ProgrammeBlock.md) | | [optional] [default to const []] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/manager_api_new/doc/SectionApi.md b/manager_api_new/doc/SectionApi.md index 4e36990..ced38e2 100644 --- a/manager_api_new/doc/SectionApi.md +++ b/manager_api_new/doc/SectionApi.md @@ -15,6 +15,7 @@ Method | HTTP request | Description [**sectionGet**](SectionApi.md#sectionget) | **GET** /api/Section | [**sectionGetAgendaDTO**](SectionApi.md#sectiongetagendadto) | **GET** /api/Section/AgendaDTO | [**sectionGetAllBeaconsForInstance**](SectionApi.md#sectiongetallbeaconsforinstance) | **GET** /api/Section/beacons/{instanceId} | +[**sectionGetAllFromType**](SectionApi.md#sectiongetallfromtype) | **GET** /api/Section/detail | [**sectionGetAllSectionSubSections**](SectionApi.md#sectiongetallsectionsubsections) | **GET** /api/Section/{id}/subsections | [**sectionGetArticleDTO**](SectionApi.md#sectiongetarticledto) | **GET** /api/Section/ArticleDTO | [**sectionGetDetail**](SectionApi.md#sectiongetdetail) | **GET** /api/Section/{id} | @@ -290,6 +291,51 @@ Name | Type | Description | Notes [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +# **sectionGetAllFromType** +> List sectionGetAllFromType(instanceId, sectionType) + + + +### Example +```dart +import 'package:manager_api_new/api.dart'; +// TODO Configure OAuth2 access token for authorization: bearer +//defaultApiClient.getAuthentication('bearer').accessToken = 'YOUR_ACCESS_TOKEN'; + +final api_instance = SectionApi(); +final instanceId = instanceId_example; // String | +final sectionType = sectionType_example; // String | + +try { + final result = api_instance.sectionGetAllFromType(instanceId, sectionType); + print(result); +} catch (e) { + print('Exception when calling SectionApi->sectionGetAllFromType: $e\n'); +} +``` + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **instanceId** | **String**| | [optional] + **sectionType** | **String**| | [optional] + +### Return type + +[**List**](SectionDTO.md) + +### Authorization + +[bearer](../README.md#bearer) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + # **sectionGetAllSectionSubSections** > List sectionGetAllSectionSubSections(id) diff --git a/manager_api_new/lib/api.dart b/manager_api_new/lib/api.dart index f302571..7c0ddb5 100644 --- a/manager_api_new/lib/api.dart +++ b/manager_api_new/lib/api.dart @@ -53,6 +53,7 @@ part 'model/app_configuration_link_device.dart'; part 'model/app_type.dart'; part 'model/application_instance.dart'; part 'model/application_instance_dto.dart'; +part 'model/application_instance_dto_section_event_dto.dart'; part 'model/application_instance_section_event.dart'; part 'model/article_dto.dart'; part 'model/categorie_dto.dart'; diff --git a/manager_api_new/lib/api/application_instance_api.dart b/manager_api_new/lib/api/application_instance_api.dart index 515ca65..e28b6b6 100644 --- a/manager_api_new/lib/api/application_instance_api.dart +++ b/manager_api_new/lib/api/application_instance_api.dart @@ -489,4 +489,62 @@ class ApplicationInstanceApi { } return null; } + + /// Performs an HTTP 'PUT /api/ApplicationInstance/application-link/order' operation and returns the [Response]. + /// Parameters: + /// + /// * [List] appConfigurationLinkDTO (required): + Future applicationInstanceUpdateApplicationLinkOrderWithHttpInfo( + List appConfigurationLinkDTO, + ) async { + // ignore: prefer_const_declarations + final path = r'/api/ApplicationInstance/application-link/order'; + + // ignore: prefer_final_locals + Object? postBody = appConfigurationLinkDTO; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + const contentTypes = ['application/json']; + + return apiClient.invokeAPI( + path, + 'PUT', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + /// Parameters: + /// + /// * [List] appConfigurationLinkDTO (required): + Future?> + applicationInstanceUpdateApplicationLinkOrder( + List appConfigurationLinkDTO, + ) async { + final response = + await applicationInstanceUpdateApplicationLinkOrderWithHttpInfo( + appConfigurationLinkDTO, + ); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await _decodeBodyBytes(response)); + } + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body.isNotEmpty && + response.statusCode != HttpStatus.noContent) { + final responseBody = await _decodeBodyBytes(response); + return (await apiClient.deserializeAsync( + responseBody, 'List') as List) + .cast() + .toList(growable: false); + } + return null; + } } diff --git a/manager_api_new/lib/api/section_api.dart b/manager_api_new/lib/api/section_api.dart index a615121..1ccc8e5 100644 --- a/manager_api_new/lib/api/section_api.dart +++ b/manager_api_new/lib/api/section_api.dart @@ -341,6 +341,78 @@ class SectionApi { return null; } + /// Performs an HTTP 'GET /api/Section/detail' operation and returns the [Response]. + /// Parameters: + /// + /// * [String] instanceId: + /// + /// * [String] sectionType: + Future sectionGetAllFromTypeWithHttpInfo({ + String? instanceId, + String? sectionType, + }) async { + // ignore: prefer_const_declarations + final path = r'/api/Section/detail'; + + // ignore: prefer_final_locals + Object? postBody; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + if (instanceId != null) { + queryParams.addAll(_queryParams('', 'instanceId', instanceId)); + } + if (sectionType != null) { + queryParams.addAll(_queryParams('', 'sectionType', sectionType)); + } + + const contentTypes = []; + + return apiClient.invokeAPI( + path, + 'GET', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + /// Parameters: + /// + /// * [String] instanceId: + /// + /// * [String] sectionType: + Future sectionGetAllFromType({ + String? instanceId, + String? sectionType, + }) async { + final response = await sectionGetAllFromTypeWithHttpInfo( + instanceId: instanceId, + sectionType: sectionType, + ); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await _decodeBodyBytes(response)); + } + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body.isNotEmpty && + response.statusCode != HttpStatus.noContent) { + /*final responseBody = await _decodeBodyBytes(response); + return (await apiClient.deserializeAsync(responseBody, 'List') + as List) + .cast() + .toList(growable: false);*/ + final decoded = json.decode(await _decodeBodyBytes(response)); + return decoded; + } + return null; + } + /// Performs an HTTP 'GET /api/Section/{id}/subsections' operation and returns the [Response]. /// Parameters: /// diff --git a/manager_api_new/lib/api_client.dart b/manager_api_new/lib/api_client.dart index 1c41593..0cd4fa1 100644 --- a/manager_api_new/lib/api_client.dart +++ b/manager_api_new/lib/api_client.dart @@ -253,6 +253,8 @@ class ApiClient { return ApplicationInstance.fromJson(value); case 'ApplicationInstanceDTO': return ApplicationInstanceDTO.fromJson(value); + case 'ApplicationInstanceDTOSectionEventDTO': + return ApplicationInstanceDTOSectionEventDTO.fromJson(value); case 'ApplicationInstanceSectionEvent': return ApplicationInstanceSectionEvent.fromJson(value); case 'ArticleDTO': diff --git a/manager_api_new/lib/model/app_configuration_link_dto.dart b/manager_api_new/lib/model/app_configuration_link_dto.dart index 6bf7889..2c15451 100644 --- a/manager_api_new/lib/model/app_configuration_link_dto.dart +++ b/manager_api_new/lib/model/app_configuration_link_dto.dart @@ -38,7 +38,7 @@ class AppConfigurationLinkDTO { String? configurationId; - AppConfigurationLinkDTOConfiguration? configuration; + ConfigurationDTO? configuration; String? applicationInstanceId; @@ -282,7 +282,7 @@ class AppConfigurationLinkDTO { return AppConfigurationLinkDTO( id: mapValueOfType(json, r'id'), configurationId: mapValueOfType(json, r'configurationId'), - configuration: AppConfigurationLinkDTOConfiguration.fromJson( + configuration: ConfigurationDTO.fromJson( json[r'configuration']), applicationInstanceId: mapValueOfType(json, r'applicationInstanceId'), diff --git a/manager_api_new/lib/model/application_instance_dto.dart b/manager_api_new/lib/model/application_instance_dto.dart index b3f3a8b..f73f8ae 100644 --- a/manager_api_new/lib/model/application_instance_dto.dart +++ b/manager_api_new/lib/model/application_instance_dto.dart @@ -23,7 +23,10 @@ class ApplicationInstanceDTO { this.loaderImageUrl, this.primaryColor, this.secondaryColor, + this.layoutMainPage, this.languages = const [], + this.sectionEventId, + this.sectionEventDTO, }); String? id; @@ -52,8 +55,20 @@ class ApplicationInstanceDTO { String? secondaryColor; + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + LayoutMainPageType? layoutMainPage; + List? languages; + String? sectionEventId; + + SectionEventDTO? sectionEventDTO; + @override bool operator ==(Object other) => identical(this, other) || @@ -68,7 +83,10 @@ class ApplicationInstanceDTO { other.loaderImageUrl == loaderImageUrl && other.primaryColor == primaryColor && other.secondaryColor == secondaryColor && - _deepEquality.equals(other.languages, languages); + other.layoutMainPage == layoutMainPage && + _deepEquality.equals(other.languages, languages) && + other.sectionEventId == sectionEventId && + other.sectionEventDTO == sectionEventDTO; @override int get hashCode => @@ -83,11 +101,14 @@ class ApplicationInstanceDTO { (loaderImageUrl == null ? 0 : loaderImageUrl!.hashCode) + (primaryColor == null ? 0 : primaryColor!.hashCode) + (secondaryColor == null ? 0 : secondaryColor!.hashCode) + - (languages == null ? 0 : languages!.hashCode); + (layoutMainPage == null ? 0 : layoutMainPage!.hashCode) + + (languages == null ? 0 : languages!.hashCode) + + (sectionEventId == null ? 0 : sectionEventId!.hashCode) + + (sectionEventDTO == null ? 0 : sectionEventDTO!.hashCode); @override String toString() => - 'ApplicationInstanceDTO[id=$id, instanceId=$instanceId, appType=$appType, configurations=$configurations, mainImageId=$mainImageId, mainImageUrl=$mainImageUrl, loaderImageId=$loaderImageId, loaderImageUrl=$loaderImageUrl, primaryColor=$primaryColor, secondaryColor=$secondaryColor, languages=$languages]'; + 'ApplicationInstanceDTO[id=$id, instanceId=$instanceId, appType=$appType, configurations=$configurations, mainImageId=$mainImageId, mainImageUrl=$mainImageUrl, loaderImageId=$loaderImageId, loaderImageUrl=$loaderImageUrl, primaryColor=$primaryColor, secondaryColor=$secondaryColor, layoutMainPage=$layoutMainPage, languages=$languages, sectionEventId=$sectionEventId, sectionEventDTO=$sectionEventDTO]'; Map toJson() { final json = {}; @@ -141,11 +162,26 @@ class ApplicationInstanceDTO { } else { json[r'secondaryColor'] = null; } + if (this.layoutMainPage != null) { + json[r'layoutMainPage'] = this.layoutMainPage; + } else { + json[r'layoutMainPage'] = null; + } if (this.languages != null) { json[r'languages'] = this.languages; } else { json[r'languages'] = null; } + if (this.sectionEventId != null) { + json[r'sectionEventId'] = this.sectionEventId; + } else { + json[r'sectionEventId'] = null; + } + if (this.sectionEventDTO != null) { + json[r'sectionEventDTO'] = this.sectionEventDTO; + } else { + json[r'sectionEventDTO'] = null; + } return json; } @@ -181,11 +217,15 @@ class ApplicationInstanceDTO { loaderImageUrl: mapValueOfType(json, r'loaderImageUrl'), primaryColor: mapValueOfType(json, r'primaryColor'), secondaryColor: mapValueOfType(json, r'secondaryColor'), + layoutMainPage: LayoutMainPageType.fromJson(json[r'layoutMainPage']), languages: json[r'languages'] is Iterable ? (json[r'languages'] as Iterable) .cast() .toList(growable: false) : const [], + sectionEventId: mapValueOfType(json, r'sectionEventId'), + sectionEventDTO: SectionEventDTO.fromJson( + json[r'sectionEventDTO']), ); } return null; diff --git a/manager_api_new/lib/model/application_instance_dto_section_event_dto.dart b/manager_api_new/lib/model/application_instance_dto_section_event_dto.dart new file mode 100644 index 0000000..8bde1c8 --- /dev/null +++ b/manager_api_new/lib/model/application_instance_dto_section_event_dto.dart @@ -0,0 +1,409 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.18 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +part of openapi.api; + +class ApplicationInstanceDTOSectionEventDTO { + /// Returns a new [ApplicationInstanceDTOSectionEventDTO] instance. + ApplicationInstanceDTOSectionEventDTO({ + this.id, + this.label, + this.title = const [], + this.description = const [], + this.isActive, + this.imageId, + this.imageSource, + this.configurationId, + this.isSubSection, + this.parentId, + this.type, + this.dateCreation, + this.order, + this.instanceId, + this.latitude, + this.longitude, + this.meterZoneGPS, + this.isBeacon, + this.beaconId, + this.startDate, + this.endDate, + this.parcoursIds = const [], + this.programme = const [], + }); + + String? id; + + String? label; + + List? title; + + List? description; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + bool? isActive; + + String? imageId; + + String? imageSource; + + String? configurationId; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + bool? isSubSection; + + String? parentId; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + SectionType? type; + + DateTime? dateCreation; + + int? order; + + String? instanceId; + + String? latitude; + + String? longitude; + + int? meterZoneGPS; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + bool? isBeacon; + + int? beaconId; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + DateTime? startDate; + + /// + /// Please note: This property should have been non-nullable! Since the specification file + /// does not include a default value (using the "default:" property), however, the generated + /// source code must fall back to having a nullable type. + /// Consider adding a "default:" property in the specification file to hide this note. + /// + DateTime? endDate; + + List? parcoursIds; + + List? programme; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is ApplicationInstanceDTOSectionEventDTO && + other.id == id && + other.label == label && + _deepEquality.equals(other.title, title) && + _deepEquality.equals(other.description, description) && + other.isActive == isActive && + other.imageId == imageId && + other.imageSource == imageSource && + other.configurationId == configurationId && + other.isSubSection == isSubSection && + other.parentId == parentId && + other.type == type && + other.dateCreation == dateCreation && + other.order == order && + other.instanceId == instanceId && + other.latitude == latitude && + other.longitude == longitude && + other.meterZoneGPS == meterZoneGPS && + other.isBeacon == isBeacon && + other.beaconId == beaconId && + other.startDate == startDate && + other.endDate == endDate && + _deepEquality.equals(other.parcoursIds, parcoursIds) && + _deepEquality.equals(other.programme, programme); + + @override + int get hashCode => + // ignore: unnecessary_parenthesis + (id == null ? 0 : id!.hashCode) + + (label == null ? 0 : label!.hashCode) + + (title == null ? 0 : title!.hashCode) + + (description == null ? 0 : description!.hashCode) + + (isActive == null ? 0 : isActive!.hashCode) + + (imageId == null ? 0 : imageId!.hashCode) + + (imageSource == null ? 0 : imageSource!.hashCode) + + (configurationId == null ? 0 : configurationId!.hashCode) + + (isSubSection == null ? 0 : isSubSection!.hashCode) + + (parentId == null ? 0 : parentId!.hashCode) + + (type == null ? 0 : type!.hashCode) + + (dateCreation == null ? 0 : dateCreation!.hashCode) + + (order == null ? 0 : order!.hashCode) + + (instanceId == null ? 0 : instanceId!.hashCode) + + (latitude == null ? 0 : latitude!.hashCode) + + (longitude == null ? 0 : longitude!.hashCode) + + (meterZoneGPS == null ? 0 : meterZoneGPS!.hashCode) + + (isBeacon == null ? 0 : isBeacon!.hashCode) + + (beaconId == null ? 0 : beaconId!.hashCode) + + (startDate == null ? 0 : startDate!.hashCode) + + (endDate == null ? 0 : endDate!.hashCode) + + (parcoursIds == null ? 0 : parcoursIds!.hashCode) + + (programme == null ? 0 : programme!.hashCode); + + @override + String toString() => + 'ApplicationInstanceDTOSectionEventDTO[id=$id, label=$label, title=$title, description=$description, isActive=$isActive, imageId=$imageId, imageSource=$imageSource, configurationId=$configurationId, isSubSection=$isSubSection, parentId=$parentId, type=$type, dateCreation=$dateCreation, order=$order, instanceId=$instanceId, latitude=$latitude, longitude=$longitude, meterZoneGPS=$meterZoneGPS, isBeacon=$isBeacon, beaconId=$beaconId, startDate=$startDate, endDate=$endDate, parcoursIds=$parcoursIds, programme=$programme]'; + + Map toJson() { + final json = {}; + if (this.id != null) { + json[r'id'] = this.id; + } else { + json[r'id'] = null; + } + if (this.label != null) { + json[r'label'] = this.label; + } else { + json[r'label'] = null; + } + if (this.title != null) { + json[r'title'] = this.title; + } else { + json[r'title'] = null; + } + if (this.description != null) { + json[r'description'] = this.description; + } else { + json[r'description'] = null; + } + if (this.isActive != null) { + json[r'isActive'] = this.isActive; + } else { + json[r'isActive'] = null; + } + if (this.imageId != null) { + json[r'imageId'] = this.imageId; + } else { + json[r'imageId'] = null; + } + if (this.imageSource != null) { + json[r'imageSource'] = this.imageSource; + } else { + json[r'imageSource'] = null; + } + if (this.configurationId != null) { + json[r'configurationId'] = this.configurationId; + } else { + json[r'configurationId'] = null; + } + if (this.isSubSection != null) { + json[r'isSubSection'] = this.isSubSection; + } else { + json[r'isSubSection'] = null; + } + if (this.parentId != null) { + json[r'parentId'] = this.parentId; + } else { + json[r'parentId'] = null; + } + if (this.type != null) { + json[r'type'] = this.type; + } else { + json[r'type'] = null; + } + if (this.dateCreation != null) { + json[r'dateCreation'] = this.dateCreation!.toUtc().toIso8601String(); + } else { + json[r'dateCreation'] = null; + } + if (this.order != null) { + json[r'order'] = this.order; + } else { + json[r'order'] = null; + } + if (this.instanceId != null) { + json[r'instanceId'] = this.instanceId; + } else { + json[r'instanceId'] = null; + } + if (this.latitude != null) { + json[r'latitude'] = this.latitude; + } else { + json[r'latitude'] = null; + } + if (this.longitude != null) { + json[r'longitude'] = this.longitude; + } else { + json[r'longitude'] = null; + } + if (this.meterZoneGPS != null) { + json[r'meterZoneGPS'] = this.meterZoneGPS; + } else { + json[r'meterZoneGPS'] = null; + } + if (this.isBeacon != null) { + json[r'isBeacon'] = this.isBeacon; + } else { + json[r'isBeacon'] = null; + } + if (this.beaconId != null) { + json[r'beaconId'] = this.beaconId; + } else { + json[r'beaconId'] = null; + } + if (this.startDate != null) { + json[r'startDate'] = this.startDate!.toUtc().toIso8601String(); + } else { + json[r'startDate'] = null; + } + if (this.endDate != null) { + json[r'endDate'] = this.endDate!.toUtc().toIso8601String(); + } else { + json[r'endDate'] = null; + } + if (this.parcoursIds != null) { + json[r'parcoursIds'] = this.parcoursIds; + } else { + json[r'parcoursIds'] = null; + } + if (this.programme != null) { + json[r'programme'] = this.programme; + } else { + json[r'programme'] = null; + } + return json; + } + + /// Returns a new [ApplicationInstanceDTOSectionEventDTO] instance and imports its values from + /// [value] if it's a [Map], null otherwise. + // ignore: prefer_constructors_over_static_methods + static ApplicationInstanceDTOSectionEventDTO? fromJson(dynamic value) { + if (value is Map) { + final json = value.cast(); + + // Ensure that the map contains the required keys. + // Note 1: the values aren't checked for validity beyond being non-null. + // Note 2: this code is stripped in release mode! + assert(() { + requiredKeys.forEach((key) { + assert(json.containsKey(key), + 'Required key "ApplicationInstanceDTOSectionEventDTO[$key]" is missing from JSON.'); + assert(json[key] != null, + 'Required key "ApplicationInstanceDTOSectionEventDTO[$key]" has a null value in JSON.'); + }); + return true; + }()); + + return ApplicationInstanceDTOSectionEventDTO( + id: mapValueOfType(json, r'id'), + label: mapValueOfType(json, r'label'), + title: TranslationDTO.listFromJson(json[r'title']), + description: TranslationDTO.listFromJson(json[r'description']), + isActive: mapValueOfType(json, r'isActive'), + imageId: mapValueOfType(json, r'imageId'), + imageSource: mapValueOfType(json, r'imageSource'), + configurationId: mapValueOfType(json, r'configurationId'), + isSubSection: mapValueOfType(json, r'isSubSection'), + parentId: mapValueOfType(json, r'parentId'), + type: SectionType.fromJson(json[r'type']), + dateCreation: mapDateTime(json, r'dateCreation', r''), + order: mapValueOfType(json, r'order'), + instanceId: mapValueOfType(json, r'instanceId'), + latitude: mapValueOfType(json, r'latitude'), + longitude: mapValueOfType(json, r'longitude'), + meterZoneGPS: mapValueOfType(json, r'meterZoneGPS'), + isBeacon: mapValueOfType(json, r'isBeacon'), + beaconId: mapValueOfType(json, r'beaconId'), + startDate: mapDateTime(json, r'startDate', r''), + endDate: mapDateTime(json, r'endDate', r''), + parcoursIds: json[r'parcoursIds'] is Iterable + ? (json[r'parcoursIds'] as Iterable) + .cast() + .toList(growable: false) + : const [], + programme: ProgrammeBlock.listFromJson(json[r'programme']), + ); + } + return null; + } + + static List listFromJson( + dynamic json, { + bool growable = false, + }) { + final result = []; + if (json is List && json.isNotEmpty) { + for (final row in json) { + final value = ApplicationInstanceDTOSectionEventDTO.fromJson(row); + if (value != null) { + result.add(value); + } + } + } + return result.toList(growable: growable); + } + + static Map mapFromJson( + dynamic json) { + final map = {}; + if (json is Map && json.isNotEmpty) { + json = json.cast(); // ignore: parameter_assignments + for (final entry in json.entries) { + final value = + ApplicationInstanceDTOSectionEventDTO.fromJson(entry.value); + if (value != null) { + map[entry.key] = value; + } + } + } + return map; + } + + // maps a json object with a list of ApplicationInstanceDTOSectionEventDTO-objects as value to a dart map + static Map> + mapListFromJson( + dynamic json, { + bool growable = false, + }) { + final map = >{}; + if (json is Map && json.isNotEmpty) { + // ignore: parameter_assignments + json = json.cast(); + for (final entry in json.entries) { + map[entry.key] = ApplicationInstanceDTOSectionEventDTO.listFromJson( + entry.value, + growable: growable, + ); + } + } + return map; + } + + /// The list of required keys that must be present in a JSON. + static const requiredKeys = {}; +} diff --git a/manager_api_new/lib/model/section_type.dart b/manager_api_new/lib/model/section_type.dart index ad229bc..392a713 100644 --- a/manager_api_new/lib/model/section_type.dart +++ b/manager_api_new/lib/model/section_type.dart @@ -10,7 +10,7 @@ part of openapi.api; -/// 0 = Map 1 = Slider 2 = Video 3 = Web 4 = Menu 5 = Quiz 6 = Article 7 = PDF 8 = Puzzle 9 = Agenda +/// 0 = Map 1 = Slider 2 = Video 3 = Web 4 = Menu 5 = Quiz 6 = Article 7 = PDF 8 = Puzzle 9 = Agenda 10 = Event class SectionType { /// Instantiate a new enum with the provided [value]. const SectionType._(this.value); @@ -34,6 +34,7 @@ class SectionType { static const Puzzle = SectionType._(8); static const Agenda = SectionType._(9); static const Weather = SectionType._(10); + static const Event = SectionType._(11); /// List of all possible values in this [enum][SectionType]. static const values = [ @@ -47,7 +48,8 @@ class SectionType { Pdf, Puzzle, Agenda, - Weather + Weather, + Event ]; static SectionType? fromJson(dynamic value) => SectionTypeTypeTransformer().decode(value); @@ -98,6 +100,7 @@ class SectionTypeTypeTransformer { case r'Puzzle': return SectionType.Puzzle; case r'Agenda': return SectionType.Agenda; case r'Weather': return SectionType.Weather; + case r'Event': return SectionType.Event; default: if (!allowNull) { throw ArgumentError('Unknown enum value to decode: $data'); @@ -117,6 +120,7 @@ class SectionTypeTypeTransformer { case 8: return SectionType.Puzzle; case 9: return SectionType.Agenda; case 10: return SectionType.Weather; + case 11: return SectionType.Event; default: if (!allowNull) { throw ArgumentError('Unknown enum value to decode: $data'); diff --git a/manager_api_new/test/application_instance_dto_section_event_dto_test.dart b/manager_api_new/test/application_instance_dto_section_event_dto_test.dart new file mode 100644 index 0000000..a2e81da --- /dev/null +++ b/manager_api_new/test/application_instance_dto_section_event_dto_test.dart @@ -0,0 +1,134 @@ +// +// AUTO-GENERATED FILE, DO NOT MODIFY! +// +// @dart=2.18 + +// ignore_for_file: unused_element, unused_import +// ignore_for_file: always_put_required_named_parameters_first +// ignore_for_file: constant_identifier_names +// ignore_for_file: lines_longer_than_80_chars + +import 'package:manager_api_new/api.dart'; +import 'package:test/test.dart'; + +// tests for ApplicationInstanceDTOSectionEventDTO +void main() { + // final instance = ApplicationInstanceDTOSectionEventDTO(); + + group('test ApplicationInstanceDTOSectionEventDTO', () { + // String id + test('to test the property `id`', () async { + // TODO + }); + + // String label + test('to test the property `label`', () async { + // TODO + }); + + // List title (default value: const []) + test('to test the property `title`', () async { + // TODO + }); + + // List description (default value: const []) + test('to test the property `description`', () async { + // TODO + }); + + // bool isActive + test('to test the property `isActive`', () async { + // TODO + }); + + // String imageId + test('to test the property `imageId`', () async { + // TODO + }); + + // String imageSource + test('to test the property `imageSource`', () async { + // TODO + }); + + // String configurationId + test('to test the property `configurationId`', () async { + // TODO + }); + + // bool isSubSection + test('to test the property `isSubSection`', () async { + // TODO + }); + + // String parentId + test('to test the property `parentId`', () async { + // TODO + }); + + // SectionType type + test('to test the property `type`', () async { + // TODO + }); + + // DateTime dateCreation + test('to test the property `dateCreation`', () async { + // TODO + }); + + // int order + test('to test the property `order`', () async { + // TODO + }); + + // String instanceId + test('to test the property `instanceId`', () async { + // TODO + }); + + // String latitude + test('to test the property `latitude`', () async { + // TODO + }); + + // String longitude + test('to test the property `longitude`', () async { + // TODO + }); + + // int meterZoneGPS + test('to test the property `meterZoneGPS`', () async { + // TODO + }); + + // bool isBeacon + test('to test the property `isBeacon`', () async { + // TODO + }); + + // int beaconId + test('to test the property `beaconId`', () async { + // TODO + }); + + // DateTime startDate + test('to test the property `startDate`', () async { + // TODO + }); + + // DateTime endDate + test('to test the property `endDate`', () async { + // TODO + }); + + // List parcoursIds (default value: const []) + test('to test the property `parcoursIds`', () async { + // TODO + }); + + // List programme (default value: const []) + test('to test the property `programme`', () async { + // TODO + }); + }); +}