Compare commits
No commits in common. "Version-2.0.4" and "master" have entirely different histories.
Version-2.
...
master
1
.gitignore
vendored
@ -32,6 +32,7 @@
|
|||||||
/build/
|
/build/
|
||||||
|
|
||||||
# Web related
|
# Web related
|
||||||
|
lib/generated_plugin_registrant.dart
|
||||||
|
|
||||||
# Symbolication related
|
# Symbolication related
|
||||||
app.*.symbols
|
app.*.symbols
|
||||||
|
|||||||
23
Dockerfile
@ -1,23 +0,0 @@
|
|||||||
#Stage 1 - Install dependencies and build the app in a build environment
|
|
||||||
FROM debian:latest AS build-env
|
|
||||||
# Install flutter dependencies
|
|
||||||
RUN apt-get update
|
|
||||||
RUN apt-get install -y curl git wget unzip libgconf-2-4 gdb libstdc++6 libglu1-mesa fonts-droid-fallback lib32stdc++6 python3 sed
|
|
||||||
RUN apt-get clean
|
|
||||||
# Clone the flutter repo
|
|
||||||
RUN git clone https://github.com/flutter/flutter.git /usr/local/flutter
|
|
||||||
# Set flutter path
|
|
||||||
ENV PATH="${PATH}:/usr/local/flutter/bin:/usr/local/flutter/bin/cache/dart-sdk/bin"
|
|
||||||
# Run flutter doctor
|
|
||||||
RUN flutter doctor -v
|
|
||||||
RUN flutter channel master
|
|
||||||
RUN flutter upgrade
|
|
||||||
# Copy files to container and build
|
|
||||||
RUN mkdir /app/
|
|
||||||
COPY . /app/
|
|
||||||
WORKDIR /app/
|
|
||||||
RUN flutter build web
|
|
||||||
#--no-sound-null-safety
|
|
||||||
# Stage 2 - Create the run-time image
|
|
||||||
FROM nginx:1.21.1-alpine
|
|
||||||
COPY --from=build-env /app/build/web /usr/share/nginx/html
|
|
||||||
18
README.md
@ -15,31 +15,21 @@ For help getting started with Flutter, view our
|
|||||||
[online documentation](https://flutter.dev/docs), which offers tutorials,
|
[online documentation](https://flutter.dev/docs), which offers tutorials,
|
||||||
samples, guidance on mobile development, and a full API reference.
|
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
|
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
|
=> Faudrait mettre à jour le projet avec les nouvelles versions plugins
|
||||||
|
|
||||||
flutter clean
|
|
||||||
|
|
||||||
flutter pub get
|
|
||||||
|
|
||||||
flutter pub run build_runner build --delete-conflicting-outputs
|
|
||||||
|
|
||||||
Le fichier est dans le projet.
|
|
||||||
|
|
||||||
# Publication sur docker
|
# Publication sur docker
|
||||||
|
|
||||||
Avant de build en docker, il faut build en web => flutter build web
|
|
||||||
|
|
||||||
docker build -t flutter-web .
|
docker build -t flutter-web .
|
||||||
|
|
||||||
Pour tester en local :
|
Pour tester en local :
|
||||||
docker run -d -p 8080:80 –name flutter-web flutter-web
|
docker run -d -p 8080:80 –name flutter-web flutter-web
|
||||||
|
|
||||||
Image tag:
|
Image tag:
|
||||||
docker image tag flutter-web registry.unov.be/mymuseum/manager:version-2.0.0
|
docker image tag flutter-web registry.unov.be/mymuseum/manager:latest
|
||||||
|
|
||||||
Docker push:
|
Docker push:
|
||||||
docker image push registry.unov.be/mymuseum/manager:version-2.0.0
|
docker image push registry.unov.be/mymuseum/manager:latest
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
Ajout du Module quizz
|
|
||||||
@ -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
|
|
||||||
@ -1 +0,0 @@
|
|||||||
2850532bac056cc3a4316af3c232a077
|
|
||||||
@ -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"]}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
[{"family":"MaterialIcons","fonts":[{"asset":"fonts/MaterialIcons-Regular.otf"}]},{"family":"packages/cupertino_icons/CupertinoIcons","fonts":[{"asset":"packages/cupertino_icons/assets/CupertinoIcons.ttf"}]}]
|
|
||||||
|
Before Width: | Height: | Size: 917 B |
@ -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;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
@ -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>
|
|
||||||
|
Before Width: | Height: | Size: 826 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
@ -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>
|
|
||||||
@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
{"app_name":"manager_app","version":"1.0.0","build_number":"1","package_name":"manager_app"}
|
|
||||||
@ -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
|
|
||||||
@ -34,7 +34,7 @@ android {
|
|||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "be.mdlf.manager_app"
|
applicationId "be.mdlf.manager_app"
|
||||||
minSdkVersion flutter.minSdkVersion
|
minSdkVersion 16
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.7.10'
|
ext.kotlin_version = '1.3.50'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
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"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -26,6 +26,6 @@ subprojects {
|
|||||||
project.evaluationDependsOn(':app')
|
project.evaluationDependsOn(':app')
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register("clean", Delete) {
|
task clean(type: Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
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
|
||||||
|
|||||||
@ -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 information’s 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>
|
|
||||||
|
|
||||||
@ -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 information’s 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.
|
|
||||||
@ -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 information’s 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.
|
|
||||||
@ -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 information’s 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.
|
|
||||||
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 225 B |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 233 B |
|
Before Width: | Height: | Size: 705 B |
|
Before Width: | Height: | Size: 219 B |
|
Before Width: | Height: | Size: 189 B |
|
Before Width: | Height: | Size: 279 B |
@ -1,173 +0,0 @@
|
|||||||
import 'package:auto_size_text/auto_size_text.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:manager_app/Components/loading_common.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: LoadingCommon()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} 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
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,246 +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) {
|
|
||||||
print("RESET ALL");
|
|
||||||
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',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,87 +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 = 20
|
|
||||||
}) : 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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
AutoSizeText(
|
|
||||||
widget.label,
|
|
||||||
style: new TextStyle(fontSize: widget.fontSize, fontWeight: FontWeight.w300),
|
|
||||||
maxLines: 2,
|
|
||||||
maxFontSize: widget.fontSize,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
),
|
|
||||||
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!);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
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 'package:manager_app/Components/rounded_button.dart';
|
||||||
|
|
||||||
import '../constants.dart';
|
import '../constants.dart';
|
||||||
@ -18,13 +18,8 @@ showColorPicker (Color currentColor, Function onSelect, BuildContext context) {
|
|||||||
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
||||||
),
|
),
|
||||||
content: SingleChildScrollView(
|
content: SingleChildScrollView(
|
||||||
child: SizedBox(
|
|
||||||
width: 500,
|
|
||||||
height: 500,
|
|
||||||
child: ColorPicker(
|
child: ColorPicker(
|
||||||
color: currentColor,
|
pickerColor: currentColor,
|
||||||
onChanged: changeColor,
|
|
||||||
/*pickerColor: currentColor,
|
|
||||||
onColorChanged: changeColor,
|
onColorChanged: changeColor,
|
||||||
colorPickerWidth: 300.0,
|
colorPickerWidth: 300.0,
|
||||||
pickerAreaHeightPercent: 0.7,
|
pickerAreaHeightPercent: 0.7,
|
||||||
@ -36,7 +31,6 @@ showColorPicker (Color currentColor, Function onSelect, BuildContext context) {
|
|||||||
.only(
|
.only(
|
||||||
topLeft: const Radius.circular(2.0),
|
topLeft: const Radius.circular(2.0),
|
||||||
topRight: const Radius.circular(2.0),
|
topRight: const Radius.circular(2.0),
|
||||||
),*/
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,18 +1,16 @@
|
|||||||
import 'package:auto_size_text/auto_size_text.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:manager_app/Components/color_picker.dart';
|
import 'package:manager_app/Components/color_picker.dart';
|
||||||
|
|
||||||
class ColorPickerInputContainer extends StatefulWidget {
|
class ColorPickerInputContainer extends StatefulWidget {
|
||||||
final String? color;
|
final String color;
|
||||||
final String label;
|
final String label;
|
||||||
final double fontSize;
|
|
||||||
final ValueChanged<String> onChanged;
|
final ValueChanged<String> onChanged;
|
||||||
const ColorPickerInputContainer({
|
const ColorPickerInputContainer({
|
||||||
Key? key,
|
Key key,
|
||||||
this.color,
|
this.color,
|
||||||
required this.label,
|
this.label,
|
||||||
this.fontSize = 25,
|
this.onChanged,
|
||||||
required this.onChanged,
|
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -20,12 +18,12 @@ class ColorPickerInputContainer extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ColorPickerInputContainerState extends State<ColorPickerInputContainer> {
|
class _ColorPickerInputContainerState extends State<ColorPickerInputContainer> {
|
||||||
Color? colorVar;
|
Color colorVar;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
setState(() {
|
setState(() {
|
||||||
colorVar = widget.color == null ? new Color(0x12345678) : new Color(int.parse(widget.color!.split('(0x')[1].split(')')[0], radix: 16));
|
colorVar = widget.color == null ? new Color(0x12345678) : new Color(int.parse(widget.color.split('(0x')[1].split(')')[0], radix: 16));
|
||||||
});
|
});
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
@ -37,20 +35,14 @@ class _ColorPickerInputContainerState extends State<ColorPickerInputContainer> {
|
|||||||
children: [
|
children: [
|
||||||
Align(
|
Align(
|
||||||
alignment: AlignmentDirectional.centerStart,
|
alignment: AlignmentDirectional.centerStart,
|
||||||
child: AutoSizeText(
|
child: Text(widget.label, style: TextStyle(fontSize: 25, fontWeight: FontWeight.w300))
|
||||||
widget.label,
|
|
||||||
style: TextStyle(fontSize: widget.fontSize, fontWeight: FontWeight.w300),
|
|
||||||
maxLines: 2,
|
|
||||||
maxFontSize: widget.fontSize,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(10.0),
|
padding: const EdgeInsets.all(10.0),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
showColorPicker(
|
showColorPicker(
|
||||||
colorVar!,
|
colorVar,
|
||||||
(Color color) {
|
(Color color) {
|
||||||
setState(() {
|
setState(() {
|
||||||
colorVar = color;
|
colorVar = color;
|
||||||
|
|||||||
@ -1,74 +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;
|
|
||||||
|
|
||||||
const DropDownInputContainer({
|
|
||||||
Key? key,
|
|
||||||
required this.label,
|
|
||||||
required this.values,
|
|
||||||
this.initialValue,
|
|
||||||
this.onChange,
|
|
||||||
}) : 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: 25, 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(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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 CategorieDTO? 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!.id);
|
|
||||||
}
|
|
||||||
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(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,24 +1,20 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:manager_api_new/api.dart';
|
import 'package:managerapi/api.dart';
|
||||||
|
|
||||||
IconData getResourceIcon(elementType) {
|
IconData getResourceIcon(elementType) {
|
||||||
switch(elementType) {
|
switch(elementType) {
|
||||||
case ResourceType.Image:
|
case ResourceType.image:
|
||||||
return Icons.image;
|
return Icons.image;
|
||||||
case ResourceType.ImageUrl:
|
break;
|
||||||
|
case ResourceType.imageUrl:
|
||||||
return Icons.image_search; // art_track
|
return Icons.image_search; // art_track
|
||||||
case ResourceType.Audio:
|
break;
|
||||||
return Icons.audiotrack; // art_track
|
case ResourceType.video:
|
||||||
case ResourceType.Video:
|
|
||||||
return Icons.slow_motion_video;
|
return Icons.slow_motion_video;
|
||||||
case ResourceType.VideoUrl:
|
break;
|
||||||
|
case ResourceType.videoUrl:
|
||||||
return Icons.ondemand_video_sharp;
|
return Icons.ondemand_video_sharp;
|
||||||
case ResourceType.Pdf:
|
break;
|
||||||
return Icons.picture_as_pdf_outlined;
|
|
||||||
case ResourceType.Json:
|
|
||||||
return Icons.file_present_outlined;
|
|
||||||
case ResourceType.JsonUrl:
|
|
||||||
return Icons.file_present_rounded;
|
|
||||||
}
|
}
|
||||||
return Icons.announcement;
|
return Icons.announcement;
|
||||||
}
|
}
|
||||||
@ -1,30 +1,26 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:manager_api_new/api.dart';
|
import 'package:managerapi/api.dart';
|
||||||
|
|
||||||
IconData getSectionIcon(elementType) {
|
IconData getSectionIcon(elementType) {
|
||||||
switch(elementType) {
|
switch(elementType) {
|
||||||
case SectionType.Map:
|
case SectionType.map:
|
||||||
return Icons.location_on;
|
return Icons.location_on;
|
||||||
case SectionType.Slider:
|
break;
|
||||||
|
case SectionType.slider:
|
||||||
return Icons.collections; // art_track
|
return Icons.collections; // art_track
|
||||||
case SectionType.Video:
|
break;
|
||||||
|
case SectionType.video:
|
||||||
return Icons.ondemand_video_rounded;
|
return Icons.ondemand_video_rounded;
|
||||||
case SectionType.Web:
|
break;
|
||||||
|
case SectionType.web:
|
||||||
return Icons.web;
|
return Icons.web;
|
||||||
case SectionType.Menu:
|
break;
|
||||||
|
case SectionType.menu:
|
||||||
return Icons.apps_sharp;
|
return Icons.apps_sharp;
|
||||||
case SectionType.Quizz:
|
break;
|
||||||
|
case SectionType.quizz:
|
||||||
return Icons.question_answer;
|
return Icons.question_answer;
|
||||||
case SectionType.Article:
|
break;
|
||||||
return Icons.article_outlined;
|
|
||||||
case SectionType.Pdf:
|
|
||||||
return Icons.picture_as_pdf_outlined;
|
|
||||||
case SectionType.Puzzle:
|
|
||||||
return Icons.extension;
|
|
||||||
case SectionType.Agenda:
|
|
||||||
return Icons.calendar_month_outlined;
|
|
||||||
case SectionType.Weather:
|
|
||||||
return Icons.sunny;
|
|
||||||
}
|
}
|
||||||
return Icons.question_mark;
|
return Icons.menu;
|
||||||
}
|
}
|
||||||
@ -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
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,181 +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/loading_common.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 = 25,
|
|
||||||
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: AutoSizeText(
|
|
||||||
widget.label,
|
|
||||||
style: TextStyle(fontSize: widget.fontSize, fontWeight: FontWeight.w300),
|
|
||||||
maxLines: 2,
|
|
||||||
maxFontSize: widget.fontSize,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
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: LoadingCommon(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,
|
|
||||||
)
|
|
||||||
),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
158
lib/Components/image_input_container.dart
Normal 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
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,7 +2,7 @@ import 'package:flare_flutter/flare_actor.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class Loading extends StatelessWidget {
|
class Loading extends StatelessWidget {
|
||||||
Loading({Key? key}) : super(key: key);
|
Loading({Key key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|||||||
@ -1,53 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:manager_app/constants.dart';
|
|
||||||
|
|
||||||
class LoadingCommon extends StatefulWidget {
|
|
||||||
double? iconSize;
|
|
||||||
|
|
||||||
LoadingCommon({Key? key, this.iconSize}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<LoadingCommon> createState() => _LoadingCommonState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _LoadingCommonState extends State<LoadingCommon> 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: Icon(Icons.museum_outlined, color: kPrimaryColor, size: widget.iconSize == null ? size.height*0.1 : widget.iconSize!),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,21 +1,10 @@
|
|||||||
import 'package:another_flushbar/flushbar.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
showNotification (Color backgroundColor, Color textColor, String text, BuildContext context, int? duration) async {
|
showNotification (Color backgroundColor, Color textColor, String text, BuildContext context, int duration) {
|
||||||
|
final snackBar = SnackBar(
|
||||||
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);
|
|
||||||
|
|
||||||
/*final snackBar = SnackBar(
|
|
||||||
behavior: SnackBarBehavior.floating,
|
behavior: SnackBarBehavior.floating,
|
||||||
duration: duration == null ? Duration(milliseconds: 1500) : Duration(milliseconds: duration),
|
duration: duration == null ? Duration(milliseconds: 1500) : Duration(milliseconds: duration),
|
||||||
width: 320.0, // Width of the SnackBar.
|
width: 280.0, // Width of the SnackBar.
|
||||||
backgroundColor: backgroundColor,
|
backgroundColor: backgroundColor,
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(10.0),
|
borderRadius: BorderRadius.circular(10.0),
|
||||||
@ -34,5 +23,5 @@ showNotification (Color backgroundColor, Color textColor, String text, BuildCont
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);*/
|
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,15 @@
|
|||||||
|
import 'package:auto_size_text/auto_size_text.dart';
|
||||||
import 'package:flutter/material.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/rounded_button.dart';
|
||||||
import 'package:manager_app/Components/text_form_input_container.dart';
|
import 'package:manager_app/Components/text_form_input_container.dart';
|
||||||
import 'package:manager_app/Models/managerContext.dart';
|
import 'package:manager_app/Models/managerContext.dart';
|
||||||
import 'package:manager_app/app_context.dart';
|
import 'package:manager_app/app_context.dart';
|
||||||
import 'package:manager_app/constants.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:collection/collection.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import 'audio_input_container.dart';
|
showMultiStringInput (String label, String modalLabel, List<TranslationDTO> values, List<TranslationDTO> newValues, Function onGetResult, int maxLines, BuildContext context) { /*Function onSelect,*/
|
||||||
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,*/
|
|
||||||
showDialog(
|
showDialog(
|
||||||
builder: (BuildContext context) => AlertDialog(
|
builder: (BuildContext context) => AlertDialog(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
@ -27,7 +23,7 @@ showMultiStringInput (String label, String modalLabel, bool isTitle, List<Transl
|
|||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: getTranslations(context, Provider.of<AppContext>(context), label, isTitle, resourceTypes, newValues),
|
children: getTranslations(context, Provider.of<AppContext>(context), label, newValues),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -49,9 +45,7 @@ showMultiStringInput (String label, String modalLabel, bool isTitle, List<Transl
|
|||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Container(
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Container(
|
|
||||||
width: 180,
|
width: 180,
|
||||||
height: 70,
|
height: 70,
|
||||||
child: RoundedButton(
|
child: RoundedButton(
|
||||||
@ -65,10 +59,7 @@ showMultiStringInput (String label, String modalLabel, bool isTitle, List<Transl
|
|||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Container(
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Container(
|
|
||||||
width: 180,
|
width: 180,
|
||||||
height: 70,
|
height: 70,
|
||||||
child: RoundedButton(
|
child: RoundedButton(
|
||||||
@ -86,7 +77,6 @@ showMultiStringInput (String label, String modalLabel, bool isTitle, List<Transl
|
|||||||
fontSize: 20,
|
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>[];
|
List<Widget> translations = <Widget>[];
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
ManagerAppContext managerAppContext = appContext.getContext();
|
||||||
for(var language in managerAppContext.selectedConfiguration!.languages!) {
|
for(var language in managerAppContext.selectedConfiguration.languages) {
|
||||||
translations.add(
|
translations.add(
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
FlagDecoration(language: language),
|
Container(
|
||||||
/*Container(
|
|
||||||
width: MediaQuery.of(context).size.width *0.05,
|
width: MediaQuery.of(context).size.width *0.05,
|
||||||
height: MediaQuery.of(context).size.height *0.10,
|
height: MediaQuery.of(context).size.height *0.10,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
@ -114,7 +103,7 @@ getTranslations(BuildContext context, AppContext appContext, String label, bool
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: Center(child: AutoSizeText(language.toUpperCase()))
|
child: Center(child: AutoSizeText(language.toUpperCase()))
|
||||||
),*/
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 8.0),
|
padding: const EdgeInsets.only(left: 8.0),
|
||||||
child: Container(
|
child: Container(
|
||||||
@ -122,37 +111,14 @@ getTranslations(BuildContext context, AppContext appContext, String label, bool
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
resourceTypes == null ?
|
|
||||||
TextFormInputContainer(
|
TextFormInputContainer(
|
||||||
label: label,
|
label: label,
|
||||||
color: kWhite,
|
color: kWhite,
|
||||||
isTitle: isTitle,
|
isTitle: true,
|
||||||
initialValue: newValues.where((element) => element.language == language).first.value!,
|
initialValue: newValues.where((element) => element.language == language).first.value,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
newValues.where((element) => element.language == language).first.value = 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;
|
return translations;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
showValues(List<TranslationDTO> newValues) {
|
showValues(List<TranslationDTO> newValues) {
|
||||||
List<Widget> valuesToShow = new List<Widget>();
|
List<Widget> valuesToShow = new List<Widget>();
|
||||||
@ -182,3 +147,5 @@ showValues(List<TranslationDTO> newValues) {
|
|||||||
});
|
});
|
||||||
return valuesToShow;
|
return valuesToShow;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,59 +1,46 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:manager_app/constants.dart';
|
import 'package:manager_app/constants.dart';
|
||||||
import 'package:html/parser.dart' show parse;
|
|
||||||
|
|
||||||
import 'message_notification.dart';
|
import 'message_notification.dart';
|
||||||
|
|
||||||
class MultiSelectContainer extends StatelessWidget {
|
class MultiSelectContainer extends StatelessWidget {
|
||||||
final Color color;
|
final Color color;
|
||||||
final String? label;
|
final String label;
|
||||||
final List<String> values;
|
final List<String> values;
|
||||||
final List<String> initialValue;
|
final List<String> initialValue;
|
||||||
final bool isMultiple;
|
final bool isMultiple;
|
||||||
final bool isAtLeastOne;
|
final bool isAtLeastOne;
|
||||||
final bool isHTMLLabel;
|
|
||||||
final double? width;
|
|
||||||
final int maxLines;
|
|
||||||
final ValueChanged<List<dynamic>> onChanged;
|
final ValueChanged<List<dynamic>> onChanged;
|
||||||
const MultiSelectContainer({
|
const MultiSelectContainer({
|
||||||
Key? key,
|
Key key,
|
||||||
this.color = kSecond,
|
this.color = kSecond,
|
||||||
required this.label,
|
this.label,
|
||||||
required this.values,
|
this.values,
|
||||||
required this.initialValue,
|
this.initialValue,
|
||||||
required this.isMultiple,
|
this.isMultiple,
|
||||||
this.isAtLeastOne = false,
|
this.isAtLeastOne = false,
|
||||||
this.isHTMLLabel = false,
|
this.onChanged,
|
||||||
this.width,
|
|
||||||
this.maxLines = 2,
|
|
||||||
required this.onChanged,
|
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
return SingleChildScrollView(
|
return Container(
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
children: [
|
||||||
if(label != null)
|
|
||||||
Align(
|
Align(
|
||||||
alignment: AlignmentDirectional.centerStart,
|
alignment: AlignmentDirectional.centerStart,
|
||||||
child: Text(label!, style: TextStyle(fontSize: 25, fontWeight: FontWeight.w300))
|
child: Text(label, style: TextStyle(fontSize: 25, fontWeight: FontWeight.w300))
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(10.0),
|
padding: const EdgeInsets.all(10.0),
|
||||||
child: Container(
|
child: Container(
|
||||||
width: width ?? size.width *0.25,
|
width: size.width *0.2,
|
||||||
//color: Colors.yellow,
|
|
||||||
child: MultiSelectChip(
|
child: MultiSelectChip(
|
||||||
values,
|
values,
|
||||||
initialValue,
|
initialValue,
|
||||||
isMultiple,
|
isMultiple,
|
||||||
isAtLeastOne,
|
isAtLeastOne,
|
||||||
isHTMLLabel,
|
|
||||||
maxLines,
|
|
||||||
onSelectionChanged: (selectedList) {
|
onSelectionChanged: (selectedList) {
|
||||||
onChanged(selectedList);
|
onChanged(selectedList);
|
||||||
},
|
},
|
||||||
@ -72,30 +59,24 @@ class MultiSelectChip extends StatefulWidget {
|
|||||||
final Function(List<String>) onSelectionChanged; // +added
|
final Function(List<String>) onSelectionChanged; // +added
|
||||||
final bool isMultiple;
|
final bool isMultiple;
|
||||||
final bool isAtLeastOne;
|
final bool isAtLeastOne;
|
||||||
final bool isHTMLLabel;
|
|
||||||
final int maxLines;
|
|
||||||
MultiSelectChip(
|
MultiSelectChip(
|
||||||
this.values,
|
this.values,
|
||||||
this.selectedValues,
|
this.selectedValues,
|
||||||
this.isMultiple,
|
this.isMultiple,
|
||||||
this.isAtLeastOne,
|
this.isAtLeastOne,
|
||||||
this.isHTMLLabel,
|
{this.onSelectionChanged} // +added
|
||||||
this.maxLines,
|
|
||||||
{required this.onSelectionChanged} // +added
|
|
||||||
);
|
);
|
||||||
@override
|
@override
|
||||||
_MultiSelectChipState createState() => _MultiSelectChipState();
|
_MultiSelectChipState createState() => _MultiSelectChipState();
|
||||||
}
|
}
|
||||||
class _MultiSelectChipState extends State<MultiSelectChip> {
|
class _MultiSelectChipState extends State<MultiSelectChip> {
|
||||||
int maxLines = 1; // Définir le nombre maximum de lignes
|
|
||||||
|
|
||||||
_buildChoiceList() {
|
_buildChoiceList() {
|
||||||
List<Widget> choices = [];
|
List<Widget> choices = List();
|
||||||
widget.values.forEach((item) {
|
widget.values.forEach((item) {
|
||||||
choices.add(Container(
|
choices.add(Container(
|
||||||
padding: const EdgeInsets.all(2.0),
|
padding: const EdgeInsets.all(2.0),
|
||||||
child: ChoiceChip(
|
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),
|
selected: widget.selectedValues.contains(item),
|
||||||
selectedColor: kPrimaryColor,
|
selectedColor: kPrimaryColor,
|
||||||
onSelected: (selected) {
|
onSelected: (selected) {
|
||||||
@ -121,17 +102,10 @@ class _MultiSelectChipState extends State<MultiSelectChip> {
|
|||||||
});
|
});
|
||||||
return choices;
|
return choices;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Wrap(
|
||||||
height: maxLines * 48.0, // Assuming each ChoiceChip is 48.0 height
|
|
||||||
child: ListView(
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
shrinkWrap: true,
|
|
||||||
children: _buildChoiceList(),
|
children: _buildChoiceList(),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,81 +0,0 @@
|
|||||||
import 'package:auto_size_text/auto_size_text.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:manager_app/constants.dart';
|
|
||||||
import 'package:multi_select_flutter/chip_display/multi_select_chip_display.dart';
|
|
||||||
import 'package:multi_select_flutter/dialog/multi_select_dialog_field.dart';
|
|
||||||
import 'package:multi_select_flutter/util/multi_select_item.dart';
|
|
||||||
import 'package:multi_select_flutter/util/multi_select_list_type.dart';
|
|
||||||
|
|
||||||
|
|
||||||
class MultiSelectDropdownLanguageContainer extends StatelessWidget {
|
|
||||||
final Color color;
|
|
||||||
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<dynamic>> 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 = 25,
|
|
||||||
required this.onChanged,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
Size size = MediaQuery.of(context).size;
|
|
||||||
return Container(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.centerStart,
|
|
||||||
child: AutoSizeText(
|
|
||||||
label,
|
|
||||||
style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.w300),
|
|
||||||
maxLines: 2,
|
|
||||||
maxFontSize: fontSize,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(10.0),
|
|
||||||
child: Container(
|
|
||||||
width: size.width *0.2,
|
|
||||||
child: MultiSelectDialogField(
|
|
||||||
items: values.map((e) => MultiSelectItem(e, e)).toList(),
|
|
||||||
listType: MultiSelectListType.LIST,
|
|
||||||
cancelText: Text("Annuler"),
|
|
||||||
initialValue: initialValue,
|
|
||||||
buttonText: Text("Sélectionner"),
|
|
||||||
checkColor: Colors.white,
|
|
||||||
searchable: true,
|
|
||||||
chipDisplay: MultiSelectChipDisplay.none(),
|
|
||||||
selectedColor: kPrimaryColor,
|
|
||||||
title: Text(labelHint),
|
|
||||||
dialogHeight: size.height *0.4,
|
|
||||||
dialogWidth: size.width *0.2,
|
|
||||||
onSelectionChanged: (selectedList) {
|
|
||||||
onChanged(selectedList);
|
|
||||||
},
|
|
||||||
onConfirm: (List<dynamic> test)
|
|
||||||
{
|
|
||||||
print("onConfirm MultiSelectDialogField");
|
|
||||||
print(test);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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: "", resourceType: null, resourceId: null, resourceUrl: 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,
|
|
||||||
)
|
|
||||||
),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -3,44 +3,28 @@ import 'dart:convert';
|
|||||||
import 'package:auto_size_text/auto_size_text.dart';
|
import 'package:auto_size_text/auto_size_text.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:manager_app/Components/multi_input_modal.dart';
|
import 'package:manager_app/Components/multi_input_modal.dart';
|
||||||
import 'package:manager_app/Components/multi_string_input_html_modal.dart';
|
|
||||||
import 'package:manager_app/Models/managerContext.dart';
|
|
||||||
import 'package:manager_app/app_context.dart';
|
|
||||||
import 'package:manager_app/constants.dart';
|
import 'package:manager_app/constants.dart';
|
||||||
import 'package:manager_api_new/api.dart';
|
import 'package:managerapi/api.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
class MultiStringInputContainer extends StatelessWidget {
|
class MultiStringContainer extends StatelessWidget {
|
||||||
final Color color;
|
final Color color;
|
||||||
final String label;
|
final String label;
|
||||||
final String modalLabel;
|
final String modalLabel;
|
||||||
final List<TranslationDTO> initialValue;
|
final List<TranslationDTO> initialValue;
|
||||||
final Function onGetResult;
|
final Function onGetResult;
|
||||||
final int maxLines;
|
final int maxLines;
|
||||||
final bool isTitle;
|
const MultiStringContainer({
|
||||||
final List<ResourceType>? resourceTypes;
|
Key key,
|
||||||
final bool isHTML;
|
|
||||||
final double fontSize;
|
|
||||||
final bool isMandatory;
|
|
||||||
const MultiStringInputContainer({
|
|
||||||
Key? key,
|
|
||||||
this.color = kSecond,
|
this.color = kSecond,
|
||||||
required this.label,
|
this.label,
|
||||||
required this.modalLabel,
|
this.modalLabel,
|
||||||
required this.initialValue,
|
this.initialValue,
|
||||||
required this.onGetResult,
|
this.onGetResult,
|
||||||
required this.maxLines,
|
this.maxLines,
|
||||||
required this.isTitle,
|
|
||||||
this.resourceTypes = null,
|
|
||||||
this.isHTML = false,
|
|
||||||
this.fontSize = 25,
|
|
||||||
this.isMandatory = true,
|
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final appContext = Provider.of<AppContext>(context);
|
|
||||||
ManagerAppContext managerAppContext = appContext.getContext();
|
|
||||||
|
|
||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
return Container(
|
return Container(
|
||||||
@ -48,13 +32,7 @@ class MultiStringInputContainer extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Align(
|
Align(
|
||||||
alignment: AlignmentDirectional.centerStart,
|
alignment: AlignmentDirectional.centerStart,
|
||||||
child: AutoSizeText(
|
child: Text(label, style: TextStyle(fontSize: 25, fontWeight: FontWeight.w300))
|
||||||
label,
|
|
||||||
style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.w300),
|
|
||||||
maxLines: 2,
|
|
||||||
maxFontSize: fontSize,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(10.0),
|
padding: const EdgeInsets.all(10.0),
|
||||||
@ -62,28 +40,14 @@ class MultiStringInputContainer extends StatelessWidget {
|
|||||||
width: size.width *0.15,
|
width: size.width *0.15,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
List<TranslationDTO> newValues = <TranslationDTO>[];
|
List<TranslationDTO> newValues = new List<TranslationDTO>();
|
||||||
|
// Make a copy
|
||||||
List<TranslationDTO> initials = initialValue;
|
initialValue.forEach((value) {
|
||||||
|
newValues.add(TranslationDTO.fromJson(jsonDecode(jsonEncode(value))));
|
||||||
managerAppContext.selectedConfiguration!.languages!.forEach((value) {
|
|
||||||
if(initials.map((iv) => iv.language).contains(value)) {
|
|
||||||
newValues.add(TranslationDTO.fromJson(jsonDecode(jsonEncode(initials.firstWhere((element) => element.language == value)))!)!);
|
|
||||||
} else {
|
|
||||||
// New language
|
|
||||||
newValues.add(TranslationDTO(language: value, value: ""));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
showMultiStringInput(label, modalLabel, initialValue, newValues, onGetResult, maxLines, context);
|
||||||
if(isHTML) {
|
|
||||||
showMultiStringInputHTML(label, modalLabel, isTitle, initials, newValues, onGetResult, maxLines, resourceTypes, context, isMandatory);
|
|
||||||
} else {
|
|
||||||
showMultiStringInput(label, modalLabel, isTitle, initials, newValues, onGetResult, maxLines, resourceTypes, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
constraints: BoxConstraints(maxHeight: 60),
|
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: color,
|
color: color,
|
||||||
borderRadius: BorderRadius.circular(50),
|
borderRadius: BorderRadius.circular(50),
|
||||||
@ -92,7 +56,7 @@ class MultiStringInputContainer extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.only(left: 5, right: 5, top: 15, bottom: 15),
|
padding: const EdgeInsets.only(left: 5, right: 5, top: 15, bottom: 15),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: AutoSizeText(
|
child: AutoSizeText(
|
||||||
resourceTypes == null ? "Changer traductions" : "Changer ressources",
|
"Changer les traductions",
|
||||||
style: TextStyle(color: kWhite),
|
style: TextStyle(color: kWhite),
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,132 +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 AlertDialog(
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
|
||||||
),
|
|
||||||
title: Center(child: Text(modalLabel)),
|
|
||||||
content: SingleChildScrollView(
|
|
||||||
child: TranslationInputContainer(isTitle: isTitle, values: values, newValues: newValues, onGetResult: onGetResult, maxLines: maxLines, resourceTypes: resourceTypes)
|
|
||||||
),
|
|
||||||
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)) {
|
|
||||||
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 AlertDialog(
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(20.0))
|
|
||||||
),
|
|
||||||
title: Center(child: Text(modalLabel)),
|
|
||||||
content: SingleChildScrollView(
|
|
||||||
child: TranslationInputAndResourceContainer(isTitle: isTitle, values: values, newValues: newValues, onGetResult: onGetResult, maxLines: maxLines, resourceTypes: resourceTypes)
|
|
||||||
),
|
|
||||||
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)) {
|
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,63 +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 = 25,
|
|
||||||
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: 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: 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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,147 +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<PDFFileDTO> initialValue;
|
|
||||||
final ValueChanged<List<PDFFileDTO>> onChanged;
|
|
||||||
PDFFileInputContainer({
|
|
||||||
Key? key,
|
|
||||||
this.color = kSecond,
|
|
||||||
required this.label,
|
|
||||||
required this.initialValue,
|
|
||||||
required this.onChanged,
|
|
||||||
}) : 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: 25, fontWeight: FontWeight.w300))
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Container(
|
|
||||||
width: size.width *0.15,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () {
|
|
||||||
List<PDFFileDTO> newValues = <PDFFileDTO>[];
|
|
||||||
List<PDFFileDTO> 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<PDFFileDTO> values, List<PDFFileDTO> 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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,190 +0,0 @@
|
|||||||
import 'package:auto_size_text/auto_size_text.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:manager_app/Components/loading_common.dart';
|
|
||||||
import 'package:manager_app/Models/managerContext.dart';
|
|
||||||
import 'package:manager_app/app_context.dart';
|
|
||||||
import 'package:manager_app/constants.dart';
|
|
||||||
import 'package:manager_app/Screens/Resources/select_resource_modal.dart';
|
|
||||||
import 'package:manager_api_new/api.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
|
|
||||||
class ResourceInputContainer extends StatefulWidget {
|
|
||||||
final Color color;
|
|
||||||
final String label;
|
|
||||||
final String? initialValue;
|
|
||||||
final ValueChanged<ResourceDTO> onChanged;
|
|
||||||
final BoxFit imageFit;
|
|
||||||
final bool isSmall;
|
|
||||||
final double fontSize;
|
|
||||||
final List<ResourceType> inResourceTypes;
|
|
||||||
final bool isLanguageTab;
|
|
||||||
const ResourceInputContainer({
|
|
||||||
Key? key,
|
|
||||||
this.color = kSecond,
|
|
||||||
required this.label,
|
|
||||||
this.initialValue,
|
|
||||||
required this.onChanged,
|
|
||||||
this.imageFit = BoxFit.cover,
|
|
||||||
this.isSmall = false,
|
|
||||||
this.fontSize = 25,
|
|
||||||
this.inResourceTypes = const [ResourceType.Image, ResourceType.ImageUrl],
|
|
||||||
this.isLanguageTab = false
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_ResourceInputContainerState createState() => _ResourceInputContainerState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ResourceInputContainerState extends State<ResourceInputContainer> {
|
|
||||||
String? resourceIdToShow;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
resourceIdToShow = widget.initialValue;
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
if(widget.isLanguageTab) {
|
|
||||||
resourceIdToShow = widget.initialValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Align(
|
|
||||||
alignment: AlignmentDirectional.centerStart,
|
|
||||||
child: AutoSizeText(
|
|
||||||
widget.label,
|
|
||||||
style: TextStyle(fontSize: widget.fontSize, fontWeight: FontWeight.w300),
|
|
||||||
maxLines: 2,
|
|
||||||
maxFontSize: widget.fontSize,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
//color: widget.isSmall ? Colors.cyanAccent: Colors.red,
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.only(left: widget.isSmall ? 5 : 10, top: 10, bottom: 10),
|
|
||||||
child: Container(
|
|
||||||
width: 90,
|
|
||||||
height: 90,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: () async {
|
|
||||||
ResourceDTO? result = await showSelectResourceModal(
|
|
||||||
"Sélectionner une ressource",
|
|
||||||
1,
|
|
||||||
widget.inResourceTypes,
|
|
||||||
context,
|
|
||||||
true, // IS SELECT
|
|
||||||
true, // IS ADD FALSE only for geopoint for now
|
|
||||||
true // IS REMOVE BUTTON
|
|
||||||
);
|
|
||||||
|
|
||||||
if (result != null) {
|
|
||||||
setState(() {
|
|
||||||
resourceIdToShow = result.id != null ? result.id : null;
|
|
||||||
});
|
|
||||||
widget.onChanged(result);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: getElement(widget.initialValue, context, widget.isSmall),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getElement(String? initialValue, BuildContext context, bool isSmall) {
|
|
||||||
if (resourceIdToShow != null) {
|
|
||||||
Size size = MediaQuery.of(context).size;
|
|
||||||
final appContext = Provider.of<AppContext>(context);
|
|
||||||
return FutureBuilder(
|
|
||||||
future: getResource(resourceIdToShow!, appContext),
|
|
||||||
builder: (context, AsyncSnapshot<dynamic> snapshot) {
|
|
||||||
if (snapshot.connectionState == ConnectionState.done) {
|
|
||||||
if (snapshot.data != null) {
|
|
||||||
ResourceDTO resourceDTO = snapshot.data!;
|
|
||||||
return Container(
|
|
||||||
decoration: boxDecoration(snapshot.data, appContext),
|
|
||||||
child: Center(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Text(resourceDTO.type == ResourceType.Image || resourceDTO.type == ResourceType.ImageUrl ? "" : resourceDTO.label!),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Center(
|
|
||||||
child: Container(
|
|
||||||
decoration: boxDecoration(null, appContext),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Text("Aucune ressource"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (snapshot.connectionState == ConnectionState.none) {
|
|
||||||
return Text("No data");
|
|
||||||
} else {
|
|
||||||
return Center(
|
|
||||||
child: Container(
|
|
||||||
height: size.height * 0.1,
|
|
||||||
child: LoadingCommon()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: widget.color,
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(left: 5, right: 5, top: 15, bottom: 15),
|
|
||||||
child: Center(
|
|
||||||
child: AutoSizeText(
|
|
||||||
"Choisir",
|
|
||||||
style: TextStyle(color: kWhite),
|
|
||||||
maxLines: 1,
|
|
||||||
)
|
|
||||||
),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<ResourceDTO?> getResource(String resourceIdToShow, dynamic appContext) async {
|
|
||||||
ResourceDTO? resource = await (appContext.getContext() as ManagerAppContext).clientAPI!.resourceApi!.resourceGetDetail(resourceIdToShow);
|
|
||||||
return resource;
|
|
||||||
}
|
|
||||||
|
|
||||||
boxDecoration(ResourceDTO? resourceDTO, AppContext appContext) {
|
|
||||||
return BoxDecoration(
|
|
||||||
shape: BoxShape.rectangle,
|
|
||||||
color: kWhite,
|
|
||||||
borderRadius: BorderRadius.circular(30.0),
|
|
||||||
image: resourceDTO != null ? resourceDTO.type != null && (resourceDTO.type == ResourceType.Image || resourceDTO.type == ResourceType.ImageUrl)? new DecorationImage(
|
|
||||||
fit: widget.imageFit,
|
|
||||||
image: new NetworkImage(
|
|
||||||
resourceDTO.url!, // TODO handle multiple type of content
|
|
||||||
),
|
|
||||||
) : null : null,
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
spreadRadius: 0.5,
|
|
||||||
blurRadius: 1,
|
|
||||||
offset: Offset(0, 1.5), // changes position of shadow
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -2,19 +2,19 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/material.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/Components/upload_online_resources_container.dart';
|
||||||
import 'package:manager_app/constants.dart';
|
import 'package:manager_app/constants.dart';
|
||||||
import 'package:manager_api_new/api.dart';
|
import 'package:managerapi/api.dart';
|
||||||
class ResourceTab extends StatefulWidget {
|
class ResourceTab extends StatefulWidget {
|
||||||
final ResourceDTO resourceDTO;
|
final ResourceDTO resourceDTO;
|
||||||
final Function onFileUpload;
|
final Function onFileUpload;
|
||||||
final Function onFileUploadWeb;
|
final Function onFileUploadWeb;
|
||||||
const ResourceTab({
|
const ResourceTab({
|
||||||
Key? key,
|
Key key,
|
||||||
required this.resourceDTO,
|
this.resourceDTO,
|
||||||
required this.onFileUpload,
|
this.onFileUpload,
|
||||||
required this.onFileUploadWeb,
|
this.onFileUploadWeb,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -22,16 +22,17 @@ class ResourceTab extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _ResourceTabState extends State<ResourceTab> with SingleTickerProviderStateMixin {
|
class _ResourceTabState extends State<ResourceTab> with SingleTickerProviderStateMixin {
|
||||||
TabController? _tabController;
|
TabController _tabController;
|
||||||
List<Tab> tabsToShow = <Tab>[];
|
List<Tab> tabsToShow = new List<Tab>();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
tabsToShow.add(new Tab(text: "Local"));
|
tabsToShow.add(new Tab(text: "Image local"));
|
||||||
tabsToShow.add(new Tab(text: "En ligne"));
|
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 = new TabController(length: 3, vsync: this);
|
||||||
//_tabController!.addListener(_handleTabSelection);
|
_tabController.addListener(_handleTabSelection);
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
@ -63,45 +64,45 @@ class _ResourceTabState extends State<ResourceTab> with SingleTickerProviderStat
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void _handleTabSelection() {
|
void _handleTabSelection() {
|
||||||
switch(_tabController!.index) {
|
switch(_tabController.index) {
|
||||||
case 0:
|
case 0:
|
||||||
setState(() {
|
setState(() {
|
||||||
widget.resourceDTO.url = null;
|
widget.resourceDTO.data = null;
|
||||||
widget.resourceDTO.type = ResourceType.Image;
|
widget.resourceDTO.type = ResourceType.image;
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
setState(() {
|
setState(() {
|
||||||
widget.resourceDTO.url = null;
|
widget.resourceDTO.data = null;
|
||||||
widget.resourceDTO.type = ResourceType.ImageUrl;
|
widget.resourceDTO.type = ResourceType.imageUrl;
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
setState(() {
|
setState(() {
|
||||||
widget.resourceDTO.url = null;
|
widget.resourceDTO.data = null;
|
||||||
widget.resourceDTO.type = ResourceType.Audio;
|
widget.resourceDTO.type = ResourceType.videoUrl;
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getContent(ResourceDTO resourceDTO, Function onFileUpload, Function onFileUploadWeb) {
|
getContent(ResourceDTO resourceDTO, Function onFileUpload, Function onFileUploadWeb) {
|
||||||
List<Widget> tabsToShow = <Widget>[];
|
List<Widget> tabsToShow = new List<Widget>();
|
||||||
|
|
||||||
// Local Image
|
// Local Image
|
||||||
tabsToShow.add(
|
tabsToShow.add(
|
||||||
new Padding(
|
new Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
|
||||||
child: UploadContentContainer(
|
child: UploadImageContainer(
|
||||||
onChanged: (List<File>? files) {
|
onChanged: (List<File> files) {
|
||||||
onFileUpload(files);
|
onFileUpload(files);
|
||||||
resourceDTO.type = ResourceType.Image;
|
resourceDTO.type = ResourceType.image;
|
||||||
},
|
},
|
||||||
onChangedWeb: (List<PlatformFile>? files) {
|
onChangedWeb: (List<PlatformFile> files) {
|
||||||
onFileUploadWeb(files);
|
onFileUploadWeb(files);
|
||||||
resourceDTO.type = ResourceType.Image;
|
resourceDTO.type = ResourceType.image;
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -120,40 +121,6 @@ getContent(ResourceDTO resourceDTO, Function onFileUpload, Function onFileUpload
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// 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
|
// Online Video
|
||||||
tabsToShow.add(
|
tabsToShow.add(
|
||||||
new Padding(
|
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;
|
return tabsToShow;
|
||||||
}
|
}
|
||||||
@ -1,24 +1,23 @@
|
|||||||
import 'package:auto_size_text/auto_size_text.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:manager_app/constants.dart';
|
import 'package:manager_app/constants.dart';
|
||||||
|
|
||||||
class RoundedButton extends StatelessWidget {
|
class RoundedButton extends StatelessWidget {
|
||||||
final String text;
|
final String text;
|
||||||
final Function press;
|
final Function press;
|
||||||
final IconData? icon;
|
final IconData icon;
|
||||||
final Color color, textColor;
|
final Color color, textColor;
|
||||||
final double fontSize;
|
final double fontSize;
|
||||||
final double? vertical;
|
final int vertical;
|
||||||
final double? horizontal;
|
final int horizontal;
|
||||||
|
|
||||||
const RoundedButton({
|
const RoundedButton({
|
||||||
Key? key,
|
Key key,
|
||||||
required this.text,
|
this.text,
|
||||||
required this.press,
|
this.press,
|
||||||
this.icon,
|
this.icon,
|
||||||
this.color = kPrimaryColor,
|
this.color = kPrimaryColor,
|
||||||
this.textColor = kWhite,
|
this.textColor = kWhite,
|
||||||
required this.fontSize,
|
this.fontSize,
|
||||||
this.vertical,
|
this.vertical,
|
||||||
this.horizontal
|
this.horizontal
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@ -28,7 +27,7 @@ class RoundedButton extends StatelessWidget {
|
|||||||
//Size size = MediaQuery.of(context).size;
|
//Size size = MediaQuery.of(context).size;
|
||||||
return TextButton(
|
return TextButton(
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
padding: MaterialStateProperty.resolveWith((states) => EdgeInsets.symmetric(vertical: this.vertical != null ? this.vertical! : 25, horizontal: this.horizontal != null ? this.horizontal!: (icon == null ? 85 : 30))),
|
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),
|
backgroundColor: MaterialStateColor.resolveWith((states) => color),
|
||||||
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||||
RoundedRectangleBorder(
|
RoundedRectangleBorder(
|
||||||
@ -50,12 +49,9 @@ class RoundedButton extends StatelessWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
Center(
|
Center(
|
||||||
child: AutoSizeText(
|
child: Text(
|
||||||
text,
|
text,
|
||||||
style: new TextStyle(color: textColor, fontSize: fontSize, fontWeight: FontWeight.w400),
|
style: new TextStyle(color: textColor, fontSize: fontSize, fontWeight: FontWeight.w400),
|
||||||
maxLines: 2,
|
|
||||||
maxFontSize: fontSize,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
@ -69,11 +65,9 @@ class RoundedButton extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return AutoSizeText(
|
return Text(
|
||||||
text,
|
text,
|
||||||
style: new TextStyle(color: textColor, fontSize: fontSize, fontWeight: FontWeight.w400),
|
style: new TextStyle(color: textColor, fontSize: fontSize, fontWeight: FontWeight.w400),
|
||||||
maxLines: 2,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,33 +1,26 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:manager_app/Components/text_field_container.dart';
|
import 'package:manager_app/Components/text_field_container.dart';
|
||||||
import 'package:manager_app/constants.dart';
|
import 'package:manager_app/constants.dart';
|
||||||
|
|
||||||
class RoundedInputField extends StatelessWidget {
|
class RoundedInputField extends StatelessWidget {
|
||||||
final String? hintText;
|
final String hintText;
|
||||||
final IconData? icon;
|
final IconData icon;
|
||||||
final ValueChanged<String> onChanged;
|
final ValueChanged<String> onChanged;
|
||||||
final String? initialValue;
|
final String initialValue;
|
||||||
final Color color, textColor, iconColor;
|
final Color color, textColor, iconColor;
|
||||||
final int? maxLength;
|
final int maxLength;
|
||||||
final bool isEmail;
|
final bool isEmail;
|
||||||
final double fontSize;
|
|
||||||
final String? autofill;
|
|
||||||
final bool isInt;
|
|
||||||
const RoundedInputField({
|
const RoundedInputField({
|
||||||
Key? key,
|
Key key,
|
||||||
this.hintText,
|
this.hintText,
|
||||||
this.initialValue,
|
this.initialValue,
|
||||||
this.icon,
|
this.icon,
|
||||||
this.color = kSecond,
|
this.color = kSecond,
|
||||||
this.textColor = kBlack,
|
this.textColor = kBlack,
|
||||||
this.iconColor = kPrimaryColor,
|
this.iconColor = kPrimaryColor,
|
||||||
required this.onChanged,
|
this.onChanged,
|
||||||
this.maxLength, // 50
|
this.maxLength, // 50
|
||||||
this.isEmail = false,
|
this.isEmail = false
|
||||||
this.fontSize = 20,
|
|
||||||
this.autofill,
|
|
||||||
this.isInt = false
|
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -39,19 +32,15 @@ class RoundedInputField extends StatelessWidget {
|
|||||||
initialValue: initialValue,
|
initialValue: initialValue,
|
||||||
cursorColor: textColor,
|
cursorColor: textColor,
|
||||||
maxLength: maxLength,
|
maxLength: maxLength,
|
||||||
autofillHints: autofill != null ? [autofill!] : [],
|
keyboardType: isEmail ? TextInputType.emailAddress : TextInputType.text,
|
||||||
keyboardType: isEmail ? TextInputType.emailAddress : isInt ? TextInputType.number : TextInputType.text,
|
style: TextStyle(fontSize: 20, color: textColor),
|
||||||
inputFormatters: !isInt ? [] : <TextInputFormatter>[
|
|
||||||
FilteringTextInputFormatter.digitsOnly
|
|
||||||
],
|
|
||||||
style: TextStyle(fontSize: fontSize, color: textColor),
|
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
icon: icon != null ? Icon(
|
icon: icon != null ? Icon(
|
||||||
icon,
|
icon,
|
||||||
color: iconColor,
|
color: iconColor,
|
||||||
): null,
|
): null,
|
||||||
hintText: hintText,
|
hintText: hintText,
|
||||||
hintStyle: TextStyle(fontSize: fontSize, color: textColor, fontWeight: FontWeight.w400),
|
hintStyle: TextStyle(fontSize: 20.0, color: textColor),
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|||||||
@ -6,9 +6,9 @@ class RoundedPasswordField extends StatefulWidget {
|
|||||||
final ValueChanged<String> onChanged;
|
final ValueChanged<String> onChanged;
|
||||||
final String initialValue;
|
final String initialValue;
|
||||||
const RoundedPasswordField({
|
const RoundedPasswordField({
|
||||||
Key? key,
|
Key key,
|
||||||
required this.onChanged,
|
this.onChanged,
|
||||||
required this.initialValue
|
this.initialValue,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -25,12 +25,11 @@ class _RoundedPasswordFieldState extends State<RoundedPasswordField> {
|
|||||||
obscureText: isVisible,
|
obscureText: isVisible,
|
||||||
onChanged: widget.onChanged,
|
onChanged: widget.onChanged,
|
||||||
initialValue: widget.initialValue,
|
initialValue: widget.initialValue,
|
||||||
autofillHints: [AutofillHints.password],
|
|
||||||
cursorColor: kPrimaryColor,
|
cursorColor: kPrimaryColor,
|
||||||
style: TextStyle(fontSize: 20, color: kBlack),
|
style: TextStyle(fontSize: 20, color: kBlack),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: "Mot de passe",
|
hintText: "Password",
|
||||||
hintStyle: TextStyle(fontSize: 20.0, color: kBlack, fontWeight: FontWeight.normal),
|
hintStyle: TextStyle(fontSize: 20.0, color: kBlack),
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.lock,
|
Icons.lock,
|
||||||
color: kPrimaryColor,
|
color: kPrimaryColor,
|
||||||
|
|||||||
@ -1,89 +0,0 @@
|
|||||||
import 'package:auto_size_text/auto_size_text.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:manager_app/constants.dart';
|
|
||||||
|
|
||||||
class SingleSelectContainer extends StatefulWidget {
|
|
||||||
final Color? color;
|
|
||||||
final String label;
|
|
||||||
final String? initialValue;
|
|
||||||
final List<String> inputValues;
|
|
||||||
final ValueChanged<String>? onChanged;
|
|
||||||
final double fontSize;
|
|
||||||
final double fontSizeText;
|
|
||||||
const SingleSelectContainer({
|
|
||||||
Key? key,
|
|
||||||
this.color = kSecond,
|
|
||||||
required this.label,
|
|
||||||
this.initialValue = "",
|
|
||||||
required this.inputValues,
|
|
||||||
this.onChanged,
|
|
||||||
this.fontSize = 25,
|
|
||||||
this.fontSizeText = 20,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
_SingleSelectContainerState createState() => _SingleSelectContainerState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _SingleSelectContainerState extends State<SingleSelectContainer> {
|
|
||||||
String? selectedValue;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
selectedValue = 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: AutoSizeText(
|
|
||||||
widget.label,
|
|
||||||
style: TextStyle(fontSize: widget.fontSize, fontWeight: FontWeight.w300),
|
|
||||||
maxLines: 2,
|
|
||||||
maxFontSize: widget.fontSize,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Container(
|
|
||||||
width: size.width *0.15,
|
|
||||||
constraints: BoxConstraints(maxWidth: 175),
|
|
||||||
child: DropdownButton<String>(
|
|
||||||
value: selectedValue,
|
|
||||||
icon: const Icon(Icons.arrow_downward),
|
|
||||||
iconSize: 24,
|
|
||||||
elevation: 16,
|
|
||||||
style: TextStyle(color: widget.color!),
|
|
||||||
underline: Container(
|
|
||||||
height: 2,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
),
|
|
||||||
onChanged: (String? newValue) {
|
|
||||||
setState(() {
|
|
||||||
selectedValue = newValue!;
|
|
||||||
widget.onChanged!(selectedValue!);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
items: widget.inputValues.map<DropdownMenuItem<String>>((String value) {
|
|
||||||
return DropdownMenuItem<String>(
|
|
||||||
value: value,
|
|
||||||
child: Text(value, style: TextStyle(fontSize: 20, fontWeight: FontWeight.w400, color: widget.color)),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -9,13 +9,13 @@ class SliderInputContainer extends StatefulWidget {
|
|||||||
final int max;
|
final int max;
|
||||||
final ValueChanged<double> onChanged;
|
final ValueChanged<double> onChanged;
|
||||||
const SliderInputContainer({
|
const SliderInputContainer({
|
||||||
Key? key,
|
Key key,
|
||||||
this.color = kSecond,
|
this.color = kSecond,
|
||||||
required this.label,
|
this.label,
|
||||||
required this.initialValue,
|
this.initialValue,
|
||||||
required this.min,
|
this.min,
|
||||||
required this.max,
|
this.max,
|
||||||
required this.onChanged,
|
this.onChanged,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -23,7 +23,7 @@ class SliderInputContainer extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SliderInputContainerState extends State<SliderInputContainer> {
|
class _SliderInputContainerState extends State<SliderInputContainer> {
|
||||||
double? currentValue;
|
double currentValue;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -42,11 +42,8 @@ class _SliderInputContainerState extends State<SliderInputContainer> {
|
|||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(10.0),
|
padding: const EdgeInsets.all(10.0),
|
||||||
child: SliderTheme(
|
|
||||||
data: SliderThemeData(
|
|
||||||
showValueIndicator: ShowValueIndicator.always),
|
|
||||||
child: Slider(
|
child: Slider(
|
||||||
value: currentValue!,
|
value: currentValue,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() => currentValue = value);
|
setState(() => currentValue = value);
|
||||||
widget.onChanged(value);
|
widget.onChanged(value);
|
||||||
@ -58,7 +55,6 @@ class _SliderInputContainerState extends State<SliderInputContainer> {
|
|||||||
activeColor: widget.color,
|
activeColor: widget.color,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,56 +1,43 @@
|
|||||||
import 'package:auto_size_text/auto_size_text.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:manager_app/Components/rounded_input_field.dart';
|
import 'package:manager_app/Components/rounded_input_field.dart';
|
||||||
import 'package:manager_app/constants.dart';
|
import 'package:manager_app/constants.dart';
|
||||||
|
|
||||||
class StringInputContainer extends StatelessWidget {
|
class StringInputContainer extends StatelessWidget {
|
||||||
final Color? color;
|
final Color color;
|
||||||
final String label;
|
final String label;
|
||||||
final String? initialValue;
|
final String initialValue;
|
||||||
final ValueChanged<String> onChanged;
|
final ValueChanged<String> onChanged;
|
||||||
final bool isUrl;
|
final bool isUrl;
|
||||||
final bool isSmall;
|
final bool isSmall;
|
||||||
final int maxLength;
|
final int maxLength;
|
||||||
final double fontSize;
|
|
||||||
final double fontSizeText;
|
|
||||||
const StringInputContainer({
|
const StringInputContainer({
|
||||||
Key? key,
|
Key key,
|
||||||
this.color = kSecond,
|
this.color = kSecond,
|
||||||
required this.label,
|
this.label,
|
||||||
this.initialValue = "",
|
this.initialValue,
|
||||||
required this.onChanged,
|
this.onChanged,
|
||||||
this.isUrl = false,
|
this.isUrl = false,
|
||||||
this.isSmall = false,
|
this.isSmall = false,
|
||||||
this.maxLength = 50,
|
this.maxLength = 50,
|
||||||
this.fontSize = 25,
|
|
||||||
this.fontSizeText = 20,
|
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
Size size = MediaQuery.of(context).size;
|
Size size = MediaQuery.of(context).size;
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Align(
|
Align(
|
||||||
alignment: AlignmentDirectional.centerStart,
|
alignment: AlignmentDirectional.centerStart,
|
||||||
child: AutoSizeText(
|
child: Text(label, style: TextStyle(fontSize: 25, fontWeight: FontWeight.w300))
|
||||||
label,
|
|
||||||
style: TextStyle(fontSize: fontSize, fontWeight: FontWeight.w300),
|
|
||||||
maxLines: 2,
|
|
||||||
maxFontSize: fontSize,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(10.0),
|
||||||
child: Container(
|
child: Container(
|
||||||
width: isUrl ? size.width *0.6 : isSmall ? size.width *0.1 : size.width *0.25,
|
width: isUrl ? size.width *0.6 : isSmall ? size.width *0.1 : size.width *0.2,
|
||||||
child: RoundedInputField(
|
child: RoundedInputField(
|
||||||
color: color!,
|
color: color,
|
||||||
textColor: kBlack,
|
textColor: kBlack,
|
||||||
fontSize: fontSizeText,
|
|
||||||
initialValue: initialValue,
|
initialValue: initialValue,
|
||||||
onChanged: onChanged,
|
onChanged: onChanged,
|
||||||
maxLength: maxLength,
|
maxLength: maxLength,
|
||||||
|
|||||||
@ -5,8 +5,8 @@ class TextFieldContainer extends StatelessWidget {
|
|||||||
final Widget child;
|
final Widget child;
|
||||||
final Color color;
|
final Color color;
|
||||||
const TextFieldContainer({
|
const TextFieldContainer({
|
||||||
Key? key,
|
Key key,
|
||||||
required this.child,
|
this.child,
|
||||||
this.color = kSecond,
|
this.color = kSecond,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
|||||||
@ -9,13 +9,13 @@ class TextFormInputContainer extends StatelessWidget {
|
|||||||
final int maxLines;
|
final int maxLines;
|
||||||
final ValueChanged<String> onChanged;
|
final ValueChanged<String> onChanged;
|
||||||
const TextFormInputContainer({
|
const TextFormInputContainer({
|
||||||
Key? key,
|
Key key,
|
||||||
this.color = kSecond,
|
this.color = kSecond,
|
||||||
required this.label,
|
this.label,
|
||||||
required this.initialValue,
|
this.initialValue,
|
||||||
required this.isTitle,
|
this.isTitle,
|
||||||
this.maxLines = 5,
|
this.maxLines = 5,
|
||||||
required this.onChanged
|
this.onChanged
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@ -1,255 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:manager_api_new/api.dart';
|
|
||||||
import 'package:manager_app/Components/audio_input_container.dart';
|
|
||||||
import 'package:manager_app/Components/resource_input_container.dart';
|
|
||||||
import 'package:manager_app/app_context.dart';
|
|
||||||
import 'package:manager_app/constants.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:quill_html_editor/quill_html_editor.dart';
|
|
||||||
|
|
||||||
import 'flag_decoration.dart';
|
|
||||||
|
|
||||||
class _TranslationInputAndResourceContainerState extends State<TranslationInputAndResourceContainer> with TickerProviderStateMixin {
|
|
||||||
TabController? _tabController;
|
|
||||||
QuillEditorController controllerQuill = QuillEditorController();
|
|
||||||
ValueNotifier<String?>? currentLanguage;
|
|
||||||
bool isInit = false;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
|
|
||||||
_tabController = new TabController(length: widget.newValues.length, vsync: this);
|
|
||||||
currentLanguage = ValueNotifier<String>(widget.newValues.first.language!);
|
|
||||||
|
|
||||||
controllerQuill.onEditorLoaded(() {
|
|
||||||
print("onEditorLoaded");
|
|
||||||
isInit = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
Future.delayed(Duration(milliseconds: 500), () {
|
|
||||||
print("Future.delayed");
|
|
||||||
controllerQuill.clear();
|
|
||||||
controllerQuill.insertText(widget.newValues[_tabController!.index].value!);
|
|
||||||
isInit = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
controllerQuill.onTextChanged((p0) async {
|
|
||||||
var plainText = await controllerQuill.getPlainText();
|
|
||||||
if(widget.isTitle) {
|
|
||||||
if(plainText.length > kTitleMaxLength) {
|
|
||||||
print("to much text au dessus");
|
|
||||||
controllerQuill.undo();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(plainText.length > kDescriptionMaxLength) {
|
|
||||||
print("to much text description au dessus");
|
|
||||||
controllerQuill.undo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
_tabController!.addListener(() {
|
|
||||||
if (!_tabController!.indexIsChanging) {
|
|
||||||
setState(() {
|
|
||||||
currentLanguage!.value = widget.newValues[_tabController!.index].language;
|
|
||||||
//if(widget.resourceTypes == null) {
|
|
||||||
print("insert try without ress");
|
|
||||||
print(widget.newValues[_tabController!.index].value!);
|
|
||||||
controllerQuill.clear();
|
|
||||||
controllerQuill.insertText(widget.newValues[_tabController!.index].value!);
|
|
||||||
//}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
super.dispose();
|
|
||||||
_tabController!.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final customToolBarList = widget.isTitle ? [
|
|
||||||
ToolBarStyle.bold,
|
|
||||||
ToolBarStyle.italic,
|
|
||||||
ToolBarStyle.color,
|
|
||||||
ToolBarStyle.background,
|
|
||||||
ToolBarStyle.clean
|
|
||||||
] : [
|
|
||||||
ToolBarStyle.bold,
|
|
||||||
ToolBarStyle.italic,
|
|
||||||
ToolBarStyle.color,
|
|
||||||
ToolBarStyle.background,
|
|
||||||
ToolBarStyle.listBullet,
|
|
||||||
ToolBarStyle.listOrdered,
|
|
||||||
ToolBarStyle.clean
|
|
||||||
];
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
height: widget.isTitle ? MediaQuery.of(context).size.height *0.45 : MediaQuery.of(context).size.height *0.5,
|
|
||||||
//color: Colors.orange,
|
|
||||||
width: MediaQuery.of(context).size.width *0.7,
|
|
||||||
constraints: BoxConstraints(
|
|
||||||
minHeight: 300,
|
|
||||||
minWidth: 300
|
|
||||||
),
|
|
||||||
child: DefaultTabController(
|
|
||||||
length: widget.newValues.length,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
RotatedBox(
|
|
||||||
quarterTurns: 0, // Can be used to test vertical tab in case of smaller screen
|
|
||||||
child: TabBar(
|
|
||||||
indicatorColor: kPrimaryColor,
|
|
||||||
//overlayColor: MaterialStateProperty().c,
|
|
||||||
labelColor: kPrimaryColor,
|
|
||||||
unselectedLabelColor: Colors.black,
|
|
||||||
controller: _tabController,
|
|
||||||
tabs: widget.newValues.map((v) => Tab(icon: FlagDecoration(language: v.language!))).toList(), // text: v.language!.toUpperCase(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
getTranslation(context, Provider.of<AppContext>(context), controllerQuill, customToolBarList, widget.isTitle, widget.resourceTypes, widget.newValues, currentLanguage!)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTranslation(BuildContext context, AppContext appContext, QuillEditorController controllerQuill, List<ToolBarStyle> customToolBarList, bool isTitle, List<ResourceType>? resourceTypes, List<TranslationAndResourceDTO> newValues, ValueNotifier<String?> currentLanguage) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.all(6.0),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(left: 8.0),
|
|
||||||
child: Container(
|
|
||||||
width: MediaQuery.of(context).size.width *0.7,
|
|
||||||
//color: Colors.blueAccent,
|
|
||||||
height: widget.isTitle ? MediaQuery.of(context).size.height *0.34 : MediaQuery.of(context).size.height *0.37,
|
|
||||||
child: resourceTypes != null ?
|
|
||||||
Column(
|
|
||||||
children: [
|
|
||||||
ToolBar(
|
|
||||||
toolBarColor: kSecond,
|
|
||||||
activeIconColor: kPrimaryColor,
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
iconSize: 20,
|
|
||||||
toolBarConfig: customToolBarList,
|
|
||||||
controller: controllerQuill,
|
|
||||||
customButtons: [],
|
|
||||||
),
|
|
||||||
SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
height: widget.isTitle ? MediaQuery.of(context).size.height *0.13 : MediaQuery.of(context).size.height *0.2,
|
|
||||||
child: QuillHtmlEditor(
|
|
||||||
text: newValues.where((element) => element.language! == currentLanguage.value).first.value!,
|
|
||||||
hintText: '',
|
|
||||||
controller: controllerQuill,
|
|
||||||
minHeight: widget.isTitle ? 80 : 240,
|
|
||||||
/*textStyle: _editorTextStyle,
|
|
||||||
hintTextStyle: _hintTextStyle,*/
|
|
||||||
hintTextAlign: TextAlign.start,
|
|
||||||
padding: const EdgeInsets.only(left: 10, right: 10, top: 5),
|
|
||||||
hintTextPadding: EdgeInsets.zero,
|
|
||||||
backgroundColor: kBackgroundColor,
|
|
||||||
ensureVisible: true,
|
|
||||||
inputAction: widget.isTitle ? InputAction.send : InputAction.newline, // don't accept enter if title
|
|
||||||
//onFocusChanged: (hasFocus) => debugPrint('has focus $hasFocus'),
|
|
||||||
//onTextChanged: (text) => debugPrint('widget text change $text'),
|
|
||||||
onTextChanged: (value) {
|
|
||||||
if(isInit) {
|
|
||||||
newValues.where((element) => element.language! == currentLanguage.value).first.value = value;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onEditorCreated: () => debugPrint('Editor has been loaded'),
|
|
||||||
onEditorResized: (height) =>
|
|
||||||
debugPrint('Editor resized $height'),
|
|
||||||
onSelectionChanged: (sel) =>
|
|
||||||
debugPrint('${sel.index},${sel.length}'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
ValueListenableBuilder<String?>(
|
|
||||||
valueListenable: currentLanguage,
|
|
||||||
builder: (context, value, _) {
|
|
||||||
return ResourceInputContainer(
|
|
||||||
label: "Ressource à afficher :",
|
|
||||||
initialValue: newValues.where((element) => element.language! == value).first.resourceId,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
inResourceTypes: resourceTypes,
|
|
||||||
isLanguageTab: true,
|
|
||||||
onChanged: (ResourceDTO resource) {
|
|
||||||
setState(() {
|
|
||||||
if(resource.id == null) {
|
|
||||||
newValues.where((element) => element.language! == value).first.resourceId = null;
|
|
||||||
newValues.where((element) => element.language! == value).first.resourceUrl = null;
|
|
||||||
newValues.where((element) => element.language! == value).first.resourceType = null;
|
|
||||||
} else {
|
|
||||||
newValues.where((element) => element.language! == value).first.resourceId = resource.id;
|
|
||||||
newValues.where((element) => element.language! == value).first.resourceUrl = resource.url;
|
|
||||||
newValues.where((element) => element.language! == value).first.resourceType = resource.type;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
isSmall: true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
) :
|
|
||||||
Container(
|
|
||||||
width: 250,
|
|
||||||
height: 120,
|
|
||||||
child: ValueListenableBuilder<String?>(
|
|
||||||
valueListenable: currentLanguage,
|
|
||||||
builder: (context, value, _) {
|
|
||||||
return ResourceInputContainer(
|
|
||||||
label: "",
|
|
||||||
initialValue: newValues.where((element) => element.language! == value).first.resourceId,
|
|
||||||
inResourceTypes: widget.resourceTypes!,
|
|
||||||
onChanged: (ResourceDTO resource) {
|
|
||||||
newValues.where((element) => element.language! == value).first.value = resource.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return AudioInputContainer(
|
|
||||||
initialValue: newValues.where((element) => element.language! == value).first.value,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
onChanged: (ResourceDTO resource) {
|
|
||||||
newValues.where((element) => element.language! == value).first.value = resource.id;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TranslationInputAndResourceContainer extends StatefulWidget {
|
|
||||||
TranslationInputAndResourceContainer({
|
|
||||||
Key? key,
|
|
||||||
required this.isTitle,
|
|
||||||
required this.values,
|
|
||||||
required this.newValues,
|
|
||||||
required this.onGetResult,
|
|
||||||
required this.maxLines,
|
|
||||||
required this.resourceTypes,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
bool isTitle;
|
|
||||||
List<TranslationAndResourceDTO> values;
|
|
||||||
List<TranslationAndResourceDTO> newValues;
|
|
||||||
Function onGetResult;
|
|
||||||
int maxLines;
|
|
||||||
List<ResourceType>? resourceTypes;
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<TranslationInputAndResourceContainer> createState() => _TranslationInputAndResourceContainerState();
|
|
||||||
}
|
|
||||||
@ -1,279 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:manager_api_new/api.dart';
|
|
||||||
import 'package:manager_app/Components/audio_input_container.dart';
|
|
||||||
import 'package:manager_app/Components/resource_input_container.dart';
|
|
||||||
import 'package:manager_app/Components/rounded_button.dart';
|
|
||||||
import 'package:manager_app/app_context.dart';
|
|
||||||
import 'package:manager_app/constants.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:quill_html_editor/quill_html_editor.dart';
|
|
||||||
|
|
||||||
import 'flag_decoration.dart';
|
|
||||||
import 'message_notification.dart';
|
|
||||||
|
|
||||||
class _TranslationInputContainerState extends State<TranslationInputContainer> with TickerProviderStateMixin {
|
|
||||||
TabController? _tabController;
|
|
||||||
QuillEditorController controllerQuill = QuillEditorController();
|
|
||||||
ValueNotifier<String?>? currentLanguage;
|
|
||||||
bool isInit = false;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_tabController = new TabController(length: widget.newValues.length, vsync: this);
|
|
||||||
currentLanguage = ValueNotifier<String>(widget.newValues.first.language!);
|
|
||||||
|
|
||||||
controllerQuill.onEditorLoaded(() {
|
|
||||||
print("onEditorLoaded");
|
|
||||||
isInit = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
Future.delayed(Duration(milliseconds: 500), () {
|
|
||||||
print("Future.delayed");
|
|
||||||
controllerQuill.clear();
|
|
||||||
controllerQuill.insertText(widget.newValues[_tabController!.index].value!);
|
|
||||||
isInit = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
controllerQuill.onTextChanged((p0) async {
|
|
||||||
var plainText = await controllerQuill.getPlainText();
|
|
||||||
if(widget.isTitle) {
|
|
||||||
if(plainText.length > kTitleMaxLength) {
|
|
||||||
print("to much text au dessus");
|
|
||||||
controllerQuill.undo();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(plainText.length > kDescriptionMaxLength) {
|
|
||||||
print("to much text description au dessus");
|
|
||||||
controllerQuill.undo();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
_tabController!.addListener(() {
|
|
||||||
if (!_tabController!.indexIsChanging) {
|
|
||||||
setState(() {
|
|
||||||
currentLanguage!.value = widget.newValues[_tabController!.index].language;
|
|
||||||
if(widget.resourceTypes == null) {
|
|
||||||
print("insert try without ress");
|
|
||||||
print(widget.newValues[_tabController!.index].value!);
|
|
||||||
controllerQuill.clear();
|
|
||||||
controllerQuill.insertText(widget.newValues[_tabController!.index].value!);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
super.dispose();
|
|
||||||
_tabController!.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
getTranslation(BuildContext context, AppContext appContext, QuillEditorController controllerQuill, List<ToolBarStyle> customToolBarList, bool isTitle, List<ResourceType>? resourceTypes, List<TranslationDTO> newValues, ValueNotifier<String?> currentLanguage) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.all(6.0),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.only(left: 8.0),
|
|
||||||
child: Container(
|
|
||||||
width: MediaQuery.of(context).size.width *0.7,
|
|
||||||
height: widget.isTitle ? MediaQuery.of(context).size.height *0.25 : MediaQuery.of(context).size.height *0.4,
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
resourceTypes == null ?
|
|
||||||
Column(
|
|
||||||
children: [
|
|
||||||
ToolBar(
|
|
||||||
toolBarColor: kSecond,
|
|
||||||
activeIconColor: kPrimaryColor,
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
iconSize: 20,
|
|
||||||
toolBarConfig: customToolBarList,
|
|
||||||
controller: controllerQuill,
|
|
||||||
customButtons: [],
|
|
||||||
),
|
|
||||||
SingleChildScrollView(
|
|
||||||
child: Container(
|
|
||||||
height: widget.isTitle ? MediaQuery.of(context).size.height *0.13 : MediaQuery.of(context).size.height *0.35,
|
|
||||||
child: QuillHtmlEditor(
|
|
||||||
//text: newValues.where((element) => element.language! == currentLanguage.value).first.value!,
|
|
||||||
hintText: '',
|
|
||||||
controller: controllerQuill,
|
|
||||||
minHeight: widget.isTitle ? 80 : 240,
|
|
||||||
/*textStyle: _editorTextStyle,
|
|
||||||
hintTextStyle: _hintTextStyle,*/
|
|
||||||
hintTextAlign: TextAlign.start,
|
|
||||||
padding: const EdgeInsets.only(left: 10, right: 10, top: 5),
|
|
||||||
hintTextPadding: EdgeInsets.zero,
|
|
||||||
backgroundColor: kBackgroundColor,
|
|
||||||
ensureVisible: true,
|
|
||||||
inputAction: widget.isTitle ? InputAction.send : InputAction.newline, // don't accept enter if title
|
|
||||||
//onFocusChanged: (hasFocus) => debugPrint('has focus $hasFocus'),
|
|
||||||
//onTextChanged: (text) => debugPrint('widget text change $text'),
|
|
||||||
onTextChanged: (value) {
|
|
||||||
if(isInit) {
|
|
||||||
newValues.where((element) => element.language! == currentLanguage.value).first.value = value;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onEditorCreated: () => debugPrint('Editor has been loaded'),
|
|
||||||
onEditorResized: (height) =>
|
|
||||||
debugPrint('Editor resized $height'),
|
|
||||||
onSelectionChanged: (sel) =>
|
|
||||||
debugPrint('${sel.index},${sel.length}'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
/*HtmlEditor(
|
|
||||||
controller: controller,
|
|
||||||
htmlEditorOptions: HtmlEditorOptions(
|
|
||||||
hint: "Your text here...",
|
|
||||||
initialText: newValues.where((element) => element.language == language).first.value!,
|
|
||||||
shouldEnsureVisible: true,
|
|
||||||
),
|
|
||||||
htmlToolbarOptions: HtmlToolbarOptions(
|
|
||||||
toolbarPosition: ToolbarPosition.aboveEditor, //required to place toolbar anywhere!
|
|
||||||
//other options
|
|
||||||
),
|
|
||||||
otherOptions: OtherOptions(
|
|
||||||
height: 400,
|
|
||||||
),
|
|
||||||
)*/
|
|
||||||
/*TextFormInputContainer(
|
|
||||||
label: label,
|
|
||||||
color: kWhite,
|
|
||||||
isTitle: isTitle,
|
|
||||||
initialValue: newValues.where((element) => element.language == language).first.value!,
|
|
||||||
onChanged: (value) {
|
|
||||||
newValues.where((element) => element.language == language).first.value = value;
|
|
||||||
},
|
|
||||||
)*/ :
|
|
||||||
Container(
|
|
||||||
width: 250,
|
|
||||||
height: 120,
|
|
||||||
child: ValueListenableBuilder<String?>(
|
|
||||||
valueListenable: currentLanguage,
|
|
||||||
builder: (context, value, _) {
|
|
||||||
return ResourceInputContainer(
|
|
||||||
label: "",
|
|
||||||
initialValue: newValues.where((element) => element.language! == value).first.value,
|
|
||||||
inResourceTypes: widget.resourceTypes!,
|
|
||||||
onChanged: (ResourceDTO resource) {
|
|
||||||
newValues.where((element) => element.language! == value).first.value = resource.id;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
/*return AudioInputContainer(
|
|
||||||
//label: "Audio :",
|
|
||||||
initialValue: newValues.where((element) => element.language! == value).first.value,
|
|
||||||
color: kPrimaryColor,
|
|
||||||
onChanged: (ResourceDTO resource) {
|
|
||||||
newValues.where((element) => element.language! == value).first.value = resource.id;
|
|
||||||
},
|
|
||||||
);*/
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final customToolBarList = widget.isTitle ? [
|
|
||||||
ToolBarStyle.bold,
|
|
||||||
ToolBarStyle.italic,
|
|
||||||
ToolBarStyle.color,
|
|
||||||
ToolBarStyle.background,
|
|
||||||
ToolBarStyle.clean
|
|
||||||
] : [
|
|
||||||
ToolBarStyle.bold,
|
|
||||||
ToolBarStyle.italic,
|
|
||||||
ToolBarStyle.color,
|
|
||||||
ToolBarStyle.background,
|
|
||||||
ToolBarStyle.listBullet,
|
|
||||||
ToolBarStyle.listOrdered,
|
|
||||||
ToolBarStyle.clean
|
|
||||||
];
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
height: widget.isTitle ? MediaQuery.of(context).size.height *0.4 : MediaQuery.of(context).size.height *0.53,
|
|
||||||
width: MediaQuery.of(context).size.width *0.7,
|
|
||||||
constraints: BoxConstraints(
|
|
||||||
minHeight: 200,
|
|
||||||
minWidth: 300
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
DefaultTabController(
|
|
||||||
length: widget.newValues.length,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
RotatedBox(
|
|
||||||
quarterTurns: 0, // Can be used to test vertical tab in case of smaller screen
|
|
||||||
child: TabBar(
|
|
||||||
indicatorColor: kPrimaryColor,
|
|
||||||
//overlayColor: MaterialStateProperty().c,
|
|
||||||
labelColor: kPrimaryColor,
|
|
||||||
unselectedLabelColor: Colors.black,
|
|
||||||
controller: _tabController,
|
|
||||||
tabs: widget.newValues.map((v) => Tab(icon: FlagDecoration(language: v.language!))).toList(), // text: v.language!.toUpperCase(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
getTranslation(context, Provider.of<AppContext>(context), controllerQuill, customToolBarList, widget.isTitle, widget.resourceTypes, widget.newValues, currentLanguage!)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Center(
|
|
||||||
child: Container(
|
|
||||||
width: 370,
|
|
||||||
height: 70,
|
|
||||||
child: RoundedButton(
|
|
||||||
text: "Appliquer à toutes les langues",
|
|
||||||
icon: Icons.copy,
|
|
||||||
color: kSecond,
|
|
||||||
press: () async {
|
|
||||||
var plainText = await controllerQuill.getText();
|
|
||||||
widget.newValues.forEach((language) {
|
|
||||||
language.value = plainText;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
showNotification(kSuccess, kWhite, 'Le texte a été appliqué à toutes les langues', context, null);
|
|
||||||
},
|
|
||||||
fontSize: 20,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TranslationInputContainer extends StatefulWidget {
|
|
||||||
TranslationInputContainer({
|
|
||||||
Key? key,
|
|
||||||
required this.isTitle,
|
|
||||||
required this.values,
|
|
||||||
required this.newValues,
|
|
||||||
required this.onGetResult,
|
|
||||||
required this.maxLines,
|
|
||||||
required this.resourceTypes,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
bool isTitle;
|
|
||||||
List<TranslationDTO> values;
|
|
||||||
List<TranslationDTO> newValues;
|
|
||||||
Function onGetResult;
|
|
||||||
int maxLines;
|
|
||||||
List<ResourceType>? resourceTypes;
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<TranslationInputContainer> createState() => _TranslationInputContainerState();
|
|
||||||
}
|
|
||||||