Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit beb98fe

Browse files
hellokidderphillwiggins
authored andcommittedJul 19, 2019
add distinct function (#225)
* Merged v1.0.22 * 1. Fix return result from save method. This is important. (#208) 2. Fix unsavedChanges issue in ParseUser login and signUp method. 3. Delete useless and reduplicative decode in ParseUser. Because this is already done in handleResponse method. This also cause wrong unsaved changes. * README.md updated from https://stackedit.io/ * README.md updated from https://stackedit.io/ * README.md updated from https://stackedit.io/ * README.md updated from https://stackedit.io/ * README.md updated from https://stackedit.io/ * Update README.md * add distinct
1 parent efd0a0f commit beb98fe

File tree

6 files changed

+64
-64
lines changed

6 files changed

+64
-64
lines changed
 

‎.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.DS_Store
22
.dart_tool/
3-
3+
.history
44
.packages
55
.pub/
66
pubspec.lock

‎README.md

Lines changed: 30 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
![enter image description here](https://upload.wikimedia.org/wikipedia/commons/1/17/Google-flutter-logo.png)
2-
![enter image description here](https://i2.wp.com/blog.openshift.com/wp-content/uploads/parse-server-logo-1.png?fit=200%2C200&ssl=1&resize=350%2C200)
31

4-
[![Build Status](https://travis-ci.org/phillwiggins/flutter_parse_sdk.svg?branch=master)](https://travis-ci.org/phillwiggins/flutter_parse_sdk)
2+
![Parse Logo](https://upload.wikimedia.org/wikipedia/commons/1/17/Google-flutter-logo.png)![Flutter Logo](https://i2.wp.com/blog.openshift.com/wp-content/uploads/parse-server-logo-1.png?fit=200%2C200&ssl=1&resize=350%2C200)
53

64
## Parse For Flutter!
75
Hi, this is a Flutter plugin that allows communication with a Parse Server, (https://parseplatform.org) either hosted on your own server or another, like (http://Back4App.com).
@@ -23,31 +21,32 @@ or clone this repository and add to your project. As this is an early developmen
2321
Once you have the library added to your project, upon first call to your app (Similar to what your application class would be) add the following...
2422
2523
```dart
26-
await Parse().initialize(
27-
ApplicationConstants.keyApplicationId,
28-
ApplicationConstants.keyParseServerUrl);
24+
await Parse().initialize(
25+
keyApplicationId,
26+
keyParseServerUrl);
2927
```
30-
if you want to use secure storage also that's allow using sdk on desktop application
28+
29+
If you want to use secure storage or use the Flutter web/desktop SDK, please change to the below instance of CoreStorage as it has no dependencies on Flutter.
3130
```dart
3231
33-
await Parse().initialize(keyParseApplicationId, keyParseServerUrl,
34-
masterKey: keyParseMasterKey,
35-
debug: true,
36-
coreStore: await CoreStoreSembastImp.getInstance());
32+
await Parse().initialize(
33+
keyParseApplicationId,
34+
keyParseServerUrl,
35+
coreStore: await CoreStoreSembastImp.getInstance());
3736
```
38-
It's possible to add other params, such as ...
37+
It's possible to add other parameters to work with your instance of Parse Server:-
3938

4039
```dart
4140
await Parse().initialize(
42-
ApplicationConstants.keyApplicationId,
43-
ApplicationConstants.keyParseServerUrl,
44-
masterKey: ApplicationConstants.keyParseMasterKey,
45-
clientKey: ApplicationConstants.keyParseClientKey,
46-
debug: true,
47-
liveQueryUrl: ApplicationConstants.keyLiveQueryUrl,
48-
autoSendSessionId: true,
49-
securityContext: securityContext,
50-
coreStore: await CoreStoreSharedPrefsImp.getInstance());
41+
keyApplicationId,
42+
keyParseServerUrl,
43+
masterKey: keyParseMasterKey, // Required for Back4App and others
44+
clientKey: keyParseClientKey, // Required for some setups
45+
debug: true, // When enabled, prints logs to console
46+
liveQueryUrl: keyLiveQueryUrl, // Required if using LiveQuery
47+
autoSendSessionId: true, // Some confurations require this to be true
48+
securityContext: securityContext, // Again, required for some setups
49+
coreStore: await CoreStoreSharedPrefsImp.getInstance()); // Will use SharedPreferences instead of Sembast as an internal DB
5150
```
5251

5352
## Objects
@@ -56,13 +55,13 @@ You can create custom objects by calling:
5655
var dietPlan = ParseObject('DietPlan')
5756
..set('Name', 'Ketogenic')
5857
..set('Fat', 65);
59-
await dietPlan.save()
58+
await dietPlan.save();
6059
```
6160
Verify that the object has been successfully saved using
6261
```dart
6362
var response = await dietPlan.save();
6463
if (response.success) {
65-
dietPlan = response.result;
64+
dietPlan = response.results.first;
6665
}
6766
```
6867
Types supported:
@@ -134,14 +133,6 @@ and to retrieve it
134133
var dietPlan = DietPlan().fromPin('OBJECT ID OF OBJECT');
135134
```
136135

137-
## Storage
138-
We now have 2 types of storage, secure and unsecure. We currently rely on 2 third party options:
139-
140-
* SharedPreferences
141-
* Sembast
142-
143-
Sembast offers secured storage, whilst SharePreferences wraps NSUserDefaults (on iOS) and SharedPreferences (on Android).
144-
145136
## Increment Counter values in objects
146137
Retrieve it, call
147138

@@ -172,9 +163,9 @@ var response = await dietPlan.remove("listKeywords", ["a"]);
172163
or using with save function
173164

174165
```dart
175-
dietPlan.setAddAll('listKeywords', ['a','a','d']);
176-
dietPlan.setAddAllUnique('listKeywords', ['a','a','d']);
177-
dietPlan.setRemoveAll('listKeywords', ['a']);
166+
dietPlan.setAdd('listKeywords', ['a','a','d']);
167+
dietPlan.setAddUnique('listKeywords', ['a','a','d']);
168+
dietPlan.setRemove('listKeywords', ['a']);
178169
var response = dietPlan.save()
179170
```
180171

@@ -214,7 +205,7 @@ var queryBuilder = QueryBuilder<DietPlan>(DietPlan())
214205
var response = await queryBuilder.query();
215206
216207
if (response.success) {
217-
print(ApplicationConstants.keyAppName + ": " + ((response.result as List<dynamic>).first as DietPlan).toString());
208+
print(ApplicationConstants.keyAppName + ": " + ((response.results as List<dynamic>).first as DietPlan).toString());
218209
} else {
219210
print(ApplicationConstants.keyAppName + ": " + response.exception.message);
220211
}
@@ -304,11 +295,11 @@ The Parse Server configuration guide on the server is found here https://docs.pa
304295
Initialize the Parse Live Query by entering the parameter liveQueryUrl in Parse().initialize:
305296
```dart
306297
Parse().initialize(
307-
ApplicationConstants.keyApplicationId,
308-
ApplicationConstants.keyParseServerUrl,
309-
clientKey: ApplicationConstants.keyParseClientKey,
298+
keyApplicationId,
299+
keyParseServerUrl,
300+
clientKey: keyParseClientKey,
310301
debug: true,
311-
liveQueryUrl: ApplicationConstants.keyLiveQueryUrl,
302+
liveQueryUrl: keyLiveQueryUrl,
312303
autoSendSessionId: true);
313304
```
314305

@@ -580,21 +571,6 @@ final Map<String, String> params = <String, String>{'plan': 'paid'};
580571
function.execute(parameters: params);
581572
```
582573

583-
## Relation
584-
The SDK supports Relation.
585-
586-
To Retrive a relation instance for user, call:
587-
```dart
588-
final relation = user.getRelation('dietPlans');
589-
```
590-
591-
and then you can add a relation to the passed in object.
592-
593-
```dart
594-
relation.add(dietPlan);
595-
final result = await user.save();
596-
```
597-
598574
## Other Features of this library
599575
Main:
600576
* Installation (View the example application)
@@ -616,6 +592,3 @@ Objects:
616592

617593
## Author:-
618594
This project was authored by Phill Wiggins. You can contact me at phill.wiggins@gmail.com
619-
<!--stackedit_data:
620-
eyJoaXN0b3J5IjpbLTU4MDA4MDUwNCw3MTg2NTA0MjBdfQ==
621-
-->

‎lib/src/base/parse_constants.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const String keyEndPointVerificationEmail = '/verificationEmailRequest';
1515
const String keyEndPointRequestPasswordReset = '/requestPasswordReset';
1616
const String keyEndPointClasses = '/classes/';
1717
const String keyEndPointHealth = '/health';
18+
const String keyEndPointAggregate = '/aggregate/';
1819

1920
// ParseObject variables
2021
const String keyVarClassName = 'className';

‎lib/src/network/parse_query.dart

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,8 @@ class QueryBuilder<T extends ParseObject> {
246246
// Add a constraint to the query that requires a particular key's value match another QueryBuilder
247247
// ignore: always_specify_types
248248
void whereMatchesQuery(String column, QueryBuilder query) {
249-
final String inQuery = query._buildQueryRelational(query.object.parseClassName);
249+
final String inQuery =
250+
query._buildQueryRelational(query.object.parseClassName);
250251

251252
queries.add(MapEntry<String, dynamic>(
252253
_SINGLE_QUERY, '\"$column\":{\"\$inQuery\":$inQuery}'));
@@ -255,7 +256,8 @@ class QueryBuilder<T extends ParseObject> {
255256
//Add a constraint to the query that requires a particular key's value does not match another QueryBuilder
256257
// ignore: always_specify_types
257258
void whereDoesNotMatchQuery(String column, QueryBuilder query) {
258-
final String inQuery = query._buildQueryRelational(query.object.parseClassName);
259+
final String inQuery =
260+
query._buildQueryRelational(query.object.parseClassName);
259261

260262
queries.add(MapEntry<String, dynamic>(
261263
_SINGLE_QUERY, '\"$column\":{\"\$notInQuery\":$inQuery}'));
@@ -268,6 +270,11 @@ class QueryBuilder<T extends ParseObject> {
268270
return object.query(_buildQuery());
269271
}
270272

273+
Future<ParseResponse> distinct(String className) async {
274+
String queryString = "distinct=$className";
275+
return object.distinct(queryString);
276+
}
277+
271278
///Counts the number of objects that match this query
272279
Future<ParseResponse> count() async {
273280
return object.query(_buildQueryCount());

‎lib/src/objects/parse_object.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class ParseObject extends ParseBase implements ParseCloneable {
1212
: super() {
1313
parseClassName = className;
1414
_path = '$keyEndPointClasses$className';
15+
_aggregatepath = '$keyEndPointAggregate$className';
1516

1617
_debug = isDebugEnabled(objectLevelDebug: debug);
1718
_client = client ??
@@ -28,6 +29,7 @@ class ParseObject extends ParseBase implements ParseCloneable {
2829
ParseObject.clone(parseClassName)..fromJson(map);
2930

3031
String _path;
32+
String _aggregatepath;
3133
bool _debug;
3234
ParseHTTPClient _client;
3335

@@ -521,6 +523,17 @@ class ParseObject extends ParseBase implements ParseCloneable {
521523
}
522524
}
523525

526+
Future<ParseResponse> distinct(String query) async {
527+
try {
528+
final Uri url = getSanitisedUri(_client, '$_aggregatepath', query: query);
529+
final Response result = await _client.get(url);
530+
return handleResponse<ParseObject>(
531+
this, result, ParseApiRQ.query, _debug, parseClassName);
532+
} on Exception catch (e) {
533+
return handleException(e, ParseApiRQ.query, _debug, parseClassName);
534+
}
535+
}
536+
524537
/// Deletes the current object locally and online
525538
Future<ParseResponse> delete({String id, String path}) async {
526539
try {

‎lib/src/objects/response/parse_response_builder.dart

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,16 @@ class _ParseResponseBuilder {
9191
response.result = map;
9292
} else if (map != null && map.length == 1 && map.containsKey('results')) {
9393
final List<dynamic> results = map['results'];
94-
final List<T> items = _handleMultipleResults<T>(object, results);
95-
response.results = items;
96-
response.result = items;
97-
response.count = items.length;
94+
if (results[0] is String) {
95+
response.results = results;
96+
response.result = results;
97+
response.count = results.length;
98+
} else {
99+
final List<T> items = _handleMultipleResults<T>(object, results);
100+
response.results = items;
101+
response.result = items;
102+
response.count = items.length;
103+
}
98104
} else if (map != null && map.length == 2 && map.containsKey('count')) {
99105
final List<int> results = <int>[map['count']];
100106
response.results = results;

0 commit comments

Comments
 (0)
Please sign in to comment.