From 06fc0e8c18a5fe02ca1bd3409114c76e7a12e9ef Mon Sep 17 00:00:00 2001 From: shams mosowi Date: Mon, 23 Sep 2019 14:45:15 +1000 Subject: [PATCH] create columns,column settings flags toggles setup --- ROADMAP.md | 15 +-- src/components/Fields/Rating.tsx | 4 +- src/components/Fields/index.tsx | 30 +++++ src/components/Table/HeaderPopper.tsx | 145 ++++++++++++++++++----- src/components/Table/index.tsx | 28 ++++- src/hooks/useFiretable/useTableConfig.ts | 5 +- 6 files changed, 180 insertions(+), 47 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index bdbefea1..5b3b556b 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -18,7 +18,7 @@ - Create columns (fields) ✅ - Create rows(documents) ✅ - Edit cells ✅ -- Authenicate ✅ +- Authenticate ✅ - Delete rows ✅ ## MVP @@ -27,12 +27,12 @@ - single select(string) - [https://material-ui.com/components/chips/#chip-array] Multiple select(array of strings) -- date(Firebase timestamp) -- time(Firebase timestamp) +- date(Firebase timestamp)✅ +- time(Firebase timestamp)✅ - file(firebase storage url string) - image(firebase storage url string) -- single select reference(DocRefrence) -- mulit select reference(DocRefrence) +- single select reference(DocReference) +- multi select reference(DocReference) - rating ✅ ### Functionality: @@ -44,10 +44,11 @@ - Edit tables - Hide tables - Fixed column +- resizable column ✅ - keyboard Navigation: - Up key to move to the cell above ✅ - Down key to move to the cell bellow, if last cell create a new row ✅ - - Tab to go to the next cell + - Tab to go to the next cell ✅ - column / table Create/edit validation ## V1 @@ -64,7 +65,7 @@ - Sort rows - Locked columns - Table view only mode -- Subcollection tables +- SubCollection tables - Permissions - Duplicate columns - Filters: diff --git a/src/components/Fields/Rating.tsx b/src/components/Fields/Rating.tsx index 202bb5b7..8d5f9bb3 100644 --- a/src/components/Fields/Rating.tsx +++ b/src/components/Fields/Rating.tsx @@ -4,13 +4,13 @@ import MuiRating from "@material-ui/lab/Rating"; // TODO: Create an interface for props interface Props { - value: number | null; + value: number; row: any; onSubmit: Function; - //fieldType: FieldType; } const Rating = (props: Props) => { const { value, row, onSubmit } = props; + return ( { return find(propEq("type", type))(FIELDS).icon; }; + +export const isFieldType = (fieldType: any) => { + const fieldTypes = FIELDS.map(field => field.type); + return fieldTypes.includes(fieldType); +}; + +export const FieldsDropDown = (value: FieldType | null, onChange: any) => { + return ( + + ); +}; diff --git a/src/components/Table/HeaderPopper.tsx b/src/components/Table/HeaderPopper.tsx index c2b2334d..4b6b3f24 100644 --- a/src/components/Table/HeaderPopper.tsx +++ b/src/components/Table/HeaderPopper.tsx @@ -1,22 +1,33 @@ -import React from "react"; +import React, { useEffect } from "react"; import Button from "@material-ui/core/Button"; import Typography from "@material-ui/core/Typography"; import InputLabel from "@material-ui/core/InputLabel"; import MenuItem from "@material-ui/core/MenuItem"; import FormHelperText from "@material-ui/core/FormHelperText"; import FormControl from "@material-ui/core/FormControl"; -import Select from "@material-ui/core/Select"; + import Popper from "@material-ui/core/Popper"; import Fade from "@material-ui/core/Fade"; import Paper from "@material-ui/core/Paper"; import ClickAwayListener from "@material-ui/core/ClickAwayListener"; -import { createStyles, Theme, makeStyles } from "@material-ui/core/styles"; +import { createStyles, makeStyles } from "@material-ui/core/styles"; import { TextField, Grid } from "@material-ui/core"; -import { FIELDS } from "../Fields"; +import { FieldsDropDown, isFieldType } from "../Fields"; +import ToggleButton from "@material-ui/lab/ToggleButton"; +import ToggleButtonGroup from "@material-ui/lab/ToggleButtonGroup"; + +import LockIcon from "@material-ui/icons/Lock"; +import LockOpenIcon from "@material-ui/icons/LockOpen"; +import VisibilityIcon from "@material-ui/icons/Visibility"; +import VisibilityOffIcon from "@material-ui/icons/VisibilityOff"; +import FormatItalicIcon from "@material-ui/icons/FormatItalic"; +import FormatUnderlinedIcon from "@material-ui/icons/FormatUnderlined"; +import FormatColorFillIcon from "@material-ui/icons/FormatColorFill"; + const useStyles = makeStyles(Theme => createStyles({ container: { - padding: 10, + padding: 15, }, typography: { padding: 1, @@ -41,17 +52,29 @@ const useStyles = makeStyles(Theme => selectEmpty: { marginTop: Theme.spacing(2), }, + toggleGrouped: { + margin: Theme.spacing(0.5), + border: "none", + padding: Theme.spacing(0, 1), + "&:not(:first-child)": { + borderRadius: Theme.shape.borderRadius, + }, + "&:first-child": { + borderRadius: Theme.shape.borderRadius, + }, + }, }) ); + const HeaderPopper = (props: any) => { - const { anchorEl, column, handleClose } = props; - console.log(column); + const { anchorEl, column, handleClose, actions } = props; const [values, setValues] = React.useState({ - age: "", - name: "hai", + type: null, + name: "", }); - console.log(props); + const [flags, setFlags] = React.useState(() => [""]); const classes = useStyles(); + function handleChange( event: React.ChangeEvent<{ name?: string; value: unknown }> ) { @@ -60,10 +83,45 @@ const HeaderPopper = (props: any) => { [event.target.name as string]: event.target.value, })); } - console.log(column); + const setValue = (key: string, value: any) => { + setValues(oldValues => ({ + ...oldValues, + [key]: value, + })); + }; + + useEffect(() => { + if (column && !column.isNew) + setValues(oldValues => ({ + ...oldValues, + name: column.name, + type: column.type, + key: column.key, + isNew: column.isNew, + })); + }, [column]); + const onClickAway = (event: any) => { + const dropDownClicked = isFieldType(event.target.dataset.value); + if (!dropDownClicked) { + handleClose(); + } + }; + const handleToggle = ( + event: React.MouseEvent, + newFlags: string[] + ) => { + setFlags(newFlags); + }; + + const createNewColumn = () => { + const { name, type } = values; + actions.add(name, type); + handleClose(); + }; + if (column) { return ( - + { - + + + {flags.includes("editable") ? ( + + ) : ( + + )} + + + {flags.includes("visible") ? ( + + ) : ( + + )} + + + + + + + + + + { + setValue("name", e.target.value); + }} + /> + - Field Type - - + Field Type + {FieldsDropDown(values.type, handleChange)} + {column.isNew && ( + + )} diff --git a/src/components/Table/index.tsx b/src/components/Table/index.tsx index 27dfc86f..a7d9f661 100644 --- a/src/components/Table/index.tsx +++ b/src/components/Table/index.tsx @@ -67,7 +67,13 @@ const formatter = (fieldType: FieldType, key: string) => { return DateFormatter(key, fieldType); case FieldType.rating: return (props: any) => { - return ; + return ( + + ); }; case FieldType.checkBox: return (props: any) => { @@ -112,23 +118,31 @@ function Table(props: any) { console.log(args); }; const headerRenderer = (props: any) => { - switch (props.column.key) { + const { column } = props; + switch (column.key) { case "new": return ( - +
+ +
); default: return (
); @@ -148,6 +162,7 @@ function Table(props: any) { ...column, })); columns.push({ + isNew: true, key: "new", name: "Add column", width: 160, @@ -174,6 +189,7 @@ function Table(props: any) { handleClose={handleCloseHeader} anchorEl={anchorEl} column={header && header.column} + actions={tableActions.column} /> ); diff --git a/src/hooks/useFiretable/useTableConfig.ts b/src/hooks/useFiretable/useTableConfig.ts index 070d0651..3bc35de1 100644 --- a/src/hooks/useFiretable/useTableConfig.ts +++ b/src/hooks/useFiretable/useTableConfig.ts @@ -1,6 +1,7 @@ import { useEffect } from "react"; import useDoc, { DocActions } from "../useDoc"; import { FieldType } from "../../components/Fields"; +import _camelCase from "lodash/camelCase"; const useTableConfig = (tablePath: string) => { const [tableConfigState, documentDispatch] = useDoc({ path: `${tablePath}/_FIRETABLE_`, @@ -14,8 +15,10 @@ const useTableConfig = (tablePath: string) => { const setTable = (table: string) => { documentDispatch({ path: `${table}/_FIRETABLE_`, columns: [], doc: null }); }; - const add = (name: string, key: string, type: FieldType) => { + const add = (name: string, type: FieldType) => { + //TODO: validation const { columns } = tableConfigState; + const key = _camelCase(name); documentDispatch({ action: DocActions.update, data: { columns: [...columns, { name, key, type }] },