igen
This commit is contained in:
11
filcnaplo_kreta_api/.github/dependabot.yml
vendored
Normal file
11
filcnaplo_kreta_api/.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "pub" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "daily"
|
||||
47
filcnaplo_kreta_api/.gitignore
vendored
Normal file
47
filcnaplo_kreta_api/.gitignore
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
**/ios/Flutter/.last_build_id
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.packages
|
||||
.pub-cache/
|
||||
.pub/
|
||||
/build/
|
||||
|
||||
# Web related
|
||||
lib/generated_plugin_registrant.dart
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
|
||||
# Obfuscation related
|
||||
app.*.map.json
|
||||
|
||||
# Android Studio will place build artifacts here
|
||||
/android/app/debug
|
||||
/android/app/profile
|
||||
/android/app/release
|
||||
pubspec.lock
|
||||
@@ -1,29 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, Filc
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2021, Filc
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
# 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-lang.github.io/linter/lints/index.html.
|
||||
#
|
||||
# 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
|
||||
# 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-lang.github.io/linter/lints/index.html.
|
||||
#
|
||||
# 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
|
||||
|
||||
@@ -1,82 +1,82 @@
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class KretaAPI {
|
||||
// IDP API
|
||||
static const login = BaseKreta.kretaIdp + KretaApiEndpoints.token;
|
||||
static const nonce = BaseKreta.kretaIdp + KretaApiEndpoints.nonce;
|
||||
static const clientId = "kreta-ellenorzo-mobile-android";
|
||||
|
||||
// ELLENORZO API
|
||||
static String notes(String iss) => BaseKreta.kreta(iss) + KretaApiEndpoints.notes;
|
||||
static String events(String iss) => BaseKreta.kreta(iss) + KretaApiEndpoints.events;
|
||||
static String student(String iss) => BaseKreta.kreta(iss) + KretaApiEndpoints.student;
|
||||
static String grades(String iss) => BaseKreta.kreta(iss) + KretaApiEndpoints.grades;
|
||||
static String absences(String iss) => BaseKreta.kreta(iss) + KretaApiEndpoints.absences;
|
||||
static String groups(String iss) => BaseKreta.kreta(iss) + KretaApiEndpoints.groups;
|
||||
static String groupAverages(String iss, String uid) =>
|
||||
BaseKreta.kreta(iss) + KretaApiEndpoints.groupAverages + "?oktatasiNevelesiFeladatUid=" + uid;
|
||||
static String timetable(String iss, {DateTime? start, DateTime? end}) =>
|
||||
BaseKreta.kreta(iss) +
|
||||
KretaApiEndpoints.timetable +
|
||||
(start != null && end != null ? "?datumTol=" + start.toUtc().toIso8601String() + "&datumIg=" + end.toUtc().toIso8601String() : "");
|
||||
static String exams(String iss) => BaseKreta.kreta(iss) + KretaApiEndpoints.exams;
|
||||
static String homework(String iss, {DateTime? start, String? id}) =>
|
||||
BaseKreta.kreta(iss) +
|
||||
KretaApiEndpoints.homework +
|
||||
(id != null ? "/$id" : "") +
|
||||
(id == null && start != null ? "?datumTol=" + DateFormat('yyyy-MM-dd').format(start) : "");
|
||||
static String capabilities(String iss) => BaseKreta.kreta(iss) + KretaApiEndpoints.capabilities;
|
||||
static String downloadHomeworkAttachments(String iss, String uid, String type) =>
|
||||
BaseKreta.kreta(iss) + KretaApiEndpoints.downloadHomeworkAttachments(uid, type);
|
||||
|
||||
// ADMIN API
|
||||
static const sendMessage = BaseKreta.kretaAdmin + KretaAdminEndpoints.sendMessage;
|
||||
static String messages(String endpoint) => BaseKreta.kretaAdmin + KretaAdminEndpoints.messages(endpoint);
|
||||
static String message(String id) => BaseKreta.kretaAdmin + KretaAdminEndpoints.message(id);
|
||||
static const recipientCategories = BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientCategories;
|
||||
static const availableCategories = BaseKreta.kretaAdmin + KretaAdminEndpoints.availableCategories;
|
||||
static const recipientsTeacher = BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientsTeacher;
|
||||
static const uploadAttachment = BaseKreta.kretaAdmin + KretaAdminEndpoints.uploadAttachment;
|
||||
static String downloadAttachment(String id) => BaseKreta.kretaAdmin + KretaAdminEndpoints.downloadAttachment(id);
|
||||
static const trashMessage = BaseKreta.kretaAdmin + KretaAdminEndpoints.trashMessage;
|
||||
static const deleteMessage = BaseKreta.kretaAdmin + KretaAdminEndpoints.deleteMessage;
|
||||
}
|
||||
|
||||
class BaseKreta {
|
||||
static String kreta(String iss) => "https://$iss.e-kreta.hu";
|
||||
static const kretaIdp = "https://idp.e-kreta.hu";
|
||||
static const kretaAdmin = "https://eugyintezes.e-kreta.hu";
|
||||
static const kretaFiles = "https://files.e-kreta.hu";
|
||||
}
|
||||
|
||||
class KretaApiEndpoints {
|
||||
static const token = "/connect/token";
|
||||
static const nonce = "/nonce";
|
||||
static const notes = "/ellenorzo/V3/Sajat/Feljegyzesek";
|
||||
static const events = "/ellenorzo/V3/Sajat/FaliujsagElemek";
|
||||
static const student = "/ellenorzo/V3/Sajat/TanuloAdatlap";
|
||||
static const grades = "/ellenorzo/V3/Sajat/Ertekelesek";
|
||||
static const absences = "/ellenorzo/V3/Sajat/Mulasztasok";
|
||||
static const groups = "/ellenorzo/V3/Sajat/OsztalyCsoportok";
|
||||
static const groupAverages = "/ellenorzo/V3/Sajat/Ertekelesek/Atlagok/OsztalyAtlagok";
|
||||
static const timetable = "/ellenorzo/V3/Sajat/OrarendElemek";
|
||||
static const exams = "/ellenorzo/V3/Sajat/BejelentettSzamonkeresek";
|
||||
static const homework = "/ellenorzo/V3/Sajat/HaziFeladatok";
|
||||
// static const homeworkDone = "/ellenorzo/V3/Sajat/HaziFeladatok/Megoldva"; // Removed from the API
|
||||
static const capabilities = "/ellenorzo/V3/Sajat/Intezmenyek";
|
||||
static String downloadHomeworkAttachments(String uid, String type) => "/ellenorzo/V3/Sajat/Csatolmany/$uid";
|
||||
}
|
||||
|
||||
class KretaAdminEndpoints {
|
||||
//static const messages = "/api/v1/kommunikacio/postaladaelemek/sajat";
|
||||
static const sendMessage = "/api/v1/kommunikacio/uzenetek";
|
||||
static String messages(String endpoint) => "/api/v1/kommunikacio/postaladaelemek/$endpoint";
|
||||
static String message(String id) => "/api/v1/kommunikacio/postaladaelemek/$id";
|
||||
static const recipientCategories = "/api/v1/adatszotarak/cimzetttipusok";
|
||||
static const availableCategories = "/api/v1/kommunikacio/cimezhetotipusok";
|
||||
static const recipientsTeacher = "/api/v1/kreta/alkalmazottak/tanar";
|
||||
static const uploadAttachment = "/ideiglenesfajlok";
|
||||
static String downloadAttachment(String id) => "/api/v1/dokumentumok/uzenetek/$id";
|
||||
static const trashMessage = "/api/v1/kommunikacio/postaladaelemek/kuka";
|
||||
static const deleteMessage = "/api/v1/kommunikacio/postaladaelemek/torles";
|
||||
}
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class KretaAPI {
|
||||
// IDP API
|
||||
static const login = BaseKreta.kretaIdp + KretaApiEndpoints.token;
|
||||
static const nonce = BaseKreta.kretaIdp + KretaApiEndpoints.nonce;
|
||||
static const clientId = "kreta-ellenorzo-mobile-android";
|
||||
|
||||
// ELLENORZO API
|
||||
static String notes(String iss) => BaseKreta.kreta(iss) + KretaApiEndpoints.notes;
|
||||
static String events(String iss) => BaseKreta.kreta(iss) + KretaApiEndpoints.events;
|
||||
static String student(String iss) => BaseKreta.kreta(iss) + KretaApiEndpoints.student;
|
||||
static String grades(String iss) => BaseKreta.kreta(iss) + KretaApiEndpoints.grades;
|
||||
static String absences(String iss) => BaseKreta.kreta(iss) + KretaApiEndpoints.absences;
|
||||
static String groups(String iss) => BaseKreta.kreta(iss) + KretaApiEndpoints.groups;
|
||||
static String groupAverages(String iss, String uid) =>
|
||||
BaseKreta.kreta(iss) + KretaApiEndpoints.groupAverages + "?oktatasiNevelesiFeladatUid=" + uid;
|
||||
static String timetable(String iss, {DateTime? start, DateTime? end}) =>
|
||||
BaseKreta.kreta(iss) +
|
||||
KretaApiEndpoints.timetable +
|
||||
(start != null && end != null ? "?datumTol=" + start.toUtc().toIso8601String() + "&datumIg=" + end.toUtc().toIso8601String() : "");
|
||||
static String exams(String iss) => BaseKreta.kreta(iss) + KretaApiEndpoints.exams;
|
||||
static String homework(String iss, {DateTime? start, String? id}) =>
|
||||
BaseKreta.kreta(iss) +
|
||||
KretaApiEndpoints.homework +
|
||||
(id != null ? "/$id" : "") +
|
||||
(id == null && start != null ? "?datumTol=" + DateFormat('yyyy-MM-dd').format(start) : "");
|
||||
static String capabilities(String iss) => BaseKreta.kreta(iss) + KretaApiEndpoints.capabilities;
|
||||
static String downloadHomeworkAttachments(String iss, String uid, String type) =>
|
||||
BaseKreta.kreta(iss) + KretaApiEndpoints.downloadHomeworkAttachments(uid, type);
|
||||
|
||||
// ADMIN API
|
||||
static const sendMessage = BaseKreta.kretaAdmin + KretaAdminEndpoints.sendMessage;
|
||||
static String messages(String endpoint) => BaseKreta.kretaAdmin + KretaAdminEndpoints.messages(endpoint);
|
||||
static String message(String id) => BaseKreta.kretaAdmin + KretaAdminEndpoints.message(id);
|
||||
static const recipientCategories = BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientCategories;
|
||||
static const availableCategories = BaseKreta.kretaAdmin + KretaAdminEndpoints.availableCategories;
|
||||
static const recipientsTeacher = BaseKreta.kretaAdmin + KretaAdminEndpoints.recipientsTeacher;
|
||||
static const uploadAttachment = BaseKreta.kretaAdmin + KretaAdminEndpoints.uploadAttachment;
|
||||
static String downloadAttachment(String id) => BaseKreta.kretaAdmin + KretaAdminEndpoints.downloadAttachment(id);
|
||||
static const trashMessage = BaseKreta.kretaAdmin + KretaAdminEndpoints.trashMessage;
|
||||
static const deleteMessage = BaseKreta.kretaAdmin + KretaAdminEndpoints.deleteMessage;
|
||||
}
|
||||
|
||||
class BaseKreta {
|
||||
static String kreta(String iss) => "https://$iss.e-kreta.hu";
|
||||
static const kretaIdp = "https://idp.e-kreta.hu";
|
||||
static const kretaAdmin = "https://eugyintezes.e-kreta.hu";
|
||||
static const kretaFiles = "https://files.e-kreta.hu";
|
||||
}
|
||||
|
||||
class KretaApiEndpoints {
|
||||
static const token = "/connect/token";
|
||||
static const nonce = "/nonce";
|
||||
static const notes = "/ellenorzo/V3/Sajat/Feljegyzesek";
|
||||
static const events = "/ellenorzo/V3/Sajat/FaliujsagElemek";
|
||||
static const student = "/ellenorzo/V3/Sajat/TanuloAdatlap";
|
||||
static const grades = "/ellenorzo/V3/Sajat/Ertekelesek";
|
||||
static const absences = "/ellenorzo/V3/Sajat/Mulasztasok";
|
||||
static const groups = "/ellenorzo/V3/Sajat/OsztalyCsoportok";
|
||||
static const groupAverages = "/ellenorzo/V3/Sajat/Ertekelesek/Atlagok/OsztalyAtlagok";
|
||||
static const timetable = "/ellenorzo/V3/Sajat/OrarendElemek";
|
||||
static const exams = "/ellenorzo/V3/Sajat/BejelentettSzamonkeresek";
|
||||
static const homework = "/ellenorzo/V3/Sajat/HaziFeladatok";
|
||||
// static const homeworkDone = "/ellenorzo/V3/Sajat/HaziFeladatok/Megoldva"; // Removed from the API
|
||||
static const capabilities = "/ellenorzo/V3/Sajat/Intezmenyek";
|
||||
static String downloadHomeworkAttachments(String uid, String type) => "/ellenorzo/V3/Sajat/Csatolmany/$uid";
|
||||
}
|
||||
|
||||
class KretaAdminEndpoints {
|
||||
//static const messages = "/api/v1/kommunikacio/postaladaelemek/sajat";
|
||||
static const sendMessage = "/api/v1/kommunikacio/uzenetek";
|
||||
static String messages(String endpoint) => "/api/v1/kommunikacio/postaladaelemek/$endpoint";
|
||||
static String message(String id) => "/api/v1/kommunikacio/postaladaelemek/$id";
|
||||
static const recipientCategories = "/api/v1/adatszotarak/cimzetttipusok";
|
||||
static const availableCategories = "/api/v1/kommunikacio/cimezhetotipusok";
|
||||
static const recipientsTeacher = "/api/v1/kreta/alkalmazottak/tanar";
|
||||
static const uploadAttachment = "/ideiglenesfajlok";
|
||||
static String downloadAttachment(String id) => "/api/v1/dokumentumok/uzenetek/$id";
|
||||
static const trashMessage = "/api/v1/kommunikacio/postaladaelemek/kuka";
|
||||
static const deleteMessage = "/api/v1/kommunikacio/postaladaelemek/torles";
|
||||
}
|
||||
|
||||
@@ -1,193 +1,193 @@
|
||||
// ignore_for_file: avoid_print
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:filcnaplo/api/login.dart';
|
||||
import 'package:filcnaplo/api/nonce.dart';
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/status_provider.dart';
|
||||
import 'package:filcnaplo/models/settings.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo/utils/jwt.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/io_client.dart' as http;
|
||||
import 'dart:async';
|
||||
|
||||
class KretaClient {
|
||||
String? accessToken;
|
||||
String? refreshToken;
|
||||
String? idToken;
|
||||
String? userAgent;
|
||||
late http.Client client;
|
||||
|
||||
late final SettingsProvider _settings;
|
||||
late final UserProvider _user;
|
||||
late final StatusProvider _status;
|
||||
|
||||
KretaClient({
|
||||
this.accessToken,
|
||||
required SettingsProvider settings,
|
||||
required UserProvider user,
|
||||
required StatusProvider status,
|
||||
}) : _settings = settings,
|
||||
_user = user,
|
||||
_status = status,
|
||||
userAgent = settings.config.userAgent {
|
||||
var ioclient = HttpClient();
|
||||
ioclient.badCertificateCallback = _checkCerts;
|
||||
client = http.IOClient(ioclient);
|
||||
}
|
||||
|
||||
bool _checkCerts(X509Certificate cert, String host, int port) {
|
||||
return _settings.developerMode;
|
||||
}
|
||||
|
||||
Future<dynamic> getAPI(
|
||||
String url, {
|
||||
Map<String, String>? headers,
|
||||
bool autoHeader = true,
|
||||
bool json = true,
|
||||
bool rawResponse = false,
|
||||
}) async {
|
||||
Map<String, String> headerMap;
|
||||
|
||||
if (rawResponse) json = false;
|
||||
|
||||
if (headers != null) {
|
||||
headerMap = headers;
|
||||
} else {
|
||||
headerMap = {};
|
||||
}
|
||||
|
||||
try {
|
||||
http.Response? res;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (autoHeader) {
|
||||
if (!headerMap.containsKey("authorization") && accessToken != null) headerMap["authorization"] = "Bearer $accessToken";
|
||||
if (!headerMap.containsKey("user-agent") && userAgent != null) headerMap["user-agent"] = "$userAgent";
|
||||
}
|
||||
|
||||
res = await client.get(Uri.parse(url), headers: headerMap);
|
||||
_status.triggerRequest(res);
|
||||
|
||||
if (res.statusCode == 401) {
|
||||
await refreshLogin();
|
||||
headerMap.remove("authorization");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
// Wait before retrying
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
if (res == null) throw "Login error";
|
||||
|
||||
if (json) {
|
||||
return jsonDecode(res.body);
|
||||
} else if (rawResponse) {
|
||||
return res.bodyBytes;
|
||||
} else {
|
||||
return res.body;
|
||||
}
|
||||
} on http.ClientException catch (error) {
|
||||
print("ERROR: KretaClient.getAPI ($url) ClientException: ${error.message}");
|
||||
} catch (error) {
|
||||
print("ERROR: KretaClient.getAPI ($url) ${error.runtimeType}: $error");
|
||||
}
|
||||
}
|
||||
|
||||
Future<dynamic> postAPI(
|
||||
String url, {
|
||||
Map<String, String>? headers,
|
||||
bool autoHeader = true,
|
||||
bool json = true,
|
||||
Object? body,
|
||||
}) async {
|
||||
Map<String, String> headerMap;
|
||||
|
||||
if (headers != null) {
|
||||
headerMap = headers;
|
||||
} else {
|
||||
headerMap = {};
|
||||
}
|
||||
|
||||
try {
|
||||
http.Response? res;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (autoHeader) {
|
||||
if (!headerMap.containsKey("authorization") && accessToken != null) headerMap["authorization"] = "Bearer $accessToken";
|
||||
if (!headerMap.containsKey("user-agent") && userAgent != null) headerMap["user-agent"] = "$userAgent";
|
||||
if (!headerMap.containsKey("content-type")) headerMap["content-type"] = "application/json";
|
||||
}
|
||||
|
||||
res = await client.post(Uri.parse(url), headers: headerMap, body: body);
|
||||
if (res.statusCode == 401) {
|
||||
await refreshLogin();
|
||||
headerMap.remove("authorization");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (res == null) throw "Login error";
|
||||
|
||||
if (json) {
|
||||
return jsonDecode(res.body);
|
||||
} else {
|
||||
return res.body;
|
||||
}
|
||||
} on http.ClientException catch (error) {
|
||||
print("ERROR: KretaClient.getAPI ($url) ClientException: ${error.message}");
|
||||
} catch (error) {
|
||||
print("ERROR: KretaClient.getAPI ($url) ${error.runtimeType}: $error");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> refreshLogin() async {
|
||||
User? loginUser = _user.user;
|
||||
if (loginUser == null) return;
|
||||
|
||||
Map<String, String> headers = {
|
||||
"content-type": "application/x-www-form-urlencoded",
|
||||
};
|
||||
|
||||
String nonceStr = await getAPI(KretaAPI.nonce, json: false);
|
||||
Nonce nonce = getNonce(nonceStr, loginUser.username, loginUser.instituteCode);
|
||||
headers.addAll(nonce.header());
|
||||
|
||||
if (_settings.presentationMode) {
|
||||
print("DEBUG: refreshLogin: ${loginUser.id}");
|
||||
} else {
|
||||
print("DEBUG: refreshLogin: ${loginUser.id} ${loginUser.name}");
|
||||
}
|
||||
|
||||
Map? loginRes = await postAPI(KretaAPI.login,
|
||||
headers: headers,
|
||||
body: User.loginBody(
|
||||
username: loginUser.username,
|
||||
password: loginUser.password,
|
||||
instituteCode: loginUser.instituteCode,
|
||||
));
|
||||
|
||||
if (loginRes != null) {
|
||||
if (loginRes.containsKey("access_token")) accessToken = loginRes["access_token"];
|
||||
if (loginRes.containsKey("refresh_token")) refreshToken = loginRes["refresh_token"];
|
||||
|
||||
// Update role
|
||||
loginUser.role = JwtUtils.getRoleFromJWT(accessToken ?? "") ?? Role.student;
|
||||
}
|
||||
|
||||
if (refreshToken != null) {
|
||||
Map? refreshRes = await postAPI(KretaAPI.login,
|
||||
headers: headers, body: User.refreshBody(refreshToken: refreshToken!, instituteCode: loginUser.instituteCode));
|
||||
if (refreshRes != null) {
|
||||
if (refreshRes.containsKey("id_token")) idToken = refreshRes["id_token"];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// ignore_for_file: avoid_print
|
||||
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:filcnaplo/api/login.dart';
|
||||
import 'package:filcnaplo/api/nonce.dart';
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/status_provider.dart';
|
||||
import 'package:filcnaplo/models/settings.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo/utils/jwt.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/io_client.dart' as http;
|
||||
import 'dart:async';
|
||||
|
||||
class KretaClient {
|
||||
String? accessToken;
|
||||
String? refreshToken;
|
||||
String? idToken;
|
||||
String? userAgent;
|
||||
late http.Client client;
|
||||
|
||||
late final SettingsProvider _settings;
|
||||
late final UserProvider _user;
|
||||
late final StatusProvider _status;
|
||||
|
||||
KretaClient({
|
||||
this.accessToken,
|
||||
required SettingsProvider settings,
|
||||
required UserProvider user,
|
||||
required StatusProvider status,
|
||||
}) : _settings = settings,
|
||||
_user = user,
|
||||
_status = status,
|
||||
userAgent = settings.config.userAgent {
|
||||
var ioclient = HttpClient();
|
||||
ioclient.badCertificateCallback = _checkCerts;
|
||||
client = http.IOClient(ioclient);
|
||||
}
|
||||
|
||||
bool _checkCerts(X509Certificate cert, String host, int port) {
|
||||
return _settings.developerMode;
|
||||
}
|
||||
|
||||
Future<dynamic> getAPI(
|
||||
String url, {
|
||||
Map<String, String>? headers,
|
||||
bool autoHeader = true,
|
||||
bool json = true,
|
||||
bool rawResponse = false,
|
||||
}) async {
|
||||
Map<String, String> headerMap;
|
||||
|
||||
if (rawResponse) json = false;
|
||||
|
||||
if (headers != null) {
|
||||
headerMap = headers;
|
||||
} else {
|
||||
headerMap = {};
|
||||
}
|
||||
|
||||
try {
|
||||
http.Response? res;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (autoHeader) {
|
||||
if (!headerMap.containsKey("authorization") && accessToken != null) headerMap["authorization"] = "Bearer $accessToken";
|
||||
if (!headerMap.containsKey("user-agent") && userAgent != null) headerMap["user-agent"] = "$userAgent";
|
||||
}
|
||||
|
||||
res = await client.get(Uri.parse(url), headers: headerMap);
|
||||
_status.triggerRequest(res);
|
||||
|
||||
if (res.statusCode == 401) {
|
||||
await refreshLogin();
|
||||
headerMap.remove("authorization");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
// Wait before retrying
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
}
|
||||
|
||||
if (res == null) throw "Login error";
|
||||
|
||||
if (json) {
|
||||
return jsonDecode(res.body);
|
||||
} else if (rawResponse) {
|
||||
return res.bodyBytes;
|
||||
} else {
|
||||
return res.body;
|
||||
}
|
||||
} on http.ClientException catch (error) {
|
||||
print("ERROR: KretaClient.getAPI ($url) ClientException: ${error.message}");
|
||||
} catch (error) {
|
||||
print("ERROR: KretaClient.getAPI ($url) ${error.runtimeType}: $error");
|
||||
}
|
||||
}
|
||||
|
||||
Future<dynamic> postAPI(
|
||||
String url, {
|
||||
Map<String, String>? headers,
|
||||
bool autoHeader = true,
|
||||
bool json = true,
|
||||
Object? body,
|
||||
}) async {
|
||||
Map<String, String> headerMap;
|
||||
|
||||
if (headers != null) {
|
||||
headerMap = headers;
|
||||
} else {
|
||||
headerMap = {};
|
||||
}
|
||||
|
||||
try {
|
||||
http.Response? res;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (autoHeader) {
|
||||
if (!headerMap.containsKey("authorization") && accessToken != null) headerMap["authorization"] = "Bearer $accessToken";
|
||||
if (!headerMap.containsKey("user-agent") && userAgent != null) headerMap["user-agent"] = "$userAgent";
|
||||
if (!headerMap.containsKey("content-type")) headerMap["content-type"] = "application/json";
|
||||
}
|
||||
|
||||
res = await client.post(Uri.parse(url), headers: headerMap, body: body);
|
||||
if (res.statusCode == 401) {
|
||||
await refreshLogin();
|
||||
headerMap.remove("authorization");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (res == null) throw "Login error";
|
||||
|
||||
if (json) {
|
||||
return jsonDecode(res.body);
|
||||
} else {
|
||||
return res.body;
|
||||
}
|
||||
} on http.ClientException catch (error) {
|
||||
print("ERROR: KretaClient.getAPI ($url) ClientException: ${error.message}");
|
||||
} catch (error) {
|
||||
print("ERROR: KretaClient.getAPI ($url) ${error.runtimeType}: $error");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> refreshLogin() async {
|
||||
User? loginUser = _user.user;
|
||||
if (loginUser == null) return;
|
||||
|
||||
Map<String, String> headers = {
|
||||
"content-type": "application/x-www-form-urlencoded",
|
||||
};
|
||||
|
||||
String nonceStr = await getAPI(KretaAPI.nonce, json: false);
|
||||
Nonce nonce = getNonce(nonceStr, loginUser.username, loginUser.instituteCode);
|
||||
headers.addAll(nonce.header());
|
||||
|
||||
if (_settings.presentationMode) {
|
||||
print("DEBUG: refreshLogin: ${loginUser.id}");
|
||||
} else {
|
||||
print("DEBUG: refreshLogin: ${loginUser.id} ${loginUser.name}");
|
||||
}
|
||||
|
||||
Map? loginRes = await postAPI(KretaAPI.login,
|
||||
headers: headers,
|
||||
body: User.loginBody(
|
||||
username: loginUser.username,
|
||||
password: loginUser.password,
|
||||
instituteCode: loginUser.instituteCode,
|
||||
));
|
||||
|
||||
if (loginRes != null) {
|
||||
if (loginRes.containsKey("access_token")) accessToken = loginRes["access_token"];
|
||||
if (loginRes.containsKey("refresh_token")) refreshToken = loginRes["refresh_token"];
|
||||
|
||||
// Update role
|
||||
loginUser.role = JwtUtils.getRoleFromJWT(accessToken ?? "") ?? Role.student;
|
||||
}
|
||||
|
||||
if (refreshToken != null) {
|
||||
Map? refreshRes = await postAPI(KretaAPI.login,
|
||||
headers: headers, body: User.refreshBody(refreshToken: refreshToken!, instituteCode: loginUser.instituteCode));
|
||||
if (refreshRes != null) {
|
||||
if (refreshRes.containsKey("id_token")) idToken = refreshRes["id_token"];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,217 +1,217 @@
|
||||
// ignore_for_file: avoid_print
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
import 'dart:math' as math;
|
||||
import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
|
||||
import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/lesson.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/week.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
enum LoadType { initial, offline, loading, online }
|
||||
|
||||
class TimetableController extends ChangeNotifier {
|
||||
late Week currentWeek;
|
||||
int currentWeekId = -1;
|
||||
late int previousWeekId;
|
||||
List<List<Lesson>>? days;
|
||||
LoadType loadType = LoadType.initial;
|
||||
|
||||
TimetableController() {
|
||||
current();
|
||||
}
|
||||
|
||||
static int getWeekId(Week week) => (week.start.difference(getSchoolYearStart()).inDays / DateTime.daysPerWeek).ceil();
|
||||
|
||||
static DateTime getSchoolYearStart() {
|
||||
DateTime now = DateTime.now();
|
||||
DateTime nowStart = _getYearStart(now.year);
|
||||
|
||||
if (nowStart.isBefore(now)) {
|
||||
return nowStart;
|
||||
} else {
|
||||
return _getYearStart(now.year - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static DateTime _getYearStart(int year) {
|
||||
var s1 = DateTime(year, DateTime.september, 1);
|
||||
if (s1.weekday == 6) {
|
||||
s1.add(const Duration(days: 2));
|
||||
} else if (s1.weekday == 7) {
|
||||
s1.add(const Duration(days: 1));
|
||||
}
|
||||
return s1;
|
||||
}
|
||||
|
||||
// Jump shortcuts
|
||||
Future<void> next(BuildContext context) => jump(Week.fromId(currentWeekId + 1), context: context);
|
||||
Future<void> previous(BuildContext context) => jump(Week.fromId(currentWeekId - 1), context: context);
|
||||
void current() {
|
||||
Week week = Week.current();
|
||||
int id = getWeekId(week);
|
||||
|
||||
if (id > 51) id = 51;
|
||||
if (id < 0) id = 0;
|
||||
|
||||
_setWeek(Week.fromId(id));
|
||||
}
|
||||
|
||||
Future<void> jump(Week week, {required BuildContext context, bool initial = false, bool skip = false, bool loader = true}) async {
|
||||
if (_setWeek(week)) return;
|
||||
|
||||
loadType = LoadType.initial;
|
||||
|
||||
if (loader) {
|
||||
days = null;
|
||||
|
||||
// Don't start loading on init
|
||||
if (!initial) notifyListeners();
|
||||
}
|
||||
|
||||
days = _sortDays(week, context: context);
|
||||
|
||||
if (week != currentWeek) return;
|
||||
|
||||
loadType = LoadType.loading;
|
||||
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
await _fetchWeek(week, context: context).timeout(const Duration(seconds: 5), onTimeout: (() => throw "timeout"));
|
||||
loadType = LoadType.online;
|
||||
} catch (error, stack) {
|
||||
print("ERROR: TimetableController.jump: $error\n$stack");
|
||||
loadType = LoadType.offline;
|
||||
}
|
||||
|
||||
if (week != currentWeek) return;
|
||||
|
||||
days = _sortDays(week, context: context);
|
||||
|
||||
if (week != currentWeek) return;
|
||||
|
||||
// Jump to next week on weekends
|
||||
if (skip && (days?.length ?? 0) > 0 && days!.last.last.end.isBefore(DateTime.now())) return next(context);
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
bool _setWeek(Week week) {
|
||||
int id = getWeekId(week);
|
||||
if (id > 51) return true; // Max 52.
|
||||
if (id < 0) return true; // Min 1.
|
||||
|
||||
// Set week start to Sept. 1 of first week
|
||||
if (!_differentDate(week.start, Week.fromId(0).start)) week.start = TimetableController.getSchoolYearStart();
|
||||
|
||||
currentWeek = week;
|
||||
previousWeekId = currentWeekId;
|
||||
currentWeekId = id;
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> _fetchWeek(Week week, {required BuildContext context}) async {
|
||||
await Future.wait([
|
||||
context.read<TimetableProvider>().fetch(week: week),
|
||||
context.read<HomeworkProvider>().fetch(from: week.start, db: false),
|
||||
]);
|
||||
}
|
||||
|
||||
List<List<Lesson>> _sortDays(Week week, {required BuildContext context}) {
|
||||
List<List<Lesson>> days = [];
|
||||
|
||||
final timetableProvider = context.read<TimetableProvider>();
|
||||
|
||||
try {
|
||||
List<Lesson> lessons = timetableProvider.getWeek(week) ?? [];
|
||||
|
||||
if (lessons.isNotEmpty) {
|
||||
days.add([]);
|
||||
lessons.sort((a, b) => a.date.compareTo(b.date));
|
||||
for (var lesson in lessons) {
|
||||
if (days.last.isNotEmpty && _differentDate(lesson.date, days.last.last.date)) days.add([]);
|
||||
days.last.add(lesson);
|
||||
}
|
||||
|
||||
for (int i = 0; i < days.length; i++) {
|
||||
List<Lesson> _day = List.castFrom(days[i]);
|
||||
|
||||
List<int> lessonIndexes = _getIndexes(_day);
|
||||
int minIndex = 0, maxIndex = 0;
|
||||
|
||||
if (lessonIndexes.isNotEmpty) {
|
||||
minIndex = lessonIndexes.reduce(math.min);
|
||||
maxIndex = lessonIndexes.reduce(math.max);
|
||||
}
|
||||
|
||||
List<Lesson> day = [];
|
||||
|
||||
if (lessonIndexes.isNotEmpty) {
|
||||
// Fill missing indexes with empty spaces
|
||||
for (var i in List<int>.generate(maxIndex - minIndex + 1, (int i) => minIndex + i)) {
|
||||
List<Lesson> indexLessons = _getLessonsByIndex(_day, i);
|
||||
|
||||
// Empty lesson
|
||||
if (indexLessons.isEmpty) {
|
||||
// Get start date by previous lesson
|
||||
List<Lesson> prevLesson = _getLessonsByIndex(day, i - 1);
|
||||
try {
|
||||
DateTime? startDate = prevLesson.last.start.add(const Duration(seconds: 1));
|
||||
indexLessons.add(Lesson.fromJson({'isEmpty': true, 'Oraszam': i, 'KezdetIdopont': startDate.toIso8601String()}));
|
||||
// ignore: empty_catches
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
day.addAll(indexLessons);
|
||||
}
|
||||
}
|
||||
|
||||
// Additional lessons
|
||||
day.addAll(_day.where((l) => int.tryParse(l.lessonIndex) == null && l.subject.id != ''));
|
||||
|
||||
day.sort((a, b) => a.start.compareTo(b.start));
|
||||
|
||||
// Special Dates
|
||||
for (var l in _day) {
|
||||
l.subject.id == '' ? day.insert(0, l) : null;
|
||||
}
|
||||
|
||||
days[i] = day;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
log("_sortDays error: $e");
|
||||
}
|
||||
|
||||
return days;
|
||||
}
|
||||
|
||||
List<Lesson> _getLessonsByIndex(List<Lesson> lessons, int index) {
|
||||
List<Lesson> ret = [];
|
||||
|
||||
for (var lesson in lessons) {
|
||||
int? lessonIndex = int.tryParse(lesson.lessonIndex);
|
||||
|
||||
if (lessonIndex != null && lessonIndex == index) {
|
||||
ret.add(lesson);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
List<int> _getIndexes(List<Lesson> lessons) {
|
||||
List<int> indexes = [];
|
||||
for (var l in lessons) {
|
||||
int? index = int.tryParse(l.lessonIndex);
|
||||
if (index != null) indexes.add(index);
|
||||
}
|
||||
return indexes;
|
||||
}
|
||||
|
||||
bool _differentDate(DateTime a, DateTime b) => !(a.year == b.year && a.month == b.month && a.day == b.day);
|
||||
}
|
||||
// ignore_for_file: avoid_print
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
import 'dart:math' as math;
|
||||
import 'package:filcnaplo_kreta_api/providers/homework_provider.dart';
|
||||
import 'package:filcnaplo_kreta_api/providers/timetable_provider.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/lesson.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/week.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
enum LoadType { initial, offline, loading, online }
|
||||
|
||||
class TimetableController extends ChangeNotifier {
|
||||
late Week currentWeek;
|
||||
int currentWeekId = -1;
|
||||
late int previousWeekId;
|
||||
List<List<Lesson>>? days;
|
||||
LoadType loadType = LoadType.initial;
|
||||
|
||||
TimetableController() {
|
||||
current();
|
||||
}
|
||||
|
||||
static int getWeekId(Week week) => (week.start.difference(getSchoolYearStart()).inDays / DateTime.daysPerWeek).ceil();
|
||||
|
||||
static DateTime getSchoolYearStart() {
|
||||
DateTime now = DateTime.now();
|
||||
DateTime nowStart = _getYearStart(now.year);
|
||||
|
||||
if (nowStart.isBefore(now)) {
|
||||
return nowStart;
|
||||
} else {
|
||||
return _getYearStart(now.year - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static DateTime _getYearStart(int year) {
|
||||
var s1 = DateTime(year, DateTime.september, 1);
|
||||
if (s1.weekday == 6) {
|
||||
s1.add(const Duration(days: 2));
|
||||
} else if (s1.weekday == 7) {
|
||||
s1.add(const Duration(days: 1));
|
||||
}
|
||||
return s1;
|
||||
}
|
||||
|
||||
// Jump shortcuts
|
||||
Future<void> next(BuildContext context) => jump(Week.fromId(currentWeekId + 1), context: context);
|
||||
Future<void> previous(BuildContext context) => jump(Week.fromId(currentWeekId - 1), context: context);
|
||||
void current() {
|
||||
Week week = Week.current();
|
||||
int id = getWeekId(week);
|
||||
|
||||
if (id > 51) id = 51;
|
||||
if (id < 0) id = 0;
|
||||
|
||||
_setWeek(Week.fromId(id));
|
||||
}
|
||||
|
||||
Future<void> jump(Week week, {required BuildContext context, bool initial = false, bool skip = false, bool loader = true}) async {
|
||||
if (_setWeek(week)) return;
|
||||
|
||||
loadType = LoadType.initial;
|
||||
|
||||
if (loader) {
|
||||
days = null;
|
||||
|
||||
// Don't start loading on init
|
||||
if (!initial) notifyListeners();
|
||||
}
|
||||
|
||||
days = _sortDays(week, context: context);
|
||||
|
||||
if (week != currentWeek) return;
|
||||
|
||||
loadType = LoadType.loading;
|
||||
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
await _fetchWeek(week, context: context).timeout(const Duration(seconds: 5), onTimeout: (() => throw "timeout"));
|
||||
loadType = LoadType.online;
|
||||
} catch (error, stack) {
|
||||
print("ERROR: TimetableController.jump: $error\n$stack");
|
||||
loadType = LoadType.offline;
|
||||
}
|
||||
|
||||
if (week != currentWeek) return;
|
||||
|
||||
days = _sortDays(week, context: context);
|
||||
|
||||
if (week != currentWeek) return;
|
||||
|
||||
// Jump to next week on weekends
|
||||
if (skip && (days?.length ?? 0) > 0 && days!.last.last.end.isBefore(DateTime.now())) return next(context);
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
bool _setWeek(Week week) {
|
||||
int id = getWeekId(week);
|
||||
if (id > 51) return true; // Max 52.
|
||||
if (id < 0) return true; // Min 1.
|
||||
|
||||
// Set week start to Sept. 1 of first week
|
||||
if (!_differentDate(week.start, Week.fromId(0).start)) week.start = TimetableController.getSchoolYearStart();
|
||||
|
||||
currentWeek = week;
|
||||
previousWeekId = currentWeekId;
|
||||
currentWeekId = id;
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> _fetchWeek(Week week, {required BuildContext context}) async {
|
||||
await Future.wait([
|
||||
context.read<TimetableProvider>().fetch(week: week),
|
||||
context.read<HomeworkProvider>().fetch(from: week.start, db: false),
|
||||
]);
|
||||
}
|
||||
|
||||
List<List<Lesson>> _sortDays(Week week, {required BuildContext context}) {
|
||||
List<List<Lesson>> days = [];
|
||||
|
||||
final timetableProvider = context.read<TimetableProvider>();
|
||||
|
||||
try {
|
||||
List<Lesson> lessons = timetableProvider.getWeek(week) ?? [];
|
||||
|
||||
if (lessons.isNotEmpty) {
|
||||
days.add([]);
|
||||
lessons.sort((a, b) => a.date.compareTo(b.date));
|
||||
for (var lesson in lessons) {
|
||||
if (days.last.isNotEmpty && _differentDate(lesson.date, days.last.last.date)) days.add([]);
|
||||
days.last.add(lesson);
|
||||
}
|
||||
|
||||
for (int i = 0; i < days.length; i++) {
|
||||
List<Lesson> _day = List.castFrom(days[i]);
|
||||
|
||||
List<int> lessonIndexes = _getIndexes(_day);
|
||||
int minIndex = 0, maxIndex = 0;
|
||||
|
||||
if (lessonIndexes.isNotEmpty) {
|
||||
minIndex = lessonIndexes.reduce(math.min);
|
||||
maxIndex = lessonIndexes.reduce(math.max);
|
||||
}
|
||||
|
||||
List<Lesson> day = [];
|
||||
|
||||
if (lessonIndexes.isNotEmpty) {
|
||||
// Fill missing indexes with empty spaces
|
||||
for (var i in List<int>.generate(maxIndex - minIndex + 1, (int i) => minIndex + i)) {
|
||||
List<Lesson> indexLessons = _getLessonsByIndex(_day, i);
|
||||
|
||||
// Empty lesson
|
||||
if (indexLessons.isEmpty) {
|
||||
// Get start date by previous lesson
|
||||
List<Lesson> prevLesson = _getLessonsByIndex(day, i - 1);
|
||||
try {
|
||||
DateTime? startDate = prevLesson.last.start.add(const Duration(seconds: 1));
|
||||
indexLessons.add(Lesson.fromJson({'isEmpty': true, 'Oraszam': i, 'KezdetIdopont': startDate.toIso8601String()}));
|
||||
// ignore: empty_catches
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
day.addAll(indexLessons);
|
||||
}
|
||||
}
|
||||
|
||||
// Additional lessons
|
||||
day.addAll(_day.where((l) => int.tryParse(l.lessonIndex) == null && l.subject.id != ''));
|
||||
|
||||
day.sort((a, b) => a.start.compareTo(b.start));
|
||||
|
||||
// Special Dates
|
||||
for (var l in _day) {
|
||||
l.subject.id == '' ? day.insert(0, l) : null;
|
||||
}
|
||||
|
||||
days[i] = day;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
log("_sortDays error: $e");
|
||||
}
|
||||
|
||||
return days;
|
||||
}
|
||||
|
||||
List<Lesson> _getLessonsByIndex(List<Lesson> lessons, int index) {
|
||||
List<Lesson> ret = [];
|
||||
|
||||
for (var lesson in lessons) {
|
||||
int? lessonIndex = int.tryParse(lesson.lessonIndex);
|
||||
|
||||
if (lessonIndex != null && lessonIndex == index) {
|
||||
ret.add(lesson);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
List<int> _getIndexes(List<Lesson> lessons) {
|
||||
List<int> indexes = [];
|
||||
for (var l in lessons) {
|
||||
int? index = int.tryParse(l.lessonIndex);
|
||||
if (index != null) indexes.add(index);
|
||||
}
|
||||
return indexes;
|
||||
}
|
||||
|
||||
bool _differentDate(DateTime a, DateTime b) => !(a.year == b.year && a.month == b.month && a.day == b.day);
|
||||
}
|
||||
|
||||
@@ -1,76 +1,76 @@
|
||||
import "category.dart";
|
||||
import "subject.dart";
|
||||
|
||||
class Absence {
|
||||
Map? json;
|
||||
String id;
|
||||
DateTime date;
|
||||
int delay;
|
||||
DateTime submitDate;
|
||||
String teacher;
|
||||
Justification state;
|
||||
Category? justification;
|
||||
Category? type;
|
||||
Category? mode;
|
||||
Subject subject;
|
||||
DateTime lessonStart;
|
||||
DateTime lessonEnd;
|
||||
int? lessonIndex;
|
||||
String group;
|
||||
|
||||
Absence({
|
||||
required this.id,
|
||||
required this.date,
|
||||
required this.delay,
|
||||
required this.submitDate,
|
||||
required this.teacher,
|
||||
required this.state,
|
||||
this.justification,
|
||||
this.type,
|
||||
this.mode,
|
||||
required this.subject,
|
||||
required this.lessonStart,
|
||||
required this.lessonEnd,
|
||||
this.lessonIndex,
|
||||
required this.group,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Absence.fromJson(Map json) {
|
||||
DateTime lessonStart;
|
||||
DateTime lessonEnd;
|
||||
int? lessonIndex;
|
||||
if (json["Ora"] != null) {
|
||||
lessonStart = json["Ora"]["KezdoDatum"] != null ? DateTime.parse(json["Ora"]["KezdoDatum"]).toLocal() : DateTime(0);
|
||||
lessonEnd = json["Ora"]["VegDatum"] != null ? DateTime.parse(json["Ora"]["VegDatum"]).toLocal() : DateTime(0);
|
||||
lessonIndex = json["Ora"]["Oraszam"];
|
||||
} else {
|
||||
lessonStart = DateTime(0);
|
||||
lessonEnd = DateTime(0);
|
||||
}
|
||||
|
||||
return Absence(
|
||||
id: json["Uid"],
|
||||
date: json["Datum"] != null ? DateTime.parse(json["Datum"]).toLocal() : DateTime(0),
|
||||
delay: json["KesesPercben"] ?? 0,
|
||||
submitDate: json["KeszitesDatuma"] != null ? DateTime.parse(json["KeszitesDatuma"]).toLocal() : DateTime(0),
|
||||
teacher: (json["RogzitoTanarNeve"] ?? "").trim(),
|
||||
state: json["IgazolasAllapota"] == "Igazolt"
|
||||
? Justification.excused
|
||||
: json["IgazolasAllapota"] == "Igazolando"
|
||||
? Justification.pending
|
||||
: Justification.unexcused,
|
||||
justification: json["IgazolasTipusa"] != null ? Category.fromJson(json["IgazolasTipusa"]) : null,
|
||||
type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
|
||||
mode: json["Mod"] != null ? Category.fromJson(json["Mod"]) : null,
|
||||
subject: Subject.fromJson(json["Tantargy"] ?? {}),
|
||||
lessonStart: lessonStart,
|
||||
lessonEnd: lessonEnd,
|
||||
lessonIndex: lessonIndex,
|
||||
group: json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] : "",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
import "category.dart";
|
||||
import "subject.dart";
|
||||
|
||||
class Absence {
|
||||
Map? json;
|
||||
String id;
|
||||
DateTime date;
|
||||
int delay;
|
||||
DateTime submitDate;
|
||||
String teacher;
|
||||
Justification state;
|
||||
Category? justification;
|
||||
Category? type;
|
||||
Category? mode;
|
||||
Subject subject;
|
||||
DateTime lessonStart;
|
||||
DateTime lessonEnd;
|
||||
int? lessonIndex;
|
||||
String group;
|
||||
|
||||
Absence({
|
||||
required this.id,
|
||||
required this.date,
|
||||
required this.delay,
|
||||
required this.submitDate,
|
||||
required this.teacher,
|
||||
required this.state,
|
||||
this.justification,
|
||||
this.type,
|
||||
this.mode,
|
||||
required this.subject,
|
||||
required this.lessonStart,
|
||||
required this.lessonEnd,
|
||||
this.lessonIndex,
|
||||
required this.group,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Absence.fromJson(Map json) {
|
||||
DateTime lessonStart;
|
||||
DateTime lessonEnd;
|
||||
int? lessonIndex;
|
||||
if (json["Ora"] != null) {
|
||||
lessonStart = json["Ora"]["KezdoDatum"] != null ? DateTime.parse(json["Ora"]["KezdoDatum"]).toLocal() : DateTime(0);
|
||||
lessonEnd = json["Ora"]["VegDatum"] != null ? DateTime.parse(json["Ora"]["VegDatum"]).toLocal() : DateTime(0);
|
||||
lessonIndex = json["Ora"]["Oraszam"];
|
||||
} else {
|
||||
lessonStart = DateTime(0);
|
||||
lessonEnd = DateTime(0);
|
||||
}
|
||||
|
||||
return Absence(
|
||||
id: json["Uid"],
|
||||
date: json["Datum"] != null ? DateTime.parse(json["Datum"]).toLocal() : DateTime(0),
|
||||
delay: json["KesesPercben"] ?? 0,
|
||||
submitDate: json["KeszitesDatuma"] != null ? DateTime.parse(json["KeszitesDatuma"]).toLocal() : DateTime(0),
|
||||
teacher: (json["RogzitoTanarNeve"] ?? "").trim(),
|
||||
state: json["IgazolasAllapota"] == "Igazolt"
|
||||
? Justification.excused
|
||||
: json["IgazolasAllapota"] == "Igazolando"
|
||||
? Justification.pending
|
||||
: Justification.unexcused,
|
||||
justification: json["IgazolasTipusa"] != null ? Category.fromJson(json["IgazolasTipusa"]) : null,
|
||||
type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
|
||||
mode: json["Mod"] != null ? Category.fromJson(json["Mod"]) : null,
|
||||
subject: Subject.fromJson(json["Tantargy"] ?? {}),
|
||||
lessonStart: lessonStart,
|
||||
lessonEnd: lessonEnd,
|
||||
lessonIndex: lessonIndex,
|
||||
group: json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] : "",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum Justification { excused, unexcused, pending }
|
||||
@@ -1,32 +1,32 @@
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
|
||||
class Attachment {
|
||||
Map? json;
|
||||
int id;
|
||||
PlatformFile? file;
|
||||
String name;
|
||||
String? fileId;
|
||||
String kretaFilePath;
|
||||
|
||||
Attachment({
|
||||
required this.id,
|
||||
this.file,
|
||||
required this.name,
|
||||
this.fileId,
|
||||
required this.kretaFilePath,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Attachment.fromJson(Map json) {
|
||||
return Attachment(
|
||||
id: json["azonosito"],
|
||||
name: (json["fajlNev"] ?? "attachment").trim(),
|
||||
kretaFilePath: json["utvonal"] ?? "",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
|
||||
String get downloadUrl => KretaAPI.downloadAttachment(id.toString());
|
||||
bool get isImage => name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".png");
|
||||
}
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
|
||||
class Attachment {
|
||||
Map? json;
|
||||
int id;
|
||||
PlatformFile? file;
|
||||
String name;
|
||||
String? fileId;
|
||||
String kretaFilePath;
|
||||
|
||||
Attachment({
|
||||
required this.id,
|
||||
this.file,
|
||||
required this.name,
|
||||
this.fileId,
|
||||
required this.kretaFilePath,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Attachment.fromJson(Map json) {
|
||||
return Attachment(
|
||||
id: json["azonosito"],
|
||||
name: (json["fajlNev"] ?? "attachment").trim(),
|
||||
kretaFilePath: json["utvonal"] ?? "",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
|
||||
String get downloadUrl => KretaAPI.downloadAttachment(id.toString());
|
||||
bool get isImage => name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".png");
|
||||
}
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
import 'grade.dart';
|
||||
|
||||
class Category {
|
||||
String id;
|
||||
String description;
|
||||
String name;
|
||||
|
||||
Category({
|
||||
required this.id,
|
||||
this.description = "",
|
||||
this.name = "",
|
||||
});
|
||||
|
||||
factory Category.fromJson(Map json) {
|
||||
return Category(
|
||||
id: json["Uid"] ?? "",
|
||||
description: json["Leiras"] != "Na" ? json["Leiras"] ?? "" : "",
|
||||
name: json["Nev"] != "Na" ? json["Nev"] ?? "" : "",
|
||||
);
|
||||
}
|
||||
|
||||
static GradeType getGradeType(String string) {
|
||||
switch (string) {
|
||||
case "evkozi_jegy_ertekeles":
|
||||
return GradeType.midYear;
|
||||
case "I_ne_jegy_ertekeles":
|
||||
return GradeType.firstQ;
|
||||
case "II_ne_jegy_ertekeles":
|
||||
return GradeType.secondQ;
|
||||
case "felevi_jegy_ertekeles":
|
||||
return GradeType.halfYear;
|
||||
case "III_ne_jegy_ertekeles":
|
||||
return GradeType.thirdQ;
|
||||
case "IV_ne_jegy_ertekeles":
|
||||
return GradeType.fourthQ;
|
||||
case "evvegi_jegy_ertekeles":
|
||||
return GradeType.endYear;
|
||||
case "osztalyozo_vizsga":
|
||||
return GradeType.levelExam;
|
||||
default:
|
||||
return GradeType.unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
import 'grade.dart';
|
||||
|
||||
class Category {
|
||||
String id;
|
||||
String description;
|
||||
String name;
|
||||
|
||||
Category({
|
||||
required this.id,
|
||||
this.description = "",
|
||||
this.name = "",
|
||||
});
|
||||
|
||||
factory Category.fromJson(Map json) {
|
||||
return Category(
|
||||
id: json["Uid"] ?? "",
|
||||
description: json["Leiras"] != "Na" ? json["Leiras"] ?? "" : "",
|
||||
name: json["Nev"] != "Na" ? json["Nev"] ?? "" : "",
|
||||
);
|
||||
}
|
||||
|
||||
static GradeType getGradeType(String string) {
|
||||
switch (string) {
|
||||
case "evkozi_jegy_ertekeles":
|
||||
return GradeType.midYear;
|
||||
case "I_ne_jegy_ertekeles":
|
||||
return GradeType.firstQ;
|
||||
case "II_ne_jegy_ertekeles":
|
||||
return GradeType.secondQ;
|
||||
case "felevi_jegy_ertekeles":
|
||||
return GradeType.halfYear;
|
||||
case "III_ne_jegy_ertekeles":
|
||||
return GradeType.thirdQ;
|
||||
case "IV_ne_jegy_ertekeles":
|
||||
return GradeType.fourthQ;
|
||||
case "evvegi_jegy_ertekeles":
|
||||
return GradeType.endYear;
|
||||
case "osztalyozo_vizsga":
|
||||
return GradeType.levelExam;
|
||||
default:
|
||||
return GradeType.unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
class Event {
|
||||
Map? json;
|
||||
String id;
|
||||
DateTime start;
|
||||
DateTime end;
|
||||
String title;
|
||||
String content;
|
||||
|
||||
Event({
|
||||
required this.id,
|
||||
required this.start,
|
||||
required this.end,
|
||||
this.title = "",
|
||||
this.content = "",
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Event.fromJson(Map json) {
|
||||
return Event(
|
||||
id: json["Uid"] ?? "",
|
||||
start: json["ErvenyessegKezdete"] != null ? DateTime.parse(json["ErvenyessegKezdete"]).toLocal() : DateTime(0),
|
||||
end: json["ErvenyessegVege"] != null ? DateTime.parse(json["ErvenyessegVege"]).toLocal() : DateTime(0),
|
||||
title: json["Cim"] ?? "",
|
||||
content: json["Tartalom"] != null ? json["Tartalom"].replaceAll("\r", "") : "",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
class Event {
|
||||
Map? json;
|
||||
String id;
|
||||
DateTime start;
|
||||
DateTime end;
|
||||
String title;
|
||||
String content;
|
||||
|
||||
Event({
|
||||
required this.id,
|
||||
required this.start,
|
||||
required this.end,
|
||||
this.title = "",
|
||||
this.content = "",
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Event.fromJson(Map json) {
|
||||
return Event(
|
||||
id: json["Uid"] ?? "",
|
||||
start: json["ErvenyessegKezdete"] != null ? DateTime.parse(json["ErvenyessegKezdete"]).toLocal() : DateTime(0),
|
||||
end: json["ErvenyessegVege"] != null ? DateTime.parse(json["ErvenyessegVege"]).toLocal() : DateTime(0),
|
||||
title: json["Cim"] ?? "",
|
||||
content: json["Tartalom"] != null ? json["Tartalom"].replaceAll("\r", "") : "",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
import 'category.dart';
|
||||
|
||||
class Exam {
|
||||
Map? json;
|
||||
DateTime date;
|
||||
DateTime writeDate;
|
||||
Category? mode;
|
||||
int? subjectIndex;
|
||||
String subjectName;
|
||||
String teacher;
|
||||
String description;
|
||||
String group;
|
||||
String id;
|
||||
|
||||
Exam({
|
||||
required this.id,
|
||||
required this.date,
|
||||
required this.writeDate,
|
||||
this.mode,
|
||||
this.subjectIndex,
|
||||
required this.subjectName,
|
||||
required this.teacher,
|
||||
required this.description,
|
||||
required this.group,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Exam.fromJson(Map json) {
|
||||
return Exam(
|
||||
id: json["Uid"] ?? "",
|
||||
date: json["BejelentesDatuma"] != null ? DateTime.parse(json["BejelentesDatuma"]).toLocal() : DateTime(0),
|
||||
writeDate: json["Datum"] != null ? DateTime.parse(json["Datum"]).toLocal() : DateTime(0),
|
||||
mode: json["Modja"] != null ? Category.fromJson(json["Modja"]) : null,
|
||||
subjectIndex: json["OrarendiOraOraszama"],
|
||||
subjectName: json["TantargyNeve"] ?? "",
|
||||
teacher: (json["RogzitoTanarNeve"] ?? "").trim(),
|
||||
description: (json["Temaja"] ?? "").trim(),
|
||||
group: json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] ?? "" : "",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'category.dart';
|
||||
|
||||
class Exam {
|
||||
Map? json;
|
||||
DateTime date;
|
||||
DateTime writeDate;
|
||||
Category? mode;
|
||||
int? subjectIndex;
|
||||
String subjectName;
|
||||
String teacher;
|
||||
String description;
|
||||
String group;
|
||||
String id;
|
||||
|
||||
Exam({
|
||||
required this.id,
|
||||
required this.date,
|
||||
required this.writeDate,
|
||||
this.mode,
|
||||
this.subjectIndex,
|
||||
required this.subjectName,
|
||||
required this.teacher,
|
||||
required this.description,
|
||||
required this.group,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Exam.fromJson(Map json) {
|
||||
return Exam(
|
||||
id: json["Uid"] ?? "",
|
||||
date: json["BejelentesDatuma"] != null ? DateTime.parse(json["BejelentesDatuma"]).toLocal() : DateTime(0),
|
||||
writeDate: json["Datum"] != null ? DateTime.parse(json["Datum"]).toLocal() : DateTime(0),
|
||||
mode: json["Modja"] != null ? Category.fromJson(json["Modja"]) : null,
|
||||
subjectIndex: json["OrarendiOraOraszama"],
|
||||
subjectName: json["TantargyNeve"] ?? "",
|
||||
teacher: (json["RogzitoTanarNeve"] ?? "").trim(),
|
||||
description: (json["Temaja"] ?? "").trim(),
|
||||
group: json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] ?? "" : "",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,120 +1,120 @@
|
||||
import 'package:filcnaplo/utils/format.dart';
|
||||
import 'category.dart';
|
||||
import 'subject.dart';
|
||||
|
||||
class Grade {
|
||||
Map? json;
|
||||
String id;
|
||||
DateTime date;
|
||||
GradeValue value;
|
||||
String teacher;
|
||||
String description;
|
||||
GradeType type;
|
||||
String groupId;
|
||||
Subject subject;
|
||||
Category? gradeType;
|
||||
Category mode;
|
||||
DateTime writeDate;
|
||||
DateTime seenDate;
|
||||
String form;
|
||||
|
||||
Grade({
|
||||
required this.id,
|
||||
required this.date,
|
||||
required this.value,
|
||||
required this.teacher,
|
||||
required this.description,
|
||||
required this.type,
|
||||
required this.groupId,
|
||||
required this.subject,
|
||||
this.gradeType,
|
||||
required this.mode,
|
||||
required this.writeDate,
|
||||
required this.seenDate,
|
||||
required this.form,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Grade.fromJson(Map json) {
|
||||
return Grade(
|
||||
id: json["Uid"] ?? "",
|
||||
date: json["KeszitesDatuma"] != null ? DateTime.parse(json["KeszitesDatuma"]).toLocal() : DateTime(0),
|
||||
value: GradeValue(
|
||||
json["SzamErtek"] ?? 0,
|
||||
json["SzovegesErtek"] ?? "",
|
||||
json["SzovegesErtekelesRovidNev"] ?? "",
|
||||
json["SulySzazalekErteke"] ?? 0,
|
||||
percentage: json["ErtekFajta"] != null ? json["ErtekFajta"]["Uid"] == "3,Szazalekos" : false,
|
||||
),
|
||||
teacher: (json["ErtekeloTanarNeve"] ?? "").trim(),
|
||||
description: json["Tema"] ?? "",
|
||||
type: json["Tipus"] != null ? Category.getGradeType(json["Tipus"]["Nev"]) : GradeType.unknown,
|
||||
groupId: (json["OsztalyCsoport"] ?? {})["Uid"] ?? "",
|
||||
subject: Subject.fromJson(json["Tantargy"] ?? {}),
|
||||
gradeType: json["ErtekFajta"] != null ? Category.fromJson(json["ErtekFajta"]) : null,
|
||||
mode: Category.fromJson(json["Mod"] ?? {}),
|
||||
writeDate: json["RogzitesDatuma"] != null ? DateTime.parse(json["RogzitesDatuma"]).toLocal() : DateTime(0),
|
||||
seenDate: json["LattamozasDatuma"] != null ? DateTime.parse(json["LattamozasDatuma"]).toLocal() : DateTime(0),
|
||||
form: (json["Jelleg"] ?? "Na") != "Na" ? json["Jelleg"] : "",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
|
||||
bool compareTo(dynamic other) {
|
||||
if (runtimeType != other.runtimeType) return false;
|
||||
|
||||
if (id == other.id && seenDate == other.seenDate) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class GradeValue {
|
||||
int _value;
|
||||
set value(int v) => _value = v;
|
||||
int get value {
|
||||
String _valueName = valueName.toLowerCase().specialChars();
|
||||
if (_value == 0 && ["peldas", "jo", "valtozo", "rossz", "hanyag"].contains(_valueName)) {
|
||||
switch (_valueName) {
|
||||
case "peldas":
|
||||
return 5;
|
||||
case "jo":
|
||||
return 4;
|
||||
case "valtozo":
|
||||
return 3;
|
||||
case "rossz":
|
||||
return 2;
|
||||
case "hanyag":
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return _value;
|
||||
}
|
||||
|
||||
String _valueName;
|
||||
set valueName(String v) => _valueName = v;
|
||||
String get valueName => _valueName.split("(")[0];
|
||||
String shortName;
|
||||
int _weight;
|
||||
set weight(int v) => _weight = v;
|
||||
int get weight {
|
||||
String _valueName = valueName.toLowerCase().specialChars();
|
||||
if (_value == 0 && ["peldas", "jo", "valtozo", "rossz", "hanyag"].contains(_valueName)) {
|
||||
return 0;
|
||||
}
|
||||
return _weight;
|
||||
}
|
||||
|
||||
final bool _percentage;
|
||||
bool get percentage => _percentage;
|
||||
|
||||
GradeValue(int value, String valueName, this.shortName, int weight, {bool percentage = false})
|
||||
: _value = value,
|
||||
_valueName = valueName,
|
||||
_weight = weight,
|
||||
_percentage = percentage;
|
||||
}
|
||||
|
||||
enum GradeType { midYear, firstQ, secondQ, halfYear, thirdQ, fourthQ, endYear, levelExam, ghost, unknown }
|
||||
import 'package:filcnaplo/utils/format.dart';
|
||||
import 'category.dart';
|
||||
import 'subject.dart';
|
||||
|
||||
class Grade {
|
||||
Map? json;
|
||||
String id;
|
||||
DateTime date;
|
||||
GradeValue value;
|
||||
String teacher;
|
||||
String description;
|
||||
GradeType type;
|
||||
String groupId;
|
||||
Subject subject;
|
||||
Category? gradeType;
|
||||
Category mode;
|
||||
DateTime writeDate;
|
||||
DateTime seenDate;
|
||||
String form;
|
||||
|
||||
Grade({
|
||||
required this.id,
|
||||
required this.date,
|
||||
required this.value,
|
||||
required this.teacher,
|
||||
required this.description,
|
||||
required this.type,
|
||||
required this.groupId,
|
||||
required this.subject,
|
||||
this.gradeType,
|
||||
required this.mode,
|
||||
required this.writeDate,
|
||||
required this.seenDate,
|
||||
required this.form,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Grade.fromJson(Map json) {
|
||||
return Grade(
|
||||
id: json["Uid"] ?? "",
|
||||
date: json["KeszitesDatuma"] != null ? DateTime.parse(json["KeszitesDatuma"]).toLocal() : DateTime(0),
|
||||
value: GradeValue(
|
||||
json["SzamErtek"] ?? 0,
|
||||
json["SzovegesErtek"] ?? "",
|
||||
json["SzovegesErtekelesRovidNev"] ?? "",
|
||||
json["SulySzazalekErteke"] ?? 0,
|
||||
percentage: json["ErtekFajta"] != null ? json["ErtekFajta"]["Uid"] == "3,Szazalekos" : false,
|
||||
),
|
||||
teacher: (json["ErtekeloTanarNeve"] ?? "").trim(),
|
||||
description: json["Tema"] ?? "",
|
||||
type: json["Tipus"] != null ? Category.getGradeType(json["Tipus"]["Nev"]) : GradeType.unknown,
|
||||
groupId: (json["OsztalyCsoport"] ?? {})["Uid"] ?? "",
|
||||
subject: Subject.fromJson(json["Tantargy"] ?? {}),
|
||||
gradeType: json["ErtekFajta"] != null ? Category.fromJson(json["ErtekFajta"]) : null,
|
||||
mode: Category.fromJson(json["Mod"] ?? {}),
|
||||
writeDate: json["RogzitesDatuma"] != null ? DateTime.parse(json["RogzitesDatuma"]).toLocal() : DateTime(0),
|
||||
seenDate: json["LattamozasDatuma"] != null ? DateTime.parse(json["LattamozasDatuma"]).toLocal() : DateTime(0),
|
||||
form: (json["Jelleg"] ?? "Na") != "Na" ? json["Jelleg"] : "",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
|
||||
bool compareTo(dynamic other) {
|
||||
if (runtimeType != other.runtimeType) return false;
|
||||
|
||||
if (id == other.id && seenDate == other.seenDate) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class GradeValue {
|
||||
int _value;
|
||||
set value(int v) => _value = v;
|
||||
int get value {
|
||||
String _valueName = valueName.toLowerCase().specialChars();
|
||||
if (_value == 0 && ["peldas", "jo", "valtozo", "rossz", "hanyag"].contains(_valueName)) {
|
||||
switch (_valueName) {
|
||||
case "peldas":
|
||||
return 5;
|
||||
case "jo":
|
||||
return 4;
|
||||
case "valtozo":
|
||||
return 3;
|
||||
case "rossz":
|
||||
return 2;
|
||||
case "hanyag":
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
return _value;
|
||||
}
|
||||
|
||||
String _valueName;
|
||||
set valueName(String v) => _valueName = v;
|
||||
String get valueName => _valueName.split("(")[0];
|
||||
String shortName;
|
||||
int _weight;
|
||||
set weight(int v) => _weight = v;
|
||||
int get weight {
|
||||
String _valueName = valueName.toLowerCase().specialChars();
|
||||
if (_value == 0 && ["peldas", "jo", "valtozo", "rossz", "hanyag"].contains(_valueName)) {
|
||||
return 0;
|
||||
}
|
||||
return _weight;
|
||||
}
|
||||
|
||||
final bool _percentage;
|
||||
bool get percentage => _percentage;
|
||||
|
||||
GradeValue(int value, String valueName, this.shortName, int weight, {bool percentage = false})
|
||||
: _value = value,
|
||||
_valueName = valueName,
|
||||
_weight = weight,
|
||||
_percentage = percentage;
|
||||
}
|
||||
|
||||
enum GradeType { midYear, firstQ, secondQ, halfYear, thirdQ, fourthQ, endYear, levelExam, ghost, unknown }
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import 'package:filcnaplo_kreta_api/models/subject.dart';
|
||||
|
||||
class GroupAverage {
|
||||
String uid;
|
||||
double average;
|
||||
Subject subject;
|
||||
Map json;
|
||||
|
||||
GroupAverage({required this.uid, required this.average, required this.subject, this.json = const {}});
|
||||
|
||||
factory GroupAverage.fromJson(Map json) {
|
||||
return GroupAverage(
|
||||
uid: json["Uid"] ?? "",
|
||||
average: json["OsztalyCsoportAtlag"] ?? 0,
|
||||
subject: Subject.fromJson(json["Tantargy"] ?? {}),
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'package:filcnaplo_kreta_api/models/subject.dart';
|
||||
|
||||
class GroupAverage {
|
||||
String uid;
|
||||
double average;
|
||||
Subject subject;
|
||||
Map json;
|
||||
|
||||
GroupAverage({required this.uid, required this.average, required this.subject, this.json = const {}});
|
||||
|
||||
factory GroupAverage.fromJson(Map json) {
|
||||
return GroupAverage(
|
||||
uid: json["Uid"] ?? "",
|
||||
average: json["OsztalyCsoportAtlag"] ?? 0,
|
||||
subject: Subject.fromJson(json["Tantargy"] ?? {}),
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,69 +1,69 @@
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
|
||||
class Homework {
|
||||
Map? json;
|
||||
DateTime date;
|
||||
DateTime lessonDate;
|
||||
DateTime deadline;
|
||||
bool byTeacher;
|
||||
bool homeworkEnabled;
|
||||
String teacher;
|
||||
String content;
|
||||
String subjectName;
|
||||
String group;
|
||||
List<HomeworkAttachment> attachments;
|
||||
String id;
|
||||
|
||||
Homework({
|
||||
required this.date,
|
||||
required this.lessonDate,
|
||||
required this.deadline,
|
||||
required this.byTeacher,
|
||||
required this.homeworkEnabled,
|
||||
required this.teacher,
|
||||
required this.content,
|
||||
required this.subjectName,
|
||||
required this.group,
|
||||
required this.attachments,
|
||||
required this.id,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Homework.fromJson(Map json) {
|
||||
return Homework(
|
||||
id: json["Uid"] ?? "",
|
||||
date: json["RogzitesIdopontja"] != null ? DateTime.parse(json["RogzitesIdopontja"]).toLocal() : DateTime(0),
|
||||
lessonDate: json["FeladasDatuma"] != null ? DateTime.parse(json["FeladasDatuma"]).toLocal() : DateTime(0),
|
||||
deadline: json["HataridoDatuma"] != null ? DateTime.parse(json["HataridoDatuma"]).toLocal() : DateTime(0),
|
||||
byTeacher: json["IsTanarRogzitette"] ?? true,
|
||||
homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false,
|
||||
teacher: (json["RogzitoTanarNeve"] ?? "").trim(),
|
||||
content: (json["Szoveg"] ?? "").trim(),
|
||||
subjectName: json["TantargyNeve"] ?? "",
|
||||
group: json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] ?? "" : "",
|
||||
attachments: ((json["Csatolmanyok"] ?? []) as List).cast<Map>().map((Map json) => HomeworkAttachment.fromJson(json)).toList(),
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HomeworkAttachment {
|
||||
Map? json;
|
||||
String id;
|
||||
String name;
|
||||
String type;
|
||||
|
||||
HomeworkAttachment({required this.id, this.name = "", this.type = "", this.json});
|
||||
|
||||
factory HomeworkAttachment.fromJson(Map json) {
|
||||
return HomeworkAttachment(
|
||||
id: json["Uid"] ?? "",
|
||||
name: json["Nev"] ?? "",
|
||||
type: json["Tipus"] ?? "",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
|
||||
String downloadUrl(String iss) => KretaAPI.downloadHomeworkAttachments(iss, id, type);
|
||||
bool get isImage => name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".png");
|
||||
}
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
|
||||
class Homework {
|
||||
Map? json;
|
||||
DateTime date;
|
||||
DateTime lessonDate;
|
||||
DateTime deadline;
|
||||
bool byTeacher;
|
||||
bool homeworkEnabled;
|
||||
String teacher;
|
||||
String content;
|
||||
String subjectName;
|
||||
String group;
|
||||
List<HomeworkAttachment> attachments;
|
||||
String id;
|
||||
|
||||
Homework({
|
||||
required this.date,
|
||||
required this.lessonDate,
|
||||
required this.deadline,
|
||||
required this.byTeacher,
|
||||
required this.homeworkEnabled,
|
||||
required this.teacher,
|
||||
required this.content,
|
||||
required this.subjectName,
|
||||
required this.group,
|
||||
required this.attachments,
|
||||
required this.id,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Homework.fromJson(Map json) {
|
||||
return Homework(
|
||||
id: json["Uid"] ?? "",
|
||||
date: json["RogzitesIdopontja"] != null ? DateTime.parse(json["RogzitesIdopontja"]).toLocal() : DateTime(0),
|
||||
lessonDate: json["FeladasDatuma"] != null ? DateTime.parse(json["FeladasDatuma"]).toLocal() : DateTime(0),
|
||||
deadline: json["HataridoDatuma"] != null ? DateTime.parse(json["HataridoDatuma"]).toLocal() : DateTime(0),
|
||||
byTeacher: json["IsTanarRogzitette"] ?? true,
|
||||
homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false,
|
||||
teacher: (json["RogzitoTanarNeve"] ?? "").trim(),
|
||||
content: (json["Szoveg"] ?? "").trim(),
|
||||
subjectName: json["TantargyNeve"] ?? "",
|
||||
group: json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] ?? "" : "",
|
||||
attachments: ((json["Csatolmanyok"] ?? []) as List).cast<Map>().map((Map json) => HomeworkAttachment.fromJson(json)).toList(),
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HomeworkAttachment {
|
||||
Map? json;
|
||||
String id;
|
||||
String name;
|
||||
String type;
|
||||
|
||||
HomeworkAttachment({required this.id, this.name = "", this.type = "", this.json});
|
||||
|
||||
factory HomeworkAttachment.fromJson(Map json) {
|
||||
return HomeworkAttachment(
|
||||
id: json["Uid"] ?? "",
|
||||
name: json["Nev"] ?? "",
|
||||
type: json["Tipus"] ?? "",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
|
||||
String downloadUrl(String iss) => KretaAPI.downloadHomeworkAttachments(iss, id, type);
|
||||
bool get isImage => name.endsWith(".jpg") || name.endsWith(".jpeg") || name.endsWith(".png");
|
||||
}
|
||||
|
||||
@@ -1,97 +1,97 @@
|
||||
import 'subject.dart';
|
||||
import 'category.dart';
|
||||
|
||||
class Lesson {
|
||||
Map? json;
|
||||
Category? status;
|
||||
DateTime date;
|
||||
Subject subject;
|
||||
String lessonIndex;
|
||||
int? lessonYearIndex;
|
||||
String substituteTeacher;
|
||||
String teacher;
|
||||
bool homeworkEnabled;
|
||||
DateTime start;
|
||||
DateTime end;
|
||||
bool studentPresence;
|
||||
String homeworkId;
|
||||
String exam;
|
||||
String id;
|
||||
Category? type;
|
||||
String description;
|
||||
String room;
|
||||
String groupName;
|
||||
String name;
|
||||
bool online;
|
||||
bool isEmpty;
|
||||
|
||||
Lesson({
|
||||
this.status,
|
||||
required this.date,
|
||||
required this.subject,
|
||||
required this.lessonIndex,
|
||||
this.lessonYearIndex,
|
||||
this.substituteTeacher = "",
|
||||
required this.teacher,
|
||||
this.homeworkEnabled = false,
|
||||
required this.start,
|
||||
required this.end,
|
||||
this.studentPresence = true,
|
||||
required this.homeworkId,
|
||||
this.exam = "",
|
||||
required this.id,
|
||||
this.type,
|
||||
required this.description,
|
||||
required this.room,
|
||||
required this.groupName,
|
||||
required this.name,
|
||||
this.online = false,
|
||||
this.isEmpty = false,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Lesson.fromJson(Map json) {
|
||||
return Lesson(
|
||||
id: json["Uid"] ?? "",
|
||||
status: json["Allapot"] != null ? Category.fromJson(json["Allapot"]) : null,
|
||||
date: json["Datum"] != null ? DateTime.parse(json["Datum"]).toLocal() : DateTime(0),
|
||||
subject: Subject.fromJson(json["Tantargy"] ?? {}),
|
||||
lessonIndex: json["Oraszam"] != null ? json["Oraszam"].toString() : "+",
|
||||
lessonYearIndex: json["OraEvesSorszama"],
|
||||
substituteTeacher: (json["HelyettesTanarNeve"] ?? "").trim(),
|
||||
teacher: (json["TanarNeve"] ?? "").trim(),
|
||||
homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false,
|
||||
start: json["KezdetIdopont"] != null ? DateTime.parse(json["KezdetIdopont"]).toLocal() : DateTime(0),
|
||||
studentPresence: json["TanuloJelenlet"] != null
|
||||
? (json["TanuloJelenlet"]["Nev"] ?? "") == "Hianyzas"
|
||||
? false
|
||||
: true
|
||||
: true,
|
||||
end: json["VegIdopont"] != null ? DateTime.parse(json["VegIdopont"]).toLocal() : DateTime(0),
|
||||
homeworkId: json["HaziFeladatUid"] ?? "",
|
||||
exam: json["BejelentettSzamonkeresUid"] ?? "",
|
||||
type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
|
||||
description: json["Tema"] ?? "",
|
||||
room: ((json["TeremNeve"] ?? "").split("_").join(" ") as String).replaceAll(RegExp(r" ?terem ?", caseSensitive: false), ""),
|
||||
groupName: json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Nev"] ?? "" : "",
|
||||
name: json["Nev"] ?? "",
|
||||
online: json["IsDigitalisOra"] ?? false,
|
||||
isEmpty: json['isEmpty'] ?? false,
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
|
||||
int? getFloor() {
|
||||
final match = RegExp(r"(\d{3})").firstMatch(room);
|
||||
if (match != null) {
|
||||
final floorNumber = int.tryParse(match[0] ?? "");
|
||||
if (floorNumber != null) {
|
||||
return (floorNumber / 100).floor();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
bool get isChanged => status?.name == "Elmaradt" || substituteTeacher != "";
|
||||
bool get swapDesc => room.length > 8;
|
||||
}
|
||||
import 'subject.dart';
|
||||
import 'category.dart';
|
||||
|
||||
class Lesson {
|
||||
Map? json;
|
||||
Category? status;
|
||||
DateTime date;
|
||||
Subject subject;
|
||||
String lessonIndex;
|
||||
int? lessonYearIndex;
|
||||
String substituteTeacher;
|
||||
String teacher;
|
||||
bool homeworkEnabled;
|
||||
DateTime start;
|
||||
DateTime end;
|
||||
bool studentPresence;
|
||||
String homeworkId;
|
||||
String exam;
|
||||
String id;
|
||||
Category? type;
|
||||
String description;
|
||||
String room;
|
||||
String groupName;
|
||||
String name;
|
||||
bool online;
|
||||
bool isEmpty;
|
||||
|
||||
Lesson({
|
||||
this.status,
|
||||
required this.date,
|
||||
required this.subject,
|
||||
required this.lessonIndex,
|
||||
this.lessonYearIndex,
|
||||
this.substituteTeacher = "",
|
||||
required this.teacher,
|
||||
this.homeworkEnabled = false,
|
||||
required this.start,
|
||||
required this.end,
|
||||
this.studentPresence = true,
|
||||
required this.homeworkId,
|
||||
this.exam = "",
|
||||
required this.id,
|
||||
this.type,
|
||||
required this.description,
|
||||
required this.room,
|
||||
required this.groupName,
|
||||
required this.name,
|
||||
this.online = false,
|
||||
this.isEmpty = false,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Lesson.fromJson(Map json) {
|
||||
return Lesson(
|
||||
id: json["Uid"] ?? "",
|
||||
status: json["Allapot"] != null ? Category.fromJson(json["Allapot"]) : null,
|
||||
date: json["Datum"] != null ? DateTime.parse(json["Datum"]).toLocal() : DateTime(0),
|
||||
subject: Subject.fromJson(json["Tantargy"] ?? {}),
|
||||
lessonIndex: json["Oraszam"] != null ? json["Oraszam"].toString() : "+",
|
||||
lessonYearIndex: json["OraEvesSorszama"],
|
||||
substituteTeacher: (json["HelyettesTanarNeve"] ?? "").trim(),
|
||||
teacher: (json["TanarNeve"] ?? "").trim(),
|
||||
homeworkEnabled: json["IsTanuloHaziFeladatEnabled"] ?? false,
|
||||
start: json["KezdetIdopont"] != null ? DateTime.parse(json["KezdetIdopont"]).toLocal() : DateTime(0),
|
||||
studentPresence: json["TanuloJelenlet"] != null
|
||||
? (json["TanuloJelenlet"]["Nev"] ?? "") == "Hianyzas"
|
||||
? false
|
||||
: true
|
||||
: true,
|
||||
end: json["VegIdopont"] != null ? DateTime.parse(json["VegIdopont"]).toLocal() : DateTime(0),
|
||||
homeworkId: json["HaziFeladatUid"] ?? "",
|
||||
exam: json["BejelentettSzamonkeresUid"] ?? "",
|
||||
type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
|
||||
description: json["Tema"] ?? "",
|
||||
room: ((json["TeremNeve"] ?? "").split("_").join(" ") as String).replaceAll(RegExp(r" ?terem ?", caseSensitive: false), ""),
|
||||
groupName: json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Nev"] ?? "" : "",
|
||||
name: json["Nev"] ?? "",
|
||||
online: json["IsDigitalisOra"] ?? false,
|
||||
isEmpty: json['isEmpty'] ?? false,
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
|
||||
int? getFloor() {
|
||||
final match = RegExp(r"(\d{3})").firstMatch(room);
|
||||
if (match != null) {
|
||||
final floorNumber = int.tryParse(match[0] ?? "");
|
||||
if (floorNumber != null) {
|
||||
return (floorNumber / 100).floor();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
bool get isChanged => status?.name == "Elmaradt" || substituteTeacher != "";
|
||||
bool get swapDesc => room.length > 8;
|
||||
}
|
||||
|
||||
@@ -1,97 +1,97 @@
|
||||
import 'recipient.dart';
|
||||
import 'attachment.dart';
|
||||
|
||||
class Message {
|
||||
Map? json;
|
||||
int id;
|
||||
int? replyId;
|
||||
int messageId;
|
||||
int? conversationId;
|
||||
bool seen;
|
||||
bool deleted;
|
||||
DateTime date;
|
||||
String author;
|
||||
String content;
|
||||
String subject;
|
||||
MessageType? type;
|
||||
List<Recipient> recipients;
|
||||
List<Attachment> attachments;
|
||||
|
||||
Message({
|
||||
required this.id,
|
||||
required this.messageId,
|
||||
required this.seen,
|
||||
required this.deleted,
|
||||
required this.date,
|
||||
required this.author,
|
||||
required this.content,
|
||||
required this.subject,
|
||||
this.type,
|
||||
required this.recipients,
|
||||
required this.attachments,
|
||||
this.replyId,
|
||||
this.conversationId,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Message.fromJson(Map json, {MessageType? forceType}) {
|
||||
Map message = json["uzenet"];
|
||||
|
||||
MessageType? type = forceType;
|
||||
if (type == null) {
|
||||
switch (json["tipus"]["kod"]) {
|
||||
case "BEERKEZETT":
|
||||
type = MessageType.inbox;
|
||||
break;
|
||||
case "ELKULDOTT":
|
||||
type = MessageType.sent;
|
||||
break;
|
||||
case "PISZKOZAT":
|
||||
type = MessageType.draft;
|
||||
break;
|
||||
}
|
||||
|
||||
if (json["isToroltElem"] == true) type = MessageType.trash;
|
||||
}
|
||||
|
||||
return Message(
|
||||
id: json["azonosito"],
|
||||
messageId: message["azonosito"],
|
||||
seen: json["isElolvasva"] ?? false,
|
||||
deleted: json["isToroltElem"] ?? false,
|
||||
date: message["kuldesDatum"] != null ? DateTime.parse(message["kuldesDatum"]).toLocal() : DateTime(0),
|
||||
author: (message["feladoNev"] ?? "").trim(),
|
||||
content: message["szoveg"].replaceAll("\r", "") ?? "",
|
||||
subject: message["targy"] ?? "",
|
||||
type: type,
|
||||
recipients: (message["cimzettLista"] as List).cast<Map>().map((Map recipient) => Recipient.fromJson(recipient)).toList(),
|
||||
attachments: (message["csatolmanyok"] as List).cast<Map>().map((Map attachment) => Attachment.fromJson(attachment)).toList(),
|
||||
replyId: message["elozoUzenetAzonosito"],
|
||||
conversationId: message["beszelgetesAzonosito"],
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
|
||||
bool compareTo(dynamic other) {
|
||||
if (runtimeType != other.runtimeType) return false;
|
||||
|
||||
return id == other.id && seen == other.seen && deleted == other.deleted;
|
||||
}
|
||||
}
|
||||
|
||||
enum MessageType { inbox, sent, trash, draft }
|
||||
|
||||
class Conversation {
|
||||
int id;
|
||||
late List<Message> _messages;
|
||||
List<Message> get messages => _messages;
|
||||
|
||||
Conversation({required this.id, List<Message> messages = const []}) {
|
||||
_messages = List.from(messages);
|
||||
}
|
||||
|
||||
void sort() => _messages.sort((a, b) => -a.date.compareTo(b.date));
|
||||
void add(Message message) => _messages.add(message);
|
||||
|
||||
Message get newest => _messages.first;
|
||||
}
|
||||
import 'recipient.dart';
|
||||
import 'attachment.dart';
|
||||
|
||||
class Message {
|
||||
Map? json;
|
||||
int id;
|
||||
int? replyId;
|
||||
int messageId;
|
||||
int? conversationId;
|
||||
bool seen;
|
||||
bool deleted;
|
||||
DateTime date;
|
||||
String author;
|
||||
String content;
|
||||
String subject;
|
||||
MessageType? type;
|
||||
List<Recipient> recipients;
|
||||
List<Attachment> attachments;
|
||||
|
||||
Message({
|
||||
required this.id,
|
||||
required this.messageId,
|
||||
required this.seen,
|
||||
required this.deleted,
|
||||
required this.date,
|
||||
required this.author,
|
||||
required this.content,
|
||||
required this.subject,
|
||||
this.type,
|
||||
required this.recipients,
|
||||
required this.attachments,
|
||||
this.replyId,
|
||||
this.conversationId,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Message.fromJson(Map json, {MessageType? forceType}) {
|
||||
Map message = json["uzenet"];
|
||||
|
||||
MessageType? type = forceType;
|
||||
if (type == null) {
|
||||
switch (json["tipus"]["kod"]) {
|
||||
case "BEERKEZETT":
|
||||
type = MessageType.inbox;
|
||||
break;
|
||||
case "ELKULDOTT":
|
||||
type = MessageType.sent;
|
||||
break;
|
||||
case "PISZKOZAT":
|
||||
type = MessageType.draft;
|
||||
break;
|
||||
}
|
||||
|
||||
if (json["isToroltElem"] == true) type = MessageType.trash;
|
||||
}
|
||||
|
||||
return Message(
|
||||
id: json["azonosito"],
|
||||
messageId: message["azonosito"],
|
||||
seen: json["isElolvasva"] ?? false,
|
||||
deleted: json["isToroltElem"] ?? false,
|
||||
date: message["kuldesDatum"] != null ? DateTime.parse(message["kuldesDatum"]).toLocal() : DateTime(0),
|
||||
author: (message["feladoNev"] ?? "").trim(),
|
||||
content: message["szoveg"].replaceAll("\r", "") ?? "",
|
||||
subject: message["targy"] ?? "",
|
||||
type: type,
|
||||
recipients: (message["cimzettLista"] as List).cast<Map>().map((Map recipient) => Recipient.fromJson(recipient)).toList(),
|
||||
attachments: (message["csatolmanyok"] as List).cast<Map>().map((Map attachment) => Attachment.fromJson(attachment)).toList(),
|
||||
replyId: message["elozoUzenetAzonosito"],
|
||||
conversationId: message["beszelgetesAzonosito"],
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
|
||||
bool compareTo(dynamic other) {
|
||||
if (runtimeType != other.runtimeType) return false;
|
||||
|
||||
return id == other.id && seen == other.seen && deleted == other.deleted;
|
||||
}
|
||||
}
|
||||
|
||||
enum MessageType { inbox, sent, trash, draft }
|
||||
|
||||
class Conversation {
|
||||
int id;
|
||||
late List<Message> _messages;
|
||||
List<Message> get messages => _messages;
|
||||
|
||||
Conversation({required this.id, List<Message> messages = const []}) {
|
||||
_messages = List.from(messages);
|
||||
}
|
||||
|
||||
void sort() => _messages.sort((a, b) => -a.date.compareTo(b.date));
|
||||
void add(Message message) => _messages.add(message);
|
||||
|
||||
Message get newest => _messages.first;
|
||||
}
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
import 'category.dart';
|
||||
|
||||
class Note {
|
||||
Map? json;
|
||||
String id;
|
||||
String title;
|
||||
DateTime date;
|
||||
DateTime submitDate;
|
||||
String teacher;
|
||||
DateTime seenDate;
|
||||
String groupId;
|
||||
String content;
|
||||
Category? type;
|
||||
|
||||
Note({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.date,
|
||||
required this.submitDate,
|
||||
required this.teacher,
|
||||
required this.seenDate,
|
||||
required this.groupId,
|
||||
required this.content,
|
||||
this.type,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Note.fromJson(Map json) {
|
||||
return Note(
|
||||
id: json["Uid"] ?? "",
|
||||
title: json["Cim"] ?? "",
|
||||
date: json["Datum"] != null ? DateTime.parse(json["Datum"]).toLocal() : DateTime(0),
|
||||
submitDate: json["KeszitesDatuma"] != null ? DateTime.parse(json["KeszitesDatuma"]).toLocal() : DateTime(0),
|
||||
teacher: (json["KeszitoTanarNeve"] ?? "").trim(),
|
||||
seenDate: json["LattamozasDatuma"] != null ? DateTime.parse(json["LattamozasDatuma"]).toLocal() : DateTime(0),
|
||||
groupId: json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] ?? "" : "",
|
||||
content: json["Tartalom"].replaceAll("\r", "") ?? "",
|
||||
type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'category.dart';
|
||||
|
||||
class Note {
|
||||
Map? json;
|
||||
String id;
|
||||
String title;
|
||||
DateTime date;
|
||||
DateTime submitDate;
|
||||
String teacher;
|
||||
DateTime seenDate;
|
||||
String groupId;
|
||||
String content;
|
||||
Category? type;
|
||||
|
||||
Note({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.date,
|
||||
required this.submitDate,
|
||||
required this.teacher,
|
||||
required this.seenDate,
|
||||
required this.groupId,
|
||||
required this.content,
|
||||
this.type,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Note.fromJson(Map json) {
|
||||
return Note(
|
||||
id: json["Uid"] ?? "",
|
||||
title: json["Cim"] ?? "",
|
||||
date: json["Datum"] != null ? DateTime.parse(json["Datum"]).toLocal() : DateTime(0),
|
||||
submitDate: json["KeszitesDatuma"] != null ? DateTime.parse(json["KeszitesDatuma"]).toLocal() : DateTime(0),
|
||||
teacher: (json["KeszitoTanarNeve"] ?? "").trim(),
|
||||
seenDate: json["LattamozasDatuma"] != null ? DateTime.parse(json["LattamozasDatuma"]).toLocal() : DateTime(0),
|
||||
groupId: json["OsztalyCsoport"] != null ? json["OsztalyCsoport"]["Uid"] ?? "" : "",
|
||||
content: json["Tartalom"].replaceAll("\r", "") ?? "",
|
||||
type: json["Tipus"] != null ? Category.fromJson(json["Tipus"]) : null,
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
class Recipient {
|
||||
Map? json;
|
||||
int id;
|
||||
String? studentId; // oktatasi azonosito
|
||||
int kretaId;
|
||||
String name;
|
||||
RecipientCategory? category;
|
||||
|
||||
Recipient({
|
||||
required this.id,
|
||||
this.studentId,
|
||||
required this.name,
|
||||
required this.kretaId,
|
||||
this.category,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Recipient.fromJson(Map json) {
|
||||
return Recipient(
|
||||
id: json["azonosito"],
|
||||
name: json["nev"] ?? "",
|
||||
kretaId: json["kretaAzonosito"],
|
||||
category: json["tipus"] != null ? RecipientCategory.fromJson(json["tipus"]) : null,
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RecipientCategory {
|
||||
Map? json;
|
||||
int id;
|
||||
String code;
|
||||
String shortName;
|
||||
String name;
|
||||
String description;
|
||||
|
||||
RecipientCategory({
|
||||
required this.id,
|
||||
required this.code,
|
||||
required this.shortName,
|
||||
required this.name,
|
||||
required this.description,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory RecipientCategory.fromJson(Map json) {
|
||||
return RecipientCategory(
|
||||
id: json["azonosito"],
|
||||
code: json["kod"] ?? "",
|
||||
shortName: json["rovidNev"] ?? "",
|
||||
name: json["nev"] ?? "",
|
||||
description: json["leiras"] ?? "",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
class Recipient {
|
||||
Map? json;
|
||||
int id;
|
||||
String? studentId; // oktatasi azonosito
|
||||
int kretaId;
|
||||
String name;
|
||||
RecipientCategory? category;
|
||||
|
||||
Recipient({
|
||||
required this.id,
|
||||
this.studentId,
|
||||
required this.name,
|
||||
required this.kretaId,
|
||||
this.category,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Recipient.fromJson(Map json) {
|
||||
return Recipient(
|
||||
id: json["azonosito"],
|
||||
name: json["nev"] ?? "",
|
||||
kretaId: json["kretaAzonosito"],
|
||||
category: json["tipus"] != null ? RecipientCategory.fromJson(json["tipus"]) : null,
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RecipientCategory {
|
||||
Map? json;
|
||||
int id;
|
||||
String code;
|
||||
String shortName;
|
||||
String name;
|
||||
String description;
|
||||
|
||||
RecipientCategory({
|
||||
required this.id,
|
||||
required this.code,
|
||||
required this.shortName,
|
||||
required this.name,
|
||||
required this.description,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory RecipientCategory.fromJson(Map json) {
|
||||
return RecipientCategory(
|
||||
id: json["azonosito"],
|
||||
code: json["kod"] ?? "",
|
||||
shortName: json["rovidNev"] ?? "",
|
||||
name: json["nev"] ?? "",
|
||||
description: json["leiras"] ?? "",
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
class School {
|
||||
String instituteCode;
|
||||
String name;
|
||||
String city;
|
||||
|
||||
School({
|
||||
required this.instituteCode,
|
||||
required this.name,
|
||||
required this.city,
|
||||
});
|
||||
|
||||
factory School.fromJson(Map json) {
|
||||
return School(
|
||||
instituteCode: json["instituteCode"] ?? "",
|
||||
name: (json["name"] ?? "").trim(),
|
||||
city: json["city"] ?? "",
|
||||
);
|
||||
}
|
||||
}
|
||||
class School {
|
||||
String instituteCode;
|
||||
String name;
|
||||
String city;
|
||||
|
||||
School({
|
||||
required this.instituteCode,
|
||||
required this.name,
|
||||
required this.city,
|
||||
});
|
||||
|
||||
factory School.fromJson(Map json) {
|
||||
return School(
|
||||
instituteCode: json["instituteCode"] ?? "",
|
||||
name: (json["name"] ?? "").trim(),
|
||||
city: json["city"] ?? "",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,55 +1,55 @@
|
||||
import 'school.dart';
|
||||
import 'package:filcnaplo/utils/format.dart';
|
||||
|
||||
class Student {
|
||||
Map? json;
|
||||
String id;
|
||||
String name;
|
||||
School school;
|
||||
DateTime birth;
|
||||
String yearId;
|
||||
String? address;
|
||||
String? groupId;
|
||||
List<String> parents;
|
||||
String? className;
|
||||
|
||||
Student({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.school,
|
||||
required this.birth,
|
||||
required this.yearId,
|
||||
this.address,
|
||||
required this.parents,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Student.fromJson(Map json) {
|
||||
List<String> parents = [];
|
||||
|
||||
parents = ((json["Gondviselok"] ?? []) as List).cast<Map>().map((e) => e["Nev"] ?? "").toList().cast<String>();
|
||||
if (json["AnyjaNeve"] != null) parents.insert(0, json["AnyjaNeve"]);
|
||||
|
||||
parents = parents.map((e) => e.capitalize()).toList(); // fix name casing
|
||||
parents = parents.toSet().toList(); // remove duplicates
|
||||
|
||||
return Student(
|
||||
id: json["Uid"] ?? "",
|
||||
name: (json["Nev"] ?? json["SzuletesiNev"] ?? "").trim(),
|
||||
school: School(
|
||||
instituteCode: json["IntezmenyAzonosito"] ?? "",
|
||||
name: json["IntezmenyNev"] ?? "",
|
||||
city: "",
|
||||
),
|
||||
birth: json["SzuletesiDatum"] != null ? DateTime.parse(json["SzuletesiDatum"]).toLocal() : DateTime(0),
|
||||
yearId: json["TanevUid"] ?? "",
|
||||
address: json["Cimek"] != null
|
||||
? json["Cimek"].length > 0
|
||||
? json["Cimek"][0]
|
||||
: null
|
||||
: null,
|
||||
parents: parents,
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'school.dart';
|
||||
import 'package:filcnaplo/utils/format.dart';
|
||||
|
||||
class Student {
|
||||
Map? json;
|
||||
String id;
|
||||
String name;
|
||||
School school;
|
||||
DateTime birth;
|
||||
String yearId;
|
||||
String? address;
|
||||
String? groupId;
|
||||
List<String> parents;
|
||||
String? className;
|
||||
|
||||
Student({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.school,
|
||||
required this.birth,
|
||||
required this.yearId,
|
||||
this.address,
|
||||
required this.parents,
|
||||
this.json,
|
||||
});
|
||||
|
||||
factory Student.fromJson(Map json) {
|
||||
List<String> parents = [];
|
||||
|
||||
parents = ((json["Gondviselok"] ?? []) as List).cast<Map>().map((e) => e["Nev"] ?? "").toList().cast<String>();
|
||||
if (json["AnyjaNeve"] != null) parents.insert(0, json["AnyjaNeve"]);
|
||||
|
||||
parents = parents.map((e) => e.capitalize()).toList(); // fix name casing
|
||||
parents = parents.toSet().toList(); // remove duplicates
|
||||
|
||||
return Student(
|
||||
id: json["Uid"] ?? "",
|
||||
name: (json["Nev"] ?? json["SzuletesiNev"] ?? "").trim(),
|
||||
school: School(
|
||||
instituteCode: json["IntezmenyAzonosito"] ?? "",
|
||||
name: json["IntezmenyNev"] ?? "",
|
||||
city: "",
|
||||
),
|
||||
birth: json["SzuletesiDatum"] != null ? DateTime.parse(json["SzuletesiDatum"]).toLocal() : DateTime(0),
|
||||
yearId: json["TanevUid"] ?? "",
|
||||
address: json["Cimek"] != null
|
||||
? json["Cimek"].length > 0
|
||||
? json["Cimek"][0]
|
||||
: null
|
||||
: null,
|
||||
parents: parents,
|
||||
json: json,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
import 'category.dart';
|
||||
|
||||
class Subject {
|
||||
String id;
|
||||
Category category;
|
||||
String name;
|
||||
String? renamedTo;
|
||||
|
||||
bool get isRenamed => renamedTo != null;
|
||||
|
||||
Subject({required this.id, required this.category, required this.name, this.renamedTo});
|
||||
|
||||
factory Subject.fromJson(Map json) {
|
||||
final id = json["Uid"] ?? "";
|
||||
return Subject(
|
||||
id: id,
|
||||
category: Category.fromJson(json["Kategoria"] ?? {}),
|
||||
name: (json["Nev"] ?? "").trim(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
if (other is! Subject) return false;
|
||||
return id == other.id;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => id.hashCode;
|
||||
}
|
||||
import 'category.dart';
|
||||
|
||||
class Subject {
|
||||
String id;
|
||||
Category category;
|
||||
String name;
|
||||
String? renamedTo;
|
||||
|
||||
bool get isRenamed => renamedTo != null;
|
||||
|
||||
Subject({required this.id, required this.category, required this.name, this.renamedTo});
|
||||
|
||||
factory Subject.fromJson(Map json) {
|
||||
final id = json["Uid"] ?? "";
|
||||
return Subject(
|
||||
id: id,
|
||||
category: Category.fromJson(json["Kategoria"] ?? {}),
|
||||
name: (json["Nev"] ?? "").trim(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
if (other is! Subject) return false;
|
||||
return id == other.id;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => id.hashCode;
|
||||
}
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
import 'package:filcnaplo_kreta_api/controllers/timetable_controller.dart';
|
||||
|
||||
class Week {
|
||||
DateTime start;
|
||||
DateTime end;
|
||||
|
||||
Week({required this.start, required this.end});
|
||||
|
||||
factory Week.current() => Week.fromDate(DateTime.now());
|
||||
|
||||
factory Week.fromId(int id) {
|
||||
DateTime _now = TimetableController.getSchoolYearStart().add(Duration(days: id * DateTime.daysPerWeek));
|
||||
DateTime now = DateTime(_now.year, _now.month, _now.day);
|
||||
return Week(
|
||||
start: now.subtract(Duration(days: now.weekday - 1)),
|
||||
end: now.add(Duration(days: DateTime.daysPerWeek - now.weekday)),
|
||||
);
|
||||
}
|
||||
|
||||
factory Week.fromDate(DateTime date) {
|
||||
// fix #32
|
||||
DateTime _date = DateTime(date.year, date.month, date.day);
|
||||
return Week(
|
||||
start: _date.subtract(Duration(days: _date.weekday - 1)),
|
||||
end: _date.add(Duration(days: DateTime.daysPerWeek - _date.weekday)),
|
||||
);
|
||||
}
|
||||
|
||||
Week next() => Week.fromDate(start.add(const Duration(days: 8)));
|
||||
|
||||
int get id => -(TimetableController.getSchoolYearStart().difference(start).inDays / DateTime.daysPerWeek).floor();
|
||||
|
||||
@override
|
||||
String toString() => "Week(start: $start, end: $end)";
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => other is Week && id == other.id;
|
||||
|
||||
@override
|
||||
int get hashCode => id;
|
||||
}
|
||||
import 'package:filcnaplo_kreta_api/controllers/timetable_controller.dart';
|
||||
|
||||
class Week {
|
||||
DateTime start;
|
||||
DateTime end;
|
||||
|
||||
Week({required this.start, required this.end});
|
||||
|
||||
factory Week.current() => Week.fromDate(DateTime.now());
|
||||
|
||||
factory Week.fromId(int id) {
|
||||
DateTime _now = TimetableController.getSchoolYearStart().add(Duration(days: id * DateTime.daysPerWeek));
|
||||
DateTime now = DateTime(_now.year, _now.month, _now.day);
|
||||
return Week(
|
||||
start: now.subtract(Duration(days: now.weekday - 1)),
|
||||
end: now.add(Duration(days: DateTime.daysPerWeek - now.weekday)),
|
||||
);
|
||||
}
|
||||
|
||||
factory Week.fromDate(DateTime date) {
|
||||
// fix #32
|
||||
DateTime _date = DateTime(date.year, date.month, date.day);
|
||||
return Week(
|
||||
start: _date.subtract(Duration(days: _date.weekday - 1)),
|
||||
end: _date.add(Duration(days: DateTime.daysPerWeek - _date.weekday)),
|
||||
);
|
||||
}
|
||||
|
||||
Week next() => Week.fromDate(start.add(const Duration(days: 8)));
|
||||
|
||||
int get id => -(TimetableController.getSchoolYearStart().difference(start).inDays / DateTime.daysPerWeek).floor();
|
||||
|
||||
@override
|
||||
String toString() => "Week(start: $start, end: $end)";
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => other is Week && id == other.id;
|
||||
|
||||
@override
|
||||
int get hashCode => id;
|
||||
}
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/absence.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class AbsenceProvider with ChangeNotifier {
|
||||
late List<Absence> _absences;
|
||||
late BuildContext _context;
|
||||
List<Absence> get absences => _absences;
|
||||
|
||||
AbsenceProvider({
|
||||
List<Absence> initialAbsences = const [],
|
||||
required BuildContext context,
|
||||
}) {
|
||||
_absences = List.castFrom(initialAbsences);
|
||||
_context = context;
|
||||
|
||||
if (_absences.isEmpty) restore();
|
||||
}
|
||||
|
||||
Future<void> restore() async {
|
||||
String? userId = Provider.of<UserProvider>(_context, listen: false).id;
|
||||
|
||||
// Load absences from the database
|
||||
if (userId != null) {
|
||||
var dbAbsences = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getAbsences(userId: userId);
|
||||
_absences = dbAbsences;
|
||||
await convertBySettings();
|
||||
}
|
||||
}
|
||||
|
||||
// for renamed subjects
|
||||
Future<void> convertBySettings() async {
|
||||
final _database = Provider.of<DatabaseProvider>(_context, listen: false);
|
||||
Map<String, String> renamedSubjects = (await _database.query.getSettings(_database)).renamedSubjectsEnabled
|
||||
? await _database.userQuery.renamedSubjects(userId: Provider.of<UserProvider>(_context, listen: false).user!.id)
|
||||
: {};
|
||||
|
||||
for (Absence absence in _absences) {
|
||||
absence.subject.renamedTo = renamedSubjects.isNotEmpty ? renamedSubjects[absence.subject.id] : null;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Fetches Absences from the Kreta API then stores them in the database
|
||||
Future<void> fetch() async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot fetch Absences for User null";
|
||||
String iss = user.instituteCode;
|
||||
|
||||
List? absencesJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.absences(iss));
|
||||
if (absencesJson == null) throw "Cannot fetch Absences for User ${user.id}";
|
||||
List<Absence> absences = absencesJson.map((e) => Absence.fromJson(e)).toList();
|
||||
|
||||
if (absences.isNotEmpty || _absences.isNotEmpty) await store(absences);
|
||||
}
|
||||
|
||||
// Stores Absences in the database
|
||||
Future<void> store(List<Absence> absences) async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot store Absences for User null";
|
||||
String userId = user.id;
|
||||
|
||||
await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeAbsences(absences, userId: userId);
|
||||
_absences = absences;
|
||||
await convertBySettings();
|
||||
}
|
||||
}
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/absence.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class AbsenceProvider with ChangeNotifier {
|
||||
late List<Absence> _absences;
|
||||
late BuildContext _context;
|
||||
List<Absence> get absences => _absences;
|
||||
|
||||
AbsenceProvider({
|
||||
List<Absence> initialAbsences = const [],
|
||||
required BuildContext context,
|
||||
}) {
|
||||
_absences = List.castFrom(initialAbsences);
|
||||
_context = context;
|
||||
|
||||
if (_absences.isEmpty) restore();
|
||||
}
|
||||
|
||||
Future<void> restore() async {
|
||||
String? userId = Provider.of<UserProvider>(_context, listen: false).id;
|
||||
|
||||
// Load absences from the database
|
||||
if (userId != null) {
|
||||
var dbAbsences = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getAbsences(userId: userId);
|
||||
_absences = dbAbsences;
|
||||
await convertBySettings();
|
||||
}
|
||||
}
|
||||
|
||||
// for renamed subjects
|
||||
Future<void> convertBySettings() async {
|
||||
final _database = Provider.of<DatabaseProvider>(_context, listen: false);
|
||||
Map<String, String> renamedSubjects = (await _database.query.getSettings(_database)).renamedSubjectsEnabled
|
||||
? await _database.userQuery.renamedSubjects(userId: Provider.of<UserProvider>(_context, listen: false).user!.id)
|
||||
: {};
|
||||
|
||||
for (Absence absence in _absences) {
|
||||
absence.subject.renamedTo = renamedSubjects.isNotEmpty ? renamedSubjects[absence.subject.id] : null;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Fetches Absences from the Kreta API then stores them in the database
|
||||
Future<void> fetch() async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot fetch Absences for User null";
|
||||
String iss = user.instituteCode;
|
||||
|
||||
List? absencesJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.absences(iss));
|
||||
if (absencesJson == null) throw "Cannot fetch Absences for User ${user.id}";
|
||||
List<Absence> absences = absencesJson.map((e) => Absence.fromJson(e)).toList();
|
||||
|
||||
if (absences.isNotEmpty || _absences.isNotEmpty) await store(absences);
|
||||
}
|
||||
|
||||
// Stores Absences in the database
|
||||
Future<void> store(List<Absence> absences) async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot store Absences for User null";
|
||||
String userId = user.id;
|
||||
|
||||
await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeAbsences(absences, userId: userId);
|
||||
_absences = absences;
|
||||
await convertBySettings();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +1,59 @@
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/event.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class EventProvider with ChangeNotifier {
|
||||
late List<Event> _events;
|
||||
late BuildContext _context;
|
||||
List<Event> get events => _events;
|
||||
|
||||
EventProvider({
|
||||
List<Event> initialEvents = const [],
|
||||
required BuildContext context,
|
||||
}) {
|
||||
_events = List.castFrom(initialEvents);
|
||||
_context = context;
|
||||
|
||||
if (_events.isEmpty) restore();
|
||||
}
|
||||
|
||||
Future<void> restore() async {
|
||||
String? userId = Provider.of<UserProvider>(_context, listen: false).id;
|
||||
|
||||
// Load events from the database
|
||||
if (userId != null) {
|
||||
var dbEvents = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getEvents(userId: userId);
|
||||
_events = dbEvents;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// Fetches Events from the Kreta API then stores them in the database
|
||||
Future<void> fetch() async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot fetch Events for User null";
|
||||
String iss = user.instituteCode;
|
||||
|
||||
List? eventsJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.events(iss));
|
||||
if (eventsJson == null) throw "Cannot fetch Events for User ${user.id}";
|
||||
List<Event> events = eventsJson.map((e) => Event.fromJson(e)).toList();
|
||||
|
||||
if (events.isNotEmpty || _events.isNotEmpty) await store(events);
|
||||
}
|
||||
|
||||
// Stores Events in the database
|
||||
Future<void> store(List<Event> events) async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot store Events for User null";
|
||||
String userId = user.id;
|
||||
|
||||
await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeEvents(events, userId: userId);
|
||||
_events = events;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/event.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class EventProvider with ChangeNotifier {
|
||||
late List<Event> _events;
|
||||
late BuildContext _context;
|
||||
List<Event> get events => _events;
|
||||
|
||||
EventProvider({
|
||||
List<Event> initialEvents = const [],
|
||||
required BuildContext context,
|
||||
}) {
|
||||
_events = List.castFrom(initialEvents);
|
||||
_context = context;
|
||||
|
||||
if (_events.isEmpty) restore();
|
||||
}
|
||||
|
||||
Future<void> restore() async {
|
||||
String? userId = Provider.of<UserProvider>(_context, listen: false).id;
|
||||
|
||||
// Load events from the database
|
||||
if (userId != null) {
|
||||
var dbEvents = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getEvents(userId: userId);
|
||||
_events = dbEvents;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// Fetches Events from the Kreta API then stores them in the database
|
||||
Future<void> fetch() async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot fetch Events for User null";
|
||||
String iss = user.instituteCode;
|
||||
|
||||
List? eventsJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.events(iss));
|
||||
if (eventsJson == null) throw "Cannot fetch Events for User ${user.id}";
|
||||
List<Event> events = eventsJson.map((e) => Event.fromJson(e)).toList();
|
||||
|
||||
if (events.isNotEmpty || _events.isNotEmpty) await store(events);
|
||||
}
|
||||
|
||||
// Stores Events in the database
|
||||
Future<void> store(List<Event> events) async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot store Events for User null";
|
||||
String userId = user.id;
|
||||
|
||||
await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeEvents(events, userId: userId);
|
||||
_events = events;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +1,59 @@
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/exam.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ExamProvider with ChangeNotifier {
|
||||
late List<Exam> _exams;
|
||||
late BuildContext _context;
|
||||
List<Exam> get exams => _exams;
|
||||
|
||||
ExamProvider({
|
||||
List<Exam> initialExams = const [],
|
||||
required BuildContext context,
|
||||
}) {
|
||||
_exams = List.castFrom(initialExams);
|
||||
_context = context;
|
||||
|
||||
if (_exams.isEmpty) restore();
|
||||
}
|
||||
|
||||
Future<void> restore() async {
|
||||
String? userId = Provider.of<UserProvider>(_context, listen: false).id;
|
||||
|
||||
// Load exams from the database
|
||||
if (userId != null) {
|
||||
var dbExams = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getExams(userId: userId);
|
||||
_exams = dbExams;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// Fetches Exams from the Kreta API then stores them in the database
|
||||
Future<void> fetch() async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot fetch Exams for User null";
|
||||
String iss = user.instituteCode;
|
||||
|
||||
List? examsJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.exams(iss));
|
||||
if (examsJson == null) throw "Cannot fetch Exams for User ${user.id}";
|
||||
List<Exam> exams = examsJson.map((e) => Exam.fromJson(e)).toList();
|
||||
|
||||
if (exams.isNotEmpty || _exams.isNotEmpty) await store(exams);
|
||||
}
|
||||
|
||||
// Stores Exams in the database
|
||||
Future<void> store(List<Exam> exams) async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot store Exams for User null";
|
||||
String userId = user.id;
|
||||
|
||||
await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeExams(exams, userId: userId);
|
||||
_exams = exams;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/exam.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ExamProvider with ChangeNotifier {
|
||||
late List<Exam> _exams;
|
||||
late BuildContext _context;
|
||||
List<Exam> get exams => _exams;
|
||||
|
||||
ExamProvider({
|
||||
List<Exam> initialExams = const [],
|
||||
required BuildContext context,
|
||||
}) {
|
||||
_exams = List.castFrom(initialExams);
|
||||
_context = context;
|
||||
|
||||
if (_exams.isEmpty) restore();
|
||||
}
|
||||
|
||||
Future<void> restore() async {
|
||||
String? userId = Provider.of<UserProvider>(_context, listen: false).id;
|
||||
|
||||
// Load exams from the database
|
||||
if (userId != null) {
|
||||
var dbExams = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getExams(userId: userId);
|
||||
_exams = dbExams;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// Fetches Exams from the Kreta API then stores them in the database
|
||||
Future<void> fetch() async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot fetch Exams for User null";
|
||||
String iss = user.instituteCode;
|
||||
|
||||
List? examsJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.exams(iss));
|
||||
if (examsJson == null) throw "Cannot fetch Exams for User ${user.id}";
|
||||
List<Exam> exams = examsJson.map((e) => Exam.fromJson(e)).toList();
|
||||
|
||||
if (exams.isNotEmpty || _exams.isNotEmpty) await store(exams);
|
||||
}
|
||||
|
||||
// Stores Exams in the database
|
||||
Future<void> store(List<Exam> exams) async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot store Exams for User null";
|
||||
String userId = user.id;
|
||||
|
||||
await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeExams(exams, userId: userId);
|
||||
_exams = exams;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,134 +1,134 @@
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/settings.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/group_average.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class GradeProvider with ChangeNotifier {
|
||||
// Private
|
||||
late List<Grade> _grades;
|
||||
late DateTime _lastSeen;
|
||||
late String _groups;
|
||||
List<GroupAverage> _groupAvg = [];
|
||||
late final SettingsProvider _settings;
|
||||
late final UserProvider _user;
|
||||
late final DatabaseProvider _database;
|
||||
late final KretaClient _kreta;
|
||||
|
||||
// Public
|
||||
List<Grade> get grades => _grades;
|
||||
DateTime get lastSeenDate => _settings.gradeOpeningFun ? _lastSeen : DateTime(3000);
|
||||
String get groups => _groups;
|
||||
List<GroupAverage> get groupAverages => _groupAvg;
|
||||
|
||||
GradeProvider({
|
||||
List<Grade> initialGrades = const [],
|
||||
required SettingsProvider settings,
|
||||
required UserProvider user,
|
||||
required DatabaseProvider database,
|
||||
required KretaClient kreta,
|
||||
}) {
|
||||
_settings = settings;
|
||||
_user = user;
|
||||
_database = database;
|
||||
_kreta = kreta;
|
||||
|
||||
_grades = List.castFrom(initialGrades);
|
||||
_lastSeen = DateTime.now();
|
||||
|
||||
if (_grades.isEmpty) restore();
|
||||
}
|
||||
|
||||
Future<void> seenAll() async {
|
||||
String? userId = _user.id;
|
||||
if (userId != null) {
|
||||
final userStore = _database.userStore;
|
||||
userStore.storeLastSeenGrade(DateTime.now(), userId: userId);
|
||||
_lastSeen = DateTime.now();
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> restore() async {
|
||||
String? userId = _user.id;
|
||||
|
||||
// Load grades from the database
|
||||
if (userId != null) {
|
||||
final userQuery = _database.userQuery;
|
||||
|
||||
_grades = await userQuery.getGrades(userId: userId);
|
||||
await convertBySettings();
|
||||
_groupAvg = await userQuery.getGroupAverages(userId: userId);
|
||||
notifyListeners();
|
||||
DateTime lastSeenDB = await userQuery.lastSeenGrade(userId: userId);
|
||||
if (lastSeenDB.millisecondsSinceEpoch == 0 || lastSeenDB.year == 0 || !_settings.gradeOpeningFun) {
|
||||
_lastSeen = DateTime.now();
|
||||
await seenAll();
|
||||
} else {
|
||||
_lastSeen = lastSeenDB;
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// good student mode, renamed subjects
|
||||
Future<void> convertBySettings() async {
|
||||
Map<String, String> renamedSubjects = _settings.renamedSubjectsEnabled ? await _database.userQuery.renamedSubjects(userId: _user.user!.id) : {};
|
||||
|
||||
for (Grade grade in _grades) {
|
||||
grade.subject.renamedTo = renamedSubjects.isNotEmpty ? renamedSubjects[grade.subject.id] : null;
|
||||
grade.value.value = _settings.goodStudent ? 5 : grade.json!["SzamErtek"] ?? 0;
|
||||
grade.value.valueName = _settings.goodStudent ? "Példás" : grade.json!["SzovegesErtek"] ?? "";
|
||||
grade.value.shortName = _settings.goodStudent ? "Példás" : grade.json!["SzovegesErtekelesRovidNev"] ?? "";
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Fetches Grades from the Kreta API then stores them in the database
|
||||
Future<void> fetch() async {
|
||||
User? user = _user.user;
|
||||
if (user == null) throw "Cannot fetch Grades for User null";
|
||||
String iss = user.instituteCode;
|
||||
|
||||
List? gradesJson = await _kreta.getAPI(KretaAPI.grades(iss));
|
||||
if (gradesJson == null) throw "Cannot fetch Grades for User ${user.id}";
|
||||
List<Grade> grades = gradesJson.map((e) => Grade.fromJson(e)).toList();
|
||||
|
||||
if (grades.isNotEmpty || _grades.isNotEmpty) await store(grades);
|
||||
|
||||
List? groupsJson = await _kreta.getAPI(KretaAPI.groups(iss));
|
||||
if (groupsJson == null || groupsJson.isEmpty) throw "Cannot fetch Groups for User ${user.id}";
|
||||
_groups = (groupsJson[0]["OktatasNevelesiFeladat"] ?? {})["Uid"] ?? "";
|
||||
|
||||
List? groupAvgJson = await _kreta.getAPI(KretaAPI.groupAverages(iss, _groups));
|
||||
if (groupAvgJson == null) throw "Cannot fetch Class Averages for User ${user.id}";
|
||||
final groupAvgs = groupAvgJson.map((e) => GroupAverage.fromJson(e)).toList();
|
||||
await storeGroupAvg(groupAvgs);
|
||||
}
|
||||
|
||||
// Stores Grades in the database
|
||||
Future<void> store(List<Grade> grades) async {
|
||||
User? user = _user.user;
|
||||
if (user == null) throw "Cannot store Grades for User null";
|
||||
String userId = user.id;
|
||||
|
||||
await _database.userStore.storeGrades(grades, userId: userId);
|
||||
_grades = grades;
|
||||
await convertBySettings();
|
||||
}
|
||||
|
||||
Future<void> storeGroupAvg(List<GroupAverage> groupAvgs) async {
|
||||
_groupAvg = groupAvgs;
|
||||
|
||||
User? user = _user.user;
|
||||
if (user == null) throw "Cannot store Grades for User null";
|
||||
String userId = user.id;
|
||||
await _database.userStore.storeGroupAverages(groupAvgs, userId: userId);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/settings.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/grade.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/group_average.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class GradeProvider with ChangeNotifier {
|
||||
// Private
|
||||
late List<Grade> _grades;
|
||||
late DateTime _lastSeen;
|
||||
late String _groups;
|
||||
List<GroupAverage> _groupAvg = [];
|
||||
late final SettingsProvider _settings;
|
||||
late final UserProvider _user;
|
||||
late final DatabaseProvider _database;
|
||||
late final KretaClient _kreta;
|
||||
|
||||
// Public
|
||||
List<Grade> get grades => _grades;
|
||||
DateTime get lastSeenDate => _settings.gradeOpeningFun ? _lastSeen : DateTime(3000);
|
||||
String get groups => _groups;
|
||||
List<GroupAverage> get groupAverages => _groupAvg;
|
||||
|
||||
GradeProvider({
|
||||
List<Grade> initialGrades = const [],
|
||||
required SettingsProvider settings,
|
||||
required UserProvider user,
|
||||
required DatabaseProvider database,
|
||||
required KretaClient kreta,
|
||||
}) {
|
||||
_settings = settings;
|
||||
_user = user;
|
||||
_database = database;
|
||||
_kreta = kreta;
|
||||
|
||||
_grades = List.castFrom(initialGrades);
|
||||
_lastSeen = DateTime.now();
|
||||
|
||||
if (_grades.isEmpty) restore();
|
||||
}
|
||||
|
||||
Future<void> seenAll() async {
|
||||
String? userId = _user.id;
|
||||
if (userId != null) {
|
||||
final userStore = _database.userStore;
|
||||
userStore.storeLastSeenGrade(DateTime.now(), userId: userId);
|
||||
_lastSeen = DateTime.now();
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> restore() async {
|
||||
String? userId = _user.id;
|
||||
|
||||
// Load grades from the database
|
||||
if (userId != null) {
|
||||
final userQuery = _database.userQuery;
|
||||
|
||||
_grades = await userQuery.getGrades(userId: userId);
|
||||
await convertBySettings();
|
||||
_groupAvg = await userQuery.getGroupAverages(userId: userId);
|
||||
notifyListeners();
|
||||
DateTime lastSeenDB = await userQuery.lastSeenGrade(userId: userId);
|
||||
if (lastSeenDB.millisecondsSinceEpoch == 0 || lastSeenDB.year == 0 || !_settings.gradeOpeningFun) {
|
||||
_lastSeen = DateTime.now();
|
||||
await seenAll();
|
||||
} else {
|
||||
_lastSeen = lastSeenDB;
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// good student mode, renamed subjects
|
||||
Future<void> convertBySettings() async {
|
||||
Map<String, String> renamedSubjects = _settings.renamedSubjectsEnabled ? await _database.userQuery.renamedSubjects(userId: _user.user!.id) : {};
|
||||
|
||||
for (Grade grade in _grades) {
|
||||
grade.subject.renamedTo = renamedSubjects.isNotEmpty ? renamedSubjects[grade.subject.id] : null;
|
||||
grade.value.value = _settings.goodStudent ? 5 : grade.json!["SzamErtek"] ?? 0;
|
||||
grade.value.valueName = _settings.goodStudent ? "Példás" : grade.json!["SzovegesErtek"] ?? "";
|
||||
grade.value.shortName = _settings.goodStudent ? "Példás" : grade.json!["SzovegesErtekelesRovidNev"] ?? "";
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Fetches Grades from the Kreta API then stores them in the database
|
||||
Future<void> fetch() async {
|
||||
User? user = _user.user;
|
||||
if (user == null) throw "Cannot fetch Grades for User null";
|
||||
String iss = user.instituteCode;
|
||||
|
||||
List? gradesJson = await _kreta.getAPI(KretaAPI.grades(iss));
|
||||
if (gradesJson == null) throw "Cannot fetch Grades for User ${user.id}";
|
||||
List<Grade> grades = gradesJson.map((e) => Grade.fromJson(e)).toList();
|
||||
|
||||
if (grades.isNotEmpty || _grades.isNotEmpty) await store(grades);
|
||||
|
||||
List? groupsJson = await _kreta.getAPI(KretaAPI.groups(iss));
|
||||
if (groupsJson == null || groupsJson.isEmpty) throw "Cannot fetch Groups for User ${user.id}";
|
||||
_groups = (groupsJson[0]["OktatasNevelesiFeladat"] ?? {})["Uid"] ?? "";
|
||||
|
||||
List? groupAvgJson = await _kreta.getAPI(KretaAPI.groupAverages(iss, _groups));
|
||||
if (groupAvgJson == null) throw "Cannot fetch Class Averages for User ${user.id}";
|
||||
final groupAvgs = groupAvgJson.map((e) => GroupAverage.fromJson(e)).toList();
|
||||
await storeGroupAvg(groupAvgs);
|
||||
}
|
||||
|
||||
// Stores Grades in the database
|
||||
Future<void> store(List<Grade> grades) async {
|
||||
User? user = _user.user;
|
||||
if (user == null) throw "Cannot store Grades for User null";
|
||||
String userId = user.id;
|
||||
|
||||
await _database.userStore.storeGrades(grades, userId: userId);
|
||||
_grades = grades;
|
||||
await convertBySettings();
|
||||
}
|
||||
|
||||
Future<void> storeGroupAvg(List<GroupAverage> groupAvgs) async {
|
||||
_groupAvg = groupAvgs;
|
||||
|
||||
User? user = _user.user;
|
||||
if (user == null) throw "Cannot store Grades for User null";
|
||||
String userId = user.id;
|
||||
await _database.userStore.storeGroupAverages(groupAvgs, userId: userId);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/homework.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class HomeworkProvider with ChangeNotifier {
|
||||
late List<Homework> _homework;
|
||||
late BuildContext _context;
|
||||
List<Homework> get homework => _homework;
|
||||
|
||||
HomeworkProvider({
|
||||
List<Homework> initialHomework = const [],
|
||||
required BuildContext context,
|
||||
}) {
|
||||
_homework = List.castFrom(initialHomework);
|
||||
_context = context;
|
||||
|
||||
if (_homework.isEmpty) restore();
|
||||
}
|
||||
|
||||
Future<void> restore() async {
|
||||
String? userId = Provider.of<UserProvider>(_context, listen: false).id;
|
||||
|
||||
// Load homework from the database
|
||||
if (userId != null) {
|
||||
var dbHomework = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getHomework(userId: userId);
|
||||
_homework = dbHomework;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// Fetches Homework from the Kreta API then stores them in the database
|
||||
Future<void> fetch({DateTime? from, bool db = true}) async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot fetch Homework for User null";
|
||||
|
||||
String iss = user.instituteCode;
|
||||
List? homeworkJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.homework(iss, start: from));
|
||||
if (homeworkJson == null) throw "Cannot fetch Homework for User ${user.id}";
|
||||
|
||||
List<Homework> homework = [];
|
||||
await Future.forEach(homeworkJson.cast<Map>(), (Map hw) async {
|
||||
Map? e = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.homework(iss, id: hw["Uid"]));
|
||||
if (e != null) homework.add(Homework.fromJson(e));
|
||||
});
|
||||
|
||||
if (homework.isEmpty && _homework.isEmpty) return;
|
||||
|
||||
if (db) await store(homework);
|
||||
_homework = homework;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Stores Homework in the database
|
||||
Future<void> store(List<Homework> homework) async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot store Homework for User null";
|
||||
String userId = user.id;
|
||||
await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeHomework(homework, userId: userId);
|
||||
}
|
||||
}
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/homework.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class HomeworkProvider with ChangeNotifier {
|
||||
late List<Homework> _homework;
|
||||
late BuildContext _context;
|
||||
List<Homework> get homework => _homework;
|
||||
|
||||
HomeworkProvider({
|
||||
List<Homework> initialHomework = const [],
|
||||
required BuildContext context,
|
||||
}) {
|
||||
_homework = List.castFrom(initialHomework);
|
||||
_context = context;
|
||||
|
||||
if (_homework.isEmpty) restore();
|
||||
}
|
||||
|
||||
Future<void> restore() async {
|
||||
String? userId = Provider.of<UserProvider>(_context, listen: false).id;
|
||||
|
||||
// Load homework from the database
|
||||
if (userId != null) {
|
||||
var dbHomework = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getHomework(userId: userId);
|
||||
_homework = dbHomework;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// Fetches Homework from the Kreta API then stores them in the database
|
||||
Future<void> fetch({DateTime? from, bool db = true}) async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot fetch Homework for User null";
|
||||
|
||||
String iss = user.instituteCode;
|
||||
List? homeworkJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.homework(iss, start: from));
|
||||
if (homeworkJson == null) throw "Cannot fetch Homework for User ${user.id}";
|
||||
|
||||
List<Homework> homework = [];
|
||||
await Future.forEach(homeworkJson.cast<Map>(), (Map hw) async {
|
||||
Map? e = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.homework(iss, id: hw["Uid"]));
|
||||
if (e != null) homework.add(Homework.fromJson(e));
|
||||
});
|
||||
|
||||
if (homework.isEmpty && _homework.isEmpty) return;
|
||||
|
||||
if (db) await store(homework);
|
||||
_homework = homework;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Stores Homework in the database
|
||||
Future<void> store(List<Homework> homework) async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot store Homework for User null";
|
||||
String userId = user.id;
|
||||
await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeHomework(homework, userId: userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,80 +1,80 @@
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/message.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MessageProvider with ChangeNotifier {
|
||||
late List<Message> _messages;
|
||||
late BuildContext _context;
|
||||
List<Message> get messages => _messages;
|
||||
|
||||
MessageProvider({
|
||||
List<Message> initialMessages = const [],
|
||||
required BuildContext context,
|
||||
}) {
|
||||
_messages = List.castFrom(initialMessages);
|
||||
_context = context;
|
||||
|
||||
if (_messages.isEmpty) restore();
|
||||
}
|
||||
|
||||
Future<void> restore() async {
|
||||
String? userId = Provider.of<UserProvider>(_context, listen: false).id;
|
||||
|
||||
// Load messages from the database
|
||||
if (userId != null) {
|
||||
var dbMessages = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getMessages(userId: userId);
|
||||
_messages = dbMessages;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// Fetches all types of Messages
|
||||
Future<void> fetchAll() => Future.forEach(MessageType.values, (MessageType v) => fetch(type: v));
|
||||
|
||||
// Fetches Messages from the Kreta API then stores them in the database
|
||||
Future<void> fetch({MessageType type = MessageType.inbox}) async {
|
||||
// Check Message Type
|
||||
if (type == MessageType.draft) return;
|
||||
String messageType = ["beerkezett", "elkuldott", "torolt"].elementAt(type.index);
|
||||
|
||||
// Check User
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot fetch Messages for User null";
|
||||
|
||||
// Get messages
|
||||
List? messagesJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.messages(messageType));
|
||||
if (messagesJson == null) throw "Cannot fetch Messages for User ${user.id}";
|
||||
|
||||
// Parse messages
|
||||
List<Message> messages = [];
|
||||
await Future.wait(List.generate(messagesJson.length, (index) {
|
||||
return () async {
|
||||
Map message = messagesJson.cast<Map>()[index];
|
||||
Map? messageJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.message(message["azonosito"].toString()));
|
||||
if (messageJson != null) messages.add(Message.fromJson(messageJson, forceType: type));
|
||||
}();
|
||||
}));
|
||||
|
||||
await store(messages, type);
|
||||
}
|
||||
|
||||
// Stores Messages in the database
|
||||
Future<void> store(List<Message> messages, MessageType type) async {
|
||||
// Only store the specified type
|
||||
_messages.removeWhere((m) => m.type == type);
|
||||
_messages.addAll(messages);
|
||||
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot store Messages for User null";
|
||||
|
||||
String userId = user.id;
|
||||
await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeMessages(_messages, userId: userId);
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/message.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MessageProvider with ChangeNotifier {
|
||||
late List<Message> _messages;
|
||||
late BuildContext _context;
|
||||
List<Message> get messages => _messages;
|
||||
|
||||
MessageProvider({
|
||||
List<Message> initialMessages = const [],
|
||||
required BuildContext context,
|
||||
}) {
|
||||
_messages = List.castFrom(initialMessages);
|
||||
_context = context;
|
||||
|
||||
if (_messages.isEmpty) restore();
|
||||
}
|
||||
|
||||
Future<void> restore() async {
|
||||
String? userId = Provider.of<UserProvider>(_context, listen: false).id;
|
||||
|
||||
// Load messages from the database
|
||||
if (userId != null) {
|
||||
var dbMessages = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getMessages(userId: userId);
|
||||
_messages = dbMessages;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// Fetches all types of Messages
|
||||
Future<void> fetchAll() => Future.forEach(MessageType.values, (MessageType v) => fetch(type: v));
|
||||
|
||||
// Fetches Messages from the Kreta API then stores them in the database
|
||||
Future<void> fetch({MessageType type = MessageType.inbox}) async {
|
||||
// Check Message Type
|
||||
if (type == MessageType.draft) return;
|
||||
String messageType = ["beerkezett", "elkuldott", "torolt"].elementAt(type.index);
|
||||
|
||||
// Check User
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot fetch Messages for User null";
|
||||
|
||||
// Get messages
|
||||
List? messagesJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.messages(messageType));
|
||||
if (messagesJson == null) throw "Cannot fetch Messages for User ${user.id}";
|
||||
|
||||
// Parse messages
|
||||
List<Message> messages = [];
|
||||
await Future.wait(List.generate(messagesJson.length, (index) {
|
||||
return () async {
|
||||
Map message = messagesJson.cast<Map>()[index];
|
||||
Map? messageJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.message(message["azonosito"].toString()));
|
||||
if (messageJson != null) messages.add(Message.fromJson(messageJson, forceType: type));
|
||||
}();
|
||||
}));
|
||||
|
||||
await store(messages, type);
|
||||
}
|
||||
|
||||
// Stores Messages in the database
|
||||
Future<void> store(List<Message> messages, MessageType type) async {
|
||||
// Only store the specified type
|
||||
_messages.removeWhere((m) => m.type == type);
|
||||
_messages.addAll(messages);
|
||||
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot store Messages for User null";
|
||||
|
||||
String userId = user.id;
|
||||
await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeMessages(_messages, userId: userId);
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +1,59 @@
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/note.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class NoteProvider with ChangeNotifier {
|
||||
late List<Note> _notes;
|
||||
late BuildContext _context;
|
||||
List<Note> get notes => _notes;
|
||||
|
||||
NoteProvider({
|
||||
List<Note> initialNotes = const [],
|
||||
required BuildContext context,
|
||||
}) {
|
||||
_notes = List.castFrom(initialNotes);
|
||||
_context = context;
|
||||
|
||||
if (_notes.isEmpty) restore();
|
||||
}
|
||||
|
||||
Future<void> restore() async {
|
||||
String? userId = Provider.of<UserProvider>(_context, listen: false).id;
|
||||
|
||||
// Load notes from the database
|
||||
if (userId != null) {
|
||||
var dbNotes = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getNotes(userId: userId);
|
||||
_notes = dbNotes;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// Fetches Notes from the Kreta API then stores them in the database
|
||||
Future<void> fetch() async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot fetch Notes for User null";
|
||||
String iss = user.instituteCode;
|
||||
|
||||
List? notesJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.notes(iss));
|
||||
if (notesJson == null) throw "Cannot fetch Notes for User ${user.id}";
|
||||
List<Note> notes = notesJson.map((e) => Note.fromJson(e)).toList();
|
||||
|
||||
if (notes.isNotEmpty || _notes.isNotEmpty) await store(notes);
|
||||
}
|
||||
|
||||
// Stores Notes in the database
|
||||
Future<void> store(List<Note> notes) async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot store Notes for User null";
|
||||
String userId = user.id;
|
||||
|
||||
await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeNotes(notes, userId: userId);
|
||||
_notes = notes;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/note.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class NoteProvider with ChangeNotifier {
|
||||
late List<Note> _notes;
|
||||
late BuildContext _context;
|
||||
List<Note> get notes => _notes;
|
||||
|
||||
NoteProvider({
|
||||
List<Note> initialNotes = const [],
|
||||
required BuildContext context,
|
||||
}) {
|
||||
_notes = List.castFrom(initialNotes);
|
||||
_context = context;
|
||||
|
||||
if (_notes.isEmpty) restore();
|
||||
}
|
||||
|
||||
Future<void> restore() async {
|
||||
String? userId = Provider.of<UserProvider>(_context, listen: false).id;
|
||||
|
||||
// Load notes from the database
|
||||
if (userId != null) {
|
||||
var dbNotes = await Provider.of<DatabaseProvider>(_context, listen: false).userQuery.getNotes(userId: userId);
|
||||
_notes = dbNotes;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
// Fetches Notes from the Kreta API then stores them in the database
|
||||
Future<void> fetch() async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot fetch Notes for User null";
|
||||
String iss = user.instituteCode;
|
||||
|
||||
List? notesJson = await Provider.of<KretaClient>(_context, listen: false).getAPI(KretaAPI.notes(iss));
|
||||
if (notesJson == null) throw "Cannot fetch Notes for User ${user.id}";
|
||||
List<Note> notes = notesJson.map((e) => Note.fromJson(e)).toList();
|
||||
|
||||
if (notes.isNotEmpty || _notes.isNotEmpty) await store(notes);
|
||||
}
|
||||
|
||||
// Stores Notes in the database
|
||||
Future<void> store(List<Note> notes) async {
|
||||
User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
if (user == null) throw "Cannot store Notes for User null";
|
||||
String userId = user.id;
|
||||
|
||||
await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeNotes(notes, userId: userId);
|
||||
_notes = notes;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,92 +1,92 @@
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/lesson.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/week.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class TimetableProvider with ChangeNotifier {
|
||||
Map<Week, List<Lesson>> _lessons = {};
|
||||
late final UserProvider _user;
|
||||
late final DatabaseProvider _database;
|
||||
late final KretaClient _kreta;
|
||||
|
||||
TimetableProvider({
|
||||
required UserProvider user,
|
||||
required DatabaseProvider database,
|
||||
required KretaClient kreta,
|
||||
}) : _user = user,
|
||||
_database = database,
|
||||
_kreta = kreta {
|
||||
restoreUser();
|
||||
}
|
||||
|
||||
Future<void> restoreUser() async {
|
||||
String? userId = _user.id;
|
||||
|
||||
// Load lessons from the database
|
||||
if (userId != null) {
|
||||
var dbLessons = await _database.userQuery.getLessons(userId: userId);
|
||||
_lessons = dbLessons;
|
||||
await convertBySettings();
|
||||
}
|
||||
}
|
||||
|
||||
// for renamed subjects
|
||||
Future<void> convertBySettings() async {
|
||||
Map<String, String> renamedSubjects =
|
||||
(await _database.query.getSettings(_database)).renamedSubjectsEnabled ? await _database.userQuery.renamedSubjects(userId: _user.id!) : {};
|
||||
|
||||
for (Lesson lesson in _lessons.values.expand((e) => e)) {
|
||||
lesson.subject.renamedTo = renamedSubjects.isNotEmpty ? renamedSubjects[lesson.subject.id] : null;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
List<Lesson>? getWeek(Week week) => _lessons[week];
|
||||
|
||||
// Fetches Lessons from the Kreta API then stores them in the database
|
||||
Future<void> fetch({Week? week}) async {
|
||||
if (week == null) return;
|
||||
User? user = _user.user;
|
||||
if (user == null) throw "Cannot fetch Lessons for User null";
|
||||
String iss = user.instituteCode;
|
||||
List? lessonsJson = await _kreta.getAPI(KretaAPI.timetable(iss, start: week.start, end: week.end));
|
||||
if (lessonsJson == null) throw "Cannot fetch Lessons for User ${user.id}";
|
||||
List<Lesson> lessons = lessonsJson.map((e) => Lesson.fromJson(e)).toList();
|
||||
|
||||
if (lessons.isEmpty && _lessons.isEmpty) return;
|
||||
|
||||
_lessons[week] = lessons;
|
||||
|
||||
await store();
|
||||
await convertBySettings();
|
||||
}
|
||||
|
||||
// Stores Lessons in the database
|
||||
Future<void> store() async {
|
||||
User? user = _user.user;
|
||||
if (user == null) throw "Cannot store Lessons for User null";
|
||||
String userId = user.id;
|
||||
|
||||
// TODO: clear indexes with weeks outside of the current school year
|
||||
await _database.userStore.storeLessons(_lessons, userId: userId);
|
||||
}
|
||||
|
||||
// Future<void> setLessonCount(SubjectLessonCount lessonCount, {bool store = true}) async {
|
||||
// _subjectLessonCount = lessonCount;
|
||||
|
||||
// if (store) {
|
||||
// User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
// if (user == null) throw "Cannot store Lesson Count for User null";
|
||||
// String userId = user.id;
|
||||
|
||||
// await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeSubjectLessonCount(lessonCount, userId: userId);
|
||||
// }
|
||||
|
||||
// notifyListeners();
|
||||
// }
|
||||
}
|
||||
import 'package:filcnaplo/api/providers/user_provider.dart';
|
||||
import 'package:filcnaplo/api/providers/database_provider.dart';
|
||||
import 'package:filcnaplo/models/user.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/api.dart';
|
||||
import 'package:filcnaplo_kreta_api/client/client.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/lesson.dart';
|
||||
import 'package:filcnaplo_kreta_api/models/week.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class TimetableProvider with ChangeNotifier {
|
||||
Map<Week, List<Lesson>> _lessons = {};
|
||||
late final UserProvider _user;
|
||||
late final DatabaseProvider _database;
|
||||
late final KretaClient _kreta;
|
||||
|
||||
TimetableProvider({
|
||||
required UserProvider user,
|
||||
required DatabaseProvider database,
|
||||
required KretaClient kreta,
|
||||
}) : _user = user,
|
||||
_database = database,
|
||||
_kreta = kreta {
|
||||
restoreUser();
|
||||
}
|
||||
|
||||
Future<void> restoreUser() async {
|
||||
String? userId = _user.id;
|
||||
|
||||
// Load lessons from the database
|
||||
if (userId != null) {
|
||||
var dbLessons = await _database.userQuery.getLessons(userId: userId);
|
||||
_lessons = dbLessons;
|
||||
await convertBySettings();
|
||||
}
|
||||
}
|
||||
|
||||
// for renamed subjects
|
||||
Future<void> convertBySettings() async {
|
||||
Map<String, String> renamedSubjects =
|
||||
(await _database.query.getSettings(_database)).renamedSubjectsEnabled ? await _database.userQuery.renamedSubjects(userId: _user.id!) : {};
|
||||
|
||||
for (Lesson lesson in _lessons.values.expand((e) => e)) {
|
||||
lesson.subject.renamedTo = renamedSubjects.isNotEmpty ? renamedSubjects[lesson.subject.id] : null;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
List<Lesson>? getWeek(Week week) => _lessons[week];
|
||||
|
||||
// Fetches Lessons from the Kreta API then stores them in the database
|
||||
Future<void> fetch({Week? week}) async {
|
||||
if (week == null) return;
|
||||
User? user = _user.user;
|
||||
if (user == null) throw "Cannot fetch Lessons for User null";
|
||||
String iss = user.instituteCode;
|
||||
List? lessonsJson = await _kreta.getAPI(KretaAPI.timetable(iss, start: week.start, end: week.end));
|
||||
if (lessonsJson == null) throw "Cannot fetch Lessons for User ${user.id}";
|
||||
List<Lesson> lessons = lessonsJson.map((e) => Lesson.fromJson(e)).toList();
|
||||
|
||||
if (lessons.isEmpty && _lessons.isEmpty) return;
|
||||
|
||||
_lessons[week] = lessons;
|
||||
|
||||
await store();
|
||||
await convertBySettings();
|
||||
}
|
||||
|
||||
// Stores Lessons in the database
|
||||
Future<void> store() async {
|
||||
User? user = _user.user;
|
||||
if (user == null) throw "Cannot store Lessons for User null";
|
||||
String userId = user.id;
|
||||
|
||||
// TODO: clear indexes with weeks outside of the current school year
|
||||
await _database.userStore.storeLessons(_lessons, userId: userId);
|
||||
}
|
||||
|
||||
// Future<void> setLessonCount(SubjectLessonCount lessonCount, {bool store = true}) async {
|
||||
// _subjectLessonCount = lessonCount;
|
||||
|
||||
// if (store) {
|
||||
// User? user = Provider.of<UserProvider>(_context, listen: false).user;
|
||||
// if (user == null) throw "Cannot store Lesson Count for User null";
|
||||
// String userId = user.id;
|
||||
|
||||
// await Provider.of<DatabaseProvider>(_context, listen: false).userStore.storeSubjectLessonCount(lessonCount, userId: userId);
|
||||
// }
|
||||
|
||||
// notifyListeners();
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
name: filcnaplo_kreta_api
|
||||
publish_to: "none"
|
||||
|
||||
environment:
|
||||
sdk: ">=2.17.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
filcnaplo:
|
||||
path: ../filcnaplo/
|
||||
http: ^0.13.3
|
||||
provider: ^5.0.0
|
||||
file_picker:
|
||||
git:
|
||||
url: https://github.com/filc/flutter_file_picker.git
|
||||
ref: master
|
||||
|
||||
dev_dependencies:
|
||||
flutter_lints: ^1.0.0
|
||||
name: filcnaplo_kreta_api
|
||||
publish_to: "none"
|
||||
|
||||
environment:
|
||||
sdk: ">=2.17.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
filcnaplo:
|
||||
path: ../filcnaplo/
|
||||
http: ^0.13.3
|
||||
provider: ^5.0.0
|
||||
file_picker:
|
||||
git:
|
||||
url: https://github.com/filc/flutter_file_picker.git
|
||||
ref: master
|
||||
|
||||
dev_dependencies:
|
||||
flutter_lints: ^1.0.0
|
||||
|
||||
Reference in New Issue
Block a user