diff --git a/apps/web/src/app/app.tsx b/apps/web/src/app/app.tsx index 0969d61a0da4f451adb633e9baf5eba019669268..9ddedfcbd9132394b21f9f7fcc1216752c4ec0b2 100644 --- a/apps/web/src/app/app.tsx +++ b/apps/web/src/app/app.tsx @@ -28,7 +28,7 @@ import { import { Query2BackendQuery, QueryBuilder, QueryMultiGraph } from '@graphpolaris/shared/lib/querybuilder'; import { Schema } from '@graphpolaris/shared/lib/schema/panel'; import { Navbar } from '../components/navbar/navbar'; -import { VisualizationPanel } from './panels/Visualization'; +import { VisualizationPanel } from '@graphpolaris/shared/lib/vis/panel'; import { SchemaFromBackend } from '@graphpolaris/shared/lib/schema'; import { LinkPredictionInstance, setMLResult, allMLTypes } from '@graphpolaris/shared/lib/data-access/store/mlSlice'; import { Resizable } from '@graphpolaris/shared/lib/components/Resizable'; diff --git a/apps/web/src/app/panels/Visualization.tsx b/apps/web/src/app/panels/Visualization.tsx index 883093ed90b97f5166ddd774d327ea844de0c2ae..6f83691ec9a30bb5d849ffa888ffe0a4eb9c5432 100644 --- a/apps/web/src/app/panels/Visualization.tsx +++ b/apps/web/src/app/panels/Visualization.tsx @@ -1,16 +1,12 @@ -import React, { useMemo, useState } from 'react'; -import { RawJSONVis, NodeLinkVis, PaohVis, SemanticSubstrates, TableVis } from '@graphpolaris/shared/lib/vis'; +import React, { useState } from 'react'; import { useAppDispatch, useGraphQueryResult, useQuerybuilderGraph, useVisualizationState } from '@graphpolaris/shared/lib/data-access'; import { LoadingSpinner } from '@graphpolaris/shared/lib/components/LoadingSpinner'; import { Visualizations, setActiveVisualization } from '@graphpolaris/shared/lib/data-access/store/visualizationSlice'; -import { DropdownItem, DropdownItemContainer, MenuDropdown } from '@graphpolaris/shared/lib/components/dropdowns'; +import { DropdownItem, DropdownItemContainer } from '@graphpolaris/shared/lib/components/dropdowns'; import ControlContainer from '@graphpolaris/shared/lib/components/controls'; import { Button } from '@graphpolaris/shared/lib/components/buttons'; - -type VisOptionFunction = () => { - payload: Visualizations; - type: 'visualization/setActiveVisualization'; -}; +import { createVisualizationComponent } from '@graphpolaris/shared/lib/vis'; +import VisualizationDialog from './VisualizationDialog'; export const VisualizationPanel = () => { const vis = useVisualizationState(); @@ -18,51 +14,26 @@ export const VisualizationPanel = () => { const query = useQuerybuilderGraph(); const dispatch = useAppDispatch(); const [visDropdownOpen, setVisDropdownOpen] = useState<boolean>(false); + const [showVisSettings, setShowVisSettings] = useState<boolean>(false); - const visOptions: Record<string, VisOptionFunction> = { - Table: () => dispatch(setActiveVisualization(Visualizations.Table)), - NodeLink: () => dispatch(setActiveVisualization(Visualizations.NodeLink)), - PaohVis: () => dispatch(setActiveVisualization(Visualizations.Paohvis)), - 'JSON Structure': () => dispatch(setActiveVisualization(Visualizations.RawJSON)), - }; - - const visualizationComponent = useMemo(() => { - switch (vis.activeVisualization) { - case Visualizations.Table: - return ( - <div id={Visualizations.Table} className="tabContent w-full h-full py-8"> - <TableVis showBarplot={true} /> - </div> - ); - case Visualizations.NodeLink: - return ( - <div id={Visualizations.NodeLink} className="tabContent w-full h-full"> - <NodeLinkVis /> - </div> - ); - case Visualizations.RawJSON: - return ( - <div id={Visualizations.RawJSON} className="tabContent w-full h-full"> - <RawJSONVis /> - </div> - ); - case Visualizations.Paohvis: - return ( - <div id={Visualizations.Paohvis} className="tabContent w-full h-full"> - <PaohVis rowHeight={30} hyperedgeColumnWidth={30} gapBetweenRanges={3} /> - </div> - ); - default: - return null; - } - }, [graphQueryResult, vis]); + const createVisComponent = createVisualizationComponent(); + const visualizationInstance = createVisComponent(); return ( <div className="vis-panel h-full w-full overflow-y-auto" style={graphQueryResult.nodes.length === 0 ? { overflow: 'hidden' } : {}}> + <VisualizationDialog open={showVisSettings} onClose={() => setShowVisSettings(false)} /> <div className="sticky top-0 flex items-center justify-between z-[2] py-0 px-2 bg-secondary-100 border-b border-secondary-200"> <h1 className="text-xs font-semibold text-secondary-800">{vis.activeVisualization} visualization</h1> <ControlContainer> - <Button type="secondary" variant="ghost" size="xs" iconName="Settings" onClick={() => {}} /> + <Button + type="secondary" + variant="ghost" + size="xs" + iconName="Settings" + onClick={() => { + setShowVisSettings(!showVisSettings); + }} + /> <Button type="secondary" variant="ghost" @@ -74,13 +45,13 @@ export const VisualizationPanel = () => { /> {visDropdownOpen && ( <DropdownItemContainer align="top-6 right-6"> - {Object.keys(visOptions).map((key) => ( + {Object.keys(Visualizations).map((key) => ( <DropdownItem key={key} value={key} onClick={() => { - visOptions[key](); setVisDropdownOpen(false); + dispatch(setActiveVisualization(Visualizations[key as keyof typeof Visualizations])); }} /> ))} @@ -89,18 +60,17 @@ export const VisualizationPanel = () => { </ControlContainer> </div> - {graphQueryResult.queryingBackend && ( + {graphQueryResult.queryingBackend ? ( <div className="w-full h-full flex flex-col items-center justify-center overflow-hidden"> <LoadingSpinner>Querying backend...</LoadingSpinner> </div> - )} - {!graphQueryResult.queryingBackend && graphQueryResult.nodes.length === 0 ? ( + ) : graphQueryResult.nodes.length === 0 ? ( <div className="w-full h-full flex flex-col items-center justify-center"> <p>No data available to be shown</p> {query.nodes.length > 0 ? <p>Query resulted in empty dataset</p> : <p>Query for data to visualize</p>} </div> ) : ( - <div className="w-full h-full">{visualizationComponent}</div> + <div className="w-full h-full">{visualizationInstance}</div> )} </div> ); diff --git a/apps/web/src/app/panels/VisualizationDialog.tsx b/apps/web/src/app/panels/VisualizationDialog.tsx new file mode 100644 index 0000000000000000000000000000000000000000..2c360bfc93ed573366bfa22684e4a0d9209c84aa --- /dev/null +++ b/apps/web/src/app/panels/VisualizationDialog.tsx @@ -0,0 +1,106 @@ +import React, { useState, useEffect } from 'react'; +import { FormActions, FormBody, FormCard, FormControl, FormDiv, FormHBar, FormTitle } from '@graphpolaris/shared/lib/components/forms'; +import { DialogProps } from '@graphpolaris/shared/lib/components/Dialog'; +import { useAppDispatch, useVisualizationState } from '@graphpolaris/shared/lib/data-access'; +import { updateGeneralSettings, updateVisualizationSettings } from '@graphpolaris/shared/lib/data-access/store/visualizationSlice'; +import Input from '@graphpolaris/shared/lib/components/inputs'; +import { globalConfigSchemaTypes, localConfigSchemaType } from '@graphpolaris/shared/lib/vis/Types'; + +export default function VisualizationDialog(props: DialogProps) { + const dispatch = useAppDispatch(); + const vis = useVisualizationState(); + const [settingsGeneral, setSettingsGeneral] = useState<globalConfigSchemaTypes>(vis.settings.general); + const [settingsSpecific, setSettingsSpecific] = useState<localConfigSchemaType>(vis.settings[vis.activeVisualization]); + + useEffect(() => { + if (vis.settings.general !== settingsGeneral) { + dispatch(updateGeneralSettings(settingsGeneral)); + } + }, [settingsGeneral]); + + useEffect(() => { + if (vis.settings[vis.activeVisualization] !== settingsSpecific) { + dispatch( + updateVisualizationSettings({ + id: vis.activeVisualization, + settings: settingsSpecific, + }), + ); + } + }, [settingsSpecific]); + + useEffect(() => { + setSettingsSpecific(vis.settings[vis.activeVisualization]); + }, [vis.settings[vis.activeVisualization]]); + + return ( + <> + {props.open && ( + <FormDiv> + <FormCard> + <FormBody + onSubmit={(e) => { + e.preventDefault(); + props.onClose(); + }} + > + <FormTitle title="Settings" onClose={props.onClose} /> + <FormHBar /> + + {settingsGeneral && ( + <> + <p className="font-sm font-bold pl-2">General</p> + {Object.keys(settingsGeneral).map((val) => ( + <FormControl key={val}> + <Input + {...settingsGeneral[val]} + value={vis.settings.general[val].value as any} + onChange={(value: any) => { + setSettingsGeneral((prevSettings) => ({ + ...prevSettings, + [val]: { ...prevSettings[val], value: value }, + })); + }} + /> + </FormControl> + ))} + </> + )} + + {settingsSpecific && ( + <> + <FormHBar /> + <p className="font-sm font-bold pl-2">Specific</p> + {Object.keys(settingsSpecific).map((val) => { + const currentSetting = settingsSpecific[val]; + const shouldShowSetting = currentSetting.condition ? currentSetting.condition?.(settingsSpecific) : true; + console.log(currentSetting, shouldShowSetting); + return ( + shouldShowSetting && ( + <FormControl key={val}> + <Input + {...settingsSpecific[val]} + value={settingsSpecific[val]?.value as any} + onChange={(value: any) => { + setSettingsSpecific((prevSettings) => ({ + ...prevSettings, + [val]: { ...prevSettings[val], value: value }, + })); + }} + /> + </FormControl> + ) + ); + })} + </> + )} + + <FormHBar /> + <FormActions onClose={props.onClose} /> + </FormBody> + </FormCard> + </FormDiv> + )} + </> + ); +} diff --git a/apps/web/src/components/navbar/DatabaseManagement/forms/AddDatabase/newdatabase.tsx b/apps/web/src/components/navbar/DatabaseManagement/forms/AddDatabase/newdatabase.tsx index ba97cb8333af8d6526aeb038a61dce7adf892774..571d597b324b7f83f6c9b89b59739bf290c0b241 100644 --- a/apps/web/src/components/navbar/DatabaseManagement/forms/AddDatabase/newdatabase.tsx +++ b/apps/web/src/components/navbar/DatabaseManagement/forms/AddDatabase/newdatabase.tsx @@ -216,10 +216,10 @@ export const NewDatabaseForm = (props: { onClose(): void; open: boolean }) => { required value={databaseNameMapping[state.type]} options={databaseNameMapping} - onChange={(value: string) => { + onChange={(value: string | number) => { setState({ ...state, - type: databaseNameMapping.indexOf(value), + type: databaseNameMapping.indexOf(String(value)), }); }} /> @@ -230,10 +230,10 @@ export const NewDatabaseForm = (props: { onClose(): void; open: boolean }) => { required value={state.protocol} options={databaseProtocolMapping} - onChange={(value: string) => { + onChange={(value: string | number) => { setState({ ...state, - protocol: value, + protocol: String(value), }); }} /> diff --git a/apps/web/src/components/navbar/DatabaseManagement/forms/settings.tsx b/apps/web/src/components/navbar/DatabaseManagement/forms/settings.tsx index 109aa2953249eb2be4159a3270027d784be9f1cc..9c6fc99afd4806f72bb04918bb65d9f01ec73c45 100644 --- a/apps/web/src/components/navbar/DatabaseManagement/forms/settings.tsx +++ b/apps/web/src/components/navbar/DatabaseManagement/forms/settings.tsx @@ -163,10 +163,10 @@ export const SettingsForm = (props: { onClose(): void; open: boolean; database: required value={databaseNameMapping[state.type]} options={databaseNameMapping} - onChange={(value: string) => { + onChange={(value: string | number) => { setState({ ...state, - type: databaseNameMapping.indexOf(value), + type: databaseNameMapping.indexOf(String(value)), }); }} /> @@ -177,10 +177,10 @@ export const SettingsForm = (props: { onClose(): void; open: boolean; database: required value={state.protocol} options={databaseProtocolMapping} - onChange={(value: string) => { + onChange={(value: string | number) => { setState({ ...state, - protocol: value, + protocol: String(value), }); }} /> diff --git a/libs/shared/lib/components/buttons/buttons.module.scss.d.ts b/libs/shared/lib/components/buttons/buttons.module.scss.d.ts index 3165183bcc43cd371b85d32e546d2904b856a67e..090a2928f1558d1bcecbdbfd73ac9089eea3458f 100644 --- a/libs/shared/lib/components/buttons/buttons.module.scss.d.ts +++ b/libs/shared/lib/components/buttons/buttons.module.scss.d.ts @@ -1,7 +1,6 @@ declare const classNames: { readonly btn: 'btn'; readonly 'btn-lg': 'btn-lg'; - readonly '5': '5'; readonly 'btn-icon-only': 'btn-icon-only'; readonly 'btn-md': 'btn-md'; readonly 'btn-sm': 'btn-sm'; diff --git a/libs/shared/lib/components/inputs/index.tsx b/libs/shared/lib/components/inputs/index.tsx index 1681881cafecf3a63491ea7d756e74d5a5d09e06..1a3c860d85d49bb9d30e5a3c10fd3d5fd7edf6ee 100644 --- a/libs/shared/lib/components/inputs/index.tsx +++ b/libs/shared/lib/components/inputs/index.tsx @@ -2,23 +2,21 @@ import React from 'react'; import styles from './inputs.module.scss'; import { DropdownButton, DropdownContainer, DropdownItem, DropdownItemContainer } from '../dropdowns'; -type BaseProps = { - type: 'slider' | 'text' | 'checkbox' | 'dropdown' | 'radio'; -}; - -type SliderProps = BaseProps & { +type SliderProps = { label: string; + type: 'slider'; value: number; min: number; max: number; step: number; showValue?: boolean; unit?: string; - onChange: (value: number) => void; + onChange?: (value: number) => void; }; -type TextProps = BaseProps & { +type TextProps = { label: string; + type: 'text'; placeholder?: string; value: string; required?: boolean; @@ -26,34 +24,45 @@ type TextProps = BaseProps & { visible?: boolean; disabled?: boolean; validate?: (value: any) => boolean; - onChange: (value: string) => void; + onChange?: (value: string) => void; }; -type CheckboxProps = BaseProps & { +type CheckboxProps = { label?: string; + type: 'checkbox'; options: Array<string>; value: Array<string>; - onChange: (value: Array<string>) => void; + onChange?: (value: Array<string>) => void; +}; + +type BooleanProps = { + label: string; + type: 'boolean'; + options?: any; + value: boolean; + onChange?: (value: boolean) => void; }; -type RadioProps = BaseProps & { +type RadioProps = { label?: string; + type: 'radio'; options: Array<string>; value: string; - onChange: (value: string) => void; + onChange?: (value: string) => void; }; -type DropdownProps = BaseProps & { +type DropdownProps = { label?: string; - value: string; - options: Array<string>; - onChange: (value: string) => void; + value: string | number; + type: 'dropdown'; + options: any; + onChange?: (value: string | number) => void; required?: boolean; }; -type InputProps = SliderProps | TextProps | CheckboxProps | DropdownProps | RadioProps; +export type InputProps = TextProps | SliderProps | CheckboxProps | DropdownProps | RadioProps | BooleanProps; -const Input: React.FC<InputProps> = (props) => { +const Input = (props: InputProps) => { switch (props.type) { case 'slider': return <Slider {...(props as SliderProps)} />; @@ -65,6 +74,8 @@ const Input: React.FC<InputProps> = (props) => { return <DropDown {...(props as DropdownProps)} />; case 'radio': return <Radio {...(props as RadioProps)} />; + case 'boolean': + return <Boolean {...(props as BooleanProps)} />; default: return null; } @@ -90,7 +101,9 @@ export const Slider = ({ label, value, min, max, step, unit, showValue = true, o step={step} value={value} onChange={(e) => { - onChange(parseFloat(e.target.value)); + if (onChange) { + onChange(parseFloat(e.target.value)); + } }} aria-labelledby="input-slider" /> @@ -125,12 +138,14 @@ export const Text = ({ className={`px-3 py-2 bg-light border border-secondary-300 placeholder-secondary-400 focus:outline-none block w-full sm:text-sm focus:ring-1 ${ isValid ? '' : 'input-error' }`} - value={value} + value={value.toString()} onChange={(e) => { if (required && validate) { setIsValid(validate(e.target.value)); } - onChange(e.target.value); + if (onChange) { + onChange(e.target.value); + } }} required={required} disabled={disabled} @@ -152,7 +167,9 @@ export const Radio = ({ label, value, options, onChange }: RadioProps) => { name={option} checked={value === option} onChange={() => { - onChange(option); + if (onChange) { + onChange(option); + } }} className="radio radio-xs radio-primary" /> @@ -179,7 +196,9 @@ export const Checkbox = ({ label, value, options, onChange }: CheckboxProps) => checked={Array.isArray(value) && value.includes(option)} onChange={(event) => { const updatedValue = event.target.checked ? [...value, option] : value.filter((val) => val !== option); - onChange(updatedValue); + if (onChange) { + onChange(updatedValue); + } }} className="checkbox checkbox-xs" /> @@ -190,6 +209,26 @@ export const Checkbox = ({ label, value, options, onChange }: CheckboxProps) => ); }; +export const Boolean = ({ label, value, onChange }: BooleanProps) => { + return ( + <div> + <label className="label cursor-pointer w-fit gap-2 px-0 py-1"> + <span className="label-text">{label}</span> + <input + type="checkbox" + checked={value} + onChange={(event) => { + if (onChange) { + onChange(event.target.checked); + } + }} + className="checkbox checkbox-xs" + /> + </label> + </div> + ); +}; + export const DropDown = ({ label, value, options, onChange, required = false }: DropdownProps) => { const dropdownRef = React.useRef<HTMLDivElement>(null); const [isDropdownOpen, setIsDropdownOpen] = React.useState<boolean>(false); @@ -229,12 +268,15 @@ export const DropDown = ({ label, value, options, onChange, required = false }: {isDropdownOpen && ( <DropdownItemContainer align="left-0"> {options && - options.map((item, index) => ( + options.map((item: any, index: number) => ( <DropdownItem key={index} - value={item} + value={item.toString()} onClick={() => { - onChange(item); + const parsedValue = typeof item === 'number' ? item.toString() : item; + if (onChange) { + onChange(parsedValue); + } setIsDropdownOpen(false); }} /> diff --git a/libs/shared/lib/data-access/store/hooks.ts b/libs/shared/lib/data-access/store/hooks.ts index da9e43a2c896e14594dffa596f640481f647ad30..e22bf1997eea13b269dcf34db7e80b53cc58fb09 100644 --- a/libs/shared/lib/data-access/store/hooks.ts +++ b/libs/shared/lib/data-access/store/hooks.ts @@ -10,7 +10,7 @@ import { } from '@graphpolaris/shared/lib/data-access/store/querybuilderSlice'; import { sessionCacheState } from './sessionSlice'; import { authState } from './authSlice'; -import { visualizationState } from './visualizationSlice'; +import { visualizationState, visualizationSettings } from './visualizationSlice'; import { allMLEnabled, selectML } from './mlSlice'; import { searchResultState, searchResultData, searchResultSchema, searchResultQB, recentSearches } from './searchResultSlice'; @@ -50,3 +50,4 @@ export const useRecentSearches = () => useAppSelector(recentSearches); // Visualization Slices export const useVisualizationState = () => useAppSelector(visualizationState); +export const useVisualizationSettings = () => useAppSelector(visualizationSettings); diff --git a/libs/shared/lib/data-access/store/index.ts b/libs/shared/lib/data-access/store/index.ts index d5ba3f4cbfc749511ab82d1bea8dbd14db6237a0..7bff27287890322aada6b478bfeee1afeddaa318 100644 --- a/libs/shared/lib/data-access/store/index.ts +++ b/libs/shared/lib/data-access/store/index.ts @@ -13,6 +13,7 @@ export { } from './graphQueryResultSlice'; export { mlSlice } from './mlSlice'; export { searchResultSlice } from './searchResultSlice'; +export { visualizationSlice } from './visualizationSlice'; // Exported types export type { Node, Edge, GraphQueryResult } from './graphQueryResultSlice'; diff --git a/libs/shared/lib/data-access/store/visualizationSlice.ts b/libs/shared/lib/data-access/store/visualizationSlice.ts index b7415b4573a5bd31c83740726c0bda4bf7061d21..d149f2f63db4af413c320c9ae0e0900da9c0970a 100644 --- a/libs/shared/lib/data-access/store/visualizationSlice.ts +++ b/libs/shared/lib/data-access/store/visualizationSlice.ts @@ -1,32 +1,78 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import type { RootState } from './store'; +import { globalConfigSchemaTypes, localConfigSchemaType } from '../../vis/Types'; export enum Visualizations { - NodeLink = 'NodeLink', - Paohvis = 'Paohvis', - RawJSON = 'RawJSON', - Table = 'Table', + NodeLink = 'NodeLinkVis', + Paohvis = 'PaohVis', + RawJSON = 'RawJSONVis', + Table = 'TableVis', } type VisState = { activeVisualization: Visualizations; + settings: { + general: globalConfigSchemaTypes; + [id: string]: localConfigSchemaType; + }; }; export const initialState: VisState = { activeVisualization: Visualizations.NodeLink, + settings: { + general: { + // Example general setting + showLegend: { + value: false, + label: 'Show legend', + type: 'boolean', + }, + }, + }, }; export const visualizationSlice = createSlice({ name: 'visualization', initialState, reducers: { + addVisualization: (state, action: PayloadAction<{ id: string; settings: localConfigSchemaType }>) => { + const { id, settings } = action.payload; + state.settings[id] = settings; + }, + removeVisualization: (state, action: PayloadAction<string>) => { + if (state.settings[action.payload]) { + delete state.settings[action.payload]; + } + }, + updateVisualizationSettings: (state, action: PayloadAction<{ id: string; settings: any }>) => { + const { id, settings } = action.payload; + state.settings[id] = { ...state.settings[id], ...settings }; + }, + updateGeneralSettings: (state, action: PayloadAction<any>) => { + state.settings.general = action.payload; + }, setActiveVisualization: (state, action: PayloadAction<Visualizations>) => { state.activeVisualization = action.payload; }, + updateSettings: (state, action: PayloadAction<any>) => { + state.settings.visualization = action.payload; + }, }, }); -export const { setActiveVisualization } = visualizationSlice.actions; +export const { + addVisualization, + removeVisualization, + updateVisualizationSettings, + updateGeneralSettings, + setActiveVisualization, + updateSettings, +} = visualizationSlice.actions; export const visualizationState = (state: RootState) => state.visualize; +export const visualizationSettings = (state: RootState) => ({ + general: state.visualize.settings.general, + [state.visualize.activeVisualization]: state.visualize.settings[state.visualize.activeVisualization], +}); + export default visualizationSlice.reducer; diff --git a/libs/shared/lib/schema/panel/schemaDialog.tsx b/libs/shared/lib/schema/panel/schemaDialog.tsx index 54b8ad354804cd3db8ee758521418e2af3183858..e8fbeaca863adff9c9be465d428150acb71d9b6e 100644 --- a/libs/shared/lib/schema/panel/schemaDialog.tsx +++ b/libs/shared/lib/schema/panel/schemaDialog.tsx @@ -73,7 +73,7 @@ export const SchemaDialog = (props: DialogProps) => { label="Type of Connection" value={state.connectionType} options={['Default', 'Step', 'Straight', 'Bezier']} - onChange={(value: string) => { + onChange={(value: string | number) => { setState({ ...state, connectionType: value as any }); }} /> @@ -85,7 +85,7 @@ export const SchemaDialog = (props: DialogProps) => { label="Layout Type" value={state.layoutName} options={Object.values(Layouts)} - onChange={(value: string) => { + onChange={(value: string | number) => { setState({ ...state, layoutName: value as any }); }} /> diff --git a/libs/shared/lib/vis/Types.tsx b/libs/shared/lib/vis/Types.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4c66c45b7920a3cc7c095fcc9704e91a336ce994 --- /dev/null +++ b/libs/shared/lib/vis/Types.tsx @@ -0,0 +1,49 @@ +import { NodeLinkProps, PaohVisProps, RawJSONVisProps, SemanticSubstratesProps, TableProps } from './visualizations'; +import { GraphQueryResult } from '../data-access/store/graphQueryResultSlice'; +import { ML } from '../data-access/store/mlSlice'; +import { SchemaGraph } from '../schema'; +import type { AppDispatch } from '../data-access'; +import { InputProps } from '../components/inputs'; +import { FC } from 'react'; +import { Visualizations } from '.'; + +export type settingConifgTypes = InputProps; + +export type globalConfigSchemaTypes = { + [id: string]: settingConifgTypes; +}; + +export type globalConfigPropTypes = { + [id: string]: any; +}; + +export type localConfigSchemaType = { + [id: string]: settingConifgTypes & { condition?: (config: Record<string, any>) => boolean }; +}; + +export type localConfigPropTypes<T extends keyof typeof Visualizations> = T extends 'TableVis' + ? TableProps + : T extends 'PaohVis' + ? PaohVisProps + : T extends 'RawJSONVis' + ? RawJSONVisProps + : T extends 'SemanticSubstrates' + ? SemanticSubstratesProps + : T extends 'NodeLinkVis' + ? NodeLinkProps + : never; + +export type VISComponentType = { + displayName: string; + VIS: FC<any>; + localConfigSchema: localConfigSchemaType; +}; + +export type VisualizationPropTypes<T extends keyof typeof Visualizations> = { + data: GraphQueryResult; + schema: SchemaGraph; + ml: ML; + dispatch: AppDispatch; + globalConfig: globalConfigPropTypes; + localConfig: localConfigPropTypes<T>; +}; diff --git a/libs/shared/lib/vis/documentation.mdx b/libs/shared/lib/vis/documentation.mdx new file mode 100644 index 0000000000000000000000000000000000000000..34ce016ac09d99ac5a2c8652283d1356635c1fdb --- /dev/null +++ b/libs/shared/lib/vis/documentation.mdx @@ -0,0 +1,152 @@ +import { Meta, Unstyled } from '@storybook/blocks'; + +<Meta title="Visualizations/Implementation" /> + +# Visualization documentation + +## Contents + +1. [Introduction](#Introduction) +2. [Overview](#Overview) +3. [Implementation](#Implementation) +4. [Props](#Props) + +## Introduction + +This is the documentation for implementing visualizations within the GraphPolaris system. + +## Overview + +The basic code implementation looks like this: + +```jsx +import React from 'react'; +import { VisualizationPropTypes, VISComponentType, localConfigSchemaType } from '@graphpolaris/shared/lib/vis/Types'; + +/** + * Props specific to the Visualization component. + */ +export type VisualizationProps = {}; + +/** + * Visualization Component + * @param {object} props - Props for the Visualization component. + * @param {GraphQueryResult} props.data - Queried data from the database. + * @param {object} props.schema - Database schema. + * @param {any} props.ml - Machine-learning results. + * @param {function} props.dispatch - Redux dispatch for state management. + * @param {object} props.globalConfig - Global configurations for the panel (applicable to all visualizations). + * @param {object} props.localConfig - Local configuration props unique to this visualization. + * @returns {JSX.Element} - Rendered content of the visualization. + */ +export const Visualization = ({ data, schema, ml, dispatch, globalConfig, localConfig }: VisualizationPropTypes) => { + // Perform additional processing specific to this visualization using the provided props + + return ( + // Rendered visualization content + ); +}; + +/** + * Schema for local configuration attributes. + */ +const localConfigSchema: localConfigSchemaType = {}; + +/** + * Visualization Component Object + * Contains information and configurations for the exported visualization component. + */ +export const VisualizationComponent: VISComponentType = { + displayName: 'Visualization', + VIS: Visualization, + localConfigSchema: localConfigSchema, +}; +``` + +## Implementation + +### VisualizationProps + +This is where the types are defined for the local configuration of the visualization. It has to define all values that are in the localConfigSchema. This is exported and used in the visualization factory for the local config types. + +Example: + +```jsx +export type TableProps = { + showBarplot: boolean, + itemsPerPage: number, +}; +``` + +### localConfigSchema + +Here are the parameters set that can be changed by a user. These values are displayed in the settings panel. It needs to be in the form of a reusable input component. + +Example: + +```jsx +const localConfigSchema: localConfigSchemaType = { + showBarplot: { + value: true, + type: 'boolean', + label: 'Show barplot', + }, + itemsPerPage: { + value: 10, + type: 'dropdown', + label: 'Items per page', + options: [10, 20, 30], + }, +}; +``` + +#### Conditional rendering + +It is possible to only show certain settings based on a condition. + +```jsx +const localConfigSchema: localConfigSchemaType = { + showBarplot: { + value: true, + type: 'boolean', + label: 'Show barplot', + }, + itemsPerPage: { + value: 10, + type: 'dropdown', + label: 'Items per page', + options: [10, 20, 30], + condition: (localConf) => localConf.showBarplot.value === false, + }, +}; +``` + +### VisualizationComponent + +The visualization component is what gets exported and is used in the factory. It must have a displayName, VIS and localConfigSchema. + +## Props + +### Data prop + +Contains the queried data from the database. + +### Schema prop + +Contains the database schema. + +### ML prop + +Contains the Machine-Learning results. + +### Dispatch prop + +Contains the dispatch for the redux state. + +### Global config prop + +Contains the global configurations for the panel that is the same for every visualization. + +### Local config prop + +Contains the local config props that are unique per visualization. diff --git a/libs/shared/lib/vis/index.tsx b/libs/shared/lib/vis/index.tsx new file mode 100644 index 0000000000000000000000000000000000000000..3abc7b697884c0527d0b103751d3d60aa79480e1 --- /dev/null +++ b/libs/shared/lib/vis/index.tsx @@ -0,0 +1,79 @@ +import React from 'react'; +import { useAppDispatch } from '@graphpolaris/shared/lib/data-access'; +import { addVisualization } from '../data-access/store/visualizationSlice'; +import { + useGraphQueryResult, + useML, + useSchemaGraph, + useVisualizationSettings, + useVisualizationState, +} from '@graphpolaris/shared/lib/data-access/store/hooks'; +import { localConfigPropTypes, globalConfigPropTypes, VISComponentType } from './Types'; +import { NodeLinkComponent, PaohVisComponent, RawJSONComponent, TableComponent } from './visualizations'; + +// export * from './rawjsonvis'; +// export * from './nodelink/nodelinkvis'; +// export * from './paohvis/paohvis'; +// export * from './semanticsubstrates/semanticsubstrates'; +// export * from './table_vis/tableVis'; +// export * from './mapvis/mapvis'; + +export const Visualizations = { + TableVis: TableComponent, + PaohVis: PaohVisComponent, + RawJSONVis: RawJSONComponent, + NodeLinkVis: NodeLinkComponent, + MapVis: '', +}; + +export const createVisualizationComponent = () => { + return () => { + const dispatch = useAppDispatch(); + const vis = useVisualizationState(); + const settings = useVisualizationSettings(); + const graphQueryResult = useGraphQueryResult(); + const schema = useSchemaGraph(); + const ml = useML(); + + const VisualizationComponent: VISComponentType = Visualizations[vis.activeVisualization]; + + React.useEffect(() => { + dispatch(addVisualization({ id: VisualizationComponent.displayName, settings: VisualizationComponent.localConfigSchema })); + }, [vis.activeVisualization]); + + const globalConfig: globalConfigPropTypes = + settings.general && + Object.keys(settings.general).reduce((propsObject, val) => { + return { + ...propsObject, + [val]: vis.settings.general[val].value, + }; + }, {}); + + const displayName = vis.activeVisualization as keyof typeof Visualizations; + + const localConfig: localConfigPropTypes<typeof displayName> = + settings[vis.activeVisualization] && + (Object.keys(settings[vis.activeVisualization]).reduce((propsObject, val) => { + return { + ...propsObject, + [val]: vis.settings[vis.activeVisualization][val].value, + }; + }, {}) as localConfigPropTypes<typeof displayName>); + + return ( + localConfig && ( + <div className="w-full h-full"> + <VisualizationComponent.VIS + data={graphQueryResult} + schema={schema} + ml={ml} + dispatch={dispatch} + globalConfig={globalConfig} + localConfig={localConfig} + /> + </div> + ) + ); + }; +}; diff --git a/libs/shared/lib/vis/mapvis/mapvis.stories.tsx b/libs/shared/lib/vis/mapvis/mapvis.stories.tsx deleted file mode 100644 index 195aebdf7988e798fc19e5cd2444948c2fc52fe5..0000000000000000000000000000000000000000 --- a/libs/shared/lib/vis/mapvis/mapvis.stories.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import React from 'react'; -import MapVis from './mapvis'; -import { Provider } from 'react-redux'; -import { configureStore } from '@reduxjs/toolkit'; -import { assignNewGraphQueryResult, graphQueryResultSlice } from '../../data-access/store'; -import { mockMobilityQueryResult, bigMockQueryResults } from '../../mock-data'; - -const Mockstore = configureStore({ - reducer: { - graphQueryResult: graphQueryResultSlice.reducer, - }, -}); - -export default { - title: 'Visualizations/MapVis', - component: MapVis, - decorators: [ - (story: any) => ( - <Provider store={Mockstore}> - <div - style={{ - width: '100%', - height: '100vh', - }} - > - {story()} - </div> - </Provider> - ), - ], -}; - -const Template = (args: any) => <MapVis {...args} />; - -export const DutchVehicleTheft: any = Template.bind({}); -DutchVehicleTheft.play = async () => { - const dispatch = Mockstore.dispatch; - dispatch(assignNewGraphQueryResult({ queryID: '1', result: { type: 'nodelink', payload: mockMobilityQueryResult } })); -}; - -export const AmericanFlights: any = Template.bind({}); -AmericanFlights.play = async () => { - const dispatch = Mockstore.dispatch; - dispatch(assignNewGraphQueryResult({ queryID: '1', result: { type: 'nodelink', payload: bigMockQueryResults } })); -}; diff --git a/libs/shared/lib/vis/mapvis/mapvis.tsx b/libs/shared/lib/vis/mapvis/mapvis.tsx deleted file mode 100644 index e2a5810ffc99fbad5fad4dd877d4700db7ad14cd..0000000000000000000000000000000000000000 --- a/libs/shared/lib/vis/mapvis/mapvis.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react'; -import {MapPanel, LayerPanel} from './components'; -import {useGraphQueryResult} from '../../data-access/store'; -import GraphModel from './graphModel'; -import {GraphType, Layer} from './Types'; - -export default function MapVis() { - const [layers, setLayers] = React.useState<Layer[]>([]); - const [showFilter, setShowFilter] = React.useState<boolean>(false); - - const graphQueryResult = useGraphQueryResult(); - if (!graphQueryResult) return <p>No loading graph data</p>; - - let graph: GraphType | null = null; - try { - graph = React.useMemo(() => { - const graphModel = new GraphModel(); - graphModel.consumeMessageFromBackend(graphQueryResult); - return graphModel; - }, [graphQueryResult]); - } catch (error) { - return <p>Error creating graph</p>; - } - - return ( - <div className="flex flex-row justify-between overflow-hidden w-screen h-screen font-sans"> - <MapPanel graph={graph} layers={layers} showFilter={showFilter} setShowFilter={setShowFilter}/> - <LayerPanel layers={layers} setLayers={setLayers} graphInfo={graph.getGraphInfo()} setShowFilter={setShowFilter}/> - </div> - ); -} diff --git a/libs/shared/lib/vis/panel/dialog.tsx b/libs/shared/lib/vis/panel/dialog.tsx new file mode 100644 index 0000000000000000000000000000000000000000..f2559879d11734bb4069627fcb39d85c1b477518 --- /dev/null +++ b/libs/shared/lib/vis/panel/dialog.tsx @@ -0,0 +1,103 @@ +import React, { useState, useEffect } from 'react'; +import { FormActions, FormBody, FormCard, FormControl, FormDiv, FormHBar, FormTitle } from '@graphpolaris/shared/lib/components/forms'; +import { DialogProps } from '@graphpolaris/shared/lib/components/Dialog'; +import { useAppDispatch, useVisualizationState } from '@graphpolaris/shared/lib/data-access'; +import { updateGeneralSettings, updateVisualizationSettings } from '@graphpolaris/shared/lib/data-access/store/visualizationSlice'; +import Input from '@graphpolaris/shared/lib/components/inputs'; +import { globalConfigSchemaTypes, localConfigSchemaType } from '@graphpolaris/shared/lib/vis/Types'; + +export default function VisualizationDialog(props: DialogProps) { + const dispatch = useAppDispatch(); + const vis = useVisualizationState(); + const [settingsGeneral, setSettingsGeneral] = useState<globalConfigSchemaTypes>(vis.settings.general); + const [settingsSpecific, setSettingsSpecific] = useState<localConfigSchemaType>(vis.settings[vis.activeVisualization]); + + useEffect(() => { + if (vis.settings.general !== settingsGeneral) { + dispatch(updateGeneralSettings(settingsGeneral)); + } + }, [settingsGeneral]); + + useEffect(() => { + if (vis.settings[vis.activeVisualization] !== settingsSpecific) { + dispatch( + updateVisualizationSettings({ + id: vis.activeVisualization, + settings: settingsSpecific, + }) + ); + } + }, [settingsSpecific]); + + useEffect(() => { + setSettingsSpecific(vis.settings[vis.activeVisualization]); + }, [vis.settings[vis.activeVisualization]]); + + return ( + <> + {props.open && ( + <FormDiv> + <FormCard> + <FormBody + onSubmit={(e) => { + e.preventDefault(); + props.onClose(); + }} + > + <FormTitle title="Settings" onClose={props.onClose} /> + <FormHBar /> + + {settingsGeneral && ( + <> + {Object.keys(settingsGeneral).map((val) => ( + <FormControl key={val}> + <Input + {...settingsGeneral[val]} + value={vis.settings.general[val].value as any} + onChange={(value: any) => { + setSettingsGeneral((prevSettings) => ({ + ...prevSettings, + [val]: { ...prevSettings[val], value: value }, + })); + }} + /> + </FormControl> + ))} + </> + )} + + {Object.keys(settingsSpecific).length > 0 && ( + <> + <FormHBar /> + {Object.keys(settingsSpecific).map((val) => { + const currentSetting = settingsSpecific[val]; + const shouldShowSetting = currentSetting.condition ? currentSetting.condition?.(settingsSpecific) : true; + return ( + shouldShowSetting && ( + <FormControl key={val}> + <Input + {...settingsSpecific[val]} + value={settingsSpecific[val]?.value as any} + onChange={(value: any) => { + setSettingsSpecific((prevSettings) => ({ + ...prevSettings, + [val]: { ...prevSettings[val], value: value }, + })); + }} + /> + </FormControl> + ) + ); + })} + </> + )} + + <FormHBar /> + <FormActions onClose={props.onClose} /> + </FormBody> + </FormCard> + </FormDiv> + )} + </> + ); +} diff --git a/libs/shared/lib/vis/panel/index.ts b/libs/shared/lib/vis/panel/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..676d864915437918c112b38567a16399a80e5a75 --- /dev/null +++ b/libs/shared/lib/vis/panel/index.ts @@ -0,0 +1 @@ +export * from './visualization'; diff --git a/libs/shared/lib/vis/panel/visualization.tsx b/libs/shared/lib/vis/panel/visualization.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6457f891e207941032f2b52e1343108518a405a5 --- /dev/null +++ b/libs/shared/lib/vis/panel/visualization.tsx @@ -0,0 +1,77 @@ +import React, { useState } from 'react'; +import { useAppDispatch, useGraphQueryResult, useQuerybuilderGraph, useVisualizationState } from '@graphpolaris/shared/lib/data-access'; +import { LoadingSpinner } from '@graphpolaris/shared/lib/components/LoadingSpinner'; +import { Visualizations, setActiveVisualization } from '@graphpolaris/shared/lib/data-access/store/visualizationSlice'; +import { DropdownItem, DropdownItemContainer } from '@graphpolaris/shared/lib/components/dropdowns'; +import ControlContainer from '@graphpolaris/shared/lib/components/controls'; +import { Button } from '@graphpolaris/shared/lib/components/buttons'; +import { createVisualizationComponent } from '../'; +import VisualizationDialog from './dialog'; + +export const VisualizationPanel = () => { + const vis = useVisualizationState(); + const graphQueryResult = useGraphQueryResult(); + const query = useQuerybuilderGraph(); + const dispatch = useAppDispatch(); + const [visDropdownOpen, setVisDropdownOpen] = useState<boolean>(false); + const [showVisSettings, setShowVisSettings] = useState<boolean>(false); + + const createVisComponent = createVisualizationComponent(); + const visualizationInstance = createVisComponent(); + + return ( + <div className="vis-panel h-full w-full overflow-y-auto" style={graphQueryResult.nodes.length === 0 ? { overflow: 'hidden' } : {}}> + <VisualizationDialog open={showVisSettings} onClose={() => setShowVisSettings(false)} /> + <div className="sticky top-0 flex items-center justify-between z-[2] py-0 px-2 bg-secondary-100 border-b border-secondary-200"> + <h1 className="text-xs font-semibold text-secondary-800">{vis.activeVisualization} visualization</h1> + <ControlContainer> + <Button + type="secondary" + variant="ghost" + size="xs" + iconName="Settings" + onClick={() => { + setShowVisSettings(!showVisSettings); + }} + /> + <Button + type="secondary" + variant="ghost" + size="xs" + iconName="Apps" + onClick={() => { + setVisDropdownOpen(!visDropdownOpen); + }} + /> + {visDropdownOpen && ( + <DropdownItemContainer align="top-6 right-6"> + {Object.keys(Visualizations).map((key) => ( + <DropdownItem + key={key} + value={key} + onClick={() => { + setVisDropdownOpen(false); + dispatch(setActiveVisualization(Visualizations[key as keyof typeof Visualizations])); + }} + /> + ))} + </DropdownItemContainer> + )} + </ControlContainer> + </div> + + {graphQueryResult.queryingBackend ? ( + <div className="w-full h-full flex flex-col items-center justify-center overflow-hidden"> + <LoadingSpinner>Querying backend...</LoadingSpinner> + </div> + ) : graphQueryResult.nodes.length === 0 ? ( + <div className="w-full h-full flex flex-col items-center justify-center"> + <p>No data available to be shown</p> + {query.nodes.length > 0 ? <p>Query resulted in empty dataset</p> : <p>Query for data to visualize</p>} + </div> + ) : ( + <div className="w-full h-full">{visualizationInstance}</div> + )} + </div> + ); +}; diff --git a/libs/shared/lib/vis/rawjsonvis/rawjsonvis.tsx b/libs/shared/lib/vis/rawjsonvis/rawjsonvis.tsx deleted file mode 100644 index 51c2ab50018eb5b743a35938cc0fba2c9275064d..0000000000000000000000000000000000000000 --- a/libs/shared/lib/vis/rawjsonvis/rawjsonvis.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { useAppDispatch, useGraphQueryResult } from '../../data-access/store'; -import React, { useEffect, useState } from 'react'; -import ReactJSONView from 'react-json-view'; - -import styles from './rawjsonvis.module.scss'; - -/* eslint-disable-next-line */ -export interface RawJSONVisProps { - loading?: boolean; -} - -export const RawJSONVis = React.memo((props: RawJSONVisProps) => { - const graphQueryResult = useGraphQueryResult(); - const dispatch = useAppDispatch(); - console.log('update rawjson'); - - useEffect(() => { - console.log('update rawjson useEffect'); - }, [graphQueryResult]); - - useEffect(() => { - return () => { - console.log('unloaded RawJSONVis'); - }; - }, []); - - const loading = props.loading; - - return ( - <div> - {loading && ( - <div - style={{ - marginTop: '50px', - paddingLeft: '30px', - }} - > - <svg className={styles.rotating} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"> - <circle className={styles.ring} cx="25" cy="25" r="20"></circle> - <circle className={styles.ball} cx="25" cy="5" r="3.5"></circle> - </svg> - </div> - )} - {!loading && ( - <div style={{ overflowY: 'auto' }}> - <div - style={{ - marginTop: '50px', - paddingLeft: '30px', - }} - className="font-mono text-sm" - > - <ReactJSONView src={graphQueryResult} collapsed={1} quotesOnKeys={false} displayDataTypes={false} /> - </div> - </div> - )} - </div> - ); -}); - -RawJSONVis.displayName = 'RawJSONVis'; diff --git a/libs/shared/lib/vis/shared/ResultNodeLinkParserUseCase.tsx b/libs/shared/lib/vis/shared/ResultNodeLinkParserUseCase.tsx index 22fcd08e2fd28d29349a4066865409049e9fa8e7..0154edafb03e8dd42f798fe48e5d761004b36c7c 100644 --- a/libs/shared/lib/vis/shared/ResultNodeLinkParserUseCase.tsx +++ b/libs/shared/lib/vis/shared/ResultNodeLinkParserUseCase.tsx @@ -3,7 +3,7 @@ * Utrecht University within the Software Project course. * © Copyright Utrecht University (Department of Information and Computing Sciences) */ -import { GraphType, LinkType, NodeType } from '../nodelink/Types'; +import { GraphType, LinkType, NodeType } from '../visualizations/nodelink/Types'; import { Edge, Node, GraphQueryResult } from '../../data-access/store'; import { ML } from '../../data-access/store/mlSlice'; /** ResultNodeLinkParserUseCase implements methods to parse and translate websocket messages from the backend into a GraphType. */ diff --git a/libs/shared/lib/vis/table_vis/tableVis.tsx b/libs/shared/lib/vis/table_vis/tableVis.tsx deleted file mode 100644 index b15ade80aa926928d00e643cef44607d7bb119fa..0000000000000000000000000000000000000000 --- a/libs/shared/lib/vis/table_vis/tableVis.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { useGraphQueryResult, useSchemaGraph } from '../../data-access/store'; -import React, { useMemo, useRef } from 'react'; -import { Table, AugmentedNodeAttributes } from './components/Table'; -import { SchemaAttribute } from '../../schema'; - -export const TableVis = React.memo(({ showBarplot }: { showBarplot: boolean }) => { - const ref = useRef<HTMLDivElement>(null); - const graphQueryResult = useGraphQueryResult(); - const schema = useSchemaGraph(); - - const attributesArray = useMemo<AugmentedNodeAttributes[]>( - () => - graphQueryResult.nodes.map((node) => { - const types: SchemaAttribute[] = - schema.nodes.find((n) => n.key === node.label)?.attributes?.attributes ?? - schema.edges.find((r) => r.key === node.label)?.attributes?.attributes ?? - []; - - return { - attribute: node.attributes, - type: Object.fromEntries(types.map((t) => [t.name, t.type])), - }; - }), - [graphQueryResult.nodes], - ); - - return ( - <> - <div className="h-full w-full" ref={ref}> - {attributesArray.length > 0 && <Table data={attributesArray} itemsPerPage={10} showBarPlot={showBarplot} />} - </div> - </> - ); -}); - -TableVis.displayName = 'TableVis'; - -export default TableVis; diff --git a/libs/shared/lib/vis/index.ts b/libs/shared/lib/vis/visualizations/index.tsx similarity index 82% rename from libs/shared/lib/vis/index.ts rename to libs/shared/lib/vis/visualizations/index.tsx index 29b87b7d31ae86c1be6a6aa160248af8e88fd5e1..f47266be85680a5427198e8ab4485dabd18a56ca 100644 --- a/libs/shared/lib/vis/index.ts +++ b/libs/shared/lib/vis/visualizations/index.tsx @@ -3,4 +3,3 @@ export * from './nodelink/nodelinkvis'; export * from './paohvis/paohvis'; export * from './semanticsubstrates/semanticsubstrates'; export * from './table_vis/tableVis'; -// export * from './geovis/NodeLinkMap'; diff --git a/libs/shared/lib/vis/mapvis/README.md b/libs/shared/lib/vis/visualizations/mapvis/README.md similarity index 100% rename from libs/shared/lib/vis/mapvis/README.md rename to libs/shared/lib/vis/visualizations/mapvis/README.md diff --git a/libs/shared/lib/vis/mapvis/Types.tsx b/libs/shared/lib/vis/visualizations/mapvis/Types.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/Types.tsx rename to libs/shared/lib/vis/visualizations/mapvis/Types.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/NodeLinkMap.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/NodeLinkMap.tsx similarity index 97% rename from libs/shared/lib/vis/mapvis/archive/geovis/NodeLinkMap.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/NodeLinkMap.tsx index 0a791268c98c54fe8670d6b8e512e5e880b4e902..3b05544865e99a18db3c8e4bf4ddb15e05a77dd6 100644 --- a/libs/shared/lib/vis/mapvis/archive/geovis/NodeLinkMap.tsx +++ b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/NodeLinkMap.tsx @@ -5,7 +5,7 @@ */ import React, { useState } from 'react'; -import { useGraphQueryResult } from '../../../../data-access/store'; +import { useGraphQueryResult } from '../../../../../data-access'; import { MapView, PickingInfo } from '@deck.gl/core/typed'; import DeckGL from '@deck.gl/react/typed'; import { getTooltip } from './Tooltip'; diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/Tooltip.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/Tooltip.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/Tooltip.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/Tooltip.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/archive/NodeLinkViewModel.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/archive/NodeLinkViewModel.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/archive/NodeLinkViewModel.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/archive/NodeLinkViewModel.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/archive/aggregateCommand.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/archive/aggregateCommand.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/archive/aggregateCommand.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/archive/aggregateCommand.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/archive/unfoldingEdges.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/archive/unfoldingEdges.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/archive/unfoldingEdges.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/archive/unfoldingEdges.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/archive/viewModel.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/archive/viewModel.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/archive/viewModel.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/archive/viewModel.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/config.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/config.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/config.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/config.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/core/attributeFaceting.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/core/attributeFaceting.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/core/attributeFaceting.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/core/attributeFaceting.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/core/edge.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/core/edge.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/core/edge.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/core/edge.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/core/graph.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/core/graph.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/core/graph.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/core/graph.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/core/index.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/core/index.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/core/index.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/core/index.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/core/node.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/core/node.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/core/node.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/core/node.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/layers/GeoBaseLayer.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/layers/GeoBaseLayer.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/layers/GeoBaseLayer.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/layers/GeoBaseLayer.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/layers/GeoClusterLayer.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/layers/GeoClusterLayer.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/layers/GeoClusterLayer.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/layers/GeoClusterLayer.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/layers/GeoFacetingLayer.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/layers/GeoFacetingLayer.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/layers/GeoFacetingLayer.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/layers/GeoFacetingLayer.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/layers/GeoNodeLinkLayer.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/layers/GeoNodeLinkLayer.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/layers/GeoNodeLinkLayer.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/layers/GeoNodeLinkLayer.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/layers/index.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/layers/index.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/layers/index.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/layers/index.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/readability.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/readability.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/readability.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/readability.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/types.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/types.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/types.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/types.tsx diff --git a/libs/shared/lib/vis/mapvis/archive/geovis/utils.tsx b/libs/shared/lib/vis/visualizations/mapvis/archive/geovis/utils.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/archive/geovis/utils.tsx rename to libs/shared/lib/vis/visualizations/mapvis/archive/geovis/utils.tsx diff --git a/libs/shared/lib/vis/mapvis/components/BaseMap.tsx b/libs/shared/lib/vis/visualizations/mapvis/components/BaseMap.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/components/BaseMap.tsx rename to libs/shared/lib/vis/visualizations/mapvis/components/BaseMap.tsx diff --git a/libs/shared/lib/vis/mapvis/components/FilterMenu.tsx b/libs/shared/lib/vis/visualizations/mapvis/components/FilterMenu.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/components/FilterMenu.tsx rename to libs/shared/lib/vis/visualizations/mapvis/components/FilterMenu.tsx diff --git a/libs/shared/lib/vis/mapvis/components/LayerPanel.tsx b/libs/shared/lib/vis/visualizations/mapvis/components/LayerPanel.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/components/LayerPanel.tsx rename to libs/shared/lib/vis/visualizations/mapvis/components/LayerPanel.tsx diff --git a/libs/shared/lib/vis/mapvis/components/MapPanel.tsx b/libs/shared/lib/vis/visualizations/mapvis/components/MapPanel.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/components/MapPanel.tsx rename to libs/shared/lib/vis/visualizations/mapvis/components/MapPanel.tsx diff --git a/libs/shared/lib/vis/mapvis/components/SecondaryMenu.tsx b/libs/shared/lib/vis/visualizations/mapvis/components/SecondaryMenu.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/components/SecondaryMenu.tsx rename to libs/shared/lib/vis/visualizations/mapvis/components/SecondaryMenu.tsx diff --git a/libs/shared/lib/vis/mapvis/components/SelectedMenu.tsx b/libs/shared/lib/vis/visualizations/mapvis/components/SelectedMenu.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/components/SelectedMenu.tsx rename to libs/shared/lib/vis/visualizations/mapvis/components/SelectedMenu.tsx diff --git a/libs/shared/lib/vis/mapvis/components/index.tsx b/libs/shared/lib/vis/visualizations/mapvis/components/index.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/components/index.tsx rename to libs/shared/lib/vis/visualizations/mapvis/components/index.tsx diff --git a/libs/shared/lib/vis/mapvis/graphModel.tsx b/libs/shared/lib/vis/visualizations/mapvis/graphModel.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/graphModel.tsx rename to libs/shared/lib/vis/visualizations/mapvis/graphModel.tsx diff --git a/libs/shared/lib/vis/mapvis/layers/choropleth-layer/ChoroplethLayer.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/choropleth-layer/ChoroplethLayer.tsx similarity index 99% rename from libs/shared/lib/vis/mapvis/layers/choropleth-layer/ChoroplethLayer.tsx rename to libs/shared/lib/vis/visualizations/mapvis/layers/choropleth-layer/ChoroplethLayer.tsx index a99e8ac792efb1601bbfab930ad753a5f8e4d3b6..bd72091c9629c31db10417f570f9a29c0c10d3cb 100644 --- a/libs/shared/lib/vis/mapvis/layers/choropleth-layer/ChoroplethLayer.tsx +++ b/libs/shared/lib/vis/visualizations/mapvis/layers/choropleth-layer/ChoroplethLayer.tsx @@ -4,7 +4,7 @@ import { ArcLayer, GeoJsonLayer, ScatterplotLayer } from '@deck.gl/layers/typed' import { getDistance } from '../../utlis'; import * as d3 from 'd3'; import ChoroplethOptions from './ChoroplethOptions'; -import { europeData, usaData, worldData, netherlands } from '../../../../mock-data/geo-json'; +import { europeData, usaData, worldData, netherlands } from '../../../../../mock-data/geo-json'; import { Edge, Node, LayerProps, GeoJSONData } from '../../Types'; export const circumferencesMap = { diff --git a/libs/shared/lib/vis/mapvis/layers/choropleth-layer/ChoroplethOptions.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/choropleth-layer/ChoroplethOptions.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/layers/choropleth-layer/ChoroplethOptions.tsx rename to libs/shared/lib/vis/visualizations/mapvis/layers/choropleth-layer/ChoroplethOptions.tsx diff --git a/libs/shared/lib/vis/mapvis/layers/edge-arc-layer/ArcLayerOptions.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/edge-arc-layer/ArcLayerOptions.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/layers/edge-arc-layer/ArcLayerOptions.tsx rename to libs/shared/lib/vis/visualizations/mapvis/layers/edge-arc-layer/ArcLayerOptions.tsx diff --git a/libs/shared/lib/vis/mapvis/layers/edge-arc-layer/EdgeArcLayer.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/edge-arc-layer/EdgeArcLayer.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/layers/edge-arc-layer/EdgeArcLayer.tsx rename to libs/shared/lib/vis/visualizations/mapvis/layers/edge-arc-layer/EdgeArcLayer.tsx diff --git a/libs/shared/lib/vis/mapvis/layers/edge-layer/EdgeLayer.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/edge-layer/EdgeLayer.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/layers/edge-layer/EdgeLayer.tsx rename to libs/shared/lib/vis/visualizations/mapvis/layers/edge-layer/EdgeLayer.tsx diff --git a/libs/shared/lib/vis/mapvis/layers/edge-layer/EdgeOptions.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/edge-layer/EdgeOptions.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/layers/edge-layer/EdgeOptions.tsx rename to libs/shared/lib/vis/visualizations/mapvis/layers/edge-layer/EdgeOptions.tsx diff --git a/libs/shared/lib/vis/mapvis/layers/heatmap-layer/HeatLayer.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/heatmap-layer/HeatLayer.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/layers/heatmap-layer/HeatLayer.tsx rename to libs/shared/lib/vis/visualizations/mapvis/layers/heatmap-layer/HeatLayer.tsx diff --git a/libs/shared/lib/vis/mapvis/layers/heatmap-layer/HeatLayerOptions.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/heatmap-layer/HeatLayerOptions.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/layers/heatmap-layer/HeatLayerOptions.tsx rename to libs/shared/lib/vis/visualizations/mapvis/layers/heatmap-layer/HeatLayerOptions.tsx diff --git a/libs/shared/lib/vis/mapvis/layers/icon-layer/IconLayer.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/icon-layer/IconLayer.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/layers/icon-layer/IconLayer.tsx rename to libs/shared/lib/vis/visualizations/mapvis/layers/icon-layer/IconLayer.tsx diff --git a/libs/shared/lib/vis/mapvis/layers/icon-layer/IconOptions.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/icon-layer/IconOptions.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/layers/icon-layer/IconOptions.tsx rename to libs/shared/lib/vis/visualizations/mapvis/layers/icon-layer/IconOptions.tsx diff --git a/libs/shared/lib/vis/mapvis/layers/index.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/index.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/layers/index.tsx rename to libs/shared/lib/vis/visualizations/mapvis/layers/index.tsx diff --git a/libs/shared/lib/vis/mapvis/layers/node-layer/NodeLayer.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/node-layer/NodeLayer.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/layers/node-layer/NodeLayer.tsx rename to libs/shared/lib/vis/visualizations/mapvis/layers/node-layer/NodeLayer.tsx diff --git a/libs/shared/lib/vis/mapvis/layers/node-layer/NodeOptions.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/node-layer/NodeOptions.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/layers/node-layer/NodeOptions.tsx rename to libs/shared/lib/vis/visualizations/mapvis/layers/node-layer/NodeOptions.tsx diff --git a/libs/shared/lib/vis/mapvis/layers/nodelink-layer/NodeLinkLayer.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/nodelink-layer/NodeLinkLayer.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/layers/nodelink-layer/NodeLinkLayer.tsx rename to libs/shared/lib/vis/visualizations/mapvis/layers/nodelink-layer/NodeLinkLayer.tsx diff --git a/libs/shared/lib/vis/mapvis/layers/nodelink-layer/NodeLinkOptions.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/nodelink-layer/NodeLinkOptions.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/layers/nodelink-layer/NodeLinkOptions.tsx rename to libs/shared/lib/vis/visualizations/mapvis/layers/nodelink-layer/NodeLinkOptions.tsx diff --git a/libs/shared/lib/vis/mapvis/layers/nodelink-layer/shapeFactory.tsx b/libs/shared/lib/vis/visualizations/mapvis/layers/nodelink-layer/shapeFactory.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/layers/nodelink-layer/shapeFactory.tsx rename to libs/shared/lib/vis/visualizations/mapvis/layers/nodelink-layer/shapeFactory.tsx diff --git a/libs/shared/lib/vis/visualizations/mapvis/mapvis.stories.tsx b/libs/shared/lib/vis/visualizations/mapvis/mapvis.stories.tsx new file mode 100644 index 0000000000000000000000000000000000000000..92ebf0d7e887db417ebb55799638f0e4642f49af --- /dev/null +++ b/libs/shared/lib/vis/visualizations/mapvis/mapvis.stories.tsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { Meta } from '@storybook/react'; +import { VisualizationPanel } from '../../panel/visualization'; +import { Provider } from 'react-redux'; +import { configureStore } from '@reduxjs/toolkit'; +import { + assignNewGraphQueryResult, + graphQueryResultSlice, + querybuilderSlice, + schemaSlice, + visualizationSlice, +} from '../../../data-access/store'; +import { mockMobilityQueryResult, bigMockQueryResults } from '../../../mock-data'; +import { Visualizations, setActiveVisualization } from '@graphpolaris/shared/lib/data-access/store/visualizationSlice'; + +const Component: Meta<typeof VisualizationPanel> = { + title: 'Visualizations/MapVis', + component: VisualizationPanel, + decorators: [ + (story) => ( + <Provider store={Mockstore}> + <div + style={{ + width: '100%', + height: '100vh', + }} + > + {story()} + </div> + </Provider> + ), + ], +}; + +const Mockstore = configureStore({ + reducer: { + schema: schemaSlice.reducer, + graphQueryResult: graphQueryResultSlice.reducer, + visualize: visualizationSlice.reducer, + querybuilder: querybuilderSlice.reducer, + }, +}); + +export const DutchVehicleTheft = { + play: async () => { + const dispatch = Mockstore.dispatch; + dispatch(assignNewGraphQueryResult({ queryID: '1', result: { type: 'nodelink', payload: mockMobilityQueryResult } })); + // dispatch(setActiveVisualization(Visualizations.MapVis)); + }, +}; + +export const AmericanFlights = { + play: async () => { + const dispatch = Mockstore.dispatch; + dispatch(assignNewGraphQueryResult({ queryID: '1', result: { type: 'nodelink', payload: bigMockQueryResults } })); + // dispatch(setActiveVisualization(Visualizations.MapVis)); + }, +}; + +export default Component; diff --git a/libs/shared/lib/vis/visualizations/mapvis/mapvis.tsx b/libs/shared/lib/vis/visualizations/mapvis/mapvis.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4a49bb17f7679f65b15709a66525fa06f4cde83d --- /dev/null +++ b/libs/shared/lib/vis/visualizations/mapvis/mapvis.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { MapPanel, LayerPanel } from './components'; +import GraphModel from './graphModel'; +import { GraphType, Layer } from './Types'; +import { VISComponentType, VisualizationPropTypes, localConfigSchemaType } from '../../Types'; + +export type MapProps = {}; + +const displayName = 'MapVis'; + +export default function MapVis({ data, schema, localConfig }: VisualizationPropTypes<typeof displayName>) { + const [layers, setLayers] = React.useState<Layer[]>([]); + const [showFilter, setShowFilter] = React.useState<boolean>(false); + + let graph: GraphType | null = null; + try { + graph = React.useMemo(() => { + const graphModel = new GraphModel(); + graphModel.consumeMessageFromBackend(data); + return graphModel; + }, [data]); + } catch (error) { + return <p>Error creating graph</p>; + } + + return ( + <div className="flex flex-row justify-between overflow-hidden w-screen h-screen font-sans"> + <MapPanel graph={graph} layers={layers} showFilter={showFilter} setShowFilter={setShowFilter} /> + <LayerPanel layers={layers} setLayers={setLayers} graphInfo={graph.getGraphInfo()} setShowFilter={setShowFilter} /> + </div> + ); +} + +const localConfigSchema: localConfigSchemaType = {}; + +export const TableComponent: VISComponentType = { + displayName: displayName, + VIS: MapVis, + localConfigSchema: localConfigSchema, +}; diff --git a/libs/shared/lib/vis/mapvis/shared/ColorPicker.tsx b/libs/shared/lib/vis/visualizations/mapvis/shared/ColorPicker.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/shared/ColorPicker.tsx rename to libs/shared/lib/vis/visualizations/mapvis/shared/ColorPicker.tsx diff --git a/libs/shared/lib/vis/mapvis/utlis.tsx b/libs/shared/lib/vis/visualizations/mapvis/utlis.tsx similarity index 100% rename from libs/shared/lib/vis/mapvis/utlis.tsx rename to libs/shared/lib/vis/visualizations/mapvis/utlis.tsx diff --git a/libs/shared/lib/vis/nodelink/Types.tsx b/libs/shared/lib/vis/visualizations/nodelink/Types.tsx similarity index 100% rename from libs/shared/lib/vis/nodelink/Types.tsx rename to libs/shared/lib/vis/visualizations/nodelink/Types.tsx diff --git a/libs/shared/lib/vis/nodelink/components/NLExport.tsx b/libs/shared/lib/vis/visualizations/nodelink/components/NLExport.tsx similarity index 100% rename from libs/shared/lib/vis/nodelink/components/NLExport.tsx rename to libs/shared/lib/vis/visualizations/nodelink/components/NLExport.tsx diff --git a/libs/shared/lib/vis/nodelink/components/NLForce.tsx b/libs/shared/lib/vis/visualizations/nodelink/components/NLForce.tsx similarity index 100% rename from libs/shared/lib/vis/nodelink/components/NLForce.tsx rename to libs/shared/lib/vis/visualizations/nodelink/components/NLForce.tsx diff --git a/libs/shared/lib/vis/nodelink/components/NLMachineLearning.tsx b/libs/shared/lib/vis/visualizations/nodelink/components/NLMachineLearning.tsx similarity index 97% rename from libs/shared/lib/vis/nodelink/components/NLMachineLearning.tsx rename to libs/shared/lib/vis/visualizations/nodelink/components/NLMachineLearning.tsx index f6f46d863c1d2bdabf304f6e4b4929bee4d701c3..771e88bc6d32182edfa75e8ce9bfb28f98e582c2 100644 --- a/libs/shared/lib/vis/nodelink/components/NLMachineLearning.tsx +++ b/libs/shared/lib/vis/visualizations/nodelink/components/NLMachineLearning.tsx @@ -1,6 +1,6 @@ import { useState } from 'react'; -import { AttributeData, NodeAttributeData } from '../../shared/InputDataTypes'; -import { AttributeCategory } from '../../shared/Types'; +import { AttributeData, NodeAttributeData } from '../../../shared/InputDataTypes'; +import { AttributeCategory } from '../../../shared/Types'; import { GraphType, LinkType, NodeType } from '../Types'; import { ML } from '@graphpolaris/shared/lib/data-access/store/mlSlice'; diff --git a/libs/shared/lib/vis/nodelink/components/NLPixi.tsx b/libs/shared/lib/vis/visualizations/nodelink/components/NLPixi.tsx similarity index 100% rename from libs/shared/lib/vis/nodelink/components/NLPixi.tsx rename to libs/shared/lib/vis/visualizations/nodelink/components/NLPixi.tsx diff --git a/libs/shared/lib/vis/nodelink/components/NLPopup.tsx b/libs/shared/lib/vis/visualizations/nodelink/components/NLPopup.tsx similarity index 100% rename from libs/shared/lib/vis/nodelink/components/NLPopup.tsx rename to libs/shared/lib/vis/visualizations/nodelink/components/NLPopup.tsx diff --git a/libs/shared/lib/vis/nodelink/components/query2NL.tsx b/libs/shared/lib/vis/visualizations/nodelink/components/query2NL.tsx similarity index 98% rename from libs/shared/lib/vis/nodelink/components/query2NL.tsx rename to libs/shared/lib/vis/visualizations/nodelink/components/query2NL.tsx index 57b39f3ba0172100a3f298d595aab53302aa7982..4aa527a8d6b17ee96a80610f2ae528d7d47d97bd 100644 --- a/libs/shared/lib/vis/nodelink/components/query2NL.tsx +++ b/libs/shared/lib/vis/visualizations/nodelink/components/query2NL.tsx @@ -4,8 +4,8 @@ * © Copyright Utrecht University (Department of Information and Computing Sciences) */ import { GraphType, LinkType, NodeType } from '../Types'; -import { Edge, Node, GraphQueryResult } from '../../../data-access/store'; -import { ML } from '../../../data-access/store/mlSlice'; +import { Edge, Node, GraphQueryResult } from '../../../../data-access/store'; +import { ML } from '../../../../data-access/store/mlSlice'; import { processML } from './NLMachineLearning'; /** ResultNodeLinkParserUseCase implements methods to parse and translate websocket messages from the backend into a GraphType. */ @@ -281,7 +281,6 @@ export function parseQueryResult(queryResult: GraphQueryResult, ml: ML, options: // toBeReturned = { ...toBeReturned, ...numberOfClusters }; // } - // return toBeReturned; return processML(ml, toBeReturned); } diff --git a/libs/shared/lib/vis/nodelink/components/utils.tsx b/libs/shared/lib/vis/visualizations/nodelink/components/utils.tsx similarity index 100% rename from libs/shared/lib/vis/nodelink/components/utils.tsx rename to libs/shared/lib/vis/visualizations/nodelink/components/utils.tsx diff --git a/libs/shared/lib/vis/nodelink/nodelinkvis.module.scss b/libs/shared/lib/vis/visualizations/nodelink/nodelinkvis.module.scss similarity index 100% rename from libs/shared/lib/vis/nodelink/nodelinkvis.module.scss rename to libs/shared/lib/vis/visualizations/nodelink/nodelinkvis.module.scss diff --git a/libs/shared/lib/vis/nodelink/nodelinkvis.module.scss.d.ts b/libs/shared/lib/vis/visualizations/nodelink/nodelinkvis.module.scss.d.ts similarity index 100% rename from libs/shared/lib/vis/nodelink/nodelinkvis.module.scss.d.ts rename to libs/shared/lib/vis/visualizations/nodelink/nodelinkvis.module.scss.d.ts diff --git a/libs/shared/lib/vis/nodelink/nodelinkvis.stories.tsx b/libs/shared/lib/vis/visualizations/nodelink/nodelinkvis.stories.tsx similarity index 72% rename from libs/shared/lib/vis/nodelink/nodelinkvis.stories.tsx rename to libs/shared/lib/vis/visualizations/nodelink/nodelinkvis.stories.tsx index 83479342bf3d5191b569939266b7588a7a8e118e..ea402d7a48d619c8d1a186bfeec9a430e9703427 100644 --- a/libs/shared/lib/vis/nodelink/nodelinkvis.stories.tsx +++ b/libs/shared/lib/vis/visualizations/nodelink/nodelinkvis.stories.tsx @@ -1,19 +1,21 @@ import React from 'react'; import { Meta } from '@storybook/react'; -import { NodeLinkVis } from './nodelinkvis'; - -import { assignNewGraphQueryResult, graphQueryResultSlice, resetGraphQueryResults, store } from '../../data-access/store'; +import { VisualizationPanel } from '../../panel/visualization'; +import { + assignNewGraphQueryResult, + graphQueryResultSlice, + querybuilderSlice, + schemaSlice, + visualizationSlice, +} from '../../../data-access/store'; import { configureStore } from '@reduxjs/toolkit'; import { Provider } from 'react-redux'; -import { big2ndChamberQueryResult, smallFlightsQueryResults, mockLargeQueryResults } from '../../mock-data'; +import { big2ndChamberQueryResult, smallFlightsQueryResults, mockLargeQueryResults } from '../../../mock-data'; +import { Visualizations, setActiveVisualization } from '@graphpolaris/shared/lib/data-access/store/visualizationSlice'; -const Component: Meta<typeof NodeLinkVis> = { - /* 👇 The title prop is optional. - * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ +const Component: Meta<typeof VisualizationPanel> = { title: 'Visualizations/NodeLinkVis', - component: NodeLinkVis, + component: VisualizationPanel, decorators: [ (story) => ( <Provider store={Mockstore}> @@ -32,17 +34,18 @@ const Component: Meta<typeof NodeLinkVis> = { const Mockstore = configureStore({ reducer: { + schema: schemaSlice.reducer, graphQueryResult: graphQueryResultSlice.reducer, + visualize: visualizationSlice.reducer, + querybuilder: querybuilderSlice.reducer, }, }); export const TestWithData = { layout: 'fullscreen', - args: { - loading: false, - }, play: async () => { const dispatch = Mockstore.dispatch; + dispatch( assignNewGraphQueryResult({ queryID: '1', @@ -58,6 +61,7 @@ export const TestWithData = { }, }) ); + dispatch(setActiveVisualization(Visualizations.NodeLink)); }, }; @@ -77,14 +81,15 @@ export const TestWithNoData = { }, }) ); + dispatch(setActiveVisualization(Visualizations.NodeLink)); }, }; export const TestWithBig2ndChamber = { - args: { loading: false }, play: async () => { const dispatch = Mockstore.dispatch; dispatch(assignNewGraphQueryResult({ queryID: '1', result: { type: 'nodelink', payload: big2ndChamberQueryResult } })); + dispatch(setActiveVisualization(Visualizations.NodeLink)); }, }; @@ -93,6 +98,7 @@ export const TestWithSmallFlights = { play: async () => { const dispatch = Mockstore.dispatch; dispatch(assignNewGraphQueryResult({ queryID: '1', result: { type: 'nodelink', payload: smallFlightsQueryResults } })); + dispatch(setActiveVisualization(Visualizations.NodeLink)); }, }; @@ -101,6 +107,7 @@ export const TestWithLargeQueryResult = { play: async () => { const dispatch = Mockstore.dispatch; dispatch(assignNewGraphQueryResult({ queryID: '1', result: { type: 'nodelink', payload: mockLargeQueryResults } })); + dispatch(setActiveVisualization(Visualizations.NodeLink)); }, }; diff --git a/libs/shared/lib/vis/nodelink/nodelinkvis.tsx b/libs/shared/lib/vis/visualizations/nodelink/nodelinkvis.tsx similarity index 84% rename from libs/shared/lib/vis/nodelink/nodelinkvis.tsx rename to libs/shared/lib/vis/visualizations/nodelink/nodelinkvis.tsx index 640c11db90d57bd083bbb5e20c5eb8c34a42f04e..8bb1eff66b89c7eece52a00d05ae8e5530a8fdb0 100644 --- a/libs/shared/lib/vis/nodelink/nodelinkvis.tsx +++ b/libs/shared/lib/vis/visualizations/nodelink/nodelinkvis.tsx @@ -1,16 +1,13 @@ -import { useAppDispatch, useGraphQueryResult, useML } from '../../data-access/store'; import React, { useEffect, useRef, useState } from 'react'; import * as PIXI from 'pixi.js'; import { GraphType, LinkType, NodeType } from './Types'; import { NLPixi } from './components/NLPixi'; import { parseQueryResult } from './components/query2NL'; import { useImmer } from 'use-immer'; -import { ML, setShortestPathSource, setShortestPathTarget } from '../../data-access/store/mlSlice'; +import { ML, setShortestPathSource, setShortestPathTarget } from '../../../data-access/store/mlSlice'; +import { VisualizationPropTypes, VISComponentType } from '../../Types'; -interface Props { - loading?: boolean; - // currentColours: any; -} +export interface NodeLinkProps {} /** Return default radius */ function Radius() { @@ -32,28 +29,26 @@ export interface NodeLinkComponentState { scalexy: number; } -export const NodeLinkVis = React.memo((props: Props) => { +const displayName = 'NodeLinkVis'; + +export const NodeLinkVis = React.memo(({ data, ml, dispatch }: VisualizationPropTypes<typeof displayName>) => { const ref = useRef<HTMLDivElement>(null); const [graph, setGraph] = useImmer<GraphType | undefined>(undefined); const [highlightNodes, setHighlightNodes] = useState<NodeType[]>([]); const [highlightedLinks, setHighlightedLinks] = useState<LinkType[]>([]); - const graphQueryResult = useGraphQueryResult(); - const ml = useML(); - const dispatch = useAppDispatch(); - useEffect(() => { - if (graphQueryResult) { - console.debug('graphQueryResult', graphQueryResult); + if (data) { + console.debug('graphQueryResult', data); setGraph( - parseQueryResult(graphQueryResult, ml, { + parseQueryResult(data, ml, { defaultX: (ref.current?.clientWidth || 1000) / 2, defaultY: (ref.current?.clientHeight || 1000) / 2, - }), + }) ); } - }, [graphQueryResult, ml]); + }, [data, ml]); const onClickedNode = (node: NodeType, ml: ML) => { console.log('shortestPath', graph, ml.shortestPath.enabled); @@ -116,6 +111,13 @@ export const NodeLinkVis = React.memo((props: Props) => { </> ); }); -NodeLinkVis.displayName = 'NodeLinkVis'; + +const localConfigSchema = {}; + +export const NodeLinkComponent: VISComponentType = { + displayName: displayName, + VIS: NodeLinkVis, + localConfigSchema: localConfigSchema, +}; export default NodeLinkVis; diff --git a/libs/shared/lib/vis/paohvis/Types.tsx b/libs/shared/lib/vis/visualizations/paohvis/Types.tsx similarity index 100% rename from libs/shared/lib/vis/paohvis/Types.tsx rename to libs/shared/lib/vis/visualizations/paohvis/Types.tsx diff --git a/libs/shared/lib/vis/paohvis/components/HyperEdgesRange.tsx b/libs/shared/lib/vis/visualizations/paohvis/components/HyperEdgesRange.tsx similarity index 100% rename from libs/shared/lib/vis/paohvis/components/HyperEdgesRange.tsx rename to libs/shared/lib/vis/visualizations/paohvis/components/HyperEdgesRange.tsx diff --git a/libs/shared/lib/vis/paohvis/components/MakePaohvisMenu.scss b/libs/shared/lib/vis/visualizations/paohvis/components/MakePaohvisMenu.scss similarity index 100% rename from libs/shared/lib/vis/paohvis/components/MakePaohvisMenu.scss rename to libs/shared/lib/vis/visualizations/paohvis/components/MakePaohvisMenu.scss diff --git a/libs/shared/lib/vis/paohvis/components/MakePaohvisMenu.tsx b/libs/shared/lib/vis/visualizations/paohvis/components/MakePaohvisMenu.tsx similarity index 99% rename from libs/shared/lib/vis/paohvis/components/MakePaohvisMenu.tsx rename to libs/shared/lib/vis/visualizations/paohvis/components/MakePaohvisMenu.tsx index 049efdee8177bbd312095f6032be9c8751ee51e6..0f676c0fa2e0617c393173464e26bcc71cc86337 100644 --- a/libs/shared/lib/vis/paohvis/components/MakePaohvisMenu.tsx +++ b/libs/shared/lib/vis/visualizations/paohvis/components/MakePaohvisMenu.tsx @@ -26,9 +26,9 @@ import { useImmer } from 'use-immer'; import { useGraphQueryResult, useSchemaGraph } from '@graphpolaris/shared/lib/data-access'; import { calculateAttributesAndRelations, calculateAttributesFromRelation } from '../utils/utils'; import calcEntitiesFromQueryResult from '../utils/CalcEntitiesFromQueryResult'; -import { isNodeLinkResult } from '../../shared/ResultNodeLinkParserUseCase'; +import { isNodeLinkResult } from '../../../shared/ResultNodeLinkParserUseCase'; import { select } from 'd3'; -import { Button } from '../../../components/buttons'; +import { Button } from '../../../../components/buttons'; /** The typing for the props of the Paohvis menu */ type MakePaohvisMenuProps = { @@ -38,7 +38,7 @@ type MakePaohvisMenuProps = { relationName: string, isEntityFromRelationFrom: boolean, chosenAttribute: Attribute, - nodeOrder: PaohvisNodeOrder, + nodeOrder: PaohvisNodeOrder ) => void; }; @@ -325,7 +325,7 @@ export const MakePaohvisMenu = (props: MakePaohvisMenuProps) => { { orderBy: state.sortOrder, isReverseOrder: state.isReverseOrder, - }, + } ); } else { setState((draft) => { diff --git a/libs/shared/lib/vis/paohvis/components/PaohvisFilterComponent.module.scss b/libs/shared/lib/vis/visualizations/paohvis/components/PaohvisFilterComponent.module.scss similarity index 100% rename from libs/shared/lib/vis/paohvis/components/PaohvisFilterComponent.module.scss rename to libs/shared/lib/vis/visualizations/paohvis/components/PaohvisFilterComponent.module.scss diff --git a/libs/shared/lib/vis/paohvis/components/PaohvisFilterComponent.module.scss.d.ts b/libs/shared/lib/vis/visualizations/paohvis/components/PaohvisFilterComponent.module.scss.d.ts similarity index 100% rename from libs/shared/lib/vis/paohvis/components/PaohvisFilterComponent.module.scss.d.ts rename to libs/shared/lib/vis/visualizations/paohvis/components/PaohvisFilterComponent.module.scss.d.ts diff --git a/libs/shared/lib/vis/paohvis/components/PaohvisFilterComponent.tsx b/libs/shared/lib/vis/visualizations/paohvis/components/PaohvisFilterComponent.tsx similarity index 99% rename from libs/shared/lib/vis/paohvis/components/PaohvisFilterComponent.tsx rename to libs/shared/lib/vis/visualizations/paohvis/components/PaohvisFilterComponent.tsx index e64495e5391b1b142608b9b750065afb94591d95..de427444589e55e3cdbbfc3b9539bd643a05ec09 100644 --- a/libs/shared/lib/vis/paohvis/components/PaohvisFilterComponent.tsx +++ b/libs/shared/lib/vis/visualizations/paohvis/components/PaohvisFilterComponent.tsx @@ -13,7 +13,7 @@ import styles from './PaohvisFilterComponent.module.scss'; import { AttributeNames, FilterType } from '../Types'; import { useImmer } from 'use-immer'; import { useGraphQueryResult, useSchemaGraph } from '@graphpolaris/shared/lib/data-access'; -import { isNodeLinkResult } from '../../shared/ResultNodeLinkParserUseCase'; +import { isNodeLinkResult } from '../../../shared/ResultNodeLinkParserUseCase'; import { calculateAttributesAndRelations, calculateAttributesFromRelation } from '../utils/utils'; import { boolPredicates, numberPredicates, textPredicates } from '../models/FilterPredicates'; import { style } from 'd3'; diff --git a/libs/shared/lib/vis/paohvis/components/RowLabelColumn.tsx b/libs/shared/lib/vis/visualizations/paohvis/components/RowLabelColumn.tsx similarity index 100% rename from libs/shared/lib/vis/paohvis/components/RowLabelColumn.tsx rename to libs/shared/lib/vis/visualizations/paohvis/components/RowLabelColumn.tsx diff --git a/libs/shared/lib/vis/paohvis/components/Tooltip.scss b/libs/shared/lib/vis/visualizations/paohvis/components/Tooltip.scss similarity index 100% rename from libs/shared/lib/vis/paohvis/components/Tooltip.scss rename to libs/shared/lib/vis/visualizations/paohvis/components/Tooltip.scss diff --git a/libs/shared/lib/vis/paohvis/components/Tooltip.tsx b/libs/shared/lib/vis/visualizations/paohvis/components/Tooltip.tsx similarity index 100% rename from libs/shared/lib/vis/paohvis/components/Tooltip.tsx rename to libs/shared/lib/vis/visualizations/paohvis/components/Tooltip.tsx diff --git a/libs/shared/lib/vis/paohvis/models/FilterPredicates.tsx b/libs/shared/lib/vis/visualizations/paohvis/models/FilterPredicates.tsx similarity index 100% rename from libs/shared/lib/vis/paohvis/models/FilterPredicates.tsx rename to libs/shared/lib/vis/visualizations/paohvis/models/FilterPredicates.tsx diff --git a/libs/shared/lib/vis/paohvis/models/PaohvisHolder.test.tsx b/libs/shared/lib/vis/visualizations/paohvis/models/PaohvisHolder.test.tsx similarity index 100% rename from libs/shared/lib/vis/paohvis/models/PaohvisHolder.test.tsx rename to libs/shared/lib/vis/visualizations/paohvis/models/PaohvisHolder.test.tsx diff --git a/libs/shared/lib/vis/paohvis/models/PaohvisHolder.tsx b/libs/shared/lib/vis/visualizations/paohvis/models/PaohvisHolder.tsx similarity index 100% rename from libs/shared/lib/vis/paohvis/models/PaohvisHolder.tsx rename to libs/shared/lib/vis/visualizations/paohvis/models/PaohvisHolder.tsx diff --git a/libs/shared/lib/vis/paohvis/models/PaohvisListener.tsx b/libs/shared/lib/vis/visualizations/paohvis/models/PaohvisListener.tsx similarity index 100% rename from libs/shared/lib/vis/paohvis/models/PaohvisListener.tsx rename to libs/shared/lib/vis/visualizations/paohvis/models/PaohvisListener.tsx diff --git a/libs/shared/lib/vis/paohvis/paohvis.module.scss b/libs/shared/lib/vis/visualizations/paohvis/paohvis.module.scss similarity index 100% rename from libs/shared/lib/vis/paohvis/paohvis.module.scss rename to libs/shared/lib/vis/visualizations/paohvis/paohvis.module.scss diff --git a/libs/shared/lib/vis/paohvis/paohvis.module.scss.d.ts b/libs/shared/lib/vis/visualizations/paohvis/paohvis.module.scss.d.ts similarity index 100% rename from libs/shared/lib/vis/paohvis/paohvis.module.scss.d.ts rename to libs/shared/lib/vis/visualizations/paohvis/paohvis.module.scss.d.ts diff --git a/libs/shared/lib/vis/paohvis/paohvis.stories.tsx b/libs/shared/lib/vis/visualizations/paohvis/paohvis.stories.tsx similarity index 68% rename from libs/shared/lib/vis/paohvis/paohvis.stories.tsx rename to libs/shared/lib/vis/visualizations/paohvis/paohvis.stories.tsx index e1178e8fa98f2a9b964c94dae3e140fe18bb2a62..96dc4eaa89e94a9654726d5b496cb8b2d674c2e2 100644 --- a/libs/shared/lib/vis/paohvis/paohvis.stories.tsx +++ b/libs/shared/lib/vis/visualizations/paohvis/paohvis.stories.tsx @@ -1,30 +1,35 @@ -import { assignNewGraphQueryResult, graphQueryResultSlice, schemaSlice, setSchema } from '../../data-access/store'; +import { + assignNewGraphQueryResult, + graphQueryResultSlice, + querybuilderSlice, + schemaSlice, + setSchema, + visualizationSlice, +} from '../../../data-access/store'; import { configureStore } from '@reduxjs/toolkit'; -import { Meta, ComponentStory } from '@storybook/react'; +import { Meta } from '@storybook/react'; +import { VisualizationPanel } from '../../panel/visualization'; import { Provider } from 'react-redux'; +import { SchemaUtils } from '../../../schema/schema-utils'; +import { bigMockQueryResults, simpleSchemaRaw, smallFlightsQueryResults } from '../../../mock-data'; +import { simpleSchemaAirportRaw } from '../../../mock-data/schema/simpleAirportRaw'; +import { Visualizations, setActiveVisualization } from '@graphpolaris/shared/lib/data-access/store/visualizationSlice'; -import Paohvis from './paohvis'; -import { SchemaUtils } from '../../schema/schema-utils'; -import { bigMockQueryResults, simpleSchemaRaw, smallFlightsQueryResults } from '../../mock-data'; -import { simpleSchemaAirportRaw } from '../../mock-data/schema/simpleAirportRaw'; - -const Component: Meta<typeof Paohvis> = { - /* 👇 The title prop is optional. - * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ +const Component: Meta<typeof VisualizationPanel> = { title: 'Visualizations/Paohvis', - component: Paohvis, + component: VisualizationPanel, decorators: [ (story) => ( - <div - style={{ - width: '83%', - height: '95vh', - }} - > - <Provider store={Mockstore}>{story()}</Provider> - </div> + <Provider store={Mockstore}> + <div + style={{ + width: '100%', + height: '100vh', + }} + > + {story()} + </div> + </Provider> ), ], }; @@ -33,16 +38,12 @@ const Mockstore = configureStore({ reducer: { schema: schemaSlice.reducer, graphQueryResult: graphQueryResultSlice.reducer, + visualize: visualizationSlice.reducer, + querybuilder: querybuilderSlice.reducer, }, }); export const TestWithData = { - args: { - loading: false, - rowHeight: 30, - hyperedgeColumnWidth: 50, - gapBetweenRanges: 10, - }, play: async () => { const dispatch = Mockstore.dispatch; const schema = SchemaUtils.schemaBackend2Graphology({ @@ -87,38 +88,29 @@ export const TestWithData = { }, }) ); + dispatch(setActiveVisualization(Visualizations.Paohvis)); }, }; export const TestWithAirportSimple = { - args: { - loading: false, - rowHeight: 50, - hyperedgeColumnWidth: 50, - gapBetweenRanges: 10, - }, play: async () => { const dispatch = Mockstore.dispatch; const schema = SchemaUtils.schemaBackend2Graphology(simpleSchemaRaw); dispatch(setSchema(schema.export())); dispatch(assignNewGraphQueryResult({ queryID: '1', result: { type: 'nodelink', payload: smallFlightsQueryResults } })); + dispatch(setActiveVisualization(Visualizations.Paohvis)); }, }; export const TestWithAirport = { - args: { - loading: false, - rowHeight: 30, - hyperedgeColumnWidth: 30, - gapBetweenRanges: 3, - }, play: async () => { const dispatch = Mockstore.dispatch; const schema = SchemaUtils.schemaBackend2Graphology(simpleSchemaAirportRaw); dispatch(setSchema(schema.export())); dispatch(assignNewGraphQueryResult({ queryID: '1', result: { type: 'nodelink', payload: bigMockQueryResults } })); + dispatch(setActiveVisualization(Visualizations.Paohvis)); }, }; diff --git a/libs/shared/lib/vis/paohvis/paohvis.tsx b/libs/shared/lib/vis/visualizations/paohvis/paohvis.tsx similarity index 97% rename from libs/shared/lib/vis/paohvis/paohvis.tsx rename to libs/shared/lib/vis/visualizations/paohvis/paohvis.tsx index d3c435dcce7b9ed57cb75e1c0e6c4143f7414186..59c6653b650ba5742aa735fab22e7f9101945416 100644 --- a/libs/shared/lib/vis/paohvis/paohvis.tsx +++ b/libs/shared/lib/vis/visualizations/paohvis/paohvis.tsx @@ -15,11 +15,11 @@ import { } from './Types'; import { useImmer } from 'use-immer'; -import { getWidthOfText } from '../../schema/schema-utils'; -import { useGraphQueryResult, useSchemaGraph } from '../../data-access'; -import { isNodeLinkResult } from '../shared/ResultNodeLinkParserUseCase'; +import { getWidthOfText } from '../../../schema/schema-utils'; +import { useGraphQueryResult, useSchemaGraph } from '../../../data-access'; +import { isNodeLinkResult } from '../../shared/ResultNodeLinkParserUseCase'; import { calculateAttributesAndRelations, calculateAttributesFromRelation } from './utils/utils'; -import VisConfigPanelComponent from '../shared/VisConfigPanel/VisConfigPanel'; +import VisConfigPanelComponent from '../../shared/VisConfigPanel/VisConfigPanel'; import { PaohvisFilterComponent } from './components/PaohvisFilterComponent'; import Tooltip from './components/Tooltip'; import { pointer, select, selectAll } from 'd3'; @@ -27,6 +27,7 @@ import { HyperEdgeRange } from './components/HyperEdgesRange'; import ToPaohvisDataParserUseCase from './utils/ToPaohvisDataParserUsecase'; import MakePaohvisMenu from './components/MakePaohvisMenu'; import { RowLabelColumn } from './components/RowLabelColumn'; +import { VISComponentType } from '../../Types'; type PaohvisViewModelState = { rowHeight: number; @@ -55,14 +56,14 @@ type PaohvisViewModelState = { }; }; -type Props = { +export type PaohVisProps = { rowHeight: number; hyperedgeColumnWidth: number; gapBetweenRanges: number; data?: PaohvisData; }; -export const PaohVis = (props: Props) => { +export const PaohVis = (props: PaohVisProps) => { const svgRef = useRef<SVGSVGElement>(null); const graphQueryResult = useGraphQueryResult(); const schema = useSchemaGraph(); @@ -637,4 +638,12 @@ export const PaohVis = (props: Props) => { ); }; +const localConfigSchema = {}; + +export const PaohVisComponent: VISComponentType = { + displayName: 'PaohVis', + VIS: PaohVis, + localConfigSchema: localConfigSchema, +}; + export default PaohVis; diff --git a/libs/shared/lib/vis/paohvis/utils/AttributesFilterUseCase.tsx b/libs/shared/lib/vis/visualizations/paohvis/utils/AttributesFilterUseCase.tsx similarity index 98% rename from libs/shared/lib/vis/paohvis/utils/AttributesFilterUseCase.tsx rename to libs/shared/lib/vis/visualizations/paohvis/utils/AttributesFilterUseCase.tsx index 07f5fae8bfc0806d49833e6c92175e0676be5209..685d7d2597de366cae81d50bd6a5afd896e912a5 100644 --- a/libs/shared/lib/vis/paohvis/utils/AttributesFilterUseCase.tsx +++ b/libs/shared/lib/vis/visualizations/paohvis/utils/AttributesFilterUseCase.tsx @@ -5,7 +5,7 @@ */ import { FilterInfo, PaohvisFilters } from '../Types'; -import { AxisType, isNotInGroup } from '../../shared/ResultNodeLinkParserUseCase'; +import { AxisType, isNotInGroup } from '../../../shared/ResultNodeLinkParserUseCase'; import { boolPredicates, numberPredicates, textPredicates } from '../models/FilterPredicates'; import { Edge, GraphQueryResult, Node } from '@graphpolaris/shared/lib/data-access'; diff --git a/libs/shared/lib/vis/paohvis/utils/CalcEntitiesFromQueryResult.tsx b/libs/shared/lib/vis/visualizations/paohvis/utils/CalcEntitiesFromQueryResult.tsx similarity index 92% rename from libs/shared/lib/vis/paohvis/utils/CalcEntitiesFromQueryResult.tsx rename to libs/shared/lib/vis/visualizations/paohvis/utils/CalcEntitiesFromQueryResult.tsx index b9a274bd9859902c69194b8d38d3e7bdadc8a296..c6988eab456eec6753ddc67f1879ea7745112670 100644 --- a/libs/shared/lib/vis/paohvis/utils/CalcEntitiesFromQueryResult.tsx +++ b/libs/shared/lib/vis/visualizations/paohvis/utils/CalcEntitiesFromQueryResult.tsx @@ -5,7 +5,7 @@ */ import { GraphQueryResult } from '@graphpolaris/shared/lib/data-access'; -import { getGroupName } from '../../shared/ResultNodeLinkParserUseCase'; +import { getGroupName } from '../../../shared/ResultNodeLinkParserUseCase'; /** * This calculates all entities from the query result. diff --git a/libs/shared/lib/vis/paohvis/utils/CalcEntityAttrAndRelNamesFromSchemaUseCase.tsx b/libs/shared/lib/vis/visualizations/paohvis/utils/CalcEntityAttrAndRelNamesFromSchemaUseCase.tsx similarity index 100% rename from libs/shared/lib/vis/paohvis/utils/CalcEntityAttrAndRelNamesFromSchemaUseCase.tsx rename to libs/shared/lib/vis/visualizations/paohvis/utils/CalcEntityAttrAndRelNamesFromSchemaUseCase.tsx diff --git a/libs/shared/lib/vis/paohvis/utils/SortUseCase.tsx b/libs/shared/lib/vis/visualizations/paohvis/utils/SortUseCase.tsx similarity index 100% rename from libs/shared/lib/vis/paohvis/utils/SortUseCase.tsx rename to libs/shared/lib/vis/visualizations/paohvis/utils/SortUseCase.tsx diff --git a/libs/shared/lib/vis/paohvis/utils/ToPaohvisDataParserUsecase.tsx b/libs/shared/lib/vis/visualizations/paohvis/utils/ToPaohvisDataParserUsecase.tsx similarity index 99% rename from libs/shared/lib/vis/paohvis/utils/ToPaohvisDataParserUsecase.tsx rename to libs/shared/lib/vis/visualizations/paohvis/utils/ToPaohvisDataParserUsecase.tsx index de75b4d88b39d21886fb1cd6714e8d5bb2d1d8ad..63d1303023cae44cd7c1de9c6fd443dad8d447f5 100644 --- a/libs/shared/lib/vis/paohvis/utils/ToPaohvisDataParserUsecase.tsx +++ b/libs/shared/lib/vis/visualizations/paohvis/utils/ToPaohvisDataParserUsecase.tsx @@ -4,7 +4,7 @@ * © Copyright Utrecht University (Department of Information and Computing Sciences) */ -import { AxisType, getGroupName } from '../../shared/ResultNodeLinkParserUseCase'; +import { AxisType, getGroupName } from '../../../shared/ResultNodeLinkParserUseCase'; import { Edge, GraphQueryResult, Node } from '@graphpolaris/shared/lib/data-access'; import { diff --git a/libs/shared/lib/vis/paohvis/utils/utils.tsx b/libs/shared/lib/vis/visualizations/paohvis/utils/utils.tsx similarity index 99% rename from libs/shared/lib/vis/paohvis/utils/utils.tsx rename to libs/shared/lib/vis/visualizations/paohvis/utils/utils.tsx index 0d41d46174e609183c9ddffc1df9b84d16ad2c86..669494fe175cb2ece5e4516506de90e70af05043 100644 --- a/libs/shared/lib/vis/paohvis/utils/utils.tsx +++ b/libs/shared/lib/vis/visualizations/paohvis/utils/utils.tsx @@ -1,5 +1,5 @@ import { log } from 'console'; -import { SchemaAttribute, SchemaGraph, SchemaGraphologyEdge, SchemaGraphologyNode } from '../../../schema'; +import { SchemaAttribute, SchemaGraph, SchemaGraphologyEdge, SchemaGraphologyNode } from '../../../../schema'; import { AttributeNames, EntitiesFromSchema, RelationsFromSchema } from '../Types'; /** diff --git a/libs/shared/lib/vis/rawjsonvis/index.ts b/libs/shared/lib/vis/visualizations/rawjsonvis/index.ts similarity index 100% rename from libs/shared/lib/vis/rawjsonvis/index.ts rename to libs/shared/lib/vis/visualizations/rawjsonvis/index.ts diff --git a/libs/shared/lib/vis/rawjsonvis/rawjsonvis.module.scss b/libs/shared/lib/vis/visualizations/rawjsonvis/rawjsonvis.module.scss similarity index 100% rename from libs/shared/lib/vis/rawjsonvis/rawjsonvis.module.scss rename to libs/shared/lib/vis/visualizations/rawjsonvis/rawjsonvis.module.scss diff --git a/libs/shared/lib/vis/rawjsonvis/rawjsonvis.module.scss.d.ts b/libs/shared/lib/vis/visualizations/rawjsonvis/rawjsonvis.module.scss.d.ts similarity index 100% rename from libs/shared/lib/vis/rawjsonvis/rawjsonvis.module.scss.d.ts rename to libs/shared/lib/vis/visualizations/rawjsonvis/rawjsonvis.module.scss.d.ts diff --git a/libs/shared/lib/vis/rawjsonvis/rawjsonvis.spec.tsx b/libs/shared/lib/vis/visualizations/rawjsonvis/rawjsonvis.spec.tsx similarity index 100% rename from libs/shared/lib/vis/rawjsonvis/rawjsonvis.spec.tsx rename to libs/shared/lib/vis/visualizations/rawjsonvis/rawjsonvis.spec.tsx diff --git a/libs/shared/lib/vis/rawjsonvis/rawjsonvis.stories.tsx b/libs/shared/lib/vis/visualizations/rawjsonvis/rawjsonvis.stories.tsx similarity index 52% rename from libs/shared/lib/vis/rawjsonvis/rawjsonvis.stories.tsx rename to libs/shared/lib/vis/visualizations/rawjsonvis/rawjsonvis.stories.tsx index ec51b4483a92561fd291837252cdb15fb9edf7f8..cdcef1260d99f650775907816507ee021862b2ec 100644 --- a/libs/shared/lib/vis/rawjsonvis/rawjsonvis.stories.tsx +++ b/libs/shared/lib/vis/visualizations/rawjsonvis/rawjsonvis.stories.tsx @@ -1,32 +1,49 @@ import React from 'react'; -import { ComponentStory, Meta } from '@storybook/react'; -import { RawJSONVis } from './rawjsonvis'; - -import { assignNewGraphQueryResult, graphQueryResultSlice, resetGraphQueryResults, store } from '../../data-access/store'; +import { Meta } from '@storybook/react'; +import { VisualizationPanel } from '../../panel/visualization'; +import { + assignNewGraphQueryResult, + graphQueryResultSlice, + querybuilderSlice, + resetGraphQueryResults, + schemaSlice, + store, + visualizationSlice, +} from '../../../data-access/store'; import { configureStore } from '@reduxjs/toolkit'; import { Provider } from 'react-redux'; -import { mockLargeQueryResults } from '../../mock-data/query-result'; +import { mockLargeQueryResults } from '../../../mock-data/query-result'; +import { Visualizations, setActiveVisualization } from '@graphpolaris/shared/lib/data-access/store/visualizationSlice'; -const Component: Meta<typeof RawJSONVis> = { - /* 👇 The title prop is optional. - * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ +const Component: Meta<typeof VisualizationPanel> = { title: 'Visualizations/RawJSONVIS', - component: RawJSONVis, - decorators: [(story) => <Provider store={Mockstore}>{story()}</Provider>], + component: VisualizationPanel, + decorators: [ + (story) => ( + <Provider store={Mockstore}> + <div + style={{ + width: '100%', + height: '100vh', + }} + > + {story()} + </div> + </Provider> + ), + ], }; const Mockstore = configureStore({ reducer: { + schema: schemaSlice.reducer, graphQueryResult: graphQueryResultSlice.reducer, + visualize: visualizationSlice.reducer, + querybuilder: querybuilderSlice.reducer, }, }); export const SimpleData = { - args: { - loading: false, - }, play: async () => { const dispatch = Mockstore.dispatch; dispatch( @@ -44,6 +61,7 @@ export const SimpleData = { }, }) ); + dispatch(setActiveVisualization(Visualizations.RawJSON)); }, }; @@ -62,22 +80,15 @@ export const LargeData = { }, }) ); - }, -}; - -export const Loading = { - args: { - loading: true, + dispatch(setActiveVisualization(Visualizations.RawJSON)); }, }; export const Empty = { - args: { - loading: false, - }, play: async () => { const dispatch = store.dispatch; dispatch(resetGraphQueryResults()); + dispatch(setActiveVisualization(Visualizations.RawJSON)); }, }; diff --git a/libs/shared/lib/vis/visualizations/rawjsonvis/rawjsonvis.tsx b/libs/shared/lib/vis/visualizations/rawjsonvis/rawjsonvis.tsx new file mode 100644 index 0000000000000000000000000000000000000000..3bfc68c491ec2bb51af804698f20a0276d791bee --- /dev/null +++ b/libs/shared/lib/vis/visualizations/rawjsonvis/rawjsonvis.tsx @@ -0,0 +1,37 @@ +import React, { useEffect } from 'react'; +import ReactJSONView from 'react-json-view'; +import { VisualizationPropTypes, VISComponentType } from '../../Types'; + +export interface RawJSONVisProps {} + +const displayName = 'RawJSONVis'; + +export const RawJSONVis = React.memo(({ data }: VisualizationPropTypes<typeof displayName>) => { + useEffect(() => { + console.log('update rawjson useEffect'); + }, [data]); + + return ( + <div> + <div style={{ overflowY: 'auto' }}> + <div + style={{ + marginTop: '50px', + paddingLeft: '30px', + }} + className="font-mono text-sm" + > + <ReactJSONView src={data} collapsed={1} quotesOnKeys={false} displayDataTypes={false} /> + </div> + </div> + </div> + ); +}); + +const localConfigSchema = {}; + +export const RawJSONComponent: VISComponentType = { + displayName: displayName, + VIS: RawJSONVis, + localConfigSchema: localConfigSchema, +}; diff --git a/libs/shared/lib/vis/semanticsubstrates/Types.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/Types.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/Types.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/Types.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/configpanel/SemanticSubstrateConfigPanel.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/configpanel/SemanticSubstrateConfigPanel.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/configpanel/SemanticSubstrateConfigPanel.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/configpanel/SemanticSubstrateConfigPanel.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/configpanel/SemanticSubstratesConfigPanelViewModel.t b/libs/shared/lib/vis/visualizations/semanticsubstrates/configpanel/SemanticSubstratesConfigPanelViewModel.t similarity index 98% rename from libs/shared/lib/vis/semanticsubstrates/configpanel/SemanticSubstratesConfigPanelViewModel.t rename to libs/shared/lib/vis/visualizations/semanticsubstrates/configpanel/SemanticSubstratesConfigPanelViewModel.t index 3075b2e5bbc8162bd3845b495ec2f8058c5847c8..3cf928252166db2e5028931a53cff81a91d265bf 100644 --- a/libs/shared/lib/vis/semanticsubstrates/configpanel/SemanticSubstratesConfigPanelViewModel.t +++ b/libs/shared/lib/vis/visualizations/semanticsubstrates/configpanel/SemanticSubstratesConfigPanelViewModel.t @@ -1,7 +1,7 @@ import SemanticSubstratesConfigPanelViewModelImpl from './SemanticSubstratesConfigPanelViewModel'; import SemanticSubstratesViewModelImpl from '../SemanticSubstratesViewModel'; -import big2ndChamberQueryResult from '../../../../data/mock-data/query-result/big2ndChamberQueryResult'; -import smallFlightsQueryResults from '../../../../data/mock-data/query-result/smallFlightsQueryResults'; +import big2ndChamberQueryResult from '../../../../../data/mock-data/query-result/big2ndChamberQueryResult'; +import smallFlightsQueryResults from '../../../../../data/mock-data/query-result/smallFlightsQueryResults'; jest.mock('../../../view/result-visualisations/semantic-substrates/SemanticSubstratesStylesheet'); diff --git a/libs/shared/lib/vis/semanticsubstrates/configpanel/SemanticSubstratesConfigPanelViewModel.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/configpanel/SemanticSubstratesConfigPanelViewModel.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/configpanel/SemanticSubstratesConfigPanelViewModel.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/configpanel/SemanticSubstratesConfigPanelViewModel.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/configpanel/Types.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/configpanel/Types.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/configpanel/Types.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/configpanel/Types.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/index.ts b/libs/shared/lib/vis/visualizations/semanticsubstrates/index.ts similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/index.ts rename to libs/shared/lib/vis/visualizations/semanticsubstrates/index.ts diff --git a/libs/shared/lib/vis/semanticsubstrates/semanticsubstrates.module.scss b/libs/shared/lib/vis/visualizations/semanticsubstrates/semanticsubstrates.module.scss similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/semanticsubstrates.module.scss rename to libs/shared/lib/vis/visualizations/semanticsubstrates/semanticsubstrates.module.scss diff --git a/libs/shared/lib/vis/semanticsubstrates/semanticsubstrates.module.scss.d.ts b/libs/shared/lib/vis/visualizations/semanticsubstrates/semanticsubstrates.module.scss.d.ts similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/semanticsubstrates.module.scss.d.ts rename to libs/shared/lib/vis/visualizations/semanticsubstrates/semanticsubstrates.module.scss.d.ts diff --git a/libs/shared/lib/vis/semanticsubstrates/semanticsubstrates.stories.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/semanticsubstrates.stories.tsx similarity index 70% rename from libs/shared/lib/vis/semanticsubstrates/semanticsubstrates.stories.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/semanticsubstrates.stories.tsx index 7e1351364757adb810df330fa44399a420619c93..5d4f31bda93924e2857eeb51dc7f20e388c6c054 100644 --- a/libs/shared/lib/vis/semanticsubstrates/semanticsubstrates.stories.tsx +++ b/libs/shared/lib/vis/visualizations/semanticsubstrates/semanticsubstrates.stories.tsx @@ -1,20 +1,23 @@ -import { assignNewGraphQueryResult, graphQueryResultSlice, schemaSlice, setSchema } from '../../data-access/store'; +import { + assignNewGraphQueryResult, + graphQueryResultSlice, + querybuilderSlice, + schemaSlice, + setSchema, + visualizationSlice, +} from '../../../data-access/store'; import { configureStore } from '@reduxjs/toolkit'; import { Meta } from '@storybook/react'; import { Provider } from 'react-redux'; +import { VisualizationPanel } from '../../panel/visualization'; +import { SchemaUtils } from '../../../schema/schema-utils'; +import { simpleSchemaAirportRaw } from '../../../mock-data/schema/simpleAirportRaw'; +import { bigMockQueryResults } from '../../../mock-data'; +import { Visualizations, setActiveVisualization } from '@graphpolaris/shared/lib/data-access/store/visualizationSlice'; -import SemanticSubstrates from './semanticsubstrates'; -import { SchemaUtils } from '../../schema/schema-utils'; -import { simpleSchemaAirportRaw } from '../../mock-data/schema/simpleAirportRaw'; -import { bigMockQueryResults } from '../../mock-data'; - -const Component: Meta<typeof SemanticSubstrates> = { - /* 👇 The title prop is optional. - * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ +const Component: Meta<typeof VisualizationPanel> = { title: 'Visualizations/SemanticSubstrates', - component: SemanticSubstrates, + component: VisualizationPanel, decorators: [(story) => <Provider store={Mockstore}>{story()}</Provider>], }; @@ -22,13 +25,12 @@ const Mockstore = configureStore({ reducer: { schema: schemaSlice.reducer, graphQueryResult: graphQueryResultSlice.reducer, + visualize: visualizationSlice.reducer, + querybuilder: querybuilderSlice.reducer, }, }); export const TestWithData = { - args: { - loading: false, - }, play: async () => { const dispatch = Mockstore.dispatch; const schema = SchemaUtils.schemaBackend2Graphology({ @@ -73,16 +75,11 @@ export const TestWithData = { }, }) ); + // dispatch(setActiveVisualization(Visualizations.SemanticSubstrates)); }, }; export const TestWithAirport = { - args: { - loading: false, - rowHeight: 30, - hyperedgeColumnWidth: 30, - gapBetweenRanges: 3, - }, play: async () => { const dispatch = Mockstore.dispatch; const schema = SchemaUtils.schemaBackend2Graphology(simpleSchemaAirportRaw); @@ -94,6 +91,7 @@ export const TestWithAirport = { result: { type: 'nodelink', payload: bigMockQueryResults }, }) ); + // dispatch(setActiveVisualization(Visualizations.SemanticSubstrates)); }, }; diff --git a/libs/shared/lib/vis/semanticsubstrates/semanticsubstrates.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/semanticsubstrates.tsx similarity index 98% rename from libs/shared/lib/vis/semanticsubstrates/semanticsubstrates.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/semanticsubstrates.tsx index 3cf14ed04a3c843f1cb1499c811c00b9d52577b7..5fd46c775164393a22959e91380b0ff7c7316bf2 100644 --- a/libs/shared/lib/vis/semanticsubstrates/semanticsubstrates.tsx +++ b/libs/shared/lib/vis/visualizations/semanticsubstrates/semanticsubstrates.tsx @@ -1,12 +1,12 @@ import { useAppDispatch, useGraphQueryResult, useSchemaGraph } from '@graphpolaris/shared/lib/data-access/store'; import { useEffect, useRef, useState } from 'react'; import { AxisLabel, EntitiesFromSchema, MinMaxType, PlotSpecifications, PlotType, RelationType } from './Types'; -import { isNodeLinkResult } from '../shared/ResultNodeLinkParserUseCase'; +import { isNodeLinkResult } from '../../shared/ResultNodeLinkParserUseCase'; import styles from './semanticsubstrates.module.scss'; import AddPlotButtonComponent from './subcomponents/AddPlotButtonComponent'; import SVGCheckboxesWithSemanticSubstrLabel from './subcomponents/SVGCheckBoxComponent'; import AddPlotPopup from './subcomponents/AddPlotPopup'; -import VisConfigPanelComponent from '../shared/VisConfigPanel/VisConfigPanel'; +import VisConfigPanelComponent from '../../shared/VisConfigPanel/VisConfigPanel'; import Plot from './subcomponents/PlotComponent'; import LinesBetweenPlots from './subcomponents/LinesBetweenPlotsComponent'; import Color from 'color'; @@ -73,7 +73,9 @@ const relationScaleCalculation: (x: number) => number = (x: number) => { return 1; }; -export const SemanticSubstrates = () => { +export type SemanticSubstratesProps = {}; + +export const SemanticSubstrates = ({}: SemanticSubstratesProps) => { const graphQueryResult = useGraphQueryResult(); const schema = useSchemaGraph(); const [entitiesFromSchema, setEntitiesFromSchema] = useState<EntitiesFromSchema>({ entityNames: [], attributesPerEntity: {} }); diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/AddPlotButtonComponent.module.scss b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/AddPlotButtonComponent.module.scss similarity index 94% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/AddPlotButtonComponent.module.scss rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/AddPlotButtonComponent.module.scss index 4ab1febb10c70fc1f01d13e5f09bf5a863a9f227..52b6ee9144fdb85611b120a80e97dd5aa288babf 100644 --- a/libs/shared/lib/vis/semanticsubstrates/subcomponents/AddPlotButtonComponent.module.scss +++ b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/AddPlotButtonComponent.module.scss @@ -1,63 +1,63 @@ -.root { - &:hover { - & .display { - & .background { - fill: '#009100'; - transition-delay: 0s; - } - & .plus { - transform: translate(-4px, 0); - transition-delay: 0s; - - & line { - transition: 0.2s; - transition-delay: 0s; - stroke-width: 3; - } - & .xAxis { - transform: translate(0, 0) scale(1, 1); - } - & .yAxis { - transform: translate(0, 0); - } - & .nodes { - opacity: 0; - transition-delay: 0s; - } - } - } - } -} - -.background { - transition: 0.1s; - transition-delay: 0.1s; -} - -.plus { - transform-box: fill-box; - transform-origin: center center; - transition: 0.2s; - transition-delay: 0.1s; - transform: translate(0, 0); - - & line { - transition: 0.2s; - transition-delay: 0.1s; - stroke-width: 1; - } - - & .nodes { - transition-delay: 0.1s; - } -} - -.xAxis { - transform-box: fill-box; - transform-origin: center right; - transform: translate(0, 5px) scale(1.4, 1); -} - -.yAxis { - transform: translate(-11px, 0); -} +.root { + &:hover { + & .display { + & .background { + fill: '#009100'; + transition-delay: 0s; + } + & .plus { + transform: translate(-4px, 0); + transition-delay: 0s; + + & line { + transition: 0.2s; + transition-delay: 0s; + stroke-width: 3; + } + & .xAxis { + transform: translate(0, 0) scale(1, 1); + } + & .yAxis { + transform: translate(0, 0); + } + & .nodes { + opacity: 0; + transition-delay: 0s; + } + } + } + } +} + +.background { + transition: 0.1s; + transition-delay: 0.1s; +} + +.plus { + transform-box: fill-box; + transform-origin: center center; + transition: 0.2s; + transition-delay: 0.1s; + transform: translate(0, 0); + + & line { + transition: 0.2s; + transition-delay: 0.1s; + stroke-width: 1; + } + + & .nodes { + transition-delay: 0.1s; + } +} + +.xAxis { + transform-box: fill-box; + transform-origin: center right; + transform: translate(0, 5px) scale(1.4, 1); +} + +.yAxis { + transform: translate(-11px, 0); +} diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/AddPlotButtonComponent.module.scss.d.ts b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/AddPlotButtonComponent.module.scss.d.ts similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/AddPlotButtonComponent.module.scss.d.ts rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/AddPlotButtonComponent.module.scss.d.ts diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/AddPlotButtonComponent.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/AddPlotButtonComponent.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/AddPlotButtonComponent.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/AddPlotButtonComponent.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/AddPlotPopup.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/AddPlotPopup.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/AddPlotPopup.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/AddPlotPopup.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/BrushComponent.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/BrushComponent.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/BrushComponent.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/BrushComponent.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/LinesBetweenPlotsComponent.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/LinesBetweenPlotsComponent.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/LinesBetweenPlotsComponent.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/LinesBetweenPlotsComponent.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/OptimizedAutocomplete.module.scss b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/OptimizedAutocomplete.module.scss similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/OptimizedAutocomplete.module.scss rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/OptimizedAutocomplete.module.scss diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/OptimizedAutocomplete.module.scss.d.ts b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/OptimizedAutocomplete.module.scss.d.ts similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/OptimizedAutocomplete.module.scss.d.ts rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/OptimizedAutocomplete.module.scss.d.ts diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/OptimizedAutocomplete.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/OptimizedAutocomplete.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/OptimizedAutocomplete.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/OptimizedAutocomplete.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/PlotAxisLabelStyles.module.css b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/PlotAxisLabelStyles.module.css similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/PlotAxisLabelStyles.module.css rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/PlotAxisLabelStyles.module.css diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/PlotAxisLabelStyles.module.css.d.ts b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/PlotAxisLabelStyles.module.css.d.ts similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/PlotAxisLabelStyles.module.css.d.ts rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/PlotAxisLabelStyles.module.css.d.ts diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/PlotAxisLabelsComponent.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/PlotAxisLabelsComponent.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/PlotAxisLabelsComponent.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/PlotAxisLabelsComponent.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/PlotComponent.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/PlotComponent.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/PlotComponent.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/PlotComponent.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/PlotTitleComponent.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/PlotTitleComponent.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/PlotTitleComponent.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/PlotTitleComponent.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/PlotTitleStyles.module.css b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/PlotTitleStyles.module.css similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/PlotTitleStyles.module.css rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/PlotTitleStyles.module.css diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/PlotTitleStyles.module.css.d.ts b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/PlotTitleStyles.module.css.d.ts similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/PlotTitleStyles.module.css.d.ts rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/PlotTitleStyles.module.css.d.ts diff --git a/libs/shared/lib/vis/semanticsubstrates/subcomponents/SVGCheckBoxComponent.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/SVGCheckBoxComponent.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/subcomponents/SVGCheckBoxComponent.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/subcomponents/SVGCheckBoxComponent.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/utils/CalcConnectionLinePositionsUseCase.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/utils/CalcConnectionLinePositionsUseCase.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/utils/CalcConnectionLinePositionsUseCase.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/utils/CalcConnectionLinePositionsUseCase.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/utils/CalcDefaultPlotSpecsUseCase.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/utils/CalcDefaultPlotSpecsUseCase.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/utils/CalcDefaultPlotSpecsUseCase.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/utils/CalcDefaultPlotSpecsUseCase.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/utils/CalcDistance.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/utils/CalcDistance.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/utils/CalcDistance.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/utils/CalcDistance.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/utils/CalcEntityAttrNamesFromResultUseCase.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/utils/CalcEntityAttrNamesFromResultUseCase.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/utils/CalcEntityAttrNamesFromResultUseCase.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/utils/CalcEntityAttrNamesFromResultUseCase.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/utils/CalcEntityAttrNamesFromSchemaUseCase.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/utils/CalcEntityAttrNamesFromSchemaUseCase.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/utils/CalcEntityAttrNamesFromSchemaUseCase.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/utils/CalcEntityAttrNamesFromSchemaUseCase.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/utils/CalcScaledPositionsUseCase.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/utils/CalcScaledPositionsUseCase.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/utils/CalcScaledPositionsUseCase.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/utils/CalcScaledPositionsUseCase.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/utils/CalcXYMinMaxUseCase.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/utils/CalcXYMinMaxUseCase.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/utils/CalcXYMinMaxUseCase.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/utils/CalcXYMinMaxUseCase.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/utils/FilterUseCase.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/utils/FilterUseCase.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/utils/FilterUseCase.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/utils/FilterUseCase.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/utils/RotateVec.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/utils/RotateVec.tsx similarity index 100% rename from libs/shared/lib/vis/semanticsubstrates/utils/RotateVec.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/utils/RotateVec.tsx diff --git a/libs/shared/lib/vis/semanticsubstrates/utils/ToPlotDataParserUseCase.tsx b/libs/shared/lib/vis/visualizations/semanticsubstrates/utils/ToPlotDataParserUseCase.tsx similarity index 98% rename from libs/shared/lib/vis/semanticsubstrates/utils/ToPlotDataParserUseCase.tsx rename to libs/shared/lib/vis/visualizations/semanticsubstrates/utils/ToPlotDataParserUseCase.tsx index bcaa713af5cad10656afe475af3cc0c403d0d8d3..487d5aa3256cf3241e2430996f7314c244292e17 100644 --- a/libs/shared/lib/vis/semanticsubstrates/utils/ToPlotDataParserUseCase.tsx +++ b/libs/shared/lib/vis/visualizations/semanticsubstrates/utils/ToPlotDataParserUseCase.tsx @@ -4,8 +4,8 @@ * © Copyright Utrecht University (Department of Information and Computing Sciences) */ import { GraphQueryResult } from '@graphpolaris/shared/lib/data-access'; -import { ParseToUniqueEdges } from '../../shared/ResultNodeLinkParserUseCase'; -import { Edge, Node } from '../../../data-access/store'; +import { ParseToUniqueEdges } from '../../../shared/ResultNodeLinkParserUseCase'; +import { Edge, Node } from '../../../../data-access/store'; import { AxisLabel, PlotInputData, PlotSpecifications, RelationType } from '../Types'; /** A use case for parsing incoming node-link data to plot data */ diff --git a/libs/shared/lib/vis/table_vis/components/Table.tsx b/libs/shared/lib/vis/visualizations/table_vis/components/Table.tsx similarity index 100% rename from libs/shared/lib/vis/table_vis/components/Table.tsx rename to libs/shared/lib/vis/visualizations/table_vis/components/Table.tsx diff --git a/libs/shared/lib/vis/table_vis/components/table.module.scss b/libs/shared/lib/vis/visualizations/table_vis/components/table.module.scss similarity index 100% rename from libs/shared/lib/vis/table_vis/components/table.module.scss rename to libs/shared/lib/vis/visualizations/table_vis/components/table.module.scss diff --git a/libs/shared/lib/vis/table_vis/components/table.module.scss.d.ts b/libs/shared/lib/vis/visualizations/table_vis/components/table.module.scss.d.ts similarity index 85% rename from libs/shared/lib/vis/table_vis/components/table.module.scss.d.ts rename to libs/shared/lib/vis/visualizations/table_vis/components/table.module.scss.d.ts index 0dc7b2cfe2feff56721fa723aee89e4d10e2f30d..8798bcd00095ed6509688816c10f5c9399d76b8b 100644 --- a/libs/shared/lib/vis/table_vis/components/table.module.scss.d.ts +++ b/libs/shared/lib/vis/visualizations/table_vis/components/table.module.scss.d.ts @@ -1,6 +1,5 @@ declare const classNames: { readonly 'table-container': 'table-container'; readonly table: 'table'; - readonly '5': '5'; }; export = classNames; diff --git a/libs/shared/lib/vis/visualizations/table_vis/tableVis.tsx b/libs/shared/lib/vis/visualizations/table_vis/tableVis.tsx new file mode 100644 index 0000000000000000000000000000000000000000..cfa411105c83b5a3a03a03d2381bd71564cb864a --- /dev/null +++ b/libs/shared/lib/vis/visualizations/table_vis/tableVis.tsx @@ -0,0 +1,61 @@ +import React, { useMemo, useRef } from 'react'; +import { Table, AugmentedNodeAttributes } from './components/Table'; +import { SchemaAttribute } from '../../../schema'; +import { VisualizationPropTypes, VISComponentType, localConfigSchemaType } from '../../Types'; + +export type TableProps = { + showBarplot: boolean; + itemsPerPage: number; +}; + +const displayName = 'TableVis'; + +export const TableVis = ({ data, schema, localConfig }: VisualizationPropTypes<typeof displayName>) => { + const ref = useRef<HTMLDivElement>(null); + + const attributesArray = useMemo<AugmentedNodeAttributes[]>( + () => + data.nodes.map((node) => { + const types: SchemaAttribute[] = + schema.nodes.find((n) => n.key === node.label)?.attributes?.attributes ?? + schema.edges.find((r) => r.key === node.label)?.attributes?.attributes ?? + []; + + return { + attribute: node.attributes, + type: Object.fromEntries(types.map((t) => [t.name, t.type])), + }; + }), + [data.nodes] + ); + + return ( + <> + <div className="h-full w-full" ref={ref}> + {attributesArray.length > 0 && ( + <Table data={attributesArray} itemsPerPage={localConfig.itemsPerPage} showBarPlot={localConfig.showBarplot} /> + )} + </div> + </> + ); +}; + +const localConfigSchema: localConfigSchemaType = { + showBarplot: { + value: true, + type: 'boolean', + label: 'Show barplot', + }, + itemsPerPage: { + value: 10, + type: 'dropdown', + label: 'Items per page', + options: [10, 20, 30], + }, +}; + +export const TableComponent: VISComponentType = { + displayName: displayName, + VIS: TableVis, + localConfigSchema: localConfigSchema, +}; diff --git a/libs/shared/lib/vis/table_vis/tablevis.stories.tsx b/libs/shared/lib/vis/visualizations/table_vis/tablevis.stories.tsx similarity index 63% rename from libs/shared/lib/vis/table_vis/tablevis.stories.tsx rename to libs/shared/lib/vis/visualizations/table_vis/tablevis.stories.tsx index 0e68173d56f39b81bb9a69cbcc314c537ab63042..b7f5d6e33a646153846e025957ca6ef35d17a6f8 100644 --- a/libs/shared/lib/vis/table_vis/tablevis.stories.tsx +++ b/libs/shared/lib/vis/visualizations/table_vis/tablevis.stories.tsx @@ -1,27 +1,25 @@ import React from 'react'; import { Meta } from '@storybook/react'; -import { TableVis } from './tableVis'; - +import { VisualizationPanel } from '../../panel/visualization'; import { assignNewGraphQueryResult, graphQueryResultSlice, + querybuilderSlice, schemaSlice, setSchema, -} from '../../data-access/store'; + visualizationSlice, +} from '../../../data-access/store'; import { configureStore } from '@reduxjs/toolkit'; import { Provider } from 'react-redux'; -import { smallFlightsQueryResults, simpleSchemaRaw, bigMockQueryResults } from '../../mock-data'; +import { smallFlightsQueryResults, simpleSchemaRaw, bigMockQueryResults } from '../../../mock-data'; -import { SchemaUtils } from '../../schema/schema-utils'; -import { simpleSchemaAirportRaw } from '../../mock-data/schema/simpleAirportRaw'; +import { SchemaUtils } from '../../../schema/schema-utils'; +import { simpleSchemaAirportRaw } from '../../../mock-data/schema/simpleAirportRaw'; +import { Visualizations, setActiveVisualization } from '@graphpolaris/shared/lib/data-access/store/visualizationSlice'; -const Component: Meta<typeof TableVis> = { - /* 👇 The title prop is optional. - * See https://storybook.js.org/docs/react/configure/overview#configure-story-loading - * to learn how to generate automatic titles - */ +const Component: Meta<typeof VisualizationPanel> = { title: 'Visualizations/SimpleTableVis', - component: TableVis, + component: VisualizationPanel, decorators: [ (story) => ( <Provider store={Mockstore}> @@ -42,44 +40,31 @@ const Mockstore = configureStore({ reducer: { schema: schemaSlice.reducer, graphQueryResult: graphQueryResultSlice.reducer, + visualize: visualizationSlice.reducer, + querybuilder: querybuilderSlice.reducer, }, }); -/* -export const TestWithBig2ndChamber = { - args: { loading: false }, - play: async () => { - const dispatch = Mockstore.dispatch; - - dispatch(assignNewGraphQueryResult({ queryID: '1', result: { type: 'nodelink', payload: big2ndChamberQueryResult } })); - }, -}; -*/ - export const TestWithAirport = { - args: { - loading: false, - }, play: async () => { const dispatch = Mockstore.dispatch; const schema = SchemaUtils.schemaBackend2Graphology(simpleSchemaAirportRaw); dispatch(setSchema(schema.export())); dispatch(assignNewGraphQueryResult({ queryID: '1', result: { type: 'nodelink', payload: bigMockQueryResults } })); + dispatch(setActiveVisualization(Visualizations.Table)); }, }; -export default Component; - export const TestWithAirportSimple = { - args: { - loading: false, - }, play: async () => { const dispatch = Mockstore.dispatch; const schema = SchemaUtils.schemaBackend2Graphology(simpleSchemaRaw); dispatch(setSchema(schema.export())); dispatch(assignNewGraphQueryResult({ queryID: '1', result: { type: 'nodelink', payload: smallFlightsQueryResults } })); + dispatch(setActiveVisualization(Visualizations.Table)); }, }; + +export default Component;