Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • graphpolaris/frontend-v2
  • rijkheere/frontend-v-2-reordering-paoh
2 results
Show changes
Commits on Source (2)
......@@ -56,7 +56,6 @@ export function InspectorPanel(props: { children?: React.ReactNode }) {
{inspector}
<div className="flex flex-col w-full">
{buildInfo === 'dev' && (
<div className="mt-auto p-2 bg-light">
<Button
variantType="primary"
......@@ -72,7 +71,6 @@ export function InspectorPanel(props: { children?: React.ReactNode }) {
className="block w-full"
/>
</div>
)}
</div>
</Panel>
);
......
......@@ -30,7 +30,7 @@ export const Visualizations: Record<string, PromiseFunc> = {
SemanticSubstratesVis: () => import('../visualizations/semanticsubstratesvis/semanticsubstratesvis'),
}),
...(isVisualizationReleased('MapVis') && { MapVis: () => import('../visualizations/mapvis/mapvis') }),
...(isVisualizationReleased('Vis0D') && { Vis0D: () => import('../visualizations/Vis0D/Vis0D') }),
...(isVisualizationReleased('Vis0D') && { Vis0D: () => import('../visualizations/vis0D/Vis0D') }),
...(isVisualizationReleased('Vis1D') && { Vis1D: () => import('../visualizations/vis1D/Vis1D') }),
};
......
import React, { useRef, useImperativeHandle, forwardRef } from 'react';
import { VisualizationPropTypes, VISComponentType, VisualizationSettingsPropTypes } from '../../common';
import { SettingsContainer } from '@graphpolaris/shared/lib/vis/components/config';
import html2canvas from 'html2canvas';
import { Input } from '@graphpolaris/shared/lib/components/inputs';
export interface Vis0DProps {
title: string;
}
const settings: Vis0DProps = {
title: '',
};
export interface Vis0DVisHandle {
exportImageInternal: () => void;
}
const formatNumber = (number: number) => {
return number.toLocaleString('de-DE');
};
const Vis0D = forwardRef<Vis0DVisHandle, VisualizationPropTypes<Vis0DProps>>(({ data, settings }, refExternal) => {
const internalRef = useRef<HTMLDivElement>(null);
useImperativeHandle(refExternal, () => ({
exportImageInternal() {
const captureImage = () => {
const element = internalRef.current;
if (element) {
html2canvas(element, {
backgroundColor: '#FFFFFF',
})
.then((canvas) => {
const finalImage = canvas.toDataURL('image/png');
const link = document.createElement('a');
link.href = finalImage;
link.download = 'Vis0D.png';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
})
.catch((error) => {
console.error('Error capturing image:', error);
});
} else {
console.error('Container element not found');
}
};
const renderCanvas = () => {
requestAnimationFrame(() => {
captureImage();
});
};
renderCanvas();
},
}));
// !FIXME: When stats pills are ready, substitue results accordingly
return (
<div className="h-full w-full flex flex-col items-center justify-center overflow-hidden" ref={internalRef}>
{settings.title && <span className="text-3xl text-center mb-4">{settings.title}</span>}
{data?.nodes?.length > 0 ? (
<span className="text-4xl text-center">Select 0D data</span>
) : (
<span className="text-8xl text-center">{formatNumber(1231312)}</span>
)}{' '}
</div>
);
});
const Vis0DSettings = ({ settings, updateSettings }: VisualizationSettingsPropTypes<Vis0DProps>) => {
return (
<SettingsContainer>
<Input type="text" label="Title" value={settings.title} onChange={(value) => updateSettings({ title: value as string })} />
</SettingsContainer>
);
};
const Vis0DRef = React.createRef<Vis0DVisHandle>();
export const Vis0DComponent: VISComponentType<Vis0DProps> = {
component: React.forwardRef((props: VisualizationPropTypes<Vis0DProps>, ref) => <Vis0D {...props} ref={Vis0DRef} />),
settingsComponent: Vis0DSettings,
settings: settings,
exportImage: () => {
if (Vis0DRef.current) {
Vis0DRef.current.exportImageInternal();
} else {
console.error('0Dvis reference is not set.');
}
},
};
export default Vis0DComponent;
......@@ -5,4 +5,4 @@ export * from './tablevis/tablevis';
export * from './matrixvis/matrixvis';
export * from './semanticsubstratesvis/semanticsubstratesvis';
export * from './vis1D/Vis1D';
export * from './Vis0D/Vis0D';
export * from './vis0D/Vis0D';
import React, { useRef, useImperativeHandle, forwardRef, useEffect, useState, Fragment } from 'react';
import { VisualizationPropTypes, VISComponentType, VisualizationSettingsPropTypes } from '../../common';
import { SettingsContainer } from '@graphpolaris/shared/lib/vis/components/config';
import html2canvas from 'html2canvas';
import { Input } from '@graphpolaris/shared/lib/components/inputs';
import { EntityPill, RelationPill } from '@graphpolaris/shared/lib/components/pills/Pill';
import { Button } from '@graphpolaris/shared/lib/components/buttons';
export interface Vis0DProps {
title: string;
selectedEntity: string;
selectedAttribute: string;
selectedStat: string;
}
const settings: Vis0DProps = {
title: '',
selectedEntity: '',
selectedAttribute: '',
selectedStat: '',
};
export interface Vis0DVisHandle {
exportImageInternal: () => void;
}
const formatNumber = (number: number) => {
return number.toLocaleString('de-DE');
};
const Vis0D = forwardRef<Vis0DVisHandle, VisualizationPropTypes<Vis0DProps>>(({ settings, graphMetadata }, refExternal) => {
const [statRender, setStatRender] = useState<number | undefined>(undefined);
const internalRef = useRef<HTMLDivElement>(null);
useImperativeHandle(refExternal, () => ({
exportImageInternal() {
const captureImage = () => {
const element = internalRef.current;
if (element) {
html2canvas(element, {
backgroundColor: '#FFFFFF',
})
.then((canvas) => {
const finalImage = canvas.toDataURL('image/png');
const link = document.createElement('a');
link.href = finalImage;
link.download = 'Vis0D.png';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
})
.catch((error) => {
console.error('Error capturing image:', error);
});
} else {
console.error('Container element not found');
}
};
const renderCanvas = () => {
requestAnimationFrame(() => {
captureImage();
});
};
renderCanvas();
},
}));
useEffect(() => {
if (settings.selectedEntity != '' && graphMetadata.nodes.types && settings.selectedAttribute != '' && settings.selectedStat != '') {
const nodesLabels = graphMetadata.nodes.labels;
let attributes = [];
if (nodesLabels.includes(settings.selectedEntity)) {
attributes = Object.keys(graphMetadata.nodes.types[settings.selectedEntity].attributes);
} else {
attributes = Object.keys(graphMetadata.edges.types[settings.selectedEntity].attributes);
}
if (attributes.includes(settings.selectedAttribute)) {
let statsAvailable = [];
if (nodesLabels.includes(settings.selectedEntity)) {
statsAvailable = Object.keys(
graphMetadata.nodes.types[settings.selectedEntity].attributes[settings.selectedAttribute].statistics,
);
} else {
statsAvailable = Object.keys(
graphMetadata.edges.types[settings.selectedEntity].attributes[settings.selectedAttribute].statistics,
);
}
if (statsAvailable.includes(settings.selectedStat)) {
let statValue = 0;
if (nodesLabels.includes(settings.selectedEntity)) {
statValue = (
graphMetadata.nodes.types[settings.selectedEntity].attributes[settings.selectedAttribute].statistics as Record<string, number>
)[settings.selectedStat];
} else {
statValue = (
graphMetadata.edges.types[settings.selectedEntity].attributes[settings.selectedAttribute].statistics as Record<string, number>
)[settings.selectedStat];
}
setStatRender(statValue);
} else {
setStatRender(undefined);
}
} else {
setStatRender(undefined);
}
}
}, [settings.selectedEntity, settings.selectedAttribute, settings.selectedStat]);
return (
<div className="h-full w-full flex flex-col items-center justify-center overflow-hidden" ref={internalRef}>
{settings.title && <span className="text-3xl text-center mb-4">{settings.title}</span>}
{statRender === undefined ? (
<span className="text-4xl text-center">Select 0D data</span>
) : (
<span className="text-8xl text-center">{formatNumber(statRender)}</span>
)}
</div>
);
});
const Vis0DSettings = ({ settings, graphMetadata, updateSettings }: VisualizationSettingsPropTypes<Vis0DProps>) => {
const [attributeOptions, setAttributeOptions] = useState<string[]>([]);
const [statsOptions, setStatsOptions] = useState<string[]>([]);
useEffect(() => {
if (settings.selectedEntity === '' && graphMetadata && graphMetadata.nodes && graphMetadata.nodes.labels.length > 0) {
const firstEntity = graphMetadata.nodes.labels[0];
const attributesFirstEntity = Object.keys(graphMetadata.nodes.types[firstEntity].attributes);
setAttributeOptions(attributesFirstEntity);
const selectedAttribute = attributesFirstEntity[0];
const attributeSelectedStatistics = graphMetadata.nodes.types[firstEntity].attributes[selectedAttribute].statistics;
const notNaNStats = Object.keys(attributeSelectedStatistics).filter((key) => {
const value = attributeSelectedStatistics[key as keyof typeof attributeSelectedStatistics];
return typeof value === 'number' && !isNaN(value);
});
setStatsOptions(notNaNStats as string[]);
updateSettings({ selectedEntity: firstEntity, selectedAttribute: selectedAttribute, selectedStat: notNaNStats[0] });
}
}, [graphMetadata]);
useEffect(() => {
if (
settings.selectedEntity != '' &&
settings.selectedAttribute != '' &&
graphMetadata &&
graphMetadata.nodes &&
graphMetadata.nodes.labels.length > 0
) {
const nodesLabels = graphMetadata.nodes.labels;
// attribute management
let attributesFirstEntity = [];
if (nodesLabels.includes(settings.selectedEntity)) {
attributesFirstEntity = Object.keys(graphMetadata.nodes.types[settings.selectedEntity].attributes);
} else {
attributesFirstEntity = Object.keys(graphMetadata.edges.types[settings.selectedEntity].attributes);
}
setAttributeOptions(attributesFirstEntity);
let selectedAttribute = '';
if (settings.selectedAttribute === '' || !attributesFirstEntity.includes(settings.selectedAttribute)) {
selectedAttribute = attributesFirstEntity[0];
updateSettings({ selectedAttribute: selectedAttribute });
} else {
selectedAttribute = settings.selectedAttribute;
}
// stat management
let attributeSelectedStatistics: Record<string, number> = {};
if (nodesLabels.includes(settings.selectedEntity)) {
attributeSelectedStatistics = graphMetadata.nodes.types[settings.selectedEntity].attributes[selectedAttribute].statistics as Record<
string,
number
>;
} else {
attributeSelectedStatistics = graphMetadata.edges.types[settings.selectedEntity].attributes[selectedAttribute].statistics as Record<
string,
number
>;
}
const notNaNStats = Object.keys(attributeSelectedStatistics).filter((key) => {
const value = attributeSelectedStatistics[key as keyof typeof attributeSelectedStatistics];
// !TODO: include string stats
return !isNaN(value);
});
setStatsOptions(notNaNStats as string[]);
if (settings.selectedStat == '' || !notNaNStats.includes(settings.selectedStat)) {
updateSettings({ selectedStat: notNaNStats[0] });
} else {
updateSettings({ selectedStat: settings.selectedStat });
}
}
}, [settings.selectedEntity, settings.selectedAttribute]);
return (
<SettingsContainer>
<div className="p-1">
<Input
className="mb-2"
type="text"
label="Title"
value={settings.title}
onChange={(value) => updateSettings({ title: value as string })}
/>
<Input
className="w-full text-justify justify-start mb-2"
type="dropdown"
value={settings.selectedEntity}
options={[...graphMetadata.nodes.labels, ...graphMetadata.edges.labels]}
onChange={(val) => updateSettings({ selectedEntity: val as string })}
overrideRender={
graphMetadata.nodes.labels.includes(settings.selectedEntity) ? (
<EntityPill
title={
<div className="flex flex-row justify-between items-center cursor-pointer">
<span>{settings.selectedEntity || ''}</span>
<Button variantType="secondary" variant="ghost" size="2xs" iconComponent="icon-[ic--baseline-arrow-drop-down]" />
</div>
}
/>
) : (
<RelationPill
title={
<div className="flex flex-row justify-between items-center cursor-pointer">
<span>{settings.selectedEntity || ''}</span>
<Button variantType="secondary" variant="ghost" size="2xs" iconComponent="icon-[ic--baseline-arrow-drop-down]" />
</div>
}
/>
)
}
></Input>
<div className="mb-2 w-full">
<Input
className="w-full text-justify justify-start"
type="dropdown"
value={settings.selectedAttribute}
options={attributeOptions}
onChange={(val) => updateSettings({ selectedAttribute: val as string })}
></Input>
</div>
<div className="mb-2">
<Input
className="w-full text-justify justify-start"
type="dropdown"
value={settings.selectedStat}
options={statsOptions}
onChange={(val) => updateSettings({ selectedStat: val as string })}
></Input>
</div>
</div>
</SettingsContainer>
);
};
const Vis0DRef = React.createRef<Vis0DVisHandle>();
export const Vis0DComponent: VISComponentType<Vis0DProps> = {
component: React.forwardRef((props: VisualizationPropTypes<Vis0DProps>, ref) => <Vis0D {...props} ref={Vis0DRef} />),
settingsComponent: Vis0DSettings,
settings: settings,
exportImage: () => {
if (Vis0DRef.current) {
Vis0DRef.current.exportImageInternal();
} else {
console.error('0Dvis reference is not set.');
}
},
};
export default Vis0DComponent;