Skip to content

Commit

Permalink
additional work for functions working in trelliscope panels (#1206)
Browse files Browse the repository at this point in the history
Co-authored-by: Brandon McArthur <[email protected]>
  • Loading branch information
Incin and Brandon McArthur authored Feb 13, 2024
1 parent 22dd508 commit d6d90d1
Show file tree
Hide file tree
Showing 11 changed files with 91 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ __loadDisplayInfo__5ae49320({
{
"source": {
"isLocal": true,
"type": "file"
"type": "JS",
'function': null
},
"aspect": 1.5,
"paneltype": "img",
Expand All @@ -114,7 +115,7 @@ __loadDisplayInfo__5ae49320({
{
"source": {
"isLocal": true,
"type": "file"
"type": "JS"
},
"aspect": 0.5,
"paneltype": "iframe",
Expand All @@ -129,7 +130,7 @@ __loadDisplayInfo__5ae49320({
{
"source": {
"isLocal": false,
"type": "file"
"type": "JS"
},
"aspect": 1.50146627565982,
"paneltype": "img",
Expand Down
5 changes: 2 additions & 3 deletions src/TrelliscopeApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@ interface TrelliscopeAppProps {
}

// component for embedding a Trelliscope app in a React app
const TrelliscopeApp: React.FC<TrelliscopeAppProps> = ({ data, width, height, options = {}}) => {
const TrelliscopeApp: React.FC<TrelliscopeAppProps> = ({ data, width, height, options = {} }) => {
const crossFilterClient = new CrossfilterClient();
const id = 'trelliscope_app';
// TODO: need to get appDims from a ref of parent component
const appDims = { width, height }
const appDims = { width, height };

return (
<div style={{ width, height, position: 'relative', overflow: 'hidden' }}>
Expand Down
8 changes: 5 additions & 3 deletions src/components/Content/Content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,11 @@ const Content: React.FC<ContentProps> = ({ table, tableWrapperRef, tableContentR
<PanelGraphic
type={primaryMeta?.paneltype}
src={
primaryMeta?.source?.isLocal === false
? d[curPanel].toString()
: panelSrcGetter(basePath, d[curPanel] as string, snakeCase(displayInfo?.name || '')).toString()
primaryMeta?.source?.type === 'JS' && primaryMeta?.source?.function
? primaryMeta.source.function(d)
: primaryMeta?.source?.isLocal === false
? d[curPanel].toString()
: panelSrcGetter(basePath, d[curPanel] as string, snakeCase(displayInfo?.name || '')).toString()
}
alt={primaryMeta?.label}
aspectRatio={primaryMeta?.aspect}
Expand Down
16 changes: 9 additions & 7 deletions src/components/ContentContainer/ContentContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -289,13 +289,15 @@ const ContentContainer: React.FC = () => {
<PanelGraphic
type={meta?.paneltype as PanelType}
src={
meta?.source?.isLocal === false
? cell.row.original[meta.varname].toString()
: panelSrcGetter(
basePath,
cell.row.original[meta.varname] as string,
snakeCase(displayInfo?.name || ''),
).toString()
meta?.source?.type === 'JS' && meta?.source?.function
? meta.source.function(cell.row.original)
: meta?.source?.isLocal === false
? cell.row.original[meta.varname].toString()
: panelSrcGetter(
basePath,
cell.row.original[meta.varname] as string,
snakeCase(displayInfo?.name || ''),
).toString()
}
alt={cell.row.original.name as string}
aspectRatio={meta?.aspect}
Expand Down
22 changes: 10 additions & 12 deletions src/components/DataProvider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,17 @@ const DataProvider: React.FC<DataProviderProps> = ({ children, client }) => {
setData(client.getData(numPerPage, page));
}, [numPerPage, page]);

const dataContextValue = useMemo(() => ({
data, allData: client.allData,
filteredData: client.filteredData,
groupBy: client.groupBy
}), [data, client.allData, client.filteredData, client.groupBy]);

return (
<DataContext.Provider
value={dataContextValue}
>
{children}
</DataContext.Provider>
const dataContextValue = useMemo(
() => ({
data,
allData: client.allData,
filteredData: client.filteredData,
groupBy: client.groupBy,
}),
[data, client.allData, client.filteredData, client.groupBy],
);

return <DataContext.Provider value={dataContextValue}>{children}</DataContext.Provider>;
};

export default DataProvider;
3 changes: 2 additions & 1 deletion src/components/PanelDialog/PanelDialog.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@

iframe {
border: none;
max-height: 500px;
// max-height: 500px;
height: auto;
// max-width: 100%;
// width: min(80vw, 80vh);
// height: min(80vw, 80vh);
Expand Down
22 changes: 15 additions & 7 deletions src/components/PanelDialog/PanelDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const PanelDialog: React.FC<PanelDialogProps> = ({ data, filteredData, open, pan
({
...variable,
sourcePath: curMetaData?.[variable.varname],
} as PanelExtended),
}) as PanelExtended,
),
);
}, [curMetaData, panel?.varname, selectedVariables]);
Expand Down Expand Up @@ -179,6 +179,10 @@ const PanelDialog: React.FC<PanelDialogProps> = ({ data, filteredData, open, pan
setSelectedVariables(value);
};

const getDataForPanel = (selectedPanel: IPanelMeta, selectedSource: string) => {
return data.find((datum) => datum[selectedPanel?.name] === selectedSource);
};

return (
<Dialog
maxWidth="lg"
Expand Down Expand Up @@ -243,9 +247,11 @@ const PanelDialog: React.FC<PanelDialogProps> = ({ data, filteredData, open, pan
<PanelGraphic
type={panel?.paneltype}
src={
panel?.source?.isLocal === false
? curSource
: panelSrcGetter(basePath, curSource, snakeCase(displayInfo?.name || '')).toString()
panel?.source?.type === 'JS' && panel?.source?.function
? panel.source.function(getDataForPanel(panel, curSource))
: panel?.source?.isLocal === false
? curSource
: panelSrcGetter(basePath, curSource, snakeCase(displayInfo?.name || '')).toString()
}
alt={panel?.label}
key={`${panel?.source}_${panel?.label}`}
Expand All @@ -262,9 +268,11 @@ const PanelDialog: React.FC<PanelDialogProps> = ({ data, filteredData, open, pan
<PanelGraphic
type={panelSource?.paneltype}
src={
panelSource?.source?.isLocal === false
? panelSource.sourcePath
: panelSrcGetter(basePath, panelSource.sourcePath, snakeCase(displayInfo?.name || '')).toString()
panelSource?.source?.type === 'JS' && panelSource?.source?.function
? panelSource.source.function(getDataForPanel(panelSource, panelSource?.sourcePath))
: panelSource?.source?.isLocal === false
? panelSource.sourcePath
: panelSrcGetter(basePath, panelSource.sourcePath, snakeCase(displayInfo?.name || '')).toString()
}
alt={panelSource?.label}
key={`${panelSource?.source}_${panelSource?.label}`}
Expand Down
6 changes: 5 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ const trelliscopeApp = (
};

window.trelliscopeApp = trelliscopeApp;
window.Trelliscope = Trelliscope;

// TODO: should be able to just attach this to window so that it can be loaded in other apps
// by including the js script and then using the component (vs. having to import and bundle it in the app)
Expand Down Expand Up @@ -192,7 +193,7 @@ if (import.meta.env.MODE === 'development') {
name: 'gapminder',
keycols: ['country', 'continent'],
})
.setDefaultLayout({ sidebarActive: true, ncol: 3, activeFilterVars: ['continent', 'mean_lexp'] })
.setDefaultLayout({ sidebarActive: true, ncol: 4, activeFilterVars: ['continent', 'mean_lexp'] })
.setDefaultLabels({ varnames: ['country', 'continent', 'mean_lexp', 'wiki_link'] })
.setDefaultSort({ varnames: ['continent', 'mean_lexp'], dirs: ['asc', 'desc'] })
.setRangeFilter({ varname: 'mean_lexp', max: 60 }) // not working yet
Expand All @@ -205,6 +206,9 @@ if (import.meta.env.MODE === 'development') {
dttm_lexp_max_pct_chg: 'Date-time of max % year-to-year change in life expectancy',
wiki_link: 'Link to country Wikipedia entry',
flag: 'Country flag',
})
.setPanelFunction('flag', (row: Datum) => {
return `https://raw.githubusercontent.com/hafen/countryflags/master/png/512/${row.iso_alpha2}.png`;
});
trelliscopeApp(example.id, appdat);
});
Expand Down
27 changes: 23 additions & 4 deletions src/jsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/* eslint-disable @typescript-eslint/lines-between-class-members */
import { max } from 'd3-array';
import { metaIndex } from './slices/metaDataAPI';
import { cloneDeep } from 'lodash';

export class Meta implements IMeta {
name: string; // why??
Expand Down Expand Up @@ -697,6 +698,24 @@ class TrelliscopeClass implements ITrelliscopeAppSpec {
return this;
}

setPanelFunction(varname: string, func: PanelFunction): ITrelliscopeAppSpec {
const { name } = this.displayList[0];
const { metas } = this.displays[name].displayInfo;
const meta = metas.find((m) => m.varname === varname) as IPanelMeta;
if (meta === undefined) {
throw new Error(`varname ${varname} not found in metas`);
}
if (meta.type !== 'panel') {
throw new Error(`varname ${varname} is not a panel`);
}
meta.source = {
...meta.source,
type: 'JS',
function: func,
};
return this;
}

setRangeFilter({
varname,
min = null,
Expand Down Expand Up @@ -812,7 +831,7 @@ export function Trelliscope({
}

export function prepareTrelliscope(data: ITrelliscopeAppSpec, id: string): ITrelliscopeAppSpec {
const data2 = JSON.parse(JSON.stringify(data));
const data2 = cloneDeep(data);
data2.config.id = id;
const di = data2.displays[data2.displayList[0].name].displayInfo;
// make sure there is a primary panel specified
Expand All @@ -827,13 +846,13 @@ export function prepareTrelliscope(data: ITrelliscopeAppSpec, id: string): ITrel
const md = data2.displays[data2.displayList[0].name].metaData;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
di.metas
.filter((d: { type: string }) => d.type === 'factor')
.forEach((d: { name: string | number; levels: string | any[] }) => {
.filter((d: IMeta) => d.type === 'factor')
.forEach((d: IMeta) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
md.forEach((row: { [x: string]: any }) => {
if (row[d.name]) {
// eslint-disable-next-line no-param-reassign
row[d.name] = d.levels.indexOf(row[d.name]) + 1;
row[d.name] = (d.levels ?? []).indexOf(row[d.name]) + 1;
}
});
});
Expand Down
7 changes: 4 additions & 3 deletions src/types/configs.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,10 +396,10 @@ type PanelType = 'img' | 'iframe';

type PanelSourceType = 'file' | 'REST' | 'localWebSocket' | 'JS';

type PanelFunction = (args: []) => string;
type PanelFunction = (args) => string;

interface IJSPanelSource extends IPanelSource {
function: PanelFunction;
function?: PanelFunction;
}

interface IPanelSource {
Expand All @@ -412,7 +412,7 @@ interface IPanelMeta extends IMeta {
paneltype: PanelType;
// format?: PanelFormat;
aspect: number;
source: IPanelSource;
source: IJSPanelSource;
}

// interface IFilePanelSource extends IPanelSource {
Expand Down Expand Up @@ -509,4 +509,5 @@ interface ITrelliscopeAppSpec {
setVarLabels(labels: { [index: string]: string }): ITrelliscopeAppSpec;
setPrimaryPanel(panel: string): ITrelliscopeAppSpec;
setRangeFilter(arg0: { varname: string; min?: number | Date | null; max?: number | Date | null }): ITrelliscopeAppSpec;
setPanelFunction(arg0: string, arg1: PanelFunction): ITrelliscopeAppSpec;
}
13 changes: 12 additions & 1 deletion src/types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ interface HTMLWidgetData {
jsHooks: unknown[];
}

interface TrelliscopeFuncGlobalSpec {
data: Datum[];
name: string;
description?: string;
tags?: string[];
keycols: string[];
primarypanel?: string;
infoOnLoad?: boolean;
}

type PanelData = string | HTMLWidgetData;
declare global {
interface Window {
Expand All @@ -24,7 +34,8 @@ declare global {
| ((data: IDisplay) => void)
| ((data: Datum[]) => void)
| ((data: IConfig) => void)
| ((data: IDisplay[]) => void);
| ((data: IDisplay[]) => void)
| ((data: TrelliscopeAppGlobalSpec) => void);
metaData: Datum[] | null;
}
interface Document {
Expand Down

0 comments on commit d6d90d1

Please sign in to comment.