Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to customize vega-lite charts via configuration #726

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const libVoyager = require('voyager');
const container = document.getElementById("voyager-embed");
const config = undefined;
const data = undefined;
const voyagerInstance = libVoyager.CreateVoyager(container, config, data)
const voyagerInstance = libVoyager.createVoyager(container, {config, data})
```

Initializing with data
Expand All @@ -71,14 +71,14 @@ const data: any = {
]
};

const voyagerInstance = libVoyager.CreateVoyager(container, undefined, data)
const voyagerInstance = libVoyager.createVoyager(container, {config: undefined, data})
```

Updating Data

```js

const voyagerInstance = libVoyager.CreateVoyager(container, undefined, undefined)
const voyagerInstance = libVoyager.createVoyager(container)

const data: any = {
"values": [
Expand All @@ -103,16 +103,16 @@ You currently also need to include the CSS. Note that this has not yet been opti

The voyager _module_ exposes 1 function.

#### CreateVoyager(container, config, data)
#### createVoyager(container, VoyagerParams)

```js
/**
* Create an instance of the voyager application and return it.
* Create an instance of the voyager application.
*
* @param {Container} container css selector or HTMLElement that will be the parent
* element of the application
* @param {Object|undefined} config Optional: configuration options
* @param {Array|undefined} data Optional: data object. Can be a string or an array of objects.
* @param {Container} container css selector or HTMLElement that will be the parent
* element of the application
* @param {VoyagerParams} params Voyager params. {data, config}. Any new additional parameter
* required by voyager can be added here as named parameter for easier visibilty
*/
```

Expand Down
10 changes: 7 additions & 3 deletions src/components/bookmark/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@ import {BOOKMARK_CLEAR_ALL, BookmarkAction} from '../../actions/bookmark';
import {ActionHandler, createDispatchHandler} from '../../actions/redux-action';
import {State} from '../../models';
import {Bookmark} from '../../models/bookmark';
import { VoyagerConfig } from '../../models/config';
import {ResultPlot} from '../../models/result';
import {selectData} from '../../selectors/dataset';
import {selectBookmark} from '../../selectors/index';
import {selectBookmark, selectConfig} from '../../selectors/index';
import {Plot} from '../plot';
import * as styles from './bookmark.scss';


export interface BookmarkProps extends ActionHandler<BookmarkAction> {
bookmark: Bookmark;
data: InlineData;
config: VoyagerConfig;
}

export class BookmarkBase extends React.PureComponent<BookmarkProps, any> {
Expand Down Expand Up @@ -99,7 +101,7 @@ export class BookmarkBase extends React.PureComponent<BookmarkProps, any> {
}

private renderBookmarks(bookmark: Bookmark) {
const {data} = this.props;
const {data, config} = this.props;
const plots: ResultPlot[] = bookmark.list.map(key => bookmark.dict[key].plot);

const bookmarkPlotListItems = plots.map((plot, index) => {
Expand All @@ -116,6 +118,7 @@ export class BookmarkBase extends React.PureComponent<BookmarkProps, any> {
isPlotListItem={true}
showBookmarkButton={true}
showSpecifyButton={true}
config={config}
spec={spec}
/>
);
Expand All @@ -139,7 +142,8 @@ export const BookmarkPane = connect(
(state: State) => {
return {
bookmark: selectBookmark(state),
data: selectData(state)
data: selectData(state),
config: selectConfig(state)
};
},
createDispatchHandler<BookmarkAction>()
Expand Down
11 changes: 8 additions & 3 deletions src/components/plot-list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ import {
import {ShelfAction} from '../../actions/shelf';
import {SPINNER_COLOR} from '../../constants';
import {Bookmark} from '../../models/bookmark';
import { VoyagerConfig } from '../../models/config';
import {State} from '../../models/index';
import {ResultType} from '../../models/result';
import {Result} from '../../models/result/index';
import {ShelfFilter} from '../../models/shelf/filter';
import {selectFilteredData} from '../../selectors/index';
import {selectConfig, selectFilteredData} from '../../selectors/index';
import {selectFilters} from '../../selectors/shelf';
import {Plot} from '../plot';
import * as styles from './plot-list.scss';
Expand All @@ -33,6 +34,8 @@ export interface PlotListConnectProps {
data: InlineData;

filters: ShelfFilter[];

config: VoyagerConfig;
}

export type PlotListProps = PlotListOwnProps & PlotListConnectProps;
Expand All @@ -45,7 +48,7 @@ export class PlotListBase extends React.PureComponent<PlotListProps, any> {
}

public render() {
const {handleAction, bookmark, data, filters, result} = this.props;
const {handleAction, bookmark, data, filters, result, config} = this.props;
const {plots, limit, isLoading} = result;
const plotListItems = plots && plots.slice(0, limit).map((plot, index) => {
const {spec, fieldInfos} = plot;
Expand All @@ -62,6 +65,7 @@ export class PlotListBase extends React.PureComponent<PlotListProps, any> {
showSpecifyButton={true}
spec={spec}
bookmark={bookmark}
config={config}
/>
);
});
Expand Down Expand Up @@ -116,7 +120,8 @@ export const PlotList = connect<PlotListConnectProps, {}, PlotListOwnProps>(
// take spec from props and read spec.data.name
return {
data: selectFilteredData(state),
filters: selectFilters(state)
filters: selectFilters(state),
config: selectConfig(state)
};
}
)(CSSModules(PlotListBase, styles));
8 changes: 5 additions & 3 deletions src/components/plot/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {ShelfAction, SPEC_LOAD} from '../../actions/shelf';
import {SHELF_PREVIEW_DISABLE, SHELF_PREVIEW_SPEC, ShelfPreviewAction} from '../../actions/shelf-preview';
import {PLOT_HOVER_MIN_DURATION} from '../../constants';
import {Bookmark} from '../../models/bookmark';
import { VoyagerConfig } from '../../models/config';
import {PlotFieldInfo, ResultPlot} from '../../models/result';
import {ShelfFilter, toTransforms} from '../../models/shelf/filter';
import {Field} from '../field/index';
Expand All @@ -40,9 +41,9 @@ export interface PlotProps extends ActionHandler<
// specified when it's in the modal
// so we can close the modal when the specify button is clicked.
closeModal?: () => void;
config: VoyagerConfig;
}


export interface PlotState {
hovered: boolean;
preview: boolean;
Expand Down Expand Up @@ -89,7 +90,7 @@ export class PlotBase extends React.PureComponent<PlotProps, PlotState> {
}

public render() {
const {isPlotListItem, onSort, showBookmarkButton, showSpecifyButton, spec, data} = this.props;
const {isPlotListItem, onSort, showBookmarkButton, showSpecifyButton, spec, data, config} = this.props;

let notesDiv;
const specKey = JSON.stringify(spec);
Expand Down Expand Up @@ -137,7 +138,7 @@ export class PlotBase extends React.PureComponent<PlotProps, PlotState> {
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
>
<VegaLite spec={spec} logger={this.plotLogger} data={data}/>
<VegaLite spec={spec} logger={this.plotLogger} data={data} config={config.vegaliteConfig}/>
</div>
{notesDiv}
</div>
Expand Down Expand Up @@ -341,4 +342,5 @@ export class PlotBase extends React.PureComponent<PlotProps, PlotState> {
}
}


export const Plot = CSSModules(PlotBase, styles);
14 changes: 12 additions & 2 deletions src/components/vega-lite/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import {ClipLoader} from 'react-spinners';
import * as vega from 'vega';
import * as vl from 'vega-lite';
import {Config} from 'vega-lite/build/src/config';
import {InlineData, isNamedData} from 'vega-lite/build/src/data';
import {TopLevelExtendedSpec} from 'vega-lite/build/src/spec';
import * as vegaTooltip from 'vega-tooltip';
Expand All @@ -16,6 +17,8 @@ export interface VegaLiteProps {
logger: Logger;

data: InlineData;

config?: Config;
}

export interface VegaLiteState {
Expand Down Expand Up @@ -72,8 +75,15 @@ export class VegaLite extends React.PureComponent<VegaLiteProps, VegaLiteState>
// "y": {"field": "b", "type": "quantitative"}
// }
// };
const {logger} = this.props;
const vlSpec = this.props.spec;
const {logger, config} = this.props;
let vlSpec = this.props.spec;
vlSpec = {
...vlSpec,
config: {
...vlSpec.config,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the general config should be overridden by a spec specific-config.

{
  ...config
  ...vlSpec.config
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this override the config users pass to modify vega-lite chart's configuration? My understanding was users pass vegaliteConfig to override spec configurations for respective charts (for instance modify the color or axis tick format etc.,)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it will override since we think about the shared config as a theme. So suppose you have multiple Vega-Lite charts and you have a common config that you pass in. Each spec can have config that override the common theme (rather than the other way round). :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that is the case would the common theme ever be applied? Say in the case of bar charts we have defined the fill color to be a blue and if users need to override that would that be possible? I am not sure if I am missing something.

Can you provide an example where a user modifies the fill color of bar charts in voyager with custom config? My assumption was the config user provides are custom config and that would override any default spec config that comes as part of voyager for vega-lite charts.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that is the case would the common theme ever be applied?

Yes, your common theme may have 10 properties and the spec specific theme may have 1 that override the common theme so 9 properties would still be applied.

Can you provide an example where a user modifies the fill color of bar charts in voyager with custom config?

Right now there is no such case. But this is how Vega-Lite treat "common" theme too. So should CompassQL output some config in the future.

That said, thinking more about it I think I agree with you that if users explicitly specify the config, it should override what's automatically generated by CompassQL.

...config
}
};
try {
const spec = vl.compile(vlSpec, logger).spec;
const runtime = vega.parse(spec, vlSpec.config);
Expand Down
3 changes: 2 additions & 1 deletion src/components/view-pane/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class ViewPaneBase extends React.PureComponent<ViewPaneProps, {}> {
}

private renderSpecifiedView() {
const {bookmark, data, filters, handleAction, spec} = this.props;
const {bookmark, data, filters, handleAction, spec, config} = this.props;

if (spec) {
return (
Expand All @@ -114,6 +114,7 @@ class ViewPaneBase extends React.PureComponent<ViewPaneProps, {}> {
onSort={this.onSort}
showBookmarkButton={true}
spec={spec}
config={config}
/>
);
} else {
Expand Down
6 changes: 3 additions & 3 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ const data: Data = undefined;
ReactDOM.render(
<Provider store={store}>
<App
config={config}
data={data}
dispatch={store.dispatch}
config={config}
data={data}
dispatch={store.dispatch}
/>
</Provider>,
document.getElementById('root')
Expand Down
Loading