mirror of
https://github.com/rowyio/rowy.git
synced 2026-05-18 13:15:50 +02:00
fix orderby
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user