feat(backups): Show the snapshot creation reason

pull/331/head
Inex Code 2023-09-09 10:22:43 +03:00
parent ef91ffaf2b
commit aac4b2773b
7 changed files with 293 additions and 2 deletions

View File

@ -220,7 +220,14 @@
"snapshot_modal_inplace_option_title": "Replace in place", "snapshot_modal_inplace_option_title": "Replace in place",
"snapshot_modal_inplace_option_description": "Less free space needed, but more risk. Replaces current data with the snapshot data during the download.", "snapshot_modal_inplace_option_description": "Less free space needed, but more risk. Replaces current data with the snapshot data during the download.",
"snapshot_modal_service_not_found": "This is a snapshot of a service you don't have on your server anymore. Usually this shouldn't happen, and we cannot do the automatic restore. You can still download the snapshot and restore it manually. Contact SelfPrivacy support if you need help.", "snapshot_modal_service_not_found": "This is a snapshot of a service you don't have on your server anymore. Usually this shouldn't happen, and we cannot do the automatic restore. You can still download the snapshot and restore it manually. Contact SelfPrivacy support if you need help.",
"restore_started": "Restore started, check the jobs list for the current status" "restore_started": "Restore started, check the jobs list for the current status",
"snapshot_reason_title": "Creation reason",
"snapshot_reasons": {
"auto": "Created automatically",
"explicit": "Created by your explicit request",
"pre_restore": "Created as a precaution before risky restore",
"unknown": "Unknown"
}
}, },
"storage": { "storage": {
"card_title": "Server Storage", "card_title": "Server Storage",

View File

@ -20,6 +20,7 @@ query AllBackupSnapshots {
displayName displayName
id id
} }
reason
} }
} }
} }
@ -98,4 +99,4 @@ mutation ForgetSnapshot($snapshotId: String!) {
...basicMutationReturnFields ...basicMutationReturnFields
} }
} }
} }

View File

@ -1486,6 +1486,13 @@ const documentNodeQueryAllBackupSnapshots = DocumentNode(definitions: [
), ),
]), ]),
), ),
FieldNode(
name: NameNode(value: 'reason'),
alias: null,
arguments: [],
directives: [],
selectionSet: null,
),
FieldNode( FieldNode(
name: NameNode(value: '__typename'), name: NameNode(value: '__typename'),
alias: null, alias: null,
@ -1801,6 +1808,7 @@ class Query$AllBackupSnapshots$backup$allSnapshots {
required this.id, required this.id,
required this.createdAt, required this.createdAt,
required this.service, required this.service,
required this.reason,
this.$__typename = 'SnapshotInfo', this.$__typename = 'SnapshotInfo',
}); });
@ -1809,12 +1817,14 @@ class Query$AllBackupSnapshots$backup$allSnapshots {
final l$id = json['id']; final l$id = json['id'];
final l$createdAt = json['createdAt']; final l$createdAt = json['createdAt'];
final l$service = json['service']; final l$service = json['service'];
final l$reason = json['reason'];
final l$$__typename = json['__typename']; final l$$__typename = json['__typename'];
return Query$AllBackupSnapshots$backup$allSnapshots( return Query$AllBackupSnapshots$backup$allSnapshots(
id: (l$id as String), id: (l$id as String),
createdAt: dateTimeFromJson(l$createdAt), createdAt: dateTimeFromJson(l$createdAt),
service: Query$AllBackupSnapshots$backup$allSnapshots$service.fromJson( service: Query$AllBackupSnapshots$backup$allSnapshots$service.fromJson(
(l$service as Map<String, dynamic>)), (l$service as Map<String, dynamic>)),
reason: fromJson$Enum$BackupReason((l$reason as String)),
$__typename: (l$$__typename as String), $__typename: (l$$__typename as String),
); );
} }
@ -1825,6 +1835,8 @@ class Query$AllBackupSnapshots$backup$allSnapshots {
final Query$AllBackupSnapshots$backup$allSnapshots$service service; final Query$AllBackupSnapshots$backup$allSnapshots$service service;
final Enum$BackupReason reason;
final String $__typename; final String $__typename;
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@ -1835,6 +1847,8 @@ class Query$AllBackupSnapshots$backup$allSnapshots {
_resultData['createdAt'] = dateTimeToJson(l$createdAt); _resultData['createdAt'] = dateTimeToJson(l$createdAt);
final l$service = service; final l$service = service;
_resultData['service'] = l$service.toJson(); _resultData['service'] = l$service.toJson();
final l$reason = reason;
_resultData['reason'] = toJson$Enum$BackupReason(l$reason);
final l$$__typename = $__typename; final l$$__typename = $__typename;
_resultData['__typename'] = l$$__typename; _resultData['__typename'] = l$$__typename;
return _resultData; return _resultData;
@ -1845,11 +1859,13 @@ class Query$AllBackupSnapshots$backup$allSnapshots {
final l$id = id; final l$id = id;
final l$createdAt = createdAt; final l$createdAt = createdAt;
final l$service = service; final l$service = service;
final l$reason = reason;
final l$$__typename = $__typename; final l$$__typename = $__typename;
return Object.hashAll([ return Object.hashAll([
l$id, l$id,
l$createdAt, l$createdAt,
l$service, l$service,
l$reason,
l$$__typename, l$$__typename,
]); ]);
} }
@ -1878,6 +1894,11 @@ class Query$AllBackupSnapshots$backup$allSnapshots {
if (l$service != lOther$service) { if (l$service != lOther$service) {
return false; return false;
} }
final l$reason = reason;
final lOther$reason = other.reason;
if (l$reason != lOther$reason) {
return false;
}
final l$$__typename = $__typename; final l$$__typename = $__typename;
final lOther$$__typename = other.$__typename; final lOther$$__typename = other.$__typename;
if (l$$__typename != lOther$$__typename) { if (l$$__typename != lOther$$__typename) {
@ -1910,6 +1931,7 @@ abstract class CopyWith$Query$AllBackupSnapshots$backup$allSnapshots<TRes> {
String? id, String? id,
DateTime? createdAt, DateTime? createdAt,
Query$AllBackupSnapshots$backup$allSnapshots$service? service, Query$AllBackupSnapshots$backup$allSnapshots$service? service,
Enum$BackupReason? reason,
String? $__typename, String? $__typename,
}); });
CopyWith$Query$AllBackupSnapshots$backup$allSnapshots$service<TRes> CopyWith$Query$AllBackupSnapshots$backup$allSnapshots$service<TRes>
@ -1933,6 +1955,7 @@ class _CopyWithImpl$Query$AllBackupSnapshots$backup$allSnapshots<TRes>
Object? id = _undefined, Object? id = _undefined,
Object? createdAt = _undefined, Object? createdAt = _undefined,
Object? service = _undefined, Object? service = _undefined,
Object? reason = _undefined,
Object? $__typename = _undefined, Object? $__typename = _undefined,
}) => }) =>
_then(Query$AllBackupSnapshots$backup$allSnapshots( _then(Query$AllBackupSnapshots$backup$allSnapshots(
@ -1943,6 +1966,9 @@ class _CopyWithImpl$Query$AllBackupSnapshots$backup$allSnapshots<TRes>
service: service == _undefined || service == null service: service == _undefined || service == null
? _instance.service ? _instance.service
: (service as Query$AllBackupSnapshots$backup$allSnapshots$service), : (service as Query$AllBackupSnapshots$backup$allSnapshots$service),
reason: reason == _undefined || reason == null
? _instance.reason
: (reason as Enum$BackupReason),
$__typename: $__typename == _undefined || $__typename == null $__typename: $__typename == _undefined || $__typename == null
? _instance.$__typename ? _instance.$__typename
: ($__typename as String), : ($__typename as String),
@ -1965,6 +1991,7 @@ class _CopyWithStubImpl$Query$AllBackupSnapshots$backup$allSnapshots<TRes>
String? id, String? id,
DateTime? createdAt, DateTime? createdAt,
Query$AllBackupSnapshots$backup$allSnapshots$service? service, Query$AllBackupSnapshots$backup$allSnapshots$service? service,
Enum$BackupReason? reason,
String? $__typename, String? $__typename,
}) => }) =>
_res; _res;

View File

@ -75,6 +75,22 @@ type AutoUpgradeSettingsMutationReturn implements MutationReturnInterface {
allowReboot: Boolean! allowReboot: Boolean!
} }
type AutobackupQuotas {
last: Int!
daily: Int!
weekly: Int!
monthly: Int!
yearly: Int!
}
input AutobackupQuotasInput {
last: Int!
daily: Int!
weekly: Int!
monthly: Int!
yearly: Int!
}
type Backup { type Backup {
configuration: BackupConfiguration! configuration: BackupConfiguration!
allSnapshots: [SnapshotInfo!]! allSnapshots: [SnapshotInfo!]!
@ -85,6 +101,7 @@ type BackupConfiguration {
encryptionKey: String! encryptionKey: String!
isInitialized: Boolean! isInitialized: Boolean!
autobackupPeriod: Int autobackupPeriod: Int
autobackupQuotas: AutobackupQuotas!
locationName: String locationName: String
locationId: String locationId: String
} }
@ -93,6 +110,7 @@ type BackupMutations {
initializeRepository(repository: InitializeRepositoryInput!): GenericBackupConfigReturn! initializeRepository(repository: InitializeRepositoryInput!): GenericBackupConfigReturn!
removeRepository: GenericBackupConfigReturn! removeRepository: GenericBackupConfigReturn!
setAutobackupPeriod(period: Int = null): GenericBackupConfigReturn! setAutobackupPeriod(period: Int = null): GenericBackupConfigReturn!
setAutobackupQuotas(quotas: AutobackupQuotasInput!): GenericBackupConfigReturn!
startBackup(serviceId: String!): GenericJobMutationReturn! startBackup(serviceId: String!): GenericJobMutationReturn!
restoreBackup(snapshotId: String!, strategy: RestoreStrategy! = DOWNLOAD_VERIFY_OVERWRITE): GenericJobMutationReturn! restoreBackup(snapshotId: String!, strategy: RestoreStrategy! = DOWNLOAD_VERIFY_OVERWRITE): GenericJobMutationReturn!
forgetSnapshot(snapshotId: String!): GenericMutationReturn! forgetSnapshot(snapshotId: String!): GenericMutationReturn!
@ -106,6 +124,12 @@ enum BackupProvider {
FILE FILE
} }
enum BackupReason {
EXPLICIT
AUTO
PRE_RESTORE
}
"""Date with time (isoformat)""" """Date with time (isoformat)"""
scalar DateTime scalar DateTime
@ -326,6 +350,7 @@ type SnapshotInfo {
id: String! id: String!
service: Service! service: Service!
createdAt: DateTime! createdAt: DateTime!
reason: BackupReason!
} }
input SshMutationInput { input SshMutationInput {

View File

@ -141,6 +141,185 @@ class _CopyWithStubImpl$Input$AutoUpgradeSettingsInput<TRes>
_res; _res;
} }
class Input$AutobackupQuotasInput {
factory Input$AutobackupQuotasInput({
required int last,
required int daily,
required int weekly,
required int monthly,
required int yearly,
}) =>
Input$AutobackupQuotasInput._({
r'last': last,
r'daily': daily,
r'weekly': weekly,
r'monthly': monthly,
r'yearly': yearly,
});
Input$AutobackupQuotasInput._(this._$data);
factory Input$AutobackupQuotasInput.fromJson(Map<String, dynamic> data) {
final result$data = <String, dynamic>{};
final l$last = data['last'];
result$data['last'] = (l$last as int);
final l$daily = data['daily'];
result$data['daily'] = (l$daily as int);
final l$weekly = data['weekly'];
result$data['weekly'] = (l$weekly as int);
final l$monthly = data['monthly'];
result$data['monthly'] = (l$monthly as int);
final l$yearly = data['yearly'];
result$data['yearly'] = (l$yearly as int);
return Input$AutobackupQuotasInput._(result$data);
}
Map<String, dynamic> _$data;
int get last => (_$data['last'] as int);
int get daily => (_$data['daily'] as int);
int get weekly => (_$data['weekly'] as int);
int get monthly => (_$data['monthly'] as int);
int get yearly => (_$data['yearly'] as int);
Map<String, dynamic> toJson() {
final result$data = <String, dynamic>{};
final l$last = last;
result$data['last'] = l$last;
final l$daily = daily;
result$data['daily'] = l$daily;
final l$weekly = weekly;
result$data['weekly'] = l$weekly;
final l$monthly = monthly;
result$data['monthly'] = l$monthly;
final l$yearly = yearly;
result$data['yearly'] = l$yearly;
return result$data;
}
CopyWith$Input$AutobackupQuotasInput<Input$AutobackupQuotasInput>
get copyWith => CopyWith$Input$AutobackupQuotasInput(
this,
(i) => i,
);
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
if (!(other is Input$AutobackupQuotasInput) ||
runtimeType != other.runtimeType) {
return false;
}
final l$last = last;
final lOther$last = other.last;
if (l$last != lOther$last) {
return false;
}
final l$daily = daily;
final lOther$daily = other.daily;
if (l$daily != lOther$daily) {
return false;
}
final l$weekly = weekly;
final lOther$weekly = other.weekly;
if (l$weekly != lOther$weekly) {
return false;
}
final l$monthly = monthly;
final lOther$monthly = other.monthly;
if (l$monthly != lOther$monthly) {
return false;
}
final l$yearly = yearly;
final lOther$yearly = other.yearly;
if (l$yearly != lOther$yearly) {
return false;
}
return true;
}
@override
int get hashCode {
final l$last = last;
final l$daily = daily;
final l$weekly = weekly;
final l$monthly = monthly;
final l$yearly = yearly;
return Object.hashAll([
l$last,
l$daily,
l$weekly,
l$monthly,
l$yearly,
]);
}
}
abstract class CopyWith$Input$AutobackupQuotasInput<TRes> {
factory CopyWith$Input$AutobackupQuotasInput(
Input$AutobackupQuotasInput instance,
TRes Function(Input$AutobackupQuotasInput) then,
) = _CopyWithImpl$Input$AutobackupQuotasInput;
factory CopyWith$Input$AutobackupQuotasInput.stub(TRes res) =
_CopyWithStubImpl$Input$AutobackupQuotasInput;
TRes call({
int? last,
int? daily,
int? weekly,
int? monthly,
int? yearly,
});
}
class _CopyWithImpl$Input$AutobackupQuotasInput<TRes>
implements CopyWith$Input$AutobackupQuotasInput<TRes> {
_CopyWithImpl$Input$AutobackupQuotasInput(
this._instance,
this._then,
);
final Input$AutobackupQuotasInput _instance;
final TRes Function(Input$AutobackupQuotasInput) _then;
static const _undefined = <dynamic, dynamic>{};
TRes call({
Object? last = _undefined,
Object? daily = _undefined,
Object? weekly = _undefined,
Object? monthly = _undefined,
Object? yearly = _undefined,
}) =>
_then(Input$AutobackupQuotasInput._({
..._instance._$data,
if (last != _undefined && last != null) 'last': (last as int),
if (daily != _undefined && daily != null) 'daily': (daily as int),
if (weekly != _undefined && weekly != null) 'weekly': (weekly as int),
if (monthly != _undefined && monthly != null)
'monthly': (monthly as int),
if (yearly != _undefined && yearly != null) 'yearly': (yearly as int),
}));
}
class _CopyWithStubImpl$Input$AutobackupQuotasInput<TRes>
implements CopyWith$Input$AutobackupQuotasInput<TRes> {
_CopyWithStubImpl$Input$AutobackupQuotasInput(this._res);
TRes _res;
call({
int? last,
int? daily,
int? weekly,
int? monthly,
int? yearly,
}) =>
_res;
}
class Input$InitializeRepositoryInput { class Input$InitializeRepositoryInput {
factory Input$InitializeRepositoryInput({ factory Input$InitializeRepositoryInput({
required Enum$BackupProvider provider, required Enum$BackupProvider provider,
@ -1310,6 +1489,34 @@ Enum$BackupProvider fromJson$Enum$BackupProvider(String value) {
} }
} }
enum Enum$BackupReason { EXPLICIT, AUTO, PRE_RESTORE, $unknown }
String toJson$Enum$BackupReason(Enum$BackupReason e) {
switch (e) {
case Enum$BackupReason.EXPLICIT:
return r'EXPLICIT';
case Enum$BackupReason.AUTO:
return r'AUTO';
case Enum$BackupReason.PRE_RESTORE:
return r'PRE_RESTORE';
case Enum$BackupReason.$unknown:
return r'$unknown';
}
}
Enum$BackupReason fromJson$Enum$BackupReason(String value) {
switch (value) {
case r'EXPLICIT':
return Enum$BackupReason.EXPLICIT;
case r'AUTO':
return Enum$BackupReason.AUTO;
case r'PRE_RESTORE':
return Enum$BackupReason.PRE_RESTORE;
default:
return Enum$BackupReason.$unknown;
}
}
enum Enum$DnsProvider { CLOUDFLARE, DIGITALOCEAN, DESEC, $unknown } enum Enum$DnsProvider { CLOUDFLARE, DIGITALOCEAN, DESEC, $unknown }
String toJson$Enum$DnsProvider(Enum$DnsProvider e) { String toJson$Enum$DnsProvider(Enum$DnsProvider e) {

View File

@ -11,6 +11,7 @@ class Backup {
time: snapshot.createdAt, time: snapshot.createdAt,
serviceId: snapshot.service.id, serviceId: snapshot.service.id,
fallbackServiceName: snapshot.service.displayName, fallbackServiceName: snapshot.service.displayName,
reason: snapshot.reason,
); );
Backup({ Backup({
@ -18,6 +19,7 @@ class Backup {
required this.id, required this.id,
required this.serviceId, required this.serviceId,
required this.fallbackServiceName, required this.fallbackServiceName,
required this.reason,
}); });
// Time of the backup // Time of the backup
@ -26,6 +28,16 @@ class Backup {
final String id; final String id;
final String serviceId; final String serviceId;
final String fallbackServiceName; final String fallbackServiceName;
final Enum$BackupReason reason;
}
extension BackupReasonExtension on Enum$BackupReason {
String get displayName => switch (this) {
Enum$BackupReason.AUTO => 'backup.snapshot_reasons.auto',
Enum$BackupReason.EXPLICIT => 'backup.snapshot_reasons.explicit',
Enum$BackupReason.PRE_RESTORE => 'backup.snapshot_reasons.pre_restore',
Enum$BackupReason.$unknown => 'backup.snapshot_reasons.unknown',
};
} }
class BackupConfiguration { class BackupConfiguration {

View File

@ -99,6 +99,18 @@ class _SnapshotModalState extends State<SnapshotModal> {
), ),
), ),
SnapshotIdListTile(snapshotId: widget.snapshot.id), SnapshotIdListTile(snapshotId: widget.snapshot.id),
ListTile(
leading: Icon(
Icons.info_outline,
color: Theme.of(context).colorScheme.onSurface,
),
title: Text(
'backup.snapshot_reason_title'.tr(),
),
subtitle: Text(
widget.snapshot.reason.displayName.tr(),
),
),
if (service != null) if (service != null)
Column( Column(
children: [ children: [