Skip to content

Commit

Permalink
feat: Suggest to import from API (#74)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gustl22 committed Oct 10, 2024
1 parent 9b4e59c commit 0ca8797
Show file tree
Hide file tree
Showing 17 changed files with 257 additions and 120 deletions.
14 changes: 14 additions & 0 deletions wrestling_scoreboard_client/lib/l10n/app_de.arb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@
"apiProvider": "API-Anbieter",
"importFromApiProvider": "Synchronisiere mit API-Anbieter",
"warningImportFromApiProvider": "Diese Aktion importiert Objekte dieser Organisation und versucht diese zu integrieren. Bist du sicher, dass du fortfahren möchtest?",
"recommendFirstImportFromApiProvider": "Der letzte Import konnte nicht bestimmt werden. Möchtest du die Daten importieren?",
"recommendImportFromApiProvider": "Der letzte Import war am {date} um {time} Uhr. Möchtest du die Daten aktualisieren?",
"@recommendImportFromApiProvider": {
"placeholders": {
"date": {
"type": "DateTime",
"format": "yMd"
},
"time": {
"type": "DateTime",
"format": "Hm"
}
}
},
"reportProvider": "Report-Anbieter",
"database": "Datenbank",
"exportDatabase": "Datenbank exportieren",
Expand Down
24 changes: 14 additions & 10 deletions wrestling_scoreboard_client/lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,31 @@
"apiProvider": "API Provider",
"importFromApiProvider": "Sync with API provider",
"warningImportFromApiProvider": "This action imports objects of this organization and tries to integrate them. Are you sure, you want to continue?",
"recommendFirstImportFromApiProvider": "Cannot determine the last import. Would you like import the data?",
"recommendImportFromApiProvider": "The last import was on {date} at {time}. Would you like to update the data?",
"@recommendImportFromApiProvider": {
"placeholders": {
"date": {
"type": "DateTime",
"format": "yMd"
},
"time": {
"type": "DateTime",
"format": "Hm"
}
}
},
"reportProvider": "Report Provider",
"database": "Database",
"exportDatabase": "Export database",
"restoreDatabase": "Restore database",
"restoreDefaultDatabase": "Restore default database",
"resetDatabase": "Reset database",
"bellSound": "Bell sound",

"profile": "Profile",
"username": "Username",
"password": "Password",
"email": "Email",

"auth_signIn": "Sign in",
"auth_signInPrompt_phrase": "Already have an account? Sign In",
"auth_signIntoAccount_phrase": "Sign in to your account",
Expand All @@ -51,7 +63,6 @@
"auth_password_save_phrase": "Save password",
"auth_change_password": "Change password",
"auth_agreeTermsAndConditions_phrase": "I read and agree to Terms & Conditions",

"imprint": "Imprint",
"imprint_phrase": "**Angaben gem. § 5 TMG:**\n\nOberhauser Dev\n\nAugust Oberhauser\n\nGroßhausener Str. 16\n\n86551 Aichach\n\n**Kontaktaufnahme:**\n\nE-Mail: [email protected]\n\n**Umsatzsteuer-Identifikationsnummer gem. § 27 a Umsatzsteuergesetz:**\n\nDE XXX XXX XXX",
"about": "About",
Expand All @@ -63,7 +74,6 @@
"about_Development": "Development",
"about_development_phrase": "August Oberhauser\n\nEmail: [email protected]\n\nWebsite: [oberhauser.dev](https://oberhauser.dev)",
"privacy_policy": "Privacy Policy",

"optionSelect": "select",
"noneSelected": "None selected",
"edit": "Edit",
Expand Down Expand Up @@ -97,15 +107,13 @@
"warningPrefilledLineup": "The lineup was prefilled with values from a previous match!",
"retry": "Retry",
"networkTimeout": "Network timeout",

"event": "Event",
"place": "Place",
"date": "Date",
"minutes": "Minutes",
"seconds": "Seconds",
"startDate": "Beginning",
"endDate": "End",

"wrestlingRulesPdf": "https://uww.org/sites/default/files/2019-12/wrestling_rules.pdf",
"teamMatchTranscript": "Transcript for Team Matches",
"teamMatchScoreSheet": "Score sheet for Team Matches",
Expand All @@ -120,7 +128,6 @@
"numberAbbreviation": "No.",
"total": "Total",
"participantVacant": "vacant",

"weight": "Weight",
"weightClass": "Weight Class",
"weightClasses": "Weight Classes",
Expand Down Expand Up @@ -190,7 +197,6 @@
"classificationPoints": "Classification Points",
"participations": "Participations",
"boutConfig": "Bout configuration",

"red": "Red",
"blue": "Blue",
"winner": "Winner",
Expand All @@ -211,15 +217,13 @@
"activityDuration": "Activity duration",
"injuryDuration": "Injury duration",
"periodCount": "Number of periods",

"referee": "Referee",
"refereeAbbr": "REF",
"judge": "Judge",
"matChairman": "Mat president",
"timeKeeper": "Time Keeper",
"transcriptionWriter": "Transcription Writer",
"steward": "Steward",

"prename": "Prename",
"surname": "Surname",
"age": "Age",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,21 @@ class MockDataManager extends DataManager {
throw UnimplementedError();
}

@override
Future<DateTime?> organizationLastImportUtcDateTime(int id) => throw UnimplementedError();

@override
Future<DateTime?> organizationLeagueLastImportUtcDateTime(int id) => throw UnimplementedError();

@override
Future<DateTime?> organizationTeamMatchLastImportUtcDateTime(int id) => throw UnimplementedError();

@override
Future<DateTime?> organizationCompetitionLastImportUtcDateTime(int id) => throw UnimplementedError();

@override
Future<DateTime?> organizationTeamLastImportUtcDateTime(int id) => throw UnimplementedError();

@override
Future<Map<String, List<DataObject>>> search({
required String searchTerm,
Expand Down
10 changes: 10 additions & 0 deletions wrestling_scoreboard_client/lib/services/network/data_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ abstract class DataManager implements AuthManager {

Future<void> organizationTeamMatchImport(int id, {AuthService? authService});

Future<DateTime?> organizationLastImportUtcDateTime(int id);

Future<DateTime?> organizationTeamLastImportUtcDateTime(int id);

Future<DateTime?> organizationLeagueLastImportUtcDateTime(int id);

Future<DateTime?> organizationCompetitionLastImportUtcDateTime(int id);

Future<DateTime?> organizationTeamMatchLastImportUtcDateTime(int id);

Future<Map<String, List<DataObject>>> search({
required String searchTerm,
Type? type,
Expand Down
107 changes: 46 additions & 61 deletions wrestling_scoreboard_client/lib/services/network/remote/rest.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class RestDataManager extends DataManager {
Uri.parse('$_apiUrl${_getPathFromType(T)}/$id').replace(queryParameters: isRaw ? rawQueryParameter : null);
final response = await http.get(uri, headers: _headers);

if (response.statusCode == 200) {
if (response.statusCode < 400) {
return jsonDecode(response.body);
} else {
throw RestException('Failed to READ single ${T.toString()}', response: response);
Expand All @@ -67,7 +67,7 @@ class RestDataManager extends DataManager {
Uri.parse('$_apiUrl$prepend${_getPathFromType(T)}s').replace(queryParameters: isRaw ? rawQueryParameter : null);
final response = await http.get(uri, headers: _headers);

if (response.statusCode == 200) {
if (response.statusCode < 400) {
final List<dynamic> json = jsonDecode(response.body);
return json.map((e) => e as Map<String, dynamic>).toList(); // TODO check order
} else {
Expand Down Expand Up @@ -112,7 +112,7 @@ class RestDataManager extends DataManager {
Future<String> exportDatabase() async {
final uri = Uri.parse('$_apiUrl/database/export');
final response = await http.get(uri, headers: _headers);
if (response.statusCode == 200) {
if (response.statusCode < 400) {
return response.body;
} else {
throw RestException('Failed to export the database', response: response);
Expand All @@ -123,7 +123,7 @@ class RestDataManager extends DataManager {
Future<void> resetDatabase() async {
final uri = Uri.parse('$_apiUrl/database/reset');
final response = await http.post(uri, headers: _headers);
if (response.statusCode != 200) {
if (response.statusCode >= 400) {
throw RestException('Failed to reset the database', response: response);
}
}
Expand All @@ -132,7 +132,7 @@ class RestDataManager extends DataManager {
Future<void> restoreDefaultDatabase() async {
final uri = Uri.parse('$_apiUrl/database/restore_default');
final response = await http.post(uri, headers: _headers);
if (response.statusCode != 200) {
if (response.statusCode >= 400) {
throw RestException('Failed to restore the default database', response: response);
}
}
Expand All @@ -141,7 +141,7 @@ class RestDataManager extends DataManager {
Future<void> restoreDatabase(String sqlDump) async {
final uri = Uri.parse('$_apiUrl/database/restore');
final response = await http.post(uri, headers: _headers, body: sqlDump);
if (response.statusCode != 200) {
if (response.statusCode >= 400) {
throw RestException('Failed to restore the database', response: response);
}
}
Expand All @@ -151,81 +151,66 @@ class RestDataManager extends DataManager {
_webSocketManager = manager;
}

@override
Future<void> organizationImport(int id, {AuthService? authService}) async {
Future<void> _import(int id, String table, {AuthService? authService}) async {
String? body;
if (authService != null) {
if (authService is BasicAuthService) {
body = jsonEncode(singleToJson(authService, BasicAuthService, CRUD.update));
}
}
final uri = Uri.parse('$_apiUrl/organization/$id/api/import');
final uri = Uri.parse('$_apiUrl/$table/$id/api/import');
final response = await http.post(uri, body: body, headers: _headers);
if (response.statusCode != 200) {
throw RestException('Failed to import from organization $id', response: response);
if (response.statusCode >= 400) {
throw RestException('Failed to import from $table $id', response: response);
}
}

@override
Future<void> organizationLeagueImport(int id, {AuthService? authService}) async {
String? body;
if (authService != null) {
if (authService is BasicAuthService) {
body = jsonEncode(singleToJson(authService, BasicAuthService, CRUD.update));
}
}
final uri = Uri.parse('$_apiUrl/league/$id/api/import');
final response = await http.post(uri, body: body, headers: _headers);
if (response.statusCode != 200) {
throw RestException('Failed to import from league $id', response: response);
}
}
Future<void> organizationImport(int id, {AuthService? authService}) =>
_import(id, 'organization', authService: authService);

@override
Future<void> organizationTeamMatchImport(int id, {AuthService? authService}) async {
String? body;
if (authService != null) {
if (authService is BasicAuthService) {
body = jsonEncode(singleToJson(authService, BasicAuthService, CRUD.update));
}
}
final uri = Uri.parse('$_apiUrl/team_match/$id/api/import');
final response = await http.post(uri, body: body, headers: _headers);
if (response.statusCode != 200) {
throw RestException('Failed to import from team_match $id', response: response);
}
}
Future<void> organizationLeagueImport(int id, {AuthService? authService}) =>
_import(id, 'league', authService: authService);

@override
Future<void> organizationCompetitionImport(int id, {AuthService? authService}) async {
String? body;
if (authService != null) {
if (authService is BasicAuthService) {
body = jsonEncode(singleToJson(authService, BasicAuthService, CRUD.update));
}
}
final uri = Uri.parse('$_apiUrl/competition/$id/api/import');
final response = await http.post(uri, body: body, headers: _headers);
if (response.statusCode != 200) {
throw RestException('Failed to import from competition $id', response: response);
}
}
Future<void> organizationTeamMatchImport(int id, {AuthService? authService}) =>
_import(id, 'team_match', authService: authService);

@override
Future<void> organizationTeamImport(int id, {AuthService? authService}) async {
String? body;
if (authService != null) {
if (authService is BasicAuthService) {
body = jsonEncode(singleToJson(authService, BasicAuthService, CRUD.update));
}
}
final uri = Uri.parse('$_apiUrl/team/$id/api/import');
final response = await http.post(uri, body: body, headers: _headers);
if (response.statusCode != 200) {
throw RestException('Failed to import from team $id', response: response);
Future<void> organizationCompetitionImport(int id, {AuthService? authService}) =>
_import(id, 'competition', authService: authService);

@override
Future<void> organizationTeamImport(int id, {AuthService? authService}) =>
_import(id, 'team', authService: authService);

Future<DateTime?> _lastImportUtcDateTime(int id, String table) async {
final uri = Uri.parse('$_apiUrl/$table/$id/api/last_import');
final response = await http.get(uri, headers: _headers);

if (response.statusCode < 400) {
return DateTime.tryParse(response.body);
} else {
throw RestException('Failed to get the last import date time for $table $id', response: response);
}
}

@override
Future<DateTime?> organizationLastImportUtcDateTime(int id) => _lastImportUtcDateTime(id, 'organization');

@override
Future<DateTime?> organizationLeagueLastImportUtcDateTime(int id) => _lastImportUtcDateTime(id, 'league');

@override
Future<DateTime?> organizationTeamMatchLastImportUtcDateTime(int id) => _lastImportUtcDateTime(id, 'team_match');

@override
Future<DateTime?> organizationCompetitionLastImportUtcDateTime(int id) => _lastImportUtcDateTime(id, 'competition');

@override
Future<DateTime?> organizationTeamLastImportUtcDateTime(int id) => _lastImportUtcDateTime(id, 'team');

@override
Future<Map<String, List<DataObject>>> search({
required String searchTerm,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ class OrganizationOverview extends ConsumerWidget {
dataObject: data,
label: localizations.organization,
details: data.name,
actions: [OrganizationImportAction(id: id, orgId: id, importType: OrganizationImportType.organization)],
actions: [
ConditionalOrganizationImportAction(
id: id, organization: data, importType: OrganizationImportType.organization),
],
tabs: [
Tab(child: HeadingText(localizations.info)),
Tab(child: HeadingText(localizations.organizations)),
Expand Down
Loading

0 comments on commit 0ca8797

Please sign in to comment.