Giter Club home page Giter Club logo

gigagrid's People

Contributors

ankita-parekh avatar ankitaparekh avatar caguthrie avatar erfangc avatar erfangchen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

gigagrid's Issues

Alternative sort algorithm

How can I use a special sort function (not lexicographical) on one column, so that when the user clicks on the header of that column, it gets sorted accordingly to that function?
I tried to use customSortFn but it does not seem to be used when clicking on the header.

Add support for horizontal scrolling

Right now we restrict the canvas size to the viewport (or component parent) size

We should allow the actual canvas to be bigger should the user specify long columns or there are many columns. Enable scrollX when that happens.

Progressive data rendering (infinitely scrolling) Feature

Similar to ReactTable, we want the ability to perform infinitely scrolling on the data, i.e. load data as the user scrolls through it.

This will need to be implemented carefully. the last iteration with ReactTable produced counter intuitive scrollbar behaviors.

In this implementation, we should make sure the scrollbar is scaled correctly for the data in the table from the beginning. i.e. the scrollbar should be as tall as there are data in the rasterized tree (even if those data is un-rendered)

Similar to the react-data-grid project, I propose we use placeholder unstyled cells to represent unloaded cells. This will stretch the body down and automatically scale the scrollbar.

Column Grouping in GigaGrid

We should leverage tr > th[col-span] features of the HTML table spec and allow users to decorate column headers with additional layers of headers

we need to decide on the input format we would accept from the user and then just render them as additional tr in the header with the appropriate col-spans

Editable Cells in GigaTable

Similar to some of the other table options out there, we should provide users with the option to edit cells natively in the table.

Cell edit actions will trigger some user defined callback (if provided) and if the return value from the callback is true we proceed to update the cell and re-render the table.

it might be wise to keep the original data immutable and simply add the edits in a mask layer.

The mask layer can consequently be implemented as a stack to allow undos ... or we don't have to be that complicated

add optional locale to formatInstruction

We should add a locale key to formatInstruction so in the format() function, a number would be formatted per an optional locale. I will raise an appropriate PR.

Use the `width` property of `ColumnDef` to size columns instead of jQuery

@caguthrie your recent upgrade from table to DIV has made a lot of behaviors possible

to give ourselves more performant table do you think it is a good idea to leverage the width property of ColumnDef instead of assigning a dynamic CSS, which requires manual jQuery action?

The way it would work

  • we allow users to specify exactly how width each column ought to be via size on ColumnDef
  • if no size is specified it is set to w% where w = 1 / visibleColumns.length
  • turn overflow on the cells to hidden, to ensure alignment across rows

Theoretical justification

A column's width is a state that dictates how wide each column is. We already have this width property in GigaGrid.

This view fits into the prop/state driven view of React ... the render() function of the main component under this proposal would still be a pure function of its props/state and we can render everything in 1 cycle - thus improving performance

If we ever need to reason about how wide columns ought to be, we avoid having to deal with direct DOM manipulation in our logic

How do we see hidden content

It is my belief that if a user wants to see overflowing content in a cell, they will intuitively want to drag a handle

At which point, a drag action on cell borders is an action to change its width ... so we dispatch that action, and the entire app re-renders ... all very 'React-isc' without resorting to complicated lifecycle methods and direct DOM manipulation

please let me know what you think!

Make GigaGrid an Immutable object somehow

There are two benefits

1 - we no longer need to override ReduceStore's isEqual() method b/c Immutable objects can be compared by reference to test equality

2 - we avoid manually copying parts of the state that were not changed in an action, e.g. we avoid

handleXAction(state, action) {
    return {
        p1: state.p1
        p12: state.p2 // needlessly copying reference
        ...
        pNew: action.pNew
    }
}

See: Immutable.js

Column Group does not work given all these new feature updates

th with colspan does not appear to play nicely with custom width during column sync

further more, we need to consider how to re-adjust column groups when leaf level columns can be removed from state.columns due to subtotaling and other factors ...

Decide on the Child -> Parent event paradigm

A Important Design Decision We Must Make

How should child components (i.e. Row) communicate user triggered events to parent Components (the table)?

There are two approaches that I can see (and are suggested by Facebook)

  • An event system exogenous of React, Here are some examples Small JS Event Emitter or js-signal there are probably more popular options that I have not come across
  • Attach callbacks as properties on the child component. The parent provide the callback and attach them to the child during construction. ex:
// parent.render()
<Child onCellClick={e=>this.onCellClick(e)} />

// child,render()
<td onClick={this.props.onCellClick} />

Would the assignee of this issue please research and enumerate the pros/cons of either approach or suggest the alternative?

Trigger resize of table on window resize

We have the ability to detect container width per #7, but once the component has been rendered and the user change the viewport dimension, we are not updating bodyWidth. This behavior should be addressed (and optionally turned off in props).

Move Rasterization into the Flux store GigaStore

TreeRasterizer.rasterizeTree() is being called effective from render() which means we are rasterizing each time the table is updated.

This might not be a good thing if we frequently make updates to the table state that does not require full rasterization of the tree (such as scrolling).

Therefore, it is best if we put this logic into GigaStore. the various action handlers will decide if re-rasterization is necessary.

Dropdown Menu and Submenu z-index

It appears sub menus have the same z-index as their parent, which is a problem when they overlap

we should write some code to detect parent z-index and stay 1 above it using something like

ReactDOM.findDOMNode(this).parentElement

Add FormatInstructions

We need to know how to format generic cells (especially numeric or currency / date)

This should be a property of ColumnDef

i.e.

columnDef: ColumnDef = {
    formatInstructions: {
        roundTo: 2, // round decimal to
        multiplier: 100 // multiple cell value by this constant
        separator: true // enable "," separator for long numbers, i.e. 1,000,000
    }

}

Add Exporting Functionality

We should create a WYSIWYG style XLS exports using rich table formatting

Since XLS accept in-line table styles and we already have the the table markup, this shouldn't be monumentally difficult. (we can build off rasterized data like we did in ReactTable)

Create lib folder with source files for building with technologies such as webpack

Current version in npm only has a file in the dist/ folder which includes dependancies such as jQuery. Let's have package.json point to a lib/index.ts file which would be the untry point for loading this when using things like webpack. This will solve potentially duplicating dependancies by a developer and reduce bundled file size

Numerical bucket Subtotal

Subtotal only works for String columns not for Number columns

We want the same behavior as ReactTable, i.e. to allow users to specify the buckets to bucket Number fields by

ex:
User enters: 1,2,3,4,5,6

Then rows are bucketed accordingly

Re-sizable columns

Add a resize handle to each column header (not column group headers ... that sounds complicated)

As the user drag this handle, the column header automatically resizes (i.e. pushing or pull the adjacent column to make itself fit)

Once the drag stops, we re-render the table with the new width so all the cell's width update as well

React exposes almost all DOM events and I have had some success with resizable widgets in the past. This should not be the most difficult.

Prevent column width from getting too small

We are computing column width based on container width for now, OR optionally taking explicit width set by the user. However, when either of these values becomes smaller than the elements in the headers, the table can look quite ridiculous.

I propose a way to derive the correct min-width on each column using rem units.

Create a Getting Started Page

Similar to most other Javascript or style plugins, we need to let the users know how to use this widget in various environments and run time setups

I will include this in the examples page for now, which we will evolve into the github.io page

Handle Cell/Row select

Replicate the cell/row select feature from ReactTable

activate callback when these events happen

we should dispatch a row select or cell select event to the store. the store will invoke the proper externally provided callback

Create a npm registry

We need to create a script to publish the distribution files to npm

and write the d.ts if necessary

Add Filter Feature

Replicate the Filtering feature from ReactTable

  • as a dropdown menu on the table headers
  • understand column data format (string vs. number)
  • the dropdown menu item is to dispatch a filter event
  • GigaStore will process the event and update the tree
    • update to the tree will consist of a boolean flag on the Rows in the tree

Determine column width automatically if not passed in by the user

@caguthrie and I discussed offline today,

the best way to achieve Fixed Header scrolling effect is to render 2 tables and control cell width and height explicitly

however, if the user does not provide column width explicitly, we should derive it in an intelligent manner

here is the decision tree / pseudo logic I propose

if (user_provide_explicit_column_width)
    table_width = sum(column_width)
if (user_provide_table_width && no_explicit_column_width)
   column_width = table_width / num_columns; // equalize column width
if (user_provide_neither)
   table_width = parent_width; // determined in componentDidMount()
   column_width = table_width / num_columns; // equalize column width

Server Side Aggregation and Progressive Data Loading

Mission

Create an StoreFactory that produces a Flux store which delegates state management to a series of Server End Points instead of the client. This allow us to navigate arbitrarily deep graphs without resorting to loading all of that data upfront, which can accumulate to become tens of megabytes.

Client Side

The new StoreFactory must produce a flux store such that for every flux action, there is an appropriate handler to mutate the grid's state. Some of these handlers will fully delegate to server end end points. (sorting becomes tricky, and might still have to be done client-side)

Note StoreFactory is truly a factory, not a store! it will produce a store

The StoreFactory should take as inputs:

  • Server URL to get the initial Tree (collapsed, subtotaled and sorted)
    1. This initial server end point should accept columnDefs so it may know how to aggregate and sort
    2. A URL template - to be resolved on each uncollapse action. the template should have variables that will be substituted by the sector path of the node being expanded
      • i.e. /GET /server-tree/expand?sectorPath={colTag}:{value},{colTag2}:{value}
    3. Note - for Node's who's children are already loaded - the old logic of collapse/expand should apply

The ServerStore instance should provide access to a async action creator (i.e. a higher-order function returns a function which dispatches two-actions instead of a single action) to handle what is now known as TOGGLE_COLLAPSE events.

The first action in this async action creator should be to market the node dispatching the action as loading. This action creator then promptly makes an Ajax call to the server URL to fetch additional data

The second action should dispatch an action that will mutate the Tree in the ServerStore. This mean's the store must learn to handle this new action type and call TreeRasterizer as appropriate.

Server Side

The server must satisfy the following contract:

  • for every call that fetches more row
    1. the returned data array must match the shape of DetailRow or SubtotalRow (or some using some static, predefined schema)
    2. any subtotal row must be already aggregated - i.e. SubtotalAggregator should NEVER be used by GigaGrid if the underlying flux store is a Server Store

Use `div` or `span` instead of `tr th | td`

Most recent experiments revealed that td do not play nice with height/width + overflow to strictly enforce these CSS properties at render time we have to not use td

second, we need to make rowHeight a prop to allow maximum flexibility. Once we make rowHeight user-defined (with default fallback to 35px) we have to enforce it in the table. This is probably also easier with div and span than td

onRowExpand

I'm using GigaGrid inside a tab component and also I update it with live data.
Therefore when the user expands a rows group clicking on the (+) icon, I need to know it, so that when the user goes to a different tab and then comes back to the original one he finds the grid with the same groups expanded as before.

GigaGrid has the property initiallyExpandedSubtotalRows, with it I can tell the grid that a list of row groups must be expanded to show the rows contained in them.
But I would neeed a property "onRowExpand", similar to onRowClick, so that when the user expands a rows group I can keep track of it and later call initiallyExpandedSubtotalRows on that row group.

Is it possible to have it?

Re-organize TestUtils

I created TestUtils.ts to serve mock/sample data for testing purposes

This class has grown big due to the new test cases written. We need to organize it so it does not confuse devs in the future

Write the API Documentation

It should be easy given we are using TypeScript and can just take the main Props interface as our public API

However, it is worth noting that there should be ways to automatically generate documentation and it might be good to explore those ...

Create re-orderable draggable columns

In addition to Resizable columns, it would really cool if the user can simply drag a column from one position to another by simply dragging the column header itself. This allow the user to reconfigure the column at will.

The entire header should be the draggable handle. The drag event simply mutates the index of the dragged column in the columns array.

note columns is not a state now! we may have to make it a state.

Subtotal By / Sort By etc Submenu Not Wide Enough

Text wraps as a result which looks counter-intuitive for a menu ... we should make these submenus or menus expand to be as big as the longest single-line item

Explore using various CSS techniques

Consolidate webpack (npm) and jspm dependencies

For targeting UMD and without bundling React itself, we use webpack

However, for webpack to work, we had to install the same jspm dependencies in npm under node_modules. I believe we can write the webpack.config.js file to smartly read package.json > jspm > dependencies and populate the resolve section on an automated basis

This would eliminate the need to keep track of two sets of dependencies

Create a Module System for Loading Source Code into the Browser for DEV

Consider using systemjs to load files into the browser when testing. This could save us from tediously having to add the src script files one-by-one.

For production deployment, we can concatenate the modules together with something like systemjs builder, because our dist still needs to be a single ES5 file.

The problem I see with this, which hopefully is trivial to resolve: how do we load 3rd party libraries through systemjs. Can we leverage it in phantomjs for testing with karma as well?

karma-jspm does not automatically watch file change or times out

In Intellij, once we added the karma-jspm plugin, the IDE no longer rerun test when assets change ... not sure if this is a known bug or a config change is needed

On the command-line, if we run karma manually, src changes are being watched BUT phantomjs cannot be "captured" if a failing test is not corrected in seconds ... I wonder what can we do to make karma with jspm as good as karma by itself ...

Config values for Null, blank and zero

@erfangc per discussion, in each cell, input cell value can be Null, currently it's output is default to NaN% (it used to be0.00).

We want to config each input Null mapping to a blank cell in GigaGrid, not NaN%. Thanks.

Handle additional aggregation methods

similar to ReactTable

there should be additional default aggregation methods for when rows are subtotaled. currently there is only sum and average, we should add count / range etc ...

if custom aggregation callback is passed on the column def by the user, use that instead

Overflow not working on cells

If cell contents becomes too long, they simply push the parent .. we need to stop this behavior as our entire table work off calculated width / height

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.