Pre-release testing bug fixes

Inex Code 2022-09-19 01:11:26 +03:00
parent 900e07f364
commit 2a4c691f1e
8 changed files with 77 additions and 31 deletions

View File

@ -202,7 +202,7 @@
"extend_volume_button": "Extend volume", "extend_volume_button": "Extend volume",
"extending_volume_title": "Extending volume", "extending_volume_title": "Extending volume",
"extending_volume_description": "Resizing volume will allow you to store more data on your server without extending the server itself. Volume can only be extended: shrinking is not possible.", "extending_volume_description": "Resizing volume will allow you to store more data on your server without extending the server itself. Volume can only be extended: shrinking is not possible.",
"extending_volume_price_info": "Price includes VAT and is estimated from pricing data provided by Hetzner.", "extending_volume_price_info": "Price includes VAT and is estimated from pricing data provided by Hetzner. Server will be rebooted after resizing.",
"extending_volume_error": "Couldn't initialize volume extending.", "extending_volume_error": "Couldn't initialize volume extending.",
"size": "Size", "size": "Size",
"euro": "Euro", "euro": "Euro",
@ -490,7 +490,8 @@
"rebootServer": "Reboot server", "rebootServer": "Reboot server",
"create_ssh_key": "Create SSH key for {}", "create_ssh_key": "Create SSH key for {}",
"delete_ssh_key": "Delete SSH key for {}", "delete_ssh_key": "Delete SSH key for {}",
"server_jobs": "Jobs on the server" "server_jobs": "Jobs on the server",
"resetUserPassword": "Reset password of user"
}, },
"validations": { "validations": {
"required": "Required.", "required": "Required.",

View File

@ -204,7 +204,7 @@
"extend_volume_button": "Расширить хранилище", "extend_volume_button": "Расширить хранилище",
"extending_volume_title": "Расширение хранилища", "extending_volume_title": "Расширение хранилища",
"extending_volume_description": "Изменение размера хранилища позволит вам держать больше данных на вашем сервере без расширения самого сервера. Объем можно только увеличить: уменьшить нельзя.", "extending_volume_description": "Изменение размера хранилища позволит вам держать больше данных на вашем сервере без расширения самого сервера. Объем можно только увеличить: уменьшить нельзя.",
"extending_volume_price_info": "Цена включает НДС и рассчитана на основе данных о ценах, предоставленных Hetzner.", "extending_volume_price_info": "Цена включает НДС и рассчитана на основе данных о ценах, предоставленных Hetzner. Сервер будет перезагружен во время процесса.",
"extending_volume_error": "Не удалось начать расширение хранилища.", "extending_volume_error": "Не удалось начать расширение хранилища.",
"size": "Размер", "size": "Размер",
"euro": "Евро", "euro": "Евро",

View File

@ -17,6 +17,8 @@ class ApiProviderVolumeCubit
VolumeProviderApiFactory? providerApi; VolumeProviderApiFactory? providerApi;
final ServerApi serverApi = ServerApi();
@override @override
Future<void> load() async { Future<void> load() async {
if (serverInstallationCubit.state is ServerInstallationFinished) { if (serverInstallationCubit.state is ServerInstallationFinished) {
@ -34,23 +36,23 @@ class ApiProviderVolumeCubit
providerApi!.getVolumeProvider().getPricePerGb(); providerApi!.getVolumeProvider().getPricePerGb();
Future<void> refresh() async { Future<void> refresh() async {
emit(const ApiProviderVolumeState([], LoadingStatus.refreshing)); emit(const ApiProviderVolumeState([], LoadingStatus.refreshing, false));
_refetch(); _refetch();
} }
Future<void> _refetch() async { Future<void> _refetch() async {
if (providerApi == null) { if (providerApi == null) {
return emit(const ApiProviderVolumeState([], LoadingStatus.error)); return emit(const ApiProviderVolumeState([], LoadingStatus.error, false));
} }
final List<ServerVolume> volumes = final List<ServerVolume> volumes =
await providerApi!.getVolumeProvider().getVolumes(); await providerApi!.getVolumeProvider().getVolumes();
if (volumes.isEmpty) { if (volumes.isEmpty) {
return emit(const ApiProviderVolumeState([], LoadingStatus.error)); return emit(const ApiProviderVolumeState([], LoadingStatus.error, false));
} }
emit(ApiProviderVolumeState(volumes, LoadingStatus.success)); emit(ApiProviderVolumeState(volumes, LoadingStatus.success, false));
} }
Future<void> attachVolume(final DiskVolume volume) async { Future<void> attachVolume(final DiskVolume volume) async {
@ -71,7 +73,12 @@ class ApiProviderVolumeCubit
Future<bool> resizeVolume( Future<bool> resizeVolume(
final DiskVolume volume, final DiskVolume volume,
final int newSizeGb, final int newSizeGb,
final Function() callback,
) async { ) async {
getIt<NavigationService>().showSnackBar(
'Starting resize',
);
emit(state.copyWith(isResizing: true));
final bool resized = await providerApi!.getVolumeProvider().resizeVolume( final bool resized = await providerApi!.getVolumeProvider().resizeVolume(
volume.providerVolume!.id, volume.providerVolume!.id,
newSizeGb, newSizeGb,
@ -81,13 +88,29 @@ class ApiProviderVolumeCubit
getIt<NavigationService>().showSnackBar( getIt<NavigationService>().showSnackBar(
'providers.storage.extending_volume_error'.tr(), 'providers.storage.extending_volume_error'.tr(),
); );
emit(state.copyWith(isResizing: false));
return false; return false;
} }
getIt<NavigationService>().showSnackBar(
'Hetzner resized, waiting 10 seconds',
);
await Future.delayed(const Duration(seconds: 10)); await Future.delayed(const Duration(seconds: 10));
await ServerApi().resizeVolume(volume.name); await ServerApi().resizeVolume(volume.name);
refresh(); getIt<NavigationService>().showSnackBar(
'Server api resized, waiting 20 seconds',
);
await Future.delayed(const Duration(seconds: 20));
getIt<NavigationService>().showSnackBar(
'Restarting server',
);
await refresh();
emit(state.copyWith(isResizing: false));
await callback();
await serverApi.reboot();
return true; return true;
} }

View File

@ -1,22 +1,25 @@
part of 'provider_volume_cubit.dart'; part of 'provider_volume_cubit.dart';
class ApiProviderVolumeState extends ServerInstallationDependendState { class ApiProviderVolumeState extends ServerInstallationDependendState {
const ApiProviderVolumeState(this._volumes, this.status); const ApiProviderVolumeState(this._volumes, this.status, this.isResizing);
const ApiProviderVolumeState.initial() const ApiProviderVolumeState.initial()
: this(const [], LoadingStatus.uninitialized); : this(const [], LoadingStatus.uninitialized, false);
final List<ServerVolume> _volumes; final List<ServerVolume> _volumes;
final LoadingStatus status; final LoadingStatus status;
final bool isResizing;
List<ServerVolume> get volumes => _volumes; List<ServerVolume> get volumes => _volumes;
ApiProviderVolumeState copyWith({ ApiProviderVolumeState copyWith({
final List<ServerVolume>? volumes, final List<ServerVolume>? volumes,
final LoadingStatus? status, final LoadingStatus? status,
final bool? isResizing,
}) => }) =>
ApiProviderVolumeState( ApiProviderVolumeState(
volumes ?? _volumes, volumes ?? _volumes,
status ?? this.status, status ?? this.status,
isResizing ?? this.isResizing,
); );
@override @override

View File

@ -24,7 +24,7 @@ class ApiServerVolumeCubit
@override @override
Future<void> load() async { Future<void> load() async {
if (serverInstallationCubit.state is ServerInstallationFinished) { if (serverInstallationCubit.state is ServerInstallationFinished) {
_refetch(); reload();
} }
} }
@ -43,7 +43,7 @@ class ApiServerVolumeCubit
return; return;
} }
Future<void> _refetch() async { Future<void> reload() async {
final volumes = await serverApi.getServerDiskVolumes(); final volumes = await serverApi.getServerDiskVolumes();
final usesBinds = await serverApi.isUsingBinds(); final usesBinds = await serverApi.isUsingBinds();
var status = LoadingStatus.error; var status = LoadingStatus.error;

View File

@ -46,21 +46,23 @@ class ServerJobCard extends StatelessWidget {
children: [ children: [
Row( Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Column( Flexible(
crossAxisAlignment: CrossAxisAlignment.start, child: Column(
children: [ crossAxisAlignment: CrossAxisAlignment.start,
Text( children: [
serverJob.name, Text(
style: Theme.of(context).textTheme.bodyMedium, serverJob.name,
), style: Theme.of(context).textTheme.bodyMedium,
Text( ),
serverJob.description, Text(
style: Theme.of(context).textTheme.bodySmall, serverJob.description,
), style: Theme.of(context).textTheme.bodySmall,
], ),
],
),
), ),
const Spacer(),
Icon( Icon(
icon, icon,
color: color, color: color,

View File

@ -3,13 +3,16 @@ import 'package:flutter/material.dart';
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
import 'package:selfprivacy/logic/models/disk_size.dart'; import 'package:selfprivacy/logic/models/disk_size.dart';
import 'package:selfprivacy/logic/models/service.dart'; import 'package:selfprivacy/logic/models/service.dart';
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
import 'package:selfprivacy/ui/components/brand_button/filled_button.dart'; import 'package:selfprivacy/ui/components/brand_button/filled_button.dart';
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
import 'package:selfprivacy/ui/components/info_box/info_box.dart'; import 'package:selfprivacy/ui/components/info_box/info_box.dart';
import 'package:selfprivacy/logic/models/disk_status.dart'; import 'package:selfprivacy/logic/models/disk_status.dart';
import 'package:selfprivacy/ui/components/jobs_content/jobs_content.dart';
import 'package:selfprivacy/ui/components/storage_list_items/server_storage_list_item.dart'; import 'package:selfprivacy/ui/components/storage_list_items/server_storage_list_item.dart';
import 'package:selfprivacy/ui/components/storage_list_items/service_migration_list_item.dart'; import 'package:selfprivacy/ui/components/storage_list_items/service_migration_list_item.dart';
import 'package:selfprivacy/ui/pages/server_storage/binds_migration/migration_process_page.dart'; import 'package:selfprivacy/ui/helpers/modals.dart';
import 'package:selfprivacy/ui/pages/root_route.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart';
class DataToBindsMigrationPage extends StatefulWidget { class DataToBindsMigrationPage extends StatefulWidget {
@ -162,8 +165,17 @@ class _DataToBindsMigrationPageState extends State<DataToBindsMigrationPage> {
title: 'providers.storage.start_migration_button'.tr(), title: 'providers.storage.start_migration_button'.tr(),
onPressed: () { onPressed: () {
context.read<ServerJobsCubit>().migrateToBinds(serviceToDisk); context.read<ServerJobsCubit>().migrateToBinds(serviceToDisk);
Navigator.of(context).push( Navigator.of(context).pushAndRemoveUntil(
materialRoute(const MigrationProcessPage()), materialRoute(const RootPage()),
(final predicate) => false,
);
showBrandBottomSheet(
context: context,
builder: (final BuildContext context) =>
const BrandBottomSheet(
isExpended: true,
child: JobsContent(),
),
); );
}, },
), ),

View File

@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart'; import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart'; import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart';
import 'package:selfprivacy/logic/models/disk_size.dart'; import 'package:selfprivacy/logic/models/disk_size.dart';
import 'package:selfprivacy/ui/components/brand_button/filled_button.dart'; import 'package:selfprivacy/ui/components/brand_button/filled_button.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart'; import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
@ -26,7 +27,7 @@ class ExtendingVolumePage extends StatefulWidget {
class _ExtendingVolumePageState extends State<ExtendingVolumePage> { class _ExtendingVolumePageState extends State<ExtendingVolumePage> {
@override @override
void initState() { void initState() {
minSize = widget.diskVolumeToResize.sizeTotal + DiskSize.fromGibibyte(2); minSize = widget.diskVolumeToResize.sizeTotal + DiskSize.fromGibibyte(3);
_currentSliderGbValue = minSize.gibibyte; _currentSliderGbValue = minSize.gibibyte;
super.initState(); super.initState();
} }
@ -73,11 +74,14 @@ class _ExtendingVolumePageState extends State<ExtendingVolumePage> {
(_euroPerGb * double.parse(_sizeController.text)) (_euroPerGb * double.parse(_sizeController.text))
.toStringAsFixed(2); .toStringAsFixed(2);
minSize = minSize =
widget.diskVolumeToResize.sizeTotal + DiskSize.fromGibibyte(2); widget.diskVolumeToResize.sizeTotal + DiskSize.fromGibibyte(3);
if (_currentSliderGbValue < 0) { if (_currentSliderGbValue < 0) {
_currentSliderGbValue = minSize.gibibyte; _currentSliderGbValue = minSize.gibibyte;
} }
final isAlreadyResizing =
context.watch<ApiProviderVolumeCubit>().state.isResizing;
return BrandHeroScreen( return BrandHeroScreen(
hasBackButton: true, hasBackButton: true,
heroTitle: 'providers.storage.extending_volume_title'.tr(), heroTitle: 'providers.storage.extending_volume_title'.tr(),
@ -143,13 +147,14 @@ class _ExtendingVolumePageState extends State<ExtendingVolumePage> {
context.read<ApiProviderVolumeCubit>().resizeVolume( context.read<ApiProviderVolumeCubit>().resizeVolume(
widget.diskVolumeToResize, widget.diskVolumeToResize,
_currentSliderGbValue.round(), _currentSliderGbValue.round(),
context.read<ApiServerVolumeCubit>().reload,
); );
Navigator.of(context).pushAndRemoveUntil( Navigator.of(context).pushAndRemoveUntil(
materialRoute(const RootPage()), materialRoute(const RootPage()),
(final predicate) => false, (final predicate) => false,
); );
}, },
disabled: _isError, disabled: _isError || isAlreadyResizing,
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
const Divider( const Divider(