Skip to content

Commit

Permalink
[graph model] impact filter ad appearance when changing model
Browse files Browse the repository at this point in the history
- filters using deprecated attributes are removed
- appearance element using deprecated attributes are reset to initial state
relates #119
  • Loading branch information
paulgirard committed Feb 1, 2024
1 parent 94ed387 commit d55f912
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 14 deletions.
3 changes: 3 additions & 0 deletions src/components/GraphAppearance/color/ColorItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export const ColorItem: FC<{ itemType: ItemType }> = ({ itemType }) => {
if (!option || option.value === "fixed") {
if (color.type !== "fixed") {
setColorAppearance(itemType, {
itemType,
type: "fixed",
value: baseValue,
});
Expand All @@ -102,6 +103,7 @@ export const ColorItem: FC<{ itemType: ItemType }> = ({ itemType }) => {
} else {
if (option.type === "ranking") {
setColorAppearance(itemType, {
itemType,
type: "ranking",
field: option.field,
colorScalePoints: [
Expand All @@ -122,6 +124,7 @@ export const ColorItem: FC<{ itemType: ItemType }> = ({ itemType }) => {
) as string[];

setColorAppearance(itemType, {
itemType,
type: "partition",
field,
colorPalette: getPalette(values),
Expand Down
4 changes: 2 additions & 2 deletions src/components/GraphAppearance/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ const GraphItemAppearance: FC<{ itemType: ItemType }> = ({ itemType }) => {
<input
className="form-check-input"
type="checkbox"
checked={showEdges}
onChange={(e) => setShowEdges(e.target.checked)}
checked={showEdges.value}
onChange={(e) => setShowEdges({ itemType: "edges", value: e.target.checked })}
id="show-edges"
/>
<label className="form-check-label" htmlFor="show-edges">
Expand Down
4 changes: 4 additions & 0 deletions src/components/GraphAppearance/label/LabelItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,25 @@ export const LabelItem: FC<{ itemType: ItemType }> = ({ itemType }) => {
onChange={(option) => {
if (!option) {
setLabelAppearance(itemType, {
itemType,
type: "none",
});
} else if (option.type === "field") {
setLabelAppearance(itemType, {
itemType,
type: "field",
field: option.field,
missingLabel: null,
});
} else if (option.type === "fixed") {
setLabelAppearance(itemType, {
itemType,
type: "fixed",
value: "label",
});
} else {
setLabelAppearance(itemType, {
itemType,
type: option.type,
});
}
Expand Down
2 changes: 2 additions & 0 deletions src/components/GraphAppearance/size/SizeItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export const SizeItem: FC<{ itemType: ItemType }> = ({ itemType }) => {
if (!option || option.value === "fixed") {
if (size.type !== "fixed") {
setSizeAppearance(itemType, {
itemType,
type: "fixed",
value: baseValue,
});
Expand All @@ -78,6 +79,7 @@ export const SizeItem: FC<{ itemType: ItemType }> = ({ itemType }) => {
} as Size);
} else if (option.type === "ranking") {
setSizeAppearance(itemType, {
itemType,
type: "ranking",
field: option.field,
minSize: baseValue / 2,
Expand Down
4 changes: 2 additions & 2 deletions src/core/appearance/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { ItemType } from "../types";
import { atom } from "../utils/atoms";
import { Producer, producerToAction } from "../utils/producers";
import { AppearanceState, Color, Label, LabelSize, Size } from "./types";
import { AppearanceState, BooleanAppearance, Color, Label, LabelSize, Size } from "./types";
import { getEmptyAppearanceState, serializeAppearanceState } from "./utils";

const resetState: Producer<AppearanceState, []> = () => {
return () => getEmptyAppearanceState();
};

const setShowEdges: Producer<AppearanceState, [boolean]> = (showEdges) => {
const setShowEdges: Producer<AppearanceState, [BooleanAppearance]> = (showEdges) => {
return (state) => ({ ...state, showEdges });
};

Expand Down
21 changes: 15 additions & 6 deletions src/core/appearance/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { EdgeDisplayData, NodeDisplayData } from "sigma/types";

import { ItemData } from "../graph/types";
import { ItemType } from "../types";

interface NoFieldValue<T extends string> {
interface AppearanceBaseElement {
itemType: ItemType;
field?: string;
}

interface NoFieldValue<T extends string> extends AppearanceBaseElement {
type: T;
field?: undefined;
}
Expand All @@ -15,7 +21,7 @@ export interface FixedSize extends NoFieldValue<"fixed"> {

export type TransformationMethod = { pow: number } | "log" | { spline: [[number, number], [number, number]] };

export interface RankingSize {
export interface RankingSize extends AppearanceBaseElement {
type: "ranking";
field: string;
minSize: number;
Expand All @@ -36,14 +42,14 @@ export interface ColorScalePointType {
scalePoint: number;
color: string;
}
export interface RankingColor {
export interface RankingColor extends AppearanceBaseElement {
type: "ranking";
field: string;
colorScalePoints: ColorScalePointType[];
transformationMethod?: { pow: number } | "log" | { spline: [[number, number], [number, number]] };
missingColor: string;
}
export interface PartitionColor {
export interface PartitionColor extends AppearanceBaseElement {
type: "partition";
field: string;
colorPalette: Record<string, string>;
Expand All @@ -56,7 +62,7 @@ export type EdgeColor = Color | SourceNodeColor | TargetNodeColor;
export type NoLabel = NoFieldValue<"none">;
export type DataLabel = NoFieldValue<"data">;
export type FixedLabel = NoFieldValue<"fixed"> & { value: string };
export interface FieldLabel {
export interface FieldLabel extends AppearanceBaseElement {
type: "field";
field: string;
missingLabel: string | null;
Expand All @@ -68,11 +74,14 @@ export type FixedLabelSize = NoFieldValue<"fixed"> & BaseLabelSize & { value: nu
export type ItemLabelSize = NoFieldValue<"item"> & BaseLabelSize & { sizeCorrelation: number };
export type LabelSize = FixedLabelSize | ItemLabelSize;

export interface BooleanAppearance extends AppearanceBaseElement {
value: boolean;
}
/**
* This state contains everything needed to generate the visual getters:
*/
export interface AppearanceState {
showEdges: boolean;
showEdges: BooleanAppearance;
nodesSize: Size;
edgesSize: Size;
nodesColor: Color;
Expand Down
13 changes: 12 additions & 1 deletion src/core/appearance/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,32 +35,43 @@ export const DEFAULT_EDGE_LABEL_SIZE = 14;

export function getEmptyAppearanceState(): AppearanceState {
return {
showEdges: true,
showEdges: {
itemType: "edges",
value: true,
},
nodesSize: {
itemType: "nodes",
type: "data",
},
edgesSize: {
itemType: "edges",
type: "data",
},
nodesColor: {
itemType: "nodes",
type: "data",
},
edgesColor: {
itemType: "edges",
type: "data",
},
nodesLabel: {
itemType: "nodes",
type: "data",
},
edgesLabel: {
itemType: "edges",
type: "data",
},
nodesLabelSize: {
itemType: "nodes",
type: "fixed",
value: DEFAULT_NODE_LABEL_SIZE,
zoomCorrelation: 0,
density: 1,
},
edgesLabelSize: {
itemType: "edges",
type: "fixed",
value: DEFAULT_EDGE_LABEL_SIZE,
zoomCorrelation: 0,
Expand Down
44 changes: 41 additions & 3 deletions src/core/graph/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Attributes } from "graphology-types";
import { isNil, last, mapValues, omit } from "lodash";
import { isNil, last, mapValues, omit, omitBy } from "lodash";
import { Coordinates } from "sigma/types";

import { appearanceAtom } from "../appearance";
import { applyVisualProperties, getAllVisualGetters } from "../appearance/utils";
import { applyVisualProperties, getAllVisualGetters, getEmptyAppearanceState } from "../appearance/utils";
import { filtersAtom } from "../filters";
import { FilteredGraph } from "../filters/types";
import { FilterType, FilteredGraph } from "../filters/types";
import { applyFilters } from "../filters/utils";
import { itemsRemove, searchActions, searchAtom } from "../search";
import { SearchState } from "../search/types";
Expand Down Expand Up @@ -241,6 +241,44 @@ graphDatasetAtom.bind((graphDataset, previousGraphDataset) => {
searchActions.indexAll();
}

// When fields changed, check if filter or appearance use it
if (updatedKeys.has("edgeFields") || updatedKeys.has("nodeFields")) {
const nodeFields = graphDataset.nodeFields.map((nf) => nf.id);
const edgeFields = graphDataset.edgeFields.map((nf) => nf.id);
// filters
const filtersState = filtersAtom.get();
const filterFilters = (f: FilterType) =>
!("field" in f) ||
(f.itemType === "nodes" && nodeFields.includes(f.field)) ||
(f.itemType === "edges" && edgeFields.includes(f.field));
filtersAtom.set({
past: filtersState.past.filter(filterFilters),
future: filtersState.future.filter(filterFilters),
});
// appearance
const appearanceState = appearanceAtom.get();
const initialState = getEmptyAppearanceState();

const newState = {
...initialState,
...omitBy(appearanceState, (appearanceElement) => {
if (
appearanceElement.field &&
((appearanceElement.itemType === "edges" && !edgeFields.includes(appearanceElement.field)) ||
(appearanceElement.itemType === "nodes" && !nodeFields.includes(appearanceElement.field)))
) {
// this appearance element is based on a field which is not in the model anymore
// let's reset it
return true;
}
// this appearance is not based on a field or on a field existing in the model
return false;
}),
};

appearanceAtom.set(newState);
}

// When graph meta change, we set the page metadata
if (updatedKeys.has("metadata")) {
document.title = ["Gephi Lite", graphDataset.metadata.title].filter((s) => !isNil(s)).join(" - ");
Expand Down

0 comments on commit d55f912

Please sign in to comment.