Wip manager app, update to support web + fix section event layout
This commit is contained in:
parent
7669f38ed8
commit
2e8b82aa80
@ -15,81 +15,95 @@ import 'flag_decoration.dart';
|
|||||||
|
|
||||||
showMultiStringInput (String label, String modalLabel, bool isTitle, List<TranslationDTO> values, List<TranslationDTO> newValues, Function onGetResult, int maxLines, List<ResourceType>? resourceTypes, BuildContext context) { /*Function onSelect,*/
|
showMultiStringInput (String label, String modalLabel, bool isTitle, List<TranslationDTO> values, List<TranslationDTO> newValues, Function onGetResult, int maxLines, List<ResourceType>? resourceTypes, BuildContext context) { /*Function onSelect,*/
|
||||||
showDialog(
|
showDialog(
|
||||||
builder: (BuildContext context) => AlertDialog(
|
builder: (BuildContext context) => Dialog(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
||||||
),
|
),
|
||||||
title: Center(child: Text(modalLabel)),
|
child: SizedBox(
|
||||||
content: SingleChildScrollView(
|
width: 560,
|
||||||
child: Column(
|
child: Padding(
|
||||||
children: [
|
padding: const EdgeInsets.fromLTRB(24, 20, 24, 24),
|
||||||
Container(
|
child: Column(
|
||||||
child: SingleChildScrollView(
|
mainAxisSize: MainAxisSize.min,
|
||||||
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
children: [
|
||||||
children: getTranslations(context, Provider.of<AppContext>(context), label, isTitle, resourceTypes, newValues),
|
Center(child: Text(modalLabel, style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500))),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Flexible(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: getTranslations(context, Provider.of<AppContext>(context), label, isTitle, resourceTypes, newValues),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
/*Container(
|
||||||
|
width: 500,
|
||||||
|
height: 200,
|
||||||
|
child: TranslationTab(
|
||||||
|
translations: newValues,
|
||||||
|
maxLines: maxLines
|
||||||
|
)
|
||||||
|
),*/
|
||||||
|
/*Column(
|
||||||
|
children: showValues(newValues),
|
||||||
|
),*/
|
||||||
|
],
|
||||||
|
)
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 16),
|
||||||
/*Container(
|
Row(
|
||||||
width: 500,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
height: 200,
|
children: [
|
||||||
child: TranslationTab(
|
Padding(
|
||||||
translations: newValues,
|
padding: const EdgeInsets.all(8.0),
|
||||||
maxLines: maxLines
|
child: Container(
|
||||||
)
|
width: 180,
|
||||||
),*/
|
height: 70,
|
||||||
/*Column(
|
child: RoundedButton(
|
||||||
children: showValues(newValues),
|
text: "Annuler",
|
||||||
),*/
|
icon: Icons.undo,
|
||||||
],
|
color: kSecond,
|
||||||
)
|
press: () {
|
||||||
),
|
onGetResult(values);
|
||||||
actions: <Widget>[
|
Navigator.of(context).pop();
|
||||||
Row(
|
},
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
fontSize: 20,
|
||||||
children: [
|
),
|
||||||
Padding(
|
),
|
||||||
padding: const EdgeInsets.all(8.0),
|
),
|
||||||
child: Container(
|
Padding(
|
||||||
width: 180,
|
padding: const EdgeInsets.all(8.0),
|
||||||
height: 70,
|
child: Container(
|
||||||
child: RoundedButton(
|
width: 180,
|
||||||
text: "Annuler",
|
height: 70,
|
||||||
icon: Icons.undo,
|
child: RoundedButton(
|
||||||
color: kSecond,
|
text: "Valider",
|
||||||
press: () {
|
icon: Icons.check,
|
||||||
onGetResult(values);
|
color: kPrimaryColor,
|
||||||
Navigator.of(context).pop();
|
textColor: kWhite,
|
||||||
},
|
press: () {
|
||||||
fontSize: 20,
|
Function deepEq = const DeepCollectionEquality().equals;
|
||||||
),
|
if (!deepEq(values, newValues)) {
|
||||||
|
onGetResult(newValues);
|
||||||
|
}
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
fontSize: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
Padding(
|
),
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Container(
|
|
||||||
width: 180,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: "Valider",
|
|
||||||
icon: Icons.check,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
textColor: kWhite,
|
|
||||||
press: () {
|
|
||||||
Function deepEq = const DeepCollectionEquality().equals;
|
|
||||||
if (!deepEq(values, newValues)) {
|
|
||||||
onGetResult(newValues);
|
|
||||||
}
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
), context: context
|
), context: context
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,28 +38,24 @@ class _ResourceTabState extends State<ResourceTab> with SingleTickerProviderStat
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Column(
|
||||||
body: Container(
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
child: Column(
|
children: [
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
TabBar(
|
||||||
children: [
|
unselectedLabelColor: Colors.black,
|
||||||
TabBar(
|
labelColor: kPrimaryColor,
|
||||||
unselectedLabelColor: Colors.black,
|
tabs: tabsToShow,
|
||||||
labelColor: kPrimaryColor,
|
controller: _tabController,
|
||||||
tabs: tabsToShow,
|
indicatorSize: TabBarIndicatorSize.tab,
|
||||||
controller: _tabController,
|
indicatorColor: kPrimaryColor,
|
||||||
indicatorSize: TabBarIndicatorSize.tab,
|
|
||||||
indicatorColor: kPrimaryColor,
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: TabBarView(
|
|
||||||
children: getContent(widget.resourceDTO, widget.onFileUpload, widget.onFileUploadWeb),
|
|
||||||
controller: _tabController,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
Expanded(
|
||||||
|
child: TabBarView(
|
||||||
|
children: getContent(widget.resourceDTO, widget.onFileUpload, widget.onFileUploadWeb),
|
||||||
|
controller: _tabController,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import 'package:auto_size_text/auto_size_text.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:manager_app/Components/rounded_input_field.dart';
|
import 'package:manager_app/Components/rounded_input_field.dart';
|
||||||
import 'package:manager_app/constants.dart';
|
import 'package:manager_app/constants.dart';
|
||||||
@ -28,37 +27,29 @@ class StringInputContainer extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Size size = MediaQuery.of(context).size;
|
return Row(
|
||||||
|
children: [
|
||||||
return Container(
|
Text(
|
||||||
child: Row(
|
label,
|
||||||
children: [
|
style: const TextStyle(
|
||||||
Align(
|
fontWeight: FontWeight.w400,
|
||||||
alignment: AlignmentDirectional.centerStart,
|
fontSize: 16,
|
||||||
child: Text(
|
|
||||||
label,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
fontSize: 16,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Padding(
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Container(
|
child: RoundedInputField(
|
||||||
width: isUrl ? size.width *0.6 : isSmall ? size.width *0.1 : size.width *0.25,
|
color: color!,
|
||||||
child: RoundedInputField(
|
textColor: kBlack,
|
||||||
color: color!,
|
fontSize: fontSizeText,
|
||||||
textColor: kBlack,
|
initialValue: initialValue,
|
||||||
fontSize: fontSizeText,
|
onChanged: onChanged,
|
||||||
initialValue: initialValue,
|
maxLength: maxLength,
|
||||||
onChanged: onChanged,
|
|
||||||
maxLength: maxLength,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ dynamic showAddConfigurationLink (BuildContext mainContext, AppContext appContex
|
|||||||
future: getConfigurations(appContext),
|
future: getConfigurations(appContext),
|
||||||
builder: (context, AsyncSnapshot<dynamic> snapshot) {
|
builder: (context, AsyncSnapshot<dynamic> snapshot) {
|
||||||
if (snapshot.connectionState == ConnectionState.done) {
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
List<ConfigurationDTO> configurations = snapshot.data;
|
List<ConfigurationDTO> configurations = snapshot.data ?? [];
|
||||||
|
|
||||||
// filter by already linked
|
// filter by already linked
|
||||||
configurations = configurations.where((c) => !configurationIds.contains(c.id)).toList();
|
configurations = configurations.where((c) => !configurationIds.contains(c.id)).toList();
|
||||||
@ -61,7 +61,7 @@ dynamic showAddConfigurationLink (BuildContext mainContext, AppContext appContex
|
|||||||
shape: BoxShape.rectangle,
|
shape: BoxShape.rectangle,
|
||||||
color: kWhite,
|
color: kWhite,
|
||||||
borderRadius: BorderRadius.circular(10.0),
|
borderRadius: BorderRadius.circular(10.0),
|
||||||
image: configuration.imageId != null
|
image: configuration.imageSource != null
|
||||||
? DecorationImage(
|
? DecorationImage(
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
image: NetworkImage(configuration.imageSource!),
|
image: NetworkImage(configuration.imageSource!),
|
||||||
@ -77,9 +77,9 @@ dynamic showAddConfigurationLink (BuildContext mainContext, AppContext appContex
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
title: Text(configuration.label!, style: Theme.of(context).textTheme.titleMedium),
|
title: Text(configuration.label ?? '', style: Theme.of(context).textTheme.titleMedium),
|
||||||
subtitle: Text(configuration.dateCreation!.toString(), style: Theme.of(context).textTheme.bodyMedium),
|
subtitle: Text(configuration.dateCreation?.toString() ?? '', style: Theme.of(context).textTheme.bodyMedium),
|
||||||
trailing: Text(configuration.languages!.toString(), style: Theme.of(context).textTheme.bodyMedium),
|
trailing: Text(configuration.languages?.toString() ?? '', style: Theme.of(context).textTheme.bodyMedium),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
|
|||||||
@ -23,7 +23,10 @@ import 'package:provider/provider.dart';
|
|||||||
|
|
||||||
class AppConfigurationLinkScreen extends StatefulWidget {
|
class AppConfigurationLinkScreen extends StatefulWidget {
|
||||||
final ApplicationInstanceDTO applicationInstanceDTO;
|
final ApplicationInstanceDTO applicationInstanceDTO;
|
||||||
AppConfigurationLinkScreen({Key? key, required this.applicationInstanceDTO}) : super(key: key);
|
final bool showAssistant;
|
||||||
|
final String? configTitle;
|
||||||
|
final String? appUpdatedLabel;
|
||||||
|
AppConfigurationLinkScreen({Key? key, required this.applicationInstanceDTO, this.showAssistant = true, this.configTitle, this.appUpdatedLabel}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_AppConfigurationLinkScreenState createState() => _AppConfigurationLinkScreenState();
|
_AppConfigurationLinkScreenState createState() => _AppConfigurationLinkScreenState();
|
||||||
@ -43,11 +46,11 @@ class _AppConfigurationLinkScreenState extends State<AppConfigurationLinkScreen>
|
|||||||
final appContext = Provider.of<AppContext>(context);
|
final appContext = Provider.of<AppContext>(context);
|
||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
ManagerAppContext managerAppContext = appContext.getContext() as ManagerAppContext;
|
ManagerAppContext managerAppContext = appContext.getContext() as ManagerAppContext;
|
||||||
|
final appUpdatedMsg = widget.appUpdatedLabel ?? AppLocalizations.of(context)!.appUpdatedSuccess;
|
||||||
|
|
||||||
_generalInfoCard() {
|
_generalInfoCard() {
|
||||||
|
|
||||||
var elementWidth = 400.0;
|
const elementHeight = 125.0;
|
||||||
var elementHeight = 125.0;
|
|
||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
margin: const EdgeInsets.symmetric(vertical: 8),
|
margin: const EdgeInsets.symmetric(vertical: 8),
|
||||||
@ -61,7 +64,10 @@ class _AppConfigurationLinkScreenState extends State<AppConfigurationLinkScreen>
|
|||||||
Text(AppLocalizations.of(context)!.generalInfo, style: TextStyle(fontWeight: FontWeight.w500, fontSize: 21)),
|
Text(AppLocalizations.of(context)!.generalInfo, style: TextStyle(fontWeight: FontWeight.w500, fontSize: 21)),
|
||||||
SizedBox(height: 8),
|
SizedBox(height: 8),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Center(
|
child: LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
final elementWidth = (constraints.maxWidth < 420) ? constraints.maxWidth : 400.0;
|
||||||
|
return Center(
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
alignment: WrapAlignment.center,
|
alignment: WrapAlignment.center,
|
||||||
@ -92,7 +98,7 @@ class _AppConfigurationLinkScreenState extends State<AppConfigurationLinkScreen>
|
|||||||
// automatic save
|
// automatic save
|
||||||
var applicationLink = await updateApplicationInstance(appContext, _applicationInstanceDTO);
|
var applicationLink = await updateApplicationInstance(appContext, _applicationInstanceDTO);
|
||||||
if(applicationLink != null) {
|
if(applicationLink != null) {
|
||||||
showNotification(kSuccess, kWhite, AppLocalizations.of(context)!.appUpdatedSuccess, context, null);
|
showNotification(kSuccess, kWhite, appUpdatedMsg, context, null);
|
||||||
/*setState(() {
|
/*setState(() {
|
||||||
|
|
||||||
});*/
|
});*/
|
||||||
@ -123,7 +129,7 @@ class _AppConfigurationLinkScreenState extends State<AppConfigurationLinkScreen>
|
|||||||
// automatic save
|
// automatic save
|
||||||
var applicationLink = await updateApplicationInstance(appContext, _applicationInstanceDTO);
|
var applicationLink = await updateApplicationInstance(appContext, _applicationInstanceDTO);
|
||||||
if(applicationLink != null) {
|
if(applicationLink != null) {
|
||||||
showNotification(kSuccess, kWhite, AppLocalizations.of(context)!.appUpdatedSuccess, context, null);
|
showNotification(kSuccess, kWhite, appUpdatedMsg, context, null);
|
||||||
/*setState(() {
|
/*setState(() {
|
||||||
|
|
||||||
});*/
|
});*/
|
||||||
@ -146,7 +152,7 @@ class _AppConfigurationLinkScreenState extends State<AppConfigurationLinkScreen>
|
|||||||
// automatic save
|
// automatic save
|
||||||
var applicationLink = await updateApplicationInstance(appContext, _applicationInstanceDTO);
|
var applicationLink = await updateApplicationInstance(appContext, _applicationInstanceDTO);
|
||||||
if(applicationLink != null) {
|
if(applicationLink != null) {
|
||||||
showNotification(kSuccess, kWhite, AppLocalizations.of(context)!.appUpdatedSuccess, context, null);
|
showNotification(kSuccess, kWhite, appUpdatedMsg, context, null);
|
||||||
/*setState(() {
|
/*setState(() {
|
||||||
|
|
||||||
});*/
|
});*/
|
||||||
@ -169,7 +175,7 @@ class _AppConfigurationLinkScreenState extends State<AppConfigurationLinkScreen>
|
|||||||
// automatic save
|
// automatic save
|
||||||
var applicationLink = await updateApplicationInstance(appContext, _applicationInstanceDTO);
|
var applicationLink = await updateApplicationInstance(appContext, _applicationInstanceDTO);
|
||||||
if(applicationLink != null) {
|
if(applicationLink != null) {
|
||||||
showNotification(kSuccess, kWhite, AppLocalizations.of(context)!.appUpdatedSuccess, context, null);
|
showNotification(kSuccess, kWhite, appUpdatedMsg, context, null);
|
||||||
/*setState(() {
|
/*setState(() {
|
||||||
|
|
||||||
});*/
|
});*/
|
||||||
@ -194,7 +200,7 @@ class _AppConfigurationLinkScreenState extends State<AppConfigurationLinkScreen>
|
|||||||
// automatic save
|
// automatic save
|
||||||
var applicationLink = await updateApplicationInstance(appContext, _applicationInstanceDTO);
|
var applicationLink = await updateApplicationInstance(appContext, _applicationInstanceDTO);
|
||||||
if(applicationLink != null) {
|
if(applicationLink != null) {
|
||||||
showNotification(kSuccess, kWhite, AppLocalizations.of(context)!.appUpdatedSuccess, context, null);
|
showNotification(kSuccess, kWhite, appUpdatedMsg, context, null);
|
||||||
/*setState(() {
|
/*setState(() {
|
||||||
|
|
||||||
});*/
|
});*/
|
||||||
@ -222,7 +228,7 @@ class _AppConfigurationLinkScreenState extends State<AppConfigurationLinkScreen>
|
|||||||
// automatic save
|
// automatic save
|
||||||
var applicationLink = await updateApplicationInstance(appContext, _applicationInstanceDTO);
|
var applicationLink = await updateApplicationInstance(appContext, _applicationInstanceDTO);
|
||||||
if(applicationLink != null) {
|
if(applicationLink != null) {
|
||||||
showNotification(kSuccess, kWhite, AppLocalizations.of(context)!.appUpdatedSuccess, context, null);
|
showNotification(kSuccess, kWhite, appUpdatedMsg, context, null);
|
||||||
/*setState(() {
|
/*setState(() {
|
||||||
|
|
||||||
});*/
|
});*/
|
||||||
@ -274,7 +280,7 @@ class _AppConfigurationLinkScreenState extends State<AppConfigurationLinkScreen>
|
|||||||
// automatic save
|
// automatic save
|
||||||
var applicationLink = await updateApplicationInstance(appContext, _applicationInstanceDTO);
|
var applicationLink = await updateApplicationInstance(appContext, _applicationInstanceDTO);
|
||||||
if(applicationLink != null) {
|
if(applicationLink != null) {
|
||||||
showNotification(kSuccess, kWhite, AppLocalizations.of(context)!.appUpdatedSuccess, context, null);
|
showNotification(kSuccess, kWhite, appUpdatedMsg, context, null);
|
||||||
//setState(() {
|
//setState(() {
|
||||||
_applicationInstanceDTO.sectionEventDTO = applicationLink.sectionEventDTO;
|
_applicationInstanceDTO.sectionEventDTO = applicationLink.sectionEventDTO;
|
||||||
//_applicationInstanceDTO = applicationLink;
|
//_applicationInstanceDTO = applicationLink;
|
||||||
@ -287,7 +293,7 @@ class _AppConfigurationLinkScreenState extends State<AppConfigurationLinkScreen>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
// Assistant IA — visible uniquement si l'instance a la fonctionnalité
|
// Assistant IA — visible uniquement si l'instance a la fonctionnalité
|
||||||
if (managerAppContext.instanceDTO?.isAssistant == true)
|
if (widget.showAssistant && managerAppContext.instanceDTO?.isAssistant == true)
|
||||||
Container(
|
Container(
|
||||||
width: elementWidth,
|
width: elementWidth,
|
||||||
height: elementHeight,
|
height: elementHeight,
|
||||||
@ -312,7 +318,7 @@ class _AppConfigurationLinkScreenState extends State<AppConfigurationLinkScreen>
|
|||||||
localSetState(() {
|
localSetState(() {
|
||||||
_applicationInstanceDTO.isAssistant = applicationLink.isAssistant;
|
_applicationInstanceDTO.isAssistant = applicationLink.isAssistant;
|
||||||
});
|
});
|
||||||
showNotification(kSuccess, kWhite, AppLocalizations.of(context)!.appUpdatedSuccess, context, null);
|
showNotification(kSuccess, kWhite, appUpdatedMsg, context, null);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showNotification(kError, kWhite, AppLocalizations.of(context)!.errorOccurred, context, null);
|
showNotification(kError, kWhite, AppLocalizations.of(context)!.errorOccurred, context, null);
|
||||||
@ -328,8 +334,10 @@ class _AppConfigurationLinkScreenState extends State<AppConfigurationLinkScreen>
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -348,7 +356,7 @@ class _AppConfigurationLinkScreenState extends State<AppConfigurationLinkScreen>
|
|||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Text(AppLocalizations.of(context)!.phoneConfigTitle, style: TextStyle(fontWeight: FontWeight.w500, fontSize: 21)),
|
child: Text(widget.configTitle ?? AppLocalizations.of(context)!.phoneConfigTitle, style: TextStyle(fontWeight: FontWeight.w500, fontSize: 21)),
|
||||||
),
|
),
|
||||||
appConfigurationLinks != null ? Padding(
|
appConfigurationLinks != null ? Padding(
|
||||||
padding: const EdgeInsets.only(left: 32, right: 32, top: 75),
|
padding: const EdgeInsets.only(left: 32, right: 32, top: 75),
|
||||||
@ -376,7 +384,7 @@ class _AppConfigurationLinkScreenState extends State<AppConfigurationLinkScreen>
|
|||||||
// TODO use order put method
|
// TODO use order put method
|
||||||
var result = await updateAppConfigurationOrder(appContext, updatedList);
|
var result = await updateAppConfigurationOrder(appContext, updatedList);
|
||||||
localSetState(() {});
|
localSetState(() {});
|
||||||
showNotification(kSuccess, kWhite, AppLocalizations.of(context)!.appUpdatedSuccess, context, null);
|
showNotification(kSuccess, kWhite, appUpdatedMsg, context, null);
|
||||||
},
|
},
|
||||||
actions: [
|
actions: [
|
||||||
(BuildContext context, int index, AppConfigurationLinkDTO link) {
|
(BuildContext context, int index, AppConfigurationLinkDTO link) {
|
||||||
|
|||||||
194
lib/Screens/Applications/web_app_screen.dart
Normal file
194
lib/Screens/Applications/web_app_screen.dart
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:manager_app/Screens/Applications/app_configuration_link_screen.dart';
|
||||||
|
import 'package:manager_app/app_context.dart';
|
||||||
|
import 'package:manager_app/Components/message_notification.dart';
|
||||||
|
import 'package:manager_app/constants.dart';
|
||||||
|
import 'package:manager_app/Models/managerContext.dart';
|
||||||
|
import 'package:manager_api_new/api.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class WebInstanceLoader extends StatefulWidget {
|
||||||
|
const WebInstanceLoader({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<WebInstanceLoader> createState() => _WebInstanceLoaderState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _WebInstanceLoaderState extends State<WebInstanceLoader> {
|
||||||
|
bool _creating = false;
|
||||||
|
String? _error;
|
||||||
|
ApplicationInstanceDTO? _instance;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) => _init());
|
||||||
|
}
|
||||||
|
|
||||||
|
void _init() {
|
||||||
|
final appContext = Provider.of<AppContext>(context, listen: false);
|
||||||
|
final managerCtx = appContext.getContext() as ManagerAppContext;
|
||||||
|
final existing = managerCtx.instanceDTO?.applicationInstanceDTOs
|
||||||
|
?.firstWhereOrNull((ai) => ai.appType == AppType.Web);
|
||||||
|
if (existing != null) {
|
||||||
|
setState(() => _instance = existing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _create() async {
|
||||||
|
final appContext = Provider.of<AppContext>(context, listen: false);
|
||||||
|
final managerCtx = appContext.getContext() as ManagerAppContext;
|
||||||
|
final instanceDTO = managerCtx.instanceDTO!;
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_creating = true;
|
||||||
|
_error = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
final newInstance = ApplicationInstanceDTO(
|
||||||
|
instanceId: instanceDTO.id,
|
||||||
|
appType: AppType.Web,
|
||||||
|
languages: ['fr'],
|
||||||
|
layoutMainPage: LayoutMainPageType.MasonryGrid,
|
||||||
|
isAssistant: false,
|
||||||
|
isStatistic: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
final created = await managerCtx.clientAPI!.applicationInstanceApi!
|
||||||
|
.applicationInstanceCreate(newInstance);
|
||||||
|
|
||||||
|
if (created != null) {
|
||||||
|
instanceDTO.applicationInstanceDTOs = [...?instanceDTO.applicationInstanceDTOs, created];
|
||||||
|
setState(() => _instance = created);
|
||||||
|
} else {
|
||||||
|
setState(() => _error = 'La création a échoué (réponse vide)');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
setState(() => _error = e.toString());
|
||||||
|
} finally {
|
||||||
|
setState(() => _creating = false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (_instance != null) {
|
||||||
|
return WebAppScreen(applicationInstanceDTO: _instance!);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'L\'application web n\'est pas encore initialisée.',
|
||||||
|
style: TextStyle(color: kBodyTextColor),
|
||||||
|
),
|
||||||
|
if (_error != null) ...[
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text(_error!, style: TextStyle(color: kError, fontSize: 12)),
|
||||||
|
],
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
_creating
|
||||||
|
? const CircularProgressIndicator()
|
||||||
|
: ElevatedButton(
|
||||||
|
onPressed: _create,
|
||||||
|
child: const Text('Initialiser l\'application web'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WebAppScreen extends StatelessWidget {
|
||||||
|
final ApplicationInstanceDTO applicationInstanceDTO;
|
||||||
|
|
||||||
|
const WebAppScreen({Key? key, required this.applicationInstanceDTO}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final appContext = Provider.of<AppContext>(context);
|
||||||
|
final managerAppContext = appContext.getContext() as ManagerAppContext;
|
||||||
|
final instanceDTO = managerAppContext.instanceDTO;
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
if (instanceDTO?.webSlug != null || instanceDTO?.publicApiKey != null)
|
||||||
|
Card(
|
||||||
|
margin: const EdgeInsets.fromLTRB(0, 0, 0, 8),
|
||||||
|
color: kWhite,
|
||||||
|
elevation: 0,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('Accès web', style: TextStyle(fontWeight: FontWeight.w500, fontSize: 21)),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
_InfoRow(
|
||||||
|
label: 'URL visiteurs',
|
||||||
|
value: 'app.myinfomate.be/${instanceDTO?.webSlug ?? '—'}',
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
_InfoRow(
|
||||||
|
label: 'Clé publique API',
|
||||||
|
value: instanceDTO?.publicApiKey ?? '—',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: AppConfigurationLinkScreen(
|
||||||
|
applicationInstanceDTO: applicationInstanceDTO,
|
||||||
|
showAssistant: false,
|
||||||
|
configTitle: 'Contenu de l\'application web',
|
||||||
|
appUpdatedLabel: 'Application web mise à jour',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _InfoRow extends StatelessWidget {
|
||||||
|
final String label;
|
||||||
|
final String value;
|
||||||
|
|
||||||
|
const _InfoRow({required this.label, required this.value});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(label, style: TextStyle(fontSize: 12, color: kBodyTextColor)),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Text(
|
||||||
|
value,
|
||||||
|
style: TextStyle(fontSize: 13, fontFamily: 'monospace', color: kPrimaryColor),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.copy_outlined, size: 18, color: kPrimaryColor),
|
||||||
|
tooltip: 'Copier',
|
||||||
|
onPressed: () {
|
||||||
|
Clipboard.setData(ClipboardData(text: value));
|
||||||
|
showNotification(kSuccess, kWhite, 'Copié !', context, null);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -431,13 +431,14 @@ class _EventConfigState extends State<EventConfig> {
|
|||||||
Divider(),
|
Divider(),
|
||||||
// --- Parcours ---
|
// --- Parcours ---
|
||||||
if (eventDTO.id != null)
|
if (eventDTO.id != null)
|
||||||
ParcoursConfig(
|
SizedBox(
|
||||||
initialValue: const [],
|
height: 500,
|
||||||
parentId: eventDTO.id!,
|
child: ParcoursConfig(
|
||||||
isEvent: true,
|
initialValue: const [],
|
||||||
onChanged: (paths) {
|
parentId: eventDTO.id!,
|
||||||
// parcours are managed independently, no DTO update needed here
|
isEvent: true,
|
||||||
},
|
onChanged: (paths) {},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@ -25,112 +25,163 @@ void showEditSubSection(SectionDTO subSectionDTO, Function getResult, AppContext
|
|||||||
|
|
||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
showDialog(
|
showDialog(
|
||||||
builder: (BuildContext context) => AlertDialog(
|
builder: (BuildContext context) => Dialog(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
||||||
),
|
),
|
||||||
content: Container(
|
child: SizedBox(
|
||||||
width: size.width *0.85,
|
width: MediaQuery.of(context).size.width * 0.85,
|
||||||
child: SingleChildScrollView(
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(24, 20, 24, 24),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Modifier sous section", style: new TextStyle(fontSize: 25, fontWeight: FontWeight.w400)),
|
Flexible(
|
||||||
Column(
|
child: SingleChildScrollView(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
child: Column(
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
Text("Modifier sous section", style: new TextStyle(fontSize: 25, fontWeight: FontWeight.w400)),
|
||||||
height: 100,
|
Column(
|
||||||
child: StringInputContainer(
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
label: "Nom :",
|
children: [
|
||||||
initialValue: subSectionDTO.label,
|
Row(
|
||||||
onChanged: (String name) {
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
subSectionDTO.label = name;
|
children: [
|
||||||
},
|
SizedBox(
|
||||||
),
|
height: 100,
|
||||||
),
|
child: StringInputContainer(
|
||||||
ResourceInputContainer(
|
label: "Nom :",
|
||||||
label: "Image :",
|
initialValue: subSectionDTO.label,
|
||||||
initialValue: subSectionDTO.imageId,
|
onChanged: (String name) {
|
||||||
color: kPrimaryColor,
|
subSectionDTO.label = name;
|
||||||
onChanged: (ResourceDTO resource) {
|
},
|
||||||
if(resource.id == null) {
|
),
|
||||||
subSectionDTO.imageId = null;
|
),
|
||||||
subSectionDTO.imageSource = null;
|
ResourceInputContainer(
|
||||||
} else {
|
label: "Image :",
|
||||||
subSectionDTO.imageId = resource.id;
|
initialValue: subSectionDTO.imageId,
|
||||||
subSectionDTO.imageSource = resource.url;
|
color: kPrimaryColor,
|
||||||
}
|
onChanged: (ResourceDTO resource) {
|
||||||
},
|
if(resource.id == null) {
|
||||||
isSmall: true,
|
subSectionDTO.imageId = null;
|
||||||
|
subSectionDTO.imageSource = null;
|
||||||
|
} else {
|
||||||
|
subSectionDTO.imageId = resource.id;
|
||||||
|
subSectionDTO.imageSource = resource.url;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isSmall: true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: size.height * 0.1,
|
||||||
|
width: double.infinity,
|
||||||
|
constraints: BoxConstraints(minHeight: 50),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
constraints: BoxConstraints(minHeight: 50, maxHeight: 80),
|
||||||
|
child: MultiStringInputContainer(
|
||||||
|
label: AppLocalizations.of(context)!.displayTitleLabel,
|
||||||
|
modalLabel: "Titre",
|
||||||
|
fontSize: 20,
|
||||||
|
isHTML: true,
|
||||||
|
color: kPrimaryColor,
|
||||||
|
initialValue: subSectionDTO.title != null ? subSectionDTO.title! : [],
|
||||||
|
onGetResult: (value) {
|
||||||
|
if (subSectionDTO.title != value) {
|
||||||
|
subSectionDTO.title = value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
maxLines: 1,
|
||||||
|
isTitle: true
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
constraints: BoxConstraints(minHeight: 50, maxHeight: 80),
|
||||||
|
child: MultiStringInputContainer(
|
||||||
|
label: AppLocalizations.of(context)!.displayedDescriptionLabel,
|
||||||
|
modalLabel: "Description",
|
||||||
|
fontSize: 20,
|
||||||
|
isHTML: true,
|
||||||
|
color: kPrimaryColor,
|
||||||
|
initialValue: subSectionDTO.description != null ? subSectionDTO.description! : [],
|
||||||
|
isMandatory: false,
|
||||||
|
onGetResult: (value) {
|
||||||
|
if (subSectionDTO.description != value) {
|
||||||
|
subSectionDTO.description = value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
maxLines: 1,
|
||||||
|
isTitle: false
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: kWhite,
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
border: Border.all(width: 0.5, color: kSecond)
|
||||||
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
child: getSpecificData(
|
||||||
|
subSectionDTO,
|
||||||
|
rawSubSectionData,
|
||||||
|
rawSubSectionData,
|
||||||
|
appContext,
|
||||||
|
(updatedData) {
|
||||||
|
updatedRawSubSectionData = updatedData;
|
||||||
|
}, context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Container(
|
),
|
||||||
height: size.height * 0.1,
|
),
|
||||||
width: double.infinity,
|
const SizedBox(height: 16),
|
||||||
constraints: BoxConstraints(minHeight: 50),
|
Row(
|
||||||
child: Row(
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
children: [
|
||||||
children: [
|
Align(
|
||||||
Container(
|
alignment: AlignmentDirectional.bottomEnd,
|
||||||
constraints: BoxConstraints(minHeight: 50, maxHeight: 80),
|
child: Container(
|
||||||
child: MultiStringInputContainer(
|
width: 175,
|
||||||
label: AppLocalizations.of(context)!.displayTitleLabel,
|
height: 70,
|
||||||
modalLabel: "Titre",
|
child: RoundedButton(
|
||||||
fontSize: 20,
|
text: "Annuler",
|
||||||
isHTML: true,
|
icon: Icons.undo,
|
||||||
color: kPrimaryColor,
|
color: kSecond,
|
||||||
initialValue: subSectionDTO.title != null ? subSectionDTO.title! : [],
|
press: () {
|
||||||
onGetResult: (value) {
|
Navigator.of(context).pop();
|
||||||
if (subSectionDTO.title != value) {
|
},
|
||||||
subSectionDTO.title = value;
|
fontSize: 20,
|
||||||
}
|
),
|
||||||
},
|
|
||||||
maxLines: 1,
|
|
||||||
isTitle: true
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
constraints: BoxConstraints(minHeight: 50, maxHeight: 80),
|
|
||||||
child: MultiStringInputContainer(
|
|
||||||
label: AppLocalizations.of(context)!.displayedDescriptionLabel,
|
|
||||||
modalLabel: "Description",
|
|
||||||
fontSize: 20,
|
|
||||||
isHTML: true,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
initialValue: subSectionDTO.description != null ? subSectionDTO.description! : [],
|
|
||||||
isMandatory: false,
|
|
||||||
onGetResult: (value) {
|
|
||||||
if (subSectionDTO.description != value) {
|
|
||||||
subSectionDTO.description = value;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
maxLines: 1,
|
|
||||||
isTitle: false
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: kWhite,
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
border: Border.all(width: 0.5, color: kSecond)
|
|
||||||
),
|
),
|
||||||
child: Padding(
|
),
|
||||||
padding: const EdgeInsets.all(10.0),
|
Align(
|
||||||
child: getSpecificData(
|
alignment: AlignmentDirectional.bottomEnd,
|
||||||
subSectionDTO,
|
child: Container(
|
||||||
rawSubSectionData,
|
width: subSectionDTO != null ? 220: 150,
|
||||||
rawSubSectionData,
|
height: 70,
|
||||||
appContext,
|
child: RoundedButton(
|
||||||
(updatedData) {
|
text: "Sauvegarder",
|
||||||
updatedRawSubSectionData = updatedData;
|
icon: Icons.check,
|
||||||
}, context),
|
color: kPrimaryColor,
|
||||||
|
textColor: kWhite,
|
||||||
|
press: () {
|
||||||
|
getResult(updatedRawSubSectionData);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
fontSize: 20,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -139,47 +190,6 @@ void showEditSubSection(SectionDTO subSectionDTO, Function getResult, AppContext
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: <Widget>[
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: 175,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: "Annuler",
|
|
||||||
icon: Icons.undo,
|
|
||||||
color: kSecond,
|
|
||||||
press: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: subSectionDTO != null ? 220: 150,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: "Sauvegarder",
|
|
||||||
icon: Icons.check,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
textColor: kWhite,
|
|
||||||
press: () {
|
|
||||||
getResult(updatedRawSubSectionData);
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
), context: context
|
), context: context
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,109 +45,119 @@ Future<OrderedTranslationAndResourceDTO?> showNewOrUpdatePDFFile(OrderedTranslat
|
|||||||
|
|
||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
var result = await showDialog(
|
var result = await showDialog(
|
||||||
builder: (BuildContext dialogContext) => AlertDialog(
|
builder: (BuildContext dialogContext) => Dialog(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
||||||
),
|
),
|
||||||
content: Container(
|
child: SizedBox(
|
||||||
width: size.width *0.5,
|
width: 560,
|
||||||
child: SingleChildScrollView(
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(24, 20, 24, 24),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(text, style: new TextStyle(fontSize: 25, fontWeight: FontWeight.w400)),
|
Flexible(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(text, style: new TextStyle(fontSize: 25, fontWeight: FontWeight.w400)),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: size.height * 0.2,
|
||||||
|
constraints: BoxConstraints(minHeight: 50, maxHeight: 80),
|
||||||
|
child: MultiStringInputAndResourceContainer(
|
||||||
|
label: "Fichier et titre pdf :",
|
||||||
|
modalLabel: "Fichier et titre pdf",
|
||||||
|
fontSize: 20,
|
||||||
|
color: kPrimaryColor,
|
||||||
|
initialValue: pdfFileDTO.translationAndResourceDTOs != null ? pdfFileDTO.translationAndResourceDTOs! : [],
|
||||||
|
resourceTypes: [ResourceType.Pdf],
|
||||||
|
onGetResult: (value) {
|
||||||
|
if (pdfFileDTO.translationAndResourceDTOs != value) {
|
||||||
|
pdfFileDTO.translationAndResourceDTOs = value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
maxLines: 1,
|
||||||
|
isTitle: true
|
||||||
|
),
|
||||||
|
),
|
||||||
|
/*Container(
|
||||||
|
height: size.height * 0.2,
|
||||||
|
constraints: BoxConstraints(minHeight: 50, maxHeight: 80),
|
||||||
|
child: ResourceInputContainer(
|
||||||
|
label: AppLocalizations.of(context)!.categoryIconLabel,
|
||||||
|
initialValue: categorieDTO.iconResourceId,
|
||||||
|
color: kPrimaryColor,
|
||||||
|
onChanged: (ResourceDTO resource) {
|
||||||
|
if(resource.id == null) {
|
||||||
|
categorieDTO.iconResourceId = null;
|
||||||
|
categorieDTO.iconUrl = null;
|
||||||
|
} else {
|
||||||
|
categorieDTO.iconResourceId = resource.id;
|
||||||
|
categorieDTO.iconUrl = resource.url;
|
||||||
|
print("Icône catégorieIcône catégorie");
|
||||||
|
print(categorieDTO);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isSmall: true
|
||||||
|
),
|
||||||
|
),*/
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Align(
|
||||||
height: size.height * 0.2,
|
alignment: AlignmentDirectional.bottomEnd,
|
||||||
constraints: BoxConstraints(minHeight: 50, maxHeight: 80),
|
child: Container(
|
||||||
child: MultiStringInputAndResourceContainer(
|
width: 175,
|
||||||
label: "Fichier et titre pdf :",
|
height: 70,
|
||||||
modalLabel: "Fichier et titre pdf",
|
child: RoundedButton(
|
||||||
fontSize: 20,
|
text: "Annuler",
|
||||||
color: kPrimaryColor,
|
icon: Icons.undo,
|
||||||
initialValue: pdfFileDTO.translationAndResourceDTOs != null ? pdfFileDTO.translationAndResourceDTOs! : [],
|
color: kSecond,
|
||||||
resourceTypes: [ResourceType.Pdf],
|
press: () {
|
||||||
onGetResult: (value) {
|
Navigator.pop(dialogContext);
|
||||||
if (pdfFileDTO.translationAndResourceDTOs != value) {
|
|
||||||
pdfFileDTO.translationAndResourceDTOs = value;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
maxLines: 1,
|
fontSize: 20,
|
||||||
isTitle: true
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
/*Container(
|
Align(
|
||||||
height: size.height * 0.2,
|
alignment: AlignmentDirectional.bottomEnd,
|
||||||
constraints: BoxConstraints(minHeight: 50, maxHeight: 80),
|
child: Container(
|
||||||
child: ResourceInputContainer(
|
width: inputPdfFile != null ? 220: 150,
|
||||||
label: AppLocalizations.of(context)!.categoryIconLabel,
|
height: 70,
|
||||||
initialValue: categorieDTO.iconResourceId,
|
child: RoundedButton(
|
||||||
color: kPrimaryColor,
|
text: inputPdfFile != null ? AppLocalizations.of(context)!.save : AppLocalizations.of(context)!.create,
|
||||||
onChanged: (ResourceDTO resource) {
|
icon: Icons.check,
|
||||||
if(resource.id == null) {
|
color: kPrimaryColor,
|
||||||
categorieDTO.iconResourceId = null;
|
textColor: kWhite,
|
||||||
categorieDTO.iconUrl = null;
|
press: () {
|
||||||
} else {
|
if(pdfFileDTO.translationAndResourceDTOs != null && pdfFileDTO.translationAndResourceDTOs!.isNotEmpty)
|
||||||
categorieDTO.iconResourceId = resource.id;
|
{
|
||||||
categorieDTO.iconUrl = resource.url;
|
Navigator.pop(dialogContext, pdfFileDTO);
|
||||||
print("Icône catégorieIcône catégorie");
|
}
|
||||||
print(categorieDTO);
|
},
|
||||||
}
|
fontSize: 20,
|
||||||
},
|
|
||||||
isSmall: true
|
|
||||||
),
|
),
|
||||||
),*/
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: <Widget>[
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: 175,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: "Annuler",
|
|
||||||
icon: Icons.undo,
|
|
||||||
color: kSecond,
|
|
||||||
press: () {
|
|
||||||
Navigator.pop(dialogContext);
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: inputPdfFile != null ? 220: 150,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: inputPdfFile != null ? AppLocalizations.of(context)!.save : AppLocalizations.of(context)!.create,
|
|
||||||
icon: Icons.check,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
textColor: kWhite,
|
|
||||||
press: () {
|
|
||||||
if(pdfFileDTO.translationAndResourceDTOs != null && pdfFileDTO.translationAndResourceDTOs!.isNotEmpty)
|
|
||||||
{
|
|
||||||
Navigator.pop(dialogContext, pdfFileDTO);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
), context: context
|
), context: context
|
||||||
);
|
);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@ -34,88 +34,142 @@ Future<QuestionDTO?> showNewOrUpdateQuestionQuizz(QuestionDTO? inputQuestionDTO,
|
|||||||
|
|
||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
var result = await showDialog(
|
var result = await showDialog(
|
||||||
builder: (BuildContext dialogContext) => AlertDialog(
|
builder: (BuildContext dialogContext) => Dialog(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
||||||
),
|
),
|
||||||
content: Container(
|
child: SizedBox(
|
||||||
width: size.width *0.5,
|
width: 560,
|
||||||
child: SingleChildScrollView(
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(24, 20, 24, 24),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(text, style: new TextStyle(fontSize: 25, fontWeight: FontWeight.w400)),
|
Flexible(
|
||||||
Column(
|
child: SingleChildScrollView(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
child: Column(
|
||||||
children: [
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
Container(
|
children: [
|
||||||
height: size.height*0.25,
|
Text(text, style: new TextStyle(fontSize: 25, fontWeight: FontWeight.w400)),
|
||||||
constraints: BoxConstraints(minHeight: 100, maxHeight: 150),
|
Column(
|
||||||
child: Row(
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
children: [
|
||||||
children: [
|
Container(
|
||||||
ResourceInputContainer(
|
height: size.height*0.25,
|
||||||
label: AppLocalizations.of(context)!.backgroundImageLabel,
|
constraints: BoxConstraints(minHeight: 100, maxHeight: 150),
|
||||||
initialValue: questionDTO.imageBackgroundResourceId,
|
child: Row(
|
||||||
color: kPrimaryColor,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
onChanged: (ResourceDTO resource) {
|
children: [
|
||||||
if(resource.id == null) {
|
ResourceInputContainer(
|
||||||
questionDTO.imageBackgroundResourceId = null;
|
label: AppLocalizations.of(context)!.backgroundImageLabel,
|
||||||
questionDTO.imageBackgroundResourceUrl = null;
|
initialValue: questionDTO.imageBackgroundResourceId,
|
||||||
questionDTO.imageBackgroundResourceType = null;
|
color: kPrimaryColor,
|
||||||
} else {
|
onChanged: (ResourceDTO resource) {
|
||||||
questionDTO.imageBackgroundResourceId = resource.id;
|
if(resource.id == null) {
|
||||||
questionDTO.imageBackgroundResourceUrl = resource.url;
|
questionDTO.imageBackgroundResourceId = null;
|
||||||
questionDTO.imageBackgroundResourceType = resource.type;
|
questionDTO.imageBackgroundResourceUrl = null;
|
||||||
}
|
questionDTO.imageBackgroundResourceType = null;
|
||||||
},
|
} else {
|
||||||
isSmall: true
|
questionDTO.imageBackgroundResourceId = resource.id;
|
||||||
),
|
questionDTO.imageBackgroundResourceUrl = resource.url;
|
||||||
Container(
|
questionDTO.imageBackgroundResourceType = resource.type;
|
||||||
//color: Colors.orangeAccent,
|
}
|
||||||
height: size.height * 0.15,
|
},
|
||||||
constraints: BoxConstraints(minHeight: 50, maxHeight: 80),
|
isSmall: true
|
||||||
child: MultiStringInputAndResourceContainer(
|
),
|
||||||
label: AppLocalizations.of(context)!.questionInputLabel,
|
Container(
|
||||||
modalLabel: AppLocalizations.of(context)!.questionLabel,
|
//color: Colors.orangeAccent,
|
||||||
fontSize: 20,
|
height: size.height * 0.15,
|
||||||
color: kPrimaryColor,
|
constraints: BoxConstraints(minHeight: 50, maxHeight: 80),
|
||||||
resourceTypes: [ResourceType.Image, ResourceType.ImageUrl, ResourceType.Video, ResourceType.VideoUrl, ResourceType.Audio],
|
child: MultiStringInputAndResourceContainer(
|
||||||
initialValue: questionDTO.label != null ? questionDTO.label! : [],
|
label: AppLocalizations.of(context)!.questionInputLabel,
|
||||||
onGetResult: (value) {
|
modalLabel: AppLocalizations.of(context)!.questionLabel,
|
||||||
if (questionDTO.label != value) {
|
fontSize: 20,
|
||||||
questionDTO.label = value;
|
color: kPrimaryColor,
|
||||||
}
|
resourceTypes: [ResourceType.Image, ResourceType.ImageUrl, ResourceType.Video, ResourceType.VideoUrl, ResourceType.Audio],
|
||||||
},
|
initialValue: questionDTO.label != null ? questionDTO.label! : [],
|
||||||
maxLines: 1,
|
onGetResult: (value) {
|
||||||
isTitle: true
|
if (questionDTO.label != value) {
|
||||||
|
questionDTO.label = value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
maxLines: 1,
|
||||||
|
isTitle: true
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
Container(
|
||||||
],
|
height: size.height * 0.33,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: kWhite,
|
||||||
|
//color: Colors.green,
|
||||||
|
shape: BoxShape.rectangle,
|
||||||
|
border: Border.all(width: 1.5, color: kSecond),
|
||||||
|
borderRadius: BorderRadius.circular(10.0),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: kSecond,
|
||||||
|
spreadRadius: 0.5,
|
||||||
|
blurRadius: 5,
|
||||||
|
offset: Offset(0, 1.5), // changes position of shadow
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: QuizzResponseList(
|
||||||
|
responses: questionDTO.responses!,
|
||||||
|
onChanged: (List<ResponseDTO> responsesOutput) {
|
||||||
|
questionDTO.responses = responsesOutput;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
Align(
|
||||||
|
alignment: AlignmentDirectional.bottomEnd,
|
||||||
|
child: Container(
|
||||||
|
width: 175,
|
||||||
|
height: 70,
|
||||||
|
child: RoundedButton(
|
||||||
|
text: AppLocalizations.of(context)!.cancel,
|
||||||
|
icon: Icons.undo,
|
||||||
|
color: kSecond,
|
||||||
|
press: () {
|
||||||
|
Navigator.pop(dialogContext);
|
||||||
|
},
|
||||||
|
fontSize: 20,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
Align(
|
||||||
height: size.height * 0.33,
|
alignment: AlignmentDirectional.bottomEnd,
|
||||||
decoration: BoxDecoration(
|
child: Container(
|
||||||
color: kWhite,
|
width: inputQuestionDTO != null ? 220: 150,
|
||||||
//color: Colors.green,
|
height: 70,
|
||||||
shape: BoxShape.rectangle,
|
child: RoundedButton(
|
||||||
border: Border.all(width: 1.5, color: kSecond),
|
text: inputQuestionDTO != null ? AppLocalizations.of(context)!.save : AppLocalizations.of(context)!.create,
|
||||||
borderRadius: BorderRadius.circular(10.0),
|
icon: Icons.check,
|
||||||
boxShadow: [
|
color: kPrimaryColor,
|
||||||
BoxShadow(
|
textColor: kWhite,
|
||||||
color: kSecond,
|
press: () {
|
||||||
spreadRadius: 0.5,
|
if(!questionDTO.label!.any((label) => label.value == null || label.value!.trim() == "")) {
|
||||||
blurRadius: 5,
|
Navigator.pop(dialogContext, questionDTO);
|
||||||
offset: Offset(0, 1.5), // changes position of shadow
|
} else {
|
||||||
),
|
showNotification(kPrimaryColor, kWhite, AppLocalizations.of(context)!.translationIncomplete, context, null);
|
||||||
],
|
}
|
||||||
),
|
},
|
||||||
child: QuizzResponseList(
|
fontSize: 20,
|
||||||
responses: questionDTO.responses!,
|
),
|
||||||
onChanged: (List<ResponseDTO> responsesOutput) {
|
|
||||||
questionDTO.responses = responsesOutput;
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -124,50 +178,6 @@ Future<QuestionDTO?> showNewOrUpdateQuestionQuizz(QuestionDTO? inputQuestionDTO,
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: <Widget>[
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: 175,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: AppLocalizations.of(context)!.cancel,
|
|
||||||
icon: Icons.undo,
|
|
||||||
color: kSecond,
|
|
||||||
press: () {
|
|
||||||
Navigator.pop(dialogContext);
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: inputQuestionDTO != null ? 220: 150,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: inputQuestionDTO != null ? AppLocalizations.of(context)!.save : AppLocalizations.of(context)!.create,
|
|
||||||
icon: Icons.check,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
textColor: kWhite,
|
|
||||||
press: () {
|
|
||||||
if(!questionDTO.label!.any((label) => label.value == null || label.value!.trim() == "")) {
|
|
||||||
Navigator.pop(dialogContext, questionDTO);
|
|
||||||
} else {
|
|
||||||
showNotification(kPrimaryColor, kWhite, AppLocalizations.of(context)!.translationIncomplete, context, null);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
), context: context
|
), context: context
|
||||||
);
|
);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@ -34,129 +34,138 @@ Future<ContentDTO?> showNewOrUpdateContentSlider(ContentDTO? inputContentDTO, Ap
|
|||||||
|
|
||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
var result = await showDialog(
|
var result = await showDialog(
|
||||||
builder: (BuildContext dialogContext) => AlertDialog(
|
builder: (BuildContext dialogContext) => Dialog(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
||||||
),
|
),
|
||||||
content: Container(
|
child: SizedBox(
|
||||||
width: size.width *0.35,
|
width: 480,
|
||||||
constraints: BoxConstraints(minWidth: 300),
|
child: Padding(
|
||||||
child: SingleChildScrollView(
|
padding: const EdgeInsets.fromLTRB(24, 20, 24, 24),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text("Ressource", style: new TextStyle(fontSize: 25, fontWeight: FontWeight.w400)),
|
Flexible(
|
||||||
Column(
|
child: SingleChildScrollView(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text("Ressource", style: new TextStyle(fontSize: 25, fontWeight: FontWeight.w400)),
|
||||||
|
Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Center(
|
||||||
|
child: ResourceInputContainer(
|
||||||
|
label: "Ressource :",
|
||||||
|
initialValue: contentDTO.resourceId,
|
||||||
|
color: kPrimaryColor,
|
||||||
|
fontSize: 20,
|
||||||
|
inResourceTypes: [ResourceType.Image, ResourceType.ImageUrl, ResourceType.Video, ResourceType.VideoUrl, ResourceType.Audio],
|
||||||
|
onChanged: (ResourceDTO resource) {
|
||||||
|
if(resource.id == null) {
|
||||||
|
contentDTO.resourceId = null;
|
||||||
|
contentDTO.resource = null;
|
||||||
|
} else {
|
||||||
|
contentDTO.resourceId = resource.id;
|
||||||
|
contentDTO.resource = resource;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isSmall: true
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if(showTitle || showDescription)
|
||||||
|
Container(
|
||||||
|
height: size.height * 0.3,
|
||||||
|
width: double.infinity,
|
||||||
|
constraints: BoxConstraints(minHeight: 200),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
MultiStringInputContainer(
|
||||||
|
label: AppLocalizations.of(context)!.displayTitleLabel,
|
||||||
|
modalLabel: "Titre",
|
||||||
|
fontSize: 20,
|
||||||
|
isHTML: true,
|
||||||
|
color: kPrimaryColor,
|
||||||
|
initialValue: contentDTO.title != null ? contentDTO.title! : [],
|
||||||
|
onGetResult: (value) {
|
||||||
|
if (contentDTO.title != value) {
|
||||||
|
contentDTO.title = value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
maxLines: 1,
|
||||||
|
isTitle: true
|
||||||
|
),
|
||||||
|
MultiStringInputContainer(
|
||||||
|
label: AppLocalizations.of(context)!.displayedDescriptionLabel,
|
||||||
|
modalLabel: "Description",
|
||||||
|
fontSize: 20,
|
||||||
|
isHTML: true,
|
||||||
|
color: kPrimaryColor,
|
||||||
|
initialValue: contentDTO.description != null ? contentDTO.description! : [],
|
||||||
|
isMandatory: false,
|
||||||
|
onGetResult: (value) {
|
||||||
|
if (contentDTO.description != value) {
|
||||||
|
contentDTO.description = value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
maxLines: 1,
|
||||||
|
isTitle: false
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
Center(
|
Align(
|
||||||
child: ResourceInputContainer(
|
alignment: AlignmentDirectional.bottomEnd,
|
||||||
label: "Ressource :",
|
child: Container(
|
||||||
initialValue: contentDTO.resourceId,
|
width: 175,
|
||||||
color: kPrimaryColor,
|
height: 70,
|
||||||
fontSize: 20,
|
child: RoundedButton(
|
||||||
inResourceTypes: [ResourceType.Image, ResourceType.ImageUrl, ResourceType.Video, ResourceType.VideoUrl, ResourceType.Audio],
|
text: "Annuler",
|
||||||
onChanged: (ResourceDTO resource) {
|
icon: Icons.undo,
|
||||||
if(resource.id == null) {
|
color: kSecond,
|
||||||
contentDTO.resourceId = null;
|
press: () {
|
||||||
contentDTO.resource = null;
|
Navigator.pop(dialogContext);
|
||||||
} else {
|
},
|
||||||
contentDTO.resourceId = resource.id;
|
fontSize: 20,
|
||||||
contentDTO.resource = resource;
|
),
|
||||||
}
|
|
||||||
},
|
|
||||||
isSmall: true
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if(showTitle || showDescription)
|
Align(
|
||||||
Container(
|
alignment: AlignmentDirectional.bottomEnd,
|
||||||
height: size.height * 0.3,
|
child: Container(
|
||||||
width: double.infinity,
|
width: inputContentDTO != null ? 220: 150,
|
||||||
constraints: BoxConstraints(minHeight: 200),
|
height: 70,
|
||||||
child: Column(
|
child: RoundedButton(
|
||||||
children: [
|
text: inputContentDTO != null ? AppLocalizations.of(context)!.save : AppLocalizations.of(context)!.create,
|
||||||
MultiStringInputContainer(
|
icon: Icons.check,
|
||||||
label: AppLocalizations.of(context)!.displayTitleLabel,
|
color: kPrimaryColor,
|
||||||
modalLabel: "Titre",
|
textColor: kWhite,
|
||||||
fontSize: 20,
|
press: () {
|
||||||
isHTML: true,
|
if (contentDTO.resourceId != null) {
|
||||||
color: kPrimaryColor,
|
Navigator.pop(dialogContext, contentDTO);
|
||||||
initialValue: contentDTO.title != null ? contentDTO.title! : [],
|
}
|
||||||
onGetResult: (value) {
|
},
|
||||||
if (contentDTO.title != value) {
|
fontSize: 20,
|
||||||
contentDTO.title = value;
|
),
|
||||||
}
|
|
||||||
},
|
|
||||||
maxLines: 1,
|
|
||||||
isTitle: true
|
|
||||||
),
|
|
||||||
MultiStringInputContainer(
|
|
||||||
label: AppLocalizations.of(context)!.displayedDescriptionLabel,
|
|
||||||
modalLabel: "Description",
|
|
||||||
fontSize: 20,
|
|
||||||
isHTML: true,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
initialValue: contentDTO.description != null ? contentDTO.description! : [],
|
|
||||||
isMandatory: false,
|
|
||||||
onGetResult: (value) {
|
|
||||||
if (contentDTO.description != value) {
|
|
||||||
contentDTO.description = value;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
maxLines: 1,
|
|
||||||
isTitle: false
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: <Widget>[
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: 175,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: "Annuler",
|
|
||||||
icon: Icons.undo,
|
|
||||||
color: kSecond,
|
|
||||||
press: () {
|
|
||||||
Navigator.pop(dialogContext);
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: inputContentDTO != null ? 220: 150,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: inputContentDTO != null ? AppLocalizations.of(context)!.save : AppLocalizations.of(context)!.create,
|
|
||||||
icon: Icons.check,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
textColor: kWhite,
|
|
||||||
press: () {
|
|
||||||
if (contentDTO.resourceId != null) {
|
|
||||||
Navigator.pop(dialogContext, contentDTO);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
), context: context
|
), context: context
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -68,6 +68,7 @@ class _SliderConfigState extends State<SliderConfig> {
|
|||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
width: size.width * 0.95,
|
width: size.width * 0.95,
|
||||||
|
height: 300,
|
||||||
child: ReorderableListView(
|
child: ReorderableListView(
|
||||||
onReorder: _onReorder,
|
onReorder: _onReorder,
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import 'package:manager_app/Components/message_notification.dart';
|
|||||||
import 'package:manager_app/l10n/app_localizations.dart';
|
import 'package:manager_app/l10n/app_localizations.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/number_input_container.dart';
|
import 'package:manager_app/Components/number_input_container.dart';
|
||||||
import 'package:manager_app/Components/rounded_button.dart';
|
|
||||||
import 'package:manager_app/Components/string_input_container.dart';
|
import 'package:manager_app/Components/string_input_container.dart';
|
||||||
import 'package:manager_app/Models/managerContext.dart';
|
import 'package:manager_app/Models/managerContext.dart';
|
||||||
import 'package:manager_app/Screens/Configurations/Section/SubSection/Video/video_config.dart';
|
import 'package:manager_app/Screens/Configurations/Section/SubSection/Video/video_config.dart';
|
||||||
@ -82,366 +81,351 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final appContext = Provider.of<AppContext>(context);
|
final appContext = Provider.of<AppContext>(context);
|
||||||
Size size = MediaQuery.of(context).size;
|
|
||||||
|
|
||||||
Object? rawSectionData;
|
|
||||||
|
|
||||||
return FutureBuilder(
|
return FutureBuilder(
|
||||||
future: _sectionFuture,
|
future: _sectionFuture,
|
||||||
builder: (context, AsyncSnapshot<dynamic> snapshot) {
|
builder: (context, AsyncSnapshot<dynamic> snapshot) {
|
||||||
if (snapshot.connectionState == ConnectionState.done) {
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
rawSectionData = snapshot.data;
|
Object? rawSectionData = snapshot.data;
|
||||||
|
var nullableSection = SectionDTO.fromJson(rawSectionData);
|
||||||
|
|
||||||
var nullableSection = SectionDTO.fromJson(rawSectionData);
|
if (nullableSection != null) {
|
||||||
|
sectionDTO = nullableSection;
|
||||||
|
|
||||||
if (nullableSection != null) {
|
if (sectionDetailDTO == null || lastLoadedSectionId != widget.id) {
|
||||||
sectionDTO = nullableSection;
|
_initializeSectionDetail(rawSectionData);
|
||||||
|
lastLoadedSectionId = widget.id;
|
||||||
// Only initialize sectionDetailDTO if it's not already loaded for this section
|
|
||||||
if (sectionDetailDTO == null ||
|
|
||||||
lastLoadedSectionId != widget.id) {
|
|
||||||
_initializeSectionDetail(rawSectionData);
|
|
||||||
lastLoadedSectionId = widget.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Stack(
|
|
||||||
fit: StackFit.expand,
|
|
||||||
children: [
|
|
||||||
bodySection(
|
|
||||||
rawSectionData, size, appContext, context),
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.bottomCenter,
|
|
||||||
child: Container(
|
|
||||||
height: 80,
|
|
||||||
child: getButtons(sectionDTO, appContext),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Center(
|
|
||||||
child: Text(
|
|
||||||
AppLocalizations.of(context)!.sectionLoadError));
|
|
||||||
}
|
}
|
||||||
} else if (snapshot.connectionState == ConnectionState.none) {
|
|
||||||
return Text(AppLocalizations.of(context)!.noData);
|
return _buildBody(rawSectionData, appContext);
|
||||||
} else {
|
} else {
|
||||||
return Center(
|
return Center(child: Text(AppLocalizations.of(context)!.sectionLoadError));
|
||||||
child: Container(
|
|
||||||
height: size.height * 0.2, child: CommonLoader()));
|
|
||||||
}
|
}
|
||||||
});
|
} else if (snapshot.connectionState == ConnectionState.none) {
|
||||||
|
return Center(child: Text(AppLocalizations.of(context)!.noData));
|
||||||
|
}
|
||||||
|
return const Center(child: CommonLoader());
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget bodySection(Object? rawSectionDTO, Size size, AppContext appContext,
|
// ── Main layout ──
|
||||||
BuildContext context) {
|
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
|
||||||
//SectionDTO? sectionDTO = SectionDTO.fromJson(rawSectionDTO);
|
|
||||||
|
|
||||||
return SingleChildScrollView(
|
Widget _buildBody(Object? rawSectionData, AppContext appContext) {
|
||||||
child: Column(
|
final managerCtx = appContext.getContext() as ManagerAppContext;
|
||||||
//mainAxisAlignment: MainAxisAlignment.spaceAround,
|
final canEdit = managerCtx.canEdit;
|
||||||
children: [
|
final l = AppLocalizations.of(context)!;
|
||||||
Container(
|
|
||||||
//color: Colors.orangeAccent,
|
return Column(
|
||||||
height: 82,
|
children: [
|
||||||
child: Row(
|
_buildHeader(appContext, l),
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
Expanded(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Align(
|
_cardIdentity(appContext, l),
|
||||||
alignment: AlignmentDirectional.bottomStart,
|
const SizedBox(height: 12),
|
||||||
child: Padding(
|
_cardQR(appContext, l),
|
||||||
padding: const EdgeInsets.all(3.0),
|
const SizedBox(height: 12),
|
||||||
child: Column(
|
_cardTypeConfig(rawSectionData, appContext),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
const SizedBox(height: 80),
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Icon(
|
|
||||||
getSectionIcon(sectionDTO.type),
|
|
||||||
color: kPrimaryColor,
|
|
||||||
size: 25,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(sectionDTO.label!,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 30,
|
|
||||||
fontWeight: FontWeight.w400)),
|
|
||||||
//if((appContext.getContext() as ManagerAppContext).selectedConfiguration!.isMobile!)
|
|
||||||
DownloadPDF(sections: [sectionDTO]),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(5.0),
|
|
||||||
child: Text(
|
|
||||||
DateFormat('dd/MM/yyyy')
|
|
||||||
.format(sectionDTO.dateCreation!),
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 15, fontWeight: FontWeight.w200)),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(5.0),
|
|
||||||
child: Align(
|
|
||||||
alignment: AlignmentDirectional.centerEnd,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
ManagerAppContext managerAppContext =
|
|
||||||
appContext.getContext();
|
|
||||||
managerAppContext.selectedSection = null;
|
|
||||||
appContext.setContext(managerAppContext);
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
child: Icon(
|
|
||||||
Icons.arrow_back,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
size: 50.0,
|
|
||||||
))),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
), // TITLE
|
|
||||||
Container(
|
|
||||||
//color: Colors.blue,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(5.0),
|
|
||||||
child: Container(
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
//if((appContext.getContext() as ManagerAppContext).selectedConfiguration!.isMobile!)
|
|
||||||
Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
InkWell(
|
|
||||||
onTap: () async {
|
|
||||||
var image = await _captureAndSharePng(
|
|
||||||
globalKey, sectionDTO.id!);
|
|
||||||
await readAndWriteFiles(image);
|
|
||||||
showNotification(
|
|
||||||
kSuccess,
|
|
||||||
kWhite,
|
|
||||||
AppLocalizations.of(context)!.qrCodeCopied,
|
|
||||||
context,
|
|
||||||
null);
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
width: size.width * 0.1,
|
|
||||||
height: 125,
|
|
||||||
child: RepaintBoundary(
|
|
||||||
key: globalKey,
|
|
||||||
child: QrImageView(
|
|
||||||
padding: EdgeInsets.only(
|
|
||||||
left: 5.0,
|
|
||||||
top: 5.0,
|
|
||||||
bottom: 5.0,
|
|
||||||
right: 5.0),
|
|
||||||
data:
|
|
||||||
"${managerAppContext.host!.replaceFirst("api", "web")}/${managerAppContext.instanceId}/${managerAppContext.selectedConfiguration!.id}/${sectionDTO.id!}",
|
|
||||||
version: QrVersions.auto,
|
|
||||||
size: 50.0,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SelectableText(sectionDTO.id!,
|
|
||||||
style: new TextStyle(fontSize: 15))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
CheckInputContainer(
|
|
||||||
label: AppLocalizations.of(context)!.beaconLabel,
|
|
||||||
isChecked: sectionDTO.isBeacon!,
|
|
||||||
onChanged: (value) {
|
|
||||||
setState(() {
|
|
||||||
sectionDTO.isBeacon = value;
|
|
||||||
save(false, appContext);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (sectionDTO.isBeacon!)
|
|
||||||
NumberInputContainer(
|
|
||||||
label: AppLocalizations.of(context)!.beaconIdLabel,
|
|
||||||
initialValue: sectionDTO.beaconId != null
|
|
||||||
? sectionDTO.beaconId!
|
|
||||||
: 0,
|
|
||||||
isSmall: true,
|
|
||||||
onChanged: (value) {
|
|
||||||
try {
|
|
||||||
sectionDTO.beaconId = int.parse(value);
|
|
||||||
} catch (e) {
|
|
||||||
print('BeaconId not a number');
|
|
||||||
showNotification(
|
|
||||||
Colors.orange,
|
|
||||||
kWhite,
|
|
||||||
AppLocalizations.of(context)!.beaconMustBeNumber,
|
|
||||||
context,
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
height: 100,
|
|
||||||
child: StringInputContainer(
|
|
||||||
label: AppLocalizations.of(context)!.identifierLabel,
|
|
||||||
initialValue: sectionDTO.label,
|
|
||||||
onChanged: (String value) {
|
|
||||||
sectionDTO.label = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
height: 100,
|
|
||||||
child: MultiStringInputContainer(
|
|
||||||
label: AppLocalizations.of(context)!.displayTitleLabel,
|
|
||||||
modalLabel: AppLocalizations.of(context)!.messageTitle,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
initialValue: sectionDTO.title!,
|
|
||||||
onGetResult: (value) {
|
|
||||||
if (sectionDTO.title! != value) {
|
|
||||||
sectionDTO.title = value;
|
|
||||||
save(true, appContext);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
maxLines: 1,
|
|
||||||
isHTML: true,
|
|
||||||
isTitle: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
/*if(!(appContext.getContext() as ManagerAppContext).selectedConfiguration!.isMobile!)
|
|
||||||
MultiStringInputContainer(
|
|
||||||
label: "Description affichée:",
|
|
||||||
modalLabel: "Description",
|
|
||||||
color: kPrimaryColor,
|
|
||||||
isHTML: true,
|
|
||||||
initialValue: sectionDTO.description!,
|
|
||||||
isMandatory: false,
|
|
||||||
onGetResult: (value) {
|
|
||||||
if (sectionDTO.description != value) {
|
|
||||||
sectionDTO.description = value!;
|
|
||||||
save(true, appContext);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
maxLines: 2,
|
|
||||||
isTitle: true,
|
|
||||||
),*/
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
ResourceInputContainer(
|
|
||||||
label: AppLocalizations.of(context)!.imageLabel,
|
|
||||||
initialValue: sectionDTO.imageId,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
onChanged: (ResourceDTO resource) {
|
|
||||||
if (resource.id == null) {
|
|
||||||
sectionDTO.imageId = null;
|
|
||||||
sectionDTO.imageSource = null;
|
|
||||||
} else {
|
|
||||||
sectionDTO.imageId = resource.id;
|
|
||||||
sectionDTO.imageSource = resource.url;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
), // FIELDS SECTION
|
|
||||||
Container(
|
|
||||||
//width: size.width * 0.8,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(10.0),
|
|
||||||
child: getSpecificData(rawSectionDTO, appContext),
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
//color: Colors.lightGreen,
|
|
||||||
borderRadius: BorderRadius.circular(30),
|
|
||||||
border: Border.all(width: 1.5, color: kSecond)),
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
_buildFooter(appContext, canEdit, l),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Header ──
|
||||||
|
|
||||||
|
Widget _buildHeader(AppContext appContext, AppLocalizations l) {
|
||||||
|
final typeName = sectionDTO.type?.toString().split('.').last ?? '';
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: kWhite,
|
||||||
|
border: Border(bottom: BorderSide(color: kSecond, width: 1)),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.arrow_back, color: kPrimaryColor),
|
||||||
|
onPressed: () {
|
||||||
|
ManagerAppContext ctx = appContext.getContext();
|
||||||
|
ctx.selectedSection = null;
|
||||||
|
appContext.setContext(ctx);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Icon(getSectionIcon(sectionDTO.type), color: kPrimaryColor, size: 22),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
sectionDTO.label ?? '',
|
||||||
|
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
DateFormat('dd/MM/yyyy').format(sectionDTO.dateCreation!),
|
||||||
|
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w300, color: Colors.grey),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Chip(
|
||||||
|
label: Text(typeName.toUpperCase()),
|
||||||
|
backgroundColor: kPrimaryColor.withValues(alpha: 0.1),
|
||||||
|
labelStyle: const TextStyle(color: kPrimaryColor, fontWeight: FontWeight.w600, fontSize: 11),
|
||||||
|
side: BorderSide.none,
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
DownloadPDF(sections: [sectionDTO]),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getButtons(SectionDTO sectionDTO, AppContext appContext) {
|
// ── Footer ──
|
||||||
final canEdit = (appContext.getContext() as ManagerAppContext).canEdit;
|
|
||||||
return Align(
|
Widget _buildFooter(AppContext appContext, bool canEdit, AppLocalizations l) {
|
||||||
alignment: AlignmentDirectional.bottomCenter,
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: kWhite,
|
||||||
|
boxShadow: [BoxShadow(color: kSecond, blurRadius: 8, offset: Offset(0, -2))],
|
||||||
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
OutlinedButton.icon(
|
||||||
padding: const EdgeInsets.all(10.0),
|
icon: const Icon(Icons.undo, size: 16),
|
||||||
child: RoundedButton(
|
label: Text(l.cancel),
|
||||||
text: AppLocalizations.of(context)!.cancel,
|
onPressed: () => cancel(appContext),
|
||||||
icon: Icons.undo,
|
|
||||||
color: Colors.grey,
|
|
||||||
textColor: Colors.white,
|
|
||||||
fontSize: 15,
|
|
||||||
press: () {
|
|
||||||
cancel(appContext);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
if (canEdit) Padding(
|
if (canEdit) ...[
|
||||||
padding: const EdgeInsets.all(8.0),
|
const SizedBox(width: 8),
|
||||||
child: RoundedButton(
|
ElevatedButton.icon(
|
||||||
text: AppLocalizations.of(context)!.delete,
|
icon: const Icon(Icons.delete, size: 16, color: kWhite),
|
||||||
icon: Icons.delete,
|
label: Text(l.delete, style: const TextStyle(color: kWhite)),
|
||||||
color: kError,
|
style: ElevatedButton.styleFrom(backgroundColor: kError),
|
||||||
textColor: Colors.white,
|
onPressed: () => delete(appContext),
|
||||||
fontSize: 15,
|
|
||||||
press: () {
|
|
||||||
delete(appContext);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 8),
|
||||||
if (canEdit) Padding(
|
ElevatedButton.icon(
|
||||||
padding: const EdgeInsets.all(8.0),
|
icon: const Icon(Icons.done, size: 16, color: kWhite),
|
||||||
child: RoundedButton(
|
label: Text(l.save, style: const TextStyle(color: kWhite)),
|
||||||
text: AppLocalizations.of(context)!.save,
|
style: ElevatedButton.styleFrom(backgroundColor: kPrimaryColor),
|
||||||
icon: Icons.done,
|
onPressed: () => save(false, appContext),
|
||||||
color: kSuccess,
|
|
||||||
textColor: Colors.white,
|
|
||||||
fontSize: 15,
|
|
||||||
press: () {
|
|
||||||
save(false, appContext);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Card Identité ──
|
||||||
|
|
||||||
|
Widget _cardIdentity(AppContext appContext, AppLocalizations l) {
|
||||||
|
return Card(
|
||||||
|
elevation: 0,
|
||||||
|
color: kWhite,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(l.identifierLabel.replaceAll(':', '').trim(),
|
||||||
|
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: kTitleTextColor)),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
final isWide = constraints.maxWidth > kBreakpointMobile;
|
||||||
|
|
||||||
|
final fields = Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
StringInputContainer(
|
||||||
|
label: l.identifierLabel,
|
||||||
|
initialValue: sectionDTO.label,
|
||||||
|
onChanged: (String value) => sectionDTO.label = value,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
MultiStringInputContainer(
|
||||||
|
label: l.displayTitleLabel,
|
||||||
|
modalLabel: l.messageTitle,
|
||||||
|
color: kPrimaryColor,
|
||||||
|
initialValue: sectionDTO.title!,
|
||||||
|
onGetResult: (value) {
|
||||||
|
if (sectionDTO.title! != value) {
|
||||||
|
sectionDTO.title = value;
|
||||||
|
save(true, appContext);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
maxLines: 1,
|
||||||
|
isHTML: true,
|
||||||
|
isTitle: true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final image = ResourceInputContainer(
|
||||||
|
label: l.imageLabel,
|
||||||
|
initialValue: sectionDTO.imageId,
|
||||||
|
color: kPrimaryColor,
|
||||||
|
onChanged: (ResourceDTO resource) {
|
||||||
|
if (resource.id == null) {
|
||||||
|
sectionDTO.imageId = null;
|
||||||
|
sectionDTO.imageSource = null;
|
||||||
|
} else {
|
||||||
|
sectionDTO.imageId = resource.id;
|
||||||
|
sectionDTO.imageSource = resource.url;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isWide) {
|
||||||
|
return Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(flex: 3, child: fields),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Expanded(flex: 2, child: image),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
fields,
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
image,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Card QR / Beacon ──
|
||||||
|
|
||||||
|
Widget _cardQR(AppContext appContext, AppLocalizations l) {
|
||||||
|
final managerCtx = appContext.getContext() as ManagerAppContext;
|
||||||
|
final qrData = "${managerCtx.host!.replaceFirst("api", "web")}/${managerCtx.instanceId}/${managerCtx.selectedConfiguration!.id}/${sectionDTO.id!}";
|
||||||
|
|
||||||
|
return Card(
|
||||||
|
elevation: 0,
|
||||||
|
color: kWhite,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||||
|
child: Theme(
|
||||||
|
data: Theme.of(context).copyWith(dividerColor: Colors.transparent),
|
||||||
|
child: ExpansionTile(
|
||||||
|
leading: const Icon(Icons.qr_code_2, color: kPrimaryColor),
|
||||||
|
title: const Text("QR Code / Identifiant",
|
||||||
|
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: kTitleTextColor)),
|
||||||
|
childrenPadding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
|
||||||
|
children: [
|
||||||
|
Wrap(
|
||||||
|
spacing: 24,
|
||||||
|
runSpacing: 12,
|
||||||
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
|
children: [
|
||||||
|
InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
var image = await _captureAndSharePng(globalKey, sectionDTO.id!);
|
||||||
|
await readAndWriteFiles(image);
|
||||||
|
if (context.mounted) {
|
||||||
|
showNotification(kSuccess, kWhite, l.qrCodeCopied, context, null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: SizedBox(
|
||||||
|
width: 120,
|
||||||
|
height: 120,
|
||||||
|
child: RepaintBoundary(
|
||||||
|
key: globalKey,
|
||||||
|
child: QrImageView(
|
||||||
|
padding: const EdgeInsets.all(5.0),
|
||||||
|
data: qrData,
|
||||||
|
version: QrVersions.auto,
|
||||||
|
size: 50.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SelectableText(sectionDTO.id!, style: const TextStyle(fontSize: 13)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Wrap(
|
||||||
|
spacing: 16,
|
||||||
|
runSpacing: 8,
|
||||||
|
children: [
|
||||||
|
CheckInputContainer(
|
||||||
|
label: l.beaconLabel,
|
||||||
|
isChecked: sectionDTO.isBeacon!,
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
sectionDTO.isBeacon = value;
|
||||||
|
save(false, appContext);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (sectionDTO.isBeacon!)
|
||||||
|
NumberInputContainer(
|
||||||
|
label: l.beaconIdLabel,
|
||||||
|
initialValue: sectionDTO.beaconId ?? 0,
|
||||||
|
isSmall: true,
|
||||||
|
onChanged: (value) {
|
||||||
|
try {
|
||||||
|
sectionDTO.beaconId = int.parse(value);
|
||||||
|
} catch (e) {
|
||||||
|
showNotification(Colors.orange, kWhite, l.beaconMustBeNumber, context, null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Card Type Config ──
|
||||||
|
|
||||||
|
Widget _cardTypeConfig(Object? rawSectionData, AppContext appContext) {
|
||||||
|
final typeName = sectionDTO.type?.toString().split('.').last ?? 'Section';
|
||||||
|
return Card(
|
||||||
|
elevation: 0,
|
||||||
|
color: kWhite,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text("Configuration $typeName",
|
||||||
|
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: kTitleTextColor)),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
getSpecificData(rawSectionData, appContext),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Actions ──
|
||||||
|
|
||||||
Future<void> cancel(AppContext appContext) async {
|
Future<void> cancel(AppContext appContext) async {
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
ManagerAppContext managerAppContext = appContext.getContext();
|
||||||
Object? rawData = await (appContext.getContext() as ManagerAppContext)
|
Object? rawData = await (appContext.getContext() as ManagerAppContext)
|
||||||
@ -480,18 +464,16 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
appContext.setContext(managerAppContext);
|
appContext.setContext(managerAppContext);
|
||||||
|
|
||||||
if (isTraduction) {
|
if (isTraduction) {
|
||||||
showNotification(
|
showNotification(kSuccess, kWhite,
|
||||||
kSuccess,
|
AppLocalizations.of(context)!.sectionTranslationSaved, context, null);
|
||||||
kWhite,
|
|
||||||
AppLocalizations.of(context)!.sectionTranslationSaved,
|
|
||||||
context,
|
|
||||||
null);
|
|
||||||
} else {
|
} else {
|
||||||
showNotification(kSuccess, kWhite,
|
showNotification(kSuccess, kWhite,
|
||||||
AppLocalizations.of(context)!.sectionSavedSuccess, context, null);
|
AppLocalizations.of(context)!.sectionSavedSuccess, context, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Type-specific config widget ──
|
||||||
|
|
||||||
getSpecificData(Object? rawSectionData, AppContext appContext) {
|
getSpecificData(Object? rawSectionData, AppContext appContext) {
|
||||||
switch (sectionDTO.type) {
|
switch (sectionDTO.type) {
|
||||||
case SectionType.Map:
|
case SectionType.Map:
|
||||||
@ -527,9 +509,7 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
case SectionType.Menu:
|
case SectionType.Menu:
|
||||||
return MenuConfig(
|
return MenuConfig(
|
||||||
initialValue: sectionDetailDTO as MenuDTO,
|
initialValue: sectionDetailDTO as MenuDTO,
|
||||||
onChanged: (String data) {
|
onChanged: (String data) {},
|
||||||
//sectionDTO.data = data;
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
case SectionType.Quiz:
|
case SectionType.Quiz:
|
||||||
return QuizzConfig(
|
return QuizzConfig(
|
||||||
@ -584,6 +564,8 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Section detail initialization ──
|
||||||
|
|
||||||
_initializeSectionDetail(Object? rawSectionData) {
|
_initializeSectionDetail(Object? rawSectionData) {
|
||||||
if (rawSectionData == null) return;
|
if (rawSectionData == null) return;
|
||||||
switch (sectionDTO.type) {
|
switch (sectionDTO.type) {
|
||||||
@ -626,6 +608,8 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Sync sectionDTO fields back to detail DTO before save ──
|
||||||
|
|
||||||
updateSectionDetail() {
|
updateSectionDetail() {
|
||||||
switch (sectionDTO.type) {
|
switch (sectionDTO.type) {
|
||||||
case SectionType.Map:
|
case SectionType.Map:
|
||||||
@ -634,8 +618,7 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
(sectionDetailDTO as MapDTO).dateCreation = sectionDTO.dateCreation;
|
(sectionDetailDTO as MapDTO).dateCreation = sectionDTO.dateCreation;
|
||||||
(sectionDetailDTO as MapDTO).type = sectionDTO.type;
|
(sectionDetailDTO as MapDTO).type = sectionDTO.type;
|
||||||
(sectionDetailDTO as MapDTO).instanceId = sectionDTO.instanceId;
|
(sectionDetailDTO as MapDTO).instanceId = sectionDTO.instanceId;
|
||||||
(sectionDetailDTO as MapDTO).configurationId =
|
(sectionDetailDTO as MapDTO).configurationId = sectionDTO.configurationId;
|
||||||
sectionDTO.configurationId;
|
|
||||||
(sectionDetailDTO as MapDTO).isSubSection = sectionDTO.isSubSection;
|
(sectionDetailDTO as MapDTO).isSubSection = sectionDTO.isSubSection;
|
||||||
(sectionDetailDTO as MapDTO).parentId = sectionDTO.parentId;
|
(sectionDetailDTO as MapDTO).parentId = sectionDTO.parentId;
|
||||||
(sectionDetailDTO as MapDTO).label = sectionDTO.label;
|
(sectionDetailDTO as MapDTO).label = sectionDTO.label;
|
||||||
@ -655,8 +638,7 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
(sectionDetailDTO as SliderDTO).dateCreation = sectionDTO.dateCreation;
|
(sectionDetailDTO as SliderDTO).dateCreation = sectionDTO.dateCreation;
|
||||||
(sectionDetailDTO as SliderDTO).type = sectionDTO.type;
|
(sectionDetailDTO as SliderDTO).type = sectionDTO.type;
|
||||||
(sectionDetailDTO as SliderDTO).instanceId = sectionDTO.instanceId;
|
(sectionDetailDTO as SliderDTO).instanceId = sectionDTO.instanceId;
|
||||||
(sectionDetailDTO as SliderDTO).configurationId =
|
(sectionDetailDTO as SliderDTO).configurationId = sectionDTO.configurationId;
|
||||||
sectionDTO.configurationId;
|
|
||||||
(sectionDetailDTO as SliderDTO).isSubSection = sectionDTO.isSubSection;
|
(sectionDetailDTO as SliderDTO).isSubSection = sectionDTO.isSubSection;
|
||||||
(sectionDetailDTO as SliderDTO).parentId = sectionDTO.parentId;
|
(sectionDetailDTO as SliderDTO).parentId = sectionDTO.parentId;
|
||||||
(sectionDetailDTO as SliderDTO).label = sectionDTO.label;
|
(sectionDetailDTO as SliderDTO).label = sectionDTO.label;
|
||||||
@ -676,8 +658,7 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
(sectionDetailDTO as VideoDTO).dateCreation = sectionDTO.dateCreation;
|
(sectionDetailDTO as VideoDTO).dateCreation = sectionDTO.dateCreation;
|
||||||
(sectionDetailDTO as VideoDTO).type = sectionDTO.type;
|
(sectionDetailDTO as VideoDTO).type = sectionDTO.type;
|
||||||
(sectionDetailDTO as VideoDTO).instanceId = sectionDTO.instanceId;
|
(sectionDetailDTO as VideoDTO).instanceId = sectionDTO.instanceId;
|
||||||
(sectionDetailDTO as VideoDTO).configurationId =
|
(sectionDetailDTO as VideoDTO).configurationId = sectionDTO.configurationId;
|
||||||
sectionDTO.configurationId;
|
|
||||||
(sectionDetailDTO as VideoDTO).isSubSection = sectionDTO.isSubSection;
|
(sectionDetailDTO as VideoDTO).isSubSection = sectionDTO.isSubSection;
|
||||||
(sectionDetailDTO as VideoDTO).parentId = sectionDTO.parentId;
|
(sectionDetailDTO as VideoDTO).parentId = sectionDTO.parentId;
|
||||||
(sectionDetailDTO as VideoDTO).label = sectionDTO.label;
|
(sectionDetailDTO as VideoDTO).label = sectionDTO.label;
|
||||||
@ -697,8 +678,7 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
(sectionDetailDTO as WebDTO).dateCreation = sectionDTO.dateCreation;
|
(sectionDetailDTO as WebDTO).dateCreation = sectionDTO.dateCreation;
|
||||||
(sectionDetailDTO as WebDTO).type = sectionDTO.type;
|
(sectionDetailDTO as WebDTO).type = sectionDTO.type;
|
||||||
(sectionDetailDTO as WebDTO).instanceId = sectionDTO.instanceId;
|
(sectionDetailDTO as WebDTO).instanceId = sectionDTO.instanceId;
|
||||||
(sectionDetailDTO as WebDTO).configurationId =
|
(sectionDetailDTO as WebDTO).configurationId = sectionDTO.configurationId;
|
||||||
sectionDTO.configurationId;
|
|
||||||
(sectionDetailDTO as WebDTO).isSubSection = sectionDTO.isSubSection;
|
(sectionDetailDTO as WebDTO).isSubSection = sectionDTO.isSubSection;
|
||||||
(sectionDetailDTO as WebDTO).parentId = sectionDTO.parentId;
|
(sectionDetailDTO as WebDTO).parentId = sectionDTO.parentId;
|
||||||
(sectionDetailDTO as WebDTO).label = sectionDTO.label;
|
(sectionDetailDTO as WebDTO).label = sectionDTO.label;
|
||||||
@ -718,8 +698,7 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
(sectionDetailDTO as MenuDTO).dateCreation = sectionDTO.dateCreation;
|
(sectionDetailDTO as MenuDTO).dateCreation = sectionDTO.dateCreation;
|
||||||
(sectionDetailDTO as MenuDTO).type = sectionDTO.type;
|
(sectionDetailDTO as MenuDTO).type = sectionDTO.type;
|
||||||
(sectionDetailDTO as MenuDTO).instanceId = sectionDTO.instanceId;
|
(sectionDetailDTO as MenuDTO).instanceId = sectionDTO.instanceId;
|
||||||
(sectionDetailDTO as MenuDTO).configurationId =
|
(sectionDetailDTO as MenuDTO).configurationId = sectionDTO.configurationId;
|
||||||
sectionDTO.configurationId;
|
|
||||||
(sectionDetailDTO as MenuDTO).isSubSection = sectionDTO.isSubSection;
|
(sectionDetailDTO as MenuDTO).isSubSection = sectionDTO.isSubSection;
|
||||||
(sectionDetailDTO as MenuDTO).parentId = sectionDTO.parentId;
|
(sectionDetailDTO as MenuDTO).parentId = sectionDTO.parentId;
|
||||||
(sectionDetailDTO as MenuDTO).label = sectionDTO.label;
|
(sectionDetailDTO as MenuDTO).label = sectionDTO.label;
|
||||||
@ -739,8 +718,7 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
(sectionDetailDTO as QuizDTO).dateCreation = sectionDTO.dateCreation;
|
(sectionDetailDTO as QuizDTO).dateCreation = sectionDTO.dateCreation;
|
||||||
(sectionDetailDTO as QuizDTO).type = sectionDTO.type;
|
(sectionDetailDTO as QuizDTO).type = sectionDTO.type;
|
||||||
(sectionDetailDTO as QuizDTO).instanceId = sectionDTO.instanceId;
|
(sectionDetailDTO as QuizDTO).instanceId = sectionDTO.instanceId;
|
||||||
(sectionDetailDTO as QuizDTO).configurationId =
|
(sectionDetailDTO as QuizDTO).configurationId = sectionDTO.configurationId;
|
||||||
sectionDTO.configurationId;
|
|
||||||
(sectionDetailDTO as QuizDTO).isSubSection = sectionDTO.isSubSection;
|
(sectionDetailDTO as QuizDTO).isSubSection = sectionDTO.isSubSection;
|
||||||
(sectionDetailDTO as QuizDTO).parentId = sectionDTO.parentId;
|
(sectionDetailDTO as QuizDTO).parentId = sectionDTO.parentId;
|
||||||
(sectionDetailDTO as QuizDTO).label = sectionDTO.label;
|
(sectionDetailDTO as QuizDTO).label = sectionDTO.label;
|
||||||
@ -760,8 +738,7 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
(sectionDetailDTO as ArticleDTO).dateCreation = sectionDTO.dateCreation;
|
(sectionDetailDTO as ArticleDTO).dateCreation = sectionDTO.dateCreation;
|
||||||
(sectionDetailDTO as ArticleDTO).type = sectionDTO.type;
|
(sectionDetailDTO as ArticleDTO).type = sectionDTO.type;
|
||||||
(sectionDetailDTO as ArticleDTO).instanceId = sectionDTO.instanceId;
|
(sectionDetailDTO as ArticleDTO).instanceId = sectionDTO.instanceId;
|
||||||
(sectionDetailDTO as ArticleDTO).configurationId =
|
(sectionDetailDTO as ArticleDTO).configurationId = sectionDTO.configurationId;
|
||||||
sectionDTO.configurationId;
|
|
||||||
(sectionDetailDTO as ArticleDTO).isSubSection = sectionDTO.isSubSection;
|
(sectionDetailDTO as ArticleDTO).isSubSection = sectionDTO.isSubSection;
|
||||||
(sectionDetailDTO as ArticleDTO).parentId = sectionDTO.parentId;
|
(sectionDetailDTO as ArticleDTO).parentId = sectionDTO.parentId;
|
||||||
(sectionDetailDTO as ArticleDTO).label = sectionDTO.label;
|
(sectionDetailDTO as ArticleDTO).label = sectionDTO.label;
|
||||||
@ -781,8 +758,7 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
(sectionDetailDTO as PdfDTO).dateCreation = sectionDTO.dateCreation;
|
(sectionDetailDTO as PdfDTO).dateCreation = sectionDTO.dateCreation;
|
||||||
(sectionDetailDTO as PdfDTO).type = sectionDTO.type;
|
(sectionDetailDTO as PdfDTO).type = sectionDTO.type;
|
||||||
(sectionDetailDTO as PdfDTO).instanceId = sectionDTO.instanceId;
|
(sectionDetailDTO as PdfDTO).instanceId = sectionDTO.instanceId;
|
||||||
(sectionDetailDTO as PdfDTO).configurationId =
|
(sectionDetailDTO as PdfDTO).configurationId = sectionDTO.configurationId;
|
||||||
sectionDTO.configurationId;
|
|
||||||
(sectionDetailDTO as PdfDTO).isSubSection = sectionDTO.isSubSection;
|
(sectionDetailDTO as PdfDTO).isSubSection = sectionDTO.isSubSection;
|
||||||
(sectionDetailDTO as PdfDTO).parentId = sectionDTO.parentId;
|
(sectionDetailDTO as PdfDTO).parentId = sectionDTO.parentId;
|
||||||
(sectionDetailDTO as PdfDTO).label = sectionDTO.label;
|
(sectionDetailDTO as PdfDTO).label = sectionDTO.label;
|
||||||
@ -802,8 +778,7 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
(sectionDetailDTO as GameDTO).dateCreation = sectionDTO.dateCreation;
|
(sectionDetailDTO as GameDTO).dateCreation = sectionDTO.dateCreation;
|
||||||
(sectionDetailDTO as GameDTO).type = sectionDTO.type;
|
(sectionDetailDTO as GameDTO).type = sectionDTO.type;
|
||||||
(sectionDetailDTO as GameDTO).instanceId = sectionDTO.instanceId;
|
(sectionDetailDTO as GameDTO).instanceId = sectionDTO.instanceId;
|
||||||
(sectionDetailDTO as GameDTO).configurationId =
|
(sectionDetailDTO as GameDTO).configurationId = sectionDTO.configurationId;
|
||||||
sectionDTO.configurationId;
|
|
||||||
(sectionDetailDTO as GameDTO).isSubSection = sectionDTO.isSubSection;
|
(sectionDetailDTO as GameDTO).isSubSection = sectionDTO.isSubSection;
|
||||||
(sectionDetailDTO as GameDTO).parentId = sectionDTO.parentId;
|
(sectionDetailDTO as GameDTO).parentId = sectionDTO.parentId;
|
||||||
(sectionDetailDTO as GameDTO).label = sectionDTO.label;
|
(sectionDetailDTO as GameDTO).label = sectionDTO.label;
|
||||||
@ -823,8 +798,7 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
(sectionDetailDTO as AgendaDTO).dateCreation = sectionDTO.dateCreation;
|
(sectionDetailDTO as AgendaDTO).dateCreation = sectionDTO.dateCreation;
|
||||||
(sectionDetailDTO as AgendaDTO).type = sectionDTO.type;
|
(sectionDetailDTO as AgendaDTO).type = sectionDTO.type;
|
||||||
(sectionDetailDTO as AgendaDTO).instanceId = sectionDTO.instanceId;
|
(sectionDetailDTO as AgendaDTO).instanceId = sectionDTO.instanceId;
|
||||||
(sectionDetailDTO as AgendaDTO).configurationId =
|
(sectionDetailDTO as AgendaDTO).configurationId = sectionDTO.configurationId;
|
||||||
sectionDTO.configurationId;
|
|
||||||
(sectionDetailDTO as AgendaDTO).isSubSection = sectionDTO.isSubSection;
|
(sectionDetailDTO as AgendaDTO).isSubSection = sectionDTO.isSubSection;
|
||||||
(sectionDetailDTO as AgendaDTO).parentId = sectionDTO.parentId;
|
(sectionDetailDTO as AgendaDTO).parentId = sectionDTO.parentId;
|
||||||
(sectionDetailDTO as AgendaDTO).label = sectionDTO.label;
|
(sectionDetailDTO as AgendaDTO).label = sectionDTO.label;
|
||||||
@ -844,8 +818,7 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
(sectionDetailDTO as WeatherDTO).dateCreation = sectionDTO.dateCreation;
|
(sectionDetailDTO as WeatherDTO).dateCreation = sectionDTO.dateCreation;
|
||||||
(sectionDetailDTO as WeatherDTO).type = sectionDTO.type;
|
(sectionDetailDTO as WeatherDTO).type = sectionDTO.type;
|
||||||
(sectionDetailDTO as WeatherDTO).instanceId = sectionDTO.instanceId;
|
(sectionDetailDTO as WeatherDTO).instanceId = sectionDTO.instanceId;
|
||||||
(sectionDetailDTO as WeatherDTO).configurationId =
|
(sectionDetailDTO as WeatherDTO).configurationId = sectionDTO.configurationId;
|
||||||
sectionDTO.configurationId;
|
|
||||||
(sectionDetailDTO as WeatherDTO).isSubSection = sectionDTO.isSubSection;
|
(sectionDetailDTO as WeatherDTO).isSubSection = sectionDTO.isSubSection;
|
||||||
(sectionDetailDTO as WeatherDTO).parentId = sectionDTO.parentId;
|
(sectionDetailDTO as WeatherDTO).parentId = sectionDTO.parentId;
|
||||||
(sectionDetailDTO as WeatherDTO).label = sectionDTO.label;
|
(sectionDetailDTO as WeatherDTO).label = sectionDTO.label;
|
||||||
@ -862,29 +835,22 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
|
|||||||
case SectionType.Event:
|
case SectionType.Event:
|
||||||
(sectionDetailDTO as SectionEventDTO).id = sectionDTO.id;
|
(sectionDetailDTO as SectionEventDTO).id = sectionDTO.id;
|
||||||
(sectionDetailDTO as SectionEventDTO).order = sectionDTO.order;
|
(sectionDetailDTO as SectionEventDTO).order = sectionDTO.order;
|
||||||
(sectionDetailDTO as SectionEventDTO).dateCreation =
|
(sectionDetailDTO as SectionEventDTO).dateCreation = sectionDTO.dateCreation;
|
||||||
sectionDTO.dateCreation;
|
|
||||||
(sectionDetailDTO as SectionEventDTO).type = sectionDTO.type;
|
(sectionDetailDTO as SectionEventDTO).type = sectionDTO.type;
|
||||||
(sectionDetailDTO as SectionEventDTO).instanceId =
|
(sectionDetailDTO as SectionEventDTO).instanceId = sectionDTO.instanceId;
|
||||||
sectionDTO.instanceId;
|
(sectionDetailDTO as SectionEventDTO).configurationId = sectionDTO.configurationId;
|
||||||
(sectionDetailDTO as SectionEventDTO).configurationId =
|
(sectionDetailDTO as SectionEventDTO).isSubSection = sectionDTO.isSubSection;
|
||||||
sectionDTO.configurationId;
|
|
||||||
(sectionDetailDTO as SectionEventDTO).isSubSection =
|
|
||||||
sectionDTO.isSubSection;
|
|
||||||
(sectionDetailDTO as SectionEventDTO).parentId = sectionDTO.parentId;
|
(sectionDetailDTO as SectionEventDTO).parentId = sectionDTO.parentId;
|
||||||
(sectionDetailDTO as SectionEventDTO).label = sectionDTO.label;
|
(sectionDetailDTO as SectionEventDTO).label = sectionDTO.label;
|
||||||
(sectionDetailDTO as SectionEventDTO).title = sectionDTO.title;
|
(sectionDetailDTO as SectionEventDTO).title = sectionDTO.title;
|
||||||
(sectionDetailDTO as SectionEventDTO).description =
|
(sectionDetailDTO as SectionEventDTO).description = sectionDTO.description;
|
||||||
sectionDTO.description;
|
|
||||||
(sectionDetailDTO as SectionEventDTO).imageId = sectionDTO.imageId;
|
(sectionDetailDTO as SectionEventDTO).imageId = sectionDTO.imageId;
|
||||||
(sectionDetailDTO as SectionEventDTO).imageSource =
|
(sectionDetailDTO as SectionEventDTO).imageSource = sectionDTO.imageSource;
|
||||||
sectionDTO.imageSource;
|
|
||||||
(sectionDetailDTO as SectionEventDTO).isBeacon = sectionDTO.isBeacon;
|
(sectionDetailDTO as SectionEventDTO).isBeacon = sectionDTO.isBeacon;
|
||||||
(sectionDetailDTO as SectionEventDTO).beaconId = sectionDTO.beaconId;
|
(sectionDetailDTO as SectionEventDTO).beaconId = sectionDTO.beaconId;
|
||||||
(sectionDetailDTO as SectionEventDTO).latitude = sectionDTO.latitude;
|
(sectionDetailDTO as SectionEventDTO).latitude = sectionDTO.latitude;
|
||||||
(sectionDetailDTO as SectionEventDTO).longitude = sectionDTO.longitude;
|
(sectionDetailDTO as SectionEventDTO).longitude = sectionDTO.longitude;
|
||||||
(sectionDetailDTO as SectionEventDTO).meterZoneGPS =
|
(sectionDetailDTO as SectionEventDTO).meterZoneGPS = sectionDTO.meterZoneGPS;
|
||||||
sectionDTO.meterZoneGPS;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,23 +1,17 @@
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:manager_app/Components/check_input_container.dart';
|
import 'package:manager_app/Components/check_input_container.dart';
|
||||||
import 'package:manager_app/Components/color_picker_input_container.dart';
|
|
||||||
import 'package:manager_app/Components/confirmation_dialog.dart';
|
import 'package:manager_app/Components/confirmation_dialog.dart';
|
||||||
import 'package:manager_app/Components/number_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/common_loader.dart';
|
import 'package:manager_app/Components/common_loader.dart';
|
||||||
import 'package:manager_app/Components/message_notification.dart';
|
import 'package:manager_app/Components/message_notification.dart';
|
||||||
import 'package:manager_app/l10n/app_localizations.dart';
|
import 'package:manager_app/l10n/app_localizations.dart';
|
||||||
import 'package:manager_app/Components/multi_select_dropdown_language_container.dart';
|
import 'package:manager_app/Components/multi_select_dropdown_language_container.dart';
|
||||||
import 'package:manager_app/Components/multi_string_input_container.dart';
|
|
||||||
import 'package:manager_app/Components/rounded_button.dart';
|
|
||||||
import 'package:manager_app/Components/string_input_container.dart';
|
import 'package:manager_app/Components/string_input_container.dart';
|
||||||
import 'package:manager_app/Helpers/FileHelper.dart';
|
import 'package:manager_app/Helpers/FileHelper.dart';
|
||||||
import 'package:manager_app/Helpers/PDFHelper.dart';
|
|
||||||
import 'package:manager_app/Models/managerContext.dart';
|
import 'package:manager_app/Models/managerContext.dart';
|
||||||
import 'package:manager_app/Screens/Configurations/section_reorderList.dart';
|
import 'package:manager_app/Screens/Configurations/section_reorderList.dart';
|
||||||
import 'package:manager_app/app_context.dart';
|
import 'package:manager_app/app_context.dart';
|
||||||
@ -38,450 +32,387 @@ class ConfigurationDetailScreen extends StatefulWidget {
|
|||||||
|
|
||||||
class _ConfigurationDetailScreenState extends State<ConfigurationDetailScreen> {
|
class _ConfigurationDetailScreenState extends State<ConfigurationDetailScreen> {
|
||||||
ConfigurationDTO? configurationDTO;
|
ConfigurationDTO? configurationDTO;
|
||||||
SectionDTO? selectedSection;
|
|
||||||
List<SectionDTO>? sections;
|
List<SectionDTO>? sections;
|
||||||
|
Future<ConfigurationDTO?>? _configFuture;
|
||||||
|
Future<List<SectionDTO>?>? _sectionsFuture;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final appContext = Provider.of<AppContext>(context);
|
final appContext = Provider.of<AppContext>(context);
|
||||||
Size size = MediaQuery.of(context).size;
|
final managerCtx = appContext.getContext() as ManagerAppContext;
|
||||||
return FutureBuilder(
|
|
||||||
future: getConfiguration(this.widget, (appContext.getContext() as ManagerAppContext).clientAPI!),
|
_configFuture ??= getConfiguration(widget, managerCtx.clientAPI!);
|
||||||
builder: (context, AsyncSnapshot<dynamic> snapshot) {
|
|
||||||
if (snapshot.connectionState == ConnectionState.done) {
|
return FutureBuilder<ConfigurationDTO?>(
|
||||||
return bodyConfiguration(snapshot.data, size, appContext, context);
|
future: _configFuture,
|
||||||
} else if (snapshot.connectionState == ConnectionState.none) {
|
builder: (context, snapshot) {
|
||||||
return Text(AppLocalizations.of(context)!.noData);
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
} else {
|
if (snapshot.data == null) return Center(child: Text(AppLocalizations.of(context)!.noData));
|
||||||
return Center(
|
return _buildBody(snapshot.data!, appContext);
|
||||||
child: Container(
|
} else if (snapshot.connectionState == ConnectionState.none) {
|
||||||
height: size.height * 0.2,
|
return Center(child: Text(AppLocalizations.of(context)!.noData));
|
||||||
child: CommonLoader()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return const Center(child: CommonLoader());
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget bodyConfiguration(ConfigurationDTO configurationDTO, Size size, AppContext appContext, BuildContext context) {
|
Widget _buildBody(ConfigurationDTO config, AppContext appContext) {
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
final managerCtx = appContext.getContext() as ManagerAppContext;
|
||||||
return Column(
|
final canEdit = managerCtx.canEdit;
|
||||||
//mainAxisAlignment: MainAxisAlignment.spaceAround,
|
final l = AppLocalizations.of(context)!;
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
//color: Colors.cyanAccent,
|
|
||||||
height: size.height *0.1,
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.bottomStart,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(10.0),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Text(configurationDTO.label!, style: TextStyle(fontSize: 30, fontWeight: FontWeight.w400)),
|
|
||||||
InkWell(
|
|
||||||
onTap: () async {
|
|
||||||
try {
|
|
||||||
// Export config
|
|
||||||
Client clientAPI = (appContext.getContext() as ManagerAppContext).clientAPI!;
|
|
||||||
ExportConfigurationDTO export = await clientAPI.configurationApi!.configurationExport(configurationDTO.id!);
|
|
||||||
|
|
||||||
if (kIsWeb) {
|
return Column(
|
||||||
html.AnchorElement anchorElement = new html.AnchorElement();
|
children: [
|
||||||
var uri = (Uri.parse((appContext.getContext() as ManagerAppContext).clientAPI!.resourceApi!.apiClient.basePath+'/api/Configuration/${configurationDTO.id}/export'));
|
_buildHeader(config, appContext, l),
|
||||||
anchorElement.href = uri.toString();
|
Expanded(
|
||||||
anchorElement.download = '${configurationDTO.label}.json';
|
child: SingleChildScrollView(
|
||||||
anchorElement.click();
|
padding: const EdgeInsets.all(16),
|
||||||
} else {
|
child: Column(
|
||||||
File test = await FileHelper().storeConfiguration(export);
|
children: [
|
||||||
showNotification(kSuccess, kWhite, AppLocalizations.of(context)!.configExportSuccess(test.path), context, 3000);
|
_cardGeneral(config, l),
|
||||||
}
|
const SizedBox(height: 12),
|
||||||
} catch(e) {
|
_cardImages(config, l),
|
||||||
log(e.toString());
|
const SizedBox(height: 12),
|
||||||
showNotification(kPrimaryColor, kWhite, AppLocalizations.of(context)!.configExportFailed, context, null);
|
_cardSections(config, appContext),
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(left: 5.0),
|
|
||||||
child: Icon(Icons.cloud_download, color: kPrimaryColor)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(5.0),
|
|
||||||
child: Text(DateFormat('dd/MM/yyyy').format(configurationDTO.dateCreation!), style: TextStyle(fontSize: 15, fontWeight: FontWeight.w200)),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(10.0),
|
|
||||||
child: Align(
|
|
||||||
alignment: AlignmentDirectional.centerEnd,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
|
||||||
managerAppContext.selectedConfiguration = null;
|
|
||||||
appContext.setContext(managerAppContext);
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
child: Icon(
|
|
||||||
Icons.arrow_back,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
size: 50.0,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
), // TITLE
|
),
|
||||||
Container(
|
_buildFooter(config, appContext, canEdit, l),
|
||||||
height: size.height *0.78,
|
|
||||||
//color: Colors.red,
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(10.0),
|
|
||||||
child: Container(
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
LayoutBuilder(
|
|
||||||
builder: (context, constraints) {
|
|
||||||
final isWide = constraints.maxWidth > 700;
|
|
||||||
|
|
||||||
final fields = Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
height: 70,
|
|
||||||
child: StringInputContainer(
|
|
||||||
label: AppLocalizations.of(context)!.identifierLabel,
|
|
||||||
fontSize: 20,
|
|
||||||
fontSizeText: 20,
|
|
||||||
initialValue: configurationDTO.label,
|
|
||||||
onChanged: (value) {
|
|
||||||
configurationDTO.label = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Wrap(
|
|
||||||
spacing: 24,
|
|
||||||
runSpacing: 8,
|
|
||||||
crossAxisAlignment: WrapCrossAlignment.center,
|
|
||||||
children: [
|
|
||||||
MultiSelectDropdownLanguageContainer(
|
|
||||||
label: AppLocalizations.of(context)!.languagesLabel,
|
|
||||||
initialValue: configurationDTO.languages != null ? configurationDTO.languages! : [],
|
|
||||||
values: languages,
|
|
||||||
isMultiple: true,
|
|
||||||
fontSize: 20,
|
|
||||||
isAtLeastOne: true,
|
|
||||||
onChanged: (value) {
|
|
||||||
var tempOutput = new List<String>.from(value);
|
|
||||||
configurationDTO.languages = tempOutput;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
CheckInputContainer(
|
|
||||||
icon: Icons.signal_wifi_off,
|
|
||||||
label: "Hors ligne :", // no ARB key for this one yet, leave as-is
|
|
||||||
fontSize: 20,
|
|
||||||
isChecked: configurationDTO.isOffline,
|
|
||||||
onChanged: (value) {
|
|
||||||
configurationDTO.isOffline = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
final images = Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
ResourceInputContainer(
|
|
||||||
label: AppLocalizations.of(context)!.mainImageLabel,
|
|
||||||
fontSize: 20,
|
|
||||||
initialValue: configurationDTO.imageId,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
onChanged: (ResourceDTO resource) {
|
|
||||||
if (resource.id == null) {
|
|
||||||
configurationDTO.imageId = null;
|
|
||||||
configurationDTO.imageSource = null;
|
|
||||||
} else {
|
|
||||||
configurationDTO.imageId = resource.id;
|
|
||||||
configurationDTO.imageSource = resource.url;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ResourceInputContainer(
|
|
||||||
label: AppLocalizations.of(context)!.loaderLabel,
|
|
||||||
fontSize: 20,
|
|
||||||
initialValue: configurationDTO.loaderImageId,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
onChanged: (ResourceDTO resource) {
|
|
||||||
if (resource.id == null) {
|
|
||||||
configurationDTO.loaderImageId = null;
|
|
||||||
configurationDTO.loaderImageUrl = null;
|
|
||||||
} else {
|
|
||||||
configurationDTO.loaderImageId = resource.id;
|
|
||||||
configurationDTO.loaderImageUrl = resource.url;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isWide) {
|
|
||||||
return Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Expanded(flex: 3, child: fields),
|
|
||||||
SizedBox(width: 24),
|
|
||||||
Expanded(flex: 2, child: images),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
height: 70,
|
|
||||||
child: StringInputContainer(
|
|
||||||
label: "Identifiant :",
|
|
||||||
fontSize: 20,
|
|
||||||
fontSizeText: 20,
|
|
||||||
initialValue: configurationDTO.label,
|
|
||||||
onChanged: (value) {
|
|
||||||
configurationDTO.label = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 8),
|
|
||||||
MultiSelectDropdownLanguageContainer(
|
|
||||||
label: "Langues :",
|
|
||||||
initialValue: configurationDTO.languages != null ? configurationDTO.languages! : [],
|
|
||||||
values: languages,
|
|
||||||
isMultiple: true,
|
|
||||||
fontSize: 20,
|
|
||||||
isAtLeastOne: true,
|
|
||||||
onChanged: (value) {
|
|
||||||
var tempOutput = new List<String>.from(value);
|
|
||||||
configurationDTO.languages = tempOutput;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
SizedBox(height: 8),
|
|
||||||
CheckInputContainer(
|
|
||||||
icon: Icons.signal_wifi_off,
|
|
||||||
label: "Hors ligne :",
|
|
||||||
fontSize: 20,
|
|
||||||
isChecked: configurationDTO.isOffline,
|
|
||||||
onChanged: (value) {
|
|
||||||
configurationDTO.isOffline = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
SizedBox(height: 16),
|
|
||||||
images,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(20.0),
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
shape: BoxShape.rectangle,
|
|
||||||
borderRadius: BorderRadius.circular(25.0),
|
|
||||||
border: Border.all(width: 0.5, color: kSecond)
|
|
||||||
),
|
|
||||||
child: FutureBuilder(
|
|
||||||
future: getSections(configurationDTO, (appContext.getContext() as ManagerAppContext).clientAPI!),
|
|
||||||
builder: (context, AsyncSnapshot<dynamic> snapshot) {
|
|
||||||
if (snapshot.connectionState == ConnectionState.done)
|
|
||||||
{
|
|
||||||
sections = new List<SectionDTO>.from(snapshot.data).where((section) => !section.isSubSection!).toList();
|
|
||||||
return bodyGrid(configurationDTO, size, appContext);
|
|
||||||
}
|
|
||||||
else if (snapshot.connectionState == ConnectionState.none) {
|
|
||||||
return Text("No data");
|
|
||||||
} else {
|
|
||||||
return Center(
|
|
||||||
child: Container(
|
|
||||||
height: size.height * 0.15,
|
|
||||||
child: CommonLoader()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),// FIELDS SECTION
|
|
||||||
Container(
|
|
||||||
height: size.height *0.08,
|
|
||||||
//color: Colors.greenAccent,
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: getButtons(configurationDTO, appContext)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getButtons(ConfigurationDTO configurationDTO, AppContext appContext) {
|
// ── Header ──
|
||||||
final canEdit = (appContext.getContext() as ManagerAppContext).canEdit;
|
|
||||||
return Align(
|
Widget _buildHeader(ConfigurationDTO config, AppContext appContext, AppLocalizations l) {
|
||||||
alignment: AlignmentDirectional.bottomCenter,
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: kWhite,
|
||||||
|
border: Border(bottom: BorderSide(color: kSecond, width: 1)),
|
||||||
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
IconButton(
|
||||||
padding: const EdgeInsets.all(5.0),
|
icon: const Icon(Icons.arrow_back, color: kPrimaryColor),
|
||||||
child: RoundedButton(
|
onPressed: () {
|
||||||
text: AppLocalizations.of(context)!.cancel,
|
ManagerAppContext ctx = appContext.getContext();
|
||||||
icon: Icons.undo,
|
ctx.selectedConfiguration = null;
|
||||||
color: Colors.grey,
|
appContext.setContext(ctx);
|
||||||
textColor: Colors.white,
|
},
|
||||||
fontSize: 15,
|
),
|
||||||
press: () {
|
const SizedBox(width: 8),
|
||||||
cancel(configurationDTO, appContext);
|
Expanded(
|
||||||
},
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
config.label ?? '',
|
||||||
|
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
DateFormat('dd/MM/yyyy').format(config.dateCreation!),
|
||||||
|
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w300, color: Colors.grey),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (canEdit) Padding(
|
IconButton(
|
||||||
padding: const EdgeInsets.all(5.0),
|
icon: const Icon(Icons.download_outlined, color: kPrimaryColor),
|
||||||
child: RoundedButton(
|
tooltip: l.configExportSuccess(''),
|
||||||
text: AppLocalizations.of(context)!.delete,
|
onPressed: () => _export(config, appContext),
|
||||||
icon: Icons.delete,
|
|
||||||
color: kError,
|
|
||||||
textColor: Colors.white,
|
|
||||||
fontSize: 15,
|
|
||||||
press: () {
|
|
||||||
delete(configurationDTO, appContext);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (canEdit) Padding(
|
|
||||||
padding: const EdgeInsets.all(5.0),
|
|
||||||
child: RoundedButton(
|
|
||||||
text: AppLocalizations.of(context)!.save,
|
|
||||||
icon: Icons.done,
|
|
||||||
color: kSuccess,
|
|
||||||
textColor: Colors.white,
|
|
||||||
fontSize: 15,
|
|
||||||
press: () {
|
|
||||||
save(configurationDTO, appContext);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget bodyGrid(ConfigurationDTO configurationDTO, Size size, AppContext appContext) {
|
// ── Footer ──
|
||||||
return SingleChildScrollView(
|
|
||||||
child: Container(
|
|
||||||
height: size.height *0.40,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: SectionReorderList(
|
|
||||||
sectionsIn: sections!,
|
|
||||||
configurationId: configurationDTO.id!,
|
|
||||||
onChangedOrder: (List<SectionDTO> sectionsOut) async {
|
|
||||||
sections = sectionsOut;
|
|
||||||
|
|
||||||
// Update section order
|
Widget _buildFooter(ConfigurationDTO config, AppContext appContext, bool canEdit, AppLocalizations l) {
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
return Container(
|
||||||
await managerAppContext.clientAPI!.sectionApi!.sectionUpdateOrder(sections!);
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||||
},
|
decoration: const BoxDecoration(
|
||||||
askReload: () {
|
color: kWhite,
|
||||||
setState(() {
|
boxShadow: [BoxShadow(color: kSecond, blurRadius: 8, offset: Offset(0, -2))],
|
||||||
// refresh UI
|
),
|
||||||
});
|
child: Row(
|
||||||
},
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
),
|
children: [
|
||||||
|
OutlinedButton.icon(
|
||||||
|
icon: const Icon(Icons.undo, size: 16),
|
||||||
|
label: Text(l.cancel),
|
||||||
|
onPressed: () => cancel(config, appContext),
|
||||||
|
),
|
||||||
|
if (canEdit) ...[
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
ElevatedButton.icon(
|
||||||
|
icon: const Icon(Icons.delete, size: 16, color: kWhite),
|
||||||
|
label: Text(l.delete, style: const TextStyle(color: kWhite)),
|
||||||
|
style: ElevatedButton.styleFrom(backgroundColor: kError),
|
||||||
|
onPressed: () => delete(config, appContext),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
ElevatedButton.icon(
|
||||||
|
icon: const Icon(Icons.done, size: 16, color: kWhite),
|
||||||
|
label: Text(l.save, style: const TextStyle(color: kWhite)),
|
||||||
|
style: ElevatedButton.styleFrom(backgroundColor: kPrimaryColor),
|
||||||
|
onPressed: () => save(config, appContext),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Card Général ──
|
||||||
|
|
||||||
|
Widget _cardGeneral(ConfigurationDTO config, AppLocalizations l) {
|
||||||
|
return Card(
|
||||||
|
elevation: 0,
|
||||||
|
color: kWhite,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(l.identifierLabel.replaceAll(':', '').trim(),
|
||||||
|
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: kTitleTextColor)),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
StringInputContainer(
|
||||||
|
label: l.identifierLabel,
|
||||||
|
fontSize: 16,
|
||||||
|
fontSizeText: 16,
|
||||||
|
initialValue: config.label,
|
||||||
|
onChanged: (value) => config.label = value,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Wrap(
|
||||||
|
spacing: 24,
|
||||||
|
runSpacing: 12,
|
||||||
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
|
children: [
|
||||||
|
MultiSelectDropdownLanguageContainer(
|
||||||
|
label: l.languagesLabel,
|
||||||
|
initialValue: config.languages ?? [],
|
||||||
|
values: languages,
|
||||||
|
isMultiple: true,
|
||||||
|
fontSize: 16,
|
||||||
|
isAtLeastOne: true,
|
||||||
|
onChanged: (value) {
|
||||||
|
config.languages = List<String>.from(value);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
CheckInputContainer(
|
||||||
|
icon: Icons.signal_wifi_off,
|
||||||
|
label: "Hors ligne :",
|
||||||
|
fontSize: 16,
|
||||||
|
isChecked: config.isOffline,
|
||||||
|
onChanged: (value) => config.isOffline = value,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> cancel(ConfigurationDTO configurationDTO, AppContext appContext) async {
|
// ── Card Images ──
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
|
||||||
ConfigurationDTO? configuration = await managerAppContext.clientAPI!.configurationApi!.configurationGetDetail(configurationDTO.id!);
|
|
||||||
managerAppContext.selectedConfiguration = configuration;
|
|
||||||
appContext.setContext(managerAppContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> delete(ConfigurationDTO configurationDTO, AppContext appContext) async {
|
Widget _cardImages(ConfigurationDTO config, AppLocalizations l) {
|
||||||
showConfirmationDialog(
|
return Card(
|
||||||
AppLocalizations.of(context)!.configDeleteConfirm,
|
elevation: 0,
|
||||||
() {},
|
color: kWhite,
|
||||||
() async {
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
child: Padding(
|
||||||
await managerAppContext.clientAPI!.configurationApi!.configurationDelete(configurationDTO.id!);
|
padding: const EdgeInsets.all(16),
|
||||||
managerAppContext.selectedConfiguration = null;
|
child: Column(
|
||||||
appContext.setContext(managerAppContext);
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
showNotification(kSuccess, kWhite, AppLocalizations.of(context)!.configDeletedSuccess, context, null);
|
children: [
|
||||||
},
|
const Text("Images",
|
||||||
context
|
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: kTitleTextColor)),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
final isWide = constraints.maxWidth > kBreakpointMobile;
|
||||||
|
final children = [
|
||||||
|
ResourceInputContainer(
|
||||||
|
label: l.mainImageLabel,
|
||||||
|
fontSize: 16,
|
||||||
|
initialValue: config.imageId,
|
||||||
|
color: kPrimaryColor,
|
||||||
|
onChanged: (ResourceDTO resource) {
|
||||||
|
if (resource.id == null) {
|
||||||
|
config.imageId = null;
|
||||||
|
config.imageSource = null;
|
||||||
|
} else {
|
||||||
|
config.imageId = resource.id;
|
||||||
|
config.imageSource = resource.url;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ResourceInputContainer(
|
||||||
|
label: l.loaderLabel,
|
||||||
|
fontSize: 16,
|
||||||
|
initialValue: config.loaderImageId,
|
||||||
|
color: kPrimaryColor,
|
||||||
|
onChanged: (ResourceDTO resource) {
|
||||||
|
if (resource.id == null) {
|
||||||
|
config.loaderImageId = null;
|
||||||
|
config.loaderImageUrl = null;
|
||||||
|
} else {
|
||||||
|
config.loaderImageId = resource.id;
|
||||||
|
config.loaderImageUrl = resource.url;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (isWide) {
|
||||||
|
return Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: children.map((c) => Expanded(child: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 16),
|
||||||
|
child: c,
|
||||||
|
))).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: children.map((c) => Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 12),
|
||||||
|
child: c,
|
||||||
|
)).toList(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> save(ConfigurationDTO configurationDTO, AppContext appContext) async {
|
// ── Card Sections ──
|
||||||
|
|
||||||
|
Widget _cardSections(ConfigurationDTO config, AppContext appContext) {
|
||||||
|
final managerCtx = appContext.getContext() as ManagerAppContext;
|
||||||
|
_sectionsFuture ??= getSections(config, managerCtx.clientAPI!);
|
||||||
|
|
||||||
|
return Card(
|
||||||
|
elevation: 0,
|
||||||
|
color: kWhite,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text("Sections",
|
||||||
|
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: kTitleTextColor)),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
FutureBuilder<List<SectionDTO>?>(
|
||||||
|
future: _sectionsFuture,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
|
if (snapshot.data == null) return const Text("No data");
|
||||||
|
sections = List<SectionDTO>.from(snapshot.data!)
|
||||||
|
.where((s) => !s.isSubSection!)
|
||||||
|
.toList();
|
||||||
|
return SectionReorderList(
|
||||||
|
sectionsIn: sections!,
|
||||||
|
configurationId: config.id!,
|
||||||
|
onChangedOrder: (List<SectionDTO> sectionsOut) async {
|
||||||
|
sections = sectionsOut;
|
||||||
|
await managerCtx.clientAPI!.sectionApi!.sectionUpdateOrder(sections!);
|
||||||
|
},
|
||||||
|
askReload: () => setState(() {
|
||||||
|
_sectionsFuture = null;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} else if (snapshot.connectionState == ConnectionState.none) {
|
||||||
|
return const Text("No data");
|
||||||
|
}
|
||||||
|
return const Center(child: Padding(
|
||||||
|
padding: EdgeInsets.all(32),
|
||||||
|
child: CommonLoader(),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Actions ──
|
||||||
|
|
||||||
|
void _export(ConfigurationDTO config, AppContext appContext) async {
|
||||||
|
final l = AppLocalizations.of(context)!;
|
||||||
|
try {
|
||||||
|
Client clientAPI = (appContext.getContext() as ManagerAppContext).clientAPI!;
|
||||||
|
await clientAPI.configurationApi!.configurationExport(config.id!);
|
||||||
|
|
||||||
|
if (kIsWeb) {
|
||||||
|
html.AnchorElement anchorElement = html.AnchorElement();
|
||||||
|
var uri = Uri.parse('${clientAPI.resourceApi!.apiClient.basePath}/api/Configuration/${config.id}/export');
|
||||||
|
anchorElement.href = uri.toString();
|
||||||
|
anchorElement.download = '${config.label}.json';
|
||||||
|
anchorElement.click();
|
||||||
|
} else {
|
||||||
|
ExportConfigurationDTO export = await clientAPI.configurationApi!.configurationExport(config.id!);
|
||||||
|
File test = await FileHelper().storeConfiguration(export);
|
||||||
|
showNotification(kSuccess, kWhite, l.configExportSuccess(test.path), context, 3000);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
log(e.toString());
|
||||||
|
showNotification(kPrimaryColor, kWhite, l.configExportFailed, context, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> cancel(ConfigurationDTO config, AppContext appContext) async {
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
ManagerAppContext managerAppContext = appContext.getContext();
|
||||||
ConfigurationDTO? configuration = await managerAppContext.clientAPI!.configurationApi!.configurationUpdate(configurationDTO);
|
ConfigurationDTO? configuration = await managerAppContext.clientAPI!.configurationApi!.configurationGetDetail(config.id!);
|
||||||
managerAppContext.selectedConfiguration = configuration;
|
managerAppContext.selectedConfiguration = configuration;
|
||||||
appContext.setContext(managerAppContext);
|
appContext.setContext(managerAppContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> delete(ConfigurationDTO config, AppContext appContext) async {
|
||||||
|
showConfirmationDialog(
|
||||||
|
AppLocalizations.of(context)!.configDeleteConfirm,
|
||||||
|
() {},
|
||||||
|
() async {
|
||||||
|
ManagerAppContext managerAppContext = appContext.getContext();
|
||||||
|
await managerAppContext.clientAPI!.configurationApi!.configurationDelete(config.id!);
|
||||||
|
managerAppContext.selectedConfiguration = null;
|
||||||
|
appContext.setContext(managerAppContext);
|
||||||
|
showNotification(kSuccess, kWhite, AppLocalizations.of(context)!.configDeletedSuccess, context, null);
|
||||||
|
},
|
||||||
|
context,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> save(ConfigurationDTO config, AppContext appContext) async {
|
||||||
|
ManagerAppContext managerAppContext = appContext.getContext();
|
||||||
|
ConfigurationDTO? configuration = await managerAppContext.clientAPI!.configurationApi!.configurationUpdate(config);
|
||||||
|
managerAppContext.selectedConfiguration = configuration;
|
||||||
|
appContext.setContext(managerAppContext);
|
||||||
showNotification(kSuccess, kWhite, AppLocalizations.of(context)!.configSavedSuccess, context, null);
|
showNotification(kSuccess, kWhite, AppLocalizations.of(context)!.configSavedSuccess, context, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ConfigurationDTO?> getConfiguration(ConfigurationDetailScreen widget, Client client) async {
|
Future<ConfigurationDTO?> getConfiguration(ConfigurationDetailScreen widget, Client client) async {
|
||||||
ConfigurationDTO? configuration = await client.configurationApi!.configurationGetDetail(widget.id);
|
return await client.configurationApi!.configurationGetDetail(widget.id);
|
||||||
return configuration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<SectionDTO>?> getSections(ConfigurationDTO configurationDTO, Client client) async {
|
Future<List<SectionDTO>?> getSections(ConfigurationDTO config, Client client) async {
|
||||||
List<SectionDTO>? sections = await client.sectionApi!.sectionGetFromConfiguration(configurationDTO.id!);
|
List<SectionDTO>? sections = await client.sectionApi!.sectionGetFromConfiguration(config.id!);
|
||||||
if(sections != null) {
|
if (sections != null) {
|
||||||
sections.sort((a, b) => a.order!.compareTo(b.order!));
|
sections.sort((a, b) => a.order!.compareTo(b.order!));
|
||||||
}
|
}
|
||||||
return sections;
|
return sections;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boxDecoration(dynamic element) {
|
|
||||||
return BoxDecoration(
|
|
||||||
color: element.id == null ? kSuccess : kTextLightColor,
|
|
||||||
shape: BoxShape.rectangle,
|
|
||||||
borderRadius: BorderRadius.circular(25.0),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: kSecond,
|
|
||||||
spreadRadius: 0.5,
|
|
||||||
blurRadius: 5,
|
|
||||||
offset: Offset(0, 1.5), // changes position of shadow
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import 'package:auto_size_text/auto_size_text.dart';
|
import 'package:auto_size_text/auto_size_text.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:manager_app/Components/common_loader.dart';
|
import 'package:manager_app/Components/common_loader.dart';
|
||||||
|
import 'package:manager_app/Components/string_input_container.dart';
|
||||||
import 'package:manager_app/l10n/app_localizations.dart';
|
import 'package:manager_app/l10n/app_localizations.dart';
|
||||||
import 'package:manager_app/Components/message_notification.dart';
|
import 'package:manager_app/Components/message_notification.dart';
|
||||||
import 'package:manager_app/Models/managerContext.dart';
|
import 'package:manager_app/Models/managerContext.dart';
|
||||||
@ -23,255 +24,249 @@ class ConfigurationsScreen extends StatefulWidget {
|
|||||||
|
|
||||||
class _ConfigurationsScreenState extends State<ConfigurationsScreen> {
|
class _ConfigurationsScreenState extends State<ConfigurationsScreen> {
|
||||||
ConfigurationDTO? selectedConfiguration;
|
ConfigurationDTO? selectedConfiguration;
|
||||||
|
String _filter = '';
|
||||||
|
Future<List<ConfigurationDTO>?>? _future;
|
||||||
|
|
||||||
|
void _refresh() => setState(() => _future = null);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final appContext = Provider.of<AppContext>(context);
|
final appContext = Provider.of<AppContext>(context);
|
||||||
Size size = MediaQuery.of(context).size;
|
final Size size = MediaQuery.of(context).size;
|
||||||
|
final ManagerAppContext managerAppContext = appContext.getContext();
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
|
||||||
|
|
||||||
if (managerAppContext.selectedSection != null) {
|
if (managerAppContext.selectedSection != null) {
|
||||||
return SectionDetailScreen(id: managerAppContext.selectedSection!.id!);
|
return SectionDetailScreen(id: managerAppContext.selectedSection!.id!);
|
||||||
}
|
}
|
||||||
if (managerAppContext.selectedConfiguration != null) {
|
if (managerAppContext.selectedConfiguration != null) {
|
||||||
return ConfigurationDetailScreen(id: managerAppContext.selectedConfiguration!.id!);
|
return ConfigurationDetailScreen(id: managerAppContext.selectedConfiguration!.id!);
|
||||||
} else {
|
|
||||||
return Align(
|
|
||||||
alignment: AlignmentDirectional.topCenter,
|
|
||||||
child: FutureBuilder(
|
|
||||||
future: getConfigurations(managerAppContext),
|
|
||||||
builder: (context, AsyncSnapshot<dynamic> snapshot) {
|
|
||||||
if (snapshot.connectionState == ConnectionState.done) {
|
|
||||||
var tempOutput = new List<ConfigurationDTO>.from(snapshot.data);
|
|
||||||
if (managerAppContext.canEdit) tempOutput.add(ConfigurationDTO(id: null));
|
|
||||||
return bodyGrid(tempOutput, size, appContext, context);
|
|
||||||
} else if (snapshot.connectionState == ConnectionState.none) {
|
|
||||||
return Text(AppLocalizations.of(context)!.noData);
|
|
||||||
} else {
|
|
||||||
return Center(
|
|
||||||
child: Container(
|
|
||||||
height: size.height * 0.2,
|
|
||||||
child: CommonLoader()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Widget bodyGrid(data, Size size, AppContext appContext, BuildContext mainContext) {
|
_future ??= getConfigurations(managerAppContext);
|
||||||
final screenWidth = MediaQuery.of(context).size.width;
|
|
||||||
final itemWidth = 175;
|
|
||||||
final crossAxisCount = (screenWidth / itemWidth).floor().clamp(1, 6);
|
|
||||||
return GridView.builder(
|
|
||||||
shrinkWrap: true,
|
|
||||||
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: crossAxisCount),
|
|
||||||
itemCount: data.length,
|
|
||||||
itemBuilder: (BuildContext context, int index) {
|
|
||||||
return
|
|
||||||
InkWell(
|
|
||||||
onTap: () async {
|
|
||||||
if (data[index].id == null) {
|
|
||||||
var configurationToCreate = await showNewConfiguration(appContext, (bool) {
|
|
||||||
if (bool) {
|
|
||||||
setState(() {
|
|
||||||
// Thanks future builder for the refresh..
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, context, mainContext);
|
|
||||||
if(configurationToCreate != null) {
|
|
||||||
if (configurationToCreate.label != null) {
|
|
||||||
configurationToCreate.dateCreation = DateTime.now();
|
|
||||||
/*configurationToCreate.isMobile = false;
|
|
||||||
configurationToCreate.isTablet = false;*/
|
|
||||||
configurationToCreate.isOffline = false;
|
|
||||||
/*configurationToCreate.isDate = false;
|
|
||||||
configurationToCreate.isHour = false;
|
|
||||||
configurationToCreate.isSectionImageBackground = false;*/
|
|
||||||
configurationToCreate.instanceId = (appContext.getContext() as ManagerAppContext).instanceId;
|
|
||||||
await (appContext.getContext() as ManagerAppContext).clientAPI!.configurationApi!.configurationCreate(configurationToCreate);
|
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
|
||||||
managerAppContext.selectedConfiguration = null;
|
|
||||||
await appContext.setContext(managerAppContext);
|
|
||||||
|
|
||||||
showNotification(kSuccess, kWhite, AppLocalizations.of(context)!.configCreatedSuccess, context, null);
|
return Align(
|
||||||
}
|
alignment: AlignmentDirectional.topCenter,
|
||||||
}
|
child: FutureBuilder(
|
||||||
} else {
|
future: _future,
|
||||||
setState(() {
|
builder: (context, AsyncSnapshot<dynamic> snapshot) {
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
managerAppContext.selectedConfiguration = data[index];
|
var all = List<ConfigurationDTO>.from(snapshot.data);
|
||||||
selectedConfiguration = data[index];
|
if (managerAppContext.canEdit) all.add(ConfigurationDTO(id: null));
|
||||||
});
|
|
||||||
}
|
final filtered = _filter.isEmpty
|
||||||
},
|
? all
|
||||||
|
: all
|
||||||
|
.where((c) =>
|
||||||
|
c.id == null ||
|
||||||
|
(c.label?.toLowerCase().contains(_filter.toLowerCase()) ??
|
||||||
|
false))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return _buildGrid(filtered, size, appContext, context);
|
||||||
|
} else if (snapshot.connectionState == ConnectionState.none) {
|
||||||
|
return Text(AppLocalizations.of(context)!.noData);
|
||||||
|
} else {
|
||||||
|
return Center(
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: boxDecoration(data[index]),
|
height: size.height * 0.2,
|
||||||
padding: const EdgeInsets.all(15),
|
child: CommonLoader(),
|
||||||
margin: EdgeInsets.symmetric(vertical: 15, horizontal: 15),
|
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: getElement(data[index], size)
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getElement(ConfigurationDTO configuration, Size size) {
|
Widget _buildGrid(List<ConfigurationDTO> data, Size size, AppContext appContext,
|
||||||
if (configuration.id != null) {
|
BuildContext mainContext) {
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
Padding(
|
||||||
children: [
|
padding: const EdgeInsets.fromLTRB(12, 12, 12, 4),
|
||||||
Align(
|
child: Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: AutoSizeText(
|
child: SizedBox(
|
||||||
configuration.label!,
|
width: 280,
|
||||||
style: new TextStyle(fontSize: 25),
|
child: StringInputContainer(
|
||||||
maxLines: 1,
|
label: AppLocalizations.of(context)!.searchLabel,
|
||||||
|
onChanged: (v) => setState(() => _filter = v),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Align(
|
),
|
||||||
alignment: Alignment.bottomRight,
|
Expanded(
|
||||||
child: AutoSizeText(
|
child: GridView.builder(
|
||||||
DateFormat('dd/MM/yyyy').format(configuration.dateCreation!),
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
||||||
style: new TextStyle(fontSize: 18, fontFamily: ""),
|
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
|
||||||
maxLines: 1,
|
maxCrossAxisExtent: 220,
|
||||||
|
childAspectRatio: 1.5,
|
||||||
|
mainAxisSpacing: 10,
|
||||||
|
crossAxisSpacing: 10,
|
||||||
),
|
),
|
||||||
|
itemCount: data.length,
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
return _ConfigCard(
|
||||||
|
config: data[index],
|
||||||
|
onTap: () => _onTap(data[index], appContext, mainContext),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _onTap(
|
||||||
|
ConfigurationDTO config, AppContext appContext, BuildContext mainContext) async {
|
||||||
|
if (config.id == null) {
|
||||||
|
var configurationToCreate = await showNewConfiguration(
|
||||||
|
appContext,
|
||||||
|
(bool refresh) {
|
||||||
|
if (refresh) _refresh();
|
||||||
|
},
|
||||||
|
context,
|
||||||
|
mainContext,
|
||||||
);
|
);
|
||||||
|
if (configurationToCreate != null && configurationToCreate.label != null) {
|
||||||
|
configurationToCreate.dateCreation = DateTime.now();
|
||||||
|
configurationToCreate.isOffline = false;
|
||||||
|
configurationToCreate.instanceId =
|
||||||
|
(appContext.getContext() as ManagerAppContext).instanceId;
|
||||||
|
await (appContext.getContext() as ManagerAppContext)
|
||||||
|
.clientAPI!
|
||||||
|
.configurationApi!
|
||||||
|
.configurationCreate(configurationToCreate);
|
||||||
|
final ctx = appContext.getContext() as ManagerAppContext;
|
||||||
|
ctx.selectedConfiguration = null;
|
||||||
|
await appContext.setContext(ctx);
|
||||||
|
showNotification(
|
||||||
|
kSuccess, kWhite, AppLocalizations.of(context)!.configCreatedSuccess, context, null);
|
||||||
|
_refresh();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return Icon(
|
setState(() {
|
||||||
Icons.add,
|
final ctx = appContext.getContext() as ManagerAppContext;
|
||||||
color: kTextLightColor,
|
ctx.selectedConfiguration = config;
|
||||||
size: size.height*0.1,
|
selectedConfiguration = config;
|
||||||
);
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<ConfigurationDTO>?> getConfigurations(ManagerAppContext managerAppContext) async {
|
class _ConfigCard extends StatefulWidget {
|
||||||
List<ConfigurationDTO>? configurations = await managerAppContext.clientAPI!.configurationApi!.configurationGet(instanceId: managerAppContext.instanceId);
|
final ConfigurationDTO config;
|
||||||
//print("number of configurations " + configurations.length.toString());
|
final VoidCallback onTap;
|
||||||
if(configurations != null) {
|
const _ConfigCard({required this.config, required this.onTap});
|
||||||
configurations.forEach((element) {
|
|
||||||
//print(element);
|
@override
|
||||||
});
|
State<_ConfigCard> createState() => _ConfigCardState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ConfigCardState extends State<_ConfigCard> {
|
||||||
|
bool _hovered = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final config = widget.config;
|
||||||
|
final isAdd = config.id == null;
|
||||||
|
final hasImage = config.imageSource != null;
|
||||||
|
|
||||||
|
return MouseRegion(
|
||||||
|
onEnter: (_) => setState(() => _hovered = true),
|
||||||
|
onExit: (_) => setState(() => _hovered = false),
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: widget.onTap,
|
||||||
|
child: AnimatedScale(
|
||||||
|
scale: _hovered ? 1.03 : 1.0,
|
||||||
|
duration: const Duration(milliseconds: 150),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: kSecond,
|
||||||
|
spreadRadius: _hovered ? 1 : 0.5,
|
||||||
|
blurRadius: _hovered ? 10 : 5,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
child: Stack(
|
||||||
|
fit: StackFit.expand,
|
||||||
|
children: [
|
||||||
|
// Background
|
||||||
|
if (!isAdd && hasImage)
|
||||||
|
Image.network(config.imageSource!, fit: BoxFit.cover)
|
||||||
|
else
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: isAdd
|
||||||
|
? [kSuccess, kSuccess.withOpacity(0.7)]
|
||||||
|
: [kPrimaryColor, kPrimaryColor.withOpacity(0.6)],
|
||||||
|
begin: Alignment.topLeft,
|
||||||
|
end: Alignment.bottomRight,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Gradient scrim
|
||||||
|
if (!isAdd)
|
||||||
|
DecoratedBox(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
begin: Alignment.topCenter,
|
||||||
|
end: Alignment.bottomCenter,
|
||||||
|
stops: const [0.35, 1.0],
|
||||||
|
colors: [
|
||||||
|
Colors.transparent,
|
||||||
|
Colors.black.withOpacity(0.65),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Content
|
||||||
|
if (isAdd)
|
||||||
|
const Center(
|
||||||
|
child: Icon(Icons.add, color: kTextLightColor, size: 36),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
Positioned(
|
||||||
|
left: 10,
|
||||||
|
right: 10,
|
||||||
|
bottom: 10,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
AutoSizeText(
|
||||||
|
config.label ?? '',
|
||||||
|
style: kCardTitleStyle,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
if (config.dateCreation != null)
|
||||||
|
Text(
|
||||||
|
DateFormat('dd/MM/yyyy').format(config.dateCreation!),
|
||||||
|
style: kCardSubtitleStyle,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return configurations;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boxDecoration(ConfigurationDTO configurationDTO) {
|
Future<List<ConfigurationDTO>?> getConfigurations(
|
||||||
return BoxDecoration(
|
ManagerAppContext managerAppContext) async {
|
||||||
color: configurationDTO.id == null ? kSuccess : kTextLightColor,
|
return managerAppContext.clientAPI!.configurationApi!
|
||||||
shape: BoxShape.rectangle,
|
.configurationGet(instanceId: managerAppContext.instanceId);
|
||||||
borderRadius: BorderRadius.circular(25.0),
|
|
||||||
image: configurationDTO.imageSource != null ? new DecorationImage(
|
|
||||||
fit: BoxFit.cover,
|
|
||||||
colorFilter: new ColorFilter.mode(Colors.black.withOpacity(0.18), BlendMode.dstATop),
|
|
||||||
image: new NetworkImage(
|
|
||||||
configurationDTO.imageSource!,
|
|
||||||
),
|
|
||||||
) : null,
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: kSecond,
|
|
||||||
spreadRadius: 0.5,
|
|
||||||
blurRadius: 5,
|
|
||||||
offset: Offset(0, 1.5), // changes position of shadow
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*Widget bodyTable(data) => DataTable(
|
|
||||||
sortColumnIndex: 0,
|
|
||||||
sortAscending: true,
|
|
||||||
columns: <DataColumn>[
|
|
||||||
DataColumn(
|
|
||||||
label: Text("Label"),
|
|
||||||
onSort: (_, __) {
|
|
||||||
setState(() {
|
|
||||||
// data.sort((a) => a.label);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: Text("Primary color"),
|
|
||||||
onSort: (_, __) {
|
|
||||||
setState(() {
|
|
||||||
/*data.sort((a, b) => a.data["stats"]["dividendYield"]
|
|
||||||
.compareTo(b.data["stats"]["dividendYield"]));*/
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: Text("Secondary color"),
|
|
||||||
onSort: (_, __) {
|
|
||||||
setState(() {
|
|
||||||
/*data.sort((a, b) => a.data["quote"]["iexBidPrice"]
|
|
||||||
.compareTo(b.data["quote"]["iexBidPrice"]));*/
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: Text("Languages"),
|
|
||||||
onSort: (_, __) {
|
|
||||||
setState(() {
|
|
||||||
/*data.sort((a, b) => a.data["stats"]["latestPrice"]
|
|
||||||
.compareTo(b.data["stats"]["latestPrice"]));*/
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: Text("Date creation"),
|
|
||||||
onSort: (_, __) {
|
|
||||||
setState(() {
|
|
||||||
/*data.sort((a, b) => a.data["stats"]["latestPrice"]
|
|
||||||
.compareTo(b.data["stats"]["latestPrice"]));*/
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
DataColumn(
|
|
||||||
label: Text("Actions"),
|
|
||||||
onSort: (_, __) {
|
|
||||||
setState(() {
|
|
||||||
/*data.sort((a, b) => a.data["stats"]["latestPrice"]
|
|
||||||
.compareTo(b.data["stats"]["latestPrice"]));*/
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
rows: data
|
|
||||||
.map<DataRow>( (configuration) => DataRow(
|
|
||||||
cells: [
|
|
||||||
DataCell(
|
|
||||||
Text('${configuration.label ?? ""}'),
|
|
||||||
),
|
|
||||||
DataCell(
|
|
||||||
Text('${configuration.primaryColor ?? ""}'),
|
|
||||||
),
|
|
||||||
DataCell(
|
|
||||||
Text('${configuration.secondaryColor ?? ""}'),
|
|
||||||
),
|
|
||||||
DataCell(
|
|
||||||
Text('${configuration.languages ?? ""}'),
|
|
||||||
),
|
|
||||||
DataCell(
|
|
||||||
Text('${configuration.dateCreation ?? ""}'),
|
|
||||||
),
|
|
||||||
DataCell(
|
|
||||||
Text("Todo buttons - open = edit, delete"),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
).toList()
|
|
||||||
);*/
|
|
||||||
|
|||||||
@ -14,114 +14,101 @@ import 'package:manager_api_new/api.dart';
|
|||||||
Future<ConfigurationDTO?> showNewConfiguration(AppContext appContext, ValueChanged<bool> isImport, BuildContext context, BuildContext mainContext) {
|
Future<ConfigurationDTO?> showNewConfiguration(AppContext appContext, ValueChanged<bool> isImport, BuildContext context, BuildContext mainContext) {
|
||||||
final l = AppLocalizations.of(mainContext)!;
|
final l = AppLocalizations.of(mainContext)!;
|
||||||
ConfigurationDTO configurationDTO = new ConfigurationDTO();
|
ConfigurationDTO configurationDTO = new ConfigurationDTO();
|
||||||
Size size = MediaQuery.of(mainContext).size;
|
|
||||||
configurationDTO.label = "";
|
configurationDTO.label = "";
|
||||||
|
|
||||||
var configuration = showDialog<ConfigurationDTO?>(
|
var configuration = showDialog<ConfigurationDTO?>(
|
||||||
builder: (BuildContext context) => AlertDialog(
|
builder: (BuildContext context) => Dialog(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
||||||
),
|
),
|
||||||
content: SingleChildScrollView(
|
child: SizedBox(
|
||||||
child: SizedBox(
|
width: 460,
|
||||||
width: size.width*0.35,
|
child: Padding(
|
||||||
height: size.height*0.3,
|
padding: const EdgeInsets.fromLTRB(24, 20, 24, 24),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Center(child: Text(l.newConfiguration, style: new TextStyle(fontSize: 25, fontWeight: FontWeight.w400))),
|
Flexible(
|
||||||
Center(
|
child: SingleChildScrollView(
|
||||||
child: SizedBox(
|
child: Column(
|
||||||
height: 100,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
child: StringInputContainer(
|
mainAxisSize: MainAxisSize.min,
|
||||||
label: l.configNameLabel,
|
children: [
|
||||||
initialValue: configurationDTO.label,
|
Center(child: Text(l.newConfiguration, style: new TextStyle(fontSize: 22, fontWeight: FontWeight.w400))),
|
||||||
onChanged: (value) {
|
SizedBox(height: 8),
|
||||||
configurationDTO.label = value;
|
SizedBox(
|
||||||
},
|
height: 90,
|
||||||
|
child: StringInputContainer(
|
||||||
|
label: l.configNameLabel,
|
||||||
|
initialValue: configurationDTO.label,
|
||||||
|
onChanged: (value) {
|
||||||
|
configurationDTO.label = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 8),
|
||||||
|
Text(l.orText),
|
||||||
|
SizedBox(height: 4),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 5.0),
|
||||||
|
child: Text(l.importLabel, style: TextStyle(fontSize: 18, fontWeight: FontWeight.w300)),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
onTap: () async {
|
||||||
|
FilePickerResult? result = await FilePicker.platform.pickFiles();
|
||||||
|
if (result != null) {
|
||||||
|
await FileHelper().importConfiguration(result, null, (appContext.getContext() as ManagerAppContext).clientAPI!, mainContext);
|
||||||
|
isImport(true);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
child: Icon(Icons.file_upload, color: kPrimaryColor, size: 30),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(l.orText),
|
const SizedBox(height: 16),
|
||||||
Column(
|
Wrap(
|
||||||
|
spacing: 8,
|
||||||
|
runSpacing: 8,
|
||||||
|
alignment: WrapAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
RoundedButton(
|
||||||
padding: const EdgeInsets.only(bottom: 5.0),
|
text: l.cancel,
|
||||||
child: Text(l.importLabel, style: TextStyle(fontSize: 25, fontWeight: FontWeight.w300)),
|
icon: Icons.undo,
|
||||||
|
color: kSecond,
|
||||||
|
press: () => Navigator.of(context).pop(),
|
||||||
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
InkWell(
|
RoundedButton(
|
||||||
onTap: () async {
|
text: l.create,
|
||||||
FilePickerResult? result = await FilePicker.platform.pickFiles();
|
icon: Icons.check,
|
||||||
|
color: kPrimaryColor,
|
||||||
//String result = filePicker();
|
textColor: kWhite,
|
||||||
if (result != null) {
|
press: () {
|
||||||
|
if(configurationDTO.label != null && configurationDTO.label!.length > 2) {
|
||||||
await FileHelper().importConfiguration(result, null, (appContext.getContext() as ManagerAppContext).clientAPI!, mainContext);
|
Navigator.of(context).pop(configurationDTO);
|
||||||
isImport(true);
|
} else {
|
||||||
Navigator.of(context).pop();
|
showNotification(Colors.orange, kWhite, l.configNameRequired, context, null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Padding(
|
fontSize: 16,
|
||||||
padding: const EdgeInsets.all(10.0),
|
),
|
||||||
child: Icon(
|
],
|
||||||
Icons.file_upload,
|
),
|
||||||
color: kPrimaryColor,
|
|
||||||
size: 30
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: <Widget>[
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: 175,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: l.cancel,
|
|
||||||
icon: Icons.undo,
|
|
||||||
color: kSecond,
|
|
||||||
press: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: 150,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: l.create,
|
|
||||||
icon: Icons.check,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
textColor: kWhite,
|
|
||||||
press: () {
|
|
||||||
if(configurationDTO.label != null && configurationDTO.label!.length > 2) {
|
|
||||||
//create(configurationDTO, appContext, context);
|
|
||||||
Navigator.of(context).pop(configurationDTO);
|
|
||||||
} else {
|
|
||||||
showNotification(Colors.orange, kWhite, l.configNameRequired, context, null);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
), context: context
|
), context: context
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -129,38 +116,12 @@ Future<ConfigurationDTO?> showNewConfiguration(AppContext appContext, ValueChang
|
|||||||
}
|
}
|
||||||
|
|
||||||
String filePicker() {
|
String filePicker() {
|
||||||
/*final file = OpenFilePicker()
|
|
||||||
..filterSpecification = {
|
|
||||||
'Fichier (*.json)': '*.json',
|
|
||||||
//'Video (*.mp4)': '*.mp4',
|
|
||||||
//'All Files': '*.*'
|
|
||||||
}
|
|
||||||
..defaultFilterIndex = 0
|
|
||||||
..title = 'Sélectionner un fichier';
|
|
||||||
|
|
||||||
final result = file.getFile();*/
|
|
||||||
var result;
|
var result;
|
||||||
|
|
||||||
return result != null ? result.path : null;
|
return result != null ? result.path : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void create(ConfigurationDTO configurationDTO, AppContext appContext, context) async {
|
void create(ConfigurationDTO configurationDTO, AppContext appContext, context) async {
|
||||||
if (configurationDTO.label != null) {
|
if (configurationDTO.label != null) {
|
||||||
/*configurationDTO.dateCreation = DateTime.now();
|
|
||||||
configurationDTO.isMobile = false;
|
|
||||||
configurationDTO.isTablet = false;
|
|
||||||
configurationDTO.isOffline = false;
|
|
||||||
configurationDTO.isDate = false;
|
|
||||||
configurationDTO.isHour = false;
|
|
||||||
configurationDTO.isSectionImageBackground = false;
|
|
||||||
configurationDTO.instanceId = (appContext.getContext() as ManagerAppContext).instanceId;
|
|
||||||
await (appContext.getContext() as ManagerAppContext).clientAPI!.configurationApi!.configurationCreate(configurationDTO);
|
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
|
||||||
managerAppContext.selectedConfiguration = null;
|
|
||||||
await appContext.setContext(managerAppContext);
|
|
||||||
|
|
||||||
showNotification(Colors.green, kWhite, 'La configuration a été créée avec succès', context, null);*/
|
|
||||||
|
|
||||||
Navigator.of(context).pop(configurationDTO);
|
Navigator.of(context).pop(configurationDTO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,118 +23,130 @@ Future<SectionDTO?> showNewSection(String configurationId,
|
|||||||
sectionDTO.type = SectionType.Map;
|
sectionDTO.type = SectionType.Map;
|
||||||
|
|
||||||
var section = showDialog<SectionDTO?>(
|
var section = showDialog<SectionDTO?>(
|
||||||
builder: (BuildContext context) => AlertDialog(
|
builder: (BuildContext context) => Dialog(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(20.0))),
|
borderRadius: BorderRadius.all(Radius.circular(20.0))),
|
||||||
content: SingleChildScrollView(
|
child: SizedBox(
|
||||||
child: SizedBox(
|
width: 780,
|
||||||
width: 750,
|
child: Padding(
|
||||||
height: 250,
|
padding: const EdgeInsets.fromLTRB(24, 20, 24, 24),
|
||||||
child: Container(
|
child: Column(
|
||||||
constraints: BoxConstraints(minHeight: 300, minWidth: 300),
|
mainAxisSize: MainAxisSize.min,
|
||||||
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Flexible(
|
||||||
isSubSection
|
child: SingleChildScrollView(
|
||||||
? l.newSubSection
|
child: SizedBox(
|
||||||
: l.newSection,
|
height: 250,
|
||||||
style: new TextStyle(
|
child: Container(
|
||||||
fontSize: 25, fontWeight: FontWeight.w400)),
|
constraints: BoxConstraints(minHeight: 300, minWidth: 300),
|
||||||
Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
Text(
|
||||||
height: 100,
|
isSubSection
|
||||||
child: StringInputContainer(
|
? l.newSubSection
|
||||||
label: l.sectionNameLabel,
|
: l.newSection,
|
||||||
initialValue: sectionDTO.label,
|
style: new TextStyle(
|
||||||
onChanged: (value) {
|
fontSize: 25, fontWeight: FontWeight.w400)),
|
||||||
sectionDTO.label = value;
|
Column(
|
||||||
},
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: 100,
|
||||||
|
child: StringInputContainer(
|
||||||
|
label: l.sectionNameLabel,
|
||||||
|
initialValue: sectionDTO.label,
|
||||||
|
onChanged: (value) {
|
||||||
|
sectionDTO.label = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
DropDownInputContainer(
|
||||||
|
label: l.sectionTypeLabel,
|
||||||
|
values: isSubSection
|
||||||
|
? section_types
|
||||||
|
.where(
|
||||||
|
(sectionType) => sectionType != "Menu")
|
||||||
|
.toList()
|
||||||
|
: section_types
|
||||||
|
.toList(), // Todo get menu by enum type
|
||||||
|
initialValue: "Map",
|
||||||
|
onChange: (String? value) {
|
||||||
|
sectionDTO.type = SectionType.fromJson(value);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
/*MultiSelectContainer(
|
||||||
|
label: "Type:",
|
||||||
|
initialValue: isMobile ? ["Article"] : ["Map"],
|
||||||
|
isMultiple: false,
|
||||||
|
values: isMobile ? section_types.where((sectionType) => sectionType == "Article" || sectionType == "Quizz").toList(): isSubSection ? section_types.where((sectionType) => sectionType != "Menu" && sectionType != "Article").toList(): section_types.where((sectionType) => sectionType != "Article").toList(), // Todo get menu by enum type
|
||||||
|
onChanged: (value) {
|
||||||
|
var tempOutput = new List<String>.from(value);
|
||||||
|
sectionDTO.type = SectionType.fromJson(tempOutput[0]);
|
||||||
|
},
|
||||||
|
),*/
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
DropDownInputContainer(
|
),
|
||||||
label: l.sectionTypeLabel,
|
|
||||||
values: isSubSection
|
|
||||||
? section_types
|
|
||||||
.where(
|
|
||||||
(sectionType) => sectionType != "Menu")
|
|
||||||
.toList()
|
|
||||||
: section_types
|
|
||||||
.toList(), // Todo get menu by enum type
|
|
||||||
initialValue: "Map",
|
|
||||||
onChange: (String? value) {
|
|
||||||
sectionDTO.type = SectionType.fromJson(value);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
/*MultiSelectContainer(
|
|
||||||
label: "Type:",
|
|
||||||
initialValue: isMobile ? ["Article"] : ["Map"],
|
|
||||||
isMultiple: false,
|
|
||||||
values: isMobile ? section_types.where((sectionType) => sectionType == "Article" || sectionType == "Quizz").toList(): isSubSection ? section_types.where((sectionType) => sectionType != "Menu" && sectionType != "Article").toList(): section_types.where((sectionType) => sectionType != "Article").toList(), // Todo get menu by enum type
|
|
||||||
onChanged: (value) {
|
|
||||||
var tempOutput = new List<String>.from(value);
|
|
||||||
sectionDTO.type = SectionType.fromJson(tempOutput[0]);
|
|
||||||
},
|
|
||||||
),*/
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
const SizedBox(height: 16),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: [
|
||||||
|
Align(
|
||||||
|
alignment: AlignmentDirectional.bottomEnd,
|
||||||
|
child: Container(
|
||||||
|
width: 175,
|
||||||
|
height: 70,
|
||||||
|
child: RoundedButton(
|
||||||
|
text: l.cancel,
|
||||||
|
icon: Icons.undo,
|
||||||
|
color: kSecond,
|
||||||
|
press: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
fontSize: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Align(
|
||||||
|
alignment: AlignmentDirectional.bottomEnd,
|
||||||
|
child: Container(
|
||||||
|
width: 150,
|
||||||
|
height: 70,
|
||||||
|
child: RoundedButton(
|
||||||
|
text: l.create,
|
||||||
|
icon: Icons.check,
|
||||||
|
color: kPrimaryColor,
|
||||||
|
textColor: kWhite,
|
||||||
|
press: () {
|
||||||
|
if (sectionDTO.label != null &&
|
||||||
|
sectionDTO.label!.length > 2) {
|
||||||
|
//onYes();
|
||||||
|
Navigator.of(context).pop(sectionDTO);
|
||||||
|
//create(sectionDTO, appContext, context, isSubSection, sendSubSection);
|
||||||
|
} else {
|
||||||
|
showNotification(
|
||||||
|
Colors.orange,
|
||||||
|
kWhite,
|
||||||
|
l.sectionNameRequired,
|
||||||
|
context,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fontSize: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: <Widget>[
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: [
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: 175,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: l.cancel,
|
|
||||||
icon: Icons.undo,
|
|
||||||
color: kSecond,
|
|
||||||
press: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: 150,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: l.create,
|
|
||||||
icon: Icons.check,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
textColor: kWhite,
|
|
||||||
press: () {
|
|
||||||
if (sectionDTO.label != null &&
|
|
||||||
sectionDTO.label!.length > 2) {
|
|
||||||
//onYes();
|
|
||||||
Navigator.of(context).pop(sectionDTO);
|
|
||||||
//create(sectionDTO, appContext, context, isSubSection, sendSubSection);
|
|
||||||
} else {
|
|
||||||
showNotification(
|
|
||||||
Colors.orange,
|
|
||||||
kWhite,
|
|
||||||
l.sectionNameRequired,
|
|
||||||
context,
|
|
||||||
null);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
context: contextBuild);
|
context: contextBuild);
|
||||||
|
|
||||||
|
|||||||
@ -62,130 +62,92 @@ class _SectionReorderListState extends State<SectionReorderList> {
|
|||||||
final appContext = Provider.of<AppContext>(context);
|
final appContext = Provider.of<AppContext>(context);
|
||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
|
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
return Column(
|
||||||
ConfigurationDTO currentConfiguration = managerAppContext.selectedConfiguration!;
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
|
||||||
return Stack(
|
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Row(
|
||||||
padding: const EdgeInsets.only(left: 10.0, right: 10.0, bottom: 10.0, top: 15.0),
|
children: [
|
||||||
child: Container(
|
Expanded(
|
||||||
height: size.height*0.3,
|
child: StringInputContainer(
|
||||||
child: ReorderableListView.builder(
|
label: "Recherche:",
|
||||||
itemCount: sections.length,
|
isSmall: true,
|
||||||
onReorder: _onReorder,
|
fontSize: 15,
|
||||||
scrollDirection: Axis.horizontal,
|
fontSizeText: 15,
|
||||||
padding: const EdgeInsets.symmetric(vertical: 20.0),
|
onChanged: (String value) {
|
||||||
itemBuilder: (context, index) {
|
setState(() {
|
||||||
//final String productName = _products[index];
|
filterSearch = value;
|
||||||
return ListViewCardSections(
|
filterResource();
|
||||||
sections,
|
});
|
||||||
index,
|
|
||||||
Key('$index'),
|
|
||||||
false,
|
|
||||||
//currentConfiguration.isMobile!,
|
|
||||||
appContext,
|
|
||||||
(section) {
|
|
||||||
setState(() {
|
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
|
||||||
managerAppContext.selectedSection = section;
|
|
||||||
appContext.setContext(managerAppContext);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
/*children: List.generate(
|
|
||||||
sections.length,
|
|
||||||
(index) {
|
|
||||||
return ListViewCardSections(
|
|
||||||
sections,
|
|
||||||
index,
|
|
||||||
Key('$index'),
|
|
||||||
appContext,
|
|
||||||
(section) {
|
|
||||||
setState(() {
|
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
|
||||||
managerAppContext.selectedSection = section;
|
|
||||||
appContext.setContext(managerAppContext);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),*/
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 8),
|
||||||
),
|
InkWell(
|
||||||
Positioned(
|
onTap: () async {
|
||||||
top: 10,
|
var sectionToCreate = await showNewSection(widget.configurationId, appContext, context, false);
|
||||||
left: 10,
|
if (sectionToCreate != null) {
|
||||||
child: Text(
|
ManagerAppContext managerAppContext = appContext.getContext();
|
||||||
"Sections",
|
sectionToCreate.instanceId = managerAppContext.instanceId;
|
||||||
style: TextStyle(fontSize: 15),
|
sectionToCreate.isBeacon = false;
|
||||||
),
|
sectionToCreate.dateCreation = DateTime.now();
|
||||||
),
|
await managerAppContext.clientAPI!.sectionApi!.sectionCreate(sectionToCreate);
|
||||||
Positioned(
|
showNotification(kSuccess, kWhite, 'La section a été créée avec succès !', context, null);
|
||||||
bottom: -20,
|
widget.askReload();
|
||||||
left: 10,
|
}
|
||||||
child: Container(
|
|
||||||
height: size.height*0.1,
|
|
||||||
constraints: BoxConstraints(minHeight: 85),
|
|
||||||
child: StringInputContainer(
|
|
||||||
label: "Recherche:",
|
|
||||||
isSmall: true,
|
|
||||||
fontSize: 15,
|
|
||||||
fontSizeText: 15,
|
|
||||||
onChanged: (String value) {
|
|
||||||
setState(() {
|
|
||||||
filterSearch = value;
|
|
||||||
filterResource();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
child: Container(
|
||||||
|
height: 36,
|
||||||
|
width: 36,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: kSuccess,
|
||||||
|
shape: BoxShape.rectangle,
|
||||||
|
borderRadius: BorderRadius.circular(20.0),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: kSecond,
|
||||||
|
spreadRadius: 0.5,
|
||||||
|
blurRadius: 5,
|
||||||
|
offset: Offset(0, 1.5),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: const Icon(
|
||||||
|
Icons.add,
|
||||||
|
color: kTextLightColor,
|
||||||
|
size: 20.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
SizedBox(
|
||||||
|
height: size.height * 0.3,
|
||||||
|
child: ReorderableListView.builder(
|
||||||
|
itemCount: sections.length,
|
||||||
|
onReorder: _onReorder,
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return ListViewCardSections(
|
||||||
|
sections,
|
||||||
|
index,
|
||||||
|
Key('$index'),
|
||||||
|
false,
|
||||||
|
appContext,
|
||||||
|
(section) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
setState(() {
|
||||||
|
ManagerAppContext managerAppContext = appContext.getContext();
|
||||||
|
managerAppContext.selectedSection = section;
|
||||||
|
appContext.setContext(managerAppContext);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Positioned(
|
|
||||||
top: 10,
|
|
||||||
right: 10,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () async {
|
|
||||||
var sectionToCreate = await showNewSection(widget.configurationId, appContext, context, false);
|
|
||||||
if(sectionToCreate != null)
|
|
||||||
{
|
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
|
||||||
sectionToCreate.instanceId = managerAppContext.instanceId;
|
|
||||||
sectionToCreate.isBeacon = false;
|
|
||||||
sectionToCreate.dateCreation = DateTime.now();
|
|
||||||
SectionDTO? newSection = await managerAppContext.clientAPI!.sectionApi!.sectionCreate(sectionToCreate);
|
|
||||||
|
|
||||||
showNotification(kSuccess, kWhite, 'La section a été créée avec succès !', context, null);
|
|
||||||
|
|
||||||
widget.askReload();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
height: MediaQuery.of(context).size.width * 0.04,
|
|
||||||
width: MediaQuery.of(context).size.width * 0.04,
|
|
||||||
child: Icon(
|
|
||||||
Icons.add,
|
|
||||||
color: kTextLightColor,
|
|
||||||
size: 30.0,
|
|
||||||
),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: kSuccess,
|
|
||||||
shape: BoxShape.rectangle,
|
|
||||||
borderRadius: BorderRadius.circular(20.0),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: kSecond,
|
|
||||||
spreadRadius: 0.5,
|
|
||||||
blurRadius: 5,
|
|
||||||
offset: Offset(0, 1.5), // changes position of shadow
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,236 +15,221 @@ import 'package:manager_api_new/api.dart';
|
|||||||
import '../../Components/resource_input_container.dart';
|
import '../../Components/resource_input_container.dart';
|
||||||
import 'dropDown_configuration.dart';
|
import 'dropDown_configuration.dart';
|
||||||
|
|
||||||
showChangeInfo (String text, DeviceDTO inputDevice, AppConfigurationLinkDTO appConfiguration, Function onGetResult, int maxLines, BuildContext mainContext, dynamic appContext) async {
|
showChangeInfo(String text, DeviceDTO inputDevice, AppConfigurationLinkDTO appConfiguration, Function onGetResult, int maxLines, BuildContext mainContext, dynamic appContext) async {
|
||||||
Size size = MediaQuery.of(mainContext).size;
|
|
||||||
|
|
||||||
var result = await showDialog(
|
var result = await showDialog(
|
||||||
builder: (BuildContext context) => AlertDialog(
|
useRootNavigator: false,
|
||||||
|
builder: (BuildContext context) => Dialog(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
||||||
),
|
),
|
||||||
title: Center(child: Text(text)),
|
child: SizedBox(
|
||||||
content: Container(
|
width: 580,
|
||||||
width: size.width * 0.5,
|
child: Padding(
|
||||||
height: size.height * 0.5,
|
padding: const EdgeInsets.fromLTRB(24, 20, 24, 24),
|
||||||
constraints: BoxConstraints(minWidth: 400, minHeight: 500),
|
child: Column(
|
||||||
child: Column(
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Row(
|
children: [
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
Center(child: Text(text, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500))),
|
||||||
children: [
|
const SizedBox(height: 16),
|
||||||
Container(
|
Flexible(
|
||||||
width: size.width * 0.3,
|
child: SingleChildScrollView(
|
||||||
height: size.height * 0.15,
|
child: Column(
|
||||||
child: StringInputContainer(
|
mainAxisSize: MainAxisSize.min,
|
||||||
label: "Nom:",
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
initialValue: inputDevice.name,
|
children: [
|
||||||
onChanged: (value) {
|
// Nom + Configuration
|
||||||
inputDevice.name = value;
|
Wrap(
|
||||||
},
|
spacing: 16,
|
||||||
maxLength: 20,
|
runSpacing: 12,
|
||||||
),
|
children: [
|
||||||
),
|
SizedBox(
|
||||||
Row(
|
width: 220,
|
||||||
children: [
|
height: 90,
|
||||||
Align(
|
child: StringInputContainer(
|
||||||
alignment: AlignmentDirectional.centerStart,
|
label: "Nom:",
|
||||||
child: Text("Configuration:", style: TextStyle(fontSize: 25, fontWeight: FontWeight.w300))
|
initialValue: inputDevice.name,
|
||||||
),
|
onChanged: (value) => inputDevice.name = value,
|
||||||
Container(
|
maxLength: 20,
|
||||||
height: size.height * 0.1,
|
),
|
||||||
child: FutureBuilder(
|
),
|
||||||
future: getConfigurations(appContext),
|
Row(
|
||||||
builder: (context, AsyncSnapshot<dynamic> snapshot) {
|
mainAxisSize: MainAxisSize.min,
|
||||||
if (snapshot.connectionState == ConnectionState.done) {
|
children: [
|
||||||
if (snapshot.data.length > 0) {
|
Text("Configuration:", style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w400)),
|
||||||
return Row(
|
const SizedBox(width: 8),
|
||||||
children: [
|
FutureBuilder(
|
||||||
Padding(
|
future: getConfigurations(appContext),
|
||||||
padding: const EdgeInsets.all(8.0),
|
builder: (context, AsyncSnapshot<dynamic> snapshot) {
|
||||||
child: DropDownConfig(
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
|
if (snapshot.data != null && snapshot.data.length > 0) {
|
||||||
|
return DropDownConfig(
|
||||||
configurations: snapshot.data,
|
configurations: snapshot.data,
|
||||||
selectedConfigurationId: inputDevice.configurationId!,
|
selectedConfigurationId: inputDevice.configurationId!,
|
||||||
onChange: (ConfigurationDTO configurationOut) {
|
onChange: (ConfigurationDTO configurationOut) {
|
||||||
inputDevice.configuration = configurationOut.label;
|
inputDevice.configuration = configurationOut.label;
|
||||||
inputDevice.configurationId = configurationOut.id;
|
inputDevice.configurationId = configurationOut.id;
|
||||||
},
|
},
|
||||||
),
|
);
|
||||||
),
|
} else {
|
||||||
],
|
return Text(AppLocalizations.of(context)!.noConfigFound);
|
||||||
);
|
}
|
||||||
} else {
|
} else if (snapshot.connectionState == ConnectionState.none) {
|
||||||
return Text(AppLocalizations.of(context)!.noConfigFound);
|
return const Text("No data");
|
||||||
}
|
} else {
|
||||||
|
return const SizedBox(width: 24, height: 24, child: CircularProgressIndicator(strokeWidth: 2));
|
||||||
} else if (snapshot.connectionState == ConnectionState.none) {
|
}
|
||||||
return Text("No data");
|
}
|
||||||
} else {
|
),
|
||||||
return Center(
|
],
|
||||||
child: Container(
|
),
|
||||||
child: Text("Loading..")
|
],
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 12),
|
||||||
],
|
// Couleurs + Loader
|
||||||
),
|
Wrap(
|
||||||
],
|
spacing: 16,
|
||||||
),
|
runSpacing: 12,
|
||||||
Row(
|
children: [
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
ColorPickerInputContainer(
|
||||||
children: [
|
label: "Couleur principale :",
|
||||||
ColorPickerInputContainer(
|
fontSize: 16,
|
||||||
label: "Couleur principale :",
|
color: appConfiguration.primaryColor,
|
||||||
fontSize: 20,
|
onChanged: (value) => appConfiguration.primaryColor = value,
|
||||||
color: appConfiguration.primaryColor,
|
),
|
||||||
onChanged: (value) {
|
ColorPickerInputContainer(
|
||||||
appConfiguration.primaryColor = value;
|
label: AppLocalizations.of(context)!.backgroundColorLabel,
|
||||||
},
|
fontSize: 16,
|
||||||
),
|
color: appConfiguration.secondaryColor,
|
||||||
ColorPickerInputContainer(
|
onChanged: (value) => appConfiguration.secondaryColor = value,
|
||||||
label: AppLocalizations.of(context)!.backgroundColorLabel,
|
),
|
||||||
fontSize: 20,
|
ResourceInputContainer(
|
||||||
color: appConfiguration.secondaryColor,
|
label: "Loader :",
|
||||||
onChanged: (value) {
|
initialValue: appConfiguration.loaderImageId,
|
||||||
appConfiguration.secondaryColor = value;
|
color: kPrimaryColor,
|
||||||
},
|
imageFit: BoxFit.fitHeight,
|
||||||
),
|
onChanged: (ResourceDTO resource) async {
|
||||||
ResourceInputContainer(
|
if (resource.id == null) {
|
||||||
label: "Loader :",
|
appConfiguration.loaderImageId = null;
|
||||||
initialValue: appConfiguration.loaderImageId,
|
appConfiguration.loaderImageUrl = null;
|
||||||
color: kPrimaryColor,
|
} else {
|
||||||
imageFit: BoxFit.fitHeight,
|
appConfiguration.loaderImageId = resource.id;
|
||||||
onChanged: (ResourceDTO resource) async {
|
appConfiguration.loaderImageUrl = resource.url;
|
||||||
if(resource.id == null) {
|
}
|
||||||
appConfiguration.loaderImageId = null;
|
},
|
||||||
appConfiguration.loaderImageUrl = null;
|
),
|
||||||
} else {
|
],
|
||||||
appConfiguration.loaderImageId = resource.id;
|
),
|
||||||
appConfiguration.loaderImageUrl = resource.url;
|
const SizedBox(height: 12),
|
||||||
}
|
// Pourcentages
|
||||||
},
|
Wrap(
|
||||||
),
|
spacing: 16,
|
||||||
],
|
runSpacing: 12,
|
||||||
),
|
children: [
|
||||||
Row(
|
SizedBox(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
height: 90,
|
||||||
children: [
|
child: NumberInputContainer(
|
||||||
Container(
|
label: "Place des sections (%) :",
|
||||||
height: 100,
|
initialValue: appConfiguration.screenPercentageSectionsMainPage ?? 0,
|
||||||
child: NumberInputContainer(
|
isSmall: true,
|
||||||
label: "Place des sections (%) :",
|
maxLength: 3,
|
||||||
initialValue: appConfiguration.screenPercentageSectionsMainPage ?? 0,
|
onChanged: (value) {
|
||||||
isSmall: true,
|
try {
|
||||||
maxLength: 3,
|
appConfiguration.screenPercentageSectionsMainPage = int.parse(value);
|
||||||
onChanged: (value) {
|
} catch (e) {
|
||||||
try {
|
showNotification(Colors.orange, kWhite, 'Cela doit être un chiffre', context, null);
|
||||||
appConfiguration.screenPercentageSectionsMainPage = int.parse(value);
|
}
|
||||||
} catch (e) {
|
},
|
||||||
print('Screen percentage value not a number');
|
),
|
||||||
showNotification(Colors.orange, kWhite, 'Cela doit être un chiffre', context, null);
|
),
|
||||||
}
|
SizedBox(
|
||||||
},
|
height: 90,
|
||||||
|
child: NumberInputContainer(
|
||||||
|
label: "Pourcentage des arrondis (0-50) :",
|
||||||
|
initialValue: appConfiguration.roundedValue ?? 0,
|
||||||
|
isSmall: true,
|
||||||
|
maxLength: 2,
|
||||||
|
onChanged: (value) {
|
||||||
|
try {
|
||||||
|
appConfiguration.roundedValue = int.parse(value);
|
||||||
|
} catch (e) {
|
||||||
|
showNotification(Colors.orange, kWhite, 'Cela doit être un chiffre', context, null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
// Toggles
|
||||||
|
Wrap(
|
||||||
|
spacing: 16,
|
||||||
|
runSpacing: 8,
|
||||||
|
children: [
|
||||||
|
CheckInputContainer(
|
||||||
|
icon: Icons.image,
|
||||||
|
label: "Fond pour les images des sections :",
|
||||||
|
fontSize: 16,
|
||||||
|
isChecked: appConfiguration.isSectionImageBackground,
|
||||||
|
onChanged: (value) => appConfiguration.isSectionImageBackground = value,
|
||||||
|
),
|
||||||
|
CheckInputContainer(
|
||||||
|
icon: Icons.watch_later_outlined,
|
||||||
|
label: "Heure :",
|
||||||
|
fontSize: 16,
|
||||||
|
isChecked: appConfiguration.isHour,
|
||||||
|
onChanged: (value) => appConfiguration.isHour = value,
|
||||||
|
),
|
||||||
|
CheckInputContainer(
|
||||||
|
icon: Icons.date_range,
|
||||||
|
label: "Date :",
|
||||||
|
fontSize: 16,
|
||||||
|
isChecked: appConfiguration.isDate,
|
||||||
|
onChanged: (value) => appConfiguration.isDate = value,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Container(
|
),
|
||||||
height: 100,
|
const SizedBox(height: 16),
|
||||||
child: NumberInputContainer(
|
Wrap(
|
||||||
label: "Pourcentage des arrondis (0-50) :",
|
spacing: 8,
|
||||||
initialValue: appConfiguration.roundedValue ?? 0,
|
runSpacing: 8,
|
||||||
isSmall: true,
|
alignment: WrapAlignment.end,
|
||||||
maxLength: 2,
|
children: [
|
||||||
onChanged: (value) {
|
RoundedButton(
|
||||||
try {
|
text: "Annuler",
|
||||||
appConfiguration.roundedValue = int.parse(value);
|
icon: Icons.undo,
|
||||||
} catch (e) {
|
color: kSecond,
|
||||||
print('Rounded value not a number');
|
press: () => Navigator.of(context).pop(),
|
||||||
showNotification(Colors.orange, kWhite, 'Cela doit être un chiffre', context, null);
|
fontSize: 16,
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
RoundedButton(
|
||||||
],
|
text: "Changer",
|
||||||
),
|
icon: Icons.check,
|
||||||
Row(
|
color: kPrimaryColor,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
textColor: kWhite,
|
||||||
children: [
|
press: () {
|
||||||
CheckInputContainer(
|
onGetResult(inputDevice, appConfiguration);
|
||||||
icon: Icons.image,
|
Navigator.of(context).pop();
|
||||||
label: "Fond pour les images des sections :",
|
},
|
||||||
fontSize: 20,
|
fontSize: 16,
|
||||||
isChecked: appConfiguration.isSectionImageBackground,
|
),
|
||||||
onChanged: (value) {
|
],
|
||||||
appConfiguration.isSectionImageBackground = value;
|
),
|
||||||
},
|
],
|
||||||
),
|
),
|
||||||
CheckInputContainer(
|
|
||||||
icon: Icons.watch_later_outlined,
|
|
||||||
label: "Heure :",
|
|
||||||
fontSize: 20,
|
|
||||||
isChecked: appConfiguration.isHour,
|
|
||||||
onChanged: (value) {
|
|
||||||
appConfiguration.isHour = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
CheckInputContainer(
|
|
||||||
icon: Icons.date_range,
|
|
||||||
label: "Date :",
|
|
||||||
fontSize: 20,
|
|
||||||
isChecked: appConfiguration.isDate,
|
|
||||||
onChanged: (value) {
|
|
||||||
appConfiguration.isDate = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: <Widget>[
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
width: 180,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: "Annuler",
|
|
||||||
icon: Icons.undo,
|
|
||||||
color: kSecond,
|
|
||||||
press: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
width: 180,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: "Changer",
|
|
||||||
icon: Icons.check,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
textColor: kWhite,
|
|
||||||
press: () {
|
|
||||||
onGetResult(inputDevice, appConfiguration);
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
), context: mainContext
|
), context: mainContext
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getConfigurationsElement(DeviceDTO inputDevice, data, Function onGetResult) {
|
getConfigurationsElement(DeviceDTO inputDevice, data, Function onGetResult) {
|
||||||
List<Widget> widgets = <Widget>[];
|
List<Widget> widgets = <Widget>[];
|
||||||
for(var configuration in data as List<ConfigurationDTO>) {
|
for (var configuration in data as List<ConfigurationDTO>) {
|
||||||
var widget = new InkWell(
|
var widget = new InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
inputDevice.configuration = configuration.label;
|
inputDevice.configuration = configuration.label;
|
||||||
@ -264,15 +249,8 @@ getConfigurationsElement(DeviceDTO inputDevice, data, Function onGetResult) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<ConfigurationDTO>?> getConfigurations(AppContext appContext) async {
|
Future<List<ConfigurationDTO>?> getConfigurations(AppContext appContext) async {
|
||||||
List<ConfigurationDTO>? configurations = await (appContext.getContext() as ManagerAppContext).clientAPI!.configurationApi!.configurationGet(instanceId: (appContext.getContext() as ManagerAppContext).instanceId);
|
return (appContext.getContext() as ManagerAppContext)
|
||||||
//print("number of configurations " + configurations.length.toString());
|
.clientAPI!
|
||||||
|
.configurationApi!
|
||||||
if(configurations != null) {
|
.configurationGet(instanceId: (appContext.getContext() as ManagerAppContext).instanceId);
|
||||||
configurations.forEach((element) {
|
|
||||||
//print(element);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return configurations;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -66,7 +66,7 @@ class _DeviceElementState extends State<DeviceElement> {
|
|||||||
children: [
|
children: [
|
||||||
AutoSizeText(
|
AutoSizeText(
|
||||||
widget.deviceDTO.name != null ? widget.deviceDTO.name! : widget.deviceDTO.identifier!,
|
widget.deviceDTO.name != null ? widget.deviceDTO.name! : widget.deviceDTO.identifier!,
|
||||||
style: new TextStyle(fontSize: 25, fontWeight: FontWeight.w300),
|
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400),
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -75,7 +75,7 @@ class _DeviceElementState extends State<DeviceElement> {
|
|||||||
Center(
|
Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
updatedDevice?.configuration != null ? updatedDevice?.configuration! ?? "Aucune configuration" : "Aucune configuration",
|
updatedDevice?.configuration != null ? updatedDevice?.configuration! ?? "Aucune configuration" : "Aucune configuration",
|
||||||
style: new TextStyle(fontSize: 20),
|
style: const TextStyle(fontSize: 13),
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -60,23 +60,18 @@ class _KioskScreenState extends State<KioskScreen> {
|
|||||||
List<AppConfigurationLinkDTO>? appConfigurationLinks = snapshot.data;
|
List<AppConfigurationLinkDTO>? appConfigurationLinks = snapshot.data;
|
||||||
|
|
||||||
if (snapshot.connectionState == ConnectionState.done && appConfigurationLinks != null) {
|
if (snapshot.connectionState == ConnectionState.done && appConfigurationLinks != null) {
|
||||||
final screenWidth = MediaQuery.of(context).size.width;
|
|
||||||
final itemWidth = 175;
|
|
||||||
final crossAxisCount = (screenWidth / itemWidth).floor().clamp(1, 6);
|
|
||||||
|
|
||||||
return GridView.builder(
|
return GridView.builder(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: crossAxisCount),
|
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
|
||||||
|
maxCrossAxisExtent: 220,
|
||||||
|
childAspectRatio: 1.5,
|
||||||
|
mainAxisSpacing: 10,
|
||||||
|
crossAxisSpacing: 10,
|
||||||
|
),
|
||||||
itemCount: appConfigurationLinks.length,
|
itemCount: appConfigurationLinks.length,
|
||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
return Container(
|
return _DeviceCard(
|
||||||
decoration: boxDecoration(),
|
deviceLink: appConfigurationLinks[index],
|
||||||
padding: const EdgeInsets.all(10),
|
|
||||||
margin: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
|
|
||||||
child: Align(
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: DeviceElement(deviceDTO: appConfigurationLinks[index].device!, appConfigurationLinkDTO: appConfigurationLinks[index]), //getElement()
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -243,20 +238,47 @@ class _KioskScreenState extends State<KioskScreen> {
|
|||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
boxDecoration() {
|
class _DeviceCard extends StatefulWidget {
|
||||||
return BoxDecoration(
|
final AppConfigurationLinkDTO deviceLink;
|
||||||
color: kTextLightColor,
|
const _DeviceCard({required this.deviceLink});
|
||||||
shape: BoxShape.rectangle,
|
|
||||||
borderRadius: BorderRadius.circular(25.0),
|
@override
|
||||||
boxShadow: [
|
State<_DeviceCard> createState() => _DeviceCardState();
|
||||||
BoxShadow(
|
}
|
||||||
color: kSecond,
|
|
||||||
spreadRadius: 0.5,
|
class _DeviceCardState extends State<_DeviceCard> {
|
||||||
blurRadius: 5,
|
bool _hovered = false;
|
||||||
offset: Offset(0, 1.5), // changes position of shadow
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MouseRegion(
|
||||||
|
onEnter: (_) => setState(() => _hovered = true),
|
||||||
|
onExit: (_) => setState(() => _hovered = false),
|
||||||
|
child: AnimatedScale(
|
||||||
|
scale: _hovered ? 1.03 : 1.0,
|
||||||
|
duration: const Duration(milliseconds: 150),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: kTextLightColor,
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: kSecond,
|
||||||
|
spreadRadius: _hovered ? 1 : 0.5,
|
||||||
|
blurRadius: _hovered ? 10 : 5,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
padding: const EdgeInsets.all(10),
|
||||||
|
child: DeviceElement(
|
||||||
|
deviceDTO: widget.deviceLink.device!,
|
||||||
|
appConfigurationLinkDTO: widget.deviceLink,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<DeviceDTO>?> getDevices(AppContext appContext) async {
|
Future<List<DeviceDTO>?> getDevices(AppContext appContext) async {
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import 'package:manager_app/Screens/Kiosk_devices/kiosk_screen.dart';
|
|||||||
import 'package:manager_app/Screens/Resources/resources_screen.dart';
|
import 'package:manager_app/Screens/Resources/resources_screen.dart';
|
||||||
import 'package:manager_app/Screens/Statistics/statistics_screen.dart';
|
import 'package:manager_app/Screens/Statistics/statistics_screen.dart';
|
||||||
import 'package:manager_app/Screens/Applications/app_configuration_link_screen.dart';
|
import 'package:manager_app/Screens/Applications/app_configuration_link_screen.dart';
|
||||||
|
import 'package:manager_app/Screens/Applications/web_app_screen.dart';
|
||||||
import 'package:manager_app/Screens/Notifications/notifications_screen.dart';
|
import 'package:manager_app/Screens/Notifications/notifications_screen.dart';
|
||||||
import 'package:manager_app/Screens/Users/users_screen.dart';
|
import 'package:manager_app/Screens/Users/users_screen.dart';
|
||||||
import 'package:manager_app/l10n/app_localizations.dart';
|
import 'package:manager_app/l10n/app_localizations.dart';
|
||||||
@ -430,47 +431,54 @@ class _MainScreenState extends State<MainScreen> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
const QuotaBarsWidget(),
|
const QuotaBarsWidget(),
|
||||||
DropdownButton<Locale>(
|
Row(
|
||||||
value: managerAppContext.locale,
|
children: [
|
||||||
underline: const SizedBox(),
|
DropdownButton<Locale>(
|
||||||
isDense: true,
|
value: managerAppContext.locale,
|
||||||
items: const [
|
underline: const SizedBox(),
|
||||||
DropdownMenuItem(value: Locale('fr'), child: Text('🇫🇷 FR')),
|
isDense: true,
|
||||||
DropdownMenuItem(value: Locale('en'), child: Text('🇬🇧 EN')),
|
items: const [
|
||||||
DropdownMenuItem(value: Locale('nl'), child: Text('🇧🇪 NL')),
|
DropdownMenuItem(value: Locale('fr'), child: Text('🇫🇷 FR')),
|
||||||
],
|
DropdownMenuItem(value: Locale('en'), child: Text('🇬🇧 EN')),
|
||||||
onChanged: (locale) {
|
DropdownMenuItem(value: Locale('nl'), child: Text('🇧🇪 NL')),
|
||||||
if (locale != null) appContext.setLocale(locale);
|
],
|
||||||
},
|
onChanged: (locale) {
|
||||||
),
|
if (locale != null) appContext.setLocale(locale);
|
||||||
const SizedBox(height: 4),
|
},
|
||||||
AutoSizeText(
|
),
|
||||||
(appContext.getContext() as ManagerAppContext).email ?? "",
|
const SizedBox(width: 8),
|
||||||
style: TextStyle(color: kBodyTextColor, fontSize: 16, fontWeight: FontWeight.w300, fontFamily: "Helvetica"),
|
Expanded(
|
||||||
maxLines: 1,
|
child: AutoSizeText(
|
||||||
),
|
(appContext.getContext() as ManagerAppContext).email ?? "",
|
||||||
if ((appContext.getContext() as ManagerAppContext).role == UserRole.SuperAdmin)
|
style: TextStyle(color: kBodyTextColor, fontSize: 14, fontWeight: FontWeight.w300, fontFamily: "Helvetica"),
|
||||||
IconButton(
|
maxLines: 1,
|
||||||
icon: Icon(Icons.swap_horiz, color: kPrimaryColor),
|
),
|
||||||
tooltip: AppLocalizations.of(context)!.tooltipSwitchInstance,
|
),
|
||||||
onPressed: () => _showSwitchInstanceDialog(context, appContext.getContext() as ManagerAppContext),
|
if ((appContext.getContext() as ManagerAppContext).role == UserRole.SuperAdmin)
|
||||||
),
|
IconButton(
|
||||||
IconButton(
|
icon: Icon(Icons.swap_horiz, color: kPrimaryColor),
|
||||||
icon: Icon(Icons.logout, color: kPrimaryColor),
|
tooltip: AppLocalizations.of(context)!.tooltipSwitchInstance,
|
||||||
onPressed: () async {
|
onPressed: () => _showSwitchInstanceDialog(context, appContext.getContext() as ManagerAppContext),
|
||||||
var session = await loadJsonSessionFile();
|
),
|
||||||
setState(() {
|
IconButton(
|
||||||
Storage localStorage = window.localStorage;
|
icon: Icon(Icons.logout, color: kPrimaryColor),
|
||||||
localStorage.clear();
|
tooltip: AppLocalizations.of(context)!.tooltipLogout,
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
onPressed: () async {
|
||||||
managerAppContext.accessToken = null;
|
await loadJsonSessionFile();
|
||||||
managerAppContext.instanceId = null;
|
setState(() {
|
||||||
managerAppContext.instanceDTO = null;
|
Storage localStorage = window.localStorage;
|
||||||
appContext.setContext(managerAppContext);
|
localStorage.clear();
|
||||||
|
ManagerAppContext managerAppContext = appContext.getContext();
|
||||||
|
managerAppContext.accessToken = null;
|
||||||
|
managerAppContext.instanceId = null;
|
||||||
|
managerAppContext.instanceDTO = null;
|
||||||
|
appContext.setContext(managerAppContext);
|
||||||
|
|
||||||
context.go('/login');
|
context.go('/login');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -597,25 +605,24 @@ class _MainScreenState extends State<MainScreen> {
|
|||||||
|
|
||||||
switch (elementToShow.type) {
|
switch (elementToShow.type) {
|
||||||
case 'mobile' :
|
case 'mobile' :
|
||||||
var applicationInstanceMobile = instanceDTO.applicationInstanceDTOs!.firstWhere((ai) => ai.appType == AppType.Mobile);
|
var applicationInstanceMobile = instanceDTO.applicationInstanceDTOs?.firstWhereOrNull((ai) => ai.appType == AppType.Mobile);
|
||||||
|
if (applicationInstanceMobile == null) return const Center(child: Text('Application mobile non configurée'));
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: AppConfigurationLinkScreen(applicationInstanceDTO: applicationInstanceMobile)
|
child: AppConfigurationLinkScreen(applicationInstanceDTO: applicationInstanceMobile)
|
||||||
);
|
);
|
||||||
case 'kiosk' :
|
case 'kiosk' :
|
||||||
var applicationInstanceTablet = instanceDTO.applicationInstanceDTOs!.firstWhere((ai) => ai.appType == AppType.Tablet);
|
var applicationInstanceTablet = instanceDTO.applicationInstanceDTOs?.firstWhereOrNull((ai) => ai.appType == AppType.Tablet);
|
||||||
|
if (applicationInstanceTablet == null) return const Center(child: Text('Application kiosk non configurée'));
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: KioskScreen(applicationInstanceDTO: applicationInstanceTablet)
|
child: KioskScreen(applicationInstanceDTO: applicationInstanceTablet)
|
||||||
);
|
);
|
||||||
case 'web' :
|
case 'web' :
|
||||||
var applicationInstanceWeb = instanceDTO.applicationInstanceDTOs!.firstWhere((ai) => ai.appType == AppType.Web);
|
return const WebInstanceLoader();
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Text("TODO web")
|
|
||||||
);
|
|
||||||
case 'vr' :
|
case 'vr' :
|
||||||
var applicationInstanceVR = instanceDTO.applicationInstanceDTOs!.firstWhere((ai) => ai.appType == AppType.VR);
|
var applicationInstanceVR = instanceDTO.applicationInstanceDTOs?.firstWhereOrNull((ai) => ai.appType == AppType.VR);
|
||||||
|
if (applicationInstanceVR == null) return const Center(child: Text('Application VR non configurée'));
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Text("TODO vr")
|
child: Text("TODO vr")
|
||||||
|
|||||||
@ -275,7 +275,9 @@ class _NotificationsScreenState extends State<NotificationsScreen> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Row(
|
Wrap(
|
||||||
|
spacing: 12,
|
||||||
|
runSpacing: 12,
|
||||||
children: [
|
children: [
|
||||||
_KpiCard(
|
_KpiCard(
|
||||||
label: l.allNotifications,
|
label: l.allNotifications,
|
||||||
@ -284,7 +286,6 @@ class _NotificationsScreenState extends State<NotificationsScreen> {
|
|||||||
selected: _statusFilter == null,
|
selected: _statusFilter == null,
|
||||||
onTap: () => _setFilter(null),
|
onTap: () => _setFilter(null),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
|
||||||
_KpiCard(
|
_KpiCard(
|
||||||
label: l.sentNotifications,
|
label: l.sentNotifications,
|
||||||
count: _sentCount,
|
count: _sentCount,
|
||||||
@ -292,7 +293,6 @@ class _NotificationsScreenState extends State<NotificationsScreen> {
|
|||||||
selected: _statusFilter == 'Sent',
|
selected: _statusFilter == 'Sent',
|
||||||
onTap: () => _setFilter('Sent'),
|
onTap: () => _setFilter('Sent'),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
|
||||||
_KpiCard(
|
_KpiCard(
|
||||||
label: l.scheduledNotifications,
|
label: l.scheduledNotifications,
|
||||||
count: _scheduledCount,
|
count: _scheduledCount,
|
||||||
@ -300,7 +300,6 @@ class _NotificationsScreenState extends State<NotificationsScreen> {
|
|||||||
selected: _statusFilter == 'Scheduled',
|
selected: _statusFilter == 'Scheduled',
|
||||||
onTap: () => _setFilter('Scheduled'),
|
onTap: () => _setFilter('Scheduled'),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
|
||||||
_KpiCard(
|
_KpiCard(
|
||||||
label: l.failedNotifications,
|
label: l.failedNotifications,
|
||||||
count: _failedCount,
|
count: _failedCount,
|
||||||
|
|||||||
@ -13,112 +13,89 @@ import 'package:manager_api_new/api.dart';
|
|||||||
|
|
||||||
dynamic showNewResource(AppContext appContext, BuildContext context) async {
|
dynamic showNewResource(AppContext appContext, BuildContext context) async {
|
||||||
ResourceDTO resourceDetailDTO = new ResourceDTO();
|
ResourceDTO resourceDetailDTO = new ResourceDTO();
|
||||||
Size size = MediaQuery.of(context).size;
|
|
||||||
var fileName;
|
|
||||||
List<File>? filesToSend;
|
List<File>? filesToSend;
|
||||||
List<PlatformFile>? filesToSendWeb;
|
List<PlatformFile>? filesToSendWeb;
|
||||||
|
|
||||||
var result = await showDialog(
|
var result = await showDialog(
|
||||||
builder: (BuildContext context) => AlertDialog(
|
builder: (BuildContext context) => Dialog(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
||||||
),
|
),
|
||||||
content: Container(
|
child: SizedBox(
|
||||||
width: size.width *0.5,
|
width: 560,
|
||||||
child: SingleChildScrollView(
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(24, 20, 24, 24),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(AppLocalizations.of(context)!.newResource, style: new TextStyle(fontSize: 25, fontWeight: FontWeight.w400)),
|
Flexible(
|
||||||
/*Column(
|
child: SingleChildScrollView(
|
||||||
children: [
|
child: Column(
|
||||||
StringInputContainer(
|
mainAxisSize: MainAxisSize.min,
|
||||||
label: "Nom :",
|
children: [
|
||||||
initialValue: resourceDetailDTO.label,
|
Text(
|
||||||
onChanged: (value) {
|
AppLocalizations.of(context)!.newResource,
|
||||||
resourceDetailDTO.label = value;
|
style: const TextStyle(fontSize: 22, fontWeight: FontWeight.w400),
|
||||||
},
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
SizedBox(
|
||||||
|
height: 400,
|
||||||
|
child: ResourceTab(
|
||||||
|
resourceDTO: resourceDetailDTO,
|
||||||
|
onFileUpload: (List<File> files) {
|
||||||
|
filesToSend = files;
|
||||||
|
},
|
||||||
|
onFileUploadWeb: (List<PlatformFile> files) {
|
||||||
|
filesToSendWeb = files;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
if (fileName != null) new Text(fileName),
|
|
||||||
],
|
|
||||||
),*/
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 10.0),
|
|
||||||
child: Container(
|
|
||||||
width: size.width *0.85,
|
|
||||||
height: size.height *0.5,
|
|
||||||
child: ResourceTab(
|
|
||||||
resourceDTO: resourceDetailDTO,
|
|
||||||
onFileUpload: (List<File> files) {
|
|
||||||
filesToSend = files;
|
|
||||||
},
|
|
||||||
onFileUploadWeb: (List<PlatformFile> files) {
|
|
||||||
filesToSendWeb = files;
|
|
||||||
},
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
const SizedBox(height: 16),
|
||||||
),
|
Wrap(
|
||||||
),
|
spacing: 8,
|
||||||
),
|
runSpacing: 8,
|
||||||
actions: <Widget>[
|
alignment: WrapAlignment.end,
|
||||||
Row(
|
children: [
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
RoundedButton(
|
||||||
children: [
|
text: AppLocalizations.of(context)!.cancel,
|
||||||
Align(
|
icon: Icons.undo,
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
color: kSecond,
|
||||||
child: Container(
|
press: () => Navigator.of(context).pop(),
|
||||||
width: 175,
|
fontSize: 16,
|
||||||
height: 70,
|
),
|
||||||
child: RoundedButton(
|
RoundedButton(
|
||||||
text: AppLocalizations.of(context)!.cancel,
|
text: AppLocalizations.of(context)!.create,
|
||||||
icon: Icons.undo,
|
icon: Icons.check,
|
||||||
color: kSecond,
|
color: kPrimaryColor,
|
||||||
press: () {
|
textColor: kWhite,
|
||||||
Navigator.of(context).pop();
|
press: () {
|
||||||
},
|
if (kIsWeb) {
|
||||||
fontSize: 20,
|
if (resourceDetailDTO.url != null || filesToSendWeb != null) {
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: 150,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: AppLocalizations.of(context)!.create,
|
|
||||||
icon: Icons.check,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
textColor: kWhite,
|
|
||||||
press: () {
|
|
||||||
//if (resourceDetailDTO.label != null && resourceDetailDTO.label!.trim() != '') {
|
|
||||||
if(kIsWeb) {
|
|
||||||
if(resourceDetailDTO.url != null || filesToSendWeb != null) { // TODO clarify resourceDetailDTO.data != null
|
|
||||||
Navigator.pop(context, [resourceDetailDTO, filesToSend, filesToSendWeb]);
|
Navigator.pop(context, [resourceDetailDTO, filesToSend, filesToSendWeb]);
|
||||||
} else {
|
} else {
|
||||||
showNotification(Colors.orange, kWhite, AppLocalizations.of(context)!.resourceNoFileLoaded, context, null);
|
showNotification(Colors.orange, kWhite, AppLocalizations.of(context)!.resourceNoFileLoaded, context, null);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (resourceDetailDTO.url != null || filesToSendWeb!.length > 0 || filesToSend!.length > 0) { // TODO clarify resourceDetailDTO.data != null
|
if (resourceDetailDTO.url != null || filesToSendWeb!.length > 0 || filesToSend!.length > 0) {
|
||||||
Navigator.pop(context, [resourceDetailDTO, filesToSend, filesToSendWeb]);
|
Navigator.pop(context, [resourceDetailDTO, filesToSend, filesToSendWeb]);
|
||||||
} else {
|
} else {
|
||||||
showNotification(Colors.orange, kWhite, AppLocalizations.of(context)!.resourceNoFileLoaded, context, null);
|
showNotification(Colors.orange, kWhite, AppLocalizations.of(context)!.resourceNoFileLoaded, context, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*} else {
|
},
|
||||||
showNotification(Colors.orange, kWhite, 'Veuillez donner un nom à la ressource', context, null);
|
fontSize: 16,
|
||||||
}*/
|
),
|
||||||
//Navigator.of(context).pop();
|
],
|
||||||
//create(resourceDetailDTO, fileToSend, appContext, context);
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
), context: context
|
), context: context
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import 'package:provider/provider.dart';
|
|||||||
import 'package:diacritic/diacritic.dart';
|
import 'package:diacritic/diacritic.dart';
|
||||||
|
|
||||||
class ResourceBodyGrid extends StatefulWidget {
|
class ResourceBodyGrid extends StatefulWidget {
|
||||||
final List<ResourceDTO> resources; //return ResourceDTO
|
final List<ResourceDTO> resources;
|
||||||
final Function onSelect;
|
final Function onSelect;
|
||||||
final bool isAddButton;
|
final bool isAddButton;
|
||||||
final bool isSelectModal;
|
final bool isSelectModal;
|
||||||
@ -22,7 +22,7 @@ class ResourceBodyGrid extends StatefulWidget {
|
|||||||
required this.onSelect,
|
required this.onSelect,
|
||||||
required this.isAddButton,
|
required this.isAddButton,
|
||||||
required this.resourceTypesIn,
|
required this.resourceTypesIn,
|
||||||
this.isSelectModal = false
|
this.isSelectModal = false,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -39,34 +39,42 @@ class _ResourceBodyGridState extends State<ResourceBodyGrid> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
resourcesToShow = widget.resources;
|
resourcesToShow = widget.resources;
|
||||||
currentFilterTypes = resource_types.where((rt) => widget.resourceTypesIn.contains(rt.type)).map((rt) => rt.label).toList();//, resource_types[2]]; // resource_types[3]
|
currentFilterTypes = resource_types
|
||||||
filterTypes = resource_types.where((rt) => widget.resourceTypesIn.contains(rt.type)).map((rt) => rt.label).toList();//, resource_types[2]]; // resource_types[3]
|
.where((rt) => widget.resourceTypesIn.contains(rt.type))
|
||||||
selectedTypes = resource_types.where((rt) => widget.resourceTypesIn.contains(rt.type)).map((rt) => rt.label).toList();
|
.map((rt) => rt.label)
|
||||||
|
.toList();
|
||||||
|
filterTypes = resource_types
|
||||||
|
.where((rt) => widget.resourceTypesIn.contains(rt.type))
|
||||||
|
.map((rt) => rt.label)
|
||||||
|
.toList();
|
||||||
|
selectedTypes = resource_types
|
||||||
|
.where((rt) => widget.resourceTypesIn.contains(rt.type))
|
||||||
|
.map((rt) => rt.label)
|
||||||
|
.toList();
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final appContext = Provider.of<AppContext>(context);
|
final appContext = Provider.of<AppContext>(context);
|
||||||
Size size = MediaQuery.of(context).size;
|
return bodyGrid(resourcesToShow, appContext);
|
||||||
|
|
||||||
return bodyGrid(resourcesToShow, size, appContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget bodyGrid(data, Size size, AppContext appContext) {
|
Widget bodyGrid(List<ResourceDTO> data, AppContext appContext) {
|
||||||
final screenWidth = MediaQuery.of(context).size.width;
|
final canEdit = (appContext.getContext() as ManagerAppContext).canEdit;
|
||||||
final itemWidth = 150;
|
|
||||||
final crossAxisCount = (screenWidth / itemWidth).floor().clamp(1, 9);
|
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
// Header: search + filter + add button — Wrap pour mobile
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
Padding(
|
||||||
children: [
|
padding: const EdgeInsets.fromLTRB(8, 8, 8, 4),
|
||||||
Padding(
|
child: Wrap(
|
||||||
padding: const EdgeInsets.all(8.0),
|
spacing: 8,
|
||||||
child: StringInputContainer(
|
runSpacing: 8,
|
||||||
label: "Recherche:",
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
|
children: [
|
||||||
|
StringInputContainer(
|
||||||
|
label: 'Recherche:',
|
||||||
onChanged: (String value) {
|
onChanged: (String value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
filterSearch = value;
|
filterSearch = value;
|
||||||
@ -74,156 +82,214 @@ class _ResourceBodyGridState extends State<ResourceBodyGrid> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
MultiSelectContainer(
|
||||||
Padding(
|
label: 'Type:',
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: MultiSelectContainer(
|
|
||||||
label: "Type:",
|
|
||||||
initialValue: filterTypes,
|
initialValue: filterTypes,
|
||||||
values: currentFilterTypes,
|
values: currentFilterTypes,
|
||||||
isMultiple: true,
|
isMultiple: true,
|
||||||
onChanged: (result) {
|
onChanged: (result) {
|
||||||
setState(() {
|
setState(() {
|
||||||
selectedTypes = result as List<String>; // TO TEST
|
selectedTypes = result as List<String>;
|
||||||
filterResource();
|
filterResource();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
if (widget.isAddButton && canEdit)
|
||||||
if (widget.isAddButton && (appContext.getContext() as ManagerAppContext).canEdit)
|
_AddButton(onTap: () {
|
||||||
InkWell(
|
widget.onSelect(
|
||||||
onTap: () {
|
ResourceDTO(id: widget.isSelectModal ? '-1' : null));
|
||||||
widget.onSelect(ResourceDTO(id: widget.isSelectModal ? "-1" : null));
|
}),
|
||||||
},
|
],
|
||||||
child: Padding(
|
),
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Container(
|
|
||||||
height: size.height *0.08,
|
|
||||||
width: size.height *0.08,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: kSuccess,
|
|
||||||
shape: BoxShape.rectangle,
|
|
||||||
borderRadius: BorderRadius.circular(25.0),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
color: kSecond,
|
|
||||||
spreadRadius: 0.5,
|
|
||||||
blurRadius: 5,
|
|
||||||
offset: Offset(0, 1.5), // changes position of shadow
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
child:
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(10.0),
|
|
||||||
child: LayoutBuilder(builder: (context, constraint) {
|
|
||||||
return new Icon(Icons.add, size: constraint.biggest.height, color: kTextLightColor);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
// Grid
|
||||||
Expanded(
|
Expanded(
|
||||||
child: GridView.builder(
|
child: GridView.builder(
|
||||||
shrinkWrap: true,
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: crossAxisCount),
|
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
|
||||||
itemCount: data.length,
|
maxCrossAxisExtent: 160,
|
||||||
itemBuilder: (BuildContext context, int index) {
|
childAspectRatio: 1.0,
|
||||||
return
|
mainAxisSpacing: 10,
|
||||||
InkWell(
|
crossAxisSpacing: 10,
|
||||||
onTap: () {
|
),
|
||||||
widget.onSelect(resourcesToShow[index]);
|
itemCount: data.length,
|
||||||
},
|
itemBuilder: (BuildContext context, int index) {
|
||||||
child: Container(
|
return _ResourceCard(
|
||||||
decoration: boxDecoration(data[index], appContext),
|
resource: resourcesToShow[index],
|
||||||
padding: const EdgeInsets.all(15),
|
onTap: () => widget.onSelect(resourcesToShow[index]),
|
||||||
margin: EdgeInsets.symmetric(vertical: 15, horizontal: 15),
|
);
|
||||||
child: Align(
|
},
|
||||||
alignment: Alignment.center,
|
|
||||||
child: getElement(data[index], size, appContext)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getElement(ResourceDTO resource, Size size, AppContext appContext) {
|
|
||||||
if (resource.id != null) {
|
|
||||||
return Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
height: size.width *0.01,
|
|
||||||
),
|
|
||||||
Align(
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: AutoSizeText(
|
|
||||||
resource.label == null ? "" : resource.label!,
|
|
||||||
style: new TextStyle(fontSize: 20),
|
|
||||||
maxLines: 1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Align(
|
|
||||||
alignment: Alignment.bottomRight,
|
|
||||||
child: Icon(
|
|
||||||
getResourceIcon(resource.type),
|
|
||||||
color: kPrimaryColor,
|
|
||||||
size: 15,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Icon(
|
|
||||||
Icons.close,
|
|
||||||
color: kTextLightColor,
|
|
||||||
size: 50.0,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void filterResource() {
|
void filterResource() {
|
||||||
resourcesToShow = filterSearch.isEmpty ? widget.resources: widget.resources.where((ResourceDTO resource) => resource.id == null || removeDiacritics(resource.label!.toUpperCase()).contains(removeDiacritics(filterSearch.toUpperCase()))).toList();
|
resourcesToShow = filterSearch.isEmpty
|
||||||
var getTypesInSelected = resource_types.where((ft) => selectedTypes.contains(ft.label)).map((rt) => rt.type).toList();
|
? widget.resources
|
||||||
resourcesToShow = resourcesToShow.where((resource) => resource.id == null || getTypesInSelected.contains(resource.type)).toList();
|
: widget.resources
|
||||||
|
.where((ResourceDTO resource) =>
|
||||||
|
resource.id == null ||
|
||||||
|
removeDiacritics(resource.label!.toUpperCase())
|
||||||
|
.contains(removeDiacritics(filterSearch.toUpperCase())))
|
||||||
|
.toList();
|
||||||
|
var getTypesInSelected = resource_types
|
||||||
|
.where((ft) => selectedTypes.contains(ft.label))
|
||||||
|
.map((rt) => rt.type)
|
||||||
|
.toList();
|
||||||
|
resourcesToShow = resourcesToShow
|
||||||
|
.where((resource) =>
|
||||||
|
resource.id == null ||
|
||||||
|
getTypesInSelected.contains(resource.type))
|
||||||
|
.toList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boxDecoration(dynamic resourceDetailDTO, appContext) {
|
// ── Add button ────────────────────────────────────────────────────────────────
|
||||||
return BoxDecoration(
|
|
||||||
color: resourceDetailDTO.id == null ? kSecond : kBackgroundColor,
|
class _AddButton extends StatelessWidget {
|
||||||
shape: BoxShape.rectangle,
|
final VoidCallback onTap;
|
||||||
borderRadius: BorderRadius.circular(30.0),
|
const _AddButton({required this.onTap});
|
||||||
image: resourceDetailDTO.id != null && (resourceDetailDTO.type == ResourceType.Image || resourceDetailDTO.type == ResourceType.ImageUrl) && resourceDetailDTO.url != null ? new DecorationImage(
|
|
||||||
fit: BoxFit.cover,
|
@override
|
||||||
colorFilter: new ColorFilter.mode(Colors.black.withValues(alpha: 0.3), BlendMode.dstATop),
|
Widget build(BuildContext context) {
|
||||||
image: new NetworkImage(
|
return GestureDetector(
|
||||||
resourceDetailDTO.url!,
|
onTap: onTap,
|
||||||
|
child: Container(
|
||||||
|
width: 56,
|
||||||
|
height: 56,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: kSuccess,
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
boxShadow: const [kDefaultShadow],
|
||||||
|
),
|
||||||
|
child: const Icon(Icons.add, color: kTextLightColor, size: 28),
|
||||||
),
|
),
|
||||||
) : null,
|
);
|
||||||
boxShadow: [
|
}
|
||||||
BoxShadow(
|
|
||||||
color: kSecond,
|
|
||||||
spreadRadius: 0.5,
|
|
||||||
blurRadius: 5,
|
|
||||||
offset: Offset(0, 1.5), // changes position of shadow
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Resource card ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
/*Future<List<ResourceDTO>> getResources(Function onGetResult, bool isImage, AppContext appContext) async {
|
class _ResourceCard extends StatefulWidget {
|
||||||
List<ResourceDTO> resources = await (appContext.getContext() as ManagerAppContext).clientAPI.resourceApi.resourceGet(instanceId:(appContext.getContext() as ManagerAppContext).instanceId);
|
final ResourceDTO resource;
|
||||||
if (onGetResult != null && isImage) {
|
final VoidCallback onTap;
|
||||||
resources = resources.where((element) => element.type == ResourceType.image || element.type == ResourceType.imageUrl).toList();
|
const _ResourceCard({required this.resource, required this.onTap});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_ResourceCard> createState() => _ResourceCardState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ResourceCardState extends State<_ResourceCard> {
|
||||||
|
bool _hovered = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final resource = widget.resource;
|
||||||
|
final isRemove = resource.id == null;
|
||||||
|
final hasImage = !isRemove &&
|
||||||
|
(resource.type == ResourceType.Image ||
|
||||||
|
resource.type == ResourceType.ImageUrl) &&
|
||||||
|
resource.url != null;
|
||||||
|
|
||||||
|
return MouseRegion(
|
||||||
|
onEnter: (_) => setState(() => _hovered = true),
|
||||||
|
onExit: (_) => setState(() => _hovered = false),
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: widget.onTap,
|
||||||
|
child: AnimatedScale(
|
||||||
|
scale: _hovered ? 1.03 : 1.0,
|
||||||
|
duration: const Duration(milliseconds: 150),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: kSecond,
|
||||||
|
spreadRadius: _hovered ? 1 : 0.5,
|
||||||
|
blurRadius: _hovered ? 10 : 5,
|
||||||
|
offset: const Offset(0, 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(16),
|
||||||
|
child: Stack(
|
||||||
|
fit: StackFit.expand,
|
||||||
|
children: [
|
||||||
|
// Background
|
||||||
|
if (hasImage)
|
||||||
|
Image.network(resource.url!, fit: BoxFit.cover)
|
||||||
|
else
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: isRemove
|
||||||
|
? [kSecond, kSecond.withValues(alpha: 0.7)]
|
||||||
|
: [kPrimaryColor, kPrimaryColor.withValues(alpha: 0.65)],
|
||||||
|
begin: Alignment.topLeft,
|
||||||
|
end: Alignment.bottomRight,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Gradient scrim (only when there's an image)
|
||||||
|
if (hasImage)
|
||||||
|
DecoratedBox(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
begin: Alignment.topCenter,
|
||||||
|
end: Alignment.bottomCenter,
|
||||||
|
stops: const [0.35, 1.0],
|
||||||
|
colors: [
|
||||||
|
Colors.transparent,
|
||||||
|
Colors.black.withValues(alpha: 0.65),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Type icon — top right badge
|
||||||
|
if (!isRemove)
|
||||||
|
Positioned(
|
||||||
|
top: 8,
|
||||||
|
right: 8,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.black.withValues(alpha: 0.35),
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
),
|
||||||
|
child: Icon(
|
||||||
|
getResourceIcon(resource.type),
|
||||||
|
color: kTextLightColor,
|
||||||
|
size: 14,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Label — bottom left
|
||||||
|
if (!isRemove)
|
||||||
|
Positioned(
|
||||||
|
left: 8,
|
||||||
|
right: 8,
|
||||||
|
bottom: 8,
|
||||||
|
child: AutoSizeText(
|
||||||
|
resource.label ?? '',
|
||||||
|
style: kCardTitleStyle.copyWith(fontSize: 13),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Remove icon
|
||||||
|
if (isRemove)
|
||||||
|
const Center(
|
||||||
|
child: Icon(Icons.close, color: kTextLightColor, size: 40),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return resources;
|
}
|
||||||
}*/
|
|
||||||
|
|||||||
@ -15,126 +15,90 @@ import 'get_element_for_resource.dart';
|
|||||||
|
|
||||||
Future<ResourceDTO?> showResource(ResourceDTO resourceDTO, AppContext appContext, BuildContext context, Size size) async {
|
Future<ResourceDTO?> showResource(ResourceDTO resourceDTO, AppContext appContext, BuildContext context, Size size) async {
|
||||||
var result = await showDialog(
|
var result = await showDialog(
|
||||||
builder: (BuildContext context) => AlertDialog(
|
builder: (BuildContext context) => Dialog(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
||||||
),
|
),
|
||||||
content: SingleChildScrollView(
|
child: SizedBox(
|
||||||
child: Column(
|
width: 520,
|
||||||
children: [
|
child: Padding(
|
||||||
Align(
|
padding: const EdgeInsets.fromLTRB(24, 20, 24, 24),
|
||||||
alignment: Alignment.center,
|
child: Column(
|
||||||
child: Padding(
|
mainAxisSize: MainAxisSize.min,
|
||||||
padding: const EdgeInsets.all(8.0),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
child: SizedBox(
|
children: [
|
||||||
width: MediaQuery.of(context).size.width * 0.6,
|
Flexible(
|
||||||
height: MediaQuery.of(context).size.height * 0.2,
|
child: SingleChildScrollView(
|
||||||
child: StringInputContainer(
|
child: Column(
|
||||||
label: "Label :",
|
mainAxisSize: MainAxisSize.min,
|
||||||
initialValue: resourceDTO.label != null ? resourceDTO.label : "",
|
children: [
|
||||||
onChanged: (value) {
|
SizedBox(
|
||||||
resourceDTO.label = value;
|
height: 80,
|
||||||
},
|
child: StringInputContainer(
|
||||||
),
|
label: "Label :",
|
||||||
),/*Text(
|
initialValue: resourceDTO.label != null ? resourceDTO.label : "",
|
||||||
resourceDTO.label == null ? "" : resourceDTO.label,
|
onChanged: (value) {
|
||||||
style: new TextStyle(fontSize: 25, fontWeight: FontWeight.w400)),*/
|
resourceDTO.label = value;
|
||||||
),
|
},
|
||||||
),
|
),
|
||||||
Container(
|
),
|
||||||
height: resourceDTO.type == ResourceType.Audio ? size.height *0.1 : size.height *0.3,
|
const SizedBox(height: 8),
|
||||||
width: resourceDTO.type == ResourceType.Audio ? size.width *0.1 : size.width *0.3,
|
ConstrainedBox(
|
||||||
child: Center(
|
constraints: BoxConstraints(
|
||||||
child: Container(
|
maxHeight: resourceDTO.type == ResourceType.Audio ? 80 : 300,
|
||||||
decoration: BoxDecoration(
|
maxWidth: resourceDTO.type == ResourceType.Audio ? 200 : double.infinity,
|
||||||
borderRadius: BorderRadius.circular(30),
|
),
|
||||||
border: Border.all(width: 3, color: kSecond)
|
child: Container(
|
||||||
),
|
decoration: BoxDecoration(
|
||||||
child: Padding(
|
borderRadius: BorderRadius.circular(30),
|
||||||
padding: const EdgeInsets.all(10.0),
|
border: Border.all(width: 3, color: kSecond),
|
||||||
child: getElementForResource(resourceDTO, appContext),
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
child: getElementForResource(resourceDTO, appContext),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 16),
|
||||||
],
|
Wrap(
|
||||||
),
|
spacing: 8,
|
||||||
),
|
runSpacing: 8,
|
||||||
actions: <Widget>[
|
alignment: WrapAlignment.end,
|
||||||
Row(
|
children: [
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
RoundedButton(
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: 175,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: "Retour",
|
text: "Retour",
|
||||||
icon: Icons.undo,
|
icon: Icons.undo,
|
||||||
color: kSecond,
|
color: kSecond,
|
||||||
press: () {
|
press: () => Navigator.of(context).pop(),
|
||||||
Navigator.of(context).pop();
|
fontSize: 16,
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
),
|
||||||
),
|
RoundedButton(
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: 200,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: "Supprimer",
|
text: "Supprimer",
|
||||||
icon: Icons.delete,
|
icon: Icons.delete,
|
||||||
color: kError,
|
color: kError,
|
||||||
textColor: kWhite,
|
textColor: kWhite,
|
||||||
press: () {
|
press: () => delete(resourceDTO, appContext, context),
|
||||||
delete(resourceDTO, appContext, context);
|
fontSize: 16,
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
),
|
||||||
),
|
RoundedButton(
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: 220,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: AppLocalizations.of(context)!.download,
|
text: AppLocalizations.of(context)!.download,
|
||||||
icon: Icons.download,
|
icon: Icons.download,
|
||||||
color: kPrimaryColor,
|
color: kPrimaryColor,
|
||||||
press: () {
|
press: () {
|
||||||
if(resourceDTO.url != null) {
|
if (resourceDTO.url != null) {
|
||||||
html.AnchorElement anchorElement = html.AnchorElement(href: resourceDTO.url!);
|
html.AnchorElement anchorElement = html.AnchorElement(href: resourceDTO.url!);
|
||||||
anchorElement.download = '${resourceDTO.label}.json';
|
anchorElement.download = '${resourceDTO.label}.json';
|
||||||
anchorElement.target = '_blank';
|
anchorElement.target = '_blank';
|
||||||
anchorElement.click();
|
anchorElement.click();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fontSize: 20,
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
),
|
RoundedButton(
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Align(
|
|
||||||
alignment: AlignmentDirectional.bottomEnd,
|
|
||||||
child: Container(
|
|
||||||
width: 220,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: AppLocalizations.of(context)!.save,
|
text: AppLocalizations.of(context)!.save,
|
||||||
icon: Icons.check,
|
icon: Icons.check,
|
||||||
color: kPrimaryColor,
|
color: kPrimaryColor,
|
||||||
@ -143,14 +107,14 @@ Future<ResourceDTO?> showResource(ResourceDTO resourceDTO, AppContext appContext
|
|||||||
Navigator.pop(context, resourceDTO);
|
Navigator.pop(context, resourceDTO);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fontSize: 20,
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
), context: context
|
), context: context
|
||||||
);
|
);
|
||||||
return result;
|
return result;
|
||||||
@ -162,11 +126,9 @@ Future<void> delete(ResourceDTO resourceDTO, AppContext appContext, context) asy
|
|||||||
() {},
|
() {},
|
||||||
() async {
|
() async {
|
||||||
await (appContext.getContext() as ManagerAppContext).clientAPI!.resourceApi!.resourceDelete(resourceDTO.id!);
|
await (appContext.getContext() as ManagerAppContext).clientAPI!.resourceApi!.resourceDelete(resourceDTO.id!);
|
||||||
// TODO Remove from firebase storage via service or ?
|
|
||||||
|
|
||||||
FirebaseStorage storage = FirebaseStorage.instance;
|
FirebaseStorage storage = FirebaseStorage.instance;
|
||||||
Reference storageReference = storage.ref().child('pictures/${appContext.getContext().instanceId}/${resourceDTO.id}');
|
Reference storageReference = storage.ref().child('pictures/${appContext.getContext().instanceId}/${resourceDTO.id}');
|
||||||
// Supprimer le fichier
|
|
||||||
try {
|
try {
|
||||||
await storageReference.delete();
|
await storageReference.delete();
|
||||||
print('Fichier supprimé avec succès');
|
print('Fichier supprimé avec succès');
|
||||||
@ -176,7 +138,6 @@ Future<void> delete(ResourceDTO resourceDTO, AppContext appContext, context) asy
|
|||||||
|
|
||||||
try {} catch (e) {}
|
try {} catch (e) {}
|
||||||
|
|
||||||
// just to refresh
|
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
ManagerAppContext managerAppContext = appContext.getContext();
|
||||||
appContext.setContext(managerAppContext);
|
appContext.setContext(managerAppContext);
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
|||||||
@ -16,6 +16,34 @@ const kWhite = Color(0xFFFFFFFF);
|
|||||||
const kBlack = Color(0xFF000000);
|
const kBlack = Color(0xFF000000);
|
||||||
const kSuccess = Color(0xFF8bc34a);
|
const kSuccess = Color(0xFF8bc34a);
|
||||||
|
|
||||||
|
// Responsive
|
||||||
|
const kBreakpointMobile = 850.0;
|
||||||
|
|
||||||
|
// Shadows
|
||||||
|
const kDefaultShadow = BoxShadow(
|
||||||
|
color: kSecond,
|
||||||
|
spreadRadius: 0.5,
|
||||||
|
blurRadius: 5,
|
||||||
|
offset: Offset(0, 1.5),
|
||||||
|
);
|
||||||
|
|
||||||
|
// TextStyles for cards
|
||||||
|
const kCardTitleStyle = TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: kWhite,
|
||||||
|
);
|
||||||
|
const kCardSubtitleStyle = TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
fontWeight: FontWeight.w300,
|
||||||
|
color: Color(0xCCFFFFFF),
|
||||||
|
);
|
||||||
|
const kSectionLabelStyle = TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: kTitleTextColor,
|
||||||
|
);
|
||||||
|
|
||||||
const List<String> section_types = ["Map", "Slider", "Video", "Web", "Menu", "Quiz", "Article", "PDF", "Game", "Agenda", "Weather", "Event"];
|
const List<String> section_types = ["Map", "Slider", "Video", "Web", "Menu", "Quiz", "Article", "PDF", "Game", "Agenda", "Weather", "Event"];
|
||||||
const List<String> map_types = ["none", "normal", "satellite", "terrain", "hybrid"];
|
const List<String> map_types = ["none", "normal", "satellite", "terrain", "hybrid"];
|
||||||
const List<String> languages = ["FR", "NL", "EN", "DE", "IT", "ES", "CN", "PL", "AR", "UK"];
|
const List<String> languages = ["FR", "NL", "EN", "DE", "IT", "ES", "CN", "PL", "AR", "UK"];
|
||||||
|
|||||||
@ -52,6 +52,7 @@
|
|||||||
"noInstanceFound": "No instance found",
|
"noInstanceFound": "No instance found",
|
||||||
"configurePlan": "Configure plan",
|
"configurePlan": "Configure plan",
|
||||||
"tooltipSwitchInstance": "Switch instance",
|
"tooltipSwitchInstance": "Switch instance",
|
||||||
|
"tooltipLogout": "Log out",
|
||||||
|
|
||||||
"usersTitle": "Users",
|
"usersTitle": "Users",
|
||||||
"createUserBtn": "Create user",
|
"createUserBtn": "Create user",
|
||||||
|
|||||||
@ -52,6 +52,7 @@
|
|||||||
"noInstanceFound": "Aucune instance trouvée",
|
"noInstanceFound": "Aucune instance trouvée",
|
||||||
"configurePlan": "Configurer le plan",
|
"configurePlan": "Configurer le plan",
|
||||||
"tooltipSwitchInstance": "Changer d'instance",
|
"tooltipSwitchInstance": "Changer d'instance",
|
||||||
|
"tooltipLogout": "Se déconnecter",
|
||||||
|
|
||||||
"usersTitle": "Utilisateurs",
|
"usersTitle": "Utilisateurs",
|
||||||
"createUserBtn": "Créer un utilisateur",
|
"createUserBtn": "Créer un utilisateur",
|
||||||
@ -369,7 +370,7 @@
|
|||||||
"configRemoveConfirm": "Êtes-vous sûr de vouloir retirer cette configuration de l'application ?",
|
"configRemoveConfirm": "Êtes-vous sûr de vouloir retirer cette configuration de l'application ?",
|
||||||
"configRemovedSuccess": "La configuration a été retirée de l'application avec succès",
|
"configRemovedSuccess": "La configuration a été retirée de l'application avec succès",
|
||||||
"configRemoveError": "Une erreur est survenue lors du retrait de la configuration",
|
"configRemoveError": "Une erreur est survenue lors du retrait de la configuration",
|
||||||
"phoneConfigTitle": "Configurations par appareil",
|
"phoneConfigTitle": "Contenu de l'application mobile",
|
||||||
"addConfig": "Ajouter une configuration",
|
"addConfig": "Ajouter une configuration",
|
||||||
"selectConfigToAdd": "Sélectionner une configuration à ajouter",
|
"selectConfigToAdd": "Sélectionner une configuration à ajouter",
|
||||||
"noItems": "Aucun élément à afficher",
|
"noItems": "Aucun élément à afficher",
|
||||||
|
|||||||
@ -328,6 +328,12 @@ abstract class AppLocalizations {
|
|||||||
/// **'Changer d\'instance'**
|
/// **'Changer d\'instance'**
|
||||||
String get tooltipSwitchInstance;
|
String get tooltipSwitchInstance;
|
||||||
|
|
||||||
|
/// No description provided for @tooltipLogout.
|
||||||
|
///
|
||||||
|
/// In fr, this message translates to:
|
||||||
|
/// **'Se déconnecter'**
|
||||||
|
String get tooltipLogout;
|
||||||
|
|
||||||
/// No description provided for @usersTitle.
|
/// No description provided for @usersTitle.
|
||||||
///
|
///
|
||||||
/// In fr, this message translates to:
|
/// In fr, this message translates to:
|
||||||
@ -1909,7 +1915,7 @@ abstract class AppLocalizations {
|
|||||||
/// No description provided for @phoneConfigTitle.
|
/// No description provided for @phoneConfigTitle.
|
||||||
///
|
///
|
||||||
/// In fr, this message translates to:
|
/// In fr, this message translates to:
|
||||||
/// **'Configurations par appareil'**
|
/// **'Contenu de l\'application mobile'**
|
||||||
String get phoneConfigTitle;
|
String get phoneConfigTitle;
|
||||||
|
|
||||||
/// No description provided for @addConfig.
|
/// No description provided for @addConfig.
|
||||||
|
|||||||
@ -126,6 +126,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get tooltipSwitchInstance => 'Switch instance';
|
String get tooltipSwitchInstance => 'Switch instance';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get tooltipLogout => 'Log out';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get usersTitle => 'Users';
|
String get usersTitle => 'Users';
|
||||||
|
|
||||||
|
|||||||
@ -127,6 +127,9 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get tooltipSwitchInstance => 'Changer d\'instance';
|
String get tooltipSwitchInstance => 'Changer d\'instance';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get tooltipLogout => 'Se déconnecter';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get usersTitle => 'Utilisateurs';
|
String get usersTitle => 'Utilisateurs';
|
||||||
|
|
||||||
@ -998,7 +1001,7 @@ class AppLocalizationsFr extends AppLocalizations {
|
|||||||
'Une erreur est survenue lors du retrait de la configuration';
|
'Une erreur est survenue lors du retrait de la configuration';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get phoneConfigTitle => 'Configurations par appareil';
|
String get phoneConfigTitle => 'Contenu de l\'application mobile';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get addConfig => 'Ajouter une configuration';
|
String get addConfig => 'Ajouter une configuration';
|
||||||
|
|||||||
@ -127,6 +127,9 @@ class AppLocalizationsNl extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get tooltipSwitchInstance => 'Instantie wisselen';
|
String get tooltipSwitchInstance => 'Instantie wisselen';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get tooltipLogout => 'Uitloggen';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get usersTitle => 'Gebruikers';
|
String get usersTitle => 'Gebruikers';
|
||||||
|
|
||||||
|
|||||||
@ -52,6 +52,7 @@
|
|||||||
"noInstanceFound": "Geen instantie gevonden",
|
"noInstanceFound": "Geen instantie gevonden",
|
||||||
"configurePlan": "Plan configureren",
|
"configurePlan": "Plan configureren",
|
||||||
"tooltipSwitchInstance": "Instantie wisselen",
|
"tooltipSwitchInstance": "Instantie wisselen",
|
||||||
|
"tooltipLogout": "Uitloggen",
|
||||||
|
|
||||||
"usersTitle": "Gebruikers",
|
"usersTitle": "Gebruikers",
|
||||||
"createUserBtn": "Gebruiker aanmaken",
|
"createUserBtn": "Gebruiker aanmaken",
|
||||||
|
|||||||
@ -49,13 +49,14 @@ Future<void> main() async {
|
|||||||
|
|
||||||
usePathUrlStrategy();
|
usePathUrlStrategy();
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
ChangeNotifierProvider<AppContext>(
|
ChangeNotifierProvider<AppContext>(
|
||||||
create: (_) => AppContext(managerAppContext),
|
create: (_) => AppContext(managerAppContext),
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
locale: const Locale('fr'),
|
locale: const Locale('fr'),
|
||||||
supportedLocales: const [Locale('fr')],
|
supportedLocales: const [Locale('fr')],
|
||||||
localizationsDelegates: const [
|
localizationsDelegates: const [
|
||||||
|
AppLocalizations.delegate,
|
||||||
FlutterQuillLocalizations.delegate,
|
FlutterQuillLocalizations.delegate,
|
||||||
GlobalMaterialLocalizations.delegate,
|
GlobalMaterialLocalizations.delegate,
|
||||||
GlobalWidgetsLocalizations.delegate,
|
GlobalWidgetsLocalizations.delegate,
|
||||||
|
|||||||
@ -34,6 +34,8 @@ class InstanceDTO {
|
|||||||
this.statsHistoryDays,
|
this.statsHistoryDays,
|
||||||
this.hasAdvancedStats,
|
this.hasAdvancedStats,
|
||||||
this.applicationInstanceDTOs = const [],
|
this.applicationInstanceDTOs = const [],
|
||||||
|
this.webSlug,
|
||||||
|
this.publicApiKey,
|
||||||
});
|
});
|
||||||
|
|
||||||
String? id;
|
String? id;
|
||||||
@ -114,6 +116,10 @@ class InstanceDTO {
|
|||||||
|
|
||||||
List<ApplicationInstanceDTO>? applicationInstanceDTOs;
|
List<ApplicationInstanceDTO>? applicationInstanceDTOs;
|
||||||
|
|
||||||
|
String? webSlug;
|
||||||
|
|
||||||
|
String? publicApiKey;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
@ -272,6 +278,16 @@ class InstanceDTO {
|
|||||||
} else {
|
} else {
|
||||||
json[r'applicationInstanceDTOs'] = null;
|
json[r'applicationInstanceDTOs'] = null;
|
||||||
}
|
}
|
||||||
|
if (this.webSlug != null) {
|
||||||
|
json[r'webSlug'] = this.webSlug;
|
||||||
|
} else {
|
||||||
|
json[r'webSlug'] = null;
|
||||||
|
}
|
||||||
|
if (this.publicApiKey != null) {
|
||||||
|
json[r'publicApiKey'] = this.publicApiKey;
|
||||||
|
} else {
|
||||||
|
json[r'publicApiKey'] = null;
|
||||||
|
}
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,6 +334,8 @@ class InstanceDTO {
|
|||||||
hasAdvancedStats: mapValueOfType<bool>(json, r'hasAdvancedStats'),
|
hasAdvancedStats: mapValueOfType<bool>(json, r'hasAdvancedStats'),
|
||||||
applicationInstanceDTOs: ApplicationInstanceDTO.listFromJson(
|
applicationInstanceDTOs: ApplicationInstanceDTO.listFromJson(
|
||||||
json[r'applicationInstanceDTOs']),
|
json[r'applicationInstanceDTOs']),
|
||||||
|
webSlug: mapValueOfType<String>(json, r'webSlug'),
|
||||||
|
publicApiKey: mapValueOfType<String>(json, r'publicApiKey'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
70
web/favicon.svg
Normal file
70
web/favicon.svg
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
version="1.1"
|
||||||
|
width="439"
|
||||||
|
height="419"
|
||||||
|
id="svg137"
|
||||||
|
sodipodi:docname="MyInfoMate_logo_only.svg"
|
||||||
|
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<defs
|
||||||
|
id="defs137" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview137"
|
||||||
|
pagecolor="#505050"
|
||||||
|
bordercolor="#eeeeee"
|
||||||
|
borderopacity="1"
|
||||||
|
inkscape:showpageshadow="0"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#505050"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="5.6568543"
|
||||||
|
inkscape:cx="348.69203"
|
||||||
|
inkscape:cy="38.448931"
|
||||||
|
inkscape:window-width="5120"
|
||||||
|
inkscape:window-height="1369"
|
||||||
|
inkscape:window-x="1912"
|
||||||
|
inkscape:window-y="1072"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg137" />
|
||||||
|
<path
|
||||||
|
d="m 178.04447,135.21247 c 0.002,9.09742 0.17625,49.4843 0.17178,58.58172 -0.005,10.44131 -0.004,20.8826 0.002,31.32392 0.005,9.06176 0.005,18.12351 0.003,27.18527 -0.002,5.37036 -0.002,10.7407 0.002,16.11105 0.0204,38.14483 0.0204,38.14483 -0.54694,53.99548 l -0.10305,3.01772 c -0.80885,18.6575 -7.8096,35.94603 -20.4863,49.70518 l -2.15235,2.35938 c -12.39998,12.98838 -30.69723,23.86033 -49.02594,24.74586 -2.64076,0.0575 -5.28022,0.0839 -7.921566,0.10008 l -3.044189,0.03 c -3.328264,0.0316 -6.656542,0.0564 -9.984864,0.0811 -2.346596,0.0206 -4.693189,0.0416 -7.039779,0.063 -4.940416,0.044 -9.880843,0.0849 -14.821305,0.12331 -6.216775,0.0484 -12.433489,0.10212 -18.650202,0.158 -6.037887,0.054 -17.776846,0.19345 -40.2740759,0.28883 L 57.571753,137.10368 c 14.685204,-1.44088 35.90966,0.0974 45.537897,0.12284 41.79401,0.11064 74.93393,-6.04872 74.93482,-2.01405 z"
|
||||||
|
fill="#d62f60"
|
||||||
|
id="path1"
|
||||||
|
transform="translate(249.91406,6.8671875)"
|
||||||
|
sodipodi:nodetypes="cscsccccccccccscccsc" />
|
||||||
|
<path
|
||||||
|
d="m 64.688834,203.13197 c 0.0035,6.66536 0.0067,13.33073 0.0093,19.99609 l 9.86e-4,2.48865 c 0.005,13.72121 -0.0058,27.44236 -0.02756,41.16355 -0.01265,8.44313 -0.01133,16.88604 0.0085,25.32916 0.01266,5.78741 0.0111,11.57471 -0.0014,17.36211 -0.0067,3.33159 -0.0047,6.66256 0.01058,9.99416 0.111194,25.65838 0.111194,25.65838 -4.500365,37.04128 l -0.849251,2.18899 c -7.771476,18.55174 -21.788527,30.7335 -39.685905,38.97898 -3.37688,1.34444 -5.301227,2.48389 -8.978708,2.48389 l -3.2442484,1.47057 c -4.8987376,0.0599 -14.0045433,0.089 -15.4540455,0.10655 -25.7222011,0.30356 -49.7229121,-5.03616 -68.8916011,-23.19214 -3.286346,-3.24956 -6.197141,-6.66938 -8.810303,-10.47827 -1.170385,-1.6798 -3.844026,-5.57044 -5.590218,-8.45711 -0.851523,-1.40767 -3.595298,-4.4516 -7.983006,-16.21404 -0.853709,-1.50963 -2.403339,-12.94213 -2.403339,-12.94213 -0.0915,-1.48718 -0.23669,-2.92345 -0.23801,-4.41344 l -0.01,-2.78866 0.005,-3.06828 -0.007,-3.25582 c -0.006,-3.61823 -0.006,-7.23642 -0.005,-10.85466 -0.003,-2.58667 -0.006,-5.17335 -0.0102,-7.76002 -0.008,-6.30723 -0.0111,-12.61445 -0.0116,-18.92169 -4.7e-4,-5.12481 -0.003,-10.24962 -0.006,-15.37442 -0.009,-14.52085 -0.0134,-29.0417 -0.0127,-43.56255 l 1.3e-4,-2.37302 1.2e-4,-2.3759 c 4.1e-4,-12.71422 -0.009,-25.42841 -0.0233,-38.14262 -0.0143,-13.04611 -0.0213,-26.0922 -0.0204,-39.13831 3.3e-4,-7.32798 -0.002,-14.65593 -0.0132,-21.9839 -0.01,-6.88802 -0.01,-13.77597 -0.002,-20.663998 10e-4,-2.533683 1.124,-6.567371 1.118,-9.101047 -0.008,-3.44738 -1.128,-5.394528 82.246422,49.699935 83.374422,55.09446 83.377322,60.92629 83.380322,66.75811 z"
|
||||||
|
fill="#51cdc8"
|
||||||
|
id="path2"
|
||||||
|
transform="translate(112.81113,8.4930303)"
|
||||||
|
sodipodi:nodetypes="sscccccccccccccsccccccccscsccccccccs" />
|
||||||
|
<path
|
||||||
|
d="m 0,0 c 2.3047995,-6.7559e-4 4.6095989,-0.00164773 6.9143982,-0.00289917 4.8125578,-0.00146675 9.6250968,6.4331e-4 14.4376528,0.00534058 6.108101,0.00567724 12.216159,0.00242443 18.324259,-0.00357247 4.756666,-0.00364996 9.513323,-0.00244655 14.269991,1.2779e-4 2.249005,6.5808e-4 4.498012,-1.1905e-4 6.747016,-0.00247955 10.980782,-0.00899429 21.945816,0.06768592 32.917523,0.54693985 l 2.536386,0.10305596 C 119.97909,1.8334817 140.8053,14.193522 157.08594,31.132812 c 14.55199,16.47268 20.55085,36.163532 20.75,57.8125 0.0272,1.535344 0.0557,3.070663 0.0855,4.605958 0.0684,3.811023 0.11277,7.62181 0.14563,11.43329 0.018,2.0392 0.0412,21.15431 0.0616,30.38266 0.0376,3.46864 -119.042723,1.76559 -119.042723,1.76559 l -20.85965,1.44008 -111.140349,85.55992 c -0.161213,-39.22828 -0.161213,-39.22828 -0.195313,-55.73828 -0.02368,-11.37426 -0.05144,-22.7484 -0.106445,-34.12256 -0.04005,-8.28583 -0.06572,-16.57157 -0.0746,-24.8575 -0.0052,-4.3814 -0.01724,-8.76252 -0.04657,-13.143825 -0.02746,-4.136862 -0.03546,-8.273336 -0.02951,-12.41028 -0.0011,-1.50588 -0.0089,-3.011774 -0.02439,-4.517574 -0.131739,-13.445652 1.806738,-26.659985 8.289322,-38.647479 l 1.049072,-2.008056 c 2.851223,-5.317287 6.068313,-10.084275 10.138428,-14.554444 L -51.898437,21.875 C -43.655062,13.127533 -37.90534,5.8098811 -26.601562,1.8203125 l -12.3125,0.3125 v -1 C -25.942811,-0.00501656 -13.012554,-0.01357216 0,0 Z"
|
||||||
|
fill="#fec728"
|
||||||
|
id="path3"
|
||||||
|
transform="translate(249.91406,6.8671875)"
|
||||||
|
sodipodi:nodetypes="cccccccccccccccccccccccccccccc" />
|
||||||
|
<path
|
||||||
|
d="M 122.4545,-1.5555303 C 104.75322,5.7344897 77.764999,26.892615 70.396697,44.304966 65.927561,56.152831 64.595666,67.366945 64.64297,79.919079 c -0.0088,1.568853 -0.01926,3.137697 -0.03133,4.706528 -0.02754,4.203537 -0.03127,8.406777 -0.03028,12.610391 -0.0032,4.413592 -0.02883,8.827052 -0.05198,13.240572 -0.04035,8.33285 -0.06085,16.66561 -0.07397,24.99854 -0.01594,9.49723 -0.05439,18.99434 -0.09459,28.4915 -0.08212,19.51341 -0.136384,39.02681 -0.171948,58.54036 -3.137967,0.048 -6.275837,0.0763 -9.414062,0.10156 l -2.652588,0.0413 C 23.81406,222.81977 1.5565346,207.45478 -18.375829,188.75648 l -2.718735,-2.53775 c -8.235245,-7.71396 -16.371582,-15.53064 -24.472001,-23.38588 -5.420898,-5.25288 -10.871421,-10.46504 -16.411803,-15.59199 -41.322082,-38.29606 -41.811362,-38.47284 -39.697042,-61.82222 2.114319,-23.349383 3.306846,-25.445419 3.989278,-27.72417 6.748595,-20.960043 21.800751,-37.772405 41,-48.4375003 18.641419,-9.40752742 36.480818,-9.88154862 87.01386,-9.85750697 50.533043,0.0240417 73.811792,-1.09807633 92.064262,-0.98624303"
|
||||||
|
fill="#264863"
|
||||||
|
id="path4"
|
||||||
|
transform="translate(112.81113,8.4930303)"
|
||||||
|
sodipodi:nodetypes="cccccccccccccccccccc" />
|
||||||
|
<path
|
||||||
|
d="m 0,0 131.25,-0.25 v 63.875 l 0.11035,19.705566 c 0.0181,7.998291 0.0181,7.998291 0.0214,11.753754 0.006,2.598872 0.0186,5.19694 0.0405,7.79565 0.033,3.95755 0.0333,7.91478 0.0318,11.87247 l 0.0436,3.45275 c -0.0875,17.24733 -6.73078,32.78677 -18.61099,45.21278 C 106.22208,169.37917 98.630621,174.4762 90,177 l -11.397775,1.80377 -1.45256,0.16395 c -7.104685,-0.0441 -3.43355,-0.0556 -10.538337,-0.0776 -2.653987,-0.0101 -5.307964,-0.0237 -7.961914,-0.041 -3.807645,-0.0242 -7.615144,-0.0356 -11.422852,-0.0444 l -3.614349,-0.0313 -3.336334,-4.6e-4 -2.947357,-0.0135 c -2.521553,0.0131 41.626196,-2.01422 39.819227,0.21323 L 33,179 H 30.1875 24 c -1.532555,0.0113 -3.065107,0.0231 -4.597656,0.0352 -1.821614,0.009 -3.643229,0.0184 -5.464844,0.0273 l -2.798828,0.0254 -2.6738282,0.01 -2.4494629,0.0159 C 4,179 5.0139855,178.84803 4.0508683,177.7768 l 1.9580347,1.35049 -19.547353,-0.15833 -0.795115,0.0476 L -16,179 l -3.272949,0.0317 c -3.999316,0.0361 -7.998616,0.0591 -11.998047,0.0781 -1.732447,0.0101 -3.464876,0.0237 -5.197266,0.041 -2.487184,0.0242 -4.974145,0.0356 -7.461425,0.0444 l -2.35495,0.0313 c -1.906618,4e-4 -13.996389,0.0497 -15.899078,-0.0727 l 18.898307,-4.96534 C -32.858078,170.63158 -17.423649,159.0936 -8,141 c 5.0244847,-11.01947 7.29498468,-20.88967 7.31884766,-32.92383 l 0.0307674,-3.60735 c 0.0305076,-3.83335 0.0477557,-7.666634 0.0644474,-11.50007 0.0169446,-2.374681 0.0347624,-4.749356 0.0534668,-7.124023 C -0.4694063,77.063221 -0.4232179,68.2816 -0.375,59.5 Z"
|
||||||
|
fill="#773aaa"
|
||||||
|
id="path5"
|
||||||
|
transform="translate(177,231)"
|
||||||
|
sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccccc" />
|
||||||
|
<path
|
||||||
|
d="m 130.75,72.125 c 0,0 -130.9459176,38.46063 -130.5354588,-0.05093 L 130.75,72.125 l 0.5,86.75 L 0,159 0.2145412,72.074065"
|
||||||
|
fill="#ef7a34"
|
||||||
|
id="path6"
|
||||||
|
transform="translate(177,72)"
|
||||||
|
sodipodi:nodetypes="cccccc" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 8.3 KiB |
@ -31,6 +31,7 @@
|
|||||||
<link rel="apple-touch-icon" sizes="144x144" href="icons/apple-icon-144x144.png">
|
<link rel="apple-touch-icon" sizes="144x144" href="icons/apple-icon-144x144.png">
|
||||||
<link rel="apple-touch-icon" sizes="152x152" href="icons/apple-icon-152x152.png">
|
<link rel="apple-touch-icon" sizes="152x152" href="icons/apple-icon-152x152.png">
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="icons/apple-icon-180x180.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="icons/apple-icon-180x180.png">
|
||||||
|
<link rel="icon" type="image/svg+xml" href="favicon.svg">
|
||||||
<link rel="icon" type="image/png" sizes="192x192" href="icons/android-icon-192x192.png">
|
<link rel="icon" type="image/png" sizes="192x192" href="icons/android-icon-192x192.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="icons/favicon-32x32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="icons/favicon-32x32.png">
|
||||||
<link rel="icon" type="image/png" sizes="96x96" href="icons/favicon-96x96.png">
|
<link rel="icon" type="image/png" sizes="96x96" href="icons/favicon-96x96.png">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user