Service generation update + Create resource modal fix + wip select image in section

This commit is contained in:
Thomas Fransolet 2021-05-12 18:54:55 +02:00
parent d0a6b796ae
commit 408177f92b
15 changed files with 361 additions and 88 deletions

View File

@ -0,0 +1,96 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:manager_app/constants.dart';
import 'package:manager_app/Screens/Resources/select_resource_modal.dart';
class ImageInputContainer extends StatefulWidget {
final Color color;
final String label;
final String initialValue;
final ValueChanged<String> onChanged;
const ImageInputContainer({
Key key,
this.color = kSecond,
this.label,
this.initialValue,
this.onChanged,
}) : super(key: key);
@override
_ImageInputContainerState createState() => _ImageInputContainerState();
}
class _ImageInputContainerState extends State<ImageInputContainer> {
String resourceIdToShow;
@override
void initState() {
resourceIdToShow = widget.initialValue;
super.initState();
}
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Container(
child: Row(
children: [
Align(
alignment: AlignmentDirectional.centerStart,
child: Text(widget.label, style: TextStyle(fontSize: 25, fontWeight: FontWeight.w300))
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
width: size.width *0.2,
child: InkWell(
onTap: () {
showSelectResourceModal(
"Sélectionner une ressource",
(String resourceId) {
print('ON GET RESULT PARENT INPUT ');
widget.onChanged(resourceId);
setState(() {
print(resourceId);
resourceIdToShow = resourceId;
print('Set State');
});
},
1,
context
);
},
child: getElement(widget.initialValue, context),
),
),
),
],
),
);
}
getElement(String initialValue, BuildContext context) {
print("getElement");
print(resourceIdToShow);
if (resourceIdToShow != null) {
return Text("Show image todo");
} else {
return Container(
decoration: BoxDecoration(
color: widget.color,
borderRadius: BorderRadius.circular(50),
),
child: Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 15, bottom: 15),
child: Center(
child: AutoSizeText(
"Choisir une image",
style: TextStyle(color: kWhite),
maxLines: 2,
)
),
)
);
}
}
}

View File

@ -3,7 +3,6 @@ import 'dart:convert';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:manager_app/Components/multi_input_modal.dart';
import 'package:manager_app/Components/rounded_input_field.dart';
import 'package:manager_app/constants.dart';
import 'package:managerapi/api.dart';
@ -55,6 +54,7 @@ class MultiStringContainer extends StatelessWidget {
child: Center(
child: AutoSizeText(
"Changer les traductions",
style: TextStyle(color: kWhite),
maxLines: 2,
)
),

View File

@ -62,8 +62,6 @@ class _ResourceTabState extends State<ResourceTab> with SingleTickerProviderStat
}
void _handleTabSelection() {
print("_handleTabSelection");
print(_tabController.index);
switch(_tabController.index) {
case 0:
setState(() {
@ -90,18 +88,12 @@ class _ResourceTabState extends State<ResourceTab> with SingleTickerProviderStat
getContent(ResourceDetailDTO resourceDetailDTO, Function onFileUpload) {
List<Widget> tabsToShow = new List<Widget>();
print("getContent");
print(resourceDetailDTO);
// Local Image
tabsToShow.add(
new Padding(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
child: UploadImageContainer(
onChanged: (File file) {
print("ONCHANGED image");
print(file.path);
//fileToSend = file;
onFileUpload(file);
resourceDetailDTO.type = ResourceType.image;
}
@ -129,7 +121,6 @@ getContent(ResourceDetailDTO resourceDetailDTO, Function onFileUpload) {
child: UploadOnlineResourceContainer(
resourceDetailDTO: resourceDetailDTO,
onChanged: (ResourceDetailDTO value) {
print("ONcHanged UploadOnlineResourceContainer parent");
resourceDetailDTO = value;
},
),

View File

@ -74,7 +74,20 @@ class _UploadImageContainerState extends State<UploadImageContainer> with Single
if (snapshot.connectionState == ConnectionState.done) {
return Container(
height: 300,
child: DartVLC(file: snapshot.data)
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("La prévisualisation de la vidéo n'est pas disponible"),
),
Icon(
Icons.ondemand_video_sharp,
size: 35,
),
],
),
//DartVLC(file: snapshot.data)
);
} else if (snapshot.connectionState == ConnectionState.none) {
return Text("No data");
@ -152,22 +165,3 @@ class _UploadImageContainerState extends State<UploadImageContainer> with Single
);
}
}
Upload(File imageFile) async {
var stream = new http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
var length = await imageFile.length();
var uri = Uri.parse("upload URL TEST");
var request = new http.MultipartRequest("POST", uri);
var multipartFile = new http.MultipartFile('file', stream, length,
filename: basename(imageFile.path));
//contentType: new MediaType('image', 'png'));
request.files.add(multipartFile);
var response = await request.send();
print(response.statusCode);
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}

View File

@ -1,5 +1,6 @@
import 'dart:io';
import 'package:dart_vlc/dart_vlc.dart';
import 'package:flutter/cupertino.dart';
import 'package:manager_app/Components/rounded_input_field.dart';
import 'package:manager_app/Components/string_input_container.dart';
import 'package:manager_app/Components/vlc_viewer.dart';
@ -37,7 +38,20 @@ class _UploadOnlineResourceContainerState extends State<UploadOnlineResourceCont
showFile() {
if (widget.resourceDetailDTO.type == ResourceType.videoUrl || widget.resourceDetailDTO.type == ResourceType.video) {
return FutureBuilder(
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("La prévisualisation de la vidéo n'est pas disponible"),
),
Icon(
Icons.ondemand_video_sharp,
size: 35,
),
],
);
/*return FutureBuilder(
future: loadFile(urlResourceToShow),
builder: (context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
@ -51,7 +65,7 @@ class _UploadOnlineResourceContainerState extends State<UploadOnlineResourceCont
return Center(child: Container(height: 200, child: Text('LOADING TODO FRAISE')));
}
}
);
);*/
/*await Media.file(widget.file)*/
} else {
return Image.network(
@ -62,9 +76,9 @@ class _UploadOnlineResourceContainerState extends State<UploadOnlineResourceCont
}
}
loadFile(String urlResourceToShow) async {
/*loadFile(String urlResourceToShow) async {
return await Media.network(urlResourceToShow);
}
}*/
displayElement(Size size) {
return Column(

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:manager_app/Components/confirmation_dialog.dart';
import 'package:manager_app/Components/fetch_section_icon.dart';
import 'package:manager_app/Components/image_input_container.dart';
import 'package:manager_app/Components/message_notification.dart';
import 'package:manager_app/Components/multi_select_container.dart';
import 'package:manager_app/Components/multi_string_input_container.dart';
@ -139,10 +140,13 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
sectionDTO.type = SectionType.fromJson(tempOutput[0]);
},
),
StringInputContainer(
ImageInputContainer(
label: "Image :",
initialValue: sectionDTO.imageId,
color: kPrimaryColor,
onChanged: (value) {
print("received value in grant older");
sectionDTO.imageId = value;
},
),
@ -154,6 +158,7 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
children: [
MultiStringContainer(
label: "Titre :",
color: kPrimaryColor,
initialValue: sectionDTO.title,
onGetResult: (value) {
if (sectionDTO.title != value) {
@ -165,6 +170,7 @@ class _SectionDetailScreenState extends State<SectionDetailScreen> {
),
MultiStringContainer(
label: "Description :",
color: kPrimaryColor,
initialValue: sectionDTO.description,
onGetResult: (value) {
if (sectionDTO.description != value) {

View File

@ -0,0 +1,26 @@
import 'package:manager_app/app_context.dart';
import 'package:managerapi/api.dart';
import 'package:flutter/material.dart';
getImageForResource(ResourceDTO resourceDTO, AppContext appContext) {
switch(resourceDTO.type) {
case ResourceType.image:
return Image.network(
appContext.getContext().clientAPI.resourceApi.apiClient.basePath+"/api/Resource/"+ resourceDTO.id,
fit:BoxFit.fill
);
break;
case ResourceType.imageUrl:
return Image.network(
resourceDTO.data,
fit:BoxFit.fill
);
break;
case ResourceType.video:
return Text("THIS IS VIDEO LOCAL");
break;
case ResourceType.videoUrl:
return Text(resourceDTO.data);
break;
}
}

View File

@ -46,7 +46,6 @@ void showNewResource(AppContext appContext, BuildContext context) {
child: ResourceTab(
resourceDetailDTO: resourceDetailDTO,
onFileUpload: (File file) {
print("Received onFileUpload - nEW RESSOURCE");
fileToSend = file;
},
)
@ -101,41 +100,68 @@ void showNewResource(AppContext appContext, BuildContext context) {
void create(ResourceDetailDTO resourceDetailDTO, File file, AppContext appContext, context) async {
if (resourceDetailDTO.label != null) {
Navigator.of(context).pop();
switch(resourceDetailDTO.type) {
case ResourceType.image:
case ResourceType.video:
if (file != null) {
var request = http.MultipartRequest('POST', Uri.parse(appContext.getContext().clientAPI.resourceApi.apiClient.basePath+"/api/Resource/upload"));
request.files.add(
await http.MultipartFile(
'picture',
file.readAsBytes().asStream(),
file.lengthSync(),
filename: file.path.toString().split("/").last
)
);
print(resourceDetailDTO.type);
if(resourceDetailDTO.type == ResourceType.image || resourceDetailDTO.type == ResourceType.video) {
var request = http.MultipartRequest('POST', Uri.parse(appContext.getContext().clientAPI.resourceApi.apiClient.basePath+"/api/Resource/upload"));
request.files.add(
await http.MultipartFile(
'picture',
file.readAsBytes().asStream(),
file.lengthSync(),
filename: file.path.toString().split("/").last
)
);
// Todo Add header with bearer token (get via managercontext - token value)
//request.headers.addEntries(newEntries)
// Todo Add header with bearer token (get via managercontext - token value)
//request.headers.addEntries(newEntries)
request.fields['label'] = resourceDetailDTO.label;
request.fields['type'] = ResourceType.image.toString();
request.fields['label'] = resourceDetailDTO.label;
request.fields['type'] = ResourceType.image.toString();
var res = await request.send();
var res = await request.send();
if (res.statusCode == 200) {
// To refresh only (UGLY COOOOODE)
ManagerAppContext managerAppContext = appContext.getContext();
appContext.setContext(managerAppContext);
print("RESULT");
print(res.statusCode);
// TODO add message if status code not ok
showNotification(Colors.green, kWhite, 'La ressource a été créée avec succès', context);
} else {
showNotification(kPrimaryColor, kWhite, 'Une erreur est survenue lors de la création de la ressource', context);
}
} else {
ResourceDetailDTO newResource = await appContext.getContext().clientAPI.resourceApi.resourceCreate(resourceDetailDTO);
} else {
showNotification(Colors.orange, kWhite, 'Aucun fichier n\'a été chargé', context);
}
Navigator.of(context).pop();
break;
case ResourceType.imageUrl:
case ResourceType.videoUrl:
if (resourceDetailDTO.data != null) {
// test if Correct url
bool _validURL = Uri.parse(resourceDetailDTO.data).isAbsolute;
if(_validURL) {
Navigator.of(context).pop();
ResourceDetailDTO newResource = await appContext.getContext().clientAPI.resourceApi.resourceCreate(resourceDetailDTO);
// To refresh only (UGLY COOOOODE)
ManagerAppContext managerAppContext = appContext.getContext();
appContext.setContext(managerAppContext);
showNotification(Colors.green, kWhite, 'La ressource a été créée avec succès', context);
} else {
showNotification(Colors.orange, kWhite, 'L\'url est invalide', context);
}
} else {
showNotification(Colors.orange, kWhite, 'Veuillez remplir le champ URL', context);
}
break;
}
// To refresh only (UGLY COOOOODE)
ManagerAppContext managerAppContext = appContext.getContext();
appContext.setContext(managerAppContext);
showNotification(Colors.green, kWhite, 'La ressource a été créée avec succès', context);
} else {
showNotification(Colors.orange, kWhite, 'Veuillez donner un nom à la ressource', context);
}
}

View File

@ -1,8 +1,6 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:manager_app/Components/fetch_resource_icon.dart';
import 'package:manager_app/Components/fetch_section_icon.dart';
import 'package:manager_app/Models/managerContext.dart';
import 'package:manager_app/Screens/Resources/new_resource_popup.dart';
import 'package:manager_app/Screens/Resources/show_resource_popup.dart';
import 'package:manager_app/app_context.dart';
@ -10,8 +8,16 @@ import 'package:manager_app/constants.dart';
import 'package:managerapi/api.dart';
import 'package:provider/provider.dart';
import 'fetch_image_for_resource.dart';
class ResourcesScreen extends StatefulWidget {
ResourcesScreen({Key key}) : super(key: key);
final Function onGetResult;
final bool isImage;
const ResourcesScreen({
Key key,
this.isImage,
this.onGetResult,
}) : super(key: key);
@override
_ResourcesScreenState createState() => _ResourcesScreenState();
@ -52,14 +58,25 @@ class _ResourcesScreenState extends State<ResourcesScreen> {
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 6),
itemCount: data.length,
itemBuilder: (BuildContext context, int index) {
return // User Picture
return
InkWell(
onTap: () {
if (data[index].id == null) {
showNewResource(appContext, context);
if (widget.onGetResult == null) {
// Main screen
if (data[index].id == null) {
showNewResource(appContext, context);
} else {
showResource(data[index], appContext, context, size);
}
} else {
showResource(data[index], appContext, context, size);
if (data[index].id == null) {
showNewResource(appContext, context);
} else {
// Result for select modal
widget.onGetResult(data[index].id);
}
}
},
child: Container(
decoration: boxDecoration(data[index]),
@ -90,13 +107,10 @@ class _ResourcesScreenState extends State<ResourcesScreen> {
),
),
Container(
height: size.height *0.08,
child: Center(
child: Image.network(
resource.type == ResourceType.image ? appContext.getContext().clientAPI.resourceApi.apiClient.basePath+"/api/Resource/"+ resource.id : "https://miro.medium.com/max/1920/1*8wFh-pEuwyAGa1IaKb-lEw.png",
fit:BoxFit.fill
),
),
height: size.height *0.08,
child: Center(
child: getImageForResource(resource, appContext),
)
),
Align(
alignment: Alignment.bottomRight,

View File

@ -0,0 +1,96 @@
import 'package:flutter/material.dart';
import 'package:manager_app/Components/rounded_button.dart';
import 'package:manager_app/Components/string_input_container.dart';
import 'package:manager_app/Screens/Resources/resources_screen.dart';
import 'package:manager_app/constants.dart';
import 'package:managerapi/api.dart';
showSelectResourceModal (String text, Function onGetResult, int maxLines, BuildContext mainContext) { /*Function onSelect,*/
Size size = MediaQuery.of(mainContext).size;
showDialog(
builder: (BuildContext context) => AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))
),
title: Center(child: Text(text)),
content: SingleChildScrollView(
child: Column(
children: [
Container(
width: size.width * 0.6,
height: size.height * 0.6,
child: ResourcesScreen(
onGetResult: (String resourceId) {
if (resourceId != null) {
onGetResult(resourceId);
Navigator.of(mainContext).pop();
}
},
isImage: true,
),
),
/*Column(
children: showValues(newValues),
),*/
],
)
),
actions: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width: 180,
height: 70,
child: RoundedButton(
text: "Annuler",
icon: Icons.undo,
color: kSecond,
press: () {
//onGetResult(values);
print("TODO onGetResult");
Navigator.of(context).pop();
},
fontSize: 20,
),
),
/*Container(
width: 180,
height: 70,
child: RoundedButton(
text: "Valider",
icon: Icons.check,
color: kPrimaryColor,
textColor: kWhite,
press: () {
print("TODO Valider resource selected");
Navigator.of(context).pop();
},
fontSize: 20,
),
),*/
],
),
],
), context: mainContext
);
}
showValues(List<TranslationDTO> newValues) {
List<Widget> valuesToShow = new List<Widget>();
newValues.forEach((newValue) {
valuesToShow.add(
new StringInputContainer(
color: Colors.lightBlue,
label: newValue.language,
initialValue: newValue.value,
onChanged: (String value) {
newValue.value = value;
},
));
});
return valuesToShow;
}

View File

@ -6,9 +6,10 @@ import 'package:manager_app/Models/managerContext.dart';
import 'package:manager_app/app_context.dart';
import 'package:manager_app/constants.dart';
import 'package:managerapi/api.dart';
import 'package:intl/intl.dart';
void showResource(ResourceDTO resourceDTO,AppContext appContext, BuildContext context, Size size) {
import 'fetch_image_for_resource.dart';
void showResource(ResourceDTO resourceDTO, AppContext appContext, BuildContext context, Size size) {
showDialog(
builder: (BuildContext context) => AlertDialog(
shape: RoundedRectangleBorder(
@ -33,10 +34,7 @@ void showResource(ResourceDTO resourceDTO,AppContext appContext, BuildContext co
),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Image.network(
resourceDTO.type == ResourceType.image ? appContext.getContext().clientAPI.resourceApi.apiClient.basePath+"/api/Resource/"+ resourceDTO.id : "https://miro.medium.com/max/1920/1*8wFh-pEuwyAGa1IaKb-lEw.png",
fit:BoxFit.scaleDown
),
child: getImageForResource(resourceDTO, appContext),
),
),
),

View File

@ -52,4 +52,3 @@ lib/model/translation_dto.dart
lib/model/user.dart
lib/model/user_detail_dto.dart
pubspec.yaml
test/resource_type_test.dart

View File

@ -11,6 +11,7 @@ Name | Type | Description | Notes
**id** | **String** | | [optional]
**type** | [**ResourceType**](ResourceType.md) | | [optional]
**label** | **String** | | [optional]
**data** | **String** | | [optional]
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@ -15,6 +15,7 @@ class ResourceDTO {
this.id,
this.type,
this.label,
this.data,
});
String id;
@ -23,20 +24,24 @@ class ResourceDTO {
String label;
String data;
@override
bool operator ==(Object other) => identical(this, other) || other is ResourceDTO &&
other.id == id &&
other.type == type &&
other.label == label;
other.label == label &&
other.data == data;
@override
int get hashCode =>
(id == null ? 0 : id.hashCode) +
(type == null ? 0 : type.hashCode) +
(label == null ? 0 : label.hashCode);
(label == null ? 0 : label.hashCode) +
(data == null ? 0 : data.hashCode);
@override
String toString() => 'ResourceDTO[id=$id, type=$type, label=$label]';
String toString() => 'ResourceDTO[id=$id, type=$type, label=$label, data=$data]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@ -49,6 +54,9 @@ class ResourceDTO {
if (label != null) {
json[r'label'] = label;
}
if (data != null) {
json[r'data'] = data;
}
return json;
}
@ -60,6 +68,7 @@ class ResourceDTO {
id: json[r'id'],
type: ResourceType.fromJson(json[r'type']),
label: json[r'label'],
data: json[r'data'],
);
static List<ResourceDTO> listFromJson(List<dynamic> json, {bool emptyIsNull, bool growable,}) =>

View File

@ -1193,6 +1193,9 @@ components:
label:
type: string
nullable: true
data:
type: string
nullable: true
ResourceType:
type: string
description: ''