fix orderby

This commit is contained in:
Shams mosowi
2021-04-26 13:07:17 +10:00
parent b45c87036e
commit 63407f5993

View File

@@ -1,16 +1,20 @@
import { db } from "../../firebase";
import Button from "@material-ui/core/Button";
import React, { useEffect, useReducer, useContext,useCallback } from "react";
import React, { useEffect, useReducer, useContext, useCallback } from "react";
import _isEqual from "lodash/isEqual";
import firebase from "firebase/app";
import { FireTableFilter, FiretableOrderBy } from ".";
import { SnackContext } from "contexts/SnackContext";
import { cloudFunction } from "../../firebase/callables";
import { isCollectionGroup, generateSmallerId,missingFieldsReducer } from "utils/fns";
import {projectId} from '../../firebase'
import _findIndex from 'lodash/findIndex';
import _orderBy from 'lodash/orderBy';
import {
isCollectionGroup,
generateSmallerId,
missingFieldsReducer,
} from "utils/fns";
import { projectId } from "../../firebase";
import _findIndex from "lodash/findIndex";
import _orderBy from "lodash/orderBy";
const CAP = 1000; // safety paramter sets the upper limit of number of docs fetched by this hook
const serverTimestamp = firebase.firestore.FieldValue.serverTimestamp;
@@ -18,38 +22,44 @@ const tableReducer = (prevState: any, newProps: any) => {
return { ...prevState, ...newProps };
};
const doc2row =(doc) => {
const doc2row = (doc) => {
const data = doc.data();
const id = doc.id;
const ref = doc.ref;
return { ...data, id, ref };
}
};
const rowsReducer = (prevRows: any, update: any) => {
switch(update.type){
switch (update.type) {
case "onSnapshot":
const localRowsIds = prevRows.map(r=>r.id)// used to remove added docs that were added from this client
const localRowsIds = prevRows.map((r) => r.id); // used to remove added docs that were added from this client
const addedRows = update.changes
.filter(change=>change.type==='added')
.map(change=>doc2row(change.doc))
.filter((row)=>!localRowsIds.includes(row.id))
.filter((change) => change.type === "added")
.map((change) => doc2row(change.doc))
.filter((row) => !localRowsIds.includes(row.id));
const removedRowIds = update.changes
.filter(change=>change.type==='removed')
.map((change)=>change.doc.id)
const _rows = [...addedRows,
...prevRows.filter(row=>!removedRowIds.includes(row.id))]
.filter((change) => change.type === "removed")
.map((change) => change.doc.id);
const _rows = [
...addedRows,
...prevRows.filter((row) => !removedRowIds.includes(row.id)),
];
const modifiedRows = update.changes
.filter(change=>change.type==='modified')
.map(change=>doc2row(change.doc))
modifiedRows.forEach(row=>{
const rowIndex = _findIndex(_rows,(r=>r.id===row.id))
_rows[rowIndex] = row
})
return _orderBy(_rows,['id'],['asc'])
case "delete":return prevRows.splice(update.rowIndex, 1);
case "set":return update.rows
case "add":return [update.newRow,...prevRows]
.filter((change) => change.type === "modified")
.map((change) => doc2row(change.doc));
modifiedRows.forEach((row) => {
const rowIndex = _findIndex(_rows, (r) => r.id === row.id);
_rows[rowIndex] = row;
});
return _rows;
case "delete":
return prevRows.splice(update.rowIndex, 1);
case "set":
return update.rows;
case "add":
return [update.newRow, ...prevRows];
case "queryChange":
return [];
}
};
const tableInitialState = {
@@ -72,7 +82,7 @@ const useTable = (initialOverrides: any) => {
...tableInitialState,
...initialOverrides,
});
const [rows,rowsDispatch] = useReducer(rowsReducer,[])
const [rows, rowsDispatch] = useReducer(rowsReducer, []);
/** set collection listener
* @param filters
@@ -93,6 +103,13 @@ const useTable = (initialOverrides: any) => {
tableState.unsubscribe();
}
//updates previous values
if (
tableState.prevFilters !== tableState.filters ||
tableState.prevOrderBy !== tableState.orderBy ||
tableState.prevPath !== tableState.path
) {
rowsDispatch({ type: "queryChange" });
}
tableDispatch({
prevFilters: filters,
prevLimit: limit,
@@ -118,12 +135,12 @@ const useTable = (initialOverrides: any) => {
const unsubscribe = query.limit(limit).onSnapshot(
(snapshot) => {
if (snapshot.docs.length > 0) {
const changes = snapshot.docChanges()
rowsDispatch({type:'onSnapshot',changes})
const changes = snapshot.docChanges();
rowsDispatch({ type: "onSnapshot", changes });
}
tableDispatch({
loading: false,
});
tableDispatch({
loading: false,
});
},
(error: any) => {
//TODO:callable to create new index
@@ -220,7 +237,7 @@ const useTable = (initialOverrides: any) => {
*/
const deleteRow = (rowIndex: number, documentId: string) => {
//remove row locally
rowsDispatch({type:"delete", rowIndex})
rowsDispatch({ type: "delete", rowIndex });
// delete document
try {
db.collection(tableState.path).doc(documentId).delete();
@@ -259,54 +276,65 @@ const useTable = (initialOverrides: any) => {
/** creating new document/row
* @param data(optional: default will create empty row)
*/
const addRow = async (data: any,requiredFields:string[]) => {
const missingRequiredFields = requiredFields ? requiredFields.reduce(missingFieldsReducer(data), []):[];
const addRow = async (data: any, requiredFields: string[]) => {
const missingRequiredFields = requiredFields
? requiredFields.reduce(missingFieldsReducer(data), [])
: [];
const valuesFromFilter = tableState.filters.reduce(filterReducer, {});
const { path } = tableState;
const newId = generateSmallerId(rows[0]?.id??'zzzzzzzzzzzzzzzzzzzzzzzz');
const newId = generateSmallerId(rows[0]?.id ?? "zzzzzzzzzzzzzzzzzzzzzzzz");
const docData = {
...valuesFromFilter,
_ft_createdAt: serverTimestamp(),
_ft_updatedAt: serverTimestamp(),
...data,
};
if (missingRequiredFields.length===0){
try {
if (missingRequiredFields.length === 0) {
try {
await db.collection(path).doc(newId).set(docData, { merge: true });
} catch (error) {
if (error.code === "permission-denied") {
snack.open({
variant: "error",
message: "You don't have permissions to add a new row",
duration: 3000,
position: { vertical: "top", horizontal: "center" },
});
} catch (error) {
if (error.code === "permission-denied") {
snack.open({
variant: "error",
message: "You don't have permissions to add a new row",
duration: 3000,
position: { vertical: "top", horizontal: "center" },
});
}
}
} else {
// missing required fields
const id = newId;
const ref = db.collection(path).doc(newId);
const newRow = {
...data,
id,
ref,
_ft_missingRequiredFields: missingRequiredFields,
};
rowsDispatch({ type: "add", newRow });
}
}else{
// missing required fields
const id = newId ;
const ref = db.collection(path).doc(newId)
const newRow = { ...data, id, ref,_ft_missingRequiredFields: missingRequiredFields};
rowsDispatch({type: "add",newRow})
}
};
const options = {merge: true}
const updateRow = (rowRef,update,onSuccess,onError)=>{
const rowIndex = _findIndex(rows,{id:rowRef.id})
const row = rows[rowIndex]
const {ref,id,_ft_missingRequiredFields,...rowData} = row
const _rows =[...rows]
_rows[rowIndex] = {...row,...update}
const missingRequiredFields = _ft_missingRequiredFields?_ft_missingRequiredFields.reduce(missingFieldsReducer(_rows[rowIndex]), []):[]
if(missingRequiredFields.length === 0){
ref.set({...rowData,...update},options).then(onSuccess,onError)
delete _rows[rowIndex]._ft_missingRequiredFields
const options = { merge: true };
const updateRow = (rowRef, update, onSuccess, onError) => {
const rowIndex = _findIndex(rows, { id: rowRef.id });
const row = rows[rowIndex];
const { ref, id, _ft_missingRequiredFields, ...rowData } = row;
const _rows = [...rows];
_rows[rowIndex] = { ...row, ...update };
const missingRequiredFields = _ft_missingRequiredFields
? _ft_missingRequiredFields.reduce(
missingFieldsReducer(_rows[rowIndex]),
[]
)
: [];
if (missingRequiredFields.length === 0) {
ref.set({ ...rowData, ...update }, options).then(onSuccess, onError);
delete _rows[rowIndex]._ft_missingRequiredFields;
}
rowsDispatch({ type:"set",rows: _rows });
}
rowsDispatch({ type: "set", rows: _rows });
};
/** used for incrementing the number of rows fetched
* @param additionalRows number additional rows to be fetched (optional: default is 150)
@@ -331,7 +359,14 @@ const useTable = (initialOverrides: any) => {
moreRows,
dispatch: tableDispatch,
};
return [{...tableState,rows}, tableActions];
const orderedRows = tableState.orderBy?.[0]
? _orderBy(
rows,
[tableState.orderBy[0].key],
[tableState.orderBy[0].direction]
)
: _orderBy(rows, ["id"], ["asc"]);
return [{ ...tableState, rows: orderedRows }, tableActions];
};
export default useTable;