Compare commits
No commits in common. "e851929dbc0f3acae6c1537adfbb5eeacadca3d2" and "a54952e5f444f15b2347e0c1c5e93d91f245e9bb" have entirely different histories.
e851929dbc
...
a54952e5f4
@ -34,15 +34,11 @@ lib/
|
|||||||
## Client API généré (manager_api_new/)
|
## Client API généré (manager_api_new/)
|
||||||
**C'est ici que le client est généré.** Il est consommé via dépendance locale par `tablet-app` et `mymuseum-visitapp`.
|
**C'est ici que le client est généré.** Il est consommé via dépendance locale par `tablet-app` et `mymuseum-visitapp`.
|
||||||
|
|
||||||
- **Éditer manuellement** les fichiers de `manager_api_new/` en miroir des changements backend — **ne pas relancer le générateur OpenAPI**, il écraserait des patches locaux déjà accumulés dans ce client.
|
- **Ne pas modifier manuellement** les fichiers dans `manager_api_new/`
|
||||||
|
- Régénérer via OpenAPI generator quand le backend change : `openapi_generator_config.json` à la racine
|
||||||
- 16 classes API : AuthenticationApi, ConfigurationApi, SectionApi, SectionMapApi, SectionEventApi, ResourceApi, DeviceApi, UserApi, StatsApi, AIApi, etc.
|
- 16 classes API : AuthenticationApi, ConfigurationApi, SectionApi, SectionMapApi, SectionEventApi, ResourceApi, DeviceApi, UserApi, StatsApi, AIApi, etc.
|
||||||
- 130+ DTOs générés dans `manager_api_new/lib/model/`
|
- 130+ DTOs générés dans `manager_api_new/lib/model/`
|
||||||
|
|
||||||
## Package layout partagé (myinfomate_layout/)
|
|
||||||
Package Dart pur (pas de dépendance Flutter) contenant `bentoLayout()` — le placement "bento" dense (chaque card occupe colSpan × lignes rowSpan sur une grille à N colonnes, même principe que `grid-auto-flow: dense` en CSS). Utilisé pour l'aperçu live de `app_configuration_link_screen.dart` ET par `mymuseum-visitapp` (même placement, pour que l'aperçu soit fidèle au rendu réel). Côté web (`visitapp-web`), le même rendu est obtenu nativement via CSS Grid (pas de portage JS nécessaire). Tests dans `myinfomate_layout/test/` (fixtures `bento_layout_cases.json`).
|
|
||||||
|
|
||||||
La taille d'une card = deux entiers `gridColSpan` / `gridRowSpan` (1 ou 2), portés par `AppConfigurationLinkDTO` (donc réglables indépendamment par plateforme). Dans l'aperçu, ils se règlent via un sélecteur de forme par ligne (`card_shape_selector.dart`) OU par glisser du coin d'une card (drag 2D) — les deux écrivent le même champ.
|
|
||||||
|
|
||||||
## État central (ManagerAppContext)
|
## État central (ManagerAppContext)
|
||||||
Contient : credentials, accessToken, instanceId, instanceDTO, référence au client API, configuration/section sélectionnée.
|
Contient : credentials, accessToken, instanceId, instanceDTO, référence au client API, configuration/section sélectionnée.
|
||||||
Accès via `context.read<AppContext>()` ou `context.watch<AppContext>()`.
|
Accès via `context.read<AppContext>()` ou `context.watch<AppContext>()`.
|
||||||
|
|||||||
@ -1,69 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:manager_app/constants.dart';
|
|
||||||
|
|
||||||
class CardShape {
|
|
||||||
final int col;
|
|
||||||
final int row;
|
|
||||||
const CardShape(this.col, this.row);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Les 4 formes proposées pour une card dans la grille bento.
|
|
||||||
const List<CardShape> kCardShapes = [
|
|
||||||
CardShape(1, 1), // standard
|
|
||||||
CardShape(2, 1), // large
|
|
||||||
CardShape(1, 2), // haute
|
|
||||||
CardShape(2, 2), // grande vedette
|
|
||||||
];
|
|
||||||
|
|
||||||
/// Sélecteur de forme compact — raccourci équivalent au drag de coin dans
|
|
||||||
/// l'aperçu (les deux écrivent gridColSpan/gridRowSpan sur le même lien).
|
|
||||||
class CardShapeSelector extends StatelessWidget {
|
|
||||||
final int colSpan;
|
|
||||||
final int rowSpan;
|
|
||||||
final void Function(int col, int row) onChanged;
|
|
||||||
|
|
||||||
const CardShapeSelector({
|
|
||||||
super.key,
|
|
||||||
required this.colSpan,
|
|
||||||
required this.rowSpan,
|
|
||||||
required this.onChanged,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Container(
|
|
||||||
padding: const EdgeInsets.all(3),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: kSecond.withValues(alpha: 0.4),
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: kCardShapes.map((shape) {
|
|
||||||
final isSelected = shape.col == colSpan && shape.row == rowSpan;
|
|
||||||
return GestureDetector(
|
|
||||||
onTap: () => onChanged(shape.col, shape.row),
|
|
||||||
child: Container(
|
|
||||||
width: 26,
|
|
||||||
height: 26,
|
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 2),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: isSelected ? kPrimaryColor : Colors.transparent,
|
|
||||||
borderRadius: BorderRadius.circular(6),
|
|
||||||
),
|
|
||||||
child: Container(
|
|
||||||
width: shape.col == 2 ? 16 : 8,
|
|
||||||
height: shape.row == 2 ? 16 : 8,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: isSelected ? kWhite : kBodyTextColor,
|
|
||||||
borderRadius: BorderRadius.circular(2),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -7,7 +7,6 @@ class CheckInputContainer extends StatefulWidget {
|
|||||||
final bool? isChecked;
|
final bool? isChecked;
|
||||||
final IconData? icon;
|
final IconData? icon;
|
||||||
final String label;
|
final String label;
|
||||||
final String? subtitle;
|
|
||||||
final ValueChanged<bool> onChanged;
|
final ValueChanged<bool> onChanged;
|
||||||
final double fontSize;
|
final double fontSize;
|
||||||
const CheckInputContainer({
|
const CheckInputContainer({
|
||||||
@ -15,7 +14,6 @@ class CheckInputContainer extends StatefulWidget {
|
|||||||
this.isChecked,
|
this.isChecked,
|
||||||
this.icon,
|
this.icon,
|
||||||
required this.label,
|
required this.label,
|
||||||
this.subtitle,
|
|
||||||
required this.onChanged,
|
required this.onChanged,
|
||||||
this.fontSize = 18
|
this.fontSize = 18
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@ -53,23 +51,9 @@ class _CheckInputContainerState extends State<CheckInputContainer> {
|
|||||||
size: 25.0,
|
size: 25.0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Column(
|
Text(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
widget.label,
|
||||||
mainAxisSize: MainAxisSize.min,
|
style: new TextStyle(fontSize: widget.fontSize, fontWeight: FontWeight.w300)
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
widget.label,
|
|
||||||
style: new TextStyle(fontSize: widget.fontSize, fontWeight: FontWeight.w300)
|
|
||||||
),
|
|
||||||
if (widget.subtitle != null)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 2),
|
|
||||||
child: Text(
|
|
||||||
widget.subtitle!,
|
|
||||||
style: TextStyle(fontSize: 12, color: Colors.grey[600]),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@ -65,7 +65,7 @@ class _MultiSelectDropdownLanguageContainerState
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 8, width: 10),
|
const SizedBox(height: 8, width: 10),
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 35),
|
||||||
/*decoration: BoxDecoration(
|
/*decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
border: Border.all(color: Colors.grey.shade400, width: 1.2),
|
border: Border.all(color: Colors.grey.shade400, width: 1.2),
|
||||||
|
|||||||
@ -36,26 +36,24 @@ class MultiStringInputAndResourceContainer extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final appContext = Provider.of<AppContext>(context);
|
final appContext = Provider.of<AppContext>(context);
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
ManagerAppContext managerAppContext = appContext.getContext();
|
||||||
|
Size size = MediaQuery.of(context).size;
|
||||||
return Container(
|
return Container(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
ConstrainedBox(
|
Align(
|
||||||
constraints: BoxConstraints(maxWidth: 150),
|
alignment: AlignmentDirectional.centerStart,
|
||||||
child: Align(
|
child: AutoSizeText(
|
||||||
alignment: AlignmentDirectional.centerStart,
|
label,
|
||||||
child: AutoSizeText(
|
style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.w300),
|
||||||
label,
|
maxLines: 2,
|
||||||
style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.w300),
|
maxFontSize: fontSize,
|
||||||
maxLines: 2,
|
textAlign: TextAlign.center,
|
||||||
maxFontSize: fontSize,
|
)
|
||||||
textAlign: TextAlign.center,
|
|
||||||
)
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(10.0),
|
padding: const EdgeInsets.all(10.0),
|
||||||
child: ConstrainedBox(
|
child: Container(
|
||||||
constraints: BoxConstraints(maxWidth: 140),
|
width: size.width *0.15,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
List<TranslationAndResourceDTO> newValues = <TranslationAndResourceDTO>[];
|
List<TranslationAndResourceDTO> newValues = <TranslationAndResourceDTO>[];
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:html/parser.dart' as html_parser;
|
|
||||||
import 'package:manager_api_new/api.dart';
|
import 'package:manager_api_new/api.dart';
|
||||||
import 'package:manager_app/Components/multi_input_modal.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/Components/multi_string_input_html_modal.dart';
|
||||||
@ -22,7 +21,6 @@ class MultiStringInputContainer extends StatelessWidget {
|
|||||||
final bool isHTML;
|
final bool isHTML;
|
||||||
final double fontSize;
|
final double fontSize;
|
||||||
final bool isMandatory;
|
final bool isMandatory;
|
||||||
final bool showPreview;
|
|
||||||
|
|
||||||
const MultiStringInputContainer({
|
const MultiStringInputContainer({
|
||||||
Key? key,
|
Key? key,
|
||||||
@ -37,20 +35,8 @@ class MultiStringInputContainer extends StatelessWidget {
|
|||||||
this.isHTML = false,
|
this.isHTML = false,
|
||||||
this.fontSize = 18,
|
this.fontSize = 18,
|
||||||
this.isMandatory = true,
|
this.isMandatory = true,
|
||||||
this.showPreview = false,
|
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
String _plainTextPreview(String htmlOrText) {
|
|
||||||
if (htmlOrText.trim().isEmpty) return "";
|
|
||||||
try {
|
|
||||||
final doc = html_parser.parse(htmlOrText);
|
|
||||||
final text = (doc.body?.text ?? htmlOrText).trim();
|
|
||||||
return text.isEmpty ? htmlOrText.trim() : text;
|
|
||||||
} catch (_) {
|
|
||||||
return htmlOrText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final appContext = Provider.of<AppContext>(context);
|
final appContext = Provider.of<AppContext>(context);
|
||||||
@ -120,74 +106,23 @@ class MultiStringInputContainer extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: showPreview
|
child: Container(
|
||||||
? Builder(builder: (context) {
|
height: 50,
|
||||||
final languages = managerAppContext.selectedConfiguration!.languages!;
|
width: 180,
|
||||||
final completed = initialValue
|
decoration: BoxDecoration(
|
||||||
.where((t) => (t.value ?? "").trim().isNotEmpty)
|
color: color,
|
||||||
.length;
|
borderRadius: BorderRadius.circular(50),
|
||||||
final currentTranslation = initialValue.isNotEmpty
|
),
|
||||||
? (initialValue.firstWhere(
|
alignment: Alignment.center,
|
||||||
(t) => t.language == 'FR',
|
child: Text(
|
||||||
orElse: () => initialValue.first)
|
resourceTypes == null ? "Changer traductions" : "Changer ressources",
|
||||||
.value ??
|
style: const TextStyle(
|
||||||
"")
|
color: kWhite,
|
||||||
: "";
|
fontWeight: FontWeight.w400,
|
||||||
final preview = _plainTextPreview(currentTranslation);
|
fontSize: 16,
|
||||||
return Container(
|
),
|
||||||
height: 54,
|
),
|
||||||
width: 200,
|
),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: color,
|
|
||||||
borderRadius: BorderRadius.circular(50),
|
|
||||||
),
|
|
||||||
alignment: Alignment.centerLeft,
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
preview.isEmpty ? "Aucun texte —" : preview,
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: TextStyle(
|
|
||||||
color: kWhite,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
fontSize: 13,
|
|
||||||
fontStyle: preview.isEmpty ? FontStyle.italic : FontStyle.normal,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 2),
|
|
||||||
Text(
|
|
||||||
"$completed / ${languages.length} langues traduites",
|
|
||||||
style: const TextStyle(
|
|
||||||
color: kWhite,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
fontSize: 11,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
})
|
|
||||||
: Container(
|
|
||||||
height: 50,
|
|
||||||
width: 180,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: color,
|
|
||||||
borderRadius: BorderRadius.circular(50),
|
|
||||||
),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: Text(
|
|
||||||
resourceTypes == null ? "Changer traductions" : "Changer ressources",
|
|
||||||
style: const TextStyle(
|
|
||||||
color: kWhite,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -1,73 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import '../constants.dart';
|
|
||||||
|
|
||||||
class NumberStepperField extends StatelessWidget {
|
|
||||||
final String label;
|
|
||||||
final num? value;
|
|
||||||
final num min;
|
|
||||||
final num max;
|
|
||||||
final num step;
|
|
||||||
final String? unit;
|
|
||||||
final ValueChanged<num> onChanged;
|
|
||||||
|
|
||||||
const NumberStepperField({
|
|
||||||
Key? key,
|
|
||||||
required this.label,
|
|
||||||
required this.value,
|
|
||||||
this.min = 0,
|
|
||||||
this.max = 999999,
|
|
||||||
this.step = 1,
|
|
||||||
this.unit,
|
|
||||||
required this.onChanged,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
num get _current => (value ?? min).clamp(min, max);
|
|
||||||
|
|
||||||
String _format(num n) => n.truncateToDouble() == n ? n.toInt().toString() : n.toString();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final current = _current;
|
|
||||||
return Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Text(label, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500)),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border.all(color: kSecond),
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.remove_circle_outline),
|
|
||||||
color: current <= min ? Colors.grey[400] : kPrimaryColor,
|
|
||||||
onPressed: current <= min
|
|
||||||
? null
|
|
||||||
: () => onChanged((current - step).clamp(min, max)),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: 56,
|
|
||||||
child: Text(
|
|
||||||
unit != null ? "${_format(current)} $unit" : _format(current),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.add_circle_outline),
|
|
||||||
color: current >= max ? Colors.grey[400] : kPrimaryColor,
|
|
||||||
onPressed: current >= max
|
|
||||||
? null
|
|
||||||
: () => onChanged((current + step).clamp(min, max)),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -34,18 +34,19 @@ class _PDFFileInputContainerState extends State<PDFFileInputContainer> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
Size size = MediaQuery.of(context).size;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Align(
|
||||||
child: Align(
|
alignment: AlignmentDirectional.centerStart,
|
||||||
alignment: AlignmentDirectional.centerStart,
|
child: Text(widget.label, style: TextStyle(fontSize: widget.fontSize, fontWeight: FontWeight.w300))
|
||||||
child: Text(widget.label, style: TextStyle(fontSize: widget.fontSize, fontWeight: FontWeight.w300), overflow: TextOverflow.ellipsis)
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Container(
|
child: Container(
|
||||||
|
width: size.width *0.16,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
List<OrderedTranslationAndResourceDTO> newValues = <OrderedTranslationAndResourceDTO>[];
|
List<OrderedTranslationAndResourceDTO> newValues = <OrderedTranslationAndResourceDTO>[];
|
||||||
|
|||||||
@ -60,7 +60,7 @@ class _ReorderableCustomListState<T> extends State<ReorderableCustomList<T>> {
|
|||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final item = itemsMiddle[index];
|
final item = itemsMiddle[index];
|
||||||
return Container(
|
return Container(
|
||||||
key: ValueKey(identityHashCode(item)),
|
key: ValueKey(item),
|
||||||
margin: const EdgeInsets.symmetric(vertical: 4),
|
margin: const EdgeInsets.symmetric(vertical: 4),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
|
|||||||
@ -1,70 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
import '../constants.dart';
|
|
||||||
|
|
||||||
class SectionCard extends StatelessWidget {
|
|
||||||
final IconData icon;
|
|
||||||
final String title;
|
|
||||||
final String? subtitle;
|
|
||||||
final Widget child;
|
|
||||||
final EdgeInsetsGeometry padding;
|
|
||||||
|
|
||||||
const SectionCard({
|
|
||||||
Key? key,
|
|
||||||
required this.icon,
|
|
||||||
required this.title,
|
|
||||||
this.subtitle,
|
|
||||||
required this.child,
|
|
||||||
this.padding = const EdgeInsets.all(16),
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border.all(color: kSecond),
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
),
|
|
||||||
padding: padding,
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Icon(icon, color: kPrimaryColor, size: 22),
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
title,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
fontSize: 15,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (subtitle != null)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 2),
|
|
||||||
child: Text(
|
|
||||||
subtitle!,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: Colors.grey[600],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
child,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,243 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:manager_api_new/api.dart';
|
|
||||||
import 'package:manager_app/constants.dart';
|
|
||||||
import 'package:myinfomate_layout/myinfomate_layout.dart';
|
|
||||||
|
|
||||||
const double _kGap = 8;
|
|
||||||
|
|
||||||
/// Aperçu live de la grille bento (même placement dense que web/mobile en prod).
|
|
||||||
/// Glisser le coin d'une card change ses spans (colonnes × lignes) ; le résultat
|
|
||||||
/// snappe sur des cellules entières. [onSpanChanged] doit rester synchronisé avec
|
|
||||||
/// le même état que le sélecteur de forme de la liste.
|
|
||||||
/// Glisser la poignée (coin haut-gauche) d'une card sur une autre échange leur
|
|
||||||
/// position dans la liste — le dense packing recalcule le reste automatiquement.
|
|
||||||
class BentoPreviewGrid extends StatelessWidget {
|
|
||||||
final List<AppConfigurationLinkDTO> links;
|
|
||||||
final int columns;
|
|
||||||
final void Function(AppConfigurationLinkDTO link, int colSpan, int rowSpan) onSpanChanged;
|
|
||||||
final void Function(String fromId, String toId) onSwap;
|
|
||||||
|
|
||||||
const BentoPreviewGrid({
|
|
||||||
super.key,
|
|
||||||
required this.links,
|
|
||||||
required this.columns,
|
|
||||||
required this.onSpanChanged,
|
|
||||||
required this.onSwap,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return LayoutBuilder(builder: (context, constraints) {
|
|
||||||
final width = constraints.maxWidth;
|
|
||||||
// Seuls les blocs actifs apparaissent réellement dans l'app — sinon le
|
|
||||||
// switch "actif/inactif" de la liste n'aurait aucun effet sur l'aperçu.
|
|
||||||
final activeLinks = links.where((l) => l.isActive == true).toList();
|
|
||||||
if (width <= 0 || activeLinks.isEmpty) return const SizedBox();
|
|
||||||
|
|
||||||
final cols = columns < 1 ? 1 : columns;
|
|
||||||
final maxSpan = cols < 2 ? 1 : 2;
|
|
||||||
final cellWidth = (width - (cols - 1) * _kGap) / cols;
|
|
||||||
final cellHeight = cellWidth * 0.78;
|
|
||||||
|
|
||||||
// Trié par `order` plutôt que par l'ordre du tableau reçu : la liste de
|
|
||||||
// gauche (ReorderableCustomList) travaille sur sa propre copie interne et
|
|
||||||
// ne réordonne que les DTO (leur champ `order`), jamais le tableau `links`
|
|
||||||
// lui-même — sans ce tri, l'aperçu ignorerait le reorder de la liste.
|
|
||||||
final orderedLinks = [...activeLinks]..sort((a, b) => (a.order ?? 0).compareTo(b.order ?? 0));
|
|
||||||
|
|
||||||
final result = bentoLayout(
|
|
||||||
orderedLinks
|
|
||||||
.map((l) => BentoItem(
|
|
||||||
id: l.id!,
|
|
||||||
colSpan: (l.gridColSpan ?? 1).clamp(1, maxSpan),
|
|
||||||
rowSpan: (l.gridRowSpan ?? 1).clamp(1, 2),
|
|
||||||
))
|
|
||||||
.toList(),
|
|
||||||
cols,
|
|
||||||
);
|
|
||||||
|
|
||||||
final totalHeight =
|
|
||||||
result.rowCount * cellHeight + (result.rowCount - 1) * _kGap;
|
|
||||||
final byId = {for (final l in activeLinks) l.id!: l};
|
|
||||||
|
|
||||||
return SizedBox(
|
|
||||||
width: width,
|
|
||||||
height: totalHeight < 0 ? 0 : totalHeight,
|
|
||||||
child: Stack(
|
|
||||||
children: result.placements.map((p) {
|
|
||||||
final link = byId[p.id]!;
|
|
||||||
return Positioned(
|
|
||||||
left: p.col * (cellWidth + _kGap),
|
|
||||||
top: p.row * (cellHeight + _kGap),
|
|
||||||
width: p.colSpan * cellWidth + (p.colSpan - 1) * _kGap,
|
|
||||||
height: p.rowSpan * cellHeight + (p.rowSpan - 1) * _kGap,
|
|
||||||
child: DragTarget<String>(
|
|
||||||
onWillAcceptWithDetails: (details) => details.data != link.id,
|
|
||||||
onAcceptWithDetails: (details) => onSwap(details.data, link.id!),
|
|
||||||
builder: (context, candidateData, rejectedData) {
|
|
||||||
return _BentoCard(
|
|
||||||
link: link,
|
|
||||||
cellWidth: cellWidth,
|
|
||||||
cellHeight: cellHeight,
|
|
||||||
maxSpan: maxSpan,
|
|
||||||
isDropTarget: candidateData.isNotEmpty,
|
|
||||||
onSpanChanged: (c, r) => onSpanChanged(link, c, r),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _BentoCard extends StatefulWidget {
|
|
||||||
final AppConfigurationLinkDTO link;
|
|
||||||
final double cellWidth;
|
|
||||||
final double cellHeight;
|
|
||||||
final int maxSpan;
|
|
||||||
final bool isDropTarget;
|
|
||||||
final void Function(int colSpan, int rowSpan) onSpanChanged;
|
|
||||||
|
|
||||||
const _BentoCard({
|
|
||||||
required this.link,
|
|
||||||
required this.cellWidth,
|
|
||||||
required this.cellHeight,
|
|
||||||
required this.maxSpan,
|
|
||||||
required this.isDropTarget,
|
|
||||||
required this.onSpanChanged,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<_BentoCard> createState() => _BentoCardState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _BentoCardState extends State<_BentoCard> {
|
|
||||||
double _accDx = 0;
|
|
||||||
double _accDy = 0;
|
|
||||||
int _startCol = 1;
|
|
||||||
int _startRow = 1;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final link = widget.link;
|
|
||||||
final hasImage = link.configuration?.imageSource != null;
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: hasImage ? null : kPrimaryColor.withValues(alpha: 0.55),
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
image: hasImage
|
|
||||||
? DecorationImage(image: NetworkImage(link.configuration!.imageSource!), fit: BoxFit.cover)
|
|
||||||
: null,
|
|
||||||
border: widget.isDropTarget ? Border.all(color: kPrimaryColor, width: 3) : null,
|
|
||||||
),
|
|
||||||
child: Stack(
|
|
||||||
children: [
|
|
||||||
Positioned.fill(
|
|
||||||
child: DecoratedBox(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
gradient: LinearGradient(
|
|
||||||
begin: Alignment.topCenter,
|
|
||||||
end: Alignment.bottomCenter,
|
|
||||||
colors: [Colors.transparent, Colors.black.withValues(alpha: 0.7)],
|
|
||||||
stops: const [0.4, 1.0],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Positioned(
|
|
||||||
bottom: 6,
|
|
||||||
left: 8,
|
|
||||||
right: 8,
|
|
||||||
child: Text(
|
|
||||||
link.configuration?.label ?? '',
|
|
||||||
maxLines: 2,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: const TextStyle(color: Colors.white, fontSize: 11, fontWeight: FontWeight.w600),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// Poignée de déplacement — glisser sur une autre card échange leur position.
|
|
||||||
// Coin opposé à la poignée de resize pour éviter tout conflit de geste.
|
|
||||||
Positioned(
|
|
||||||
left: 0,
|
|
||||||
top: 0,
|
|
||||||
child: Draggable<String>(
|
|
||||||
data: link.id,
|
|
||||||
feedback: Material(
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: Opacity(
|
|
||||||
opacity: 0.85,
|
|
||||||
child: SizedBox(
|
|
||||||
width: widget.cellWidth,
|
|
||||||
height: widget.cellHeight,
|
|
||||||
child: _dragHandle(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: _dragHandle(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// Poignée de coin — drag 2D : largeur = colonnes, hauteur = lignes.
|
|
||||||
Positioned(
|
|
||||||
right: 0,
|
|
||||||
bottom: 0,
|
|
||||||
child: MouseRegion(
|
|
||||||
cursor: SystemMouseCursors.resizeDownRight,
|
|
||||||
child: GestureDetector(
|
|
||||||
onPanStart: (_) {
|
|
||||||
_accDx = 0;
|
|
||||||
_accDy = 0;
|
|
||||||
_startCol = (link.gridColSpan ?? 1).clamp(1, widget.maxSpan);
|
|
||||||
_startRow = (link.gridRowSpan ?? 1).clamp(1, 2);
|
|
||||||
},
|
|
||||||
onPanUpdate: (details) {
|
|
||||||
_accDx += details.delta.dx;
|
|
||||||
_accDy += details.delta.dy;
|
|
||||||
final newCol = (_startCol + (_accDx / (widget.cellWidth + _kGap)).round())
|
|
||||||
.clamp(1, widget.maxSpan);
|
|
||||||
final newRow = (_startRow + (_accDy / (widget.cellHeight + _kGap)).round())
|
|
||||||
.clamp(1, 2);
|
|
||||||
if (newCol != (link.gridColSpan ?? 1) || newRow != (link.gridRowSpan ?? 1)) {
|
|
||||||
widget.onSpanChanged(newCol, newRow);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
width: 20,
|
|
||||||
height: 20,
|
|
||||||
margin: const EdgeInsets.all(3),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: kWhite,
|
|
||||||
borderRadius: BorderRadius.circular(5),
|
|
||||||
border: Border.all(color: kPrimaryColor, width: 2),
|
|
||||||
),
|
|
||||||
child: Icon(Icons.open_in_full, size: 11, color: kPrimaryColor),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _dragHandle() {
|
|
||||||
return MouseRegion(
|
|
||||||
cursor: SystemMouseCursors.grab,
|
|
||||||
child: Container(
|
|
||||||
width: 20,
|
|
||||||
height: 20,
|
|
||||||
margin: const EdgeInsets.all(3),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: kWhite,
|
|
||||||
borderRadius: BorderRadius.circular(5),
|
|
||||||
border: Border.all(color: kPrimaryColor, width: 2),
|
|
||||||
),
|
|
||||||
child: Icon(Icons.drag_indicator, size: 11, color: kPrimaryColor),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
/// Cadre navigateur — pendant de [PhoneMockup] pour l'aperçu de l'onglet Web.
|
|
||||||
/// [width]/[height] sont imposés par l'appelant (espace réellement disponible
|
|
||||||
/// dans le panneau d'aperçu), [width] permettant en plus de simuler une largeur
|
|
||||||
/// de viewport donnée (desktop vs mobile web) — visitapp-web est un site
|
|
||||||
/// responsive, pas une app figée à une taille.
|
|
||||||
class BrowserFrame extends StatelessWidget {
|
|
||||||
final Widget child;
|
|
||||||
final double width;
|
|
||||||
final double height;
|
|
||||||
|
|
||||||
const BrowserFrame({super.key, required this.child, required this.width, required this.height});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Container(
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.black,
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
border: Border.all(color: Colors.black, width: 6),
|
|
||||||
),
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
height: 28,
|
|
||||||
color: const Color(0xFFE8EAED),
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
|
||||||
child: Row(
|
|
||||||
children: const [
|
|
||||||
_Dot(color: Color(0xFFFF5F57)),
|
|
||||||
SizedBox(width: 6),
|
|
||||||
_Dot(color: Color(0xFFFEBC2E)),
|
|
||||||
SizedBox(width: 6),
|
|
||||||
_Dot(color: Color(0xFF28C840)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(child: Container(color: Colors.white, child: child)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _Dot extends StatelessWidget {
|
|
||||||
final Color color;
|
|
||||||
const _Dot({required this.color});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Container(
|
|
||||||
width: 10,
|
|
||||||
height: 10,
|
|
||||||
decoration: BoxDecoration(color: color, shape: BoxShape.circle),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,20 +1,17 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
/// [width]/[height] sont imposés par l'appelant (espace réellement disponible
|
|
||||||
/// dans le panneau d'aperçu) plutôt que dérivés de tout l'écran, pour que le
|
|
||||||
/// cadre entier reste visible sans avoir à scroller pour le voir en entier.
|
|
||||||
class PhoneMockup extends StatelessWidget {
|
class PhoneMockup extends StatelessWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
final double width;
|
|
||||||
final double height;
|
|
||||||
|
|
||||||
const PhoneMockup({super.key, required this.child, required this.width, required this.height});
|
const PhoneMockup({super.key, required this.child});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
Size size = MediaQuery.of(context).size;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
width: width,
|
width: size.width * 0.4,
|
||||||
height: height,
|
height: size.height * 0.6,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.black,
|
color: Colors.black,
|
||||||
borderRadius: BorderRadius.circular(40),
|
borderRadius: BorderRadius.circular(40),
|
||||||
@ -35,8 +32,8 @@ class PhoneMockup extends StatelessWidget {
|
|||||||
// Notch
|
// Notch
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 8,
|
top: 8,
|
||||||
left:(width * 0.35) / 2,
|
left:(size.width * 0.35) / 2,
|
||||||
right: (width * 0.35) / 2,
|
right: (size.width * 0.35) / 2,
|
||||||
child: Container(
|
child: Container(
|
||||||
height: 20,
|
height: 20,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
|
|||||||
@ -52,6 +52,7 @@ class _WebInstanceLoaderState extends State<WebInstanceLoader> {
|
|||||||
instanceId: instanceDTO.id,
|
instanceId: instanceDTO.id,
|
||||||
appType: AppType.Web,
|
appType: AppType.Web,
|
||||||
languages: ['fr'],
|
languages: ['fr'],
|
||||||
|
layoutMainPage: LayoutMainPageType.MasonryGrid,
|
||||||
isAssistant: false,
|
isAssistant: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -118,7 +119,7 @@ class WebAppScreen extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
if (instanceDTO?.webSlug != null || instanceDTO?.publicApiKey != null)
|
if (instanceDTO?.webSlug != null || instanceDTO?.publicApiKey != null)
|
||||||
Card(
|
Card(
|
||||||
margin: const EdgeInsets.fromLTRB(16, 8, 16, 8),
|
margin: const EdgeInsets.fromLTRB(0, 0, 0, 8),
|
||||||
color: kWhite,
|
color: kWhite,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@ -128,23 +129,14 @@ class WebAppScreen extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text('Accès web', style: TextStyle(fontWeight: FontWeight.w500, fontSize: 21)),
|
Text('Accès web', style: TextStyle(fontWeight: FontWeight.w500, fontSize: 21)),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Row(
|
_InfoRow(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
label: 'URL visiteurs',
|
||||||
children: [
|
value: 'app.myinfomate.be/${instanceDTO?.webSlug ?? '—'}',
|
||||||
Expanded(
|
),
|
||||||
child: _InfoRow(
|
const SizedBox(height: 8),
|
||||||
label: 'URL visiteurs',
|
_InfoRow(
|
||||||
value: 'app.myinfomate.be/${instanceDTO?.webSlug ?? '—'}',
|
label: 'Clé publique API',
|
||||||
),
|
value: instanceDTO?.publicApiKey ?? '—',
|
||||||
),
|
|
||||||
const SizedBox(width: 24),
|
|
||||||
Expanded(
|
|
||||||
child: _InfoRow(
|
|
||||||
label: 'Clé publique API',
|
|
||||||
value: instanceDTO?.publicApiKey ?? '—',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,13 +1,10 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
|
||||||
import 'package:manager_api_new/api.dart';
|
import 'package:manager_api_new/api.dart';
|
||||||
import 'package:manager_app/constants.dart';
|
import 'package:manager_app/constants.dart';
|
||||||
import 'package:manager_app/Components/check_input_container.dart';
|
import 'package:manager_app/Components/check_input_container.dart';
|
||||||
import 'package:manager_app/Components/multi_string_input_container.dart';
|
import 'package:manager_app/Components/multi_string_input_container.dart';
|
||||||
import 'package:manager_app/Components/single_select_container.dart';
|
import 'package:manager_app/Components/single_select_container.dart';
|
||||||
import 'package:manager_app/Components/string_input_container.dart';
|
|
||||||
import 'package:manager_app/Components/message_notification.dart';
|
import 'package:manager_app/Components/message_notification.dart';
|
||||||
import 'package:manager_app/Components/confirmation_dialog.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:manager_app/app_context.dart';
|
import 'package:manager_app/app_context.dart';
|
||||||
import 'package:manager_app/l10n/app_localizations.dart';
|
import 'package:manager_app/l10n/app_localizations.dart';
|
||||||
@ -15,8 +12,6 @@ import 'package:manager_app/Models/managerContext.dart';
|
|||||||
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
||||||
import 'showNewOrUpdateEventAgenda.dart';
|
import 'showNewOrUpdateEventAgenda.dart';
|
||||||
|
|
||||||
enum _AgendaDateFilter { all, thisMonth, thisYear, past }
|
|
||||||
|
|
||||||
class AgendaConfig extends StatefulWidget {
|
class AgendaConfig extends StatefulWidget {
|
||||||
final String? color;
|
final String? color;
|
||||||
final String? label;
|
final String? label;
|
||||||
@ -38,94 +33,6 @@ class AgendaConfig extends StatefulWidget {
|
|||||||
class _AgendaConfigState extends State<AgendaConfig> {
|
class _AgendaConfigState extends State<AgendaConfig> {
|
||||||
late AgendaDTO agendaDTO;
|
late AgendaDTO agendaDTO;
|
||||||
List<EventAgendaDTO> events = [];
|
List<EventAgendaDTO> events = [];
|
||||||
String _searchFilter = '';
|
|
||||||
_AgendaDateFilter _dateFilter = _AgendaDateFilter.all;
|
|
||||||
|
|
||||||
List<EventAgendaDTO> get _filteredEvents {
|
|
||||||
final now = DateTime.now();
|
|
||||||
var filtered = events.where((event) {
|
|
||||||
switch (_dateFilter) {
|
|
||||||
case _AgendaDateFilter.thisMonth:
|
|
||||||
return event.dateFrom != null &&
|
|
||||||
event.dateFrom!.year == now.year &&
|
|
||||||
event.dateFrom!.month == now.month;
|
|
||||||
case _AgendaDateFilter.thisYear:
|
|
||||||
return event.dateFrom != null && event.dateFrom!.year == now.year;
|
|
||||||
case _AgendaDateFilter.past:
|
|
||||||
return event.dateFrom != null && event.dateFrom!.isBefore(now);
|
|
||||||
case _AgendaDateFilter.all:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
if (_searchFilter.isNotEmpty) {
|
|
||||||
filtered = filtered.where((event) {
|
|
||||||
final label = _labelFor(event);
|
|
||||||
return label.toLowerCase().contains(_searchFilter.toLowerCase());
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
filtered.sort((a, b) {
|
|
||||||
if (a.dateFrom == null && b.dateFrom == null) return 0;
|
|
||||||
if (a.dateFrom == null) return 1;
|
|
||||||
if (b.dateFrom == null) return -1;
|
|
||||||
return a.dateFrom!.compareTo(b.dateFrom!);
|
|
||||||
});
|
|
||||||
|
|
||||||
return filtered;
|
|
||||||
}
|
|
||||||
|
|
||||||
String _labelFor(EventAgendaDTO event) {
|
|
||||||
if (event.label != null && event.label!.isNotEmpty) {
|
|
||||||
return (event.label!.firstWhere((t) => t.language == 'FR',
|
|
||||||
orElse: () => event.label![0]))
|
|
||||||
.value ??
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Groups events synced from the same external agenda that share the same
|
|
||||||
/// address and dates: the sync creates one EventAgendaDTO per language
|
|
||||||
/// instead of one multilingual event, so this recombines them for display.
|
|
||||||
String? _syncGroupKey(EventAgendaDTO event) {
|
|
||||||
if (event.isSynced != true) return null;
|
|
||||||
final dates =
|
|
||||||
"${event.dateFrom?.toIso8601String()}|${event.dateTo?.toIso8601String()}";
|
|
||||||
final address = event.address?.address?.trim();
|
|
||||||
if (address != null && address.isNotEmpty) {
|
|
||||||
return "addr:$address|$dates";
|
|
||||||
}
|
|
||||||
// No address to match on (common for these synced events): fall back to
|
|
||||||
// an identical title, which only happens when the source repeats the
|
|
||||||
// same untranslated name per language pass.
|
|
||||||
final label = _labelFor(event).trim();
|
|
||||||
if (label.isNotEmpty) {
|
|
||||||
return "label:$label|$dates";
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<List<EventAgendaDTO>> get _displayGroups {
|
|
||||||
final groups = <List<EventAgendaDTO>>[];
|
|
||||||
final groupByKey = <String, List<EventAgendaDTO>>{};
|
|
||||||
for (final event in _filteredEvents) {
|
|
||||||
final key = _syncGroupKey(event);
|
|
||||||
if (key == null) {
|
|
||||||
groups.add([event]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final existing = groupByKey[key];
|
|
||||||
if (existing != null) {
|
|
||||||
existing.add(event);
|
|
||||||
} else {
|
|
||||||
final group = [event];
|
|
||||||
groupByKey[key] = group;
|
|
||||||
groups.add(group);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return groups;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -235,39 +142,6 @@ class _AgendaConfigState extends State<AgendaConfig> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
width: 280,
|
|
||||||
child: StringInputContainer(
|
|
||||||
label: AppLocalizations.of(context)!.searchLabel,
|
|
||||||
onChanged: (v) => setState(() => _searchFilter = v),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Wrap(
|
|
||||||
spacing: 8,
|
|
||||||
children: [
|
|
||||||
_buildDateFilterChip(
|
|
||||||
_AgendaDateFilter.all,
|
|
||||||
AppLocalizations.of(context)!.agendaFilterAll),
|
|
||||||
_buildDateFilterChip(
|
|
||||||
_AgendaDateFilter.thisMonth,
|
|
||||||
AppLocalizations.of(context)!.agendaFilterThisMonth),
|
|
||||||
_buildDateFilterChip(
|
|
||||||
_AgendaDateFilter.thisYear,
|
|
||||||
AppLocalizations.of(context)!.agendaFilterThisYear),
|
|
||||||
_buildDateFilterChip(
|
|
||||||
_AgendaDateFilter.past,
|
|
||||||
AppLocalizations.of(context)!.agendaFilterPast),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
Container(
|
||||||
height: 600,
|
height: 600,
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
@ -275,164 +149,116 @@ class _AgendaConfigState extends State<AgendaConfig> {
|
|||||||
? Center(
|
? Center(
|
||||||
child: Text(AppLocalizations.of(context)!.noEvents,
|
child: Text(AppLocalizations.of(context)!.noEvents,
|
||||||
style: TextStyle(fontStyle: FontStyle.italic)))
|
style: TextStyle(fontStyle: FontStyle.italic)))
|
||||||
: Builder(builder: (context) {
|
: ListView.builder(
|
||||||
final groups = _displayGroups;
|
itemCount: events.length,
|
||||||
return ListView.builder(
|
itemBuilder: (context, index) {
|
||||||
itemCount: groups.length,
|
final event = events[index];
|
||||||
itemBuilder: (context, index) {
|
return Card(
|
||||||
final group = groups[index];
|
elevation: 2,
|
||||||
final primary = group.firstWhere(
|
margin: const EdgeInsets.symmetric(
|
||||||
(e) => e.label?.any((t) => t.language == 'FR') ??
|
horizontal: 16, vertical: 6),
|
||||||
false,
|
shape: RoundedRectangleBorder(
|
||||||
orElse: () => group.first);
|
borderRadius: BorderRadius.circular(12)),
|
||||||
return Card(
|
child: ListTile(
|
||||||
elevation: 2,
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
margin: const EdgeInsets.symmetric(
|
horizontal: 16, vertical: 8),
|
||||||
horizontal: 16, vertical: 6),
|
leading: CircleAvatar(
|
||||||
shape: RoundedRectangleBorder(
|
backgroundColor: kPrimaryColor.withOpacity(0.1),
|
||||||
borderRadius: BorderRadius.circular(12)),
|
child:
|
||||||
child: ListTile(
|
const Icon(Icons.event, color: kPrimaryColor),
|
||||||
contentPadding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 16, vertical: 8),
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor: kPrimaryColor.withOpacity(0.1),
|
|
||||||
child: const Icon(Icons.event,
|
|
||||||
color: kPrimaryColor),
|
|
||||||
),
|
|
||||||
title: HtmlWidget(
|
|
||||||
(primary.label != null &&
|
|
||||||
primary.label!.isNotEmpty)
|
|
||||||
? (primary.label!.firstWhere(
|
|
||||||
(t) => t.language == 'FR',
|
|
||||||
orElse: () => primary.label![0]))
|
|
||||||
.value ??
|
|
||||||
"${AppLocalizations.of(context)!.agendaEventFallback} $index"
|
|
||||||
: "${AppLocalizations.of(context)!.agendaEventFallback} $index",
|
|
||||||
textStyle:
|
|
||||||
const TextStyle(fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
subtitle: Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 4),
|
|
||||||
child: Text([
|
|
||||||
_formatEventDate(primary),
|
|
||||||
primary.address?.address ??
|
|
||||||
AppLocalizations.of(context)!.noAddress,
|
|
||||||
].where((s) => s.isNotEmpty).join(' • ')),
|
|
||||||
),
|
|
||||||
trailing: group.length > 1
|
|
||||||
? _buildLanguageChips(group)
|
|
||||||
: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.edit,
|
|
||||||
color: kPrimaryColor),
|
|
||||||
onPressed: () =>
|
|
||||||
_editEvent(context, primary),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.delete,
|
|
||||||
color: kError),
|
|
||||||
onPressed: () =>
|
|
||||||
_deleteEvent(context, primary),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
title: HtmlWidget(
|
||||||
},
|
(event.label != null && event.label!.isNotEmpty)
|
||||||
);
|
? (event.label!.firstWhere(
|
||||||
}),
|
(t) => t.language == 'FR',
|
||||||
|
orElse: () => event.label![0])).value ?? "${AppLocalizations.of(context)!.agendaEventFallback} $index"
|
||||||
|
: "${AppLocalizations.of(context)!.agendaEventFallback} $index",
|
||||||
|
textStyle: const TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
subtitle: Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 4),
|
||||||
|
child:
|
||||||
|
Text(event.address?.address ?? AppLocalizations.of(context)!.noAddress),
|
||||||
|
),
|
||||||
|
trailing: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.edit,
|
||||||
|
color: kPrimaryColor),
|
||||||
|
onPressed: () {
|
||||||
|
showNewOrUpdateEventAgenda(
|
||||||
|
context,
|
||||||
|
event,
|
||||||
|
agendaDTO.id ?? "",
|
||||||
|
(updatedEvent) async {
|
||||||
|
try {
|
||||||
|
final result = await _api(context)
|
||||||
|
.sectionAgendaUpdateEventAgenda(
|
||||||
|
updatedEvent);
|
||||||
|
if (result != null && mounted) {
|
||||||
|
setState(
|
||||||
|
() => events[index] = result);
|
||||||
|
showNotification(
|
||||||
|
kSuccess,
|
||||||
|
kWhite,
|
||||||
|
AppLocalizations.of(context)!.agendaEventUpdatedSuccess,
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
showNotification(
|
||||||
|
kError,
|
||||||
|
kWhite,
|
||||||
|
AppLocalizations.of(context)!.agendaEventUpdateError,
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.delete, color: kError),
|
||||||
|
onPressed: () async {
|
||||||
|
try {
|
||||||
|
if (event.id != null) {
|
||||||
|
await _api(context)
|
||||||
|
.sectionAgendaDeleteEventAgenda(
|
||||||
|
event.id!);
|
||||||
|
}
|
||||||
|
if (mounted) {
|
||||||
|
setState(() => events.removeAt(index));
|
||||||
|
showNotification(
|
||||||
|
kSuccess,
|
||||||
|
kWhite,
|
||||||
|
AppLocalizations.of(context)!.agendaEventDeletedSuccess,
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
showNotification(
|
||||||
|
kError,
|
||||||
|
kWhite,
|
||||||
|
AppLocalizations.of(context)!.agendaEventDeleteError,
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _editEvent(BuildContext context, EventAgendaDTO event) {
|
|
||||||
showNewOrUpdateEventAgenda(
|
|
||||||
context,
|
|
||||||
event,
|
|
||||||
agendaDTO.id ?? "",
|
|
||||||
(updatedEvent) async {
|
|
||||||
try {
|
|
||||||
final result =
|
|
||||||
await _api(context).sectionAgendaUpdateEventAgenda(updatedEvent);
|
|
||||||
if (result != null && mounted) {
|
|
||||||
setState(() =>
|
|
||||||
events[events.indexWhere((e) => e.id == event.id)] = result);
|
|
||||||
showNotification(kSuccess, kWhite,
|
|
||||||
AppLocalizations.of(context)!.agendaEventUpdatedSuccess, context, null);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
showNotification(kError, kWhite,
|
|
||||||
AppLocalizations.of(context)!.agendaEventUpdateError, context, null);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _deleteEvent(BuildContext context, EventAgendaDTO event) {
|
|
||||||
showConfirmationDialog(
|
|
||||||
AppLocalizations.of(context)!.agendaEventDeleteConfirm,
|
|
||||||
() {},
|
|
||||||
() async {
|
|
||||||
try {
|
|
||||||
if (event.id != null) {
|
|
||||||
await _api(context).sectionAgendaDeleteEventAgenda(event.id!);
|
|
||||||
}
|
|
||||||
if (mounted) {
|
|
||||||
setState(() => events.removeWhere((e) => e.id == event.id));
|
|
||||||
showNotification(kSuccess, kWhite,
|
|
||||||
AppLocalizations.of(context)!.agendaEventDeletedSuccess, context, null);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
showNotification(kError, kWhite,
|
|
||||||
AppLocalizations.of(context)!.agendaEventDeleteError, context, null);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
context,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildLanguageChips(List<EventAgendaDTO> group) {
|
|
||||||
return Wrap(
|
|
||||||
spacing: 4,
|
|
||||||
children: group.map((event) {
|
|
||||||
final language = (event.label != null && event.label!.isNotEmpty)
|
|
||||||
? event.label![0].language ?? '?'
|
|
||||||
: '?';
|
|
||||||
return InputChip(
|
|
||||||
label: Text(language.toUpperCase(),
|
|
||||||
style: const TextStyle(fontSize: 12)),
|
|
||||||
onPressed: () => _editEvent(context, event),
|
|
||||||
onDeleted: () => _deleteEvent(context, event),
|
|
||||||
deleteIconColor: kError,
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildDateFilterChip(_AgendaDateFilter filter, String label) {
|
|
||||||
return ChoiceChip(
|
|
||||||
label: Text(label),
|
|
||||||
selected: _dateFilter == filter,
|
|
||||||
selectedColor: kPrimaryColor.withOpacity(0.2),
|
|
||||||
onSelected: (_) => setState(() => _dateFilter = filter),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
String _formatEventDate(EventAgendaDTO event) {
|
|
||||||
if (event.dateFrom == null) return '';
|
|
||||||
final dateFormat = DateFormat('dd/MM/yyyy');
|
|
||||||
final from = dateFormat.format(event.dateFrom!.toLocal());
|
|
||||||
if (event.dateTo == null || event.dateTo!.isAtSameMomentAs(event.dateFrom!)) {
|
|
||||||
return from;
|
|
||||||
}
|
|
||||||
return "$from - ${dateFormat.format(event.dateTo!.toLocal())}";
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildAgendaHeader(Size size, String mapProviderIn) {
|
Widget _buildAgendaHeader(Size size, String mapProviderIn) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
|||||||
@ -78,7 +78,6 @@ void showNewOrUpdateEventAgenda(
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: true,
|
isTitle: true,
|
||||||
isHTML: true,
|
isHTML: true,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
@ -93,7 +92,6 @@ void showNewOrUpdateEventAgenda(
|
|||||||
maxLines: 5,
|
maxLines: 5,
|
||||||
isTitle: false,
|
isTitle: false,
|
||||||
isHTML: true,
|
isHTML: true,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -72,10 +72,9 @@ class _ArticleConfigState extends State<ArticleConfig> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
constraints: BoxConstraints(minHeight: size.height * 0.15),
|
height: size.height * 0.15,
|
||||||
//width: size.width * 0.5,//,
|
//width: size.width * 0.5,//,
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
@ -97,7 +96,6 @@ class _ArticleConfigState extends State<ArticleConfig> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
CheckInputContainer(
|
CheckInputContainer(
|
||||||
label: "Contenu au-dessus :",
|
label: "Contenu au-dessus :",
|
||||||
|
|||||||
@ -97,7 +97,6 @@ void showNewOrUpdateMapAnnotation(
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: true,
|
isTitle: true,
|
||||||
isHTML: false,
|
isHTML: false,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 20),
|
const SizedBox(width: 20),
|
||||||
|
|||||||
@ -86,7 +86,6 @@ void showNewOrUpdateProgrammeBlock(
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: true,
|
isTitle: true,
|
||||||
isHTML: true,
|
isHTML: true,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
@ -101,7 +100,6 @@ void showNewOrUpdateProgrammeBlock(
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: false,
|
isTitle: false,
|
||||||
isHTML: true,
|
isHTML: true,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -74,7 +74,6 @@ Future<CategorieDTO?> showNewOrUpdateCategory(CategorieDTO? inputCategorieDTO, A
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: true,
|
isTitle: true,
|
||||||
isHTML: true,
|
isHTML: true,
|
||||||
showPreview: true,
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
|
|||||||
@ -111,7 +111,6 @@ void showNewOrUpdateGeoPoint(MapDTO mapDTO, GeoPointDTO? inputGeoPointDTO,
|
|||||||
},
|
},
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: true,
|
isTitle: true,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
@ -130,7 +129,6 @@ void showNewOrUpdateGeoPoint(MapDTO mapDTO, GeoPointDTO? inputGeoPointDTO,
|
|||||||
},
|
},
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: false,
|
isTitle: false,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
@ -149,7 +147,6 @@ void showNewOrUpdateGeoPoint(MapDTO mapDTO, GeoPointDTO? inputGeoPointDTO,
|
|||||||
},
|
},
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: true,
|
isTitle: true,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -173,7 +170,6 @@ void showNewOrUpdateGeoPoint(MapDTO mapDTO, GeoPointDTO? inputGeoPointDTO,
|
|||||||
},
|
},
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: false,
|
isTitle: false,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
@ -192,7 +188,6 @@ void showNewOrUpdateGeoPoint(MapDTO mapDTO, GeoPointDTO? inputGeoPointDTO,
|
|||||||
},
|
},
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: true,
|
isTitle: true,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
@ -211,7 +206,6 @@ void showNewOrUpdateGeoPoint(MapDTO mapDTO, GeoPointDTO? inputGeoPointDTO,
|
|||||||
},
|
},
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: true,
|
isTitle: true,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -236,7 +230,6 @@ void showNewOrUpdateGeoPoint(MapDTO mapDTO, GeoPointDTO? inputGeoPointDTO,
|
|||||||
},
|
},
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: false,
|
isTitle: false,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
|
|||||||
@ -210,7 +210,6 @@ class _SubSectionEditScreenState extends State<SubSectionEditScreen> {
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isHTML: true,
|
isHTML: true,
|
||||||
isTitle: true,
|
isTitle: true,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
MultiStringInputContainer(
|
MultiStringInputContainer(
|
||||||
@ -227,7 +226,6 @@ class _SubSectionEditScreenState extends State<SubSectionEditScreen> {
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isHTML: true,
|
isHTML: true,
|
||||||
isTitle: false,
|
isTitle: false,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -8,10 +8,9 @@ import 'package:manager_app/l10n/app_localizations.dart';
|
|||||||
import 'package:manager_app/Components/rounded_button.dart';
|
import 'package:manager_app/Components/rounded_button.dart';
|
||||||
import 'package:manager_app/Components/multi_string_input_container.dart';
|
import 'package:manager_app/Components/multi_string_input_container.dart';
|
||||||
import 'package:manager_app/Components/check_input_container.dart';
|
import 'package:manager_app/Components/check_input_container.dart';
|
||||||
import 'package:manager_app/Components/number_stepper_field.dart';
|
import 'package:manager_app/Components/string_input_container.dart';
|
||||||
import 'package:manager_app/Components/resource_input_container.dart';
|
import 'package:manager_app/Components/resource_input_container.dart';
|
||||||
import 'package:manager_app/Components/reorderable_custom_list.dart';
|
import 'package:manager_app/Components/reorderable_custom_list.dart';
|
||||||
import 'package:manager_app/Components/section_card.dart';
|
|
||||||
import 'showNewOrUpdateGuidedStep.dart';
|
import 'showNewOrUpdateGuidedStep.dart';
|
||||||
|
|
||||||
void showNewOrUpdateGuidedPath(
|
void showNewOrUpdateGuidedPath(
|
||||||
@ -45,6 +44,7 @@ void showNewOrUpdateGuidedPath(
|
|||||||
// contentWidth = dialogWidth minus the 24px padding on each side
|
// contentWidth = dialogWidth minus the 24px padding on each side
|
||||||
final double contentWidth = dialogWidth - 48;
|
final double contentWidth = dialogWidth - 48;
|
||||||
final double halfWidth = (contentWidth - 20) / 2;
|
final double halfWidth = (contentWidth - 20) / 2;
|
||||||
|
final double thirdWidth = (contentWidth - 40) / 3;
|
||||||
|
|
||||||
return Dialog(
|
return Dialog(
|
||||||
shape:
|
shape:
|
||||||
@ -95,7 +95,6 @@ void showNewOrUpdateGuidedPath(
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: true,
|
isTitle: true,
|
||||||
isHTML: true,
|
isHTML: true,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
@ -110,257 +109,243 @@ void showNewOrUpdateGuidedPath(
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: false,
|
isTitle: false,
|
||||||
isHTML: true,
|
isHTML: true,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 16),
|
Divider(height: 24),
|
||||||
// Options
|
// Options
|
||||||
SectionCard(
|
Row(
|
||||||
icon: Icons.settings,
|
children: [
|
||||||
title: "Options du parcours",
|
SizedBox(
|
||||||
child: Column(
|
width: thirdWidth,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: CheckInputContainer(
|
||||||
children: [
|
|
||||||
CheckInputContainer(
|
|
||||||
label: AppLocalizations.of(context)!.linearLabel,
|
label: AppLocalizations.of(context)!.linearLabel,
|
||||||
subtitle: "Les étapes doivent être suivies dans l'ordre.",
|
|
||||||
isChecked: workingPath.isLinear ?? false,
|
isChecked: workingPath.isLinear ?? false,
|
||||||
onChanged: (val) => setState(
|
onChanged: (val) => setState(
|
||||||
() => workingPath.isLinear = val),
|
() => workingPath.isLinear = val),
|
||||||
),
|
),
|
||||||
CheckInputContainer(
|
),
|
||||||
|
SizedBox(width: 20),
|
||||||
|
SizedBox(
|
||||||
|
width: thirdWidth,
|
||||||
|
child: CheckInputContainer(
|
||||||
label: AppLocalizations.of(context)!.requiredSuccessLabel,
|
label: AppLocalizations.of(context)!.requiredSuccessLabel,
|
||||||
subtitle: "Le quiz de chaque étape doit être validé pour débloquer la suivante.",
|
|
||||||
isChecked:
|
isChecked:
|
||||||
workingPath.requireSuccessToAdvance ??
|
workingPath.requireSuccessToAdvance ??
|
||||||
false,
|
false,
|
||||||
onChanged: (val) => setState(() => workingPath
|
onChanged: (val) => setState(() => workingPath
|
||||||
.requireSuccessToAdvance = val),
|
.requireSuccessToAdvance = val),
|
||||||
),
|
),
|
||||||
CheckInputContainer(
|
),
|
||||||
|
SizedBox(width: 20),
|
||||||
|
SizedBox(
|
||||||
|
width: thirdWidth,
|
||||||
|
child: CheckInputContainer(
|
||||||
label: "Cacher les suivantes :",
|
label: "Cacher les suivantes :",
|
||||||
subtitle: "Seule l'étape en cours est visible sur la carte.",
|
|
||||||
isChecked:
|
isChecked:
|
||||||
workingPath.hideNextStepsUntilComplete ??
|
workingPath.hideNextStepsUntilComplete ??
|
||||||
false,
|
false,
|
||||||
onChanged: (val) => setState(() => workingPath
|
onChanged: (val) => setState(() => workingPath
|
||||||
.hideNextStepsUntilComplete = val),
|
.hideNextStepsUntilComplete = val),
|
||||||
),
|
),
|
||||||
SizedBox(height: 8),
|
),
|
||||||
NumberStepperField(
|
],
|
||||||
label: "Durée estimée",
|
),
|
||||||
value: workingPath.estimatedDurationMinutes,
|
SizedBox(height: 8),
|
||||||
min: 0,
|
SizedBox(
|
||||||
max: 600,
|
width: thirdWidth,
|
||||||
unit: "min",
|
child: StringInputContainer(
|
||||||
onChanged: (val) => setState(() =>
|
label: "Durée estimée (min) :",
|
||||||
workingPath.estimatedDurationMinutes = val.toInt()),
|
initialValue: workingPath.estimatedDurationMinutes?.toString() ?? "",
|
||||||
),
|
onChanged: (val) => setState(() =>
|
||||||
],
|
workingPath.estimatedDurationMinutes = int.tryParse(val)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 16),
|
Divider(height: 24),
|
||||||
// Mode jeu
|
// Mode jeu
|
||||||
SectionCard(
|
CheckInputContainer(
|
||||||
icon: Icons.sports_esports,
|
label: "Mode jeu (escape game / chasse au trésor)",
|
||||||
title: "Mode jeu",
|
isChecked: workingPath.isGameMode ?? false,
|
||||||
subtitle: "Escape game ou chasse au trésor",
|
onChanged: (val) =>
|
||||||
child: Column(
|
setState(() => workingPath.isGameMode = val),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
CheckInputContainer(
|
|
||||||
label: "Mode jeu (escape game / chasse au trésor)",
|
|
||||||
subtitle: "Active les messages de jeu ci-dessous et le vocabulaire escape game sur les étapes.",
|
|
||||||
isChecked: workingPath.isGameMode ?? false,
|
|
||||||
onChanged: (val) =>
|
|
||||||
setState(() => workingPath.isGameMode = val),
|
|
||||||
),
|
|
||||||
if (workingPath.isGameMode == true) ...[
|
|
||||||
SizedBox(height: 8),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: MultiStringInputContainer(
|
|
||||||
label: "Message de début :",
|
|
||||||
modalLabel: "Message d'introduction du jeu",
|
|
||||||
color: kPrimaryColor,
|
|
||||||
initialValue: (workingPath.gameMessageDebut ?? [])
|
|
||||||
.map((t) => TranslationDTO(language: t.language, value: t.value))
|
|
||||||
.toList(),
|
|
||||||
onGetResult: (val) {
|
|
||||||
setState(() {
|
|
||||||
workingPath.gameMessageDebut = val.map((t) {
|
|
||||||
final prev = (workingPath.gameMessageDebut ?? []).firstWhere(
|
|
||||||
(e) => e.language == t.language,
|
|
||||||
orElse: () => TranslationAndResourceDTO(),
|
|
||||||
);
|
|
||||||
return TranslationAndResourceDTO(
|
|
||||||
language: t.language,
|
|
||||||
value: t.value,
|
|
||||||
resourceId: prev.resourceId,
|
|
||||||
resource: prev.resource,
|
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
maxLines: 2,
|
|
||||||
isTitle: false,
|
|
||||||
isHTML: true,
|
|
||||||
showPreview: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 20),
|
|
||||||
Expanded(
|
|
||||||
child: MultiStringInputContainer(
|
|
||||||
label: "Message de fin :",
|
|
||||||
modalLabel: "Message de félicitations du jeu",
|
|
||||||
color: kPrimaryColor,
|
|
||||||
initialValue: (workingPath.gameMessageFin ?? [])
|
|
||||||
.map((t) => TranslationDTO(language: t.language, value: t.value))
|
|
||||||
.toList(),
|
|
||||||
onGetResult: (val) {
|
|
||||||
setState(() {
|
|
||||||
workingPath.gameMessageFin = val.map((t) {
|
|
||||||
final prev = (workingPath.gameMessageFin ?? []).firstWhere(
|
|
||||||
(e) => e.language == t.language,
|
|
||||||
orElse: () => TranslationAndResourceDTO(),
|
|
||||||
);
|
|
||||||
return TranslationAndResourceDTO(
|
|
||||||
language: t.language,
|
|
||||||
value: t.value,
|
|
||||||
resourceId: prev.resourceId,
|
|
||||||
resource: prev.resource,
|
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
maxLines: 2,
|
|
||||||
isTitle: false,
|
|
||||||
isHTML: true,
|
|
||||||
showPreview: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
SizedBox(height: 16),
|
if (workingPath.isGameMode == true) ...[
|
||||||
// Étapes
|
SizedBox(height: 8),
|
||||||
SectionCard(
|
Row(
|
||||||
icon: Icons.list_alt,
|
|
||||||
title: AppLocalizations.of(context)!.pathStepsLabel,
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
Align(
|
Expanded(
|
||||||
alignment: Alignment.centerRight,
|
child: MultiStringInputContainer(
|
||||||
child: IconButton(
|
label: "Message de début :",
|
||||||
icon: Icon(Icons.add_circle_outline,
|
modalLabel: "Message d'introduction du jeu",
|
||||||
color: kSuccess),
|
color: kPrimaryColor,
|
||||||
onPressed: () {
|
initialValue: (workingPath.gameMessageDebut ?? [])
|
||||||
showNewOrUpdateGuidedStep(
|
.map((t) => TranslationDTO(language: t.language, value: t.value))
|
||||||
context,
|
.toList(),
|
||||||
null,
|
onGetResult: (val) {
|
||||||
workingPath.id ?? "temp",
|
|
||||||
workingPath.isGameMode ?? false,
|
|
||||||
(newStep) async {
|
|
||||||
setState(() {
|
|
||||||
newStep.order =
|
|
||||||
workingPath.steps?.length ?? 0;
|
|
||||||
workingPath.steps = [
|
|
||||||
...(workingPath.steps ?? []),
|
|
||||||
newStep
|
|
||||||
];
|
|
||||||
stepsRevision++;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (workingPath.steps?.isEmpty ?? true)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
|
||||||
child: Text(
|
|
||||||
AppLocalizations.of(context)!.noStepConfigured,
|
|
||||||
style: TextStyle(
|
|
||||||
fontStyle: FontStyle.italic,
|
|
||||||
color: Colors.grey[600]),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
else
|
|
||||||
ReorderableCustomList<GuidedStepDTO>(
|
|
||||||
key: ValueKey(stepsRevision),
|
|
||||||
items: workingPath.steps!,
|
|
||||||
shrinkWrap: true,
|
|
||||||
onChanged: (updatedList) {
|
|
||||||
setState(() {
|
setState(() {
|
||||||
for (var i = 0; i < updatedList.length; i++) {
|
workingPath.gameMessageDebut = val.map((t) {
|
||||||
updatedList[i].order = i;
|
final prev = (workingPath.gameMessageDebut ?? []).firstWhere(
|
||||||
}
|
(e) => e.language == t.language,
|
||||||
workingPath.steps = List.from(updatedList);
|
orElse: () => TranslationAndResourceDTO(),
|
||||||
|
);
|
||||||
|
return TranslationAndResourceDTO(
|
||||||
|
language: t.language,
|
||||||
|
value: t.value,
|
||||||
|
resourceId: prev.resourceId,
|
||||||
|
resource: prev.resource,
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
itemBuilder: (context, index, step) {
|
maxLines: 2,
|
||||||
return ListTile(
|
isTitle: false,
|
||||||
leading:
|
isHTML: true,
|
||||||
CircleAvatar(child: Text("${index + 1}")),
|
|
||||||
title: HtmlWidget(
|
|
||||||
step.title != null && step.title!.isNotEmpty
|
|
||||||
? step.title!
|
|
||||||
.firstWhere(
|
|
||||||
(t) => t.language == 'FR',
|
|
||||||
orElse: () =>
|
|
||||||
step.title![0])
|
|
||||||
.value ??
|
|
||||||
"${AppLocalizations.of(context)!.stepFallback} $index"
|
|
||||||
: "${AppLocalizations.of(context)!.stepFallback} $index",
|
|
||||||
),
|
|
||||||
subtitle: workingPath.isGameMode ?? false
|
|
||||||
? Text(
|
|
||||||
"${step.quizQuestions?.length ?? 0} question(s)")
|
|
||||||
: null,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
actions: [
|
|
||||||
(context, index, step) => IconButton(
|
|
||||||
icon: Icon(Icons.edit,
|
|
||||||
color: kPrimaryColor),
|
|
||||||
onPressed: () {
|
|
||||||
showNewOrUpdateGuidedStep(
|
|
||||||
context,
|
|
||||||
step,
|
|
||||||
workingPath.id ?? "temp",
|
|
||||||
workingPath.isGameMode ?? false,
|
|
||||||
(updatedStep) async {
|
|
||||||
setState(() {
|
|
||||||
updatedStep.order = step.order;
|
|
||||||
workingPath.steps![index] =
|
|
||||||
updatedStep;
|
|
||||||
stepsRevision++;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
(context, index, step) => IconButton(
|
|
||||||
icon: Icon(Icons.delete, color: kError),
|
|
||||||
onPressed: () {
|
|
||||||
setState(() {
|
|
||||||
workingPath.steps!.removeAt(index);
|
|
||||||
stepsRevision++;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
SizedBox(width: 20),
|
||||||
|
Expanded(
|
||||||
|
child: MultiStringInputContainer(
|
||||||
|
label: "Message de fin :",
|
||||||
|
modalLabel: "Message de félicitations du jeu",
|
||||||
|
color: kPrimaryColor,
|
||||||
|
initialValue: (workingPath.gameMessageFin ?? [])
|
||||||
|
.map((t) => TranslationDTO(language: t.language, value: t.value))
|
||||||
|
.toList(),
|
||||||
|
onGetResult: (val) {
|
||||||
|
setState(() {
|
||||||
|
workingPath.gameMessageFin = val.map((t) {
|
||||||
|
final prev = (workingPath.gameMessageFin ?? []).firstWhere(
|
||||||
|
(e) => e.language == t.language,
|
||||||
|
orElse: () => TranslationAndResourceDTO(),
|
||||||
|
);
|
||||||
|
return TranslationAndResourceDTO(
|
||||||
|
language: t.language,
|
||||||
|
value: t.value,
|
||||||
|
resourceId: prev.resourceId,
|
||||||
|
resource: prev.resource,
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
maxLines: 2,
|
||||||
|
isTitle: false,
|
||||||
|
isHTML: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
Divider(height: 24),
|
||||||
|
// Étapes
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(AppLocalizations.of(context)!.pathStepsLabel,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 15)),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.add_circle_outline,
|
||||||
|
color: kSuccess),
|
||||||
|
onPressed: () {
|
||||||
|
showNewOrUpdateGuidedStep(
|
||||||
|
context,
|
||||||
|
null,
|
||||||
|
workingPath.id ?? "temp",
|
||||||
|
workingPath.isGameMode ?? false,
|
||||||
|
(newStep) async {
|
||||||
|
setState(() {
|
||||||
|
newStep.order =
|
||||||
|
workingPath.steps?.length ?? 0;
|
||||||
|
workingPath.steps = [
|
||||||
|
...(workingPath.steps ?? []),
|
||||||
|
newStep
|
||||||
|
];
|
||||||
|
stepsRevision++;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
|
if (workingPath.steps?.isEmpty ?? true)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context)!.noStepConfigured,
|
||||||
|
style: TextStyle(
|
||||||
|
fontStyle: FontStyle.italic,
|
||||||
|
color: Colors.grey[600]),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
ReorderableCustomList<GuidedStepDTO>(
|
||||||
|
key: ValueKey(stepsRevision),
|
||||||
|
items: workingPath.steps!,
|
||||||
|
shrinkWrap: true,
|
||||||
|
onChanged: (updatedList) {
|
||||||
|
setState(() {
|
||||||
|
for (var i = 0; i < updatedList.length; i++) {
|
||||||
|
updatedList[i].order = i;
|
||||||
|
}
|
||||||
|
workingPath.steps = List.from(updatedList);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
itemBuilder: (context, index, step) {
|
||||||
|
return ListTile(
|
||||||
|
leading:
|
||||||
|
CircleAvatar(child: Text("${index + 1}")),
|
||||||
|
title: HtmlWidget(
|
||||||
|
step.title != null && step.title!.isNotEmpty
|
||||||
|
? step.title!
|
||||||
|
.firstWhere(
|
||||||
|
(t) => t.language == 'FR',
|
||||||
|
orElse: () =>
|
||||||
|
step.title![0])
|
||||||
|
.value ??
|
||||||
|
"${AppLocalizations.of(context)!.stepFallback} $index"
|
||||||
|
: "${AppLocalizations.of(context)!.stepFallback} $index",
|
||||||
|
),
|
||||||
|
subtitle: workingPath.isGameMode ?? false
|
||||||
|
? Text(
|
||||||
|
"${step.quizQuestions?.length ?? 0} question(s)")
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
actions: [
|
||||||
|
(context, index, step) => IconButton(
|
||||||
|
icon: Icon(Icons.edit,
|
||||||
|
color: kPrimaryColor),
|
||||||
|
onPressed: () {
|
||||||
|
showNewOrUpdateGuidedStep(
|
||||||
|
context,
|
||||||
|
step,
|
||||||
|
workingPath.id ?? "temp",
|
||||||
|
workingPath.isGameMode ?? false,
|
||||||
|
(updatedStep) async {
|
||||||
|
setState(() {
|
||||||
|
updatedStep.order = step.order;
|
||||||
|
workingPath.steps![index] =
|
||||||
|
updatedStep;
|
||||||
|
stepsRevision++;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(context, index, step) => IconButton(
|
||||||
|
icon: Icon(Icons.delete, color: kError),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
workingPath.steps!.removeAt(index);
|
||||||
|
stepsRevision++;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -5,11 +5,10 @@ import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
|||||||
import 'package:manager_api_new/api.dart';
|
import 'package:manager_api_new/api.dart';
|
||||||
import 'package:manager_app/Components/confirmation_dialog.dart';
|
import 'package:manager_app/Components/confirmation_dialog.dart';
|
||||||
import 'package:manager_app/Components/geometry_input_container.dart';
|
import 'package:manager_app/Components/geometry_input_container.dart';
|
||||||
import 'package:manager_app/Components/number_stepper_field.dart';
|
|
||||||
import 'package:manager_app/Components/reorderable_custom_list.dart';
|
import 'package:manager_app/Components/reorderable_custom_list.dart';
|
||||||
import 'package:manager_app/Components/multi_string_input_container.dart';
|
import 'package:manager_app/Components/multi_string_input_container.dart';
|
||||||
import 'package:manager_app/Components/rounded_button.dart';
|
import 'package:manager_app/Components/rounded_button.dart';
|
||||||
import 'package:manager_app/Components/section_card.dart';
|
import 'package:manager_app/Components/string_input_container.dart';
|
||||||
import 'package:manager_app/Screens/Configurations/Section/SubSection/Slider/listView_card_image.dart';
|
import 'package:manager_app/Screens/Configurations/Section/SubSection/Slider/listView_card_image.dart';
|
||||||
import 'package:manager_app/Screens/Configurations/Section/SubSection/Slider/new_update_image_slider.dart';
|
import 'package:manager_app/Screens/Configurations/Section/SubSection/Slider/new_update_image_slider.dart';
|
||||||
import 'package:manager_app/app_context.dart';
|
import 'package:manager_app/app_context.dart';
|
||||||
@ -94,7 +93,6 @@ void showNewOrUpdateGuidedStep(
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: true,
|
isTitle: true,
|
||||||
isHTML: true,
|
isHTML: true,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(width: 20),
|
SizedBox(width: 20),
|
||||||
@ -109,378 +107,300 @@ void showNewOrUpdateGuidedStep(
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: false,
|
isTitle: false,
|
||||||
isHTML: true,
|
isHTML: true,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 16),
|
Divider(height: 24),
|
||||||
// Emplacement — Directement avec GeometryDTO
|
// Géométrie — Directement avec GeometryDTO
|
||||||
SectionCard(
|
GeometryInputContainer(
|
||||||
icon: Icons.location_on,
|
label: AppLocalizations.of(context)!.stepLocationLabel,
|
||||||
title: "Emplacement",
|
initialGeometry: workingStep.geometry,
|
||||||
subtitle: "Position et déclenchement géolocalisé de l'étape",
|
initialColor: null,
|
||||||
child: Column(
|
onSave: (geometry, color) {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
setState(() {
|
||||||
children: [
|
workingStep.geometry = geometry;
|
||||||
GeometryInputContainer(
|
});
|
||||||
label: AppLocalizations.of(context)!.stepLocationLabel,
|
},
|
||||||
initialGeometry: workingStep.geometry,
|
|
||||||
initialColor: null,
|
|
||||||
onSave: (geometry, color) {
|
|
||||||
setState(() {
|
|
||||||
workingStep.geometry = geometry;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
SizedBox(height: 8),
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Switch(
|
|
||||||
value: workingStep.isGeoTriggered ?? false,
|
|
||||||
onChanged: (val) => setState(() => workingStep.isGeoTriggered = val),
|
|
||||||
activeThumbColor: kPrimaryColor,
|
|
||||||
),
|
|
||||||
SizedBox(width: 8),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Text("Déclenchement géolocalisé", style: TextStyle(fontSize: 14)),
|
|
||||||
Text(
|
|
||||||
"L'étape se débloque automatiquement quand le visiteur entre dans la zone.",
|
|
||||||
style: TextStyle(fontSize: 12, color: Colors.grey[600]),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (workingStep.isGeoTriggered == true)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(left: 12),
|
|
||||||
child: NumberStepperField(
|
|
||||||
label: "Rayon",
|
|
||||||
value: workingStep.zoneRadiusMeters,
|
|
||||||
min: 1,
|
|
||||||
max: 500,
|
|
||||||
unit: "m",
|
|
||||||
onChanged: (val) => setState(() =>
|
|
||||||
workingStep.zoneRadiusMeters = val.toDouble()),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
SizedBox(height: 16),
|
SizedBox(height: 8),
|
||||||
|
SwitchListTile(
|
||||||
|
dense: true,
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
title: Text("Déclenchement géolocalisé"),
|
||||||
|
value: workingStep.isGeoTriggered ?? false,
|
||||||
|
onChanged: (val) => setState(() => workingStep.isGeoTriggered = val),
|
||||||
|
activeThumbColor: kPrimaryColor,
|
||||||
|
),
|
||||||
|
if (workingStep.isGeoTriggered == true) ...[
|
||||||
|
SizedBox(height: 8),
|
||||||
|
SizedBox(
|
||||||
|
width: halfWidth,
|
||||||
|
child: StringInputContainer(
|
||||||
|
label: "Rayon (mètres) :",
|
||||||
|
initialValue: workingStep.zoneRadiusMeters?.toString() ?? "",
|
||||||
|
onChanged: (val) => setState(() =>
|
||||||
|
workingStep.zoneRadiusMeters = double.tryParse(val)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
Divider(height: 24),
|
||||||
// Comportement de l'étape
|
// Comportement de l'étape
|
||||||
SectionCard(
|
Text("Comportement", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15)),
|
||||||
icon: Icons.tune,
|
SizedBox(height: 8),
|
||||||
title: "Comportement",
|
Row(
|
||||||
subtitle: "Visibilité et verrouillage de l'étape",
|
children: [
|
||||||
child: Row(
|
Expanded(
|
||||||
children: [
|
child: SwitchListTile(
|
||||||
Expanded(
|
dense: true,
|
||||||
child: SwitchListTile(
|
title: Text(AppLocalizations.of(context)!.initiallyHiddenLabel),
|
||||||
dense: true,
|
value: workingStep.isHiddenInitially ?? false,
|
||||||
title: Text(AppLocalizations.of(context)!.initiallyHiddenLabel),
|
onChanged: (val) => setState(() => workingStep.isHiddenInitially = val),
|
||||||
subtitle: Text(
|
activeThumbColor: kPrimaryColor,
|
||||||
"N'apparaît pas sur la carte tant qu'elle n'a pas été débloquée.",
|
|
||||||
style: TextStyle(fontSize: 12),
|
|
||||||
),
|
|
||||||
value: workingStep.isHiddenInitially ?? false,
|
|
||||||
onChanged: (val) => setState(() => workingStep.isHiddenInitially = val),
|
|
||||||
activeThumbColor: kPrimaryColor,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Expanded(
|
),
|
||||||
child: SwitchListTile(
|
Expanded(
|
||||||
dense: true,
|
child: SwitchListTile(
|
||||||
title: Text(AppLocalizations.of(context)!.lockedLabel),
|
dense: true,
|
||||||
subtitle: Text(
|
title: Text(AppLocalizations.of(context)!.lockedLabel),
|
||||||
"Visible mais non accessible tant que les étapes précédentes ne sont pas terminées.",
|
value: workingStep.isStepLocked ?? false,
|
||||||
style: TextStyle(fontSize: 12),
|
onChanged: (val) => setState(() => workingStep.isStepLocked = val),
|
||||||
),
|
activeThumbColor: kPrimaryColor,
|
||||||
value: workingStep.isStepLocked ?? false,
|
|
||||||
onChanged: (val) => setState(() => workingStep.isStepLocked = val),
|
|
||||||
activeThumbColor: kPrimaryColor,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
SizedBox(height: 16),
|
Divider(height: 24),
|
||||||
SectionCard(
|
Text("Contenu riche", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15)),
|
||||||
icon: Icons.perm_media,
|
SizedBox(height: 8),
|
||||||
title: "Contenu riche",
|
// Audio
|
||||||
subtitle: "Audio guide et images affichés sur la fiche de l'étape",
|
MultiStringInputContainer(
|
||||||
child: Column(
|
label: "Audio :",
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
resourceTypes: [ResourceType.Audio],
|
||||||
|
modalLabel: "Audio du guide",
|
||||||
|
initialValue: workingStep.audioIds!,
|
||||||
|
onGetResult: (val) => setState(() => workingStep.audioIds = val.isEmpty ? null : val),
|
||||||
|
maxLines: 1,
|
||||||
|
isTitle: false,
|
||||||
|
isHTML: false,
|
||||||
|
),
|
||||||
|
SizedBox(height: 12),
|
||||||
|
// Images
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text("Images :", style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500)),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.add_circle_outline, color: kSuccess),
|
||||||
|
onPressed: () async {
|
||||||
|
final result = await showNewOrUpdateContentSlider(null, appCtx, context, true, false);
|
||||||
|
if (result != null) {
|
||||||
|
setState(() {
|
||||||
|
result.order = workingStep.contents!.length;
|
||||||
|
workingStep.contents = [...workingStep.contents!, result];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (workingStep.contents!.isEmpty)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 8),
|
||||||
|
child: Text(
|
||||||
|
"Aucune image — cliquez + pour en ajouter",
|
||||||
|
style: TextStyle(fontStyle: FontStyle.italic, color: Colors.grey[600], fontSize: 13),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
SizedBox(
|
||||||
|
height: 250,
|
||||||
|
child: ReorderableListView(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
onReorderItem: (oldIndex, newIndex) {
|
||||||
|
setState(() {
|
||||||
|
final item = workingStep.contents!.removeAt(oldIndex);
|
||||||
|
workingStep.contents!.insert(newIndex, item);
|
||||||
|
for (var i = 0; i < workingStep.contents!.length; i++) {
|
||||||
|
workingStep.contents![i].order = i;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
children: List.generate(workingStep.contents!.length, (i) => ListViewCardContent(
|
||||||
|
workingStep.contents!,
|
||||||
|
i,
|
||||||
|
Key('content_$i'),
|
||||||
|
appCtx,
|
||||||
|
(updated) => setState(() => workingStep.contents = List.from(updated)),
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Questions — uniquement en mode Escape Game
|
||||||
|
if (isEscapeMode) ...[
|
||||||
|
Divider(height: 24),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
// Audio
|
Text(AppLocalizations.of(context)!.questionsChallengesLabel,
|
||||||
MultiStringInputContainer(
|
style: TextStyle(
|
||||||
label: "Audio :",
|
fontWeight: FontWeight.bold,
|
||||||
resourceTypes: [ResourceType.Audio],
|
fontSize: 15)),
|
||||||
modalLabel: "Audio du guide",
|
IconButton(
|
||||||
initialValue: workingStep.audioIds!,
|
icon: Icon(Icons.add_circle_outline,
|
||||||
onGetResult: (val) => setState(() => workingStep.audioIds = val.isEmpty ? null : val),
|
color: kSuccess),
|
||||||
maxLines: 1,
|
onPressed: () {
|
||||||
isTitle: false,
|
showNewOrUpdateQuizQuestion(
|
||||||
isHTML: false,
|
context,
|
||||||
),
|
null,
|
||||||
SizedBox(height: 12),
|
workingStep.id ?? "temp",
|
||||||
// Images
|
isEscapeMode,
|
||||||
Row(
|
(newQuestion) {
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text("Images :", style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500)),
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(Icons.add_circle_outline, color: kSuccess),
|
|
||||||
onPressed: () async {
|
|
||||||
final result = await showNewOrUpdateContentSlider(null, appCtx, context, true, false);
|
|
||||||
if (result != null) {
|
|
||||||
setState(() {
|
|
||||||
result.order = workingStep.contents!.length;
|
|
||||||
workingStep.contents = [...workingStep.contents!, result];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (workingStep.contents!.isEmpty)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: 8),
|
|
||||||
child: Text(
|
|
||||||
"Aucune image — cliquez + pour en ajouter",
|
|
||||||
style: TextStyle(fontStyle: FontStyle.italic, color: Colors.grey[600], fontSize: 13),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
else
|
|
||||||
SizedBox(
|
|
||||||
height: 250,
|
|
||||||
child: ReorderableListView(
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
onReorderItem: (oldIndex, newIndex) {
|
|
||||||
setState(() {
|
setState(() {
|
||||||
final item = workingStep.contents!.removeAt(oldIndex);
|
newQuestion.order =
|
||||||
workingStep.contents!.insert(newIndex, item);
|
workingStep.quizQuestions?.length ?? 0;
|
||||||
for (var i = 0; i < workingStep.contents!.length; i++) {
|
workingStep.quizQuestions = [
|
||||||
workingStep.contents![i].order = i;
|
...(workingStep.quizQuestions ??
|
||||||
}
|
[]),
|
||||||
|
newQuestion
|
||||||
|
];
|
||||||
|
questionsRevision++;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
children: List.generate(workingStep.contents!.length, (i) => ListViewCardContent(
|
);
|
||||||
workingStep.contents!,
|
},
|
||||||
i,
|
),
|
||||||
Key('content_$i'),
|
|
||||||
appCtx,
|
|
||||||
(updated) => setState(() => workingStep.contents = List.from(updated)),
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
SizedBox(
|
||||||
SizedBox(height: 16),
|
width: halfWidth,
|
||||||
// Questions — disponibles pour tous les parcours (guidés et escape game)
|
child: SwitchListTile(
|
||||||
SectionCard(
|
dense: true,
|
||||||
icon: Icons.quiz,
|
contentPadding: EdgeInsets.zero,
|
||||||
title: AppLocalizations.of(context)!.questionsChallengesLabel,
|
title: Text("Timer"),
|
||||||
subtitle: isEscapeMode
|
value: workingStep.isStepTimer ?? false,
|
||||||
? "Énigme à résoudre pour progresser"
|
onChanged: (val) => setState(() => workingStep.isStepTimer = val),
|
||||||
: "Quiz optionnel pour cette étape",
|
activeThumbColor: kPrimaryColor,
|
||||||
child: Column(
|
),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
),
|
||||||
children: [
|
if (workingStep.isStepTimer == true) ...[
|
||||||
Align(
|
SizedBox(height: 8),
|
||||||
alignment: Alignment.centerRight,
|
Row(
|
||||||
child: IconButton(
|
children: [
|
||||||
icon: Icon(Icons.add_circle_outline,
|
SizedBox(
|
||||||
color: kSuccess),
|
width: halfWidth,
|
||||||
onPressed: () {
|
child: StringInputContainer(
|
||||||
showNewOrUpdateQuizQuestion(
|
label: AppLocalizations.of(context)!.durationSecondsLabel,
|
||||||
context,
|
initialValue: workingStep.timerSeconds?.toString() ?? "",
|
||||||
null,
|
onChanged: (val) => setState(() =>
|
||||||
workingStep.id ?? "temp",
|
workingStep.timerSeconds = int.tryParse(val)),
|
||||||
isEscapeMode,
|
),
|
||||||
(newQuestion) {
|
),
|
||||||
setState(() {
|
SizedBox(width: 20),
|
||||||
newQuestion.order =
|
SizedBox(
|
||||||
workingStep.quizQuestions?.length ?? 0;
|
width: halfWidth,
|
||||||
workingStep.quizQuestions = [
|
child: MultiStringInputContainer(
|
||||||
...(workingStep.quizQuestions ??
|
label: "Message d'expiration :",
|
||||||
[]),
|
modalLabel: "Message d'expiration du timer",
|
||||||
newQuestion
|
initialValue: workingStep.timerExpiredMessage ?? [],
|
||||||
];
|
onGetResult: (val) => setState(() =>
|
||||||
questionsRevision++;
|
workingStep.timerExpiredMessage = val.isEmpty ? null : val),
|
||||||
});
|
maxLines: 2,
|
||||||
},
|
isTitle: false,
|
||||||
);
|
isHTML: true,
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Switch(
|
|
||||||
value: workingStep.isStepTimer ?? false,
|
|
||||||
onChanged: (val) => setState(() => workingStep.isStepTimer = val),
|
|
||||||
activeThumbColor: kPrimaryColor,
|
|
||||||
),
|
|
||||||
SizedBox(width: 8),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Text("Timer", style: TextStyle(fontSize: 14)),
|
|
||||||
Text(
|
|
||||||
"Chronomètre la réponse ; passé le délai, le message d'expiration s'affiche.",
|
|
||||||
style: TextStyle(fontSize: 12, color: Colors.grey[600]),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
if (workingStep.isStepTimer == true)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(left: 12),
|
|
||||||
child: NumberStepperField(
|
|
||||||
label: AppLocalizations.of(context)!.durationSecondsLabel,
|
|
||||||
value: workingStep.timerSeconds,
|
|
||||||
min: 0,
|
|
||||||
max: 3600,
|
|
||||||
unit: "sec",
|
|
||||||
onChanged: (val) => setState(() => workingStep.timerSeconds = val.toInt()),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (workingStep.isStepTimer == true) ...[
|
|
||||||
SizedBox(height: 8),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: MultiStringInputContainer(
|
|
||||||
label: "Message d'expiration :",
|
|
||||||
modalLabel: "Message d'expiration du timer",
|
|
||||||
initialValue: workingStep.timerExpiredMessage ?? [],
|
|
||||||
onGetResult: (val) => setState(() =>
|
|
||||||
workingStep.timerExpiredMessage = val.isEmpty ? null : val),
|
|
||||||
maxLines: 2,
|
|
||||||
isTitle: false,
|
|
||||||
isHTML: true,
|
|
||||||
showPreview: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
SizedBox(height: 8),
|
|
||||||
],
|
],
|
||||||
if (workingStep.quizQuestions == null ||
|
),
|
||||||
workingStep.quizQuestions!.isEmpty)
|
SizedBox(height: 8),
|
||||||
Padding(
|
],
|
||||||
padding:
|
if (workingStep.quizQuestions == null ||
|
||||||
const EdgeInsets.symmetric(vertical: 8),
|
workingStep.quizQuestions!.isEmpty)
|
||||||
child: Text(
|
Padding(
|
||||||
AppLocalizations.of(context)!.noQuestionsConfigured,
|
padding:
|
||||||
style: TextStyle(
|
const EdgeInsets.symmetric(vertical: 8),
|
||||||
fontStyle: FontStyle.italic,
|
child: Text(
|
||||||
color: Colors.grey[600]),
|
AppLocalizations.of(context)!.noQuestionsConfigured,
|
||||||
|
style: TextStyle(
|
||||||
|
fontStyle: FontStyle.italic,
|
||||||
|
color: Colors.grey[600]),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
ReorderableCustomList<QuizQuestion>(
|
||||||
|
key: ValueKey(questionsRevision),
|
||||||
|
items: workingStep.quizQuestions!,
|
||||||
|
shrinkWrap: true,
|
||||||
|
onChanged: (updatedList) {
|
||||||
|
setState(() {
|
||||||
|
for (var i = 0; i < updatedList.length; i++) {
|
||||||
|
updatedList[i].order = i;
|
||||||
|
}
|
||||||
|
workingStep.quizQuestions =
|
||||||
|
List.from(updatedList);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
itemBuilder: (context, qIndex, question) {
|
||||||
|
return ListTile(
|
||||||
|
dense: true,
|
||||||
|
title: HtmlWidget(
|
||||||
|
question.label.isNotEmpty
|
||||||
|
? question.label
|
||||||
|
.firstWhere(
|
||||||
|
(t) => t.language == 'FR',
|
||||||
|
orElse: () =>
|
||||||
|
question.label[0])
|
||||||
|
.value ??
|
||||||
|
"Question $qIndex"
|
||||||
|
: "Question $qIndex",
|
||||||
|
textStyle: TextStyle(fontSize: 14),
|
||||||
),
|
),
|
||||||
)
|
subtitle: Text(
|
||||||
else
|
"Type: ${question.validationQuestionType?.value == 2 ? 'Puzzle' : question.validationQuestionType?.value == 1 ? 'QCM' : 'Texte'}"),
|
||||||
ReorderableCustomList<QuizQuestion>(
|
);
|
||||||
key: ValueKey(questionsRevision),
|
},
|
||||||
items: workingStep.quizQuestions!,
|
actions: [
|
||||||
shrinkWrap: true,
|
(context, qIndex, question) => IconButton(
|
||||||
onChanged: (updatedList) {
|
icon: Icon(Icons.edit,
|
||||||
setState(() {
|
size: 18, color: kPrimaryColor),
|
||||||
for (var i = 0; i < updatedList.length; i++) {
|
onPressed: () {
|
||||||
updatedList[i].order = i;
|
showNewOrUpdateQuizQuestion(
|
||||||
}
|
context,
|
||||||
workingStep.quizQuestions =
|
question,
|
||||||
List.from(updatedList);
|
workingStep.id ?? "temp",
|
||||||
});
|
isEscapeMode,
|
||||||
},
|
(updatedQuestion) {
|
||||||
itemBuilder: (context, qIndex, question) {
|
setState(() {
|
||||||
return ListTile(
|
updatedQuestion.order =
|
||||||
dense: true,
|
question.order;
|
||||||
title: HtmlWidget(
|
workingStep.quizQuestions![
|
||||||
question.label.isNotEmpty
|
qIndex] = updatedQuestion;
|
||||||
? question.label
|
questionsRevision++;
|
||||||
.firstWhere(
|
});
|
||||||
(t) => t.language == 'FR',
|
|
||||||
orElse: () =>
|
|
||||||
question.label[0])
|
|
||||||
.value ??
|
|
||||||
"Question $qIndex"
|
|
||||||
: "Question $qIndex",
|
|
||||||
textStyle: TextStyle(fontSize: 14),
|
|
||||||
),
|
|
||||||
subtitle: Text(
|
|
||||||
"Type: ${question.validationQuestionType?.value == 2 ? 'Puzzle' : question.validationQuestionType?.value == 1 ? 'QCM' : 'Texte'}"),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
actions: [
|
|
||||||
(context, qIndex, question) => IconButton(
|
|
||||||
icon: Icon(Icons.edit,
|
|
||||||
size: 18, color: kPrimaryColor),
|
|
||||||
onPressed: () {
|
|
||||||
showNewOrUpdateQuizQuestion(
|
|
||||||
context,
|
|
||||||
question,
|
|
||||||
workingStep.id ?? "temp",
|
|
||||||
isEscapeMode,
|
|
||||||
(updatedQuestion) {
|
|
||||||
setState(() {
|
|
||||||
updatedQuestion.order =
|
|
||||||
question.order;
|
|
||||||
workingStep.quizQuestions![
|
|
||||||
qIndex] = updatedQuestion;
|
|
||||||
questionsRevision++;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
);
|
||||||
(context, qIndex, question) => IconButton(
|
},
|
||||||
icon: Icon(Icons.delete,
|
),
|
||||||
size: 18, color: kError),
|
(context, qIndex, question) => IconButton(
|
||||||
onPressed: () {
|
icon: Icon(Icons.delete,
|
||||||
showConfirmationDialog(
|
size: 18, color: kError),
|
||||||
"Supprimer cette question ?",
|
onPressed: () {
|
||||||
() {},
|
showConfirmationDialog(
|
||||||
() => setState(() {
|
"Supprimer cette question ?",
|
||||||
workingStep.quizQuestions!
|
() {},
|
||||||
.removeAt(qIndex);
|
() => setState(() {
|
||||||
questionsRevision++;
|
workingStep.quizQuestions!
|
||||||
}),
|
.removeAt(qIndex);
|
||||||
context,
|
questionsRevision++;
|
||||||
);
|
}),
|
||||||
},
|
context,
|
||||||
),
|
);
|
||||||
],
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -516,6 +436,11 @@ void showNewOrUpdateGuidedStep(
|
|||||||
if (workingStep.isGeoTriggered != true) {
|
if (workingStep.isGeoTriggered != true) {
|
||||||
workingStep.zoneRadiusMeters = null;
|
workingStep.zoneRadiusMeters = null;
|
||||||
}
|
}
|
||||||
|
if (!isEscapeMode) {
|
||||||
|
workingStep.isStepTimer = false;
|
||||||
|
workingStep.timerSeconds = null;
|
||||||
|
workingStep.timerExpiredMessage = null;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await onSave(workingStep);
|
await onSave(workingStep);
|
||||||
if (context.mounted) Navigator.pop(context);
|
if (context.mounted) Navigator.pop(context);
|
||||||
|
|||||||
@ -115,7 +115,6 @@ void showNewOrUpdateQuizQuestion(
|
|||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
isTitle: false,
|
isTitle: false,
|
||||||
isHTML: true,
|
isHTML: true,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
|
|
||||||
@ -168,7 +167,6 @@ void showNewOrUpdateQuizQuestion(
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: true,
|
isTitle: true,
|
||||||
isHTML: true,
|
isHTML: true,
|
||||||
showPreview: true,
|
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
SizedBox(height: 4),
|
SizedBox(height: 4),
|
||||||
@ -258,7 +256,6 @@ void showNewOrUpdateQuizQuestion(
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: true,
|
isTitle: true,
|
||||||
isHTML: true,
|
isHTML: true,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// Supprimer
|
// Supprimer
|
||||||
|
|||||||
@ -97,8 +97,7 @@ Future<ContentDTO?> showNewOrUpdateContentSlider(ContentDTO? inputContentDTO, Ap
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: true,
|
isTitle: true
|
||||||
showPreview: true
|
|
||||||
),
|
),
|
||||||
MultiStringInputContainer(
|
MultiStringInputContainer(
|
||||||
label: AppLocalizations.of(context)!.displayedDescriptionLabel,
|
label: AppLocalizations.of(context)!.displayedDescriptionLabel,
|
||||||
@ -114,8 +113,7 @@ Future<ContentDTO?> showNewOrUpdateContentSlider(ContentDTO? inputContentDTO, Ap
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isTitle: false,
|
isTitle: false
|
||||||
showPreview: true
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@ -34,43 +34,19 @@ class _VideoConfigState extends State<VideoConfig> {
|
|||||||
late VideoDTO resourceSource;
|
late VideoDTO resourceSource;
|
||||||
late _VideoSourceMode _mode;
|
late _VideoSourceMode _mode;
|
||||||
String? _selectedResourceLabel;
|
String? _selectedResourceLabel;
|
||||||
String? _youtubeUrl;
|
|
||||||
String? _vimeoUrl;
|
|
||||||
String? _resourceUrl;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
resourceSource = widget.initialValue;
|
resourceSource = widget.initialValue;
|
||||||
_mode = _detectMode(resourceSource.source_);
|
_mode = _detectMode(resourceSource.source_);
|
||||||
switch (_mode) {
|
|
||||||
case _VideoSourceMode.youtube:
|
|
||||||
_youtubeUrl = resourceSource.source_;
|
|
||||||
break;
|
|
||||||
case _VideoSourceMode.vimeo:
|
|
||||||
_vimeoUrl = resourceSource.source_;
|
|
||||||
break;
|
|
||||||
case _VideoSourceMode.resource:
|
|
||||||
_resourceUrl = resourceSource.source_;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onModeChanged(_VideoSourceMode mode) {
|
void _onModeChanged(_VideoSourceMode mode) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_mode = mode;
|
_mode = mode;
|
||||||
|
resourceSource.source_ = null;
|
||||||
_selectedResourceLabel = null;
|
_selectedResourceLabel = null;
|
||||||
switch (mode) {
|
|
||||||
case _VideoSourceMode.youtube:
|
|
||||||
resourceSource.source_ = _youtubeUrl;
|
|
||||||
break;
|
|
||||||
case _VideoSourceMode.vimeo:
|
|
||||||
resourceSource.source_ = _vimeoUrl;
|
|
||||||
break;
|
|
||||||
case _VideoSourceMode.resource:
|
|
||||||
resourceSource.source_ = _resourceUrl;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
widget.onChanged(resourceSource);
|
widget.onChanged(resourceSource);
|
||||||
}
|
}
|
||||||
@ -92,11 +68,9 @@ class _VideoConfigState extends State<VideoConfig> {
|
|||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
if (_mode == _VideoSourceMode.youtube)
|
if (_mode == _VideoSourceMode.youtube)
|
||||||
StringInputContainer(
|
StringInputContainer(
|
||||||
key: const ValueKey('youtube'),
|
|
||||||
label: 'URL YouTube :',
|
label: 'URL YouTube :',
|
||||||
initialValue: _youtubeUrl,
|
initialValue: _mode == _VideoSourceMode.youtube ? resourceSource.source_ : null,
|
||||||
onChanged: (url) {
|
onChanged: (url) {
|
||||||
_youtubeUrl = url;
|
|
||||||
resourceSource.source_ = url;
|
resourceSource.source_ = url;
|
||||||
widget.onChanged(resourceSource);
|
widget.onChanged(resourceSource);
|
||||||
},
|
},
|
||||||
@ -105,11 +79,9 @@ class _VideoConfigState extends State<VideoConfig> {
|
|||||||
),
|
),
|
||||||
if (_mode == _VideoSourceMode.vimeo)
|
if (_mode == _VideoSourceMode.vimeo)
|
||||||
StringInputContainer(
|
StringInputContainer(
|
||||||
key: const ValueKey('vimeo'),
|
|
||||||
label: 'URL Vimeo :',
|
label: 'URL Vimeo :',
|
||||||
initialValue: _vimeoUrl,
|
initialValue: _mode == _VideoSourceMode.vimeo ? resourceSource.source_ : null,
|
||||||
onChanged: (url) {
|
onChanged: (url) {
|
||||||
_vimeoUrl = url;
|
|
||||||
resourceSource.source_ = url;
|
resourceSource.source_ = url;
|
||||||
widget.onChanged(resourceSource);
|
widget.onChanged(resourceSource);
|
||||||
},
|
},
|
||||||
@ -119,10 +91,9 @@ class _VideoConfigState extends State<VideoConfig> {
|
|||||||
if (_mode == _VideoSourceMode.resource)
|
if (_mode == _VideoSourceMode.resource)
|
||||||
_ResourceVideoPicker(
|
_ResourceVideoPicker(
|
||||||
selectedLabel: _selectedResourceLabel,
|
selectedLabel: _selectedResourceLabel,
|
||||||
selectedUrl: _resourceUrl,
|
selectedUrl: _mode == _VideoSourceMode.resource ? resourceSource.source_ : null,
|
||||||
onChanged: (resource) {
|
onChanged: (resource) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_resourceUrl = resource.url;
|
|
||||||
resourceSource.source_ = resource.url;
|
resourceSource.source_ = resource.url;
|
||||||
_selectedResourceLabel = resource.label;
|
_selectedResourceLabel = resource.label;
|
||||||
});
|
});
|
||||||
|
|||||||
@ -273,7 +273,6 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
isHTML: true,
|
isHTML: true,
|
||||||
isTitle: true,
|
isTitle: true,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@ -200,8 +200,7 @@ class _ConfigurationDetailScreenState extends State<ConfigurationDetailScreen> {
|
|||||||
isHTML: true,
|
isHTML: true,
|
||||||
isMandatory: false,
|
isMandatory: false,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
onGetResult: (value) => setState(() => config.title = value),
|
onGetResult: (value) => config.title = value,
|
||||||
showPreview: true,
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Wrap(
|
Wrap(
|
||||||
|
|||||||
@ -117,6 +117,7 @@ class _DeviceElementState extends State<DeviceElement> {
|
|||||||
DeviceDTO? device = await managerAppContext.clientAPI!.deviceApi!.deviceUpdateMainInfos(deviceToUpdate);
|
DeviceDTO? device = await managerAppContext.clientAPI!.deviceApi!.deviceUpdateMainInfos(deviceToUpdate);
|
||||||
|
|
||||||
appConfigurationToUpdate.configurationId = deviceToUpdate.configurationId;
|
appConfigurationToUpdate.configurationId = deviceToUpdate.configurationId;
|
||||||
|
appConfigurationToUpdate.layoutMainPage = LayoutMainPageType.SimpleGrid; // Hardcoded for now as not supported
|
||||||
AppConfigurationLinkDTO? result = await managerAppContext.clientAPI!.applicationInstanceApi!.applicationInstanceUpdateApplicationLink(appConfigurationToUpdate);
|
AppConfigurationLinkDTO? result = await managerAppContext.clientAPI!.applicationInstanceApi!.applicationInstanceUpdateApplicationLink(appConfigurationToUpdate);
|
||||||
|
|
||||||
//print(device);
|
//print(device);
|
||||||
|
|||||||
@ -289,11 +289,6 @@
|
|||||||
"addEvent": "Add an event",
|
"addEvent": "Add an event",
|
||||||
"noEvents": "No events",
|
"noEvents": "No events",
|
||||||
"noAddress": "No address",
|
"noAddress": "No address",
|
||||||
"agendaFilterAll": "All",
|
|
||||||
"agendaFilterThisMonth": "This month",
|
|
||||||
"agendaFilterThisYear": "This year",
|
|
||||||
"agendaFilterPast": "Past",
|
|
||||||
"agendaEventDeleteConfirm": "Are you sure you want to delete this event?",
|
|
||||||
"onlineLabel": "Online:",
|
"onlineLabel": "Online:",
|
||||||
"mapViewLabel": "Map view:",
|
"mapViewLabel": "Map view:",
|
||||||
"mapServiceLabel": "Map service:",
|
"mapServiceLabel": "Map service:",
|
||||||
@ -367,10 +362,6 @@
|
|||||||
"languagesLabel": "Languages:",
|
"languagesLabel": "Languages:",
|
||||||
"featuredEventLabel": "Featured event:",
|
"featuredEventLabel": "Featured event:",
|
||||||
"chooseEvent": "Choose an event",
|
"chooseEvent": "Choose an event",
|
||||||
"previewWebTitle": "Preview — Web",
|
|
||||||
"previewMobileTitle": "Preview — Mobile",
|
|
||||||
"previewDesktop": "Desktop",
|
|
||||||
"previewMobile": "Mobile",
|
|
||||||
"noneOption": "None",
|
"noneOption": "None",
|
||||||
"aiAssistantLabel": "AI assistant:",
|
"aiAssistantLabel": "AI assistant:",
|
||||||
"appUpdatedSuccess": "Mobile application updated",
|
"appUpdatedSuccess": "Mobile application updated",
|
||||||
|
|||||||
@ -289,11 +289,6 @@
|
|||||||
"addEvent": "Ajouter un évènement",
|
"addEvent": "Ajouter un évènement",
|
||||||
"noEvents": "Aucun évènement",
|
"noEvents": "Aucun évènement",
|
||||||
"noAddress": "Pas d'adresse",
|
"noAddress": "Pas d'adresse",
|
||||||
"agendaFilterAll": "Tous",
|
|
||||||
"agendaFilterThisMonth": "Ce mois-ci",
|
|
||||||
"agendaFilterThisYear": "Cette année",
|
|
||||||
"agendaFilterPast": "Passés",
|
|
||||||
"agendaEventDeleteConfirm": "Êtes-vous sûr de vouloir supprimer cet évènement ?",
|
|
||||||
"onlineLabel": "En ligne :",
|
"onlineLabel": "En ligne :",
|
||||||
"mapViewLabel": "Vue carte :",
|
"mapViewLabel": "Vue carte :",
|
||||||
"mapServiceLabel": "Service carte :",
|
"mapServiceLabel": "Service carte :",
|
||||||
@ -367,10 +362,6 @@
|
|||||||
"languagesLabel": "Langues :",
|
"languagesLabel": "Langues :",
|
||||||
"featuredEventLabel": "Evènement à l'affiche :",
|
"featuredEventLabel": "Evènement à l'affiche :",
|
||||||
"chooseEvent": "Choisir un évènement",
|
"chooseEvent": "Choisir un évènement",
|
||||||
"previewWebTitle": "Aperçu — Web",
|
|
||||||
"previewMobileTitle": "Aperçu — Mobile",
|
|
||||||
"previewDesktop": "Desktop",
|
|
||||||
"previewMobile": "Mobile",
|
|
||||||
"noneOption": "Aucun",
|
"noneOption": "Aucun",
|
||||||
"aiAssistantLabel": "Assistant IA :",
|
"aiAssistantLabel": "Assistant IA :",
|
||||||
"appUpdatedSuccess": "Application mobile mise à jour",
|
"appUpdatedSuccess": "Application mobile mise à jour",
|
||||||
|
|||||||
@ -1462,36 +1462,6 @@ abstract class AppLocalizations {
|
|||||||
/// **'Pas d\'adresse'**
|
/// **'Pas d\'adresse'**
|
||||||
String get noAddress;
|
String get noAddress;
|
||||||
|
|
||||||
/// No description provided for @agendaFilterAll.
|
|
||||||
///
|
|
||||||
/// In fr, this message translates to:
|
|
||||||
/// **'Tous'**
|
|
||||||
String get agendaFilterAll;
|
|
||||||
|
|
||||||
/// No description provided for @agendaFilterThisMonth.
|
|
||||||
///
|
|
||||||
/// In fr, this message translates to:
|
|
||||||
/// **'Ce mois-ci'**
|
|
||||||
String get agendaFilterThisMonth;
|
|
||||||
|
|
||||||
/// No description provided for @agendaFilterThisYear.
|
|
||||||
///
|
|
||||||
/// In fr, this message translates to:
|
|
||||||
/// **'Cette année'**
|
|
||||||
String get agendaFilterThisYear;
|
|
||||||
|
|
||||||
/// No description provided for @agendaFilterPast.
|
|
||||||
///
|
|
||||||
/// In fr, this message translates to:
|
|
||||||
/// **'Passés'**
|
|
||||||
String get agendaFilterPast;
|
|
||||||
|
|
||||||
/// No description provided for @agendaEventDeleteConfirm.
|
|
||||||
///
|
|
||||||
/// In fr, this message translates to:
|
|
||||||
/// **'Êtes-vous sûr de vouloir supprimer cet évènement ?'**
|
|
||||||
String get agendaEventDeleteConfirm;
|
|
||||||
|
|
||||||
/// No description provided for @onlineLabel.
|
/// No description provided for @onlineLabel.
|
||||||
///
|
///
|
||||||
/// In fr, this message translates to:
|
/// In fr, this message translates to:
|
||||||
@ -1894,30 +1864,6 @@ abstract class AppLocalizations {
|
|||||||
/// **'Choisir un évènement'**
|
/// **'Choisir un évènement'**
|
||||||
String get chooseEvent;
|
String get chooseEvent;
|
||||||
|
|
||||||
/// No description provided for @previewWebTitle.
|
|
||||||
///
|
|
||||||
/// In fr, this message translates to:
|
|
||||||
/// **'Aperçu — Web'**
|
|
||||||
String get previewWebTitle;
|
|
||||||
|
|
||||||
/// No description provided for @previewMobileTitle.
|
|
||||||
///
|
|
||||||
/// In fr, this message translates to:
|
|
||||||
/// **'Aperçu — Mobile'**
|
|
||||||
String get previewMobileTitle;
|
|
||||||
|
|
||||||
/// No description provided for @previewDesktop.
|
|
||||||
///
|
|
||||||
/// In fr, this message translates to:
|
|
||||||
/// **'Desktop'**
|
|
||||||
String get previewDesktop;
|
|
||||||
|
|
||||||
/// No description provided for @previewMobile.
|
|
||||||
///
|
|
||||||
/// In fr, this message translates to:
|
|
||||||
/// **'Mobile'**
|
|
||||||
String get previewMobile;
|
|
||||||
|
|
||||||
/// No description provided for @noneOption.
|
/// No description provided for @noneOption.
|
||||||
///
|
///
|
||||||
/// In fr, this message translates to:
|
/// In fr, this message translates to:
|
||||||
|
|||||||
@ -737,22 +737,6 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get noAddress => 'No address';
|
String get noAddress => 'No address';
|
||||||
|
|
||||||
@override
|
|
||||||
String get agendaFilterAll => 'All';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get agendaFilterThisMonth => 'This month';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get agendaFilterThisYear => 'This year';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get agendaFilterPast => 'Past';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get agendaEventDeleteConfirm =>
|
|
||||||
'Are you sure you want to delete this event?';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get onlineLabel => 'Online:';
|
String get onlineLabel => 'Online:';
|
||||||
|
|
||||||
@ -959,18 +943,6 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get chooseEvent => 'Choose an event';
|
String get chooseEvent => 'Choose an event';
|
||||||
|
|
||||||
@override
|
|
||||||
String get previewWebTitle => 'Preview — Web';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get previewMobileTitle => 'Preview — Mobile';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get previewDesktop => 'Desktop';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get previewMobile => 'Mobile';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get noneOption => 'None';
|
String get noneOption => 'None';
|
||||||
|
|
||||||
|
|||||||
@ -760,22 +760,6 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get noAddress => 'Pas d\'adresse';
|
String get noAddress => 'Pas d\'adresse';
|
||||||
|
|
||||||
@override
|
|
||||||
String get agendaFilterAll => 'Tous';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get agendaFilterThisMonth => 'Ce mois-ci';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get agendaFilterThisYear => 'Cette année';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get agendaFilterPast => 'Passés';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get agendaEventDeleteConfirm =>
|
|
||||||
'Êtes-vous sûr de vouloir supprimer cet évènement ?';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get onlineLabel => 'En ligne :';
|
String get onlineLabel => 'En ligne :';
|
||||||
|
|
||||||
@ -989,18 +973,6 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get chooseEvent => 'Choisir un évènement';
|
String get chooseEvent => 'Choisir un évènement';
|
||||||
|
|
||||||
@override
|
|
||||||
String get previewWebTitle => 'Aperçu — Web';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get previewMobileTitle => 'Aperçu — Mobile';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get previewDesktop => 'Desktop';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get previewMobile => 'Mobile';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get noneOption => 'Aucun';
|
String get noneOption => 'Aucun';
|
||||||
|
|
||||||
|
|||||||
@ -746,22 +746,6 @@ class AppLocalizationsNl extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get noAddress => 'Geen adres';
|
String get noAddress => 'Geen adres';
|
||||||
|
|
||||||
@override
|
|
||||||
String get agendaFilterAll => 'Alle';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get agendaFilterThisMonth => 'Deze maand';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get agendaFilterThisYear => 'Dit jaar';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get agendaFilterPast => 'Verleden';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get agendaEventDeleteConfirm =>
|
|
||||||
'Weet u zeker dat u dit evenement wilt verwijderen?';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get onlineLabel => 'Online:';
|
String get onlineLabel => 'Online:';
|
||||||
|
|
||||||
@ -970,18 +954,6 @@ class AppLocalizationsNl extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get chooseEvent => 'Kies een evenement';
|
String get chooseEvent => 'Kies een evenement';
|
||||||
|
|
||||||
@override
|
|
||||||
String get previewWebTitle => 'Voorbeeld — Web';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get previewMobileTitle => 'Voorbeeld — Mobiel';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get previewDesktop => 'Desktop';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get previewMobile => 'Mobiel';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get noneOption => 'Geen';
|
String get noneOption => 'Geen';
|
||||||
|
|
||||||
|
|||||||
@ -289,11 +289,6 @@
|
|||||||
"addEvent": "Evenement toevoegen",
|
"addEvent": "Evenement toevoegen",
|
||||||
"noEvents": "Geen evenementen",
|
"noEvents": "Geen evenementen",
|
||||||
"noAddress": "Geen adres",
|
"noAddress": "Geen adres",
|
||||||
"agendaFilterAll": "Alle",
|
|
||||||
"agendaFilterThisMonth": "Deze maand",
|
|
||||||
"agendaFilterThisYear": "Dit jaar",
|
|
||||||
"agendaFilterPast": "Verleden",
|
|
||||||
"agendaEventDeleteConfirm": "Weet u zeker dat u dit evenement wilt verwijderen?",
|
|
||||||
"onlineLabel": "Online:",
|
"onlineLabel": "Online:",
|
||||||
"mapViewLabel": "Kaartweergave:",
|
"mapViewLabel": "Kaartweergave:",
|
||||||
"mapServiceLabel": "Kaartservice:",
|
"mapServiceLabel": "Kaartservice:",
|
||||||
@ -367,10 +362,6 @@
|
|||||||
"languagesLabel": "Talen:",
|
"languagesLabel": "Talen:",
|
||||||
"featuredEventLabel": "Uitgelicht evenement:",
|
"featuredEventLabel": "Uitgelicht evenement:",
|
||||||
"chooseEvent": "Kies een evenement",
|
"chooseEvent": "Kies een evenement",
|
||||||
"previewWebTitle": "Voorbeeld — Web",
|
|
||||||
"previewMobileTitle": "Voorbeeld — Mobiel",
|
|
||||||
"previewDesktop": "Desktop",
|
|
||||||
"previewMobile": "Mobiel",
|
|
||||||
"noneOption": "Geen",
|
"noneOption": "Geen",
|
||||||
"aiAssistantLabel": "AI-assistent:",
|
"aiAssistantLabel": "AI-assistent:",
|
||||||
"appUpdatedSuccess": "Mobiele applicatie bijgewerkt",
|
"appUpdatedSuccess": "Mobiele applicatie bijgewerkt",
|
||||||
|
|||||||
@ -238,6 +238,7 @@ Class | Method | HTTP request | Description
|
|||||||
- [GuidedStepTriggerGeoPoint](doc//GuidedStepTriggerGeoPoint.md)
|
- [GuidedStepTriggerGeoPoint](doc//GuidedStepTriggerGeoPoint.md)
|
||||||
- [Instance](doc//Instance.md)
|
- [Instance](doc//Instance.md)
|
||||||
- [InstanceDTO](doc//InstanceDTO.md)
|
- [InstanceDTO](doc//InstanceDTO.md)
|
||||||
|
- [LayoutMainPageType](doc//LayoutMainPageType.md)
|
||||||
- [LoginDTO](doc//LoginDTO.md)
|
- [LoginDTO](doc//LoginDTO.md)
|
||||||
- [MapAnnotation](doc//MapAnnotation.md)
|
- [MapAnnotation](doc//MapAnnotation.md)
|
||||||
- [MapAnnotationDTO](doc//MapAnnotationDTO.md)
|
- [MapAnnotationDTO](doc//MapAnnotationDTO.md)
|
||||||
|
|||||||
@ -13,13 +13,13 @@ Name | Type | Description | Notes
|
|||||||
**id** | **String** | | [optional]
|
**id** | **String** | | [optional]
|
||||||
**order** | **int** | | [optional]
|
**order** | **int** | | [optional]
|
||||||
**isActive** | **bool** | | [optional]
|
**isActive** | **bool** | | [optional]
|
||||||
**gridColSpan** | **int** | | [optional]
|
**weightMasonryGrid** | **int** | | [optional]
|
||||||
**gridRowSpan** | **int** | | [optional]
|
|
||||||
**isDate** | **bool** | | [optional]
|
**isDate** | **bool** | | [optional]
|
||||||
**isHour** | **bool** | | [optional]
|
**isHour** | **bool** | | [optional]
|
||||||
**roundedValue** | **int** | | [optional]
|
**roundedValue** | **int** | | [optional]
|
||||||
**screenPercentageSectionsMainPage** | **int** | | [optional]
|
**screenPercentageSectionsMainPage** | **int** | | [optional]
|
||||||
**isSectionImageBackground** | **bool** | | [optional]
|
**isSectionImageBackground** | **bool** | | [optional]
|
||||||
|
**layoutMainPage** | [**LayoutMainPageType**](LayoutMainPageType.md) | | [optional]
|
||||||
**loaderImageId** | **String** | | [optional]
|
**loaderImageId** | **String** | | [optional]
|
||||||
**loaderImageUrl** | **String** | | [optional]
|
**loaderImageUrl** | **String** | | [optional]
|
||||||
**primaryColor** | **String** | | [optional]
|
**primaryColor** | **String** | | [optional]
|
||||||
|
|||||||
@ -18,6 +18,7 @@ Name | Type | Description | Notes
|
|||||||
**loaderImageUrl** | **String** | | [optional]
|
**loaderImageUrl** | **String** | | [optional]
|
||||||
**primaryColor** | **String** | | [optional]
|
**primaryColor** | **String** | | [optional]
|
||||||
**secondaryColor** | **String** | | [optional]
|
**secondaryColor** | **String** | | [optional]
|
||||||
|
**layoutMainPage** | [**LayoutMainPageType**](LayoutMainPageType.md) | | [optional]
|
||||||
**languages** | **List<String>** | | [optional] [default to const []]
|
**languages** | **List<String>** | | [optional] [default to const []]
|
||||||
**sectionEventId** | **String** | | [optional]
|
**sectionEventId** | **String** | | [optional]
|
||||||
**sectionEvent** | [**ApplicationInstanceSectionEvent**](ApplicationInstanceSectionEvent.md) | | [optional]
|
**sectionEvent** | [**ApplicationInstanceSectionEvent**](ApplicationInstanceSectionEvent.md) | | [optional]
|
||||||
|
|||||||
@ -14,8 +14,7 @@ Name | Type | Description | Notes
|
|||||||
**applicationInstanceId** | **String** | | [optional]
|
**applicationInstanceId** | **String** | | [optional]
|
||||||
**order** | **int** | | [optional]
|
**order** | **int** | | [optional]
|
||||||
**isActive** | **bool** | | [optional]
|
**isActive** | **bool** | | [optional]
|
||||||
**gridColSpan** | **int** | | [optional]
|
**weightMasonryGrid** | **int** | | [optional]
|
||||||
**gridRowSpan** | **int** | | [optional]
|
|
||||||
**isDate** | **bool** | | [optional]
|
**isDate** | **bool** | | [optional]
|
||||||
**isHour** | **bool** | | [optional]
|
**isHour** | **bool** | | [optional]
|
||||||
**roundedValue** | **int** | | [optional]
|
**roundedValue** | **int** | | [optional]
|
||||||
@ -23,6 +22,7 @@ Name | Type | Description | Notes
|
|||||||
**isSectionImageBackground** | **bool** | | [optional]
|
**isSectionImageBackground** | **bool** | | [optional]
|
||||||
**deviceId** | **String** | | [optional]
|
**deviceId** | **String** | | [optional]
|
||||||
**device** | [**AppConfigurationLinkDTODevice**](AppConfigurationLinkDTODevice.md) | | [optional]
|
**device** | [**AppConfigurationLinkDTODevice**](AppConfigurationLinkDTODevice.md) | | [optional]
|
||||||
|
**layoutMainPage** | [**LayoutMainPageType**](LayoutMainPageType.md) | | [optional]
|
||||||
**loaderImageId** | **String** | | [optional]
|
**loaderImageId** | **String** | | [optional]
|
||||||
**loaderImageUrl** | **String** | | [optional]
|
**loaderImageUrl** | **String** | | [optional]
|
||||||
**primaryColor** | **String** | | [optional]
|
**primaryColor** | **String** | | [optional]
|
||||||
|
|||||||
@ -18,6 +18,7 @@ Name | Type | Description | Notes
|
|||||||
**loaderImageUrl** | **String** | | [optional]
|
**loaderImageUrl** | **String** | | [optional]
|
||||||
**primaryColor** | **String** | | [optional]
|
**primaryColor** | **String** | | [optional]
|
||||||
**secondaryColor** | **String** | | [optional]
|
**secondaryColor** | **String** | | [optional]
|
||||||
|
**layoutMainPage** | [**LayoutMainPageType**](LayoutMainPageType.md) | | [optional]
|
||||||
**languages** | **List<String>** | | [optional] [default to const []]
|
**languages** | **List<String>** | | [optional] [default to const []]
|
||||||
**sectionEventId** | **String** | | [optional]
|
**sectionEventId** | **String** | | [optional]
|
||||||
**sectionEvent** | [**ApplicationInstanceSectionEvent**](ApplicationInstanceSectionEvent.md) | | [optional]
|
**sectionEvent** | [**ApplicationInstanceSectionEvent**](ApplicationInstanceSectionEvent.md) | | [optional]
|
||||||
|
|||||||
@ -18,6 +18,7 @@ Name | Type | Description | Notes
|
|||||||
**loaderImageUrl** | **String** | | [optional]
|
**loaderImageUrl** | **String** | | [optional]
|
||||||
**primaryColor** | **String** | | [optional]
|
**primaryColor** | **String** | | [optional]
|
||||||
**secondaryColor** | **String** | | [optional]
|
**secondaryColor** | **String** | | [optional]
|
||||||
|
**layoutMainPage** | [**LayoutMainPageType**](LayoutMainPageType.md) | | [optional]
|
||||||
**languages** | **List<String>** | | [optional] [default to const []]
|
**languages** | **List<String>** | | [optional] [default to const []]
|
||||||
**sectionEventId** | **String** | | [optional]
|
**sectionEventId** | **String** | | [optional]
|
||||||
**sectionEventDTO** | [**ApplicationInstanceDTOSectionEventDTO**](ApplicationInstanceDTOSectionEventDTO.md) | | [optional]
|
**sectionEventDTO** | [**ApplicationInstanceDTOSectionEventDTO**](ApplicationInstanceDTOSectionEventDTO.md) | | [optional]
|
||||||
|
|||||||
14
manager_api_new/doc/LayoutMainPageType.md
Normal file
14
manager_api_new/doc/LayoutMainPageType.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# manager_api_new.model.LayoutMainPageType
|
||||||
|
|
||||||
|
## Load the model package
|
||||||
|
```dart
|
||||||
|
import 'package:manager_api_new/api.dart';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
Name | Type | Description | Notes
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
|
||||||
|
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||||
|
|
||||||
|
|
||||||
@ -118,6 +118,7 @@ part 'model/instance.dart';
|
|||||||
part 'model/instance_dto.dart';
|
part 'model/instance_dto.dart';
|
||||||
part 'model/instance_quota_dto.dart';
|
part 'model/instance_quota_dto.dart';
|
||||||
part 'model/subscription_plan_dto.dart';
|
part 'model/subscription_plan_dto.dart';
|
||||||
|
part 'model/layout_main_page_type.dart';
|
||||||
part 'model/login_dto.dart';
|
part 'model/login_dto.dart';
|
||||||
part 'model/map_annotation.dart';
|
part 'model/map_annotation.dart';
|
||||||
part 'model/map_annotation_dto.dart';
|
part 'model/map_annotation_dto.dart';
|
||||||
|
|||||||
@ -361,6 +361,8 @@ class ApiClient {
|
|||||||
return InstanceDTO.fromJson(value);
|
return InstanceDTO.fromJson(value);
|
||||||
case 'InstanceQuotaDTO':
|
case 'InstanceQuotaDTO':
|
||||||
return InstanceQuotaDTO.fromJson(value);
|
return InstanceQuotaDTO.fromJson(value);
|
||||||
|
case 'LayoutMainPageType':
|
||||||
|
return LayoutMainPageTypeTypeTransformer().decode(value);
|
||||||
case 'LoginDTO':
|
case 'LoginDTO':
|
||||||
return LoginDTO.fromJson(value);
|
return LoginDTO.fromJson(value);
|
||||||
case 'MapAnnotation':
|
case 'MapAnnotation':
|
||||||
|
|||||||
@ -80,6 +80,9 @@ String parameterToString(dynamic value) {
|
|||||||
if (value is GeometryType) {
|
if (value is GeometryType) {
|
||||||
return GeometryTypeTypeTransformer().encode(value).toString();
|
return GeometryTypeTypeTransformer().encode(value).toString();
|
||||||
}
|
}
|
||||||
|
if (value is LayoutMainPageType) {
|
||||||
|
return LayoutMainPageTypeTypeTransformer().encode(value).toString();
|
||||||
|
}
|
||||||
if (value is MapProvider) {
|
if (value is MapProvider) {
|
||||||
return MapProviderTypeTransformer().encode(value).toString();
|
return MapProviderTypeTransformer().encode(value).toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,13 +18,13 @@ class AppConfigurationLink {
|
|||||||
this.id,
|
this.id,
|
||||||
this.order,
|
this.order,
|
||||||
this.isActive,
|
this.isActive,
|
||||||
this.gridColSpan,
|
this.weightMasonryGrid,
|
||||||
this.gridRowSpan,
|
|
||||||
this.isDate,
|
this.isDate,
|
||||||
this.isHour,
|
this.isHour,
|
||||||
this.roundedValue,
|
this.roundedValue,
|
||||||
this.screenPercentageSectionsMainPage,
|
this.screenPercentageSectionsMainPage,
|
||||||
this.isSectionImageBackground,
|
this.isSectionImageBackground,
|
||||||
|
this.layoutMainPage,
|
||||||
this.loaderImageId,
|
this.loaderImageId,
|
||||||
this.loaderImageUrl,
|
this.loaderImageUrl,
|
||||||
this.primaryColor,
|
this.primaryColor,
|
||||||
@ -51,9 +51,7 @@ class AppConfigurationLink {
|
|||||||
///
|
///
|
||||||
bool? isActive;
|
bool? isActive;
|
||||||
|
|
||||||
int? gridColSpan;
|
int? weightMasonryGrid;
|
||||||
|
|
||||||
int? gridRowSpan;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
@ -83,6 +81,14 @@ class AppConfigurationLink {
|
|||||||
///
|
///
|
||||||
bool? isSectionImageBackground;
|
bool? isSectionImageBackground;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// 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;
|
||||||
|
|
||||||
String? loaderImageId;
|
String? loaderImageId;
|
||||||
|
|
||||||
String? loaderImageUrl;
|
String? loaderImageUrl;
|
||||||
@ -108,14 +114,14 @@ class AppConfigurationLink {
|
|||||||
other.id == id &&
|
other.id == id &&
|
||||||
other.order == order &&
|
other.order == order &&
|
||||||
other.isActive == isActive &&
|
other.isActive == isActive &&
|
||||||
other.gridColSpan == gridColSpan &&
|
other.weightMasonryGrid == weightMasonryGrid &&
|
||||||
other.gridRowSpan == gridRowSpan &&
|
|
||||||
other.isDate == isDate &&
|
other.isDate == isDate &&
|
||||||
other.isHour == isHour &&
|
other.isHour == isHour &&
|
||||||
other.roundedValue == roundedValue &&
|
other.roundedValue == roundedValue &&
|
||||||
other.screenPercentageSectionsMainPage ==
|
other.screenPercentageSectionsMainPage ==
|
||||||
screenPercentageSectionsMainPage &&
|
screenPercentageSectionsMainPage &&
|
||||||
other.isSectionImageBackground == isSectionImageBackground &&
|
other.isSectionImageBackground == isSectionImageBackground &&
|
||||||
|
other.layoutMainPage == layoutMainPage &&
|
||||||
other.loaderImageId == loaderImageId &&
|
other.loaderImageId == loaderImageId &&
|
||||||
other.loaderImageUrl == loaderImageUrl &&
|
other.loaderImageUrl == loaderImageUrl &&
|
||||||
other.primaryColor == primaryColor &&
|
other.primaryColor == primaryColor &&
|
||||||
@ -133,8 +139,7 @@ class AppConfigurationLink {
|
|||||||
(id == null ? 0 : id!.hashCode) +
|
(id == null ? 0 : id!.hashCode) +
|
||||||
(order == null ? 0 : order!.hashCode) +
|
(order == null ? 0 : order!.hashCode) +
|
||||||
(isActive == null ? 0 : isActive!.hashCode) +
|
(isActive == null ? 0 : isActive!.hashCode) +
|
||||||
(gridColSpan == null ? 0 : gridColSpan!.hashCode) +
|
(weightMasonryGrid == null ? 0 : weightMasonryGrid!.hashCode) +
|
||||||
(gridRowSpan == null ? 0 : gridRowSpan!.hashCode) +
|
|
||||||
(isDate == null ? 0 : isDate!.hashCode) +
|
(isDate == null ? 0 : isDate!.hashCode) +
|
||||||
(isHour == null ? 0 : isHour!.hashCode) +
|
(isHour == null ? 0 : isHour!.hashCode) +
|
||||||
(roundedValue == null ? 0 : roundedValue!.hashCode) +
|
(roundedValue == null ? 0 : roundedValue!.hashCode) +
|
||||||
@ -144,6 +149,7 @@ class AppConfigurationLink {
|
|||||||
(isSectionImageBackground == null
|
(isSectionImageBackground == null
|
||||||
? 0
|
? 0
|
||||||
: isSectionImageBackground!.hashCode) +
|
: isSectionImageBackground!.hashCode) +
|
||||||
|
(layoutMainPage == null ? 0 : layoutMainPage!.hashCode) +
|
||||||
(loaderImageId == null ? 0 : loaderImageId!.hashCode) +
|
(loaderImageId == null ? 0 : loaderImageId!.hashCode) +
|
||||||
(loaderImageUrl == null ? 0 : loaderImageUrl!.hashCode) +
|
(loaderImageUrl == null ? 0 : loaderImageUrl!.hashCode) +
|
||||||
(primaryColor == null ? 0 : primaryColor!.hashCode) +
|
(primaryColor == null ? 0 : primaryColor!.hashCode) +
|
||||||
@ -155,7 +161,7 @@ class AppConfigurationLink {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() =>
|
String toString() =>
|
||||||
'AppConfigurationLink[configurationId=$configurationId, applicationInstanceId=$applicationInstanceId, id=$id, order=$order, isActive=$isActive, gridColSpan=$gridColSpan, gridRowSpan=$gridRowSpan, isDate=$isDate, isHour=$isHour, roundedValue=$roundedValue, screenPercentageSectionsMainPage=$screenPercentageSectionsMainPage, isSectionImageBackground=$isSectionImageBackground, loaderImageId=$loaderImageId, loaderImageUrl=$loaderImageUrl, primaryColor=$primaryColor, secondaryColor=$secondaryColor, configuration=$configuration, applicationInstance=$applicationInstance, deviceId=$deviceId, device=$device]';
|
'AppConfigurationLink[configurationId=$configurationId, applicationInstanceId=$applicationInstanceId, id=$id, order=$order, isActive=$isActive, weightMasonryGrid=$weightMasonryGrid, isDate=$isDate, isHour=$isHour, roundedValue=$roundedValue, screenPercentageSectionsMainPage=$screenPercentageSectionsMainPage, isSectionImageBackground=$isSectionImageBackground, layoutMainPage=$layoutMainPage, loaderImageId=$loaderImageId, loaderImageUrl=$loaderImageUrl, primaryColor=$primaryColor, secondaryColor=$secondaryColor, configuration=$configuration, applicationInstance=$applicationInstance, deviceId=$deviceId, device=$device]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@ -176,15 +182,10 @@ class AppConfigurationLink {
|
|||||||
} else {
|
} else {
|
||||||
json[r'isActive'] = null;
|
json[r'isActive'] = null;
|
||||||
}
|
}
|
||||||
if (this.gridColSpan != null) {
|
if (this.weightMasonryGrid != null) {
|
||||||
json[r'gridColSpan'] = this.gridColSpan;
|
json[r'weightMasonryGrid'] = this.weightMasonryGrid;
|
||||||
} else {
|
} else {
|
||||||
json[r'gridColSpan'] = null;
|
json[r'weightMasonryGrid'] = null;
|
||||||
}
|
|
||||||
if (this.gridRowSpan != null) {
|
|
||||||
json[r'gridRowSpan'] = this.gridRowSpan;
|
|
||||||
} else {
|
|
||||||
json[r'gridRowSpan'] = null;
|
|
||||||
}
|
}
|
||||||
if (this.isDate != null) {
|
if (this.isDate != null) {
|
||||||
json[r'isDate'] = this.isDate;
|
json[r'isDate'] = this.isDate;
|
||||||
@ -212,6 +213,11 @@ class AppConfigurationLink {
|
|||||||
} else {
|
} else {
|
||||||
json[r'isSectionImageBackground'] = null;
|
json[r'isSectionImageBackground'] = null;
|
||||||
}
|
}
|
||||||
|
if (this.layoutMainPage != null) {
|
||||||
|
json[r'layoutMainPage'] = this.layoutMainPage;
|
||||||
|
} else {
|
||||||
|
json[r'layoutMainPage'] = null;
|
||||||
|
}
|
||||||
if (this.loaderImageId != null) {
|
if (this.loaderImageId != null) {
|
||||||
json[r'loaderImageId'] = this.loaderImageId;
|
json[r'loaderImageId'] = this.loaderImageId;
|
||||||
} else {
|
} else {
|
||||||
@ -282,8 +288,7 @@ class AppConfigurationLink {
|
|||||||
id: mapValueOfType<String>(json, r'id'),
|
id: mapValueOfType<String>(json, r'id'),
|
||||||
order: mapValueOfType<int>(json, r'order'),
|
order: mapValueOfType<int>(json, r'order'),
|
||||||
isActive: mapValueOfType<bool>(json, r'isActive'),
|
isActive: mapValueOfType<bool>(json, r'isActive'),
|
||||||
gridColSpan: mapValueOfType<int>(json, r'gridColSpan'),
|
weightMasonryGrid: mapValueOfType<int>(json, r'weightMasonryGrid'),
|
||||||
gridRowSpan: mapValueOfType<int>(json, r'gridRowSpan'),
|
|
||||||
isDate: mapValueOfType<bool>(json, r'isDate'),
|
isDate: mapValueOfType<bool>(json, r'isDate'),
|
||||||
isHour: mapValueOfType<bool>(json, r'isHour'),
|
isHour: mapValueOfType<bool>(json, r'isHour'),
|
||||||
roundedValue: mapValueOfType<int>(json, r'roundedValue'),
|
roundedValue: mapValueOfType<int>(json, r'roundedValue'),
|
||||||
@ -291,6 +296,7 @@ class AppConfigurationLink {
|
|||||||
mapValueOfType<int>(json, r'screenPercentageSectionsMainPage'),
|
mapValueOfType<int>(json, r'screenPercentageSectionsMainPage'),
|
||||||
isSectionImageBackground:
|
isSectionImageBackground:
|
||||||
mapValueOfType<bool>(json, r'isSectionImageBackground'),
|
mapValueOfType<bool>(json, r'isSectionImageBackground'),
|
||||||
|
layoutMainPage: LayoutMainPageType.fromJson(json[r'layoutMainPage']),
|
||||||
loaderImageId: mapValueOfType<String>(json, r'loaderImageId'),
|
loaderImageId: mapValueOfType<String>(json, r'loaderImageId'),
|
||||||
loaderImageUrl: mapValueOfType<String>(json, r'loaderImageUrl'),
|
loaderImageUrl: mapValueOfType<String>(json, r'loaderImageUrl'),
|
||||||
primaryColor: mapValueOfType<String>(json, r'primaryColor'),
|
primaryColor: mapValueOfType<String>(json, r'primaryColor'),
|
||||||
|
|||||||
@ -23,6 +23,7 @@ class AppConfigurationLinkApplicationInstance {
|
|||||||
this.loaderImageUrl,
|
this.loaderImageUrl,
|
||||||
this.primaryColor,
|
this.primaryColor,
|
||||||
this.secondaryColor,
|
this.secondaryColor,
|
||||||
|
this.layoutMainPage,
|
||||||
this.languages = const [],
|
this.languages = const [],
|
||||||
this.sectionEventId,
|
this.sectionEventId,
|
||||||
this.sectionEvent,
|
this.sectionEvent,
|
||||||
@ -49,6 +50,14 @@ class AppConfigurationLinkApplicationInstance {
|
|||||||
|
|
||||||
String? secondaryColor;
|
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<String>? languages;
|
List<String>? languages;
|
||||||
|
|
||||||
String? sectionEventId;
|
String? sectionEventId;
|
||||||
@ -77,6 +86,7 @@ class AppConfigurationLinkApplicationInstance {
|
|||||||
other.loaderImageUrl == loaderImageUrl &&
|
other.loaderImageUrl == loaderImageUrl &&
|
||||||
other.primaryColor == primaryColor &&
|
other.primaryColor == primaryColor &&
|
||||||
other.secondaryColor == secondaryColor &&
|
other.secondaryColor == secondaryColor &&
|
||||||
|
other.layoutMainPage == layoutMainPage &&
|
||||||
_deepEquality.equals(other.languages, languages) &&
|
_deepEquality.equals(other.languages, languages) &&
|
||||||
other.sectionEventId == sectionEventId &&
|
other.sectionEventId == sectionEventId &&
|
||||||
other.sectionEvent == sectionEvent &&
|
other.sectionEvent == sectionEvent &&
|
||||||
@ -95,6 +105,7 @@ class AppConfigurationLinkApplicationInstance {
|
|||||||
(loaderImageUrl == null ? 0 : loaderImageUrl!.hashCode) +
|
(loaderImageUrl == null ? 0 : loaderImageUrl!.hashCode) +
|
||||||
(primaryColor == null ? 0 : primaryColor!.hashCode) +
|
(primaryColor == null ? 0 : primaryColor!.hashCode) +
|
||||||
(secondaryColor == null ? 0 : secondaryColor!.hashCode) +
|
(secondaryColor == null ? 0 : secondaryColor!.hashCode) +
|
||||||
|
(layoutMainPage == null ? 0 : layoutMainPage!.hashCode) +
|
||||||
(languages == null ? 0 : languages!.hashCode) +
|
(languages == null ? 0 : languages!.hashCode) +
|
||||||
(sectionEventId == null ? 0 : sectionEventId!.hashCode) +
|
(sectionEventId == null ? 0 : sectionEventId!.hashCode) +
|
||||||
(sectionEvent == null ? 0 : sectionEvent!.hashCode) +
|
(sectionEvent == null ? 0 : sectionEvent!.hashCode) +
|
||||||
@ -102,7 +113,7 @@ class AppConfigurationLinkApplicationInstance {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() =>
|
String toString() =>
|
||||||
'AppConfigurationLinkApplicationInstance[instanceId=$instanceId, appType=$appType, id=$id, configurations=$configurations, mainImageId=$mainImageId, mainImageUrl=$mainImageUrl, loaderImageId=$loaderImageId, loaderImageUrl=$loaderImageUrl, primaryColor=$primaryColor, secondaryColor=$secondaryColor, languages=$languages, sectionEventId=$sectionEventId, sectionEvent=$sectionEvent, isAssistant=$isAssistant]';
|
'AppConfigurationLinkApplicationInstance[instanceId=$instanceId, appType=$appType, id=$id, configurations=$configurations, mainImageId=$mainImageId, mainImageUrl=$mainImageUrl, loaderImageId=$loaderImageId, loaderImageUrl=$loaderImageUrl, primaryColor=$primaryColor, secondaryColor=$secondaryColor, layoutMainPage=$layoutMainPage, languages=$languages, sectionEventId=$sectionEventId, sectionEvent=$sectionEvent, isAssistant=$isAssistant]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@ -148,6 +159,11 @@ class AppConfigurationLinkApplicationInstance {
|
|||||||
} else {
|
} else {
|
||||||
json[r'secondaryColor'] = null;
|
json[r'secondaryColor'] = null;
|
||||||
}
|
}
|
||||||
|
if (this.layoutMainPage != null) {
|
||||||
|
json[r'layoutMainPage'] = this.layoutMainPage;
|
||||||
|
} else {
|
||||||
|
json[r'layoutMainPage'] = null;
|
||||||
|
}
|
||||||
if (this.languages != null) {
|
if (this.languages != null) {
|
||||||
json[r'languages'] = this.languages;
|
json[r'languages'] = this.languages;
|
||||||
} else {
|
} else {
|
||||||
@ -203,6 +219,7 @@ class AppConfigurationLinkApplicationInstance {
|
|||||||
loaderImageUrl: mapValueOfType<String>(json, r'loaderImageUrl'),
|
loaderImageUrl: mapValueOfType<String>(json, r'loaderImageUrl'),
|
||||||
primaryColor: mapValueOfType<String>(json, r'primaryColor'),
|
primaryColor: mapValueOfType<String>(json, r'primaryColor'),
|
||||||
secondaryColor: mapValueOfType<String>(json, r'secondaryColor'),
|
secondaryColor: mapValueOfType<String>(json, r'secondaryColor'),
|
||||||
|
layoutMainPage: LayoutMainPageType.fromJson(json[r'layoutMainPage']),
|
||||||
languages: json[r'languages'] is Iterable
|
languages: json[r'languages'] is Iterable
|
||||||
? (json[r'languages'] as Iterable)
|
? (json[r'languages'] as Iterable)
|
||||||
.cast<String>()
|
.cast<String>()
|
||||||
|
|||||||
@ -19,8 +19,7 @@ class AppConfigurationLinkDTO {
|
|||||||
this.applicationInstanceId,
|
this.applicationInstanceId,
|
||||||
this.order,
|
this.order,
|
||||||
this.isActive,
|
this.isActive,
|
||||||
this.gridColSpan,
|
this.weightMasonryGrid,
|
||||||
this.gridRowSpan,
|
|
||||||
this.isDate,
|
this.isDate,
|
||||||
this.isHour,
|
this.isHour,
|
||||||
this.roundedValue,
|
this.roundedValue,
|
||||||
@ -28,6 +27,7 @@ class AppConfigurationLinkDTO {
|
|||||||
this.isSectionImageBackground,
|
this.isSectionImageBackground,
|
||||||
this.deviceId,
|
this.deviceId,
|
||||||
this.device,
|
this.device,
|
||||||
|
this.layoutMainPage,
|
||||||
this.loaderImageId,
|
this.loaderImageId,
|
||||||
this.loaderImageUrl,
|
this.loaderImageUrl,
|
||||||
this.primaryColor,
|
this.primaryColor,
|
||||||
@ -52,9 +52,7 @@ class AppConfigurationLinkDTO {
|
|||||||
///
|
///
|
||||||
bool? isActive;
|
bool? isActive;
|
||||||
|
|
||||||
int? gridColSpan;
|
int? weightMasonryGrid;
|
||||||
|
|
||||||
int? gridRowSpan;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
@ -88,6 +86,14 @@ class AppConfigurationLinkDTO {
|
|||||||
|
|
||||||
DeviceDTO? device;
|
DeviceDTO? device;
|
||||||
|
|
||||||
|
///
|
||||||
|
/// 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;
|
||||||
|
|
||||||
String? loaderImageId;
|
String? loaderImageId;
|
||||||
|
|
||||||
String? loaderImageUrl;
|
String? loaderImageUrl;
|
||||||
@ -106,8 +112,7 @@ class AppConfigurationLinkDTO {
|
|||||||
other.applicationInstanceId == applicationInstanceId &&
|
other.applicationInstanceId == applicationInstanceId &&
|
||||||
other.order == order &&
|
other.order == order &&
|
||||||
other.isActive == isActive &&
|
other.isActive == isActive &&
|
||||||
other.gridColSpan == gridColSpan &&
|
other.weightMasonryGrid == weightMasonryGrid &&
|
||||||
other.gridRowSpan == gridRowSpan &&
|
|
||||||
other.isDate == isDate &&
|
other.isDate == isDate &&
|
||||||
other.isHour == isHour &&
|
other.isHour == isHour &&
|
||||||
other.roundedValue == roundedValue &&
|
other.roundedValue == roundedValue &&
|
||||||
@ -116,6 +121,7 @@ class AppConfigurationLinkDTO {
|
|||||||
other.isSectionImageBackground == isSectionImageBackground &&
|
other.isSectionImageBackground == isSectionImageBackground &&
|
||||||
other.deviceId == deviceId &&
|
other.deviceId == deviceId &&
|
||||||
other.device == device &&
|
other.device == device &&
|
||||||
|
other.layoutMainPage == layoutMainPage &&
|
||||||
other.loaderImageId == loaderImageId &&
|
other.loaderImageId == loaderImageId &&
|
||||||
other.loaderImageUrl == loaderImageUrl &&
|
other.loaderImageUrl == loaderImageUrl &&
|
||||||
other.primaryColor == primaryColor &&
|
other.primaryColor == primaryColor &&
|
||||||
@ -130,8 +136,7 @@ class AppConfigurationLinkDTO {
|
|||||||
(applicationInstanceId == null ? 0 : applicationInstanceId!.hashCode) +
|
(applicationInstanceId == null ? 0 : applicationInstanceId!.hashCode) +
|
||||||
(order == null ? 0 : order!.hashCode) +
|
(order == null ? 0 : order!.hashCode) +
|
||||||
(isActive == null ? 0 : isActive!.hashCode) +
|
(isActive == null ? 0 : isActive!.hashCode) +
|
||||||
(gridColSpan == null ? 0 : gridColSpan!.hashCode) +
|
(weightMasonryGrid == null ? 0 : weightMasonryGrid!.hashCode) +
|
||||||
(gridRowSpan == null ? 0 : gridRowSpan!.hashCode) +
|
|
||||||
(isDate == null ? 0 : isDate!.hashCode) +
|
(isDate == null ? 0 : isDate!.hashCode) +
|
||||||
(isHour == null ? 0 : isHour!.hashCode) +
|
(isHour == null ? 0 : isHour!.hashCode) +
|
||||||
(roundedValue == null ? 0 : roundedValue!.hashCode) +
|
(roundedValue == null ? 0 : roundedValue!.hashCode) +
|
||||||
@ -143,6 +148,7 @@ class AppConfigurationLinkDTO {
|
|||||||
: isSectionImageBackground!.hashCode) +
|
: isSectionImageBackground!.hashCode) +
|
||||||
(deviceId == null ? 0 : deviceId!.hashCode) +
|
(deviceId == null ? 0 : deviceId!.hashCode) +
|
||||||
(device == null ? 0 : device!.hashCode) +
|
(device == null ? 0 : device!.hashCode) +
|
||||||
|
(layoutMainPage == null ? 0 : layoutMainPage!.hashCode) +
|
||||||
(loaderImageId == null ? 0 : loaderImageId!.hashCode) +
|
(loaderImageId == null ? 0 : loaderImageId!.hashCode) +
|
||||||
(loaderImageUrl == null ? 0 : loaderImageUrl!.hashCode) +
|
(loaderImageUrl == null ? 0 : loaderImageUrl!.hashCode) +
|
||||||
(primaryColor == null ? 0 : primaryColor!.hashCode) +
|
(primaryColor == null ? 0 : primaryColor!.hashCode) +
|
||||||
@ -150,7 +156,7 @@ class AppConfigurationLinkDTO {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() =>
|
String toString() =>
|
||||||
'AppConfigurationLinkDTO[id=$id, configurationId=$configurationId, configuration=$configuration, applicationInstanceId=$applicationInstanceId, order=$order, isActive=$isActive, gridColSpan=$gridColSpan, gridRowSpan=$gridRowSpan, isDate=$isDate, isHour=$isHour, roundedValue=$roundedValue, screenPercentageSectionsMainPage=$screenPercentageSectionsMainPage, isSectionImageBackground=$isSectionImageBackground, deviceId=$deviceId, device=$device, loaderImageId=$loaderImageId, loaderImageUrl=$loaderImageUrl, primaryColor=$primaryColor, secondaryColor=$secondaryColor]';
|
'AppConfigurationLinkDTO[id=$id, configurationId=$configurationId, configuration=$configuration, applicationInstanceId=$applicationInstanceId, order=$order, isActive=$isActive, weightMasonryGrid=$weightMasonryGrid, isDate=$isDate, isHour=$isHour, roundedValue=$roundedValue, screenPercentageSectionsMainPage=$screenPercentageSectionsMainPage, isSectionImageBackground=$isSectionImageBackground, deviceId=$deviceId, device=$device, layoutMainPage=$layoutMainPage, loaderImageId=$loaderImageId, loaderImageUrl=$loaderImageUrl, primaryColor=$primaryColor, secondaryColor=$secondaryColor]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@ -184,15 +190,10 @@ class AppConfigurationLinkDTO {
|
|||||||
} else {
|
} else {
|
||||||
json[r'isActive'] = null;
|
json[r'isActive'] = null;
|
||||||
}
|
}
|
||||||
if (this.gridColSpan != null) {
|
if (this.weightMasonryGrid != null) {
|
||||||
json[r'gridColSpan'] = this.gridColSpan;
|
json[r'weightMasonryGrid'] = this.weightMasonryGrid;
|
||||||
} else {
|
} else {
|
||||||
json[r'gridColSpan'] = null;
|
json[r'weightMasonryGrid'] = null;
|
||||||
}
|
|
||||||
if (this.gridRowSpan != null) {
|
|
||||||
json[r'gridRowSpan'] = this.gridRowSpan;
|
|
||||||
} else {
|
|
||||||
json[r'gridRowSpan'] = null;
|
|
||||||
}
|
}
|
||||||
if (this.isDate != null) {
|
if (this.isDate != null) {
|
||||||
json[r'isDate'] = this.isDate;
|
json[r'isDate'] = this.isDate;
|
||||||
@ -230,6 +231,11 @@ class AppConfigurationLinkDTO {
|
|||||||
} else {
|
} else {
|
||||||
json[r'device'] = null;
|
json[r'device'] = null;
|
||||||
}
|
}
|
||||||
|
if (this.layoutMainPage != null) {
|
||||||
|
json[r'layoutMainPage'] = this.layoutMainPage;
|
||||||
|
} else {
|
||||||
|
json[r'layoutMainPage'] = null;
|
||||||
|
}
|
||||||
if (this.loaderImageId != null) {
|
if (this.loaderImageId != null) {
|
||||||
json[r'loaderImageId'] = this.loaderImageId;
|
json[r'loaderImageId'] = this.loaderImageId;
|
||||||
} else {
|
} else {
|
||||||
@ -282,8 +288,7 @@ class AppConfigurationLinkDTO {
|
|||||||
mapValueOfType<String>(json, r'applicationInstanceId'),
|
mapValueOfType<String>(json, r'applicationInstanceId'),
|
||||||
order: mapValueOfType<int>(json, r'order'),
|
order: mapValueOfType<int>(json, r'order'),
|
||||||
isActive: mapValueOfType<bool>(json, r'isActive'),
|
isActive: mapValueOfType<bool>(json, r'isActive'),
|
||||||
gridColSpan: mapValueOfType<int>(json, r'gridColSpan'),
|
weightMasonryGrid: mapValueOfType<int>(json, r'weightMasonryGrid'),
|
||||||
gridRowSpan: mapValueOfType<int>(json, r'gridRowSpan'),
|
|
||||||
isDate: mapValueOfType<bool>(json, r'isDate'),
|
isDate: mapValueOfType<bool>(json, r'isDate'),
|
||||||
isHour: mapValueOfType<bool>(json, r'isHour'),
|
isHour: mapValueOfType<bool>(json, r'isHour'),
|
||||||
roundedValue: mapValueOfType<int>(json, r'roundedValue'),
|
roundedValue: mapValueOfType<int>(json, r'roundedValue'),
|
||||||
@ -293,6 +298,7 @@ class AppConfigurationLinkDTO {
|
|||||||
mapValueOfType<bool>(json, r'isSectionImageBackground'),
|
mapValueOfType<bool>(json, r'isSectionImageBackground'),
|
||||||
deviceId: mapValueOfType<String>(json, r'deviceId'),
|
deviceId: mapValueOfType<String>(json, r'deviceId'),
|
||||||
device: DeviceDTO.fromJson(json[r'device']),
|
device: DeviceDTO.fromJson(json[r'device']),
|
||||||
|
layoutMainPage: LayoutMainPageType.fromJson(json[r'layoutMainPage']),
|
||||||
loaderImageId: mapValueOfType<String>(json, r'loaderImageId'),
|
loaderImageId: mapValueOfType<String>(json, r'loaderImageId'),
|
||||||
loaderImageUrl: mapValueOfType<String>(json, r'loaderImageUrl'),
|
loaderImageUrl: mapValueOfType<String>(json, r'loaderImageUrl'),
|
||||||
primaryColor: mapValueOfType<String>(json, r'primaryColor'),
|
primaryColor: mapValueOfType<String>(json, r'primaryColor'),
|
||||||
|
|||||||
@ -23,6 +23,7 @@ class ApplicationInstance {
|
|||||||
this.loaderImageUrl,
|
this.loaderImageUrl,
|
||||||
this.primaryColor,
|
this.primaryColor,
|
||||||
this.secondaryColor,
|
this.secondaryColor,
|
||||||
|
this.layoutMainPage,
|
||||||
this.languages = const [],
|
this.languages = const [],
|
||||||
this.sectionEventId,
|
this.sectionEventId,
|
||||||
this.sectionEvent,
|
this.sectionEvent,
|
||||||
@ -49,6 +50,14 @@ class ApplicationInstance {
|
|||||||
|
|
||||||
String? secondaryColor;
|
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<String>? languages;
|
List<String>? languages;
|
||||||
|
|
||||||
String? sectionEventId;
|
String? sectionEventId;
|
||||||
@ -77,6 +86,7 @@ class ApplicationInstance {
|
|||||||
other.loaderImageUrl == loaderImageUrl &&
|
other.loaderImageUrl == loaderImageUrl &&
|
||||||
other.primaryColor == primaryColor &&
|
other.primaryColor == primaryColor &&
|
||||||
other.secondaryColor == secondaryColor &&
|
other.secondaryColor == secondaryColor &&
|
||||||
|
other.layoutMainPage == layoutMainPage &&
|
||||||
_deepEquality.equals(other.languages, languages) &&
|
_deepEquality.equals(other.languages, languages) &&
|
||||||
other.sectionEventId == sectionEventId &&
|
other.sectionEventId == sectionEventId &&
|
||||||
other.sectionEvent == sectionEvent &&
|
other.sectionEvent == sectionEvent &&
|
||||||
@ -95,6 +105,7 @@ class ApplicationInstance {
|
|||||||
(loaderImageUrl == null ? 0 : loaderImageUrl!.hashCode) +
|
(loaderImageUrl == null ? 0 : loaderImageUrl!.hashCode) +
|
||||||
(primaryColor == null ? 0 : primaryColor!.hashCode) +
|
(primaryColor == null ? 0 : primaryColor!.hashCode) +
|
||||||
(secondaryColor == null ? 0 : secondaryColor!.hashCode) +
|
(secondaryColor == null ? 0 : secondaryColor!.hashCode) +
|
||||||
|
(layoutMainPage == null ? 0 : layoutMainPage!.hashCode) +
|
||||||
(languages == null ? 0 : languages!.hashCode) +
|
(languages == null ? 0 : languages!.hashCode) +
|
||||||
(sectionEventId == null ? 0 : sectionEventId!.hashCode) +
|
(sectionEventId == null ? 0 : sectionEventId!.hashCode) +
|
||||||
(sectionEvent == null ? 0 : sectionEvent!.hashCode) +
|
(sectionEvent == null ? 0 : sectionEvent!.hashCode) +
|
||||||
@ -102,7 +113,7 @@ class ApplicationInstance {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() =>
|
String toString() =>
|
||||||
'ApplicationInstance[instanceId=$instanceId, appType=$appType, id=$id, configurations=$configurations, mainImageId=$mainImageId, mainImageUrl=$mainImageUrl, loaderImageId=$loaderImageId, loaderImageUrl=$loaderImageUrl, primaryColor=$primaryColor, secondaryColor=$secondaryColor, languages=$languages, sectionEventId=$sectionEventId, sectionEvent=$sectionEvent, isAssistant=$isAssistant]';
|
'ApplicationInstance[instanceId=$instanceId, appType=$appType, id=$id, configurations=$configurations, mainImageId=$mainImageId, mainImageUrl=$mainImageUrl, loaderImageId=$loaderImageId, loaderImageUrl=$loaderImageUrl, primaryColor=$primaryColor, secondaryColor=$secondaryColor, layoutMainPage=$layoutMainPage, languages=$languages, sectionEventId=$sectionEventId, sectionEvent=$sectionEvent, isAssistant=$isAssistant]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@ -148,6 +159,11 @@ class ApplicationInstance {
|
|||||||
} else {
|
} else {
|
||||||
json[r'secondaryColor'] = null;
|
json[r'secondaryColor'] = null;
|
||||||
}
|
}
|
||||||
|
if (this.layoutMainPage != null) {
|
||||||
|
json[r'layoutMainPage'] = this.layoutMainPage;
|
||||||
|
} else {
|
||||||
|
json[r'layoutMainPage'] = null;
|
||||||
|
}
|
||||||
if (this.languages != null) {
|
if (this.languages != null) {
|
||||||
json[r'languages'] = this.languages;
|
json[r'languages'] = this.languages;
|
||||||
} else {
|
} else {
|
||||||
@ -203,6 +219,7 @@ class ApplicationInstance {
|
|||||||
loaderImageUrl: mapValueOfType<String>(json, r'loaderImageUrl'),
|
loaderImageUrl: mapValueOfType<String>(json, r'loaderImageUrl'),
|
||||||
primaryColor: mapValueOfType<String>(json, r'primaryColor'),
|
primaryColor: mapValueOfType<String>(json, r'primaryColor'),
|
||||||
secondaryColor: mapValueOfType<String>(json, r'secondaryColor'),
|
secondaryColor: mapValueOfType<String>(json, r'secondaryColor'),
|
||||||
|
layoutMainPage: LayoutMainPageType.fromJson(json[r'layoutMainPage']),
|
||||||
languages: json[r'languages'] is Iterable
|
languages: json[r'languages'] is Iterable
|
||||||
? (json[r'languages'] as Iterable)
|
? (json[r'languages'] as Iterable)
|
||||||
.cast<String>()
|
.cast<String>()
|
||||||
|
|||||||
@ -23,6 +23,7 @@ class ApplicationInstanceDTO {
|
|||||||
this.loaderImageUrl,
|
this.loaderImageUrl,
|
||||||
this.primaryColor,
|
this.primaryColor,
|
||||||
this.secondaryColor,
|
this.secondaryColor,
|
||||||
|
this.layoutMainPage,
|
||||||
this.languages = const [],
|
this.languages = const [],
|
||||||
this.sectionEventId,
|
this.sectionEventId,
|
||||||
this.sectionEventDTO,
|
this.sectionEventDTO,
|
||||||
@ -56,6 +57,14 @@ class ApplicationInstanceDTO {
|
|||||||
|
|
||||||
String? secondaryColor;
|
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<String>? languages;
|
List<String>? languages;
|
||||||
|
|
||||||
String? sectionEventId;
|
String? sectionEventId;
|
||||||
@ -80,6 +89,7 @@ class ApplicationInstanceDTO {
|
|||||||
other.loaderImageUrl == loaderImageUrl &&
|
other.loaderImageUrl == loaderImageUrl &&
|
||||||
other.primaryColor == primaryColor &&
|
other.primaryColor == primaryColor &&
|
||||||
other.secondaryColor == secondaryColor &&
|
other.secondaryColor == secondaryColor &&
|
||||||
|
other.layoutMainPage == layoutMainPage &&
|
||||||
_deepEquality.equals(other.languages, languages) &&
|
_deepEquality.equals(other.languages, languages) &&
|
||||||
other.sectionEventId == sectionEventId &&
|
other.sectionEventId == sectionEventId &&
|
||||||
other.sectionEventDTO == sectionEventDTO &&
|
other.sectionEventDTO == sectionEventDTO &&
|
||||||
@ -99,6 +109,7 @@ class ApplicationInstanceDTO {
|
|||||||
(loaderImageUrl == null ? 0 : loaderImageUrl!.hashCode) +
|
(loaderImageUrl == null ? 0 : loaderImageUrl!.hashCode) +
|
||||||
(primaryColor == null ? 0 : primaryColor!.hashCode) +
|
(primaryColor == null ? 0 : primaryColor!.hashCode) +
|
||||||
(secondaryColor == null ? 0 : secondaryColor!.hashCode) +
|
(secondaryColor == null ? 0 : secondaryColor!.hashCode) +
|
||||||
|
(layoutMainPage == null ? 0 : layoutMainPage!.hashCode) +
|
||||||
(languages == null ? 0 : languages!.hashCode) +
|
(languages == null ? 0 : languages!.hashCode) +
|
||||||
(sectionEventId == null ? 0 : sectionEventId!.hashCode) +
|
(sectionEventId == null ? 0 : sectionEventId!.hashCode) +
|
||||||
(sectionEventDTO == null ? 0 : sectionEventDTO!.hashCode) +
|
(sectionEventDTO == null ? 0 : sectionEventDTO!.hashCode) +
|
||||||
@ -107,7 +118,7 @@ class ApplicationInstanceDTO {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() =>
|
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, sectionEventId=$sectionEventId, sectionEventDTO=$sectionEventDTO, isAssistant=$isAssistant, hasStats=$hasStats]';
|
'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, isAssistant=$isAssistant, hasStats=$hasStats]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@ -161,6 +172,11 @@ class ApplicationInstanceDTO {
|
|||||||
} else {
|
} else {
|
||||||
json[r'secondaryColor'] = null;
|
json[r'secondaryColor'] = null;
|
||||||
}
|
}
|
||||||
|
if (this.layoutMainPage != null) {
|
||||||
|
json[r'layoutMainPage'] = this.layoutMainPage;
|
||||||
|
} else {
|
||||||
|
json[r'layoutMainPage'] = null;
|
||||||
|
}
|
||||||
if (this.languages != null) {
|
if (this.languages != null) {
|
||||||
json[r'languages'] = this.languages;
|
json[r'languages'] = this.languages;
|
||||||
} else {
|
} else {
|
||||||
@ -221,6 +237,7 @@ class ApplicationInstanceDTO {
|
|||||||
loaderImageUrl: mapValueOfType<String>(json, r'loaderImageUrl'),
|
loaderImageUrl: mapValueOfType<String>(json, r'loaderImageUrl'),
|
||||||
primaryColor: mapValueOfType<String>(json, r'primaryColor'),
|
primaryColor: mapValueOfType<String>(json, r'primaryColor'),
|
||||||
secondaryColor: mapValueOfType<String>(json, r'secondaryColor'),
|
secondaryColor: mapValueOfType<String>(json, r'secondaryColor'),
|
||||||
|
layoutMainPage: LayoutMainPageType.fromJson(json[r'layoutMainPage']),
|
||||||
languages: json[r'languages'] is Iterable
|
languages: json[r'languages'] is Iterable
|
||||||
? (json[r'languages'] as Iterable)
|
? (json[r'languages'] as Iterable)
|
||||||
.cast<String>()
|
.cast<String>()
|
||||||
|
|||||||
102
manager_api_new/lib/model/layout_main_page_type.dart
Normal file
102
manager_api_new/lib/model/layout_main_page_type.dart
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
//
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
/// 0 = SimpleGrid 1 = MasonryGrid
|
||||||
|
class LayoutMainPageType {
|
||||||
|
/// Instantiate a new enum with the provided [value].
|
||||||
|
const LayoutMainPageType._(this.value);
|
||||||
|
|
||||||
|
/// The underlying value of this enum member.
|
||||||
|
final int value;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => value.toString();
|
||||||
|
|
||||||
|
int toJson() => value;
|
||||||
|
|
||||||
|
static const SimpleGrid = LayoutMainPageType._(0);
|
||||||
|
static const MasonryGrid = LayoutMainPageType._(1);
|
||||||
|
|
||||||
|
/// List of all possible values in this [enum][LayoutMainPageType].
|
||||||
|
static const values = <LayoutMainPageType>[
|
||||||
|
SimpleGrid,
|
||||||
|
MasonryGrid,
|
||||||
|
];
|
||||||
|
|
||||||
|
static LayoutMainPageType? fromJson(dynamic value) =>
|
||||||
|
LayoutMainPageTypeTypeTransformer().decode(value);
|
||||||
|
|
||||||
|
static List<LayoutMainPageType> listFromJson(
|
||||||
|
dynamic json, {
|
||||||
|
bool growable = false,
|
||||||
|
}) {
|
||||||
|
final result = <LayoutMainPageType>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = LayoutMainPageType.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Transformation class that can [encode] an instance of [LayoutMainPageType] to int,
|
||||||
|
/// and [decode] dynamic data back to [LayoutMainPageType].
|
||||||
|
class LayoutMainPageTypeTypeTransformer {
|
||||||
|
factory LayoutMainPageTypeTypeTransformer() =>
|
||||||
|
_instance ??= const LayoutMainPageTypeTypeTransformer._();
|
||||||
|
|
||||||
|
const LayoutMainPageTypeTypeTransformer._();
|
||||||
|
|
||||||
|
int encode(LayoutMainPageType data) => data.value;
|
||||||
|
|
||||||
|
/// Decodes a [dynamic value][data] to a LayoutMainPageType.
|
||||||
|
///
|
||||||
|
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
||||||
|
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
||||||
|
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
||||||
|
///
|
||||||
|
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
||||||
|
/// and users are still using an old app with the old code.
|
||||||
|
LayoutMainPageType? decode(dynamic data, {bool allowNull = true}) {
|
||||||
|
if (data != null) {
|
||||||
|
if(data.runtimeType == String) {
|
||||||
|
switch (data.toString()) {
|
||||||
|
case r'SimpleGrid': return LayoutMainPageType.SimpleGrid;
|
||||||
|
case r'MasonryGrid': return LayoutMainPageType.MasonryGrid;
|
||||||
|
default:
|
||||||
|
if (!allowNull) {
|
||||||
|
throw ArgumentError('Unknown enum value to decode: $data');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(data.runtimeType == int) {
|
||||||
|
switch (data) {
|
||||||
|
case 0: return LayoutMainPageType.SimpleGrid;
|
||||||
|
case 1: return LayoutMainPageType.MasonryGrid;
|
||||||
|
default:
|
||||||
|
if (!allowNull) {
|
||||||
|
throw ArgumentError('Unknown enum value to decode: $data');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Singleton [LayoutMainPageTypeTypeTransformer] instance.
|
||||||
|
static LayoutMainPageTypeTypeTransformer? _instance;
|
||||||
|
}
|
||||||
@ -91,6 +91,11 @@ void main() {
|
|||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// LayoutMainPageType layoutMainPage
|
||||||
|
test('to test the property `layoutMainPage`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
// List<String> languages (default value: const [])
|
// List<String> languages (default value: const [])
|
||||||
test('to test the property `languages`', () async {
|
test('to test the property `languages`', () async {
|
||||||
// TODO
|
// TODO
|
||||||
|
|||||||
@ -41,13 +41,8 @@ void main() {
|
|||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
// int gridColSpan
|
// int weightMasonryGrid
|
||||||
test('to test the property `gridColSpan`', () async {
|
test('to test the property `weightMasonryGrid`', () async {
|
||||||
// TODO
|
|
||||||
});
|
|
||||||
|
|
||||||
// int gridRowSpan
|
|
||||||
test('to test the property `gridRowSpan`', () async {
|
|
||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -41,13 +41,8 @@ void main() {
|
|||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
// int gridColSpan
|
// int weightMasonryGrid
|
||||||
test('to test the property `gridColSpan`', () async {
|
test('to test the property `weightMasonryGrid`', () async {
|
||||||
// TODO
|
|
||||||
});
|
|
||||||
|
|
||||||
// int gridRowSpan
|
|
||||||
test('to test the property `gridRowSpan`', () async {
|
|
||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -91,6 +91,11 @@ void main() {
|
|||||||
// TODO
|
// TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// LayoutMainPageType layoutMainPage
|
||||||
|
test('to test the property `layoutMainPage`', () async {
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
|
||||||
// List<String> languages (default value: const [])
|
// List<String> languages (default value: const [])
|
||||||
test('to test the property `languages`', () async {
|
test('to test the property `languages`', () async {
|
||||||
// TODO
|
// TODO
|
||||||
|
|||||||
17
manager_api_new/test/layout_main_page_type_test.dart
Normal file
17
manager_api_new/test/layout_main_page_type_test.dart
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// 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 LayoutMainPageType
|
||||||
|
void main() {
|
||||||
|
group('test LayoutMainPageType', () {});
|
||||||
|
}
|
||||||
@ -1 +0,0 @@
|
|||||||
export 'src/bento_layout.dart';
|
|
||||||
@ -1,94 +0,0 @@
|
|||||||
class BentoItem {
|
|
||||||
final String id;
|
|
||||||
final int colSpan;
|
|
||||||
final int rowSpan;
|
|
||||||
|
|
||||||
const BentoItem({required this.id, this.colSpan = 1, this.rowSpan = 1});
|
|
||||||
}
|
|
||||||
|
|
||||||
class BentoPlacement {
|
|
||||||
final String id;
|
|
||||||
final int col;
|
|
||||||
final int row;
|
|
||||||
final int colSpan;
|
|
||||||
final int rowSpan;
|
|
||||||
|
|
||||||
const BentoPlacement({
|
|
||||||
required this.id,
|
|
||||||
required this.col,
|
|
||||||
required this.row,
|
|
||||||
required this.colSpan,
|
|
||||||
required this.rowSpan,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
class BentoResult {
|
|
||||||
final List<BentoPlacement> placements;
|
|
||||||
final int rowCount;
|
|
||||||
|
|
||||||
const BentoResult({required this.placements, required this.rowCount});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Placement "bento" dense sur une grille de [columns] colonnes.
|
|
||||||
/// Chaque item occupe colSpan × rowSpan cellules ; on place chaque item à la
|
|
||||||
/// première cellule libre (parcours ligne par ligne) qui l'accueille — même
|
|
||||||
/// principe que `grid-auto-flow: dense` en CSS, pour que l'aperçu Flutter et le
|
|
||||||
/// rendu web restent cohérents.
|
|
||||||
BentoResult bentoLayout(List<BentoItem> items, int columns) {
|
|
||||||
final cols = columns < 1 ? 1 : columns;
|
|
||||||
final occupied = <List<bool>>[];
|
|
||||||
|
|
||||||
void ensureRow(int r) {
|
|
||||||
while (occupied.length <= r) {
|
|
||||||
occupied.add(List<bool>.filled(cols, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fits(int r, int c, int cs, int rs) {
|
|
||||||
if (c + cs > cols) return false;
|
|
||||||
for (var rr = r; rr < r + rs; rr++) {
|
|
||||||
ensureRow(rr);
|
|
||||||
for (var cc = c; cc < c + cs; cc++) {
|
|
||||||
if (occupied[rr][cc]) return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fill(int r, int c, int cs, int rs) {
|
|
||||||
for (var rr = r; rr < r + rs; rr++) {
|
|
||||||
ensureRow(rr);
|
|
||||||
for (var cc = c; cc < c + cs; cc++) {
|
|
||||||
occupied[rr][cc] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final placements = <BentoPlacement>[];
|
|
||||||
|
|
||||||
for (final item in items) {
|
|
||||||
final cs = item.colSpan.clamp(1, cols);
|
|
||||||
final rs = item.rowSpan < 1 ? 1 : item.rowSpan;
|
|
||||||
|
|
||||||
var placed = false;
|
|
||||||
var r = 0;
|
|
||||||
while (!placed) {
|
|
||||||
for (var c = 0; c + cs <= cols; c++) {
|
|
||||||
if (fits(r, c, cs, rs)) {
|
|
||||||
fill(r, c, cs, rs);
|
|
||||||
placements.add(BentoPlacement(id: item.id, col: c, row: r, colSpan: cs, rowSpan: rs));
|
|
||||||
placed = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!placed) r++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var rowCount = occupied.length;
|
|
||||||
while (rowCount > 0 && occupied[rowCount - 1].every((cell) => !cell)) {
|
|
||||||
rowCount--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return BentoResult(placements: placements, rowCount: rowCount);
|
|
||||||
}
|
|
||||||
@ -1,381 +0,0 @@
|
|||||||
# Generated by pub
|
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
|
||||||
packages:
|
|
||||||
_fe_analyzer_shared:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: _fe_analyzer_shared
|
|
||||||
sha256: f6526c100095fd63a916824e3da344bbbd50c25c8f56bcd52d13c59d35bbe422
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "104.0.0"
|
|
||||||
analyzer:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: analyzer
|
|
||||||
sha256: "6c6d751533496152e78f71c46ad001260c5e74e0f9ec1f1cbc165a0467c086d6"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "14.0.0"
|
|
||||||
args:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: args
|
|
||||||
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.7.0"
|
|
||||||
async:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: async
|
|
||||||
sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.13.1"
|
|
||||||
boolean_selector:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: boolean_selector
|
|
||||||
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.2"
|
|
||||||
cli_config:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: cli_config
|
|
||||||
sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.2.0"
|
|
||||||
collection:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: collection
|
|
||||||
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.19.1"
|
|
||||||
convert:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: convert
|
|
||||||
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.1.2"
|
|
||||||
coverage:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: coverage
|
|
||||||
sha256: "956a3de0725ca232ad353565a8290d3357592bf4250f6f298a185e2d949c5d3d"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.15.1"
|
|
||||||
crypto:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: crypto
|
|
||||||
sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.7"
|
|
||||||
file:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: file
|
|
||||||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "7.0.1"
|
|
||||||
frontend_server_client:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: frontend_server_client
|
|
||||||
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "4.0.0"
|
|
||||||
glob:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: glob
|
|
||||||
sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.3"
|
|
||||||
http_multi_server:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: http_multi_server
|
|
||||||
sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.2.2"
|
|
||||||
http_parser:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: http_parser
|
|
||||||
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "4.1.2"
|
|
||||||
io:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: io
|
|
||||||
sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.5"
|
|
||||||
logging:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: logging
|
|
||||||
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.0"
|
|
||||||
matcher:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: matcher
|
|
||||||
sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.12.20"
|
|
||||||
meta:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: meta
|
|
||||||
sha256: "307249ce4ff29d58a18e97f6345f539382eb9c9c29ecda628900f31de0443dd9"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.19.0"
|
|
||||||
mime:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: mime
|
|
||||||
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.0"
|
|
||||||
node_preamble:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: node_preamble
|
|
||||||
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.2"
|
|
||||||
package_config:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: package_config
|
|
||||||
sha256: ffcf4cf3d6c0b74ac43708d9f56625506e8a68aa935abe9d267a7330f320eb5d
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.0"
|
|
||||||
path:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: path
|
|
||||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.9.1"
|
|
||||||
pool:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: pool
|
|
||||||
sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.5.2"
|
|
||||||
pub_semver:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: pub_semver
|
|
||||||
sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.2.0"
|
|
||||||
shelf:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: shelf
|
|
||||||
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.4.2"
|
|
||||||
shelf_packages_handler:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: shelf_packages_handler
|
|
||||||
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.2"
|
|
||||||
shelf_static:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: shelf_static
|
|
||||||
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.3"
|
|
||||||
shelf_web_socket:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: shelf_web_socket
|
|
||||||
sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.0"
|
|
||||||
source_map_stack_trace:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: source_map_stack_trace
|
|
||||||
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.2"
|
|
||||||
source_maps:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: source_maps
|
|
||||||
sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.10.13"
|
|
||||||
source_span:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: source_span
|
|
||||||
sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.10.2"
|
|
||||||
stack_trace:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: stack_trace
|
|
||||||
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.12.1"
|
|
||||||
stream_channel:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: stream_channel
|
|
||||||
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.4"
|
|
||||||
string_scanner:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: string_scanner
|
|
||||||
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.4.1"
|
|
||||||
term_glyph:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: term_glyph
|
|
||||||
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.2.2"
|
|
||||||
test:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description:
|
|
||||||
name: test
|
|
||||||
sha256: "0d5ba5602ec3baa28c8ce365e1efc5575969c765f45c554a3e167dc7945b9c30"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.31.2"
|
|
||||||
test_api:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: test_api
|
|
||||||
sha256: "475610b2aa23c19687cce2961e44b0cc57cafe220f67c2b80201231b2a07fbe7"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.7.13"
|
|
||||||
test_core:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: test_core
|
|
||||||
sha256: a39c204a4fc7a7ccb04a2b985e359fda3cc37e45e0b8ac61c3fb1a05aa832132
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.6.19"
|
|
||||||
typed_data:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: typed_data
|
|
||||||
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.4.0"
|
|
||||||
vm_service:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: vm_service
|
|
||||||
sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "15.2.0"
|
|
||||||
watcher:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: watcher
|
|
||||||
sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.2.1"
|
|
||||||
web:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: web
|
|
||||||
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.1"
|
|
||||||
web_socket:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: web_socket
|
|
||||||
sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.1"
|
|
||||||
web_socket_channel:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: web_socket_channel
|
|
||||||
sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.3"
|
|
||||||
webkit_inspection_protocol:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: webkit_inspection_protocol
|
|
||||||
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.2.1"
|
|
||||||
yaml:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: yaml
|
|
||||||
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.1.3"
|
|
||||||
sdks:
|
|
||||||
dart: ">=3.11.0 <4.0.0"
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
name: myinfomate_layout
|
|
||||||
version: 1.0.0
|
|
||||||
description: Placement "bento" partagé (grille à spans colSpan x rowSpan, dense) pour les apps MyInfoMate.
|
|
||||||
environment:
|
|
||||||
sdk: '>=2.17.0 <4.0.0'
|
|
||||||
dev_dependencies:
|
|
||||||
test: ^1.24.0
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
import 'dart:convert';
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:myinfomate_layout/myinfomate_layout.dart';
|
|
||||||
import 'package:test/test.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
final fixturePath =
|
|
||||||
'${Directory.current.path}/test/fixtures/bento_layout_cases.json';
|
|
||||||
final fixture =
|
|
||||||
jsonDecode(File(fixturePath).readAsStringSync()) as Map<String, dynamic>;
|
|
||||||
final cases = fixture['cases'] as List<dynamic>;
|
|
||||||
|
|
||||||
for (final rawCase in cases) {
|
|
||||||
final testCase = rawCase as Map<String, dynamic>;
|
|
||||||
test(testCase['name'], () {
|
|
||||||
final items = (testCase['items'] as List<dynamic>)
|
|
||||||
.map((raw) => BentoItem(
|
|
||||||
id: raw['id'] as String,
|
|
||||||
colSpan: raw['colSpan'] as int,
|
|
||||||
rowSpan: raw['rowSpan'] as int,
|
|
||||||
))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
final result = bentoLayout(items, testCase['columns'] as int);
|
|
||||||
final expected = testCase['expected'] as Map<String, dynamic>;
|
|
||||||
|
|
||||||
expect(result.rowCount, expected['rowCount']);
|
|
||||||
|
|
||||||
final expectedPlacements = expected['placements'] as List<dynamic>;
|
|
||||||
expect(result.placements.length, expectedPlacements.length);
|
|
||||||
|
|
||||||
for (var i = 0; i < result.placements.length; i++) {
|
|
||||||
final p = result.placements[i];
|
|
||||||
final e = expectedPlacements[i] as Map<String, dynamic>;
|
|
||||||
expect(p.id, e['id']);
|
|
||||||
expect(p.col, e['col']);
|
|
||||||
expect(p.row, e['row']);
|
|
||||||
expect(p.colSpan, e['colSpan']);
|
|
||||||
expect(p.rowSpan, e['rowSpan']);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,72 +0,0 @@
|
|||||||
{
|
|
||||||
"cases": [
|
|
||||||
{
|
|
||||||
"name": "two_columns_uniform",
|
|
||||||
"columns": 2,
|
|
||||||
"items": [
|
|
||||||
{ "id": "a", "colSpan": 1, "rowSpan": 1 },
|
|
||||||
{ "id": "b", "colSpan": 1, "rowSpan": 1 },
|
|
||||||
{ "id": "c", "colSpan": 1, "rowSpan": 1 }
|
|
||||||
],
|
|
||||||
"expected": {
|
|
||||||
"rowCount": 2,
|
|
||||||
"placements": [
|
|
||||||
{ "id": "a", "col": 0, "row": 0, "colSpan": 1, "rowSpan": 1 },
|
|
||||||
{ "id": "b", "col": 1, "row": 0, "colSpan": 1, "rowSpan": 1 },
|
|
||||||
{ "id": "c", "col": 0, "row": 1, "colSpan": 1, "rowSpan": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "wide_then_dense_backfill",
|
|
||||||
"columns": 4,
|
|
||||||
"items": [
|
|
||||||
{ "id": "big", "colSpan": 2, "rowSpan": 2 },
|
|
||||||
{ "id": "a", "colSpan": 1, "rowSpan": 1 },
|
|
||||||
{ "id": "b", "colSpan": 1, "rowSpan": 1 },
|
|
||||||
{ "id": "c", "colSpan": 1, "rowSpan": 1 },
|
|
||||||
{ "id": "d", "colSpan": 1, "rowSpan": 1 }
|
|
||||||
],
|
|
||||||
"expected": {
|
|
||||||
"rowCount": 2,
|
|
||||||
"placements": [
|
|
||||||
{ "id": "big", "col": 0, "row": 0, "colSpan": 2, "rowSpan": 2 },
|
|
||||||
{ "id": "a", "col": 2, "row": 0, "colSpan": 1, "rowSpan": 1 },
|
|
||||||
{ "id": "b", "col": 3, "row": 0, "colSpan": 1, "rowSpan": 1 },
|
|
||||||
{ "id": "c", "col": 2, "row": 1, "colSpan": 1, "rowSpan": 1 },
|
|
||||||
{ "id": "d", "col": 3, "row": 1, "colSpan": 1, "rowSpan": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tall_card",
|
|
||||||
"columns": 2,
|
|
||||||
"items": [
|
|
||||||
{ "id": "tall", "colSpan": 1, "rowSpan": 2 },
|
|
||||||
{ "id": "a", "colSpan": 1, "rowSpan": 1 },
|
|
||||||
{ "id": "b", "colSpan": 1, "rowSpan": 1 }
|
|
||||||
],
|
|
||||||
"expected": {
|
|
||||||
"rowCount": 2,
|
|
||||||
"placements": [
|
|
||||||
{ "id": "tall", "col": 0, "row": 0, "colSpan": 1, "rowSpan": 2 },
|
|
||||||
{ "id": "a", "col": 1, "row": 0, "colSpan": 1, "rowSpan": 1 },
|
|
||||||
{ "id": "b", "col": 1, "row": 1, "colSpan": 1, "rowSpan": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "colspan_clamped_to_columns",
|
|
||||||
"columns": 2,
|
|
||||||
"items": [
|
|
||||||
{ "id": "wide", "colSpan": 3, "rowSpan": 1 }
|
|
||||||
],
|
|
||||||
"expected": {
|
|
||||||
"rowCount": 1,
|
|
||||||
"placements": [
|
|
||||||
{ "id": "wide", "col": 0, "row": 0, "colSpan": 2, "rowSpan": 1 }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1028,13 +1028,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.7"
|
version: "0.1.7"
|
||||||
myinfomate_layout:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
path: myinfomate_layout
|
|
||||||
relative: true
|
|
||||||
source: path
|
|
||||||
version: "1.0.0"
|
|
||||||
nested:
|
nested:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@ -67,8 +67,6 @@ dependencies:
|
|||||||
package_info_plus: ^4.2.0
|
package_info_plus: ^4.2.0
|
||||||
manager_api_new:
|
manager_api_new:
|
||||||
path: manager_api_new
|
path: manager_api_new
|
||||||
myinfomate_layout:
|
|
||||||
path: myinfomate_layout
|
|
||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user