Skip to content
This repository has been archived by the owner on May 22, 2024. It is now read-only.

Nouveau service scolaire: La vie scolaire #115

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
56 changes: 26 additions & 30 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
PODS:
- "app_settings (3.0.0+1)":
- Flutter
- awesome_notifications (0.0.2):
- Flutter
- background_fetch (1.0.0-nullsafety.2):
Expand All @@ -26,37 +24,36 @@ PODS:
- Flutter
- flutter_secure_storage (3.3.1):
- Flutter
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- geolocator (6.2.0):
- Flutter
- MTBBarcodeScanner (5.0.11)
- open_file (0.0.1):
- Flutter
- OrderedSet (5.0.0)
- package_info (0.0.1):
- package_info_plus (0.4.5):
- Flutter
- path_provider (0.0.1):
- Flutter
- "permission_handler (5.1.0+2)":
- Flutter
- qr_code_scanner (0.2.0):
- Flutter
- MTBBarcodeScanner
- Reachability (3.2)
- sensors (0.0.1):
- Shake (15.0.2)
- shake_flutter (0.0.1):
- Flutter
- Shake (~> 15.0.0-rc)
- share (0.0.1):
- Flutter
- shared_preferences (0.0.1):
- Flutter
- sqflite (0.0.2):
- Flutter
- FMDB (>= 2.7.5)
- url_launcher (0.0.1):
- Flutter
- webview_flutter (0.0.1):
- Flutter

DEPENDENCIES:
- app_settings (from `.symlinks/plugins/app_settings/ios`)
- awesome_notifications (from `.symlinks/plugins/awesome_notifications/ios`)
- background_fetch (from `.symlinks/plugins/background_fetch/ios`)
- battery_optimization (from `.symlinks/plugins/battery_optimization/ios`)
Expand All @@ -69,25 +66,24 @@ DEPENDENCIES:
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- geolocator (from `.symlinks/plugins/geolocator/ios`)
- open_file (from `.symlinks/plugins/open_file/ios`)
- package_info (from `.symlinks/plugins/package_info/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider (from `.symlinks/plugins/path_provider/ios`)
- permission_handler (from `.symlinks/plugins/permission_handler/ios`)
- sensors (from `.symlinks/plugins/sensors/ios`)
- qr_code_scanner (from `.symlinks/plugins/qr_code_scanner/ios`)
- shake_flutter (from `.symlinks/plugins/shake_flutter/ios`)
- share (from `.symlinks/plugins/share/ios`)
- shared_preferences (from `.symlinks/plugins/shared_preferences/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
- webview_flutter (from `.symlinks/plugins/webview_flutter/ios`)

SPEC REPOS:
trunk:
- FMDB
- MTBBarcodeScanner
- OrderedSet
- Reachability
- Shake

EXTERNAL SOURCES:
app_settings:
:path: ".symlinks/plugins/app_settings/ios"
awesome_notifications:
:path: ".symlinks/plugins/awesome_notifications/ios"
background_fetch:
Expand All @@ -112,49 +108,49 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/geolocator/ios"
open_file:
:path: ".symlinks/plugins/open_file/ios"
package_info:
:path: ".symlinks/plugins/package_info/ios"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider:
:path: ".symlinks/plugins/path_provider/ios"
permission_handler:
:path: ".symlinks/plugins/permission_handler/ios"
sensors:
:path: ".symlinks/plugins/sensors/ios"
qr_code_scanner:
:path: ".symlinks/plugins/qr_code_scanner/ios"
shake_flutter:
:path: ".symlinks/plugins/shake_flutter/ios"
share:
:path: ".symlinks/plugins/share/ios"
shared_preferences:
:path: ".symlinks/plugins/shared_preferences/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
url_launcher:
:path: ".symlinks/plugins/url_launcher/ios"
webview_flutter:
:path: ".symlinks/plugins/webview_flutter/ios"

SPEC CHECKSUMS:
app_settings: d103828c9f5d515c4df9ee754dabd443f7cedcf3
awesome_notifications: 74462bc8e68b11f8235d78422266886759e9da61
background_fetch: 67b227578932e795dbe3ea6d3f7c006e45f3ce66
battery_optimization: 2cfe96337f15b292912db1d874c317962fda5635
connectivity_plus: 5f0eb61093bec56935f21a1699dd2758bc895587
ext_storage: 4eaf3a84d5594106e2ebcc2502248cfde53c8fa1
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
flutter_file_dialog: 34ab8c55c460c69cb70e75a8d74bfe8b5c852824
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
flutter_file_dialog: 4c014a45b105709a27391e266c277d7e588e9299
flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
geolocator: f5e3de65e241caba7ce3e8a618803387bda73384
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
open_file: 02eb5cb6b21264bd3a696876f5afbfb7ca4f4b7d
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
permission_handler: ccb20a9fad0ee9b1314a52b70b76b473c5f8dab0
qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
sensors: 84eb7a30e47a649e4172b71d6e81be614c280336
Shake: 56265204198c497ceb35b614e32d22268af003d0
shake_flutter: 8ed3dd3100e61d616d4eb1921c96cffa604f38fc
share: 0b2c3e82132f5888bccca3351c504d0003b3b410
shared_preferences: af6bfa751691cdc24be3045c43ec037377ada40d
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
webview_flutter: 9f491a9b5a66f2573946a389b2677987b0ff8c0b

Expand Down
182 changes: 182 additions & 0 deletions lib/core/apis/lvs.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import 'dart:convert';

import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:ynotes/core/apis/lvs/lvs_methods.dart';
import 'package:ynotes/core/logic/models_exporter.dart';
import 'package:ynotes/core/logic/shared/models.dart';
import 'package:ynotes/core/logic/agenda/models.dart';

import 'package:http/src/request.dart';
import 'package:ynotes/core/offline/data/disciplines/disciplines.dart';
import 'package:ynotes/core/offline/data/homework/homework.dart';
import 'package:ynotes/core/offline/offline.dart';
import 'package:ynotes/core/utils/logging_utils/logging_utils.dart';
import 'package:ynotes/globals.dart';

import 'lvs/lvs_client.dart';
import 'lvs/converters/account.dart';
import 'model.dart';

final storage = new FlutterSecureStorage();

void createStorage(String key, String? data) async {
await storage.write(key: key, value: data);
}

class APILVS extends API {
LvsClient client = LvsClient();
APILVS(Offline offlineController) : super(offlineController, apiName: "Lvs");

@override
Future<List> login(username, password, {Map? additionnalSettings}) async {
print('wooow');
// CustomLogger.saveLog(object: 'LVS', text: 'Login called');
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
// if (url == null) {
// url = "";
// }

var url = 'https://institut';

Map<String, dynamic> credentials = {
'url': Uri.parse(url),
'username': username,
'password': password
};

List res = await this.client.start(credentials);

if (res[0] == 1) {
try {
var req_infos = await this
.client
.get(Uri.parse('/vsn.main/WSMenu/infosPortailUser'));

Map<String, dynamic> raw_infos = jsonDecode(req_infos.body);
/* raw_infos = {
"infoUser": {
"logo": "https://institut.la-vie-scolaire.fr/vsn.main/WSMenu/logo",
"etabName": "Intitut",
"userPrenom": "Inom",
"userNom": "Iom",
"profil": "Elève"
},
"plateform": ""
}; */
appSys.account = LvsAccountConverter.account(raw_infos);

if (appSys.account != null &&
appSys.account!.managableAccounts != null) {
await storage.write(
key: "appAccount", value: jsonEncode(appSys.account!.toJson()));
appSys.currentSchoolAccount = appSys.account!.managableAccounts![0];
} else {
return [0, "Impossible de collecter les comptes."];
}
createStorage("password", password ?? "");
createStorage("username", username ?? "");
this.loggedIn = true;
return ([1, "Bienvenue ${appSys.account?.name ?? "Invité"}!"]);
} catch (e) {
CustomLogger.error(
'An error occured while registering the account: ' + e.toString());
}
return [
0,
"Erreur à l'inscription du compte. Seuls les comptes élèves sont supportés."
];
}
return [0, "Erreur à la connection"];
}

@override
Future<List> apiStatus() async {
return [1, "Pas de problème connu."];
}

@override
app(String appname, {String? args, String? action, CloudItem? folder}) {
switch (appname) {
}
;
}

@override
Future<List<Homework>?> getHomeworkFor(DateTime? dateHomework,
{bool? forceReload}) async {
return await fetch(
() async => LvsMethods(await this.getClient(), this.offlineController)
.homeworkFor(dateHomework!),
() async =>
HomeworkOffline(offlineController).getHomeworkFor(dateHomework!),
forceFetch: forceReload ?? false);
}

@override
Future<List<Homework>?> getNextHomework({bool? forceReload}) async {
return await fetch(
() async => LvsMethods(await this.getClient(), this.offlineController)
.nextHomework(),
() => HomeworkOffline(offlineController).getAllHomework(),
forceFetch: forceReload ?? false);
}

@override
Future<Request> downloadRequest(Document document) async {
var cl = await this.getClient();
var hw_client = await cl.getHwClient();
var url = hw_client.base_url +
"/fichier/afficherFichier" +
hw_client.token +
'?fichierId=' +
document.id;
return new Request('GET', Uri.parse(url));
}

@override
Future<List<Discipline>?> getGrades({bool? forceReload}) async {
return await fetch(
() async =>
LvsMethods(await this.getClient(), this.offlineController).grades(),
() => DisciplinesOffline(offlineController).getDisciplines(),
forceFetch: forceReload ?? false);
}

@override
Future<List<Lesson>?> getNextLessons(DateTime from,
{bool? forceReload}) async {
// TODO: implement getNextLessons
throw UnimplementedError();
}

@override
Future<List<SchoolLifeTicket>?> getSchoolLife(
{bool forceReload = false}) async {
// TODO: implement getSchoolLife
throw UnimplementedError();
}

@override
Future<bool?> testNewGrades() async {
// TODO: implement testNewGrades
return (true);
}

@override
Future uploadFile(String context, String id, String filepath) async {
// Not available
throw UnimplementedError();
}

getClient() async {
if (!this.client.started) {
throw ('Client is called but not started.');
}
return this.client;
}
}
32 changes: 32 additions & 0 deletions lib/core/apis/lvs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Introduction ✨
Api apportant l'intégration du service scolaire "La Vie Scolaire" à l'application Ynotes. Se référer aux conditions d'utilisation de celle-ci.
Seuls les devoirs, notes et informations de l'élève sont disponibles pour l'instant.

# Fonctionnement 🧙🏻
## Clients
Implementant `SessionClient.dart`, les clients permettent de gérer une session en apportant des méthodes facilitant l'authentification, la gestion de token et les requêtes. Si configuré à cet effet, le client peut assurer le rafraichissement automatique de la session.

## Methods
```nextHomework()```: donne les devoirs sur les 23 prochains jours.

## Converters
Permettent de convertir les données brutes renvoyées par le service scolaire sous forme d'instance d'objets définis par l'application.
- ### Account Converter
Exemple de données attendues pour `account()`:
```json{
"infoUser": {
"logo":
"https://etablissement.la-vie-scolaire.fr/vsn.main/WSMenu/logo",
"etabName": "Inserer Etablissement",
"userPrenom": "Inserer prenom",
"userNom": "Inserer nom",
"profil": "Elève"
},
"plateform": ""
}
```
- ### Homework Converter
Un contenu json est attendu.

- ### Disciplines Converter
Un contenu html est attendu.
Loading