mirror of
https://github.com/rowyio/rowy.git
synced 2025-12-29 00:16:39 +01:00
168 lines
4.9 KiB
TypeScript
168 lines
4.9 KiB
TypeScript
import { useEffect } from "react";
|
|
import { useDebouncedCallback } from "use-debounce";
|
|
import _camelCase from "lodash/camelCase";
|
|
|
|
import _sortBy from "lodash/sortBy";
|
|
|
|
import useDoc, { DocActions } from "../useDoc";
|
|
import { FieldType } from "constants/fields";
|
|
import { arrayMover, formatPath } from "../../utils/fns";
|
|
import { db, deleteField } from "../../firebase";
|
|
|
|
export type ColumnConfig = {
|
|
fieldName: string;
|
|
key: string;
|
|
name: string;
|
|
type: FieldType;
|
|
index: number;
|
|
width?: number;
|
|
editable?: boolean;
|
|
config: { [key: string]: any };
|
|
[key: string]: any;
|
|
};
|
|
|
|
const useTableConfig = (tablePath?: string) => {
|
|
const [tableConfigState, documentDispatch] = useDoc({
|
|
path: tablePath ? formatPath(tablePath) : "",
|
|
});
|
|
|
|
useEffect(() => {
|
|
const { doc, columns, rowHeight } = tableConfigState;
|
|
// TODO: REMOVE THIS
|
|
// Copy columns, rowHeight to tableConfigState
|
|
if (doc && columns !== doc.columns) {
|
|
documentDispatch({ columns: doc.columns });
|
|
}
|
|
if (doc && rowHeight !== doc.rowHeight) {
|
|
documentDispatch({ rowHeight: doc.rowHeight });
|
|
}
|
|
}, [tableConfigState.doc]);
|
|
/** used for specifying the table in use
|
|
* @param table firestore collection path
|
|
*/
|
|
const setTable = (table: string) => {
|
|
documentDispatch({
|
|
path: formatPath(table),
|
|
columns: [],
|
|
doc: null,
|
|
ref: db.doc(formatPath(table)),
|
|
loading: true,
|
|
});
|
|
};
|
|
/** used for creating a new column
|
|
* @param name of column.
|
|
* @param type of column
|
|
* @param data additional column properties
|
|
*/
|
|
const addColumn = (name: string, type: FieldType, data?: any) => {
|
|
//TODO: validation
|
|
const { columns } = tableConfigState;
|
|
const newIndex = Object.keys(columns).length ?? 0;
|
|
let updatedColumns = { ...columns };
|
|
const key = _camelCase(name);
|
|
updatedColumns[key] = { name, key, type, ...data, index: newIndex ?? 0 };
|
|
documentDispatch({
|
|
action: DocActions.update,
|
|
data: { columns: updatedColumns },
|
|
});
|
|
};
|
|
|
|
/** used for updating the width of column
|
|
* @param index of column.
|
|
* @param width number of pixels, eg: 120
|
|
*/
|
|
const [resize] = useDebouncedCallback((index: number, width: number) => {
|
|
const { columns } = tableConfigState;
|
|
const numberOfFixedColumns = Object.values(columns).filter(
|
|
(col: any) => col.fixed && !col.hidden
|
|
).length;
|
|
const columnsArray = _sortBy(
|
|
Object.values(columns).filter((col: any) => !col.hidden && !col.fixed),
|
|
"index"
|
|
);
|
|
let column: any = columnsArray[index - numberOfFixedColumns];
|
|
column.width = width;
|
|
let updatedColumns = columns;
|
|
updatedColumns[column.key] = column;
|
|
documentDispatch({
|
|
action: DocActions.update,
|
|
data: { columns: updatedColumns },
|
|
});
|
|
}, 1000);
|
|
// type updatable = { field: string; value: unknown };
|
|
|
|
/** used for updating column properties such as type,name etc.
|
|
* @param index of column.
|
|
* @param {updatable[]} updatables properties to be updated
|
|
*/
|
|
const updateColumn = (key: string, updates: any) => {
|
|
const { columns } = tableConfigState;
|
|
|
|
const updatedColumns = {
|
|
...columns,
|
|
[key]: { ...columns[key], ...updates },
|
|
};
|
|
|
|
documentDispatch({
|
|
action: DocActions.update,
|
|
data: { columns: updatedColumns },
|
|
});
|
|
};
|
|
/** remove column by index
|
|
* @param index of column.
|
|
*/
|
|
const remove = (key: string) => {
|
|
const { columns } = tableConfigState;
|
|
let updatedColumns = columns;
|
|
updatedColumns[key] = deleteField();
|
|
documentDispatch({
|
|
action: DocActions.update,
|
|
data: { columns: updatedColumns },
|
|
});
|
|
};
|
|
/** reorder columns by key
|
|
* @param draggedColumnKey column being repositioned.
|
|
* @param droppedColumnKey column being .
|
|
*/
|
|
const reorder = (draggedColumnKey: string, droppedColumnKey: string) => {
|
|
const { columns } = tableConfigState;
|
|
const oldIndex = columns[draggedColumnKey].index;
|
|
const newIndex = columns[droppedColumnKey].index;
|
|
const columnsArray = _sortBy(Object.values(columns), "index");
|
|
arrayMover(columnsArray, oldIndex, newIndex);
|
|
let updatedColumns = columns;
|
|
|
|
columnsArray
|
|
.filter((c) => c) // arrayMover has a bug creating undefined items
|
|
.forEach((column: any, index) => {
|
|
updatedColumns[column.key] = { ...column, index };
|
|
});
|
|
documentDispatch({
|
|
action: DocActions.update,
|
|
data: { columns: updatedColumns },
|
|
});
|
|
};
|
|
/** changing table configuration used for things such as row height
|
|
* @param key name of parameter eg. rowHeight
|
|
* @param value new value eg. 65
|
|
*/
|
|
const updateConfig = (key: string, value: unknown) => {
|
|
documentDispatch({
|
|
action: DocActions.update,
|
|
data: { [key]: value },
|
|
});
|
|
};
|
|
const actions = {
|
|
updateColumn,
|
|
updateConfig,
|
|
addColumn,
|
|
resize,
|
|
setTable,
|
|
remove,
|
|
reorder,
|
|
};
|
|
return [tableConfigState, actions];
|
|
};
|
|
|
|
export default useTableConfig;
|