From 55a8be5dbb410759489d76dc629c4ef7bca0c75f Mon Sep 17 00:00:00 2001 From: Elias Projahn Date: Fri, 1 May 2020 15:40:49 +0200 Subject: [PATCH] client: Add pagination, search and delete methods The package now depends on meta for parameter annotations. Also, Uri objects are used instead of strings. This means, that the parameters to the constructor have changed too. --- client/lib/src/client.dart | 276 +++++++++++++++++++++++++++++++++---- client/pubspec.yaml | 1 + 2 files changed, 250 insertions(+), 27 deletions(-) diff --git a/client/lib/src/client.dart b/client/lib/src/client.dart index 4bfc657..6475106 100644 --- a/client/lib/src/client.dart +++ b/client/lib/src/client.dart @@ -2,38 +2,97 @@ import 'dart:convert'; import 'dart:io'; import 'package:http/http.dart' as http; +import 'package:meta/meta.dart'; import 'package:musicus_database/musicus_database.dart'; /// A simple http client for the Musicus server. class MusicusClient { - /// The URL of the Musicus server to connect to. + /// URI scheme to use for the connection. + /// + /// This will be used as the scheme parameter when creating Uri objects. + final String scheme; + + /// The host name of the Musicus server to connect to. + /// + /// This will be used as the host parameter when creating Uri objects. final String host; + /// This will be used as the port parameter when creating Uri objects. + final int port; + final _client = http.Client(); - MusicusClient(this.host); + MusicusClient({ + this.scheme = 'https', + this.port = 443, + @required this.host, + }) : assert(scheme != null), + assert(port != null), + assert(host != null); + + /// Get a list of persons. + /// + /// You can get another page using the [page] parameter. If a non empty + /// [search] string is provided, the persons will get filtered based on that + /// string. + Future> getPersons([int page, String search]) async { + final params = {}; + + if (page != null) { + params['p'] = page.toString(); + } + + if (search != null) { + params['s'] = search; + } + + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/persons', + queryParameters: params, + )); - /// Get a list of all available persons. - Future> getPersons() async { - final response = await _client.get('$host/persons'); final json = jsonDecode(response.body); return json.map((j) => Person.fromJson(j)).toList(); } /// Get a person by ID. Future getPerson(int id) async { - final response = await _client.get('$host/persons/$id'); + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/persons/$id', + )); + final json = jsonDecode(response.body); return Person.fromJson(json); } + /// Delete a person by ID. + Future deletePerson(int id) async { + await _client.delete(Uri( + scheme: scheme, + host: host, + port: port, + path: '/persons/$id', + )); + } + /// Create or update a person. /// /// Returns true, if the operation was successful. Future putPerson(Person person) async { try { final response = await _client.put( - '$host/persons/${person.id}', + Uri( + scheme: scheme, + host: host, + port: port, + path: '/persons/${person.id}', + ), headers: {'Content-Type': 'application/json'}, body: jsonEncode(person.toJson()), ); @@ -44,16 +103,43 @@ class MusicusClient { } } - /// Get a list of all available instruments. - Future> getInstruments() async { - final response = await _client.get('$host/instruments'); + /// Get a list of instruments. + /// + /// You can get another page using the [page] parameter. If a non empty + /// [search] string is provided, the results will get filtered based on that + /// string. + Future> getInstruments([int page, String search]) async { + final params = {}; + + if (page != null) { + params['p'] = page.toString(); + } + + if (search != null) { + params['s'] = search; + } + + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/instruments', + queryParameters: params, + )); + final json = jsonDecode(response.body); return json.map((j) => Instrument.fromJson(j)).toList(); } /// Get an instrument by ID. Future getInstrument(int id) async { - final response = await _client.get('$host/instruments/$id'); + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/instruments/$id', + )); + final json = jsonDecode(response.body); return Instrument.fromJson(json); } @@ -64,7 +150,12 @@ class MusicusClient { Future putInstrument(Instrument instrument) async { try { final response = await _client.put( - '$host/instruments/${instrument.id}', + Uri( + scheme: scheme, + host: host, + port: port, + path: '/instruments/${instrument.id}', + ), headers: {'Content-Type': 'application/json'}, body: jsonEncode(instrument.toJson()), ); @@ -75,23 +166,86 @@ class MusicusClient { } } - /// Get all works composed by the person with the ID [personId]. - Future> getWorks(int personId) async { - final response = await _client.get('$host/persons/$personId/works'); + /// Delete an instrument by ID. + Future deleteInstrument(int id) async { + await _client.delete(Uri( + scheme: scheme, + host: host, + port: port, + path: '/instruments/$id', + )); + } + + /// Get a list of works written by the person with the ID [personId]. + /// + /// You can get another page using the [page] parameter. If a non empty + /// [search] string is provided, the results will get filtered based on that + /// string. + Future> getWorks(int personId, + [int page, String search]) async { + final params = {}; + + if (page != null) { + params['p'] = page.toString(); + } + + if (search != null) { + params['s'] = search; + } + + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/persons/$personId/works', + queryParameters: params, + )); + final json = jsonDecode(response.body); return json.map((j) => WorkInfo.fromJson(j)).toList(); } /// Get a work by ID. Future getWork(int id) async { - final response = await _client.get('$host/works/$id'); + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/works/$id', + )); + final json = jsonDecode(response.body); return WorkInfo.fromJson(json); } - /// Get all recordings of the work with the ID [workId]. - Future> getRecordings(int workId) async { - final response = await _client.get('$host/works/$workId/recordings'); + /// Delete a work by ID. + Future deleteWork(int id) async { + await _client.delete(Uri( + scheme: scheme, + host: host, + port: port, + path: '/works/$id', + )); + } + + /// Get a list of recordings of the work with the ID [workId]. + /// + /// You can get another page using the [page] parameter. + Future> getRecordings(int workId, [int page]) async { + final params = {}; + + if (page != null) { + params['p'] = page.toString(); + } + + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/works/$workId/recordings', + queryParameters: params, + )); + final json = jsonDecode(response.body); return json.map((j) => RecordingInfo.fromJson(j)).toList(); } @@ -102,7 +256,12 @@ class MusicusClient { Future putWork(WorkInfo workInfo) async { try { final response = await _client.put( - '$host/works/${workInfo.work.id}', + Uri( + scheme: scheme, + host: host, + port: port, + path: '/works/${workInfo.work.id}', + ), headers: {'Content-Type': 'application/json'}, body: jsonEncode(workInfo.toJson()), ); @@ -113,16 +272,43 @@ class MusicusClient { } } - /// Get a list of all ensembles. - Future> getEnsembles() async { - final response = await _client.get('$host/ensembles'); + /// Get a list of ensembles. + /// + /// You can get another page using the [page] parameter. If a non empty + /// [search] string is provided, the results will get filtered based on that + /// string. + Future> getEnsembles([int page, String search]) async { + final params = {}; + + if (page != null) { + params['p'] = page.toString(); + } + + if (search != null) { + params['s'] = search; + } + + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/ensembles', + queryParameters: params, + )); + final json = jsonDecode(response.body); return json.map((j) => Ensemble.fromJson(j)).toList(); } /// Get an ensemble by ID. Future getEnsemble(int id) async { - final response = await _client.get('$host/ensembles/$id'); + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/ensembles/$id', + )); + final json = jsonDecode(response.body); return Ensemble.fromJson(json); } @@ -133,7 +319,12 @@ class MusicusClient { Future putEnsemble(Ensemble ensemble) async { try { final response = await _client.put( - '$host/ensembles/${ensemble.id}', + Uri( + scheme: scheme, + host: host, + port: port, + path: '/ensembles/${ensemble.id}', + ), headers: {'Content-Type': 'application/json'}, body: jsonEncode(ensemble.toJson()), ); @@ -144,9 +335,25 @@ class MusicusClient { } } + /// Delete an ensemble by ID. + Future deleteEnsemble(int id) async { + await _client.delete(Uri( + scheme: scheme, + host: host, + port: port, + path: '/ensembles/$id', + )); + } + /// Get a recording by ID. Future getRecording(int id) async { - final response = await _client.get('$host/recordings/$id'); + final response = await _client.get(Uri( + scheme: scheme, + host: host, + port: port, + path: '/recordings/$id', + )); + final json = jsonDecode(response.body); return RecordingInfo.fromJson(json); } @@ -157,7 +364,12 @@ class MusicusClient { Future putRecording(RecordingInfo recordingInfo) async { try { final response = await _client.put( - '$host/recordings/${recordingInfo.recording.id}', + Uri( + scheme: scheme, + host: host, + port: port, + path: '/recordings/${recordingInfo.recording.id}', + ), headers: {'Content-Type': 'application/json'}, body: jsonEncode(recordingInfo.toJson()), ); @@ -168,6 +380,16 @@ class MusicusClient { } } + /// Delete a recording by ID. + Future deleteRecording(int id) async { + await _client.delete(Uri( + scheme: scheme, + host: host, + port: port, + path: '/recordings/$id', + )); + } + /// Close the internal http client. void dispose() { _client.close(); diff --git a/client/pubspec.yaml b/client/pubspec.yaml index ba9945e..4d6bda6 100644 --- a/client/pubspec.yaml +++ b/client/pubspec.yaml @@ -7,5 +7,6 @@ environment: dependencies: http: + meta: musicus_database: path: ../database \ No newline at end of file