Compare commits

..

No commits in common. "Add-role-switch-instance" and "master" have entirely different histories.

831 changed files with 16830 additions and 205404 deletions

1
.gitignore vendored
View File

@ -32,6 +32,7 @@
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols

View File

@ -1,10 +0,0 @@
FROM cirrusci/flutter:3.7.0 AS build
WORKDIR /app
COPY . .
RUN flutter pub get
RUN flutter build web
FROM nginx:1.21.1-alpine
COPY --from=build /app/build/web /usr/share/nginx/html

View File

@ -15,31 +15,21 @@ For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
# Ancienne version de generation = Model generation via command line
# Model generation via command line
java -cp openapi-generator-cli-5.1.0.jar org.openapitools.codegen.OpenAPIGenerator generate -i swagger.yaml --additional-properties pubName=managerapi -g dart --enable-post-process-file
# OPENAPI Generation cmd
flutter clean
flutter pub get
dart run build_runner build --delete-conflicting-outputs
Le fichier est dans le projet.
=> Faudrait mettre à jour le projet avec les nouvelles versions plugins
# Publication sur docker
Avant de build en docker, il faut build en web => flutter build web
docker build -t manager-web .
docker build -t flutter-web .
Pour tester en local :
docker run -d -p 8080:80 name manager-web manager-web
docker run -d -p 8080:80 name flutter-web flutter-web
Image tag:
docker image tag manager-web registry.unov.be/myinfomate/manager:version-3.0.0 #registry.unov.be/mymuseum/manager:version-2.0.0
docker image tag flutter-web registry.unov.be/mymuseum/manager:latest
Docker push:
docker image push registry.unov.be/myinfomate/manager:version-3.0.0 #registry.unov.be/mymuseum/manager:version-2.0.0
docker image push registry.unov.be/mymuseum/manager:latest

View File

@ -1 +0,0 @@
Ajout du Module quizz

View File

@ -1,26 +0,0 @@
- Create BAK folder !!
- FTP fichiers vers rpi (home/Manager_app)
- puis mv -v /home/ubuntu/Manager_app/* /var/www/html/manager/
- Changer nginx : etc/nginx/sites-enabled
- Changer le port du service vers le 5002
- Ajouter ou décommenter (check addresse ip):
server {
listen 8080;
listen [::]:8080;
server_name 192.168.31.96;
root /var/www/html/manager;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
- Tester nginx : sudo nginx -t
- Reload nginx : sudo systemctl reload nginx
Connect manager via http://192.168.1.19:8089 => Si pas ça, peut aller changer dans le main.dart.js puis faire un CTRL MAJ R

View File

@ -1 +0,0 @@
2850532bac056cc3a4316af3c232a077

View File

@ -1 +0,0 @@
{"assets/animations/MDLF_animation.flr":["assets/animations/MDLF_animation.flr"],"assets/files/session.json":["assets/files/session.json"],"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"]}

View File

@ -1 +0,0 @@
[{"family":"MaterialIcons","fonts":[{"asset":"fonts/MaterialIcons-Regular.otf"}]},{"family":"packages/cupertino_icons/CupertinoIcons","fonts":[{"asset":"packages/cupertino_icons/assets/CupertinoIcons.ttf"}]}]

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 917 B

View File

@ -1,219 +0,0 @@
'use strict';
const MANIFEST = 'flutter-app-manifest';
const TEMP = 'flutter-temp-cache';
const CACHE_NAME = 'flutter-app-cache';
const RESOURCES = {
"assets/AssetManifest.json": "7ceda6dd13738309d0b4d4d2702b3010",
"assets/assets/animations/MDLF_animation.flr": "5151e91ce20a70dbc097f01a7ec97497",
"assets/assets/files/session.json": "d41d8cd98f00b204e9800998ecf8427e",
"assets/FontManifest.json": "dc3d03800ccca4601324923c0b1d6d57",
"assets/fonts/MaterialIcons-Regular.otf": "4e6447691c9509f7acdbf8a931a85ca1",
"assets/NOTICES": "838205c3fa2fbd0319ce48d7c8347af6",
"assets/packages/cupertino_icons/assets/CupertinoIcons.ttf": "6d342eb68f170c97609e9da345464e5e",
"favicon.png": "5dcef449791fa27946b3d35ad8803796",
"icons/android-icon-144x144.png": "25849c1de85e1ac87dfde295a6c97dfe",
"icons/android-icon-192x192.png": "2f38b513d97a00ddf494059260c193b5",
"icons/android-icon-36x36.png": "5317b23569b5976037738ae5dec04859",
"icons/android-icon-48x48.png": "1f7a48a32ed8b3d4c1e6fa7734534fc7",
"icons/android-icon-72x72.png": "6db0636ec0c228480197e362f3f32fe5",
"icons/android-icon-96x96.png": "d925090c0a2f6b1a24078a8640fb18e4",
"icons/apple-icon-114x114.png": "ddd67f65d43fb30b64ebf7b3ff702427",
"icons/apple-icon-120x120.png": "b6bee39cb32e80068c5e1e87c600ffbc",
"icons/apple-icon-144x144.png": "25849c1de85e1ac87dfde295a6c97dfe",
"icons/apple-icon-152x152.png": "42b1ae2dedce452961803388468d6eae",
"icons/apple-icon-180x180.png": "17655db1c0eaff334ff6208d302a576a",
"icons/apple-icon-57x57.png": "ffd9c2b4dfe93b5874edbef7a3829495",
"icons/apple-icon-60x60.png": "5984c1c3aca2b357f604855446cf30f5",
"icons/apple-icon-72x72.png": "6db0636ec0c228480197e362f3f32fe5",
"icons/apple-icon-76x76.png": "45bb7aabc4d7211f0ee13c77e6300ec4",
"icons/apple-icon-precomposed.png": "9cd7f52d632b4bb32f3b701eed4ec663",
"icons/apple-icon.png": "9cd7f52d632b4bb32f3b701eed4ec663",
"icons/browserconfig.xml": "653d077300a12f09a69caeea7a8947f8",
"icons/favicon-16x16.png": "4fca1fd9f6c90305df787a99fe7abf62",
"icons/favicon-32x32.png": "e78cf52bb5861c5829d6f2b63e0f703e",
"icons/favicon-96x96.png": "91b367951bf21712259a3aa598456d29",
"icons/favicon.ico": "941f61fe5dd76ff538f9fd9456705d7a",
"icons/Icon-192.png": "ac9a721a12bbc803b44f645561ecb1e1",
"icons/Icon-512.png": "96e752610906ba2a93c65f8abe1645f1",
"icons/manifest.json": "b58fcfa7628c9205cb11a1b2c3e8f99a",
"icons/ms-icon-144x144.png": "7f185a22f8c85fb7ccd97cd7711214e5",
"icons/ms-icon-150x150.png": "5e33aababf68472e0bcc89c752e33fec",
"icons/ms-icon-310x310.png": "9eace62e32aec3853604ae2919eca0ea",
"icons/ms-icon-70x70.png": "6720855c40d6a5ba6cd4a384605fc270",
"index.html": "b934f3f00758439d39e79bff55598ca7",
"/": "b934f3f00758439d39e79bff55598ca7",
"main.dart.js": "d92d406acbbcdeb9b4675562b75a0cd3",
"manifest.json": "2ea69ab3cf494be775c9c65d32512a45",
"version.json": "c659aa18797537bf2ce076aa3126b86e"
};
// The application shell files that are downloaded before a service worker can
// start.
const CORE = [
"/",
"main.dart.js",
"index.html",
"assets/NOTICES",
"assets/AssetManifest.json",
"assets/FontManifest.json"];
// During install, the TEMP cache is populated with the application shell files.
self.addEventListener("install", (event) => {
self.skipWaiting();
return event.waitUntil(
caches.open(TEMP).then((cache) => {
return cache.addAll(
CORE.map((value) => new Request(value, {'cache': 'reload'})));
})
);
});
// During activate, the cache is populated with the temp files downloaded in
// install. If this service worker is upgrading from one with a saved
// MANIFEST, then use this to retain unchanged resource files.
self.addEventListener("activate", function(event) {
return event.waitUntil(async function() {
try {
var contentCache = await caches.open(CACHE_NAME);
var tempCache = await caches.open(TEMP);
var manifestCache = await caches.open(MANIFEST);
var manifest = await manifestCache.match('manifest');
// When there is no prior manifest, clear the entire cache.
if (!manifest) {
await caches.delete(CACHE_NAME);
contentCache = await caches.open(CACHE_NAME);
for (var request of await tempCache.keys()) {
var response = await tempCache.match(request);
await contentCache.put(request, response);
}
await caches.delete(TEMP);
// Save the manifest to make future upgrades efficient.
await manifestCache.put('manifest', new Response(JSON.stringify(RESOURCES)));
return;
}
var oldManifest = await manifest.json();
var origin = self.location.origin;
for (var request of await contentCache.keys()) {
var key = request.url.substring(origin.length + 1);
if (key == "") {
key = "/";
}
// If a resource from the old manifest is not in the new cache, or if
// the MD5 sum has changed, delete it. Otherwise the resource is left
// in the cache and can be reused by the new service worker.
if (!RESOURCES[key] || RESOURCES[key] != oldManifest[key]) {
await contentCache.delete(request);
}
}
// Populate the cache with the app shell TEMP files, potentially overwriting
// cache files preserved above.
for (var request of await tempCache.keys()) {
var response = await tempCache.match(request);
await contentCache.put(request, response);
}
await caches.delete(TEMP);
// Save the manifest to make future upgrades efficient.
await manifestCache.put('manifest', new Response(JSON.stringify(RESOURCES)));
return;
} catch (err) {
// On an unhandled exception the state of the cache cannot be guaranteed.
console.error('Failed to upgrade service worker: ' + err);
await caches.delete(CACHE_NAME);
await caches.delete(TEMP);
await caches.delete(MANIFEST);
}
}());
});
// The fetch handler redirects requests for RESOURCE files to the service
// worker cache.
self.addEventListener("fetch", (event) => {
if (event.request.method !== 'GET') {
return;
}
var origin = self.location.origin;
var key = event.request.url.substring(origin.length + 1);
// Redirect URLs to the index.html
if (key.indexOf('?v=') != -1) {
key = key.split('?v=')[0];
}
if (event.request.url == origin || event.request.url.startsWith(origin + '/#') || key == '') {
key = '/';
}
// If the URL is not the RESOURCE list then return to signal that the
// browser should take over.
if (!RESOURCES[key]) {
return;
}
// If the URL is the index.html, perform an online-first request.
if (key == '/') {
return onlineFirst(event);
}
event.respondWith(caches.open(CACHE_NAME)
.then((cache) => {
return cache.match(event.request).then((response) => {
// Either respond with the cached resource, or perform a fetch and
// lazily populate the cache.
return response || fetch(event.request).then((response) => {
cache.put(event.request, response.clone());
return response;
});
})
})
);
});
self.addEventListener('message', (event) => {
// SkipWaiting can be used to immediately activate a waiting service worker.
// This will also require a page refresh triggered by the main worker.
if (event.data === 'skipWaiting') {
self.skipWaiting();
return;
}
if (event.data === 'downloadOffline') {
downloadOffline();
return;
}
});
// Download offline will check the RESOURCES for all files not in the cache
// and populate them.
async function downloadOffline() {
var resources = [];
var contentCache = await caches.open(CACHE_NAME);
var currentContent = {};
for (var request of await contentCache.keys()) {
var key = request.url.substring(origin.length + 1);
if (key == "") {
key = "/";
}
currentContent[key] = true;
}
for (var resourceKey of Object.keys(RESOURCES)) {
if (!currentContent[resourceKey]) {
resources.push(resourceKey);
}
}
return contentCache.addAll(resources);
}
// Attempt to download the resource online before falling back to
// the offline cache.
function onlineFirst(event) {
return event.respondWith(
fetch(event.request).then((response) => {
return caches.open(CACHE_NAME).then((cache) => {
cache.put(event.request, response.clone());
return response;
});
}).catch((error) => {
return caches.open(CACHE_NAME).then((cache) => {
return cache.match(event.request).then((response) => {
if (response != null) {
return response;
}
throw error;
});
});
})
);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig><msapplication><tile><square70x70logo src="/ms-icon-70x70.png"/><square150x150logo src="/ms-icon-150x150.png"/><square310x310logo src="/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 826 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,41 +0,0 @@
{
"name": "App",
"icons": [
{
"src": "\/android-icon-36x36.png",
"sizes": "36x36",
"type": "image\/png",
"density": "0.75"
},
{
"src": "\/android-icon-48x48.png",
"sizes": "48x48",
"type": "image\/png",
"density": "1.0"
},
{
"src": "\/android-icon-72x72.png",
"sizes": "72x72",
"type": "image\/png",
"density": "1.5"
},
{
"src": "\/android-icon-96x96.png",
"sizes": "96x96",
"type": "image\/png",
"density": "2.0"
},
{
"src": "\/android-icon-144x144.png",
"sizes": "144x144",
"type": "image\/png",
"density": "3.0"
},
{
"src": "\/android-icon-192x192.png",
"sizes": "192x192",
"type": "image\/png",
"density": "4.0"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -1,115 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<!--
If you are serving your web app in a path other than the root, change the
href value below to reflect the base path you are serving from.
The path provided below has to start and end with a slash "/" in order for
it to work correctly.
For more details:
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
-->
<base href="/">
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A new Flutter application.">
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="manager_app">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<link rel="apple-touch-icon" sizes="57x57" href="icons/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="icons/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="icons/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="icons/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="icons/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="icons/apple-icon-120x120.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="180x180" href="icons/apple-icon-180x180.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="96x96" href="icons/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="icons/favicon-16x16.png">
<link rel="manifest" href="/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="icons/ms-icon-144x144.png">
<meta name="theme-color" content="#ffffff">
<title>manager_app</title>
<link rel="manifest" href="manifest.json">
</head>
<body>
<!-- This script installs service_worker.js to provide PWA functionality to
application. For more information, see:
https://developers.google.com/web/fundamentals/primers/service-workers -->
<script>
var serviceWorkerVersion = '3552968134';
var scriptLoaded = false;
function loadMainDartJs() {
if (scriptLoaded) {
return;
}
scriptLoaded = true;
var scriptTag = document.createElement('script');
scriptTag.src = 'main.dart.js';
scriptTag.type = 'application/javascript';
document.body.append(scriptTag);
}
if ('serviceWorker' in navigator) {
// Service workers are supported. Use them.
window.addEventListener('load', function () {
// Wait for registration to finish before dropping the <script> tag.
// Otherwise, the browser will load the script multiple times,
// potentially different versions.
var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;
navigator.serviceWorker.register(serviceWorkerUrl)
.then((reg) => {
function waitForActivation(serviceWorker) {
serviceWorker.addEventListener('statechange', () => {
if (serviceWorker.state == 'activated') {
console.log('Installed new service worker.');
loadMainDartJs();
}
});
}
if (!reg.active && (reg.installing || reg.waiting)) {
// No active web worker and we have installed or are installing
// one for the first time. Simply wait for it to activate.
waitForActivation(reg.installing ?? reg.waiting);
} else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
// When the app updates the serviceWorkerVersion changes, so we
// need to ask the service worker to update.
console.log('New service worker available.');
reg.update();
waitForActivation(reg.installing);
} else {
// Existing service worker is still good.
console.log('Loading app from service worker.');
loadMainDartJs();
}
});
// If service worker doesn't succeed in a reasonable amount of time,
// fallback to plaint <script> tag.
setTimeout(() => {
if (!scriptLoaded) {
console.warn(
'Failed to load app from service worker. Falling back to plain <script> tag.',
);
loadMainDartJs();
}
}, 4000);
});
} else {
// Service workers not supported. Just drop the <script> tag.
loadMainDartJs();
}
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@ -1,59 +0,0 @@
{
"name": "Manager app",
"short_name": "Manager_app",
"start_url": ".",
"display": "standalone",
"background_color": "#0175C2",
"theme_color": "#0175C2",
"description": "Manager application for MDLF",
"orientation": "portrait-primary",
"prefer_related_applications": false,
"icons": [
{
"src": "icons/android-icon-36x36.png",
"sizes": "36x36",
"type": "image/png",
"density": "0.75"
},
{
"src": "icons/android-icon-48x48.png",
"sizes": "48x48",
"type": "image/png",
"density": "1.0"
},
{
"src": "icons/android-icon-72x72.png",
"sizes": "72x72",
"type": "image/png",
"density": "1.5"
},
{
"src": "icons/android-icon-96x96.png",
"sizes": "96x96",
"type": "image/png",
"density": "2.0"
},
{
"src": "icons/android-icon-144x144.png",
"sizes": "144x144",
"type": "image/png",
"density": "3.0"
},
{
"src": "icons/android-icon-192x192.png",
"sizes": "192x192",
"type": "image/png",
"density": "4.0"
},
{
"src": "icons/Icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icons/Icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}

View File

@ -1 +0,0 @@
{"app_name":"manager_app","version":"1.0.0","build_number":"1","package_name":"manager_app"}

View File

@ -1,28 +0,0 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at https://dart.dev/lints.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options

View File

@ -34,7 +34,7 @@ android {
defaultConfig {
applicationId "be.mdlf.manager_app"
minSdkVersion flutter.minSdkVersion
minSdkVersion 16
targetSdkVersion 30
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName

View File

@ -1,12 +1,12 @@
buildscript {
ext.kotlin_version = '1.7.10'
ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.1'
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
@ -26,6 +26,6 @@ subprojects {
project.evaluationDependsOn(':app')
}
tasks.register("clean", Delete) {
task clean(type: Delete) {
delete rootProject.buildDir
}

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip

View File

@ -1,6 +0,0 @@
{
"backend": {
"baseUrl": "http://localhost:5000/api",
"apiKey": "6848e18f-d1d7-49fb-a047-c213c646904b"
}
}

View File

@ -1,6 +0,0 @@
{
"backend": {
"baseUrl": "https://espaces-naturels-mobile-orange.intranet.etat.lu/api",
"apiKey": "6848e18f-d1d7-49fb-a047-c213c646904b"
}
}

View File

@ -1,111 +0,0 @@
<h1>Privacy Policy</h1>
<p>Effective date: 2023-02-20</p>
<p>Updated on: 2023-02-20</p>
<p>
This Privacy Policy explains the policies of UNOV on the collection
and use of the information we collect when you access https://manager.myinfomate.be/ (the “Service”). This Privacy Policy describes your
privacy rights and how you are protected under privacy laws.</p>
<p>
By using our Service, you are consenting to the collection and use of your information in accordance
with this Privacy Policy. Please do not access or use our Service if you do not consent to the collection
and use of your information as outlined in this Privacy Policy. This Privacy Policy has been created with
the help of <a target="_blank" href="https://cookie-script.com/privacy-policy-generator">CookieScript Privacy Policy Generator</a>.</p>
<p>UNOV is authorized to modify this Privacy Policy at any time.
This may occur without prior notice.</p>
<p>
UNOV will post the revised Privacy Policy on the https://manager.myinfomate.be/ website</p>
<h3>Collection and Use of Your Personal Information</h3>
<h4>Information We Collect</h4>
<p>
When using our Service, you will be prompted to provide us with personal information used to
contact or identify you. https://manager.myinfomate.be/ collects the following information: </p>
<ul>
<li>Usage Data</li>
</ul>
<p>Usage Data includes the following:</p>
<ul>
<li>Internet Protocol (IP) address of computers accessing the site</li>
<li>Web page requests</li>
<li>Referring web pages</li>
<li>Browser used to access site</li>
<li>Time and date of access</li>
</ul>
<h4>How We Collect Information</h4>
<p>
https://manager.myinfomate.be/ collects and receives information from you in the following manner: </p>
<ul>
<li>When you fill a registration form or otherwise submit your personal information.</li>
</ul>
<p>
Your information will be stored for up to 1 days after it is
no longer required to provide you the services. Your information may be retained for longer periods for
reporting or record- keeping in accordance with applicable laws. Information which does not identify you
personally may be stored indefinitely. </p>
<h4>How We Use Your Information</h4>
<p>
https://manager.myinfomate.be/ may use your information for the following purposes: </p>
<ul>
<li><b>Providing and maintaining our Service,</b> as well as monitoring the usage of our Service.</li>
<li><b>For other purposes.</b> UNOV will use your information for data analysis to identify usage
trends or determine the effective of our marketing campaigns when reasonable. We will use
your information to evaluate and improve our Service, products, services, and marketing efforts.</li>
<li>Show content based on location</li>
</ul>
<h4>How We Share Your Information</h4>
<p>
UNOV will share your information, when applicable, in the following situations: </p>
<ul>
<li><b>With your consent.</b> UNOV will share your information for any purpose with your explicit
consent.</li>
</ul>
<h4>Third-party Sharing</h4>
<p>Your information may be disclosed for additional reasons, including:</p>
<ul>
<li>Complying with applicable laws, regulations, or court orders.</li>
<li>Responding to claims that your use of our Service violates third-party rights.</li>
<li>Enforcing agreements you make with us, including this Privacy Policy.</li>
</ul>
<h4>Cookies</h4>
<p>
Cookies are small text files that are placed on your computer by websites that you visit. Websites use
cookies to help users navigate efficiently and perform certain functions. Cookies that are required for
the website to operate properly are allowed to be set without your permission. All other cookies need
to be approved before they can be set in the browser. </p>
<ul>
<li><b>Strictly necessary cookies.</b> Strictly necessary cookies allow core website functionality such as
user login and account management. The website cannot be used properly without strictly necessary cookies.</li>
</ul>
<h4>Security</h4>
<p>
Your informations security is important to us. https://manager.myinfomate.be/
utilizes a range of security measures to prevent the misuse, loss, or alteration of the information you have given us.
However, because we cannot guarantee the security of the information you provide us, you must access our service at your
own risk. </p>
<p>
UNOV is not responsible for the performance of websites
operated by third parties or your interactions with them. When you leave this website, we recommend you review the
privacy practices of other websites you interact with and determine the adequacy of those practices. </p>
<h4>Contact Us</h4>
<p>For any questions, please contact us through the following methods:</p>
<p>Name: UNOV</p>
<p>Address: Rue Mazy 72</p>
<p>Email: contact@unov.be</p>
<p>Website: https://manager.myinfomate.be/</p>
<p>
For any queries or concerns you have related to the processing of your information,
you may contact our Privacy Officer at Fransolet Thomas, contact@unov.be. </p>

View File

@ -1,98 +0,0 @@
PRIVACY POLICY
Effective date: 2023-02-20
Updated on: 2024-01-11
This Privacy Policy explains the policies of UNOV on the collection and use of the information we collect when you use the mobile app "MyInfoMate". This Privacy Policy describes your privacy rights and how you are protected under privacy laws.
By using our Service, you are consenting to the collection and use of your information in accordance with this Privacy Policy. Please do not access or use our
Service if you do not consent to the collection and use of your information as outlined in this Privacy Policy. This Privacy Policy has been created with the
help of CookieScript Privacy Policy Generator.
UNOV is authorized to modify this Privacy Policy at any time. This may occur without prior notice.
UNOV will post the revised Privacy Policy on the https://manager.myinfomate.be/ website
COLLECTION AND USE OF YOUR PERSONAL INFORMATION
INFORMATION WE COLLECT
When using our Service, you will be prompted to provide us with personal information used to contact or identify you. The mobile app "MyInfoMate" collects the following information:
* Usage Data
Usage Data includes the following:
* Internet Protocol (IP) address of computers accessing the site
* Web page requests
* Referring web pages
* Browser used to access site
* Time and date of access
HOW WE COLLECT INFORMATION
The mobile app "MyInfoMate" collects and receives information from you in the following manner:
* When you fill a registration form or otherwise submit your personal information.
Your information will be stored for up to 1 days after it is no longer required to provide you the services. Your information may be retained for longer periods
for reporting or record- keeping in accordance with applicable laws. Information which does not identify you personally may be stored indefinitely.
HOW WE USE YOUR INFORMATION
The mobile app "MyInfoMate" may use your information for the following purposes:
* Providing and maintaining our Service, as well as monitoring the usage of our Service.
* For other purposes. UNOV will use your information for data analysis to identify usage trends or determine the effective of our marketing campaigns when
reasonable. We will use your information to evaluate and improve our Service, products, services, and marketing efforts.
* As explained before, only to show content based on location (The collection of location data also occurs in background)
HOW WE SHARE YOUR INFORMATION
UNOV will share your information, when applicable, in the following situations:
* With your consent. UNOV will share your information for any purpose with your explicit consent.
THIRD-PARTY SHARING
Your information may be disclosed for additional reasons, including:
* Complying with applicable laws, regulations, or court orders.
* Responding to claims that your use of our Service violates third-party rights.
* Enforcing agreements you make with us, including this Privacy Policy.
COOKIES
Cookies are small text files that are placed on your computer by websites that you visit. Websites use cookies to help users navigate efficiently and perform
certain functions. Cookies that are required for the website to operate properly are allowed to be set without your permission. All other cookies need to be
approved before they can be set in the browser.
* Strictly necessary cookies. Strictly necessary cookies allow core website functionality such as user login and account management. The website cannot be used
properly without strictly necessary cookies.
SECURITY
Your informations security is important to us. The mobile app "MyInfoMate" utilizes a range of security measures to prevent the misuse, loss, or
alteration of the information you have given us. However, because we cannot guarantee the security of the information you provide us, you must access our
service at your own risk.
UNOV is not responsible for the performance of websites operated by third parties or your interactions with them. When you leave this website, we recommend you
review the privacy practices of other websites you interact with and determine the adequacy of those practices.
CONTACT US
For any questions, please contact us through the following methods:
Name: UNOV
Address: Rue René Copette 3
Email: contact@unov.be
Website: https://manager.myinfomate.be/
Mobile Application : "MyInfoMate"
For any queries or concerns you have related to the processing of your information, you may contact our Privacy Officer at Fransolet Thomas, contact@unov.be.

View File

@ -1,100 +0,0 @@
PRIVACY POLICY
Effective date: 2024-07-07
Updated on: 2024-07-07
This Privacy Policy explains the policies of UNOV on the collection and use of the information we collect when you use the mobile app "Fort de Saint-Héribert". This Privacy Policy describes your privacy rights and how you are protected under privacy laws.
By using our Service, you are consenting to the collection and use of your information in accordance with this Privacy Policy. Please do not access or use our
Service if you do not consent to the collection and use of your information as outlined in this Privacy Policy. This Privacy Policy has been created with the
help of CookieScript Privacy Policy Generator.
UNOV is authorized to modify this Privacy Policy at any time. This may occur without prior notice.
UNOV will post the revised Privacy Policy on the https://manager.myinfomate.be/ website
COLLECTION AND USE OF YOUR PERSONAL INFORMATION
INFORMATION WE COLLECT
When using our Service, you will be prompted to provide us with personal information used to contact or identify you. The mobile app "Fort de Saint-Héribert" collects the following information:
* Usage Data
* User location but briefly and only to show content in app. This location data is not store or send to other services. The collection of location data also occurs in background.
Usage Data includes the following:
* Internet Protocol (IP) address of computers accessing the site
* Web page requests
* Referring web pages
* Browser used to access site
* Time and date of access
HOW WE COLLECT INFORMATION
The mobile app "Fort de Saint-Héribert" collects and receives information from you in the following manner:
* When you fill a registration form or otherwise submit your personal information.
Your information will be stored for up to 1 days after it is no longer required to provide you the services. Your information may be retained for longer periods
for reporting or record- keeping in accordance with applicable laws. Information which does not identify you personally may be stored indefinitely.
HOW WE USE YOUR INFORMATION
The mobile app "Fort de Saint-Héribert" may use your information for the following purposes:
* Providing and maintaining our Service, as well as monitoring the usage of our Service.
* For other purposes. UNOV will use your information for data analysis to identify usage trends or determine the effective of our marketing campaigns when
reasonable. We will use your information to evaluate and improve our Service, products, services, and marketing efforts.
* As explained before, only to show content based on location (The collection of location data also occurs in background)
HOW WE SHARE YOUR INFORMATION
UNOV will share your information, when applicable, in the following situations:
* With your consent. UNOV will share your information for any purpose with your explicit consent.
THIRD-PARTY SHARING
Your information may be disclosed for additional reasons, including:
* Complying with applicable laws, regulations, or court orders.
* Responding to claims that your use of our Service violates third-party rights.
* Enforcing agreements you make with us, including this Privacy Policy.
COOKIES
Cookies are small text files that are placed on your computer by websites that you visit. Websites use cookies to help users navigate efficiently and perform
certain functions. Cookies that are required for the website to operate properly are allowed to be set without your permission. All other cookies need to be
approved before they can be set in the browser.
* Strictly necessary cookies. Strictly necessary cookies allow core website functionality such as user login and account management. The website cannot be used
properly without strictly necessary cookies.
SECURITY
Your informations security is important to us. The mobile app "Fort de Saint-Héribert" utilizes a range of security measures to prevent the misuse, loss, or
alteration of the information you have given us. However, because we cannot guarantee the security of the information you provide us, you must access our
service at your own risk.
UNOV is not responsible for the performance of websites operated by third parties or your interactions with them. When you leave this website, we recommend you
review the privacy practices of other websites you interact with and determine the adequacy of those practices.
CONTACT US
For any questions, please contact us through the following methods:
Name: UNOV
Address: Rue René Copette 3
Email: contact@unov.be
Website: https://manager.myinfomate.be/
Mobile Application : "Fort de Saint-Héribert"
For any queries or concerns you have related to the processing of your information, you may contact our Privacy Officer at Fransolet Thomas, contact@unov.be.

View File

@ -1,100 +0,0 @@
PRIVACY POLICY
Effective date: 2024-07-07
Updated on: 2024-07-07
This Privacy Policy explains the policies of UNOV on the collection and use of the information we collect when you use the mobile app "Musée de la fraise". This Privacy Policy describes your privacy rights and how you are protected under privacy laws.
By using our Service, you are consenting to the collection and use of your information in accordance with this Privacy Policy. Please do not access or use our
Service if you do not consent to the collection and use of your information as outlined in this Privacy Policy. This Privacy Policy has been created with the
help of CookieScript Privacy Policy Generator.
UNOV is authorized to modify this Privacy Policy at any time. This may occur without prior notice.
UNOV will post the revised Privacy Policy on the https://manager.myinfomate.be/ website
COLLECTION AND USE OF YOUR PERSONAL INFORMATION
INFORMATION WE COLLECT
When using our Service, you will be prompted to provide us with personal information used to contact or identify you. The mobile app "Musée de la fraise" collects the following information:
* Usage Data
* User location but briefly and only to show content in app. This location data is not store or send to other services. The collection of location data also occurs in background.
Usage Data includes the following:
* Internet Protocol (IP) address of computers accessing the site
* Web page requests
* Referring web pages
* Browser used to access site
* Time and date of access
HOW WE COLLECT INFORMATION
The mobile app "Musée de la fraise" collects and receives information from you in the following manner:
* When you fill a registration form or otherwise submit your personal information.
Your information will be stored for up to 1 days after it is no longer required to provide you the services. Your information may be retained for longer periods
for reporting or record- keeping in accordance with applicable laws. Information which does not identify you personally may be stored indefinitely.
HOW WE USE YOUR INFORMATION
The mobile app "Musée de la fraise" may use your information for the following purposes:
* Providing and maintaining our Service, as well as monitoring the usage of our Service.
* For other purposes. UNOV will use your information for data analysis to identify usage trends or determine the effective of our marketing campaigns when
reasonable. We will use your information to evaluate and improve our Service, products, services, and marketing efforts.
* As explained before, only to show content based on location (The collection of location data also occurs in background)
HOW WE SHARE YOUR INFORMATION
UNOV will share your information, when applicable, in the following situations:
* With your consent. UNOV will share your information for any purpose with your explicit consent.
THIRD-PARTY SHARING
Your information may be disclosed for additional reasons, including:
* Complying with applicable laws, regulations, or court orders.
* Responding to claims that your use of our Service violates third-party rights.
* Enforcing agreements you make with us, including this Privacy Policy.
COOKIES
Cookies are small text files that are placed on your computer by websites that you visit. Websites use cookies to help users navigate efficiently and perform
certain functions. Cookies that are required for the website to operate properly are allowed to be set without your permission. All other cookies need to be
approved before they can be set in the browser.
* Strictly necessary cookies. Strictly necessary cookies allow core website functionality such as user login and account management. The website cannot be used
properly without strictly necessary cookies.
SECURITY
Your informations security is important to us. The mobile app "Musée de la fraise" utilizes a range of security measures to prevent the misuse, loss, or
alteration of the information you have given us. However, because we cannot guarantee the security of the information you provide us, you must access our
service at your own risk.
UNOV is not responsible for the performance of websites operated by third parties or your interactions with them. When you leave this website, we recommend you
review the privacy practices of other websites you interact with and determine the adequacy of those practices.
CONTACT US
For any questions, please contact us through the following methods:
Name: UNOV
Address: Rue René Copette 3
Email: contact@unov.be
Website: https://manager.myinfomate.be/
Mobile Application : "Musée de la fraise"
For any queries or concerns you have related to the processing of your information, you may contact our Privacy Officer at Fransolet Thomas, contact@unov.be.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 KiB

View File

@ -1,650 +0,0 @@
<?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="cccccccccccccccccscccccccccccc" />
<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" />
<path
d="M0 0 C4 1 4 1 4 1 Z "
fill="#19F2F2"
transform="translate(75,409)"
id="path21" />
<path
d="M0 0 C4 1 4 1 4 1 Z "
fill="#2A4A4A"
transform="translate(159,7)"
id="path22" />
<path
d="M0 0 C4 1 4 1 4 1 Z "
fill="#001F1F"
transform="translate(143,7)"
id="path23" />
<path
d="M0 0 C4 1 4 1 4 1 Z "
fill="#000000"
transform="translate(125,7)"
id="path24" />
<path
d="M0 0 C3 1 3 1 3 1 Z "
fill="#2A2AD4"
transform="translate(203,411)"
id="path25" />
<path
d="M0 0 C3 1 3 1 3 1 Z "
fill="#46B8E2"
transform="translate(80,410)"
id="path26" />
<path
d="M0 0 C3 1 3 1 3 1 Z "
fill="#005454"
transform="translate(84,7)"
id="path27" />
<path
d=""
fill="#0000FF"
transform="translate(0,0)"
id="path28" />
<path
d="M0 0 C2 1 2 1 2 1 Z "
fill="#0000FF"
transform="translate(228,411)"
id="path29" />
<path
d="M0 0 C2 1 2 1 2 1 Z "
fill="#0000FF"
transform="translate(214,411)"
id="path30" />
<path
d="M0 0 C2 1 2 1 2 1 Z "
fill="#3F3FBF"
transform="translate(196,411)"
id="path31" />
<path
d="M0 0 C2 1 2 1 2 1 Z "
fill="#0000FF"
transform="translate(172,411)"
id="path32" />
<path
d="M0 0 C2 1 2 1 2 1 Z "
fill="#3F3FDF"
transform="translate(147,411)"
id="path33" />
<path
d="M0 0 C2 1 2 1 2 1 Z "
fill="#3FBFBF"
transform="translate(115,411)"
id="path34" />
<path
d="M0 0 C2 1 2 1 2 1 Z "
fill="#3FBFBF"
transform="translate(107,411)"
id="path35" />
<path
d="M0 0 C2 1 2 1 2 1 Z "
fill="#00FFFF"
transform="translate(83,411)"
id="path36" />
<path
d="M0 0 C2 1 2 1 2 1 Z "
fill="#7FFFFF"
transform="translate(63,405)"
id="path37" />
<path
d="M0 0 C2 1 2 1 2 1 Z "
fill="#AA5555"
transform="translate(400,389)"
id="path38" />
<path
d=""
fill="#FF003F"
transform="translate(0,0)"
id="path39" />
<path
d=""
fill="#5FDFDF"
transform="translate(0,0)"
id="path40" />
<path
d=""
fill="#000000"
transform="translate(0,0)"
id="path41" />
<path
d="M0 0 C2 1 2 1 2 1 Z "
fill="#4A4A6A"
transform="translate(60,14)"
id="path42" />
<path
d="M0 0 C2 1 2 1 2 1 Z "
fill="#000000"
transform="translate(200,7)"
id="path43" />
<path
d="M0 0 C2 1 2 1 2 1 Z "
fill="#3F3F3F"
transform="translate(183,7)"
id="path44" />
<path
d="M0 0 C2 1 2 1 2 1 Z "
fill="#000000"
transform="translate(170,7)"
id="path45" />
<path
d="M0 0 C2 1 2 1 2 1 Z "
fill="#003F3F"
transform="translate(108,7)"
id="path46" />
<path
d="M0 0 C2 1 2 1 2 1 Z "
fill="#94946A"
transform="translate(232,6)"
id="path48" />
<path
d=""
fill="#FF00FF"
transform="translate(0,0)"
id="path49" />
<path
d=""
fill="#0000FF"
transform="translate(0,0)"
id="path50" />
<path
d=""
fill="#00FFFF"
transform="translate(0,0)"
id="path51" />
<path
d=""
fill="#00FFFF"
transform="translate(0,0)"
id="path52" />
<path
d=""
fill="#00FFFF"
transform="translate(0,0)"
id="path53" />
<path
d=""
fill="#0000FF"
transform="translate(0,0)"
id="path54" />
<path
d=""
fill="#0000FF"
transform="translate(0,0)"
id="path55" />
<path
d=""
fill="#0000FF"
transform="translate(0,0)"
id="path56" />
<path
d=""
fill="#0000FF"
transform="translate(0,0)"
id="path57" />
<path
d=""
fill="#FF0000"
transform="translate(0,0)"
id="path58" />
<path
d=""
fill="#FF0000"
transform="translate(0,0)"
id="path59" />
<path
d=""
fill="#FF0000"
transform="translate(0,0)"
id="path60" />
<path
d=""
fill="#FF0000"
transform="translate(0,0)"
id="path61" />
<path
d=""
fill="#FF0000"
transform="translate(0,0)"
id="path62" />
<path
d=""
fill="#FF0000"
transform="translate(0,0)"
id="path63" />
<path
d=""
fill="#FF00FF"
transform="translate(0,0)"
id="path64" />
<path
d=""
fill="#FF00FF"
transform="translate(0,0)"
id="path65" />
<path
d=""
fill="#0000FF"
transform="translate(0,0)"
id="path66" />
<path
d=""
fill="#5555AA"
transform="translate(0,0)"
id="path67" />
<path
d=""
fill="#0000FF"
transform="translate(0,0)"
id="path68" />
<path
d=""
fill="#0000FF"
transform="translate(0,0)"
id="path69" />
<path
d=""
fill="#7F7F7F"
transform="translate(0,0)"
id="path70" />
<path
d=""
fill="#0000FF"
transform="translate(0,0)"
id="path71" />
<path
d=""
fill="#7F7F7F"
transform="translate(0,0)"
id="path72" />
<path
d=""
fill="#00FFFF"
transform="translate(0,0)"
id="path73" />
<path
d=""
fill="#00FFFF"
transform="translate(0,0)"
id="path74" />
<path
d=""
fill="#00FFFF"
transform="translate(0,0)"
id="path75" />
<path
d=""
fill="#FF0000"
transform="translate(0,0)"
id="path76" />
<path
d=""
fill="#FF0000"
transform="translate(0,0)"
id="path77" />
<path
d=""
fill="#0000FF"
transform="translate(0,0)"
id="path78" />
<path
d=""
fill="#FF0000"
transform="translate(0,0)"
id="path79" />
<path
d=""
fill="#FF0000"
transform="translate(0,0)"
id="path80" />
<path
d=""
fill="#FF0000"
transform="translate(0,0)"
id="path81" />
<path
d=""
fill="#FF007F"
transform="translate(0,0)"
id="path82" />
<path
d=""
fill="#55AAAA"
transform="translate(0,0)"
id="path83" />
<path
d=""
fill="#FF0000"
transform="translate(0,0)"
id="path84" />
<path
d=""
fill="#00FFFF"
transform="translate(0,0)"
id="path85" />
<path
d=""
fill="#00FFFF"
transform="translate(0,0)"
id="path86" />
<path
d=""
fill="#55AAAA"
transform="translate(0,0)"
id="path87" />
<path
d=""
fill="#55AAAA"
transform="translate(0,0)"
id="path88" />
<path
d=""
fill="#00FFFF"
transform="translate(0,0)"
id="path89" />
<path
d=""
fill="#7F7FFF"
transform="translate(0,0)"
id="path90" />
<path
d=""
fill="#00FFFF"
transform="translate(0,0)"
id="path91" />
<path
d=""
fill="#00FFFF"
transform="translate(0,0)"
id="path92" />
<path
d=""
fill="#7F7F7F"
transform="translate(0,0)"
id="path93" />
<path
d=""
fill="#55AAAA"
transform="translate(0,0)"
id="path94" />
<path
d=""
fill="#7FFFFF"
transform="translate(0,0)"
id="path95" />
<path
d=""
fill="#00FFFF"
transform="translate(0,0)"
id="path96" />
<path
d=""
fill="#FF0000"
transform="translate(0,0)"
id="path97" />
<path
d=""
fill="#00FFFF"
transform="translate(0,0)"
id="path98" />
<path
d=""
fill="#55AAAA"
transform="translate(0,0)"
id="path99" />
<path
d=""
fill="#007F7F"
transform="translate(0,0)"
id="path100" />
<path
d=""
fill="#000000"
transform="translate(0,0)"
id="path101" />
<path
d=""
fill="#FFFF00"
transform="translate(0,0)"
id="path102" />
<path
d=""
fill="#FF7F00"
transform="translate(0,0)"
id="path103" />
<path
d=""
fill="#FFFF00"
transform="translate(0,0)"
id="path104" />
<path
d=""
fill="#007F7F"
transform="translate(0,0)"
id="path105" />
<path
d=""
fill="#FF7F00"
transform="translate(0,0)"
id="path106" />
<path
d=""
fill="#005555"
transform="translate(0,0)"
id="path107" />
<path
d=""
fill="#FFFF00"
transform="translate(0,0)"
id="path108" />
<path
d=""
fill="#3F3F7F"
transform="translate(0,0)"
id="path109" />
<path
d=""
fill="#FFFF00"
transform="translate(0,0)"
id="path110" />
<path
d=""
fill="#FFFF00"
transform="translate(0,0)"
id="path111" />
<path
d=""
fill="#FF7F00"
transform="translate(0,0)"
id="path112" />
<path
d=""
fill="#FFFF00"
transform="translate(0,0)"
id="path113" />
<path
d=""
fill="#000000"
transform="translate(0,0)"
id="path114" />
<path
d=""
fill="#FF7F00"
transform="translate(0,0)"
id="path115" />
<path
d=""
fill="#000000"
transform="translate(0,0)"
id="path116" />
<path
d=""
fill="#FF7F00"
transform="translate(0,0)"
id="path117" />
<path
d=""
fill="#7F7F7F"
transform="translate(0,0)"
id="path118" />
<path
d=""
fill="#000000"
transform="translate(0,0)"
id="path119" />
<path
d=""
fill="#000000"
transform="translate(0,0)"
id="path120" />
<path
d=""
fill="#7F7F7F"
transform="translate(0,0)"
id="path121" />
<path
d=""
fill="#007F7F"
transform="translate(0,0)"
id="path122" />
<path
d=""
fill="#000000"
transform="translate(0,0)"
id="path123" />
<path
d=""
fill="#007F7F"
transform="translate(0,0)"
id="path124" />
<path
d=""
fill="#000000"
transform="translate(0,0)"
id="path125" />
<path
d=""
fill="#000000"
transform="translate(0,0)"
id="path126" />
<path
d=""
fill="#000000"
transform="translate(0,0)"
id="path127" />
<path
d=""
fill="#000000"
transform="translate(0,0)"
id="path128" />
<path
d=""
fill="#000000"
transform="translate(0,0)"
id="path129" />
<path
d=""
fill="#555555"
transform="translate(0,0)"
id="path130" />
<path
d=""
fill="#000000"
transform="translate(0,0)"
id="path131" />
<path
d=""
fill="#FFFF00"
transform="translate(0,0)"
id="path132" />
<path
d=""
fill="#919148"
transform="translate(0,0)"
id="path133" />
<path
d=""
fill="#FFFF00"
transform="translate(0,0)"
id="path134" />
<path
d=""
fill="#7F7F7F"
transform="translate(0,0)"
id="path135" />
<path
d=""
fill="#000000"
transform="translate(0,0)"
id="path136" />
<path
d=""
fill="#000000"
transform="translate(0,0)"
id="path137" />
</svg>

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 705 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 279 B

View File

@ -1,173 +0,0 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:manager_app/Components/common_loader.dart';
import 'package:manager_app/Models/managerContext.dart';
import 'package:manager_app/app_context.dart';
import 'package:manager_app/constants.dart';
import 'package:manager_app/Screens/Resources/select_resource_modal.dart';
import 'package:manager_api_new/api.dart';
import 'package:provider/provider.dart';
class AudioInputContainer extends StatefulWidget {
final Color color;
final String? label;
final String? initialValue;
final ValueChanged<ResourceDTO> onChanged;
final BoxFit imageFit;
final bool isSmall;
final double fontSize;
const AudioInputContainer({
Key? key,
this.color = kSecond,
this.label,
this.initialValue,
required this.onChanged,
this.imageFit = BoxFit.cover,
this.isSmall = false,
this.fontSize = 20
}) : super(key: key);
@override
_AudioInputContainerState createState() => _AudioInputContainerState();
}
class _AudioInputContainerState extends State<AudioInputContainer> {
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(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if(widget.label != null) Align(
alignment: AlignmentDirectional.centerStart,
child: AutoSizeText(
widget.label!,
style: TextStyle(fontSize: widget.fontSize, fontWeight: FontWeight.w300),
maxLines: 2,
maxFontSize: widget.fontSize,
textAlign: TextAlign.center,
)
),
Container(
//color: widget.isSmall ? Colors.cyanAccent: Colors.red,
child: Padding(
padding: EdgeInsets.only(left: widget.isSmall ? 5 : 10, top: 10, bottom: 10),
child: Container(
width: size.width *0.125,
height: size.width *0.06,
child: InkWell(
onTap: () async {
ResourceDTO? result = await showSelectResourceModal(
"Sélectionner une ressource",
1,
[ResourceType.Audio],
context,
true, // IS SELECT
false, // IS ADD FALSE only for geopoint for now
true // IS REMOVE BUTTON
);
if (result != null) {
setState(() {
resourceIdToShow = result.id != null ? result.id : null;
});
widget.onChanged(result);
}
},
child: getElement(context),
),
),
),
),
],
),
);
}
getElement(BuildContext context) {
if (resourceIdToShow != null) {
Size size = MediaQuery.of(context).size;
final appContext = Provider.of<AppContext>(context);
return FutureBuilder(
future: getResource(resourceIdToShow!, appContext),
builder: (context, AsyncSnapshot<ResourceDTO?> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data != null) {
return Container(
decoration: boxDecoration(snapshot.data!, appContext),
child: Center(child: AutoSizeText(snapshot.data!.label!, textAlign: TextAlign.center)),
);
} else {
return Text("No data");
}
} else if (snapshot.connectionState == ConnectionState.none) {
return Text("No data");
} else {
return Center(
child: Container(
height: size.height * 0.1,
child: CommonLoader()
)
);
}
}
);
} else {
return Container(
decoration: BoxDecoration(
color: widget.color,
borderRadius: BorderRadius.circular(20),
),
child: Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 15, bottom: 15),
child: Center(
child: AutoSizeText(
"Choisir un fichier audio",
style: TextStyle(color: kWhite),
maxLines: 1,
textAlign: TextAlign.center,
)
),
)
);
}
}
Future<ResourceDTO?> getResource(String resourceIdToShow, dynamic appContext) async {
// Just in resource tab detail not here
ResourceDTO? resource = await (appContext.getContext() as ManagerAppContext).clientAPI!.resourceApi!.resourceGetDetail(resourceIdToShow);
return resource;
}
boxDecoration(ResourceDTO resourceDTO, appContext) {
return BoxDecoration(
shape: BoxShape.rectangle,
color: kWhite,
borderRadius: BorderRadius.circular(20.0),
/*image: new DecorationImage(
fit: widget.imageFit,
image: resourceDTO.type != null ? new NetworkImage(
resourceDTO.type == ResourceType.image ? appContext.getContext().clientAPI.resourceApi.apiClient.basePath+"/api/Resource/"+ resourceDTO.id : resourceDTO.data,
) : null,
),*/
boxShadow: [
BoxShadow(
spreadRadius: 0.5,
blurRadius: 1,
offset: Offset(0, 1.5), // changes position of shadow
),
],
);
}
}

View File

@ -1,245 +0,0 @@
import 'dart:typed_data';
//import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
import 'package:manager_app/app_context.dart';
import 'package:manager_app/constants.dart';
import 'package:provider/provider.dart';
import 'package:just_audio/just_audio.dart';
class AudioPlayerFloatingContainer extends StatefulWidget {
const AudioPlayerFloatingContainer({Key? key, required this.audioBytes, required this.resourceURl, required this.isAuto}) : super(key: key);
final Uint8List? audioBytes;
final String resourceURl;
final bool isAuto;
@override
State<AudioPlayerFloatingContainer> createState() => _AudioPlayerFloatingContainerState();
}
class _AudioPlayerFloatingContainerState extends State<AudioPlayerFloatingContainer> {
AudioPlayer player = AudioPlayer();
late Uint8List audiobytes;
bool isplaying = false;
bool audioplayed = false;
int currentpos = 0;
int maxduration = 100;
Duration? durationAudio;
String currentpostlabel = "00:00";
@override
void initState() {
Future.delayed(Duration.zero, () async {
if(widget.audioBytes != null) {
audiobytes = widget.audioBytes!;
}
player.durationStream.listen((Duration? d) { //get the duration of audio
if(d != null) {
maxduration = d.inSeconds;
durationAudio = d;
}
});
//player.bufferedPositionStream
player.positionStream.listen((event) {
if(durationAudio != null) {
currentpos = event.inMilliseconds; //get the current position of playing audio
//generating the duration label
int shours = Duration(milliseconds:durationAudio!.inMilliseconds - currentpos).inHours;
int sminutes = Duration(milliseconds:durationAudio!.inMilliseconds - currentpos).inMinutes;
int sseconds = Duration(milliseconds:durationAudio!.inMilliseconds - currentpos).inSeconds;
int rminutes = sminutes - (shours * 60);
int rseconds = sseconds - (sminutes * 60 + shours * 60 * 60);
String minutesToShow = rminutes < 10 ? '0$rminutes': rminutes.toString();
String secondsToShow = rseconds < 10 ? '0$rseconds': rseconds.toString();
currentpostlabel = "$minutesToShow:$secondsToShow";
setState(() {
//refresh the UI
if(currentpos > player.duration!.inMilliseconds) {
player.stop();
player.seek(const Duration(seconds: 0));
isplaying = false;
audioplayed = false;
currentpostlabel = "00:00";
}
});
}
});
/*player.onPositionChanged.listen((Duration p){
currentpos = p.inMilliseconds; //get the current position of playing audio
//generating the duration label
int shours = Duration(milliseconds:currentpos).inHours;
int sminutes = Duration(milliseconds:currentpos).inMinutes;
int sseconds = Duration(milliseconds:currentpos).inSeconds;
int rminutes = sminutes - (shours * 60);
int rseconds = sseconds - (sminutes * 60 + shours * 60 * 60);
String minutesToShow = rminutes < 10 ? '0$rminutes': rminutes.toString();
String secondsToShow = rseconds < 10 ? '0$rseconds': rseconds.toString();
currentpostlabel = "$minutesToShow:$secondsToShow";
setState(() {
//refresh the UI
});
});*/
if(widget.isAuto) {
//player.play(BytesSource(audiobytes));
//await player.setAudioSource(LoadedSource(audiobytes));
await player.setUrl(widget.resourceURl);
player.play();
setState(() {
isplaying = true;
audioplayed = true;
});
}
});
super.initState();
}
@override
void dispose() {
player.stop();
player.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final appContext = Provider.of<AppContext>(context);
return FloatingActionButton(
backgroundColor: kPrimaryColor.withOpacity(0.7),
onPressed: () async {
if(!isplaying && !audioplayed){
//player.play(BytesSource(audiobytes));
await player.setAudioSource(LoadedSource(audiobytes));
player.play();
setState(() {
isplaying = true;
audioplayed = true;
});
}else if(audioplayed && !isplaying){
//player.resume();
player.play();
setState(() {
isplaying = true;
audioplayed = true;
});
}else{
player.pause();
setState(() {
isplaying = false;
});
}
},
child: isplaying ? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.pause),
Text(currentpostlabel),
],
) : audioplayed ? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.play_arrow),
Text(currentpostlabel),
],
): const Icon(Icons.play_arrow),
/*Column(
children: [
//Text(currentpostlabel, style: const TextStyle(fontSize: 25)),
Wrap(
spacing: 10,
children: [
ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: kSecondColor, // Background color
),
onPressed: () async {
if(!isplaying && !audioplayed){
//player.play(BytesSource(audiobytes));
await player.setAudioSource(LoadedSource(audiobytes));
player.play();
setState(() {
isplaying = true;
audioplayed = true;
});
}else if(audioplayed && !isplaying){
//player.resume();
player.play();
setState(() {
isplaying = true;
audioplayed = true;
});
}else{
player.pause();
setState(() {
isplaying = false;
});
}
},
icon: Icon(isplaying?Icons.pause:Icons.play_arrow),
//label:Text(isplaying?TranslationHelper.getFromLocale("pause", appContext.getContext()):TranslationHelper.getFromLocale("play", appContext.getContext()))
),
/*ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: kSecondColor, // Background color
),
onPressed: () async {
player.stop();
player.seek(const Duration(seconds: 0));
setState(() {
isplaying = false;
audioplayed = false;
currentpostlabel = "00:00";
});
},
icon: const Icon(Icons.stop),
//label: Text(TranslationHelper.getFromLocale("stop", appContext.getContext()))
),*/
],
)
],
),*/
);
}
}
// Feed your own stream of bytes into the player
class LoadedSource extends StreamAudioSource {
final List<int> bytes;
LoadedSource(this.bytes);
@override
Future<StreamAudioResponse> request([int? start, int? end]) async {
start ??= 0;
end ??= bytes.length;
return StreamAudioResponse(
sourceLength: bytes.length,
contentLength: end - start,
offset: start,
stream: Stream.value(bytes.sublist(start, end)),
contentType: 'audio/mpeg',
);
}
}

View File

@ -1,84 +0,0 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import '../constants.dart';
class CheckInputContainer extends StatefulWidget {
final bool? isChecked;
final IconData? icon;
final String label;
final ValueChanged<bool> onChanged;
final double fontSize;
const CheckInputContainer({
Key? key,
this.isChecked,
this.icon,
required this.label,
required this.onChanged,
this.fontSize = 18
}) : super(key: key);
@override
_CheckInputContainerState createState() => _CheckInputContainerState();
}
class _CheckInputContainerState extends State<CheckInputContainer> {
bool? isChecked;
@override
void initState() {
setState(() {
isChecked = widget.isChecked;
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
child: Row(
children: [
Align(
alignment: AlignmentDirectional.centerStart,
child: Row(
children: [
if(widget.icon != null)
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Icon(
widget.icon,
color: kPrimaryColor,
size: 25.0,
),
),
Text(
widget.label,
style: new TextStyle(fontSize: widget.fontSize, fontWeight: FontWeight.w300)
),
],
)
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
width: 50,
height: 50,
child: Checkbox(
shape: CircleBorder(),
value: isChecked,
checkColor: Colors.white,
activeColor: kPrimaryColor,
onChanged: (bool? value) {
setState(() {
isChecked = value;
});
widget.onChanged(value!);
},
),
),
),
],
),
);
}
}

View File

@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_hsvcolor_picker/flutter_hsvcolor_picker.dart';
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
import 'package:manager_app/Components/rounded_button.dart';
import '../constants.dart';
@ -18,25 +18,19 @@ showColorPicker (Color currentColor, Function onSelect, BuildContext context) {
borderRadius: BorderRadius.all(Radius.circular(20.0))
),
content: SingleChildScrollView(
child: SizedBox(
width: 500,
height: 500,
child: ColorPicker(
color: currentColor,
onChanged: changeColor,
/*pickerColor: currentColor,
onColorChanged: changeColor,
colorPickerWidth: 300.0,
pickerAreaHeightPercent: 0.7,
enableAlpha: true,
displayThumbColor: true,
showLabel: true,
paletteType: PaletteType.hsv,
pickerAreaBorderRadius: const BorderRadius
.only(
topLeft: const Radius.circular(2.0),
topRight: const Radius.circular(2.0),
),*/
child: ColorPicker(
pickerColor: currentColor,
onColorChanged: changeColor,
colorPickerWidth: 300.0,
pickerAreaHeightPercent: 0.7,
enableAlpha: true,
displayThumbColor: true,
showLabel: true,
paletteType: PaletteType.hsv,
pickerAreaBorderRadius: const BorderRadius
.only(
topLeft: const Radius.circular(2.0),
topRight: const Radius.circular(2.0),
),
),
),

View File

@ -1,95 +1,69 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:manager_app/Components/color_picker.dart';
import 'package:manager_app/constants.dart';
class ColorPickerInputContainer extends StatefulWidget {
final String? color;
final String color;
final String label;
final double fontSize;
final ValueChanged<String> onChanged;
const ColorPickerInputContainer({
Key? key,
Key key,
this.color,
required this.label,
this.fontSize = 18,
required this.onChanged,
this.label,
this.onChanged,
}) : super(key: key);
@override
_ColorPickerInputContainerState createState() =>
_ColorPickerInputContainerState();
_ColorPickerInputContainerState createState() => _ColorPickerInputContainerState();
}
class _ColorPickerInputContainerState extends State<ColorPickerInputContainer> {
late Color colorVar;
Color colorVar;
@override
void initState() {
setState(() {
colorVar = widget.color == null ? new Color(0x12345678) : new Color(int.parse(widget.color.split('(0x')[1].split(')')[0], radix: 16));
});
super.initState();
try {
colorVar = widget.color == null || widget.color!.isEmpty
? Colors.grey
: Color(int.parse(
widget.color!.split('(0x')[1].split(')')[0], radix: 16));
} catch (e) {
colorVar = Colors.grey;
}
}
@override
Widget build(BuildContext context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Align(
alignment: AlignmentDirectional.centerStart,
child: Text(
widget.label,
style: const TextStyle(
fontWeight: FontWeight.w400,
fontSize: 16,
),
return Container(
child: Row(
children: [
Align(
alignment: AlignmentDirectional.centerStart,
child: Text(widget.label, style: TextStyle(fontSize: 25, fontWeight: FontWeight.w300))
),
),
const SizedBox(height: 8, width: 10),
Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
/*decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.grey.shade400, width: 1.2),
),*/
child: InkWell(
onTap: () {
showColorPicker(colorVar, (Color color) {
setState(() {
colorVar = color;
});
widget.onChanged(colorToString(color));
}, context);
},
child: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: colorVar,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.black26),
Padding(
padding: const EdgeInsets.all(10.0),
child: InkWell(
onTap: () {
showColorPicker(
colorVar,
(Color color) {
setState(() {
colorVar = color;
});
widget.onChanged(color.toString());
},
context
);
},
child: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: colorVar,
borderRadius: BorderRadius.circular(50),
),
),
),
),
),
],
],
),
);
}
String colorToString(Color color) {
final aHex = color.alpha.toRadixString(16).padLeft(2, '0');
final rHex = color.red.toRadixString(16).padLeft(2, '0');
final gHex = color.green.toRadixString(16).padLeft(2, '0');
final bHex = color.blue.toRadixString(16).padLeft(2, '0');
return 'Color(0x$aHex$rHex$gHex$bHex)';
}
}
}

View File

@ -1,57 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:manager_app/constants.dart';
class CommonLoader extends StatefulWidget {
double? iconSize;
CommonLoader({Key? key, this.iconSize}) : super(key: key);
@override
State<CommonLoader> createState() => _CommonLoaderState();
}
class _CommonLoaderState extends State<CommonLoader> with TickerProviderStateMixin {
AnimationController? _controller;
@override
void initState() {
_controller = AnimationController(
duration: const Duration(milliseconds: 5000),
vsync: this,
)..repeat();
super.initState();
}
@override
void dispose() {
_controller!.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
_controller!.forward(from: 0.0);
_controller!.addListener(() {
if (_controller!.isCompleted) {
_controller!.reverse();
}
if(_controller!.isDismissed){
_controller!.forward();
}
});
return Center(
child: RotationTransition(
turns: Tween(begin: 0.0, end: 3.0).animate(_controller!),
child: SizedBox(
height: 45,
child: SvgPicture.asset('assets/images/MyInfoMate_logo_only.svg')
)/*Icon(Icons.museum_outlined, color: kPrimaryColor, size: widget.iconSize == null ? size.height*0.1 : widget.iconSize!)*/,
),
);
}
}

View File

@ -1,76 +0,0 @@
import 'package:flutter/material.dart';
import 'package:manager_app/constants.dart';
class DropDownInputContainer extends StatefulWidget {
final String label;
final List<String> values;
final String? initialValue;
final ValueChanged<String>? onChange;
final double fontSize;
const DropDownInputContainer({
Key? key,
required this.label,
required this.values,
this.initialValue,
this.onChange,
this.fontSize = 18,
}) : super(key: key);
@override
_DropDownInputContainerState createState() => _DropDownInputContainerState();
}
class _DropDownInputContainerState extends State<DropDownInputContainer> {
late String? selectedValue;
@override
void initState() {
super.initState();
selectedValue = widget.initialValue;
}
@override
Widget build(BuildContext context) {
return Row(
children: [
Align(
alignment: AlignmentDirectional.centerStart,
child: Text(
widget.label,
style: TextStyle(fontSize: widget.fontSize, fontWeight: FontWeight.w300),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: DropdownButton<String>(
value: selectedValue,
icon: const Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: Colors.black),
underline: Container(
height: 2,
color: kPrimaryColor,
),
onChanged: (String? newValue) {
setState(() {
selectedValue = newValue;
widget.onChange!(selectedValue!);
});
},
items: widget.values.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: TextStyle(fontSize: 15),
),
);
}).toList(),
),
),
],
);
}
}

View File

@ -1,83 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
import 'package:manager_api_new/api.dart';
import 'package:manager_app/constants.dart';
class DropDownInputContainerCategories extends StatefulWidget {
final String label;
final List<CategorieDTO> categories;
final int? initialValue;
final ValueChanged<CategorieDTO>? onChange;
const DropDownInputContainerCategories({
Key? key,
required this.label,
required this.categories,
required this.initialValue,
this.onChange,
}) : super(key: key);
@override
_DropDownInputContainerCategoriesState createState() => _DropDownInputContainerCategoriesState();
}
class _DropDownInputContainerCategoriesState extends State<DropDownInputContainerCategories> {
List<CategorieDTO> categoriesToShow = [];
CategorieDTO? selectedCategorieDTO;
@override
void initState() {
if(widget.initialValue != null) {
selectedCategorieDTO = widget.categories.firstWhere((element) => element.id == widget.initialValue);
}
List<TranslationDTO> label = [];
label.add(TranslationDTO(language: "FR", value: "Aucune catégorie"));
categoriesToShow.add(CategorieDTO(order: -1, label: label));
categoriesToShow.addAll(widget.categories);
super.initState();
}
@override
Widget build(BuildContext context) {
/*final appContext = Provider.of<AppContext>(context);
Size size = MediaQuery.of(context).size;*/
return Row(
children: [
Align(
alignment: AlignmentDirectional.centerStart,
child: Text(widget.label, style: TextStyle(fontSize: 25, fontWeight: FontWeight.w300))
),
Padding(
padding: const EdgeInsets.all(8.0),
child: DropdownButton<CategorieDTO>(
value: selectedCategorieDTO,
icon: const Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: const TextStyle(color: kWhite),
underline: Container(
height: 2,
color: kPrimaryColor,
),
onChanged: (CategorieDTO? newValue) {
setState(() {
selectedCategorieDTO = newValue!;
widget.onChange!(selectedCategorieDTO!);
});
},
items: categoriesToShow.map<DropdownMenuItem<CategorieDTO>>((CategorieDTO value) {
return DropdownMenuItem<CategorieDTO>(
value: value,
child: HtmlWidget(
value.label == null ? "" : value.label![0].value!,
textStyle: TextStyle(fontSize: 15, color: Colors.black, fontWeight: FontWeight.w400)
),
);
}).toList(),
),
),
],
);
}
}

View File

@ -1,24 +1,20 @@
import 'package:flutter/material.dart';
import 'package:manager_api_new/api.dart';
import 'package:managerapi/api.dart';
IconData getResourceIcon(elementType) {
switch(elementType) {
case ResourceType.Image:
case ResourceType.image:
return Icons.image;
case ResourceType.ImageUrl:
break;
case ResourceType.imageUrl:
return Icons.image_search; // art_track
case ResourceType.Audio:
return Icons.audiotrack; // art_track
case ResourceType.Video:
break;
case ResourceType.video:
return Icons.slow_motion_video;
case ResourceType.VideoUrl:
break;
case ResourceType.videoUrl:
return Icons.ondemand_video_sharp;
case ResourceType.Pdf:
return Icons.picture_as_pdf_outlined;
case ResourceType.Json:
return Icons.file_present_outlined;
case ResourceType.JsonUrl:
return Icons.file_present_rounded;
break;
}
return Icons.announcement;
}

View File

@ -1,32 +1,26 @@
import 'package:flutter/material.dart';
import 'package:manager_api_new/api.dart';
import 'package:managerapi/api.dart';
IconData getSectionIcon(elementType) {
switch(elementType) {
case SectionType.Map:
case SectionType.map:
return Icons.location_on;
case SectionType.Slider:
break;
case SectionType.slider:
return Icons.collections; // art_track
case SectionType.Video:
break;
case SectionType.video:
return Icons.ondemand_video_rounded;
case SectionType.Web:
break;
case SectionType.web:
return Icons.web;
case SectionType.Menu:
break;
case SectionType.menu:
return Icons.apps_sharp;
case SectionType.Quiz:
break;
case SectionType.quizz:
return Icons.question_answer;
case SectionType.Article:
return Icons.article_outlined;
case SectionType.Pdf:
return Icons.picture_as_pdf_outlined;
case SectionType.Game:
return Icons.sports_esports;
case SectionType.Agenda:
return Icons.calendar_month_outlined;
case SectionType.Weather:
return Icons.sunny;
case SectionType.Event:
return Icons.event;
break;
}
return Icons.question_mark;
return Icons.menu;
}

View File

@ -1,35 +0,0 @@
import 'package:flutter/material.dart';
import 'package:manager_app/constants.dart';
class FlagDecoration extends StatelessWidget {
final String language;
FlagDecoration({Key? key, required this.language}) : super(key: key);
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Container(
width: 35,
height: 35,
decoration: BoxDecoration(
color: kBackgroundColor,
shape: BoxShape.circle,
//border: Border.all(width: 1.5, color: kSecondGrey),
image: DecorationImage(
fit: BoxFit.contain,
image: AssetImage("assets/images/"+language.toLowerCase()+".png")/*Svg(
"assets/images/"+language.toLowerCase()+".svg",
)*/, //AssetImage("assets/images/"+language+".png"),
),
boxShadow: const [
BoxShadow(
color: kBackgroundColor,
spreadRadius: 0.5,
blurRadius: 5,
offset: Offset(0, 1.5), // changes position of shadow
),
],
),
);
}
}

View File

@ -1,178 +0,0 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:location_picker_flutter_map/location_picker_flutter_map.dart';
import 'package:manager_app/Components/common_loader.dart';
import 'package:manager_app/Components/message_notification.dart';
import 'package:manager_app/Components/rounded_button.dart';
import 'package:manager_app/Components/rounded_input_field.dart';
import 'package:manager_app/constants.dart';
class GeolocInputContainer extends StatefulWidget {
final Color color;
final String label;
final LatLong? initialValue;
final ValueChanged<LatLong> onChanged;
final bool isSmall;
final double fontSize;
final double fontSizeText;
const GeolocInputContainer({
Key? key,
this.color = kSecond,
required this.label,
required this.initialValue,
required this.onChanged,
this.isSmall = false,
this.fontSize = 18,
this.fontSizeText = 20,
}) : super(key: key);
@override
State<GeolocInputContainer> createState() => _GeolocInputContainerState();
}
class _GeolocInputContainerState extends State<GeolocInputContainer> {
LatLong? localisation;
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
localisation = widget.initialValue;
return Container(
child: Row(
children: [
Align(
alignment: AlignmentDirectional.centerStart,
child: Text(
widget.label,
style: TextStyle(fontSize: widget.fontSize, fontWeight: FontWeight.w300),
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
width: size.width *0.15,
child: InkWell(
onTap: () {
showDialog(
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))
),
title: Center(child: Text(widget.label)),
content: SingleChildScrollView(
child: Container(
width: size.width *0.75,
height: 350,
child: FlutterLocationPicker(
initZoom: 14,
initPosition: localisation == null ? LatLong(50.429333, 4.891434) : LatLong(localisation!.latitude, localisation!.longitude),
minZoomLevel: 0,
maxZoomLevel: 17,
markerIcon: const Icon(
Icons.location_pin,
color: kPrimaryColor,
size: 50,
),
loadingWidget: CommonLoader(iconSize: 40.0),
searchBarHintColor: kPrimaryColor,
mapLoadingBackgroundColor: kSecond,
zoomButtonsBackgroundColor: kPrimaryColor,
zoomButtonsColor: Colors.white,
locationButtonBackgroundColor: kPrimaryColor,
locationButtonsColor: Colors.white,
countryFilter: "be, fr",
trackMyPosition: false,
searchBarHintText: "Chercher une localisation",
searchBarTextColor: Colors.black,
searchBarBackgroundColor: Colors.white,
showSelectLocationButton : true,
selectLocationButtonText: "Choisir cette localisation",
selectedLocationButtonTextstyle: const TextStyle(fontSize: 18, color: kPrimaryColor),
mapLanguage: 'fr',
onError: (e) => print(e),
selectLocationButtonLeadingIcon: const Icon(Icons.check, color: kPrimaryColor),
onPicked: (pickedData) {
print("onPicked");
localisation = pickedData.latLong;
print(localisation);
},
onChanged: (pickedData) {
print("onChanged");
print(pickedData.latLong.latitude);
print(pickedData.latLong.longitude);
print(pickedData.address);
print(pickedData.addressData);
},
showContributorBadgeForOSM: false,
),
),
),
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: "Valider",
icon: Icons.check,
color: kPrimaryColor,
textColor: kWhite,
press: () {
if(localisation != null) {
widget.onChanged(localisation!);
Navigator.of(context).pop();
} else {
showNotification(kPrimaryColor, kWhite, "Aucune localisation choisie", context, null);
}
},
fontSize: 20,
),
),
],
),
],
);
}, context: context
);
},
child: 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(
"Changer la localisation",
style: TextStyle(color: kWhite),
maxLines: 2,
)
),
)
),
),
),
),
],
),
);
}
}

View File

@ -1,144 +0,0 @@
import 'package:flutter/material.dart';
import 'package:manager_api_new/api.dart';
import 'package:manager_app/Components/map_geometry_picker.dart';
import 'package:manager_app/constants.dart';
class GeometryInputContainer extends StatelessWidget {
final String label;
final GeometryDTO? initialGeometry;
final String? initialColor;
final Function(GeometryDTO, String) onSave;
final Color color;
final bool isSmall;
GeometryInputContainer({
required this.label,
this.initialGeometry,
this.initialColor,
required this.onSave,
this.color = kPrimaryColor,
this.isSmall = false,
});
@override
Widget build(BuildContext context) {
String typeInfo = initialGeometry?.type ?? "Aucun";
int pointCount = 0;
if (initialGeometry?.coordinates != null) {
if (initialGeometry!.type == "Point") {
pointCount = 1;
} else if (initialGeometry!.coordinates is List) {
pointCount = (initialGeometry!.coordinates as List).length;
}
}
Size size = MediaQuery.of(context).size;
return Container(
margin: EdgeInsets.symmetric(vertical: 4),
child: Row(
children: [
Container(
width: 150,
child: Text(
label,
style: const TextStyle(
fontWeight: FontWeight.w400,
fontSize: 16,
),
),
),
Container(
width: isSmall ? size.width * 0.15 : size.width * 0.25,
child: InkWell(
onTap: () {
showDialog(
context: context,
builder: (context) => MapGeometryPicker(
initialGeometry: initialGeometry,
initialColor: initialColor,
onSave: onSave,
),
);
},
child: Container(
padding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(29),
border: Border.all(color: kSecond),
),
child: Row(
children: [
Icon(
_getIconForType(initialGeometry?.type),
color: color,
size: 20,
),
SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
initialGeometry != null
? "$typeInfo ($pointCount pts)"
: "Définir",
style: TextStyle(
fontSize: 13,
color: initialGeometry != null ? kBlack : kSecond,
overflow: TextOverflow.ellipsis,
),
),
if (initialColor != null)
Row(
children: [
Container(
width: 8,
height: 8,
decoration: BoxDecoration(
color: _parseColor(initialColor!),
shape: BoxShape.circle,
),
),
SizedBox(width: 4),
Text(initialColor!,
style: TextStyle(
fontSize: 9, color: Colors.grey)),
],
),
],
),
),
Icon(Icons.edit, color: kSecond, size: 16),
],
),
),
),
),
],
),
);
}
IconData _getIconForType(String? type) {
switch (type) {
case "Point":
return Icons.location_on;
case "LineString":
return Icons.show_chart;
case "Polygon":
return Icons.pentagon;
default:
return Icons.map;
}
}
Color _parseColor(String hex) {
try {
return Color(int.parse(hex.replaceFirst('#', '0xFF')));
} catch (e) {
return kPrimaryColor;
}
}
}

View File

@ -0,0 +1,158 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:manager_app/Components/loading.dart';
import 'package:manager_app/app_context.dart';
import 'package:manager_app/constants.dart';
import 'package:manager_app/Screens/Resources/select_resource_modal.dart';
import 'package:managerapi/api.dart';
import 'package:provider/provider.dart';
class ImageInputContainer extends StatefulWidget {
final Color color;
final String label;
final String initialValue;
final ValueChanged<ResourceDTO> onChanged;
final BoxFit imageFit;
final bool isSmall;
const ImageInputContainer({
Key key,
this.color = kSecond,
this.label,
this.initialValue,
this.onChanged,
this.imageFit = BoxFit.cover,
this.isSmall = false,
}) : 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: EdgeInsets.only(left: widget.isSmall ? 15 : 70, top: 10, bottom: 10),
child: Container(
width: size.width *0.08,
child: InkWell(
onTap: () async {
var result = await showSelectResourceModal(
"Sélectionner une ressource",
1,
true,
context
);
if (result != null) {
setState(() {
resourceIdToShow = result.id;
});
widget.onChanged(result);
}
},
child: getElement(widget.initialValue, context, widget.isSmall),
),
),
),
],
),
);
}
getElement(String initialValue, BuildContext context, bool isSmall) {
if (resourceIdToShow != null) {
Size size = MediaQuery.of(context).size;
final appContext = Provider.of<AppContext>(context);
return FutureBuilder(
future: getResource(resourceIdToShow, appContext),
builder: (context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data != null) {
return Transform.scale(
scale: isSmall ? size.aspectRatio * 0.5: size.aspectRatio * 0.9,
child: AspectRatio(
aspectRatio: 4/4,
child: Container(
decoration: boxDecoration(snapshot.data, appContext),
),
),
);
} else {
return Text("No data");
}
} else if (snapshot.connectionState == ConnectionState.none) {
return Text("No data");
} else {
return Center(
child: Container(
height: size.height * 0.1,
child: Loading()
)
);
}
}
);
} 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: 1,
)
),
)
);
}
}
Future<ResourceDTO> getResource(String resourceIdToShow, dynamic appContext) async {
ResourceDTO resource = await appContext.getContext().clientAPI.resourceApi.resourceGetDetail(resourceIdToShow);
return resource;
}
boxDecoration(ResourceDTO resourceDTO, appContext) {
return BoxDecoration(
shape: BoxShape.rectangle,
color: kWhite,
borderRadius: BorderRadius.circular(30.0),
image: new DecorationImage(
fit: widget.imageFit,
image: resourceDTO.type != null ? new NetworkImage(
resourceDTO.type == ResourceType.image ? appContext.getContext().clientAPI.resourceApi.apiClient.basePath+"/api/Resource/"+ resourceDTO.id : resourceDTO.data,
) : null,
),
boxShadow: [
BoxShadow(
spreadRadius: 0.5,
blurRadius: 1,
offset: Offset(0, 1.5), // changes position of shadow
),
],
);
}
}

View File

@ -2,7 +2,7 @@ import 'package:flare_flutter/flare_actor.dart';
import 'package:flutter/material.dart';
class Loading extends StatelessWidget {
Loading({Key? key}) : super(key: key);
Loading({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {

View File

@ -1,379 +0,0 @@
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import 'package:manager_api_new/api.dart';
import 'package:manager_app/constants.dart';
import 'package:manager_app/Components/rounded_button.dart';
import 'package:manager_app/Components/color_picker.dart';
class MapGeometryPicker extends StatefulWidget {
final GeometryDTO? initialGeometry;
final String? initialColor;
final Function(GeometryDTO, String) onSave;
MapGeometryPicker({
this.initialGeometry,
this.initialColor,
required this.onSave,
});
@override
_MapGeometryPickerState createState() => _MapGeometryPickerState();
}
class _MapGeometryPickerState extends State<MapGeometryPicker> {
List<LatLng> points = [];
String currentType = "Point";
Color selectedColor = kPrimaryColor;
final MapController _mapController = MapController();
@override
void initState() {
super.initState();
if (widget.initialGeometry != null) {
currentType = widget.initialGeometry!.type ?? "Point";
_parseInitialGeometry();
}
if (widget.initialColor != null) {
try {
selectedColor = _hexToColor(widget.initialColor!);
} catch (e) {
selectedColor = kPrimaryColor;
}
}
}
Color _hexToColor(String hex) {
hex = hex.replaceFirst('#', '');
if (hex.length == 6) hex = 'FF' + hex;
return Color(int.parse(hex, radix: 16));
}
void _parseInitialGeometry() {
if (widget.initialGeometry?.coordinates == null) return;
try {
if (currentType == "Point") {
var coords = widget.initialGeometry!.coordinates as List<dynamic>;
points = [LatLng(coords[0].toDouble(), coords[1].toDouble())];
} else if (currentType == "LineString") {
var list = widget.initialGeometry!.coordinates as List<dynamic>;
points = list.map((e) {
var pair = e as List<dynamic>;
return LatLng(pair[0].toDouble(), pair[1].toDouble());
}).toList();
} else if (currentType == "Polygon") {
// Polygon coordinates: [[[lat,lng],...]] first element is exterior ring
var rings = widget.initialGeometry!.coordinates as List<dynamic>;
var ring = rings[0] as List<dynamic>;
points = ring.map((e) {
var pair = e as List<dynamic>;
return LatLng(pair[0].toDouble(), pair[1].toDouble());
}).toList();
// Remove closing point if it duplicates the first
if (points.length > 1 && points.first == points.last) {
points.removeLast();
}
}
} catch (e) {
print("Error parsing geometry: $e");
}
}
void _handleTap(TapPosition tapPosition, LatLng latLng) {
setState(() {
if (currentType == "Point") {
points = [latLng];
} else {
points.add(latLng);
}
});
}
GeometryDTO _buildGeometry() {
if (currentType == "Point") {
return GeometryDTO(
type: "Point",
coordinates: points.isNotEmpty
? [points[0].latitude, points[0].longitude]
: null,
);
} else if (currentType == "Polygon") {
// Polygon: [[[lat,lng],...]] wrap ring in outer array
return GeometryDTO(
type: "Polygon",
coordinates: [points.map((e) => [e.latitude, e.longitude]).toList()],
);
} else {
return GeometryDTO(
type: currentType,
coordinates: points.map((e) => [e.latitude, e.longitude]).toList(),
);
}
}
String _colorToHex(Color color) {
return '#${color.value.toRadixString(16).padLeft(8, '0').substring(2)}';
}
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Dialog(
insetPadding: EdgeInsets.all(20),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
child: Container(
width: size.width * 0.9,
height: size.height * 0.9,
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Column(
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
color: kPrimaryColor,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("Éditeur de Géométrie",
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold)),
Row(
children: [
IconButton(
icon: Icon(Icons.palette, color: Colors.white),
onPressed: () {
showColorPicker(selectedColor, (Color color) {
setState(() => selectedColor = color);
}, context);
},
),
IconButton(
icon: Icon(Icons.delete, color: Colors.white),
onPressed: () => setState(() => points.clear()),
),
IconButton(
icon: Icon(Icons.close, color: Colors.white),
onPressed: () => Navigator.pop(context),
),
],
),
],
),
),
Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
children: [
Wrap(
spacing: 12,
alignment: WrapAlignment.center,
children: [
_buildTypeButton("Point", Icons.location_on),
_buildTypeButton("LineString", Icons.show_chart),
_buildTypeButton("Polygon", Icons.pentagon),
],
),
SizedBox(height: 8),
Text(
_getInstructions(),
style: TextStyle(
fontStyle: FontStyle.italic, color: Colors.grey[600]),
textAlign: TextAlign.center,
),
],
),
),
Expanded(
child: Stack(
children: [
FlutterMap(
key: _mapKey,
mapController: _mapController,
options: MapOptions(
initialCenter: points.isNotEmpty
? points[0]
: LatLng(50.429333, 4.891434),
initialZoom: 14,
onTap: _handleTap,
),
children: [
TileLayer(
urlTemplate:
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
),
if (currentType == "Polygon" && points.length >= 3)
PolygonLayer(
polygons: [
Polygon(
points: points,
color: selectedColor.withOpacity(0.3),
borderStrokeWidth: 2,
borderColor: selectedColor,
isFilled: true,
),
],
),
if (currentType == "LineString" && points.length >= 2)
PolylineLayer(
polylines: [
Polyline(
points: points,
color: selectedColor,
strokeWidth: 4,
),
],
),
MarkerLayer(
markers: points.asMap().entries.map((entry) {
int idx = entry.key;
LatLng p = entry.value;
return Marker(
point: p,
width: 30,
height: 30,
child: GestureDetector(
onPanUpdate: (details) {
_handleDrag(idx, details);
},
child: Container(
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
border: Border.all(
color: selectedColor, width: 2),
boxShadow: [
BoxShadow(
blurRadius: 4,
color: Colors.black26,
offset: Offset(0, 2))
],
),
child: Center(
child: Icon(Icons.circle,
color: selectedColor, size: 14),
),
),
),
);
}).toList(),
),
],
),
],
),
),
Container(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 4,
offset: Offset(0, -2))
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
height: 45,
child: RoundedButton(
text: "Annuler",
color: Colors.grey[200]!,
textColor: Colors.black87,
press: () => Navigator.pop(context),
fontSize: 16,
horizontal: 24,
),
),
SizedBox(width: 12),
Container(
height: 45,
child: RoundedButton(
text: "Sauvegarder",
color: kPrimaryColor,
press: () {
widget.onSave(
_buildGeometry(), _colorToHex(selectedColor));
Navigator.pop(context);
},
fontSize: 16,
horizontal: 32,
),
),
],
),
)
],
),
),
),
);
}
String _getInstructions() {
switch (currentType) {
case "Point":
return "Touchez la carte pour placer le point. Faites glisser le point pour le déplacer.";
case "LineString":
return "Touchez la carte pour ajouter des points à la ligne. Faites glisser un point pour le déplacer.";
case "Polygon":
return "Touchez la carte pour définir les sommets du polygone. Faites glisser un sommet pour le déplacer.";
default:
return "";
}
}
final GlobalKey _mapKey = GlobalKey();
void _handleDrag(int index, DragUpdateDetails details) {
if (index < 0 || index >= points.length) return;
final RenderBox? mapBox =
_mapKey.currentContext?.findRenderObject() as RenderBox?;
if (mapBox != null) {
final Offset localOffset = mapBox.globalToLocal(details.globalPosition);
try {
LatLng newLatLng = _mapController.camera
.pointToLatLng(math.Point(localOffset.dx, localOffset.dy));
setState(() {
points[index] = newLatLng;
});
} catch (e) {
print("Error dragging point: $e");
}
}
}
Widget _buildTypeButton(String type, IconData icon) {
bool isSelected = currentType == type;
return ChoiceChip(
label: Text(type == "LineString"
? "Ligne"
: type == "Polygon"
? "Polygone"
: "Point"),
avatar: Icon(icon,
size: 18, color: isSelected ? Colors.white : kPrimaryColor),
selected: isSelected,
onSelected: (val) {
if (val) {
setState(() {
currentType = type;
if (currentType == "Point" && points.length > 1) {
points = [points[0]];
}
});
}
},
selectedColor: kPrimaryColor,
labelStyle: TextStyle(color: isSelected ? Colors.white : kPrimaryColor),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
);
}
}

View File

@ -1,21 +1,10 @@
//import 'package:another_flushbar/flushbar.dart';
import 'package:flutter/material.dart';
showNotification (Color backgroundColor, Color textColor, String text, BuildContext context, int? duration) async {
/*await Flushbar(
message: text,
messageColor: textColor,
margin: EdgeInsets.all(8),
backgroundColor: backgroundColor,
borderRadius: BorderRadius.circular(8),
duration: duration == null ? Duration(milliseconds: 1500) : Duration(milliseconds: duration),
).show(context);*/
showNotification (Color backgroundColor, Color textColor, String text, BuildContext context, int duration) {
final snackBar = SnackBar(
behavior: SnackBarBehavior.floating,
duration: duration == null ? Duration(milliseconds: 1500) : Duration(milliseconds: duration),
width: 450.0, // Width of the SnackBar.
width: 280.0, // Width of the SnackBar.
backgroundColor: backgroundColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
@ -24,7 +13,7 @@ showNotification (Color backgroundColor, Color textColor, String text, BuildCont
horizontal: 10.0, // Inner padding for SnackBar content.
),
content: Container(
height: 50.5,
height: 32.5,
child: Center(
child: Text(
text,

View File

@ -1,19 +1,15 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:manager_app/Components/resource_input_container.dart';
import 'package:manager_app/Components/rounded_button.dart';
import 'package:manager_app/Components/text_form_input_container.dart';
import 'package:manager_app/Models/managerContext.dart';
import 'package:manager_app/app_context.dart';
import 'package:manager_app/constants.dart';
import 'package:manager_api_new/api.dart';
import 'package:managerapi/api.dart';
import 'package:collection/collection.dart';
import 'package:provider/provider.dart';
import 'audio_input_container.dart';
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, List<TranslationDTO> values, List<TranslationDTO> newValues, Function onGetResult, int maxLines, BuildContext context) { /*Function onSelect,*/
showDialog(
builder: (BuildContext context) => AlertDialog(
shape: RoundedRectangleBorder(
@ -27,7 +23,7 @@ showMultiStringInput (String label, String modalLabel, bool isTitle, List<Transl
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: getTranslations(context, Provider.of<AppContext>(context), label, isTitle, resourceTypes, newValues),
children: getTranslations(context, Provider.of<AppContext>(context), label, newValues),
),
),
),
@ -49,42 +45,36 @@ showMultiStringInput (String label, String modalLabel, bool isTitle, List<Transl
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 180,
height: 70,
child: RoundedButton(
text: "Annuler",
icon: Icons.undo,
color: kSecond,
press: () {
onGetResult(values);
Navigator.of(context).pop();
},
fontSize: 20,
),
Container(
width: 180,
height: 70,
child: RoundedButton(
text: "Annuler",
icon: Icons.undo,
color: kSecond,
press: () {
onGetResult(values);
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,
),
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,
),
),
],
@ -94,18 +84,17 @@ showMultiStringInput (String label, String modalLabel, bool isTitle, List<Transl
);
}
getTranslations(BuildContext context, AppContext appContext, String label, bool isTitle, List<ResourceType>? resourceTypes, List<TranslationDTO> newValues) {
getTranslations(BuildContext context, AppContext appContext, String label, List<TranslationDTO> newValues) {
List<Widget> translations = <Widget>[];
ManagerAppContext managerAppContext = appContext.getContext();
for(var language in managerAppContext.selectedConfiguration!.languages!) {
for(var language in managerAppContext.selectedConfiguration.languages) {
translations.add(
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
FlagDecoration(language: language),
/*Container(
Container(
width: MediaQuery.of(context).size.width *0.05,
height: MediaQuery.of(context).size.height *0.10,
decoration: BoxDecoration(
@ -114,7 +103,7 @@ getTranslations(BuildContext context, AppContext appContext, String label, bool
),
),
child: Center(child: AutoSizeText(language.toUpperCase()))
),*/
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Container(
@ -122,37 +111,14 @@ getTranslations(BuildContext context, AppContext appContext, String label, bool
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
resourceTypes == null ?
TextFormInputContainer(
label: label,
color: kWhite,
isTitle: isTitle,
initialValue: newValues.where((element) => element.language == language).first.value!,
isTitle: true,
initialValue: newValues.where((element) => element.language == language).first.value,
onChanged: (value) {
newValues.where((element) => element.language == language).first.value = value;
},
) :
Container(
width: MediaQuery.of(context).size.width *0.15,
height: 100,
//color: Colors.blueAccent,
child: Center(
child: ResourceInputContainer(
label: "",
initialValue: newValues.where((element) => element.language == language).first.value == null ? null : newValues.where((element) => element.language == language).first.value!,
inResourceTypes: resourceTypes,
onChanged: (ResourceDTO resource) {
newValues.where((element) => element.language == language).first.value = resource.id;
},
)/*AudioInputContainer(
//label: "Audio :",
initialValue: newValues.where((element) => element.language == language).first.value,
color: kPrimaryColor,
onChanged: (ResourceDTO resource) {
newValues.where((element) => element.language == language).first.value = resource.id;
},
),*/
),
),
],
),
@ -165,7 +131,6 @@ getTranslations(BuildContext context, AppContext appContext, String label, bool
}
return translations;
}
/*
showValues(List<TranslationDTO> newValues) {
List<Widget> valuesToShow = new List<Widget>();
@ -182,3 +147,5 @@ showValues(List<TranslationDTO> newValues) {
});
return valuesToShow;
}*/

View File

@ -1,59 +1,46 @@
import 'package:flutter/material.dart';
import 'package:manager_app/constants.dart';
import 'package:html/parser.dart' show parse;
import 'message_notification.dart';
class MultiSelectContainer extends StatelessWidget {
final Color color;
final String? label;
final String label;
final List<String> values;
final List<String> initialValue;
final bool isMultiple;
final bool isAtLeastOne;
final bool isHTMLLabel;
final double? width;
final int maxLines;
final ValueChanged<List<dynamic>> onChanged;
const MultiSelectContainer({
Key? key,
Key key,
this.color = kSecond,
required this.label,
required this.values,
required this.initialValue,
required this.isMultiple,
this.label,
this.values,
this.initialValue,
this.isMultiple,
this.isAtLeastOne = false,
this.isHTMLLabel = false,
this.width,
this.maxLines = 2,
required this.onChanged,
this.onChanged,
}) : super(key: key);
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
return Container(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if(label != null)
Align(
alignment: AlignmentDirectional.centerStart,
child: Text(label!, style: TextStyle(fontSize: 25, fontWeight: FontWeight.w300))
),
Align(
alignment: AlignmentDirectional.centerStart,
child: Text(label, style: TextStyle(fontSize: 25, fontWeight: FontWeight.w300))
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
width: width ?? size.width *0.25,
//color: Colors.yellow,
width: size.width *0.2,
child: MultiSelectChip(
values,
initialValue,
isMultiple,
isAtLeastOne,
isHTMLLabel,
maxLines,
onSelectionChanged: (selectedList) {
onChanged(selectedList);
},
@ -72,36 +59,30 @@ class MultiSelectChip extends StatefulWidget {
final Function(List<String>) onSelectionChanged; // +added
final bool isMultiple;
final bool isAtLeastOne;
final bool isHTMLLabel;
final int maxLines;
MultiSelectChip(
this.values,
this.selectedValues,
this.isMultiple,
this.isAtLeastOne,
this.isHTMLLabel,
this.maxLines,
{required this.onSelectionChanged} // +added
{this.onSelectionChanged} // +added
);
@override
_MultiSelectChipState createState() => _MultiSelectChipState();
}
class _MultiSelectChipState extends State<MultiSelectChip> {
int maxLines = 1; // Définir le nombre maximum de lignes
_buildChoiceList() {
List<Widget> choices = [];
List<Widget> choices = List();
widget.values.forEach((item) {
choices.add(Container(
padding: const EdgeInsets.all(2.0),
child: ChoiceChip(
label: Text(widget.isHTMLLabel ? parse(item).documentElement!.text : item, style: TextStyle(color: kBlack)),
label: Text(item, style: TextStyle(color: kBlack)),
selected: widget.selectedValues.contains(item),
selectedColor: kPrimaryColor,
onSelected: (selected) {
setState(() {
if (widget.isAtLeastOne && widget.selectedValues.length == 1 && widget.selectedValues[0] == item) {
showNotification(Colors.orange, kWhite, 'Au moins une valeur doit être sélectionnée', context, null);
showNotification(Colors.orange, kWhite, 'Au moins une valeur doit être sélectionnée', context, null);
} else {
if (widget.isMultiple) {
widget.selectedValues.contains(item)
@ -121,17 +102,10 @@ class _MultiSelectChipState extends State<MultiSelectChip> {
});
return choices;
}
@override
Widget build(BuildContext context) {
return Container(
height: maxLines * 48.0, // Assuming each ChoiceChip is 48.0 height
child: ListView(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
children: _buildChoiceList(),
),
return Wrap(
children: _buildChoiceList(),
);
}
}
}

View File

@ -1,109 +0,0 @@
import 'package:flutter/material.dart';
import 'package:multi_select_flutter/multi_select_flutter.dart';
import 'package:manager_app/constants.dart';
class MultiSelectDropdownLanguageContainer extends StatefulWidget {
final Color color;
final String label;
final String labelHint;
final List<String> values;
final List<String> initialValue;
final bool isMultiple;
final bool isAtLeastOne;
final double fontSize;
final ValueChanged<List<String>> onChanged;
const MultiSelectDropdownLanguageContainer({
Key? key,
this.color = kSecond,
required this.label,
this.labelHint = "Veuillez sélectionner une langue",
required this.values,
required this.initialValue,
required this.isMultiple,
this.isAtLeastOne = false,
this.fontSize = 18,
required this.onChanged,
}) : super(key: key);
@override
State<MultiSelectDropdownLanguageContainer> createState() =>
_MultiSelectDropdownLanguageContainerState();
}
class _MultiSelectDropdownLanguageContainerState
extends State<MultiSelectDropdownLanguageContainer> {
late List<String> _selectedValues;
@override
void initState() {
super.initState();
_selectedValues = List.from(widget.initialValue);
}
String _buildSummary(List<String> selected) {
if (selected.isEmpty) return widget.labelHint;
if (selected.length <= 5) return selected.join(", ");
return "${selected.length} sélectionnés";
}
@override
Widget build(BuildContext context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Align(
alignment: AlignmentDirectional.centerStart,
child: Text(
widget.label,
style: const TextStyle(
fontWeight: FontWeight.w400,
fontSize: 16,
),
),
),
const SizedBox(height: 8, width: 10),
Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 35),
/*decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.grey.shade400, width: 1.2),
color: Colors.white,
),*/
child: MultiSelectDialogField<String>(
items: widget.values.map((e) => MultiSelectItem(e, e)).toList(),
initialValue: _selectedValues,
listType: MultiSelectListType.LIST,
searchable: true,
searchIcon: Icon(Icons.search, color: kPrimaryColor),
selectedColor: kPrimaryColor,
checkColor: Colors.white,
buttonIcon: Icon(Icons.arrow_drop_down, color: kPrimaryColor),
buttonText: Text(
_buildSummary(_selectedValues),
style: TextStyle(color: Colors.black87, fontSize: 14),
),
chipDisplay: MultiSelectChipDisplay.none(),
dialogHeight: MediaQuery.of(context).size.height * 0.4,
dialogWidth: MediaQuery.of(context).size.width * 0.6,
onConfirm: (selected) {
if (widget.isAtLeastOne && selected.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text("Au moins une valeur doit être sélectionnée"),
),
);
} else {
setState(() {
_selectedValues = selected.cast<String>();
});
widget.onChanged(_selectedValues);
}
},
),
),
],
);
}
}

View File

@ -1,97 +0,0 @@
import 'dart:convert';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:manager_app/Components/multi_string_input_html_modal.dart';
import 'package:manager_app/Models/managerContext.dart';
import 'package:manager_app/app_context.dart';
import 'package:manager_app/constants.dart';
import 'package:manager_api_new/api.dart';
import 'package:provider/provider.dart';
class MultiStringInputAndResourceContainer extends StatelessWidget {
final Color color;
final String label;
final String modalLabel;
final List<TranslationAndResourceDTO> initialValue;
final Function onGetResult;
final int maxLines;
final bool isTitle;
final List<ResourceType>? resourceTypes;
final double fontSize;
const MultiStringInputAndResourceContainer({
Key? key,
this.color = kSecond,
required this.label,
required this.modalLabel,
required this.initialValue,
required this.onGetResult,
required this.maxLines,
required this.isTitle,
this.resourceTypes = null,
this.fontSize = 25,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final appContext = Provider.of<AppContext>(context);
ManagerAppContext managerAppContext = appContext.getContext();
Size size = MediaQuery.of(context).size;
return Container(
child: Row(
children: [
Align(
alignment: AlignmentDirectional.centerStart,
child: AutoSizeText(
label,
style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.w300),
maxLines: 2,
maxFontSize: fontSize,
textAlign: TextAlign.center,
)
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
width: size.width *0.15,
child: InkWell(
onTap: () {
List<TranslationAndResourceDTO> newValues = <TranslationAndResourceDTO>[];
List<TranslationAndResourceDTO> initials = initialValue;
managerAppContext.selectedConfiguration!.languages!.forEach((value) {
if(initials.map((iv) => iv.language).contains(value)) {
newValues.add(TranslationAndResourceDTO.fromJson(jsonDecode(jsonEncode(initials.firstWhere((element) => element.language == value)))!)!);
} else {
// New language
newValues.add(TranslationAndResourceDTO(language: value, value: "", resource: null));
}
});
showMultiStringInputAndResourceHTML(label, modalLabel, isTitle, initials, newValues, onGetResult, maxLines, resourceTypes, context);
},
child: Container(
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(50),
),
child: Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 15, bottom: 15),
child: Center(
child: AutoSizeText(
resourceTypes == null ? "Changer traductions" : "Changer ressources",
style: TextStyle(color: kWhite),
maxLines: 2,
)
),
)
),
),
),
),
],
),
);
}
}

View File

@ -1,131 +1,73 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:manager_api_new/api.dart';
import 'package:manager_app/Components/multi_input_modal.dart';
import 'package:manager_app/Components/multi_string_input_html_modal.dart';
import 'package:manager_app/Models/managerContext.dart';
import 'package:manager_app/app_context.dart';
import 'package:manager_app/constants.dart';
import 'package:provider/provider.dart';
import 'package:auto_size_text/auto_size_text.dart';
class MultiStringInputContainer extends StatelessWidget {
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/constants.dart';
import 'package:managerapi/api.dart';
class MultiStringContainer extends StatelessWidget {
final Color color;
final String label;
final String modalLabel;
final List<TranslationDTO> initialValue;
final Function(List<TranslationDTO>) onGetResult;
final Function onGetResult;
final int maxLines;
final bool isTitle;
final List<ResourceType>? resourceTypes;
final bool isHTML;
final double fontSize;
final bool isMandatory;
const MultiStringInputContainer({
Key? key,
const MultiStringContainer({
Key key,
this.color = kSecond,
required this.label,
required this.modalLabel,
required this.initialValue,
required this.onGetResult,
required this.maxLines,
required this.isTitle,
this.resourceTypes,
this.isHTML = false,
this.fontSize = 18,
this.isMandatory = true,
this.label,
this.modalLabel,
this.initialValue,
this.onGetResult,
this.maxLines,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final appContext = Provider.of<AppContext>(context);
final managerAppContext = appContext.getContext();
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Align(
alignment: AlignmentDirectional.centerStart,
child: Text(
label,
style: TextStyle(
fontWeight: FontWeight.w400,
fontSize: fontSize,
),
Size size = MediaQuery.of(context).size;
return Container(
child: Row(
children: [
Align(
alignment: AlignmentDirectional.centerStart,
child: Text(label, style: TextStyle(fontSize: 25, fontWeight: FontWeight.w300))
),
),
const SizedBox(height: 8, width: 10),
Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
/*decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.grey.shade400, width: 1.2),
),*/
child: InkWell(
onTap: () {
List<TranslationDTO> newValues = [];
List<TranslationDTO> initials = initialValue;
// Préparer les valeurs pour toutes les langues
managerAppContext.selectedConfiguration!.languages!.forEach((lang) {
if (initials.any((iv) => iv.language == lang)) {
newValues.add(TranslationDTO.fromJson(
jsonDecode(jsonEncode(initials.firstWhere((e) => e.language == lang)))!)!);
} else {
newValues.add(TranslationDTO(language: lang, value: ""));
}
});
if (isHTML) {
showMultiStringInputHTML(
label,
modalLabel,
isTitle,
initials,
newValues,
onGetResult,
maxLines,
resourceTypes,
context,
isMandatory,
);
} else {
showMultiStringInput(
label,
modalLabel,
isTitle,
initials,
newValues,
onGetResult,
maxLines,
resourceTypes,
context,
);
}
},
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 50,
width: 180,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(50),
),
alignment: Alignment.center,
child: Text(
resourceTypes == null ? "Changer traductions" : "Changer ressources",
style: const TextStyle(
color: kWhite,
fontWeight: FontWeight.w400,
fontSize: 16,
width: size.width *0.15,
child: InkWell(
onTap: () {
List<TranslationDTO> newValues = new List<TranslationDTO>();
// Make a copy
initialValue.forEach((value) {
newValues.add(TranslationDTO.fromJson(jsonDecode(jsonEncode(value))));
});
showMultiStringInput(label, modalLabel, initialValue, newValues, onGetResult, maxLines, context);
},
child: Container(
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(50),
),
child: Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 15, bottom: 15),
child: Center(
child: AutoSizeText(
"Changer les traductions",
style: TextStyle(color: kWhite),
maxLines: 2,
)
),
)
),
),
),
)
),
],
),
),
],
),
);
}
}
}

View File

@ -1,156 +0,0 @@
import 'package:flutter/material.dart';
import 'package:manager_app/Components/message_notification.dart';
import 'package:manager_app/Components/rounded_button.dart';
import 'package:manager_app/Components/translation_input_and_resource_container.dart';
import 'package:manager_app/Components/translation_input_container.dart';
import 'package:manager_app/constants.dart';
import 'package:manager_api_new/api.dart';
import 'package:collection/collection.dart';
showMultiStringInputHTML (String label, String modalLabel, bool isTitle, List<TranslationDTO> values, List<TranslationDTO> newValues, Function onGetResult, int maxLines, List<ResourceType>? resourceTypes, BuildContext context, bool isMandatory) {
showDialog(
useRootNavigator: false,
builder: (BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))
),
insetPadding: const EdgeInsets.symmetric(horizontal: 60, vertical: 24),
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 800),
child: Padding(
padding: const EdgeInsets.fromLTRB(24, 20, 24, 16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Center(child: Text(modalLabel, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500))),
const SizedBox(height: 16),
SingleChildScrollView(
child: TranslationInputContainer(isTitle: isTitle, values: values, newValues: newValues, onGetResult: onGetResult, maxLines: maxLines, resourceTypes: resourceTypes),
),
const SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SizedBox(
width: 180,
height: 70,
child: RoundedButton(
text: "Annuler",
icon: Icons.undo,
color: kSecond,
press: () {
onGetResult(values);
Navigator.of(context).pop();
},
fontSize: 20,
),
),
SizedBox(
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)) {
if(isMandatory && newValues.any((label) => label.value == null || label.value!.trim() == "")) {
showNotification(kPrimaryColor, kWhite, "La traduction n'est pas complète", context, null);
} else {
onGetResult(newValues);
Navigator.of(context).pop();
}
} else {
Navigator.of(context).pop();
}
},
fontSize: 20,
),
),
],
),
],
),
),
),
);
}, context: context
);
}
showMultiStringInputAndResourceHTML (String label, String modalLabel, bool isTitle, List<TranslationAndResourceDTO> values, List<TranslationAndResourceDTO> newValues, Function onGetResult, int maxLines, List<ResourceType>? resourceTypes, BuildContext context) {
showDialog(
useRootNavigator: false,
builder: (BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))
),
insetPadding: const EdgeInsets.symmetric(horizontal: 60, vertical: 24),
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 800),
child: Padding(
padding: const EdgeInsets.fromLTRB(24, 20, 24, 16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Center(child: Text(modalLabel, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500))),
const SizedBox(height: 16),
SingleChildScrollView(
child: TranslationInputAndResourceContainer(isTitle: isTitle, values: values, newValues: newValues, onGetResult: onGetResult, maxLines: maxLines, resourceTypes: resourceTypes),
),
const SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SizedBox(
width: 180,
height: 70,
child: RoundedButton(
text: "Annuler",
icon: Icons.undo,
color: kSecond,
press: () {
onGetResult(values);
Navigator.of(context).pop();
},
fontSize: 20,
),
),
SizedBox(
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)) {
if(newValues.any((label) => label.value == null || label.value!.trim() == "")) {
showNotification(kPrimaryColor, kWhite, "La traduction n'est pas complète", context, null);
} else {
onGetResult(newValues);
Navigator.of(context).pop();
}
} else {
Navigator.of(context).pop();
}
},
fontSize: 20,
),
),
],
),
],
),
),
),
);
}, context: context
);
}

View File

@ -1,60 +0,0 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:manager_app/Components/rounded_input_field.dart';
import 'package:manager_app/constants.dart';
class NumberInputContainer extends StatelessWidget {
final Color color;
final String label;
final int initialValue;
final ValueChanged<String> onChanged;
final bool isUrl;
final bool isSmall;
final int maxLength;
final double fontSize;
final double fontSizeText;
const NumberInputContainer({
Key? key,
this.color = kSecond,
required this.label,
required this.initialValue,
required this.onChanged,
this.isUrl = false,
this.isSmall = false,
this.maxLength = 50,
this.fontSize = 18.0,
this.fontSizeText = 20,
}) : super(key: key);
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Container(
child: Row(
children: [
Align(
alignment: AlignmentDirectional.centerStart,
child: Text(
label,
style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.w300),
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
width: isUrl ? size.width *0.6 : isSmall ? size.width *0.1 : size.width *0.2,
child: RoundedInputField(
color: color,
textColor: kBlack,
fontSize: fontSizeText,
initialValue: initialValue.toString(),
onChanged: onChanged,
maxLength: maxLength,
),
),
),
],
),
);
}
}

View File

@ -1,149 +0,0 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:manager_api_new/api.dart';
import 'package:manager_app/Components/rounded_button.dart';
import 'package:manager_app/Screens/Configurations/Section/SubSection/Map/category_list.dart';
import 'package:manager_app/Screens/Configurations/Section/SubSection/PDF/pdf_list.dart';
import 'package:manager_app/constants.dart';
class PDFFileInputContainer extends StatefulWidget {
final Color color;
final String label;
List<OrderedTranslationAndResourceDTO> initialValue;
final ValueChanged<List<OrderedTranslationAndResourceDTO>> onChanged;
final double fontSize;
PDFFileInputContainer({
Key? key,
this.color = kSecond,
required this.label,
required this.initialValue,
required this.onChanged,
this.fontSize = 18.0,
}) : super(key: key);
@override
_PDFFileInputContainerState createState() => _PDFFileInputContainerState();
}
class _PDFFileInputContainerState extends State<PDFFileInputContainer> {
@override
void initState() {
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: widget.fontSize, fontWeight: FontWeight.w300))
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: size.width *0.16,
child: InkWell(
onTap: () {
List<OrderedTranslationAndResourceDTO> newValues = <OrderedTranslationAndResourceDTO>[];
List<OrderedTranslationAndResourceDTO> initials = widget.initialValue;
showCreateOrUpdatePdfFiles("Fichiers PDF", initials, newValues, (value) {
widget.onChanged(value);
widget.initialValue = value;
}, context);
},
child: Container(
decoration: BoxDecoration(
color: kPrimaryColor,
borderRadius: BorderRadius.circular(50),
),
child: Padding(
padding: const EdgeInsets.only(left: 5, right: 5, top: 15, bottom: 15),
child: Center(
child: AutoSizeText(
"Changer",
style: TextStyle(color: kWhite),
maxLines: 2,
)
),
)
),
),
),
),
],
),
);
}
}
showCreateOrUpdatePdfFiles(String modalLabel, List<OrderedTranslationAndResourceDTO> values, List<OrderedTranslationAndResourceDTO> newValues, Function onGetResult, BuildContext context) {
showDialog(
builder: (BuildContext context) {
Size size = MediaQuery.of(context).size;
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))
),
title: Center(child: Text(modalLabel)),
content: SingleChildScrollView(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
border: Border.all(width: 0.75, color: kSecond)
),
height: size.height * 0.7,
width: size.width * 0.65,
child: PDFList(pdfs: values, onChanged: (result) {
newValues = result;
onGetResult(result);
}),
)
),
actions: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width: 180,
height: 70,
child: RoundedButton(
text: "Annuler",
icon: Icons.undo,
color: kSecond,
press: () {
onGetResult(values);
Navigator.of(context).pop();
},
fontSize: 20,
),
),
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
);
}

View File

@ -1,100 +0,0 @@
import 'package:flutter/material.dart';
/// Composant générique pour réordonner une liste avec heading et actions
class ReorderableCustomList<T> extends StatefulWidget {
final List<T> items;
final ValueChanged<List<T>> onChanged;
final Widget Function(BuildContext context, int index, T item) itemBuilder;
/// Liste dactions (icônes) par item, ex: delete, edit
final List<Widget Function(BuildContext context, int index, T item)>? actions;
final EdgeInsets? padding;
final bool shrinkWrap;
const ReorderableCustomList({
Key? key,
required this.items,
required this.onChanged,
required this.itemBuilder,
this.actions,
this.padding,
this.shrinkWrap = false,
}) : super(key: key);
@override
State<ReorderableCustomList<T>> createState() => _ReorderableCustomListState<T>();
}
class _ReorderableCustomListState<T> extends State<ReorderableCustomList<T>> {
late List<T> itemsMiddle;
@override
void initState() {
super.initState();
itemsMiddle = List<T>.from(widget.items);
}
void _onReorder(int oldIndex, int newIndex) {
setState(() {
if (newIndex > oldIndex) newIndex -= 1;
final T item = itemsMiddle.removeAt(oldIndex);
itemsMiddle.insert(newIndex, item);
widget.onChanged(itemsMiddle);
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
ReorderableListView.builder(
shrinkWrap: widget.shrinkWrap,
physics: const NeverScrollableScrollPhysics(),
padding: widget.padding,
itemCount: itemsMiddle.length,
buildDefaultDragHandles: false,
onReorder: _onReorder,
itemBuilder: (context, index) {
final item = itemsMiddle[index];
return Container(
key: ValueKey(item),
margin: const EdgeInsets.symmetric(vertical: 4),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: Colors.grey.shade300),
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
ReorderableDragStartListener(
index: index,
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.drag_handle, color: Colors.grey),
),
),
// Contenu de litem
Expanded(
child: widget.itemBuilder(context, index, item),
),
// Actions personnalisées
if (widget.actions != null)
Row(
children: widget.actions!
.map((builder) => builder(context, index, item))
.toList(),
),
],
),
);
},
),
],
);
}
}

View File

@ -1,151 +0,0 @@
import 'package:flutter/material.dart';
import 'package:manager_api_new/api.dart';
import 'package:manager_app/constants.dart';
import 'package:manager_app/Models/managerContext.dart';
import 'package:manager_app/app_context.dart';
import 'package:manager_app/Screens/Resources/select_resource_modal.dart';
import 'package:provider/provider.dart';
class ResourceInputContainer extends StatefulWidget {
final Color color;
final String label;
final String? initialValue;
final ValueChanged<ResourceDTO> onChanged;
final BoxFit imageFit;
final double fontSize;
final List<ResourceType> inResourceTypes;
final bool isSmall;
final bool isLanguageTab;
const ResourceInputContainer({
Key? key,
this.color = kSecond,
required this.label,
this.initialValue,
required this.onChanged,
this.imageFit = BoxFit.cover,
this.fontSize = 18,
this.inResourceTypes = const [ResourceType.Image, ResourceType.ImageUrl],
this.isSmall = false,
this.isLanguageTab = false,
}) : super(key: key);
@override
_ResourceInputContainerState createState() => _ResourceInputContainerState();
}
class _ResourceInputContainerState extends State<ResourceInputContainer> {
String? resourceIdToShow;
@override
void initState() {
super.initState();
resourceIdToShow = widget.initialValue;
}
@override
Widget build(BuildContext context) {
final appContext = Provider.of<AppContext>(context);
if (widget.isLanguageTab) {
resourceIdToShow = widget.initialValue;
}
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Align(
alignment: AlignmentDirectional.centerStart,
child: Text(
widget.label,
style: TextStyle(
fontWeight: FontWeight.w400,
fontSize: widget.fontSize,
),
),
),
const SizedBox(height: 8, width: 10),
Container(
padding: const EdgeInsets.all(4),
/*decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.grey.shade400, width: 1.2),
),*/
child: InkWell(
onTap: () async {
ResourceDTO? result = await showSelectResourceModal(
"Sélectionner une ressource",
1,
widget.inResourceTypes,
context,
true,
true,
true,
);
if (result != null) {
setState(() {
resourceIdToShow = result.id;
});
widget.onChanged(result);
}
},
child: Container(
height: widget.isSmall ? 35 : 100,
width: widget.isSmall ? 60 : 120,
alignment: Alignment.center,
decoration: BoxDecoration(
color: resourceIdToShow == null ? widget.color : Colors.transparent,
borderRadius: BorderRadius.circular(10),
),
child: resourceIdToShow == null
? Text(
"Choisir",
style: TextStyle(
color: kWhite,
fontSize: widget.fontSize,
),
maxLines: 1,
)
: FutureBuilder<ResourceDTO?>(
future: (appContext.getContext() as ManagerAppContext)
.clientAPI!
.resourceApi!
.resourceGetDetail(resourceIdToShow!),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(strokeWidth: 2),
);
} else if (snapshot.hasError || snapshot.data == null) {
return Text(
"Erreur",
style: TextStyle(
color: kWhite,
fontSize: widget.fontSize,
),
maxLines: 1,
);
} else {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
image: DecorationImage(
fit: widget.imageFit,
image: NetworkImage(snapshot.data!.url!),
),
),
);
}
},
),
),
),
),
],
);
}
}

View File

@ -2,19 +2,19 @@ import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:manager_app/Components/upload_content_container.dart';
import 'package:manager_app/Components/upload_image_container.dart';
import 'package:manager_app/Components/upload_online_resources_container.dart';
import 'package:manager_app/constants.dart';
import 'package:manager_api_new/api.dart';
import 'package:managerapi/api.dart';
class ResourceTab extends StatefulWidget {
final ResourceDTO resourceDTO;
final Function onFileUpload;
final Function onFileUploadWeb;
const ResourceTab({
Key? key,
required this.resourceDTO,
required this.onFileUpload,
required this.onFileUploadWeb,
Key key,
this.resourceDTO,
this.onFileUpload,
this.onFileUploadWeb,
}) : super(key: key);
@override
@ -22,16 +22,17 @@ class ResourceTab extends StatefulWidget {
}
class _ResourceTabState extends State<ResourceTab> with SingleTickerProviderStateMixin {
TabController? _tabController;
List<Tab> tabsToShow = <Tab>[];
TabController _tabController;
List<Tab> tabsToShow = new List<Tab>();
@override
void initState() {
tabsToShow.add(new Tab(text: "Local"));
tabsToShow.add(new Tab(text: "En ligne"));
tabsToShow.add(new Tab(text: "Image local"));
tabsToShow.add(new Tab(text: "Image en ligne"));
tabsToShow.add(new Tab(text: "Vidéo en ligne"));
_tabController = new TabController(length: 2, vsync: this);
//_tabController!.addListener(_handleTabSelection);
_tabController = new TabController(length: 3, vsync: this);
_tabController.addListener(_handleTabSelection);
super.initState();
}
@ -63,45 +64,45 @@ class _ResourceTabState extends State<ResourceTab> with SingleTickerProviderStat
);
}
/*void _handleTabSelection() {
switch(_tabController!.index) {
void _handleTabSelection() {
switch(_tabController.index) {
case 0:
setState(() {
widget.resourceDTO.url = null;
widget.resourceDTO.type = ResourceType.Image;
widget.resourceDTO.data = null;
widget.resourceDTO.type = ResourceType.image;
});
break;
case 1:
setState(() {
widget.resourceDTO.url = null;
widget.resourceDTO.type = ResourceType.ImageUrl;
widget.resourceDTO.data = null;
widget.resourceDTO.type = ResourceType.imageUrl;
});
break;
case 2:
setState(() {
widget.resourceDTO.url = null;
widget.resourceDTO.type = ResourceType.Audio;
widget.resourceDTO.data = null;
widget.resourceDTO.type = ResourceType.videoUrl;
});
break;
}
}*/
}
}
getContent(ResourceDTO resourceDTO, Function onFileUpload, Function onFileUploadWeb) {
List<Widget> tabsToShow = <Widget>[];
List<Widget> tabsToShow = new List<Widget>();
// Local Image
tabsToShow.add(
new Padding(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
child: UploadContentContainer(
onChanged: (List<File>? files) {
child: UploadImageContainer(
onChanged: (List<File> files) {
onFileUpload(files);
resourceDTO.type = ResourceType.Image;
resourceDTO.type = ResourceType.image;
},
onChangedWeb: (List<PlatformFile>? files) {
onChangedWeb: (List<PlatformFile> files) {
onFileUploadWeb(files);
resourceDTO.type = ResourceType.Image;
resourceDTO.type = ResourceType.image;
},
),
)
@ -113,47 +114,13 @@ getContent(ResourceDTO resourceDTO, Function onFileUpload, Function onFileUpload
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
child: UploadOnlineResourceContainer(
resourceDTO: resourceDTO,
onChanged: (ResourceDTO value) {
onChanged: (ResourceDTO value) {
resourceDTO = value;
},
),
)
);
// Audio
/*tabsToShow.add(
new Padding(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
child: UploadAudioContainer(
onChanged: (List<File> files) {
onFileUpload(files);
resourceDTO.type = ResourceType.Audio;
},
onChangedWeb: (List<PlatformFile> files) {
onFileUploadWeb(files);
resourceDTO.type = ResourceType.Audio;
},
),
)
);
// Video
tabsToShow.add(
new Padding(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
child: UploadContentContainer(
onChanged: (List<File>? files) {
onFileUpload(files);
resourceDTO.type = ResourceType.Video;
},
onChangedWeb: (List<PlatformFile>? files) {
onFileUploadWeb(files);
resourceDTO.type = ResourceType.Video;
},
),
)
);
// Online Video
tabsToShow.add(
new Padding(
@ -166,39 +133,5 @@ getContent(ResourceDTO resourceDTO, Function onFileUpload, Function onFileUpload
),
)
);
// PDF
tabsToShow.add(
new Padding(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
child: UploadContentContainer(
onChanged: (List<File>? files) {
onFileUpload(files);
resourceDTO.type = ResourceType.Pdf;
},
onChangedWeb: (List<PlatformFile>? files) {
onFileUploadWeb(files);
resourceDTO.type = ResourceType.Pdf;
},
),
)
);
// JSON
tabsToShow.add(
new Padding(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
child: UploadContentContainer(
onChanged: (List<File>? files) {
onFileUpload(files);
resourceDTO.type = ResourceType.Json;
},
onChangedWeb: (List<PlatformFile>? files) {
onFileUploadWeb(files);
resourceDTO.type = ResourceType.Json;
},
),
)
);*/
return tabsToShow;
}

View File

@ -1,43 +1,46 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:manager_app/constants.dart';
class RoundedButton extends StatelessWidget {
final String text;
final Function press;
final IconData? icon;
final IconData icon;
final Color color, textColor;
final double fontSize;
final double? vertical;
final double? horizontal;
final int vertical;
final int horizontal;
const RoundedButton(
{Key? key,
required this.text,
required this.press,
this.icon,
this.color = kPrimaryColor,
this.textColor = kWhite,
required this.fontSize,
this.vertical,
this.horizontal})
: super(key: key);
const RoundedButton({
Key key,
this.text,
this.press,
this.icon,
this.color = kPrimaryColor,
this.textColor = kWhite,
this.fontSize,
this.vertical,
this.horizontal
}) : super(key: key);
@override
Widget build(BuildContext context) {
//Size size = MediaQuery.of(context).size;
return TextButton(
style: ButtonStyle(
padding: MaterialStateProperty.all(EdgeInsets.symmetric(
vertical: vertical ?? 12,
horizontal: horizontal ?? (icon == null ? 20 : 15),
)),
backgroundColor: MaterialStateProperty.all(color),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
))),
onPressed: () => {press()},
child: getValue(icon));
padding: MaterialStateProperty.resolveWith((states) => EdgeInsets.symmetric(vertical: this.vertical != null ? this.vertical : 25, horizontal: this.horizontal != null ? this.horizontal : (icon == null ? 85 : 30))),
backgroundColor: MaterialStateColor.resolveWith((states) => color),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
)
)
),
onPressed: () => {
press()
},
child: getValue(icon)
);
}
getValue(icon) {
@ -46,18 +49,14 @@ class RoundedButton extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Center(
child: AutoSizeText(
child: Text(
text,
style: new TextStyle(
color: textColor,
fontSize: fontSize,
fontWeight: FontWeight.w400),
maxLines: 2,
maxFontSize: fontSize,
textAlign: TextAlign.center,
style: new TextStyle(color: textColor, fontSize: fontSize, fontWeight: FontWeight.w400),
),
),
SizedBox(width: 10),
SizedBox(
width: 10
),
Icon(
icon,
color: textColor,
@ -66,13 +65,10 @@ class RoundedButton extends StatelessWidget {
],
);
} else {
return AutoSizeText(
text,
style: new TextStyle(
color: textColor, fontSize: fontSize, fontWeight: FontWeight.w400),
maxLines: 2,
textAlign: TextAlign.center,
);
return Text(
text,
style: new TextStyle(color: textColor, fontSize: fontSize, fontWeight: FontWeight.w400),
);
}
}
}
}

View File

@ -1,33 +1,26 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:manager_app/Components/text_field_container.dart';
import 'package:manager_app/constants.dart';
class RoundedInputField extends StatelessWidget {
final String? hintText;
final IconData? icon;
final String hintText;
final IconData icon;
final ValueChanged<String> onChanged;
final String? initialValue;
final String initialValue;
final Color color, textColor, iconColor;
final int? maxLength;
final int maxLength;
final bool isEmail;
final double fontSize;
final String? autofill;
final bool isInt;
const RoundedInputField({
Key? key,
Key key,
this.hintText,
this.initialValue,
this.icon,
this.color = kSecond,
this.textColor = kBlack,
this.iconColor = kPrimaryColor,
required this.onChanged,
this.onChanged,
this.maxLength, // 50
this.isEmail = false,
this.fontSize = 20,
this.autofill,
this.isInt = false
this.isEmail = false
}) : super(key: key);
@override
@ -39,19 +32,15 @@ class RoundedInputField extends StatelessWidget {
initialValue: initialValue,
cursorColor: textColor,
maxLength: maxLength,
autofillHints: autofill != null ? [autofill!] : [],
keyboardType: isEmail ? TextInputType.emailAddress : isInt ? TextInputType.number : TextInputType.text,
inputFormatters: !isInt ? [] : <TextInputFormatter>[
FilteringTextInputFormatter.digitsOnly
],
style: TextStyle(fontSize: fontSize, color: textColor),
keyboardType: isEmail ? TextInputType.emailAddress : TextInputType.text,
style: TextStyle(fontSize: 20, color: textColor),
decoration: InputDecoration(
icon: icon != null ? Icon(
icon,
color: iconColor,
): null,
hintText: hintText,
hintStyle: TextStyle(fontSize: fontSize, color: textColor, fontWeight: FontWeight.w400),
hintStyle: TextStyle(fontSize: 20.0, color: textColor),
border: InputBorder.none,
)
),

View File

@ -6,9 +6,9 @@ class RoundedPasswordField extends StatefulWidget {
final ValueChanged<String> onChanged;
final String initialValue;
const RoundedPasswordField({
Key? key,
required this.onChanged,
required this.initialValue
Key key,
this.onChanged,
this.initialValue,
}) : super(key: key);
@override
@ -25,12 +25,11 @@ class _RoundedPasswordFieldState extends State<RoundedPasswordField> {
obscureText: isVisible,
onChanged: widget.onChanged,
initialValue: widget.initialValue,
autofillHints: [AutofillHints.password],
cursorColor: kPrimaryColor,
style: TextStyle(fontSize: 20, color: kBlack),
decoration: InputDecoration(
hintText: "Mot de passe",
hintStyle: TextStyle(fontSize: 20.0, color: kBlack, fontWeight: FontWeight.normal),
hintText: "Password",
hintStyle: TextStyle(fontSize: 20.0, color: kBlack),
icon: Icon(
Icons.lock,
color: kPrimaryColor,

Some files were not shown because too many files have changed in this diff Show More