Removing useless binary in conf + managing services url resolution at runtime

This commit is contained in:
plm
2025-01-09 10:29:31 +01:00
parent 2c86e90b76
commit 047591d031
118 changed files with 1185 additions and 4699 deletions

View File

@@ -0,0 +1,21 @@
import 'dart:convert';
import 'package:flutter/services.dart';
class AppConfig {
static final AppConfig _instance = AppConfig._internal();
Map<String, String> _config = {};
AppConfig._internal();
factory AppConfig() => _instance;
Future<void> loadConfig() async {
final response = await rootBundle.loadString('assets/config/front.json');
_config = Map<String, String>.from(json.decode(response));
print('Config loaded: $_config');
}
String get(String key, {String defaultValue = ''}) {
return _config[key] ?? defaultValue;
}
}

View File

@@ -1,166 +1,246 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:alert_banner/exports.dart';
import 'package:localstorage/localstorage.dart';
import 'package:oc_front/core/conf/conf_reader.dart';
import 'package:oc_front/models/abstract.dart';
import 'package:oc_front/models/response.dart';
import 'package:oc_front/widgets/dialog/alert.dart';
import 'package:oc_front/core/services/html.dart' if (kIsWeb) 'dart:html' as http;
import 'package:oc_front/core/services/html.dart' if (kIsWeb) 'dart:html'
as http;
class APIService<T extends SerializerDeserializer> {
static bool forceRequest = false;
static Map<String, APIResponse<dynamic>> cache = <String, APIResponse<dynamic>>{};
static var config = AppConfig();
static Map<String, APIResponse<dynamic>> cache =
<String, APIResponse<dynamic>>{};
Dio _dio = Dio(
BaseOptions(
baseUrl: const String.fromEnvironment('HOST', defaultValue: 'http://localhost:8080'), // you can keep this blank
headers: { 'Content-Type': 'application/json; charset=UTF-8' },
baseUrl: config.get('HOST',
defaultValue: 'http://localhost:8080'), // you can keep this blank
headers: {'Content-Type': 'application/json; charset=UTF-8'},
),
)..interceptors.add(LogInterceptor( requestHeader: true, ));
)..interceptors.add(LogInterceptor(
requestHeader: true,
));
APIService({ required String baseURL}) {
APIService({required String baseURL}) {
_dio = Dio(
BaseOptions(
baseUrl: baseURL, // you can keep this blank
headers: { 'Content-Type': 'application/json; charset=UTF-8' },
headers: {'Content-Type': 'application/json; charset=UTF-8'},
),
)..interceptors.add(LogInterceptor( requestHeader: true, ),);
)..interceptors.add(
LogInterceptor(
requestHeader: true,
),
);
}
Future<APIResponse<T>> call(
String url, String method, Map<String, dynamic>? body, bool force, BuildContext? context) async {
Future<APIResponse<T>> call(String url, String method,
Map<String, dynamic>? body, bool force, BuildContext? context) async {
switch (method.toLowerCase()) {
case 'get' : return await get(url, force, context);
case 'post' : return await post(url, body!, context);
case 'put' : return await put(url, body!, context);
case 'delete' : return await delete(url, context);
default : return await get(url, force, context);
case 'get':
return await get(url, force, context);
case 'post':
return await post(url, body!, context);
case 'put':
return await put(url, body!, context);
case 'delete':
return await delete(url, context);
default:
return await get(url, force, context);
}
}
Future<Response> _request(String url, String method, dynamic body, Options? options) async {
Future<Response> _request(
String url, String method, dynamic body, Options? options) async {
switch (method.toLowerCase()) {
case 'get' : return await _dio.get(url, options: options);
case 'post' : return await _dio.post(url, data:body, options: options);
case 'put' : return await _dio.put(url, data: body!, options: options);
case 'delete' : return await _dio.delete(url, options: options);
default : return await _dio.get(url, options: options);
case 'get':
return await _dio.get(url, options: options);
case 'post':
return await _dio.post(url, data: body, options: options);
case 'put':
return await _dio.put(url, data: body!, options: options);
case 'delete':
return await _dio.delete(url, options: options);
default:
return await _dio.get(url, options: options);
}
}
ValueNotifier downloadProgressNotifier = ValueNotifier(0);
Future _mainDownload(String url, String method, bool isFilter, String? extend, String savePath, bool isWeb, BuildContext context) async {
Future _mainDownload(String url, String method, bool isFilter, String? extend,
String savePath, bool isWeb, BuildContext context) async {
try {
downloadProgressNotifier.value = 0;
if (isWeb) {
if (isWeb) {
_dio.get("$url${extend ?? ""}").then((value) {
var url = http.Url.createObjectUrlFromBlob(http.Blob([value.data]));
http.AnchorElement(href: url)..setAttribute('download', savePath.split("/").last)..click();
http.AnchorElement(href: url)
..setAttribute('download', savePath.split("/").last)
..click();
downloadProgressNotifier.value = 100;
Future.delayed(const Duration(seconds: 1), () { Navigator.of(context).pop(); });
Future.delayed(const Duration(seconds: 1), () {
Navigator.of(context).pop();
});
});
} else {
_dio.download("$url${extend ?? ""}", savePath, onReceiveProgress: (actualBytes, int totalBytes) {
_dio.download("$url${extend ?? ""}", savePath,
onReceiveProgress: (actualBytes, int totalBytes) {
Future.delayed(const Duration(seconds: 1), () {
downloadProgressNotifier.value = (actualBytes / totalBytes * 100).floor();
if (downloadProgressNotifier.value == 100) { Navigator.of(context).pop(); }
});
downloadProgressNotifier.value =
(actualBytes / totalBytes * 100).floor();
if (downloadProgressNotifier.value == 100) {
Navigator.of(context).pop();
}
});
});
}
} catch (e) { /* */ }
} catch (e) {/* */}
}
Future<APIResponse<T>> _main(String url, dynamic body, String method, String succeed, bool force,
BuildContext? context, Options? options) async {
var err = "";
try {
var type = localStorage.getItem('tokenType') ?? "bearer";
_dio.options.headers["Authorization"] = "${type[0].toUpperCase() + type.substring(1)} ${localStorage.getItem('accessToken') ?? ""}";
_dio.interceptors.clear();
var response = await _request(url, method, body, options);
if (response.statusCode != null && response.statusCode! < 400) {
if (method == "delete") { cache.remove(url); return APIResponse<T>(); }
APIResponse<T> resp = APIResponse<T>().deserialize(response.data);
if (resp.error == "") {
if (context != null && succeed != "") {
// ignore: use_build_context_synchronously
showAlertBanner(context, () {}, InfoAlertBannerChild(text: succeed), // <-- Put any widget here you want!
alertBannerLocation: AlertBannerLocation.bottom,);
}
return resp;
Future<APIResponse<T>> _main(
String url,
dynamic body,
String method,
String succeed,
bool force,
BuildContext? context,
Options? options) async {
var err = "";
try {
var type = localStorage.getItem('tokenType') ?? "bearer";
_dio.options.headers["Authorization"] =
"${type[0].toUpperCase() + type.substring(1)} ${localStorage.getItem('accessToken') ?? ""}";
_dio.interceptors.clear();
var response = await _request(url, method, body, options);
if (response.statusCode != null && response.statusCode! < 400) {
if (method == "delete") {
cache.remove(url);
return APIResponse<T>();
}
APIResponse<T> resp = APIResponse<T>().deserialize(response.data);
if (resp.error == "") {
if (context != null && succeed != "") {
// ignore: use_build_context_synchronously
showAlertBanner(
context,
() {},
InfoAlertBannerChild(
text: succeed), // <-- Put any widget here you want!
alertBannerLocation: AlertBannerLocation.bottom,
);
}
err = resp.error ?? "internal error";
}
if (response.statusCode == 401) { err = "not authorized"; }
} catch(e, s) {
print(e);
print(s);
err = e.toString();
return resp;
}
err = resp.error ?? "internal error";
}
if (response.statusCode == 401) {
err = "not authorized";
}
} catch (e, s) {
print(e);
print(s);
err = e.toString();
}
//if (err.contains("token") && err.contains("expired")) { AuthService().unAuthenticate(); }
if (context != null) {
// ignore: use_build_context_synchronously
showAlertBanner( context, () {}, AlertAlertBannerChild(text: err),// <-- Put any widget here you want!
alertBannerLocation: AlertBannerLocation.bottom,);
}
showAlertBanner(
context, () {},
AlertAlertBannerChild(text: err), // <-- Put any widget here you want!
alertBannerLocation: AlertBannerLocation.bottom,
);
}
throw Exception(err);
}
Future<APIResponse<RawData>> raw(String url, dynamic body, String method) async {
var err = "";
Future<APIResponse<RawData>> raw(
String url, dynamic body, String method) async {
var err = "";
if (url != "") {
try {
var type = localStorage.getItem('tokenType') ?? "bearer";
_dio.options.headers["Authorization"] = "${type[0].toUpperCase() + type.substring(1)} ${localStorage.getItem('accessToken') ?? ""}";
_dio.interceptors.clear();
_dio.options.headers["Authorization"] =
"${type[0].toUpperCase() + type.substring(1)} ${localStorage.getItem('accessToken') ?? ""}";
_dio.interceptors.clear();
var response = await _request(url, method, body, null);
if (response.statusCode != null && response.statusCode! < 400) {
if (method == "delete") { cache.remove(url); return APIResponse<RawData>(); }
APIResponse<RawData> resp = APIResponse<RawData>().deserialize(response.data);
if (resp.error == "") { return resp; }
if (method == "delete") {
cache.remove(url);
return APIResponse<RawData>();
}
APIResponse<RawData> resp =
APIResponse<RawData>().deserialize(response.data);
if (resp.error == "") {
return resp;
}
err = resp.error ?? "internal error";
}
if (response.statusCode == 401) { err = "not authorized"; }
} catch(e, s) { print(e); print(s);
err = "${e.toString()} ${const String.fromEnvironment('HOST', defaultValue: 'http://localhost:8080')}"; }
} else { err = "no url"; }
}
if (response.statusCode == 401) {
err = "not authorized";
}
} catch (e, s) {
print(e);
print(s);
err =
"${e.toString()} ${config.get('HOST', defaultValue: 'http://localhost:8080')}";
}
} else {
err = "no url";
}
throw Exception(err);
}
Future<APIResponse<T>> sendFile(String url, File file, BuildContext context) async {
Future<APIResponse<T>> sendFile(
String url, File file, BuildContext context) async {
FormData formData = FormData.fromMap({
"file": await MultipartFile.fromFile(file.path, filename:file.path.split("/").last),
"file": await MultipartFile.fromFile(file.path,
filename: file.path.split("/").last),
});
// ignore: use_build_context_synchronously
return _main(url, formData, "post", "send succeed", true, context, Options(contentType: 'multipart/form-data'));
return _main(url, formData, "post", "send succeed", true, context,
Options(contentType: 'multipart/form-data'));
}
Future getWithDownload(String url, String format, Map<String,dynamic> cache, String savePath, bool isWeb, BuildContext context) async {
Future getWithDownload(String url, String format, Map<String, dynamic> cache,
String savePath, bool isWeb, BuildContext context) async {
String asLabel = "";
for (var key in cache.keys) {
if (!asLabel.contains(key)) { asLabel += "&${key}_aslabel=${cache[key]!}"; }
if (!asLabel.contains(key)) {
asLabel += "&${key}_aslabel=${cache[key]!}";
}
}
try { _mainDownload(url, "get", true, "&export=$format$asLabel", savePath, isWeb, context);
} catch (e) { /* */ }
try {
_mainDownload(url, "get", true, "&export=$format$asLabel", savePath,
isWeb, context);
} catch (e) {/* */}
}
Future<APIResponse<T>> getWithOffset(String url, bool force, BuildContext? context) async {
Future<APIResponse<T>> getWithOffset(
String url, bool force, BuildContext? context) async {
return _main(url, null, "get", "", force, context, null);
}
Future<APIResponse<T>> get(String url, bool force, BuildContext? context) async {
Future<APIResponse<T>> get(
String url, bool force, BuildContext? context) async {
return _main(url, null, "get", "", force, context, null);
}
Future<APIResponse<T>> post(String url, Map<String, dynamic> values, BuildContext? context) async {
Future<APIResponse<T>> post(
String url, Map<String, dynamic> values, BuildContext? context) async {
return _main(url, values, "post", "send succeed", true, context, null);
}
Future<APIResponse<T>> put(String url, Map<String, dynamic> values, BuildContext? context) async {
Future<APIResponse<T>> put(
String url, Map<String, dynamic> values, BuildContext? context) async {
return _main(url, values, "put", "save succeed", true, context, null);
}
Future<APIResponse<T>> delete(String url, BuildContext? context) async {
return _main(url, null, "delete", "deletion succeed", true, context, null);
}
}
}

View File

@@ -1,26 +1,36 @@
import 'package:localstorage/localstorage.dart';
import 'package:oc_front/core/conf/conf_reader.dart';
import 'package:oc_front/core/sections/header/header.dart';
import 'package:oc_front/core/services/api_service.dart';
import 'package:oc_front/core/services/perms_service.dart';
import 'package:oc_front/main.dart';
import 'package:oc_front/models/response.dart';
class AuthService {
static var isAuth = const bool.fromEnvironment('AUTH_MODE', defaultValue: false);
static var config = AppConfig();
static var isAuth = false;
AuthService() {
isAuth = config.get('AUTH_MODE') == 'true';
}
static APIService<SimpleData> service = APIService(
baseURL: const String.fromEnvironment('AUTH_HOST', defaultValue: 'http://localhost:8080/auth'),
baseURL:
config.get('AUTH_HOST', defaultValue: 'http://localhost:8080/auth'),
);
static Future<void> init() async {
if (!isAuth) {
return;
}
PermsService.init(localStorage.getItem('accessToken') ?? "");
bool ok = await introspect().catchError( (e) => false );
bool ok = await introspect().catchError((e) => false);
if (ok) {
var now = DateTime.now();
var expires = DateTime.parse(localStorage.getItem('expiresIn') ?? DateTime.now().toIso8601String());
var expires = DateTime.parse(localStorage.getItem('expiresIn') ??
DateTime.now().toIso8601String());
var duration = expires.difference(now);
refresh(localStorage.getItem('accessToken') ?? "", localStorage.getItem('username') ?? "", duration);
refresh(localStorage.getItem('accessToken') ?? "",
localStorage.getItem('username') ?? "", duration);
} else {
localStorage.setItem('accessToken', '');
localStorage.setItem('username', '');
@@ -37,25 +47,27 @@ class AuthService {
static String? getUsername() {
if (!isAuth) {
return "no auth user";
return "no auth user";
}
return localStorage.getItem('username') ?? "unknown";
}
static Future<void> login(String username, String password) async {
var token = await service.post("/ldap/login", <String, dynamic> {
"username": username,
"password": password
}, null);
var token = await service.post("/ldap/login",
<String, dynamic>{"username": username, "password": password}, null);
if (token.code == 200 && token.data != null) {
localStorage.setItem('accessToken', token.data?.value['access_token']);
localStorage.setItem('tokenType', token.data?.value['token_type']);
localStorage.setItem('username', username);
localStorage.setItem('expiresIn',
DateTime.now().add(Duration(seconds: token.data?.value['expires_in'])).toIso8601String());
localStorage.setItem(
'expiresIn',
DateTime.now()
.add(Duration(seconds: token.data?.value['expires_in']))
.toIso8601String());
HeaderConstants.headerKey.currentState?.setState(() {});
PermsService.init(token.data?.value['access_token']);
refresh(token.data?.value['access_token'] ?? "", username, Duration(seconds: token.data?.value['expires_in']));
refresh(token.data?.value['access_token'] ?? "", username,
Duration(seconds: token.data?.value['expires_in']));
}
}
@@ -77,20 +89,31 @@ class AuthService {
return isIntrospected.code == 200;
}
static Future<void> refresh(String accessToken, String username, Duration duration) async {
static Future<void> refresh(
String accessToken, String username, Duration duration) async {
Future.delayed(duration, () {
service.post("/refresh", <String, dynamic> {
"access_token": accessToken,
"username": username
}, null).then((token) {
service
.post(
"/refresh",
<String, dynamic>{
"access_token": accessToken,
"username": username
},
null)
.then((token) {
if (token.code == 200 && token.data != null) {
PermsService.init(token.data?.value['access_token']);
localStorage.setItem('accessToken', token.data?.value['access_token']);
localStorage.setItem(
'accessToken', token.data?.value['access_token']);
localStorage.setItem('username', username);
localStorage.setItem('expiresIn',
DateTime.now().add(Duration(seconds: token.data?.value['expires_in']) - Duration(seconds: 10)).toIso8601String());
localStorage.setItem(
'expiresIn',
DateTime.now()
.add(Duration(seconds: token.data?.value['expires_in']) -
Duration(seconds: 10))
.toIso8601String());
}
});
});
}
}
}

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:oc_front/core/conf/conf_reader.dart';
import 'package:oc_front/models/abstract.dart';
import 'package:oc_front/models/response.dart';
import 'package:oc_front/core/services/api_service.dart';
@@ -6,22 +7,33 @@ import 'package:oc_front/core/services/api_service.dart';
abstract class AbstractService<T extends SerializerDeserializer> {
abstract APIService<T> service;
abstract String subPath;
Future<APIResponse<T>> search(BuildContext? context, List<String> words, Map<String, dynamic> params) { throw UnimplementedError(); }
var conf = AppConfig();
Future<APIResponse<T>> search(
BuildContext? context, List<String> words, Map<String, dynamic> params) {
throw UnimplementedError();
}
Future<APIResponse<RawData>> all(BuildContext? context) {
return service.raw(subPath, null, "get");
}
Future<APIResponse<T>> get(BuildContext? context, String id) {
Future<APIResponse<T>> get(BuildContext? context, String id) {
return service.get("$subPath$id", true, context);
}
Future<APIResponse<T>> post(BuildContext? context, Map<String, dynamic> body, Map<String, String> params) {
Future<APIResponse<T>> post(BuildContext? context, Map<String, dynamic> body,
Map<String, String> params) {
return service.post(subPath, body, context);
}
Future<APIResponse<T>> put(BuildContext? context, String id, Map<String, dynamic> body, Map<String, String> params) {
Future<APIResponse<T>> put(BuildContext? context, String id,
Map<String, dynamic> body, Map<String, String> params) {
return service.put("$subPath$id", body, context);
}
Future<APIResponse<T>> delete(BuildContext? context, String id, Map<String, String> params) {
Future<APIResponse<T>> delete(
BuildContext? context, String id, Map<String, String> params) {
return service.delete("$subPath$id", context);
}
}

View File

@@ -5,20 +5,33 @@ import 'package:oc_front/models/response.dart';
import 'package:oc_front/models/workflow.dart';
class BookingExecutionService extends AbstractService<WorkflowExecutions> {
@override APIService<WorkflowExecutions> service = APIService<WorkflowExecutions>(
baseURL: const String.fromEnvironment('DATACENTER_HOST', defaultValue: 'http://localhost:8080/datacenter')
);
@override String subPath = "/booking/";
@override
late final APIService<WorkflowExecutions> service;
@override
String subPath = "/booking/";
@override Future<APIResponse<WorkflowExecutions>> search(BuildContext? context, List<String> words, Map<String, dynamic> params) {
BookingExecutionService() {
service = APIService<WorkflowExecutions>(
baseURL: super.conf.get('DATACENTER_HOST',
defaultValue: 'http://localhost:8080/datacenter'));
}
@override
Future<APIResponse<WorkflowExecutions>> search(
BuildContext? context, List<String> words, Map<String, dynamic> params) {
print("${subPath}search/${words.join("/")}");
return service.get("${subPath}search/${words.join("/")}", false, context);
}
@override Future<APIResponse<WorkflowExecutions>> post(BuildContext? context, Map<String, dynamic> body, Map<String, String> params) {
@override
Future<APIResponse<WorkflowExecutions>> post(BuildContext? context,
Map<String, dynamic> body, Map<String, String> params) {
return throw UnimplementedError();
}
@override Future<APIResponse<WorkflowExecutions>> put(BuildContext? context, String id, Map<String, dynamic> body, Map<String, String> params) {
@override
Future<APIResponse<WorkflowExecutions>> put(BuildContext? context, String id,
Map<String, dynamic> body, Map<String, String> params) {
return throw UnimplementedError();
}
}
}

View File

@@ -5,32 +5,49 @@ import 'package:oc_front/models/response.dart';
import 'package:oc_front/models/workflow.dart';
class CheckService extends AbstractService<Check> {
@override APIService<Check> service = APIService<Check>(
baseURL: const String.fromEnvironment('WORKFLOW_HOST', defaultValue: 'http://localhost:8080/workflow')
);
@override String subPath = "/check/";
@override
late final APIService<Check> service;
Future<APIResponse<Check>> search(BuildContext? context, List<String> words, Map<String, dynamic> params) {
@override
String subPath = "/check/";
CheckService() {
service = APIService<Check>(
baseURL: super
.conf
.get('CHECK_HOST', defaultValue: 'http://localhost:8080/check'));
}
Future<APIResponse<Check>> search(
BuildContext? context, List<String> words, Map<String, dynamic> params) {
return service.get("$subPath${words.join("/")}", true, context);
}
@override
Future<APIResponse<RawData>> all(BuildContext? context) {
throw UnimplementedError();
}
@override
Future<APIResponse<Check>> get(BuildContext? context, String id) {
throw UnimplementedError();
}
@override
Future<APIResponse<Check>> post(BuildContext? context, Map<String, dynamic> body, Map<String, String> params) {
throw UnimplementedError();
}
@override
Future<APIResponse<Check>> put(BuildContext? context, String id, Map<String, dynamic> body, Map<String, String> params) {
throw UnimplementedError();
}
@override
Future<APIResponse<Check>> delete(BuildContext? context, String id, Map<String, String> params) {
Future<APIResponse<Check>> get(BuildContext? context, String id) {
throw UnimplementedError();
}
}
@override
Future<APIResponse<Check>> post(BuildContext? context,
Map<String, dynamic> body, Map<String, String> params) {
throw UnimplementedError();
}
@override
Future<APIResponse<Check>> put(BuildContext? context, String id,
Map<String, dynamic> body, Map<String, String> params) {
throw UnimplementedError();
}
@override
Future<APIResponse<Check>> delete(
BuildContext? context, String id, Map<String, String> params) {
throw UnimplementedError();
}
}

View File

@@ -5,31 +5,56 @@ import 'package:oc_front/models/logs.dart';
import 'package:oc_front/models/response.dart';
class LogsService extends AbstractService<LogsResult> {
@override APIService<LogsResult> service = APIService<LogsResult>(
baseURL: const String.fromEnvironment('LOGS_HOST', defaultValue: 'http://localhost:3100')
);
@override String subPath = "/loki/api/v1/";
@override
late final APIService<LogsResult> service;
@override Future<APIResponse<LogsResult>> search(BuildContext? context, List<String> words, Map<String, dynamic> params) {
@override
String subPath = "/loki/api/v1/";
LogService() {
service = APIService<LogsResult>(
baseURL:
super.conf.get('LOGS_HOST', defaultValue: 'http://localhost:3100'));
}
@override
Future<APIResponse<LogsResult>> search(
BuildContext? context, List<String> words, Map<String, dynamic> params) {
List<String> v = [];
for (var p in params.keys) {
if (p == "start" || p == "end") { continue; }
if (p == "start" || p == "end") {
continue;
}
v.add("$p=\"${params[p]}\"");
}
print("${subPath}query_range?query={${v.join(", ")}}&start=${params["start"].toString().substring(0, 10)}&end=${params["end"].toString().substring(0, 10)}");
return service.get("${subPath}query_range?query={${v.join(", ")}}&start=${params["start"].toString().substring(0, 10)}&end=${params["end"].toString().substring(0, 10)}", false, context);
}
print(
"${subPath}query_range?query={${v.join(", ")}}&start=${params["start"].toString().substring(0, 10)}&end=${params["end"].toString().substring(0, 10)}");
return service.get(
"${subPath}query_range?query={${v.join(", ")}}&start=${params["start"].toString().substring(0, 10)}&end=${params["end"].toString().substring(0, 10)}",
false,
context);
}
@override Future<APIResponse<LogsResult>> get(BuildContext? context, String id) {
@override
Future<APIResponse<LogsResult>> get(BuildContext? context, String id) {
throw UnimplementedError();
}
@override Future<APIResponse<LogsResult>> post(BuildContext? context, Map<String, dynamic> body, Map<String, String> params) {
@override
Future<APIResponse<LogsResult>> post(BuildContext? context,
Map<String, dynamic> body, Map<String, String> params) {
throw UnimplementedError();
}
@override Future<APIResponse<LogsResult>> put(BuildContext? context, String id, Map<String, dynamic> body, Map<String, String> params) {
@override
Future<APIResponse<LogsResult>> put(BuildContext? context, String id,
Map<String, dynamic> body, Map<String, String> params) {
throw UnimplementedError();
}
@override Future<APIResponse<LogsResult>> delete(BuildContext? context, String id, Map<String, String> params) {
@override
Future<APIResponse<LogsResult>> delete(
BuildContext? context, String id, Map<String, String> params) {
throw UnimplementedError();
}
}

View File

@@ -3,8 +3,15 @@ import 'package:oc_front/core/services/specialized_services/abstract_service.dar
import 'package:oc_front/models/shared.dart';
class PeerService extends AbstractService<Peer> {
@override APIService<Peer> service = APIService<Peer>(
baseURL: const String.fromEnvironment('PEER_HOST', defaultValue: 'http://localhost:8080/peer')
);
@override String subPath = "/";
}
@override
late final APIService<Peer> service;
@override
String subPath = "/";
PeerService() {
service = APIService<Peer>(
baseURL: super
.conf
.get('PEER_HOST', defaultValue: 'http://localhost:8080/peer'));
}
}

View File

@@ -5,19 +5,34 @@ import 'package:oc_front/models/response.dart';
import 'package:oc_front/models/search.dart';
class ResourceService extends AbstractService<Resource> {
@override APIService<Resource> service = APIService<Resource>(
baseURL: const String.fromEnvironment('ITEM_HOST', defaultValue: 'http://localhost:8080/catalog')
);
@override String subPath = "/resource/";
@override
late final APIService<Resource> service;
@override Future<APIResponse<Resource>> search(BuildContext? context, List<String> words, Map<String, dynamic> params) {
@override
String subPath = "/resource/";
ResourceService() {
service = APIService<Resource>(
baseURL: super
.conf
.get('ITEM_HOST', defaultValue: 'http://localhost:8080/catalog'));
}
@override
Future<APIResponse<Resource>> search(
BuildContext? context, List<String> words, Map<String, dynamic> params) {
return service.get("${subPath}search/${words.join("/")}", false, context);
}
@override Future<APIResponse<Resource>> post(BuildContext? context, Map<String, dynamic> body, Map<String, String> params) {
@override
Future<APIResponse<Resource>> post(BuildContext? context,
Map<String, dynamic> body, Map<String, String> params) {
return throw UnimplementedError();
}
@override Future<APIResponse<Resource>> put(BuildContext? context, String id, Map<String, dynamic> body, Map<String, String> params) {
@override
Future<APIResponse<Resource>> put(BuildContext? context, String id,
Map<String, dynamic> body, Map<String, String> params) {
return throw UnimplementedError();
}
}

View File

@@ -5,32 +5,45 @@ import 'package:oc_front/models/response.dart';
import 'package:oc_front/models/shared.dart';
class SharedService extends AbstractService<CollaborativeArea> {
@override APIService<CollaborativeArea> service = APIService<CollaborativeArea>(
baseURL: const String.fromEnvironment('COLLABORATIVE_AREA_HOST', defaultValue: 'http://localhost:8080/shared')
);
@override String subPath = "/collaborative_area/";
@override
late final APIService<CollaborativeArea> service;
Future<APIResponse<CollaborativeArea>> addWorkspace(BuildContext? context, String id, String id2) {
@override
String subPath = "/collaborative_area/";
SharedService() {
service = APIService<CollaborativeArea>(
baseURL: super.conf.get('COLLABORATIVE_AREA_HOST',
defaultValue: 'http://localhost:8080/shared'));
}
Future<APIResponse<CollaborativeArea>> addWorkspace(
BuildContext? context, String id, String id2) {
return service.post("$subPath$id/workspace/$id2", {}, context);
}
Future<APIResponse<CollaborativeArea>> addWorkflow(BuildContext? context, String id, String id2) {
Future<APIResponse<CollaborativeArea>> addWorkflow(
BuildContext? context, String id, String id2) {
return service.post("$subPath$id/workflow/$id2", {}, context);
}
Future<APIResponse<CollaborativeArea>> addPeer(BuildContext? context, String id, String id2) {
Future<APIResponse<CollaborativeArea>> addPeer(
BuildContext? context, String id, String id2) {
return service.post("$subPath$id/peer/$id2", {}, context);
}
Future<APIResponse<CollaborativeArea>> removeWorkspace(BuildContext? context, String id, String id2) {
Future<APIResponse<CollaborativeArea>> removeWorkspace(
BuildContext? context, String id, String id2) {
return service.delete("$subPath$id/workspace/$id2", context);
}
Future<APIResponse<CollaborativeArea>> removeWorkflow(BuildContext? context, String id, String id2) {
Future<APIResponse<CollaborativeArea>> removeWorkflow(
BuildContext? context, String id, String id2) {
return service.delete("$subPath$id/workflow/$id2", context);
}
Future<APIResponse<CollaborativeArea>> removePeer(BuildContext? context, String id, String id2) {
Future<APIResponse<CollaborativeArea>> removePeer(
BuildContext? context, String id, String id2) {
return service.delete("$subPath$id/peer/$id2", context);
}
}
}

View File

@@ -5,19 +5,32 @@ import 'package:oc_front/models/response.dart';
import 'package:oc_front/models/workflow.dart';
class WorkflowExecutionService extends AbstractService<WorkflowExecutions> {
@override APIService<WorkflowExecutions> service = APIService<WorkflowExecutions>(
baseURL: const String.fromEnvironment('SCHEDULER_HOST', defaultValue: 'http://localhost:8080/scheduler')
);
@override String subPath = "/";
@override
late final APIService<WorkflowExecutions> service;
@override Future<APIResponse<WorkflowExecutions>> search(BuildContext? context, List<String> words, Map<String, dynamic> params) {
@override
String subPath = "/";
WorkflowExecutionService() {
service = APIService<WorkflowExecutions>(
baseURL: super.conf.get('SCHEDULER_HOST',
defaultValue: 'http://localhost:8080/scheduler'));
}
@override
Future<APIResponse<WorkflowExecutions>> search(
BuildContext? context, List<String> words, Map<String, dynamic> params) {
return service.get("${subPath}search/${words.join("/")}", false, context);
}
@override Future<APIResponse<WorkflowExecutions>> post(BuildContext? context, Map<String, dynamic> body, Map<String, String> params) {
@override
Future<APIResponse<WorkflowExecutions>> post(BuildContext? context,
Map<String, dynamic> body, Map<String, String> params) {
return throw UnimplementedError();
}
@override Future<APIResponse<WorkflowExecutions>> put(BuildContext? context, String id, Map<String, dynamic> body, Map<String, String> params) {
@override
Future<APIResponse<WorkflowExecutions>> put(BuildContext? context, String id,
Map<String, dynamic> body, Map<String, String> params) {
return throw UnimplementedError();
}
}
}

View File

@@ -3,8 +3,14 @@ import 'package:oc_front/core/services/specialized_services/abstract_service.dar
import 'package:oc_front/models/workflow.dart';
class WorflowService extends AbstractService<Workflow> {
@override APIService<Workflow> service = APIService<Workflow>(
baseURL: const String.fromEnvironment('WORKFLOW_HOST', defaultValue: 'http://localhost:8080/workflow')
);
@override String subPath = "/";
}
@override
late final APIService<Workflow> service;
@override
String subPath = "/";
WorflowService() {
service = APIService<Workflow>(
baseURL: super.conf.get('WORKFLOW_HOST',
defaultValue: 'http://localhost:8080/workflow'));
}
}

View File

@@ -3,8 +3,15 @@ import 'package:oc_front/core/services/specialized_services/abstract_service.dar
import 'package:oc_front/models/workspace.dart';
class WorkspaceService extends AbstractService<Workspace> {
@override APIService<Workspace> service = APIService<Workspace>(
baseURL: const String.fromEnvironment('WORKSPACE_HOST', defaultValue: 'http://localhost:8080/workspace')
);
@override String subPath = "/";
}
@override
late final APIService<Workspace> service;
@override
String subPath = "/";
WorkspaceService() {
service = APIService<Workspace>(
baseURL: super.conf.get('WORKSPACE_HOST',
defaultValue: 'http://localhost:8080/workspace'));
}
}

View File

@@ -12,28 +12,38 @@ import 'package:oc_front/core/services/auth.service.dart';
import 'package:oc_front/core/services/router.dart';
import 'package:oc_front/core/sections/end_drawer.dart';
import 'package:oc_front/widgets/dialog/login.dart';
import 'package:oc_front/core/conf/conf_reader.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
WidgetsFlutterBinding.ensureInitialized();
// Load configuration before running the app
final appConfig = AppConfig();
await appConfig.loadConfig();
// Run `LinuxWebViewPlugin.initialize()` first before creating a WebView.
await initLocalStorage();
runApp(const MyApp());
}
GlobalKey<MainPageState>? mainKey;
GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
AuthService.init();
return MaterialApp.router( routerConfig: GoRouter( routes: AppRouter.routes ) );
return MaterialApp.router(routerConfig: GoRouter(routes: AppRouter.routes));
}
}
// ignore: must_be_immutable
class MainPage extends StatefulWidget {
Widget? page;
MainPage({Key? key, required this.page}) : super(key: GlobalKey<MainPageState>());
MainPage({Key? key, required this.page})
: super(key: GlobalKey<MainPageState>());
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
@@ -49,22 +59,27 @@ class MainPage extends StatefulWidget {
}
var darkColor = Color.fromRGBO(26, 83, 92, 1);
var lightColor = Color.fromRGBO(78, 205, 196, 1);
var lightColor = Color.fromRGBO(78, 205, 196, 1);
var darkMidColor = Color.fromRGBO(44, 83, 100, 1);
var midColor = Colors.grey.shade300;
var redColor = Color.fromRGBO(255, 107, 107, 1);
double getWidth(BuildContext context) {
return MediaQuery.of(context).size.width <= 800 ? 800 : MediaQuery.of(context).size.width;
return MediaQuery.of(context).size.width <= 800
? 800
: MediaQuery.of(context).size.width;
}
double getHeight(BuildContext context) {
return MediaQuery.of(context).size.height <= 400 ? 400 : MediaQuery.of(context).size.height;
return MediaQuery.of(context).size.height <= 400
? 400
: MediaQuery.of(context).size.height;
}
double getMainHeight(BuildContext context) {
return getHeight(context) - HeaderConstants.height;
}
double getMainWidth(BuildContext context) {
return getWidth(context) - 50;
}
@@ -88,63 +103,80 @@ class MainPageState extends State<MainPage> {
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.i
scaffoldKey = GlobalKey<ScaffoldState>();
isCtrl = false;
isCtrl = false;
if (!AuthService.isConnected()) {
print("isConnected: ${AuthService.isConnected()}");
Future.delayed(const Duration(milliseconds: 500), () {
showDialog(
barrierDismissible: false,
context: context, builder: (context) {
return AlertDialog(
print("isConnected: ${AuthService.isConnected()}");
Future.delayed(const Duration(milliseconds: 500), () {
showDialog(
barrierDismissible: false,
context: context,
builder: (context) {
return AlertDialog(
insetPadding: EdgeInsets.zero,
backgroundColor: Colors.white,
shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0)),
title: LoginWidget());
});
});
});
});
}
return FutureBuilder(future: AuthService.init(),
builder: (e, s) {
WorkspaceLocal.init(context, false);
CollaborativeAreaLocal.init(context, false);
HeaderConstants.height = HeaderConstants.isNoHeader(AppRouter.currentRoute.route) || AppRouter.currentRoute.factory.searchFill() ? 50 : 100;
return Scaffold( key: scaffoldKey, endDrawer: EndDrawerWidget(), body:
SingleChildScrollView(
controller: ScrollController(),
scrollDirection: Axis.horizontal,
child: SingleChildScrollView(
child: Column( children: [
HeaderMenuWidget(),
Row( children : [
Container( padding: const EdgeInsets.symmetric(vertical: 30),
decoration: BoxDecoration( color: darkColor),
width: 50, height: getHeight(context) - 50,
child: SingleChildScrollView( child: LeftMenuWidget() )),
SizedBox( width: getMainWidth(context), height: getHeight(context) - 50,
child: KeyboardListener(
focusNode: node,
onKeyEvent: (event) async {
if ( event.logicalKey == LogicalKeyboardKey.controlLeft ) {
isCtrl = (event is KeyDownEvent);
node.requestFocus();
} else if( (event is KeyDownEvent) && event.logicalKey == LogicalKeyboardKey.enter) {
AppRouter.currentRoute.factory.search(context, isCtrl);
node.requestFocus();
}
},
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
HeaderWidget(),
widget.page ?? Container() // CatalogPageWidget(),
],
),
)),
])
])
)
));
});
return FutureBuilder(
future: AuthService.init(),
builder: (e, s) {
WorkspaceLocal.init(context, false);
CollaborativeAreaLocal.init(context, false);
HeaderConstants.height =
HeaderConstants.isNoHeader(AppRouter.currentRoute.route) ||
AppRouter.currentRoute.factory.searchFill()
? 50
: 100;
return Scaffold(
key: scaffoldKey,
endDrawer: EndDrawerWidget(),
body: SingleChildScrollView(
controller: ScrollController(),
scrollDirection: Axis.horizontal,
child: SingleChildScrollView(
child: Column(children: [
HeaderMenuWidget(),
Row(children: [
Container(
padding: const EdgeInsets.symmetric(vertical: 30),
decoration: BoxDecoration(color: darkColor),
width: 50,
height: getHeight(context) - 50,
child:
SingleChildScrollView(child: LeftMenuWidget())),
SizedBox(
width: getMainWidth(context),
height: getHeight(context) - 50,
child: KeyboardListener(
focusNode: node,
onKeyEvent: (event) async {
if (event.logicalKey ==
LogicalKeyboardKey.controlLeft) {
isCtrl = (event is KeyDownEvent);
node.requestFocus();
} else if ((event is KeyDownEvent) &&
event.logicalKey ==
LogicalKeyboardKey.enter) {
AppRouter.currentRoute.factory
.search(context, isCtrl);
node.requestFocus();
}
},
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
HeaderWidget(),
widget.page ??
Container() // CatalogPageWidget(),
],
),
)),
])
]))));
});
}
}