Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use native sorting, filtering and paging, allow get query #5

Draft
wants to merge 19 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,6 @@
"react": "16.9.0",
"react-admin": "^2.9.6",
"react-dom": "^16.9.0",
"sort-by": "^1.2.0"
"ra-realtime": "^2.8.6"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! Did not know this exists!

}
}
35 changes: 35 additions & 0 deletions src/lib/createRealtimeSaga.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import realtimeSaga from 'ra-realtime';
import { SnapshotFlag } from './methods.js';

const observeRequest = dataProvider => (type, resource, params) => {

return {
subscribe(observer) {

params[SnapshotFlag] = true;

const query = dataProvider(type, resource, params);
const cancelSnapshots = query.onSnapshot(
snaphot => {
observer.next(snapshot.docs)// New data received, notify the observer
},
error => {
observer.error(error)); // Ouch, an error occured, notify the observer
}
)

const subscription = {
unsubscribe() {
// Clean up after ourselves
cancelSnapshots();
// Notify the saga that we cleaned up everything
observer.complete();
}
};

return subscription;
},
};
};

export default dataProvider => realtimeSaga(observeRequest(dataProvider));
70 changes: 36 additions & 34 deletions src/lib/methods.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import firebase from 'firebase/app';
import 'firebase/firestore';
import 'firebase/storage';
import sortBy from 'sort-by';
import { CREATE } from 'react-admin';

const SnapshotFlag = Symbol('snapshot');

export SnapshotFlag;

const convertFileToBase64 = file =>
new Promise((resolve, reject) => {
const reader = new FileReader();
Expand Down Expand Up @@ -167,11 +170,15 @@ const getItemID = (params, type, resourceName, resourcePath, resourceData) => {

const getOne = async (params, resourceName, resourceData) => {
if (params.id) {
let result = await firebase

const query = firebase
.firestore()
.collection(resourceName)
.doc(params.id)
.get();
.doc(params.id);

if (params[SnapshotFlag]) return query;

const result = await query.get();

if (result.exists) {
const data = result.data();
Expand All @@ -198,10 +205,20 @@ const getOne = async (params, resourceName, resourceData) => {
const getList = async (params, resourceName, resourceData) => {
if (params.pagination) {
let values = [];
let snapshots = await firebase
.firestore()
.collection(resourceName)
.get();

const query = firebase
.firestore()
.collection(resourceName)
.limit(params.pagination.perPage)
.offset(params.pagination.perPage * params.pagination.page);

if (params.sort) query.orderBy(params.sort.field, params.sort.order.toLower())

Object.keys(params.filter).forEach(field => {query.where(field, '==', params.filter[field])})

if (params[SnapshotFlag]) return query;

let snapshots = await query.get()

for (const snapshot of snapshots.docs) {
const data = snapshot.data();
Expand All @@ -211,40 +228,25 @@ const getList = async (params, resourceName, resourceData) => {
values.push(data);
}

if (params.filter) {
values = values.filter(item => {
let meetsFilters = true;
for (const key of Object.keys(params.filter)) {
meetsFilters = item[key] === params.filter[key];
}
return meetsFilters;
});
}

if (params.sort) {
values.sort(sortBy(`${params.sort.order === 'ASC' ? '-' : ''}${params.sort.field}`));
}

const keys = values.map(i => i.id);
const { page, perPage } = params.pagination;
const _start = (page - 1) * perPage;
const _end = page * perPage;
const data = values ? values.slice(_start, _end) : [];
const ids = keys.slice(_start, _end) || [];
const total = values ? values.length : 0;
return { data, ids, total };

return { values, keys, values.length };
} else {
throw new Error('Error processing request');
}
};

const getMany = async (params, resourceName, resourceData) => {
let data = [];
/* eslint-disable no-await-in-loop */
for (const id of params.ids) {
let { data: item } = await getOne({ id }, resourceName, resourceData);
data.push(item);
}

const firestore = firabase.firestore()

const snapshot = await firestore.getAll(...params.ids.map(id => {firestore.collection(resourceName).doc(id)}))

if (params[SnapshotFlag]) return snapshot;

snapshot.forEach(docRef => {data.push(docRef.data())})

return { data };
};

Expand Down