-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #56 from eyra/development
Development
- Loading branch information
Showing
87 changed files
with
5,324 additions
and
1,556 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"prettier.trailingComma": "none", | ||
"prettier.tabWidth": 2, | ||
"prettier.semi": false, | ||
"prettier.singleQuote": true, | ||
"prettier.printWidth": 100, | ||
"search.exclude": { | ||
"**/node_modules": true, | ||
"**/dist": true | ||
}, | ||
"tailwindCSS.includeLanguages": { | ||
"html": "html", | ||
"javascript": "javascript", | ||
"typescript": "typescript", | ||
"css": "css" | ||
}, | ||
"editor.quickSuggestions": { | ||
"strings": true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { Text } from './elements'; | ||
export interface VisualizationProps { | ||
title: Text; | ||
height?: number; | ||
} | ||
export type AggregationFunction = 'count' | 'mean' | 'sum' | 'count_pct' | 'pct'; | ||
export interface Axis { | ||
label?: string; | ||
column: string; | ||
} | ||
export interface AggregationGroup { | ||
label?: string; | ||
column: string; | ||
dateFormat?: DateFormat; | ||
tokenize?: boolean; | ||
} | ||
export interface AggregationValue { | ||
label?: string; | ||
column: string; | ||
aggregate?: AggregationFunction; | ||
group_by?: string; | ||
secondAxis?: boolean; | ||
z?: string; | ||
zAggregate?: AggregationFunction; | ||
addZeroes?: boolean; | ||
} | ||
export interface ChartVisualization extends VisualizationProps { | ||
type: 'line' | 'bar' | 'area'; | ||
group: AggregationGroup; | ||
values: AggregationValue[]; | ||
} | ||
export interface TextVisualization extends VisualizationProps { | ||
type: 'wordcloud'; | ||
textColumn: string; | ||
valueColumn?: string; | ||
tokenize?: boolean; | ||
} | ||
export interface ScoredTerm { | ||
text: string; | ||
value: number; | ||
importance: number; | ||
rowIds?: string[]; | ||
} | ||
export type VisualizationType = ChartVisualization | TextVisualization; | ||
export interface AxisSettings { | ||
label: string; | ||
secondAxis?: boolean; | ||
tickerFormat?: TickerFormat; | ||
} | ||
export type TickerFormat = 'percent' | 'default'; | ||
export interface ChartVisualizationData { | ||
type: 'line' | 'bar' | 'area'; | ||
data: Array<Record<string, any>>; | ||
xKey: AxisSettings; | ||
yKeys: Record<string, AxisSettings>; | ||
} | ||
export interface TextVisualizationData { | ||
type: 'wordcloud'; | ||
topTerms: ScoredTerm[]; | ||
} | ||
export type VisualizationData = ChartVisualizationData | TextVisualizationData; | ||
export type DateFormat = 'auto' | 'year' | 'quarter' | 'month' | 'day' | 'hour' | 'month_cycle' | 'weekday_cycle' | 'day_cycle' | 'hour_cycle'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export {}; |
9 changes: 9 additions & 0 deletions
9
dist/framework/visualisation/react/ui/elements/Minimizable.d.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { ReactNode } from 'react'; | ||
interface Props { | ||
children: ReactNode; | ||
size?: string; | ||
fullSize?: boolean; | ||
minimized?: ReactNode; | ||
} | ||
export declare const Minimizable: ({ children, size, fullSize, minimized }: Props) => JSX.Element; | ||
export {}; |
24 changes: 24 additions & 0 deletions
24
dist/framework/visualisation/react/ui/elements/Minimizable.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; | ||
import { useState } from 'react'; | ||
export const Minimizable = ({ children, size = 'h-[15rem] w-[24rem]', fullSize, minimized }) => { | ||
const [isMinimized, setIsMinimized] = useState(true); | ||
const containerStyle = isMinimized | ||
? `${size} overflow-hidden animate-fadeIn` | ||
: (fullSize !== null && fullSize !== void 0 ? fullSize : false) | ||
? 'w-full' | ||
: ''; | ||
const childStyle = isMinimized | ||
? 'scale-50 origin-top-left z-10 p-5 w-[200%] ' | ||
: 'transition-all duration-500'; | ||
const toggleStyle = isMinimized | ||
? 'transition-all absolute top-0 left-0 h-full w-full z-20 bg-primary/0 hover:bg-primary/25 border-solid cursor-zoom-in' | ||
: 'w-min mr-auto mt-2 cursor-zoom-out'; | ||
const iconStyle = isMinimized ? 'rounded-tr-sm bg-primary' : 'rounded-sm mb-2 bg-primary'; | ||
const minimizedTruthy = Boolean(minimized); | ||
const child = minimizedTruthy | ||
? minimized | ||
: (_jsx("div", Object.assign({ className: `relative ${childStyle}` }, { children: minimizedTruthy ? minimized : children }))); | ||
return (_jsxs("div", Object.assign({ className: `overflow-auto relative ${containerStyle}` }, { children: [child, _jsx("div", Object.assign({ className: `flex items-end justify-start rounded-sm border-primary ${toggleStyle}`, onClick: () => setIsMinimized(!isMinimized) }, { children: _jsx("div", Object.assign({ className: `relative font-caption text-xl px-4 py-1 backdrop-blur-[2px] text-white z-30 ${iconStyle}` }, { children: isMinimized ? zoomInIcon : zoomOutIcon })) }))] }))); | ||
}; | ||
const zoomInIcon = (_jsx("svg", Object.assign({ className: 'h-6 w-6', fill: 'none', stroke: 'currentColor', strokeWidth: '2', viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg', "aria-hidden": 'true' }, { children: _jsx("path", { strokeLinecap: 'round', strokeLinejoin: 'round', d: 'M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607zM10.5 7.5v6m3-3h-6' }) }))); | ||
const zoomOutIcon = (_jsx("svg", Object.assign({ className: 'h-6 w-6', fill: 'none', stroke: 'currentColor', strokeWidth: '2', viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg', "aria-hidden": 'true' }, { children: _jsx("path", { strokeLinecap: 'round', strokeLinejoin: 'round', d: 'M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607zM13.5 10.5h-6' }) }))); |
14 changes: 14 additions & 0 deletions
14
dist/framework/visualisation/react/ui/elements/figure.d.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/// <reference types="react" /> | ||
import { TableWithContext } from '../../../../types/elements'; | ||
import { VisualizationType } from '../../../../types/visualizations'; | ||
import { ReactFactoryContext } from '../../factory'; | ||
type Props = VisualizationProps & ReactFactoryContext; | ||
export interface VisualizationProps { | ||
table: TableWithContext; | ||
visualization: VisualizationType; | ||
locale: string; | ||
handleDelete: (rowIds: string[]) => void; | ||
handleUndo: () => void; | ||
} | ||
export declare const Figure: ({ table, visualization, locale, handleDelete, handleUndo }: Props) => JSX.Element; | ||
export {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; | ||
import TextBundle from '../../../../text_bundle'; | ||
import { Translator } from '../../../../translator'; | ||
import { memo, useMemo } from 'react'; | ||
import useVisualizationData from '../hooks/useVisualizationData'; | ||
import { Title6 } from './text'; | ||
import Lottie from 'lottie-react'; | ||
import spinnerDark from '../../../../../assets/lottie/spinner-dark.json'; | ||
import RechartsGraph from './figures/recharts_graph'; | ||
import VisxWordcloud from './figures/visx_wordcloud'; | ||
export const Figure = ({ table, visualization, locale, handleDelete, handleUndo }) => { | ||
var _a; | ||
const [visualizationData, status] = useVisualizationData(table, visualization); | ||
const { title } = useMemo(() => { | ||
const title = Translator.translate(visualization.title, locale); | ||
return { title }; | ||
}, [visualization]); | ||
const { errorMsg, noDataMsg } = useMemo(() => prepareCopy(locale), [locale]); | ||
if ((visualizationData == null) && status === 'loading') { | ||
return (_jsx("div", Object.assign({ className: 'w-12 h-12' }, { children: _jsx(Lottie, { animationData: spinnerDark, loop: true }) }))); | ||
} | ||
if (status === 'error') { | ||
return _jsx("div", Object.assign({ className: 'flex justify-center items-center text-error' }, { children: errorMsg })); | ||
} | ||
const visualizationHeightTruthy = Boolean(visualization.height); | ||
const minHeight = visualizationHeightTruthy ? `${(_a = visualization.height) !== null && _a !== void 0 ? _a : ''} px` : '20rem'; | ||
return (_jsxs("div", Object.assign({ className: 'flex flex-col overflow-hidden' }, { children: [_jsx(Title6, { text: title, margin: 'mt-2 mb-4' }), _jsx("div", Object.assign({ className: 'relative z-50 flex max-w-full', style: { flex: `1 1 ${minHeight}`, minHeight } }, { children: _jsx(RenderVisualization, { visualizationData: visualizationData, fallbackMessage: noDataMsg }) }))] }))); | ||
}; | ||
const RenderVisualization = memo(({ visualizationData, fallbackMessage }) => { | ||
if (visualizationData == null) | ||
return null; | ||
const fallback = (_jsx("div", Object.assign({ className: 'm-auto font-bodybold text-4xl text-grey2 ' }, { children: fallbackMessage }))); | ||
if (['line', 'bar', 'area'].includes(visualizationData.type)) { | ||
const chartVisualizationData = visualizationData; | ||
if (chartVisualizationData.data.length === 0) | ||
return fallback; | ||
return _jsx(RechartsGraph, { visualizationData: chartVisualizationData }); | ||
} | ||
if (visualizationData.type === 'wordcloud') { | ||
const textVisualizationData = visualizationData; | ||
if (textVisualizationData.topTerms.length === 0) | ||
return fallback; | ||
return _jsx(VisxWordcloud, { visualizationData: textVisualizationData }); | ||
} | ||
return null; | ||
}); | ||
function prepareCopy(locale) { | ||
return { | ||
errorMsg: Translator.translate(errorMsg, locale), | ||
noDataMsg: Translator.translate(noDataMsg, locale) | ||
}; | ||
} | ||
const noDataMsg = new TextBundle().add('en', 'No data').add('nl', 'Geen data'); | ||
const errorMsg = new TextBundle() | ||
.add('en', 'Could not create visualization') | ||
.add('nl', 'Kon visualisatie niet maken'); |
7 changes: 7 additions & 0 deletions
7
dist/framework/visualisation/react/ui/elements/figures/recharts_graph.d.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/// <reference types="react" /> | ||
import { ChartVisualizationData } from '../../../../../types/visualizations'; | ||
interface Props { | ||
visualizationData: ChartVisualizationData; | ||
} | ||
export default function RechartsGraph({ visualizationData }: Props): JSX.Element | null; | ||
export {}; |
84 changes: 84 additions & 0 deletions
84
dist/framework/visualisation/react/ui/elements/figures/recharts_graph.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; | ||
import { ResponsiveContainer, LineChart, Line, XAxis, YAxis, Tooltip, Legend, BarChart, Bar, AreaChart, Area } from 'recharts'; | ||
export default function RechartsGraph({ visualizationData }) { | ||
function tooltip() { | ||
return (_jsx(Tooltip, { allowEscapeViewBox: { x: false, y: false }, labelStyle: { marginBottom: '0.5rem' }, contentStyle: { | ||
fontSize: '0.8rem', | ||
lineHeight: '0.8rem', | ||
background: '#fff8', | ||
backdropFilter: 'blur(3px)' | ||
} })); | ||
} | ||
function axes(minTickGap) { | ||
const hasVisualizationData = Boolean(visualizationData); | ||
if (!hasVisualizationData) | ||
return null; | ||
const secondary = Object.values(visualizationData.yKeys).findIndex((yKey) => yKey.secondAxis) !== | ||
-1; | ||
const { tickFormatter, tickFormatter2 } = getTickFormatters(Object.values(visualizationData.yKeys)); | ||
return (_jsxs(_Fragment, { children: [_jsx(XAxis, { dataKey: visualizationData.xKey.label, minTickGap: minTickGap }), _jsx(YAxis, { yAxisId: 'left', tickFormatter: tickFormatter }), secondary && _jsx(YAxis, { yAxisId: 'right', orientation: 'right', tickFormatter: tickFormatter2 })] })); | ||
} | ||
function legend() { | ||
return (_jsx(Legend, { margin: { left: 10 }, align: 'right', verticalAlign: 'top', iconType: 'plainline', wrapperStyle: { fontSize: '0.8rem' } })); | ||
} | ||
let chart = null; | ||
if (visualizationData.type === 'line') { | ||
chart = (_jsxs(LineChart, Object.assign({ data: visualizationData.data }, { children: [axes(20), tooltip(), legend(), Object.values(visualizationData.yKeys).map((yKey, i) => { | ||
var _a; | ||
const { color, dash } = getLineStyle(i); | ||
return (_jsx(Line, { yAxisId: ((_a = yKey.secondAxis) !== null && _a !== void 0 ? _a : false) ? 'right' : 'left', type: 'monotone', dataKey: yKey.label, dot: false, strokeWidth: 2, stroke: color, strokeDasharray: dash }, yKey.label)); | ||
})] }))); | ||
} | ||
if (visualizationData.type === 'bar') { | ||
chart = (_jsxs(BarChart, Object.assign({ data: visualizationData.data }, { children: [axes(0), tooltip(), legend(), Object.values(visualizationData.yKeys).map((yKey, i) => { | ||
var _a; | ||
const { color } = getLineStyle(i); | ||
return (_jsx(Bar, { yAxisId: ((_a = yKey.secondAxis) !== null && _a !== void 0 ? _a : false) ? 'right' : 'left', dataKey: yKey.label, fill: color }, yKey.label)); | ||
})] }))); | ||
} | ||
if (visualizationData.type === 'area') { | ||
chart = (_jsxs(AreaChart, Object.assign({ data: visualizationData.data }, { children: [axes(20), tooltip(), legend(), Object.values(visualizationData.yKeys).map((yKey, i) => { | ||
var _a; | ||
const { color } = getLineStyle(i); | ||
return (_jsx(Area, { yAxisId: ((_a = yKey.secondAxis) !== null && _a !== void 0 ? _a : false) ? 'right' : 'left', dataKey: yKey.label, fill: color }, yKey.label)); | ||
})] }))); | ||
} | ||
if (chart == null) | ||
return null; | ||
return (_jsx(ResponsiveContainer, Object.assign({ width: '100%', height: '100%' }, { children: chart }))); | ||
} | ||
function getLineStyle(index) { | ||
const COLORS = ['#4272EF', '#FF5E5E', '#FFCF60', '#1E3FCC', '#CC3F3F', '#CC9F3F']; | ||
const DASHES = ['1', '5 5', '10 10', '5 5 10 10']; | ||
const cell = index % (COLORS.length * DASHES.length); | ||
const row = index % COLORS.length; | ||
const column = Math.floor(cell / COLORS.length); | ||
return { color: COLORS[row], dash: DASHES[column] }; | ||
} | ||
function getTickFormatters(yKeys) { | ||
var _a; | ||
let tickerFormat; | ||
let tickerFormat2; | ||
for (const yKey of yKeys) { | ||
if (!((_a = yKey.secondAxis) !== null && _a !== void 0 ? _a : false)) { | ||
if (tickerFormat === undefined) | ||
tickerFormat = yKey.tickerFormat; | ||
if (tickerFormat !== yKey.tickerFormat) | ||
tickerFormat = 'default'; | ||
} | ||
else { | ||
if (tickerFormat2 === undefined) | ||
tickerFormat2 = yKey.tickerFormat; | ||
if (tickerFormat2 !== yKey.tickerFormat) | ||
tickerFormat2 = 'default'; | ||
} | ||
} | ||
const tickFormatter = getTickFormatter(tickerFormat !== null && tickerFormat !== void 0 ? tickerFormat : 'default'); | ||
const tickFormatter2 = getTickFormatter(tickerFormat2 !== null && tickerFormat2 !== void 0 ? tickerFormat2 : 'default'); | ||
return { tickFormatter, tickFormatter2 }; | ||
} | ||
function getTickFormatter(format) { | ||
if (format === 'percent') | ||
return (value) => `${value}%`; | ||
return undefined; | ||
} |
7 changes: 7 additions & 0 deletions
7
dist/framework/visualisation/react/ui/elements/figures/visx_wordcloud.d.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/// <reference types="react" /> | ||
import { TextVisualizationData } from '../../../../../types/visualizations'; | ||
interface Props { | ||
visualizationData: TextVisualizationData; | ||
} | ||
declare function VisxWordcloud({ visualizationData }: Props): JSX.Element | null; | ||
export default VisxWordcloud; |
20 changes: 20 additions & 0 deletions
20
dist/framework/visualisation/react/ui/elements/figures/visx_wordcloud.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { jsx as _jsx } from "react/jsx-runtime"; | ||
import { Text } from '@visx/text'; | ||
import Wordcloud from '@visx/wordcloud/lib/Wordcloud'; | ||
import { ParentSize } from '@visx/responsive'; | ||
import { useMemo } from 'react'; | ||
function VisxWordcloud({ visualizationData }) { | ||
const fontRange = [12, 60]; | ||
const colors = ['#1E3FCC', '#4272EF', '#CC9F3F', '#FFCF60']; | ||
const nWords = 100; | ||
const words = useMemo(() => { | ||
return visualizationData.topTerms.slice(0, nWords); | ||
}, [visualizationData, nWords]); | ||
return (_jsx(ParentSize, { children: (parent) => (_jsx(Wordcloud, Object.assign({ words: words, height: parent.height, width: parent.width, rotate: 0, padding: 3, spiral: 'rectangular', fontSize: (w) => w.importance * (fontRange[1] - fontRange[0]) + fontRange[0], random: () => 0.5 }, { children: (cloudWords) => { | ||
return cloudWords.map((w, i) => { | ||
var _a, _b, _c; | ||
return (_jsx(Text, Object.assign({ fill: colors[Math.floor((i / cloudWords.length) * colors.length)], fontSize: w.size, textAnchor: 'middle', fontFamily: w.font, transform: `translate(${(_a = w.x) !== null && _a !== void 0 ? _a : 0}, ${(_b = w.y) !== null && _b !== void 0 ? _b : 0}) rotate(${(_c = w.rotate) !== null && _c !== void 0 ? _c : 0})` }, { children: w.text }), w.text)); | ||
}); | ||
} }))) })); | ||
} | ||
export default VisxWordcloud; |
7 changes: 7 additions & 0 deletions
7
dist/framework/visualisation/react/ui/elements/pagination.d.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/// <reference types="react" /> | ||
export interface Props { | ||
page: number; | ||
setPage: (page: number) => void; | ||
nPages: number; | ||
} | ||
export declare const Pagination: ({ page, setPage, nPages }: Props) => JSX.Element; |
13 changes: 13 additions & 0 deletions
13
dist/framework/visualisation/react/ui/elements/pagination.js
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
9 changes: 9 additions & 0 deletions
9
dist/framework/visualisation/react/ui/elements/question_multiple_choice.d.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/// <reference types="react" /> | ||
import { PropsUIQuestionMultipleChoice } from '../../../../types/elements'; | ||
import { ReactFactoryContext } from '../../factory'; | ||
interface parentSetter { | ||
parentSetter: (arg: any) => any; | ||
} | ||
type Props = PropsUIQuestionMultipleChoice & parentSetter & ReactFactoryContext; | ||
export declare const MultipleChoiceQuestion: (props: Props) => JSX.Element; | ||
export {}; |
Oops, something went wrong.