feat: Add tests, update notes implementation

This commit is contained in:
Anton Stubenbord
2023-12-31 15:26:20 +01:00
parent d7f297a4df
commit 55aa42e4ab
29 changed files with 273 additions and 115 deletions

View File

@@ -1,61 +0,0 @@
import 'package:dio/dio.dart';
import 'package:paperless_api/paperless_api.dart';
class DioHttpErrorInterceptor extends Interceptor {
@override
void onError(DioException err, ErrorInterceptorHandler handler) {
if (err.response?.statusCode == 400) {
final data = err.response!.data;
if (PaperlessServerMessageException.canParse(data)) {
final exception = PaperlessServerMessageException.fromJson(data);
final message = exception.detail;
handler.reject(
DioException(
message: message,
requestOptions: err.requestOptions,
error: exception,
response: err.response,
type: DioExceptionType.badResponse,
),
);
} else if (PaperlessFormValidationException.canParse(data)) {
final exception = PaperlessFormValidationException.fromJson(data);
handler.reject(
DioException(
requestOptions: err.requestOptions,
error: exception,
response: err.response,
type: DioExceptionType.badResponse,
),
);
} else if (data is String) {
if (data.contains("No required SSL certificate was sent")) {
handler.reject(
DioException(
requestOptions: err.requestOptions,
type: DioExceptionType.badResponse,
error: const PaperlessApiException(
ErrorCode.missingClientCertificate),
),
);
} else {
handler.reject(
DioException(
requestOptions: err.requestOptions,
message: data,
error: PaperlessApiException(
ErrorCode.documentLoadFailed,
details: data,
),
response: err.response,
stackTrace: err.stackTrace,
type: DioExceptionType.badResponse,
),
);
}
} else {
handler.reject(err);
}
}
}
}

View File

@@ -9,4 +9,9 @@ class InfoMessageException implements Exception {
this.message,
this.stackTrace,
});
@override
String toString() {
return 'InfoMessageException(code: $code, message: $message, stackTrace: $stackTrace)';
}
}

View File

@@ -3,7 +3,7 @@ import 'dart:io';
import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:flutter/material.dart';
import 'package:paperless_mobile/core/interceptor/dio_http_error_interceptor.dart';
import 'package:paperless_api/src/interceptor/dio_http_error_interceptor.dart';
import 'package:paperless_mobile/core/interceptor/dio_offline_interceptor.dart';
import 'package:paperless_mobile/core/interceptor/dio_unauthorized_interceptor.dart';
import 'package:paperless_mobile/core/interceptor/retry_on_connection_change_interceptor.dart';

View File

@@ -82,5 +82,7 @@ String translateError(BuildContext context, ErrorCode code) {
'Could not load custom field.', //TODO: INTL
ErrorCode.customFieldDeleteFailed =>
'Could not delete custom field, please try again.', //TODO: INTL
ErrorCode.deleteNoteFailed => 'Could not delete note, please try again.',
ErrorCode.addNoteFailed => 'Could not create note, please try again.',
};
}

View File

@@ -311,4 +311,17 @@ class DocumentDetailsCubit extends Cubit<DocumentDetailsState> {
_notifier.removeListener(this);
await super.close();
}
Future<void> addNote(String text) async {
assert(state.status == LoadingStatus.loaded);
try {
final updatedDocument = await _api.addNote(
document: state.document!,
text: text,
);
_notifier.notifyUpdated(updatedDocument);
} on PaperlessApiException catch (err) {
addError(TransientPaperlessApiError(code: err.code));
}
}
}

View File

@@ -1,37 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
class AddNotePage extends StatefulWidget {
final DocumentModel document;
const AddNotePage({super.key, required this.document});
@override
State<AddNotePage> createState() => _AddNotePageState();
}
class _AddNotePageState extends State<AddNotePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(S.of(context)!.addNote),
),
body: Column(
children: [
TextField(
decoration: InputDecoration(
labelText: S.of(context)!.content,
),
),
ElevatedButton(
onPressed: () {},
child: Text(S.of(context)!.save),
),
],
),
);
}
}

View File

@@ -8,18 +8,65 @@ import 'package:paperless_mobile/features/document_details/cubit/document_detail
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
import 'package:paperless_mobile/helpers/message_helpers.dart';
class DocumentNotesWidget extends StatelessWidget {
class DocumentNotesWidget extends StatefulWidget {
final DocumentModel document;
const DocumentNotesWidget({super.key, required this.document});
@override
State<DocumentNotesWidget> createState() => _DocumentNotesWidgetState();
}
class _DocumentNotesWidgetState extends State<DocumentNotesWidget> {
final _noteContentController = TextEditingController();
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return SliverMainAxisGroup(
slivers: [
SliverToBoxAdapter(
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
controller: _noteContentController,
maxLines: null,
validator: (value) {
if (value?.isEmpty ?? true) {
return S.of(context)!.thisFieldIsRequired;
}
return null;
},
decoration: InputDecoration(
hintText: 'Your note here...',
labelText: 'New note',
floatingLabelBehavior: FloatingLabelBehavior.always,
),
).padded(),
Align(
alignment: Alignment.centerRight,
child: FilledButton.icon(
icon: Icon(Icons.note_add_outlined),
label: Text("Add note"),
onPressed: () {
_formKey.currentState?.save();
if (_formKey.currentState?.validate() ?? false) {
context
.read<DocumentDetailsCubit>()
.addNote(_noteContentController.text);
}
},
).padded(),
),
],
).padded(),
),
),
SliverList.separated(
separatorBuilder: (context, index) => const SizedBox(height: 16),
itemBuilder: (context, index) {
final note = document.notes.elementAt(index);
final note = widget.document.notes.elementAt(index);
return Card(
// borderRadius: BorderRadius.circular(8),
// elevation: 1,
@@ -51,13 +98,6 @@ class DocumentNotesWidget extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Spacer(),
IconButton(
icon: Icon(Icons.edit),
onPressed: () {
// Push edit page
},
),
IconButton(
icon: Icon(Icons.delete),
onPressed: () {
@@ -74,7 +114,7 @@ class DocumentNotesWidget extends StatelessWidget {
).padded(16),
);
},
itemCount: document.notes.length,
itemCount: widget.document.notes.length,
),
],
);

View File

@@ -1,15 +0,0 @@
import 'package:flutter/material.dart';
class EditNotePage extends StatefulWidget {
const EditNotePage({super.key});
@override
State<EditNotePage> createState() => _EditNotePageState();
}
class _EditNotePageState extends State<EditNotePage> {
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}

View File

@@ -54,7 +54,9 @@ class DocumentScannerCubit extends Cubit<DocumentScannerState> {
Future<void> removeScan(File file) async {
try {
await file.delete();
if (await file.exists()) {
await file.delete();
}
} catch (error, stackTrace) {
throw InfoMessageException(
code: ErrorCode.scanRemoveFailed,

View File

@@ -14,6 +14,7 @@ import 'package:paperless_mobile/core/bloc/loading_status.dart';
import 'package:paperless_mobile/core/database/hive/hive_config.dart';
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
import 'package:paperless_mobile/core/global/constants.dart';
import 'package:paperless_mobile/core/model/info_message_exception.dart';
import 'package:paperless_mobile/core/service/file_service.dart';
import 'package:paperless_mobile/features/app_drawer/view/app_drawer.dart';
import 'package:paperless_mobile/features/document_scan/cubit/document_scanner_cubit.dart';
@@ -326,6 +327,8 @@ class _ScannerPageState extends State<ScannerPage>
.removeScan(scans[index]);
} on PaperlessApiException catch (error, stackTrace) {
showErrorMessage(context, error, stackTrace);
} on InfoMessageException catch (error, stackTrace) {
showInfoMessage(context, error, stackTrace);
}
},
index: index,

View File

@@ -9,7 +9,6 @@ import 'package:paperless_mobile/features/document_bulk_action/view/widgets/full
import 'package:paperless_mobile/features/document_bulk_action/view/widgets/fullscreen_bulk_edit_tags_widget.dart';
import 'package:paperless_mobile/features/document_details/cubit/document_details_cubit.dart';
import 'package:paperless_mobile/features/document_details/view/pages/document_details_page.dart';
import 'package:paperless_mobile/features/document_details/view/widgets/add_note_page.dart';
import 'package:paperless_mobile/features/document_edit/cubit/document_edit_cubit.dart';
import 'package:paperless_mobile/features/document_edit/view/document_edit_page.dart';
import 'package:paperless_mobile/features/documents/view/pages/document_view.dart';
@@ -211,16 +210,3 @@ class BulkEditDocumentsRoute extends GoRouteData {
);
}
}
class AddNoteRoute extends GoRouteData {
final DocumentModel $extra;
AddNoteRoute({required this.$extra});
@override
Widget build(BuildContext context, GoRouterState state) {
return AddNotePage(
document: $extra,
);
}
}

View File

@@ -85,10 +85,6 @@ part 'authenticated_route.g.dart';
path: 'preview',
name: R.documentPreview,
),
TypedGoRoute<AddNoteRoute>(
path: 'add-note',
name: R.addNote,
),
],
)
],