Skip to content

Commit

Permalink
feat: read-only activity journal
Browse files Browse the repository at this point in the history
refs: #30
  • Loading branch information
daniele-athome committed Jul 25, 2022
1 parent 0d85e42 commit 5b42298
Show file tree
Hide file tree
Showing 10 changed files with 671 additions and 1 deletion.
10 changes: 10 additions & 0 deletions lib/helpers/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ class AppConfig extends ChangeNotifier {
return _currentAircraft!.backendInfo['flightlog_spreadsheet_id'] != null &&
_currentAircraft!.backendInfo['flightlog_sheet_name'] != null &&
_currentAircraft!.noPilotName != null;
case 'activities':
return _currentAircraft!.backendInfo['activities_spreadsheet_id'] != null &&
_currentAircraft!.backendInfo['activities_sheet_name'] != null;
default:
throw Exception('Unknown feature: $feature');
}
Expand Down Expand Up @@ -72,6 +75,13 @@ class AppConfig extends ChangeNotifier {
};
}

Map<String, String> get activitiesBackendInfo {
return {
'spreadsheet_id': _currentAircraft!.backendInfo['activities_spreadsheet_id'],
'sheet_name': _currentAircraft!.backendInfo['activities_sheet_name'],
};
}

String get locationName {
return _currentAircraft!.locationName;
}
Expand Down
7 changes: 7 additions & 0 deletions lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

"mainNav_bookFlight": "Bookings",
"mainNav_logBook": "Log book",
"mainNav_activities": "Activities",
"mainNav_about": "Info",

"button_goToday": "Today",
Expand Down Expand Up @@ -108,6 +109,12 @@
"flightLogModal_dialog_delete_message": "You are deleting a registered flight. You won't be able to undo this!",
"flightLogModal_dialog_working": "Please wait...",

"activities_title": "Activities",
"activities_button_error_retry": "Retry",
"activities_error_noItemsFound": "Nothing to do!",
"activities_error_firstPageIndicator": "Something went wrong.",
"activities_error_newPageIndicator": "Something went wrong. Tap to retry.",

"addAircraft_title": "Setup aircraft",
"addAircraft_text1": "Please type in the address to the aircraft data and its password.",
"addAircraft_label_address": "Address",
Expand Down
7 changes: 7 additions & 0 deletions lib/l10n/app_it.arb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

"mainNav_bookFlight": "Prenota",
"mainNav_logBook": "Log book",
"mainNav_activities": "Attività",
"mainNav_about": "Info",

"button_goToday": "Oggi",
Expand Down Expand Up @@ -91,6 +92,12 @@
"flightLogModal_dialog_delete_message": "Stai cancellando un volo registrato. Non potrai recuperarlo!",
"flightLogModal_dialog_working": "Un attimo...",

"activities_title": "Attività",
"activities_button_error_retry": "Riprova",
"activities_error_noItemsFound": "Nulla da segnalare!",
"activities_error_firstPageIndicator": "Qualcosa è andato storto.",
"activities_error_newPageIndicator": "Qualcosa è andato storto. Tocca per riprovare.",

"addAircraft_title": "Configura aereo",
"addAircraft_text1": "Inserisci l'indirizzo della configurazione dell'aereo e la sua password.",
"addAircraft_label_address": "Indirizzo",
Expand Down
21 changes: 21 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ import 'helpers/config.dart';
import 'helpers/googleapis.dart';
import 'helpers/utils.dart';
import 'screens/about/about_screen.dart';
import 'screens/activities/activities_screen.dart';
import 'screens/aircraft_select/aircraft_data_screen.dart';
import 'screens/book_flight/book_flight_screen.dart';
import 'screens/flight_log/flight_log_screen.dart';
import 'screens/pilot_select/pilot_select_screen.dart';
import 'services/activities_services.dart';
import 'services/book_flight_services.dart';
import 'services/flight_log_services.dart';

Expand Down Expand Up @@ -129,6 +131,8 @@ class _MyAppState extends State<MyApp> {
MainNavigation(appConfig) : const SizedBox.shrink(),
'pilot-select': (context) => appConfig.currentAircraft != null ?
const PilotSelectScreen() : const SizedBox.shrink(),
'activities': (context) => appConfig.currentAircraft != null ?
const ActivitiesScreen() : const SizedBox.shrink(),
'aircraft-data': (context) => const SetAircraftDataScreen(),
},
debugShowCheckedModeBanner: false,
Expand Down Expand Up @@ -158,11 +162,13 @@ class MainNavigation extends StatefulWidget {

final BookFlightCalendarService? bookFlightCalendarService;
final FlightLogBookService? flightLogBookService;
final ActivitiesService? activitiesService;
// TODO other services one day...

const MainNavigation(this.appConfig, {Key? key})
: bookFlightCalendarService = null,
flightLogBookService = null,
activitiesService = null,
super(key: key);

/// Mainly for integration testing.
Expand All @@ -171,6 +177,7 @@ class MainNavigation extends StatefulWidget {
Key? key,
this.bookFlightCalendarService,
this.flightLogBookService,
this.activitiesService,
}) : super(key: key);

@override
Expand All @@ -181,6 +188,7 @@ class _MainNavigationState extends State<MainNavigation> {
late PlatformTabController _tabController;
late BookFlightCalendarService? _bookFlightCalendarService;
late FlightLogBookService? _flightLogBookService;
late ActivitiesService? _activitiesService;

@override
void initState() {
Expand All @@ -205,6 +213,8 @@ class _MainNavigationState extends State<MainNavigation> {
(widget.appConfig.hasFeature('book_flight') ? BookFlightCalendarService(account!, widget.appConfig.googleCalendarId) : null);
_flightLogBookService = widget.flightLogBookService ??
(widget.appConfig.hasFeature('flight_log') ? FlightLogBookService(account!, widget.appConfig.flightlogBackendInfo) : null);
_activitiesService = widget.activitiesService ??
(widget.appConfig.hasFeature('activities') ? ActivitiesService(account!, widget.appConfig.activitiesBackendInfo) : null);
}

@override
Expand Down Expand Up @@ -235,6 +245,10 @@ class _MainNavigationState extends State<MainNavigation> {
value: _flightLogBookService,
child: const FlightLogScreen(),
),
if (widget.appConfig.hasFeature('activities')) () => Provider.value(
value: _activitiesService,
child: const ActivitiesScreen(),
),
() => const AboutScreen(),
][index]();
}
Expand All @@ -256,6 +270,13 @@ class _MainNavigationState extends State<MainNavigation> {
label: AppLocalizations.of(context)!.mainNav_logBook,
tooltip: '',
),
if (widget.appConfig.hasFeature('activities')) BottomNavigationBarItem(
icon: Icon(PlatformIcons(context).flag,
key: const Key('nav_activities'),
),
label: AppLocalizations.of(context)!.mainNav_activities,
tooltip: '',
),
BottomNavigationBarItem(
icon: Icon(PlatformIcons(context).info,
key: const Key('nav_info'),
Expand Down
80 changes: 80 additions & 0 deletions lib/models/activities_models.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@

/// Activity types. The code is used by the backend.
/// A type can be a task (i.e. can be marked as done) or not.
/// A type can also trigger an alert: it will be notified to all pilots (may be overridden in entry)
enum ActivityType {
/// A simple note. Not a task.
note(10, false, false),
/// A minor task to be done (e.g. washing)
minor(30, true, false),
/// A non-critical issue requiring a notice to all pilots.
notice(70, false, true),
/// A relevant, important issue that must be addressed (although aircraft is able to fly).
important(90, true, true),
/// A critical issue, possibly related to flight security. Must be addressed before flight.
critical(100, true, true);

const ActivityType(this.code, this.task, this.alert);

final int code;
final bool task;
final bool alert;

static ActivityType fromCode(int code) =>
ActivityType.values.firstWhere((element) => element.code == code);
}

enum ActivityStatus {
todo('TODO'),
inProgress('IN PROGRESS'),
done('DONE');

const ActivityStatus(this.label);

final String label;

static ActivityStatus fromLabel(String label) =>
ActivityStatus.values.firstWhere((element) => element.label == label);
}

class ActivityEntry {
ActivityEntry({
this.id,
required this.type,
required this.creationDate,
this.status,
this.dueDate,
required this.author,
required this.summary,
this.description,
this.alert,
});

/// Entry ID. Used by the backend.
String? id;

/// Entry type.
ActivityType type;

/// Creation date.
DateTime creationDate;

/// Entry status.
ActivityStatus? status;

/// Due date (if any).
DateTime? dueDate;

/// Pilot that created this entry.
String author;

/// Entry summary.
String summary;

/// Entry description.
String? description;

/// Trigger an alert to all pilots. If null, the alert flag in [type] will be used.
bool? alert;

}
Loading

0 comments on commit 5b42298

Please sign in to comment.