mirror of
https://github.com/immich-app/immich.git
synced 2025-12-17 01:11:13 +03:00
feat: sync status to web app
This commit is contained in:
3
mobile/openapi/README.md
generated
3
mobile/openapi/README.md
generated
@@ -159,6 +159,8 @@ Class | Method | HTTP request | Description
|
|||||||
*LibrariesApi* | [**scanLibrary**](doc//LibrariesApi.md#scanlibrary) | **POST** /libraries/{id}/scan | Scan a library
|
*LibrariesApi* | [**scanLibrary**](doc//LibrariesApi.md#scanlibrary) | **POST** /libraries/{id}/scan | Scan a library
|
||||||
*LibrariesApi* | [**updateLibrary**](doc//LibrariesApi.md#updatelibrary) | **PUT** /libraries/{id} | Update a library
|
*LibrariesApi* | [**updateLibrary**](doc//LibrariesApi.md#updatelibrary) | **PUT** /libraries/{id} | Update a library
|
||||||
*LibrariesApi* | [**validate**](doc//LibrariesApi.md#validate) | **POST** /libraries/{id}/validate | Validate library settings
|
*LibrariesApi* | [**validate**](doc//LibrariesApi.md#validate) | **POST** /libraries/{id}/validate | Validate library settings
|
||||||
|
*MaintenanceAdminApi* | [**deleteBackup**](doc//MaintenanceAdminApi.md#deletebackup) | **DELETE** /admin/maintenance/admin/maintenance/backups/{filename} | Delete backup
|
||||||
|
*MaintenanceAdminApi* | [**listBackups**](doc//MaintenanceAdminApi.md#listbackups) | **GET** /admin/maintenance/admin/maintenance/backups/list | List backups
|
||||||
*MaintenanceAdminApi* | [**maintenanceLogin**](doc//MaintenanceAdminApi.md#maintenancelogin) | **POST** /admin/maintenance/login | Log into maintenance mode
|
*MaintenanceAdminApi* | [**maintenanceLogin**](doc//MaintenanceAdminApi.md#maintenancelogin) | **POST** /admin/maintenance/login | Log into maintenance mode
|
||||||
*MaintenanceAdminApi* | [**maintenanceStatus**](doc//MaintenanceAdminApi.md#maintenancestatus) | **GET** /admin/maintenance/admin/maintenance/status | Get maintenance mode status
|
*MaintenanceAdminApi* | [**maintenanceStatus**](doc//MaintenanceAdminApi.md#maintenancestatus) | **GET** /admin/maintenance/admin/maintenance/status | Get maintenance mode status
|
||||||
*MaintenanceAdminApi* | [**setMaintenanceMode**](doc//MaintenanceAdminApi.md#setmaintenancemode) | **POST** /admin/maintenance | Set maintenance mode
|
*MaintenanceAdminApi* | [**setMaintenanceMode**](doc//MaintenanceAdminApi.md#setmaintenancemode) | **POST** /admin/maintenance | Set maintenance mode
|
||||||
@@ -409,6 +411,7 @@ Class | Method | HTTP request | Description
|
|||||||
- [MachineLearningAvailabilityChecksDto](doc//MachineLearningAvailabilityChecksDto.md)
|
- [MachineLearningAvailabilityChecksDto](doc//MachineLearningAvailabilityChecksDto.md)
|
||||||
- [MaintenanceAction](doc//MaintenanceAction.md)
|
- [MaintenanceAction](doc//MaintenanceAction.md)
|
||||||
- [MaintenanceAuthDto](doc//MaintenanceAuthDto.md)
|
- [MaintenanceAuthDto](doc//MaintenanceAuthDto.md)
|
||||||
|
- [MaintenanceListBackupsResponseDto](doc//MaintenanceListBackupsResponseDto.md)
|
||||||
- [MaintenanceLoginDto](doc//MaintenanceLoginDto.md)
|
- [MaintenanceLoginDto](doc//MaintenanceLoginDto.md)
|
||||||
- [MaintenanceStatusResponseDto](doc//MaintenanceStatusResponseDto.md)
|
- [MaintenanceStatusResponseDto](doc//MaintenanceStatusResponseDto.md)
|
||||||
- [ManualJobName](doc//ManualJobName.md)
|
- [ManualJobName](doc//ManualJobName.md)
|
||||||
|
|||||||
1
mobile/openapi/lib/api.dart
generated
1
mobile/openapi/lib/api.dart
generated
@@ -166,6 +166,7 @@ part 'model/logout_response_dto.dart';
|
|||||||
part 'model/machine_learning_availability_checks_dto.dart';
|
part 'model/machine_learning_availability_checks_dto.dart';
|
||||||
part 'model/maintenance_action.dart';
|
part 'model/maintenance_action.dart';
|
||||||
part 'model/maintenance_auth_dto.dart';
|
part 'model/maintenance_auth_dto.dart';
|
||||||
|
part 'model/maintenance_list_backups_response_dto.dart';
|
||||||
part 'model/maintenance_login_dto.dart';
|
part 'model/maintenance_login_dto.dart';
|
||||||
part 'model/maintenance_status_response_dto.dart';
|
part 'model/maintenance_status_response_dto.dart';
|
||||||
part 'model/manual_job_name.dart';
|
part 'model/manual_job_name.dart';
|
||||||
|
|||||||
97
mobile/openapi/lib/api/maintenance_admin_api.dart
generated
97
mobile/openapi/lib/api/maintenance_admin_api.dart
generated
@@ -16,6 +16,103 @@ class MaintenanceAdminApi {
|
|||||||
|
|
||||||
final ApiClient apiClient;
|
final ApiClient apiClient;
|
||||||
|
|
||||||
|
/// Delete backup
|
||||||
|
///
|
||||||
|
/// Delete a backup by its filename
|
||||||
|
///
|
||||||
|
/// Note: This method returns the HTTP [Response].
|
||||||
|
///
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [String] filename (required):
|
||||||
|
Future<Response> deleteBackupWithHttpInfo(String filename,) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final apiPath = r'/admin/maintenance/admin/maintenance/backups/{filename}'
|
||||||
|
.replaceAll('{filename}', filename);
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>[];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
apiPath,
|
||||||
|
'DELETE',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete backup
|
||||||
|
///
|
||||||
|
/// Delete a backup by its filename
|
||||||
|
///
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [String] filename (required):
|
||||||
|
Future<void> deleteBackup(String filename,) async {
|
||||||
|
final response = await deleteBackupWithHttpInfo(filename,);
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// List backups
|
||||||
|
///
|
||||||
|
/// Get the list of the successful and failed backups
|
||||||
|
///
|
||||||
|
/// Note: This method returns the HTTP [Response].
|
||||||
|
Future<Response> listBackupsWithHttpInfo() async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final apiPath = r'/admin/maintenance/admin/maintenance/backups/list';
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>[];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
apiPath,
|
||||||
|
'GET',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// List backups
|
||||||
|
///
|
||||||
|
/// Get the list of the successful and failed backups
|
||||||
|
Future<MaintenanceListBackupsResponseDto?> listBackups() async {
|
||||||
|
final response = await listBackupsWithHttpInfo();
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||||
|
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||||
|
// FormatException when trying to decode an empty string.
|
||||||
|
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||||
|
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'MaintenanceListBackupsResponseDto',) as MaintenanceListBackupsResponseDto;
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// Log into maintenance mode
|
/// Log into maintenance mode
|
||||||
///
|
///
|
||||||
/// Login with maintenance token or cookie to receive current information and perform further actions.
|
/// Login with maintenance token or cookie to receive current information and perform further actions.
|
||||||
|
|||||||
2
mobile/openapi/lib/api_client.dart
generated
2
mobile/openapi/lib/api_client.dart
generated
@@ -382,6 +382,8 @@ class ApiClient {
|
|||||||
return MaintenanceActionTypeTransformer().decode(value);
|
return MaintenanceActionTypeTransformer().decode(value);
|
||||||
case 'MaintenanceAuthDto':
|
case 'MaintenanceAuthDto':
|
||||||
return MaintenanceAuthDto.fromJson(value);
|
return MaintenanceAuthDto.fromJson(value);
|
||||||
|
case 'MaintenanceListBackupsResponseDto':
|
||||||
|
return MaintenanceListBackupsResponseDto.fromJson(value);
|
||||||
case 'MaintenanceLoginDto':
|
case 'MaintenanceLoginDto':
|
||||||
return MaintenanceLoginDto.fromJson(value);
|
return MaintenanceLoginDto.fromJson(value);
|
||||||
case 'MaintenanceStatusResponseDto':
|
case 'MaintenanceStatusResponseDto':
|
||||||
|
|||||||
111
mobile/openapi/lib/model/maintenance_list_backups_response_dto.dart
generated
Normal file
111
mobile/openapi/lib/model/maintenance_list_backups_response_dto.dart
generated
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
//
|
||||||
|
// AUTO-GENERATED FILE, DO NOT MODIFY!
|
||||||
|
//
|
||||||
|
// @dart=2.18
|
||||||
|
|
||||||
|
// ignore_for_file: unused_element, unused_import
|
||||||
|
// ignore_for_file: always_put_required_named_parameters_first
|
||||||
|
// ignore_for_file: constant_identifier_names
|
||||||
|
// ignore_for_file: lines_longer_than_80_chars
|
||||||
|
|
||||||
|
part of openapi.api;
|
||||||
|
|
||||||
|
class MaintenanceListBackupsResponseDto {
|
||||||
|
/// Returns a new [MaintenanceListBackupsResponseDto] instance.
|
||||||
|
MaintenanceListBackupsResponseDto({
|
||||||
|
this.backups = const [],
|
||||||
|
this.failedBackups = const [],
|
||||||
|
});
|
||||||
|
|
||||||
|
List<String> backups;
|
||||||
|
|
||||||
|
List<String> failedBackups;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => identical(this, other) || other is MaintenanceListBackupsResponseDto &&
|
||||||
|
_deepEquality.equals(other.backups, backups) &&
|
||||||
|
_deepEquality.equals(other.failedBackups, failedBackups);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode =>
|
||||||
|
// ignore: unnecessary_parenthesis
|
||||||
|
(backups.hashCode) +
|
||||||
|
(failedBackups.hashCode);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => 'MaintenanceListBackupsResponseDto[backups=$backups, failedBackups=$failedBackups]';
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final json = <String, dynamic>{};
|
||||||
|
json[r'backups'] = this.backups;
|
||||||
|
json[r'failedBackups'] = this.failedBackups;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new [MaintenanceListBackupsResponseDto] instance and imports its values from
|
||||||
|
/// [value] if it's a [Map], null otherwise.
|
||||||
|
// ignore: prefer_constructors_over_static_methods
|
||||||
|
static MaintenanceListBackupsResponseDto? fromJson(dynamic value) {
|
||||||
|
upgradeDto(value, "MaintenanceListBackupsResponseDto");
|
||||||
|
if (value is Map) {
|
||||||
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
|
return MaintenanceListBackupsResponseDto(
|
||||||
|
backups: json[r'backups'] is Iterable
|
||||||
|
? (json[r'backups'] as Iterable).cast<String>().toList(growable: false)
|
||||||
|
: const [],
|
||||||
|
failedBackups: json[r'failedBackups'] is Iterable
|
||||||
|
? (json[r'failedBackups'] as Iterable).cast<String>().toList(growable: false)
|
||||||
|
: const [],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<MaintenanceListBackupsResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final result = <MaintenanceListBackupsResponseDto>[];
|
||||||
|
if (json is List && json.isNotEmpty) {
|
||||||
|
for (final row in json) {
|
||||||
|
final value = MaintenanceListBackupsResponseDto.fromJson(row);
|
||||||
|
if (value != null) {
|
||||||
|
result.add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toList(growable: growable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Map<String, MaintenanceListBackupsResponseDto> mapFromJson(dynamic json) {
|
||||||
|
final map = <String, MaintenanceListBackupsResponseDto>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
final value = MaintenanceListBackupsResponseDto.fromJson(entry.value);
|
||||||
|
if (value != null) {
|
||||||
|
map[entry.key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
// maps a json object with a list of MaintenanceListBackupsResponseDto-objects as value to a dart map
|
||||||
|
static Map<String, List<MaintenanceListBackupsResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
|
final map = <String, List<MaintenanceListBackupsResponseDto>>{};
|
||||||
|
if (json is Map && json.isNotEmpty) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
json = json.cast<String, dynamic>();
|
||||||
|
for (final entry in json.entries) {
|
||||||
|
map[entry.key] = MaintenanceListBackupsResponseDto.listFromJson(entry.value, growable: growable,);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The list of required keys that must be present in a JSON.
|
||||||
|
static const requiredKeys = <String>{
|
||||||
|
'backups',
|
||||||
|
'failedBackups',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@@ -13,13 +13,13 @@ part of openapi.api;
|
|||||||
class MaintenanceStatusResponseDto {
|
class MaintenanceStatusResponseDto {
|
||||||
/// Returns a new [MaintenanceStatusResponseDto] instance.
|
/// Returns a new [MaintenanceStatusResponseDto] instance.
|
||||||
MaintenanceStatusResponseDto({
|
MaintenanceStatusResponseDto({
|
||||||
this.action,
|
required this.action,
|
||||||
this.error,
|
this.error,
|
||||||
this.progress,
|
this.progress,
|
||||||
this.task,
|
this.task,
|
||||||
});
|
});
|
||||||
|
|
||||||
MaintenanceStatusResponseDtoActionEnum? action;
|
MaintenanceAction action;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Please note: This property should have been non-nullable! Since the specification file
|
/// Please note: This property should have been non-nullable! Since the specification file
|
||||||
@@ -55,7 +55,7 @@ class MaintenanceStatusResponseDto {
|
|||||||
@override
|
@override
|
||||||
int get hashCode =>
|
int get hashCode =>
|
||||||
// ignore: unnecessary_parenthesis
|
// ignore: unnecessary_parenthesis
|
||||||
(action == null ? 0 : action!.hashCode) +
|
(action.hashCode) +
|
||||||
(error == null ? 0 : error!.hashCode) +
|
(error == null ? 0 : error!.hashCode) +
|
||||||
(progress == null ? 0 : progress!.hashCode) +
|
(progress == null ? 0 : progress!.hashCode) +
|
||||||
(task == null ? 0 : task!.hashCode);
|
(task == null ? 0 : task!.hashCode);
|
||||||
@@ -65,11 +65,7 @@ class MaintenanceStatusResponseDto {
|
|||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
if (this.action != null) {
|
|
||||||
json[r'action'] = this.action;
|
json[r'action'] = this.action;
|
||||||
} else {
|
|
||||||
// json[r'action'] = null;
|
|
||||||
}
|
|
||||||
if (this.error != null) {
|
if (this.error != null) {
|
||||||
json[r'error'] = this.error;
|
json[r'error'] = this.error;
|
||||||
} else {
|
} else {
|
||||||
@@ -97,7 +93,7 @@ class MaintenanceStatusResponseDto {
|
|||||||
final json = value.cast<String, dynamic>();
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
return MaintenanceStatusResponseDto(
|
return MaintenanceStatusResponseDto(
|
||||||
action: MaintenanceStatusResponseDtoActionEnum.fromJson(json[r'action']),
|
action: MaintenanceAction.fromJson(json[r'action'])!,
|
||||||
error: mapValueOfType<String>(json, r'error'),
|
error: mapValueOfType<String>(json, r'error'),
|
||||||
progress: num.parse('${json[r'progress']}'),
|
progress: num.parse('${json[r'progress']}'),
|
||||||
task: mapValueOfType<String>(json, r'task'),
|
task: mapValueOfType<String>(json, r'task'),
|
||||||
@@ -148,83 +144,7 @@ class MaintenanceStatusResponseDto {
|
|||||||
|
|
||||||
/// The list of required keys that must be present in a JSON.
|
/// The list of required keys that must be present in a JSON.
|
||||||
static const requiredKeys = <String>{
|
static const requiredKeys = <String>{
|
||||||
|
'action',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class MaintenanceStatusResponseDtoActionEnum {
|
|
||||||
/// Instantiate a new enum with the provided [value].
|
|
||||||
const MaintenanceStatusResponseDtoActionEnum._(this.value);
|
|
||||||
|
|
||||||
/// The underlying value of this enum member.
|
|
||||||
final String value;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() => value;
|
|
||||||
|
|
||||||
String toJson() => value;
|
|
||||||
|
|
||||||
static const start = MaintenanceStatusResponseDtoActionEnum._(r'start');
|
|
||||||
static const end = MaintenanceStatusResponseDtoActionEnum._(r'end');
|
|
||||||
static const restoreDatabase = MaintenanceStatusResponseDtoActionEnum._(r'restore_database');
|
|
||||||
|
|
||||||
/// List of all possible values in this [enum][MaintenanceStatusResponseDtoActionEnum].
|
|
||||||
static const values = <MaintenanceStatusResponseDtoActionEnum>[
|
|
||||||
start,
|
|
||||||
end,
|
|
||||||
restoreDatabase,
|
|
||||||
];
|
|
||||||
|
|
||||||
static MaintenanceStatusResponseDtoActionEnum? fromJson(dynamic value) => MaintenanceStatusResponseDtoActionEnumTypeTransformer().decode(value);
|
|
||||||
|
|
||||||
static List<MaintenanceStatusResponseDtoActionEnum> listFromJson(dynamic json, {bool growable = false,}) {
|
|
||||||
final result = <MaintenanceStatusResponseDtoActionEnum>[];
|
|
||||||
if (json is List && json.isNotEmpty) {
|
|
||||||
for (final row in json) {
|
|
||||||
final value = MaintenanceStatusResponseDtoActionEnum.fromJson(row);
|
|
||||||
if (value != null) {
|
|
||||||
result.add(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result.toList(growable: growable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Transformation class that can [encode] an instance of [MaintenanceStatusResponseDtoActionEnum] to String,
|
|
||||||
/// and [decode] dynamic data back to [MaintenanceStatusResponseDtoActionEnum].
|
|
||||||
class MaintenanceStatusResponseDtoActionEnumTypeTransformer {
|
|
||||||
factory MaintenanceStatusResponseDtoActionEnumTypeTransformer() => _instance ??= const MaintenanceStatusResponseDtoActionEnumTypeTransformer._();
|
|
||||||
|
|
||||||
const MaintenanceStatusResponseDtoActionEnumTypeTransformer._();
|
|
||||||
|
|
||||||
String encode(MaintenanceStatusResponseDtoActionEnum data) => data.value;
|
|
||||||
|
|
||||||
/// Decodes a [dynamic value][data] to a MaintenanceStatusResponseDtoActionEnum.
|
|
||||||
///
|
|
||||||
/// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
|
|
||||||
/// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
|
|
||||||
/// cannot be decoded successfully, then an [UnimplementedError] is thrown.
|
|
||||||
///
|
|
||||||
/// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
|
|
||||||
/// and users are still using an old app with the old code.
|
|
||||||
MaintenanceStatusResponseDtoActionEnum? decode(dynamic data, {bool allowNull = true}) {
|
|
||||||
if (data != null) {
|
|
||||||
switch (data) {
|
|
||||||
case r'start': return MaintenanceStatusResponseDtoActionEnum.start;
|
|
||||||
case r'end': return MaintenanceStatusResponseDtoActionEnum.end;
|
|
||||||
case r'restore_database': return MaintenanceStatusResponseDtoActionEnum.restoreDatabase;
|
|
||||||
default:
|
|
||||||
if (!allowNull) {
|
|
||||||
throw ArgumentError('Unknown enum value to decode: $data');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Singleton [MaintenanceStatusResponseDtoActionEnumTypeTransformer] instance.
|
|
||||||
static MaintenanceStatusResponseDtoActionEnumTypeTransformer? _instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16705,12 +16705,11 @@
|
|||||||
"MaintenanceStatusResponseDto": {
|
"MaintenanceStatusResponseDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"action": {
|
"action": {
|
||||||
"enum": [
|
"allOf": [
|
||||||
"start",
|
{
|
||||||
"end",
|
"$ref": "#/components/schemas/MaintenanceAction"
|
||||||
"restore_database"
|
}
|
||||||
],
|
]
|
||||||
"type": "string"
|
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
|||||||
@@ -44,8 +44,12 @@ export type SetMaintenanceModeDto = {
|
|||||||
action: MaintenanceAction;
|
action: MaintenanceAction;
|
||||||
restoreBackupFilename?: string;
|
restoreBackupFilename?: string;
|
||||||
};
|
};
|
||||||
|
export type MaintenanceListBackupsResponseDto = {
|
||||||
|
backups: string[];
|
||||||
|
failedBackups: string[];
|
||||||
|
};
|
||||||
export type MaintenanceStatusResponseDto = {
|
export type MaintenanceStatusResponseDto = {
|
||||||
action?: Action;
|
action: MaintenanceAction;
|
||||||
error?: string;
|
error?: string;
|
||||||
progress?: number;
|
progress?: number;
|
||||||
task?: string;
|
task?: string;
|
||||||
@@ -521,7 +525,7 @@ export type AssetBulkUploadCheckDto = {
|
|||||||
assets: AssetBulkUploadCheckItem[];
|
assets: AssetBulkUploadCheckItem[];
|
||||||
};
|
};
|
||||||
export type AssetBulkUploadCheckResult = {
|
export type AssetBulkUploadCheckResult = {
|
||||||
action: Action2;
|
action: Action;
|
||||||
assetId?: string;
|
assetId?: string;
|
||||||
id: string;
|
id: string;
|
||||||
isTrashed?: boolean;
|
isTrashed?: boolean;
|
||||||
@@ -1851,6 +1855,28 @@ export function setMaintenanceMode({ setMaintenanceModeDto }: {
|
|||||||
body: setMaintenanceModeDto
|
body: setMaintenanceModeDto
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* List backups
|
||||||
|
*/
|
||||||
|
export function listBackups(opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
|
status: 200;
|
||||||
|
data: MaintenanceListBackupsResponseDto;
|
||||||
|
}>("/admin/maintenance/admin/maintenance/backups/list", {
|
||||||
|
...opts
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Delete backup
|
||||||
|
*/
|
||||||
|
export function deleteBackup({ filename }: {
|
||||||
|
filename: string;
|
||||||
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchText(`/admin/maintenance/admin/maintenance/backups/${encodeURIComponent(filename)}`, {
|
||||||
|
...opts,
|
||||||
|
method: "DELETE"
|
||||||
|
}));
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Get maintenance mode status
|
* Get maintenance mode status
|
||||||
*/
|
*/
|
||||||
@@ -5074,11 +5100,6 @@ export enum MaintenanceAction {
|
|||||||
End = "end",
|
End = "end",
|
||||||
RestoreDatabase = "restore_database"
|
RestoreDatabase = "restore_database"
|
||||||
}
|
}
|
||||||
export enum Action {
|
|
||||||
Start = "start",
|
|
||||||
End = "end",
|
|
||||||
RestoreDatabase = "restore_database"
|
|
||||||
}
|
|
||||||
export enum NotificationLevel {
|
export enum NotificationLevel {
|
||||||
Success = "success",
|
Success = "success",
|
||||||
Error = "error",
|
Error = "error",
|
||||||
@@ -5284,7 +5305,7 @@ export enum AssetMediaStatus {
|
|||||||
Replaced = "replaced",
|
Replaced = "replaced",
|
||||||
Duplicate = "duplicate"
|
Duplicate = "duplicate"
|
||||||
}
|
}
|
||||||
export enum Action2 {
|
export enum Action {
|
||||||
Accept = "accept",
|
Accept = "accept",
|
||||||
Reject = "reject"
|
Reject = "reject"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export class MaintenanceAuthDto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class MaintenanceStatusResponseDto {
|
export class MaintenanceStatusResponseDto {
|
||||||
|
@ValidateEnum({ enum: MaintenanceAction, name: 'MaintenanceAction' })
|
||||||
action!: MaintenanceAction;
|
action!: MaintenanceAction;
|
||||||
|
|
||||||
progress?: number;
|
progress?: number;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export enum AppRoute {
|
|||||||
ADMIN_USERS = '/admin/users',
|
ADMIN_USERS = '/admin/users',
|
||||||
ADMIN_LIBRARY_MANAGEMENT = '/admin/library-management',
|
ADMIN_LIBRARY_MANAGEMENT = '/admin/library-management',
|
||||||
ADMIN_SETTINGS = '/admin/system-settings',
|
ADMIN_SETTINGS = '/admin/system-settings',
|
||||||
|
ADMIN_MAINTENANCE = '/admin/maintenance',
|
||||||
ADMIN_STATS = '/admin/server-status',
|
ADMIN_STATS = '/admin/server-status',
|
||||||
ADMIN_JOBS = '/admin/jobs-status',
|
ADMIN_JOBS = '/admin/jobs-status',
|
||||||
ADMIN_REPAIR = '/admin/repair',
|
ADMIN_REPAIR = '/admin/repair',
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { type MaintenanceAuthDto } from '@immich/sdk';
|
import { type MaintenanceAuthDto, type MaintenanceStatusResponseDto } from '@immich/sdk';
|
||||||
import { writable } from 'svelte/store';
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
export const maintenanceStore = {
|
export const maintenanceStore = {
|
||||||
auth: writable<MaintenanceAuthDto>(),
|
auth: writable<MaintenanceAuthDto>(),
|
||||||
|
status: writable<MaintenanceStatusResponseDto>(),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
import { page } from '$app/state';
|
import { page } from '$app/state';
|
||||||
import { AppRoute } from '$lib/constants';
|
import { AppRoute } from '$lib/constants';
|
||||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||||
|
import { maintenanceStore } from '$lib/stores/maintenance.store';
|
||||||
import { notificationManager } from '$lib/stores/notification-manager.svelte';
|
import { notificationManager } from '$lib/stores/notification-manager.svelte';
|
||||||
import { createEventEmitter } from '$lib/utils/eventemitter';
|
import { createEventEmitter } from '$lib/utils/eventemitter';
|
||||||
import { type AssetResponseDto, type NotificationDto, type ServerVersionResponseDto } from '@immich/sdk';
|
import {
|
||||||
|
MaintenanceAction,
|
||||||
|
type AssetResponseDto,
|
||||||
|
type MaintenanceStatusResponseDto,
|
||||||
|
type NotificationDto,
|
||||||
|
type ServerVersionResponseDto,
|
||||||
|
} from '@immich/sdk';
|
||||||
import { io, type Socket } from 'socket.io-client';
|
import { io, type Socket } from 'socket.io-client';
|
||||||
import { get, writable } from 'svelte/store';
|
import { get, writable } from 'svelte/store';
|
||||||
import { user } from './user.store';
|
import { user } from './user.store';
|
||||||
@@ -37,6 +44,8 @@ export interface Events {
|
|||||||
on_notification: (notification: NotificationDto) => void;
|
on_notification: (notification: NotificationDto) => void;
|
||||||
|
|
||||||
AppRestartV1: (event: AppRestartEvent) => void;
|
AppRestartV1: (event: AppRestartEvent) => void;
|
||||||
|
|
||||||
|
MaintenanceStatusV1: (event: MaintenanceStatusResponseDto) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const websocket: Socket<Events> = io({
|
const websocket: Socket<Events> = io({
|
||||||
@@ -61,6 +70,15 @@ websocket
|
|||||||
.on('disconnect', () => websocketStore.connected.set(false))
|
.on('disconnect', () => websocketStore.connected.set(false))
|
||||||
.on('on_server_version', (serverVersion) => websocketStore.serverVersion.set(serverVersion))
|
.on('on_server_version', (serverVersion) => websocketStore.serverVersion.set(serverVersion))
|
||||||
.on('AppRestartV1', (mode) => websocketStore.serverRestarting.set(mode))
|
.on('AppRestartV1', (mode) => websocketStore.serverRestarting.set(mode))
|
||||||
|
.on('MaintenanceStatusV1', (status) => {
|
||||||
|
maintenanceStore.status.set(status);
|
||||||
|
|
||||||
|
if (status.action === MaintenanceAction.End) {
|
||||||
|
websocketStore.serverRestarting.set({
|
||||||
|
isMaintenanceMode: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
.on('on_new_release', (releaseVersion) => websocketStore.release.set(releaseVersion))
|
.on('on_new_release', (releaseVersion) => websocketStore.release.set(releaseVersion))
|
||||||
.on('on_session_delete', () => authManager.logout())
|
.on('on_session_delete', () => authManager.logout())
|
||||||
.on('on_notification', () => notificationManager.refresh())
|
.on('on_notification', () => notificationManager.refresh())
|
||||||
@@ -68,7 +86,7 @@ websocket
|
|||||||
|
|
||||||
export const openWebsocketConnection = () => {
|
export const openWebsocketConnection = () => {
|
||||||
try {
|
try {
|
||||||
if (get(user) || page.url.pathname.startsWith(AppRoute.MAINTENANCE)) {
|
if (get(user) || get(websocketStore.serverRestarting) || page.url.pathname.startsWith(AppRoute.MAINTENANCE)) {
|
||||||
websocket.connect();
|
websocket.connect();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { AppRoute } from '$lib/constants';
|
import { AppRoute } from '$lib/constants';
|
||||||
import { maintenanceStore } from '$lib/stores/maintenance.store';
|
import { maintenanceStore } from '$lib/stores/maintenance.store';
|
||||||
import { maintenanceLogin } from '@immich/sdk';
|
import { websocketStore } from '$lib/stores/websocket';
|
||||||
|
import { MaintenanceAction, maintenanceLogin, maintenanceStatus } from '@immich/sdk';
|
||||||
|
|
||||||
export function maintenanceCreateUrl(url: URL) {
|
export function maintenanceCreateUrl(url: URL) {
|
||||||
const target = new URL(AppRoute.MAINTENANCE, url.origin);
|
const target = new URL(AppRoute.MAINTENANCE, url.origin);
|
||||||
@@ -31,3 +32,22 @@ export const loadMaintenanceAuth = async () => {
|
|||||||
// silently fail
|
// silently fail
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const loadMaintenanceStatus = async () => {
|
||||||
|
try {
|
||||||
|
const status = await maintenanceStatus();
|
||||||
|
maintenanceStore.status.set(status);
|
||||||
|
|
||||||
|
if (status.action === MaintenanceAction.End) {
|
||||||
|
websocketStore.serverRestarting.set({
|
||||||
|
isMaintenanceMode: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
const status = (error as { status: number })?.status;
|
||||||
|
if (status && status >= 500 && status < 600) {
|
||||||
|
await new Promise((r) => setTimeout(r, 1e3));
|
||||||
|
await loadMaintenanceStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { loadMaintenanceAuth } from '$lib/utils/maintenance';
|
import { loadMaintenanceAuth, loadMaintenanceStatus } from '$lib/utils/maintenance';
|
||||||
import type { PageLoad } from '../admin/$types';
|
import type { PageLoad } from '../admin/$types';
|
||||||
|
|
||||||
export const load = (async () => {
|
export const load = (async () => {
|
||||||
await loadMaintenanceAuth();
|
await Promise.allSettled([loadMaintenanceAuth(), loadMaintenanceStatus()]);
|
||||||
}) satisfies PageLoad;
|
}) satisfies PageLoad;
|
||||||
|
|||||||
Reference in New Issue
Block a user