Skip to content
6 changes: 3 additions & 3 deletions src/models/data-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import {
sendMessage,
} from "@concord-consortium/codap-plugin-api";
import { decodePng } from "@concord-consortium/png-codec";
import { kChartGraphName, kDataContextName, kMapPinsCollectionName, kXYGraphName } from "../data/constants";
import { kChartGraphName, kDataContextName, kMapPinsCollectionName, kXYGraphName } from "../data/constants";
import { createOrUpdateGraphs, createOrUpdateDateSlider, createOrUpdateMap, addConnectingLinesToGraph,
addRegionOfInterestToGraphs, updateGraphRegionOfInterest, updateLocationColorMap, rescaleGraph
} from "../utils/codap-utils";
addRegionOfInterestToGraphs, updateGraphRegionOfInterest, updateLocationColorMap, rescaleGraph
} from "../utils/codap-utils";
import { GeoImage } from "./geo-image";
import { NeoDataset, NeoImageInfo } from "./neo-types";
import { kImageLoadDelay, kMaxSerialImages, kParallelLoad } from "./config";
Expand Down
76 changes: 73 additions & 3 deletions src/models/plugin-state.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,63 @@
import { getAllItems, IResult } from "@concord-consortium/codap-plugin-api";
import { makeAutoObservable } from "mobx";
import { getAllItems, getCaseBySearch, IResult } from "@concord-consortium/codap-plugin-api";
import { makeAutoObservable, reaction } from "mobx";
import {
kDataContextName,
kMapPinsCollectionName,
kPinColorAttributeName, kPinDataContextName, kPinLatAttributeName, kPinLongAttributeName
} from "../data/constants";
import { createSelectionList, deleteSelectionList, updateSelectionList } from "../utils/codap-utils";

Check warning on line 8 in src/models/plugin-state.ts

View workflow job for this annotation

GitHub Actions / Build and Run Jest Tests

Dependency cycle detected

Check warning on line 8 in src/models/plugin-state.ts

View workflow job for this annotation

GitHub Actions / Build and Run Jest Tests

Dependency cycle detected

Check warning on line 8 in src/models/plugin-state.ts

View workflow job for this annotation

GitHub Actions / S3 Deploy

Dependency cycle detected

Check warning on line 8 in src/models/plugin-state.ts

View workflow job for this annotation

GitHub Actions / S3 Deploy

Dependency cycle detected
import { NeoDataset } from "./neo-types";

interface IMapPin {
export interface IMapPin {
color: string;
id: string;
lat: number;
long: number;
}

export interface ILocationCase {
label: string;
pinColor: string;
}

export function pinLabel(pin: IMapPin) {
return `${pin.lat.toFixed(2)}, ${pin.long.toFixed(2)}`;
}


class PluginState {
neoDataset: NeoDataset | undefined;
neoDatasetName = "";
pins: IMapPin[] = [];
selectedPins: IMapPin[] = [];
selectedCases: any[] =[];

constructor() {
makeAutoObservable(this);
// Reaction to changes in selectedPins from MapPinDataContext
reaction(
() => this.selectedPins,
(selectedPins) => {
this.handleSelectionChange(
selectedPins,
kDataContextName,
kMapPinsCollectionName,
(pin) => `label == ${pinLabel(pin)}`
);
}
);
// Reaction to changes in selectedCases NEOPluginDataContext
reaction(
() => this.selectedCases,
(selectedCases) => {
this.handleSelectionChange(
selectedCases,
kPinDataContextName,
kMapPinsCollectionName,
(sCase) => `pinColor == ${sCase.pinColor}`
);
}
);
}

setNeoDataset(neoDataset: NeoDataset | undefined) {
Expand All @@ -45,6 +80,41 @@
});
}
}

setSelectedPins(selectedPins: IMapPin[]) {
this.selectedPins = selectedPins;
}

setSelectedCases(selectedCases: any[]) {
this.selectedCases = selectedCases;
}

async handleSelectionChange<T>(
selectedItems: T[], dataContextName: string, collectionName: string, searchQueryFn: (item: T) => string
): Promise<void> {
if (selectedItems.length === 0) {
deleteSelectionList(dataContextName);
return;
}

for (const item of selectedItems) {
const searchQuery = searchQueryFn(item);
const result = await getCaseBySearch(dataContextName, collectionName, searchQuery);

if (result.success) {
const selectedItemIds = result.values.map((val: any) => val.id);
if (selectedItems.length === 1) {
createSelectionList(dataContextName, selectedItemIds);
return;
} else {
const updateSelection = await updateSelectionList(dataContextName, selectedItemIds);
if (!updateSelection.success) {
createSelectionList(dataContextName, selectedItemIds);
}
}
}
}
}
}

export const pluginState = new PluginState();
92 changes: 83 additions & 9 deletions src/utils/codap-utils.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { addDataContextChangeListener, codapInterface, initializePlugin, sendMessage
} from "@concord-consortium/codap-plugin-api";
import {
kPinDataContextName, kPinLatAttributeName, kPinLongAttributeName, kPinColorAttributeName,
kPluginName, kInitialDimensions, kVersion,
kDataContextName, kMapPinsCollectionName, kOneMonthInSeconds,
kMapName, kSliderComponentName, kChartGraphName, kXYGraphName,
} from "../data/constants";
import { pluginState } from "../models/plugin-state";
import { addDataContextChangeListener, codapInterface, getCaseByID, initializePlugin, sendMessage }
from "@concord-consortium/codap-plugin-api";
// import {
// kPinDataContextName, kPinLatAttributeName, kPinLongAttributeName, kPinColorAttributeName,
// kPluginName, kInitialDimensions, kVersion,
// kDataContextName, kMapPinsCollectionName, kOneMonthInSeconds,
// kMapName, kSliderComponentName, kChartGraphName, kXYGraphName,
// } from "../data/constants";
import { kPluginName, kInitialDimensions, kVersion, kOneMonthInSeconds, kMapName,
kMapPinsCollectionName, kPinColorAttributeName, kPinDataContextName, kPinLatAttributeName, kPinLongAttributeName,
kDataContextName, kSliderComponentName, kChartGraphName, kXYGraphName } from "../data/constants";
import { IMapPin, pluginState } from "../models/plugin-state";

Check warning on line 12 in src/utils/codap-utils.ts

View workflow job for this annotation

GitHub Actions / Build and Run Jest Tests

Dependency cycle detected

Check warning on line 12 in src/utils/codap-utils.ts

View workflow job for this annotation

GitHub Actions / Build and Run Jest Tests

Dependency cycle detected

Check warning on line 12 in src/utils/codap-utils.ts

View workflow job for this annotation

GitHub Actions / S3 Deploy

Dependency cycle detected

Check warning on line 12 in src/utils/codap-utils.ts

View workflow job for this annotation

GitHub Actions / S3 Deploy

Dependency cycle detected


export async function initializeNeoPlugin() {
initializePlugin({ pluginName: kPluginName, version: kVersion, dimensions: kInitialDimensions });
Expand Down Expand Up @@ -40,7 +44,54 @@
pluginState.updatePins();
}
});
// Set up a listener for pin selection
addDataContextChangeListener(kPinDataContextName, async notification => {
const { operation, result } = notification.values;
if (operation === "selectCases" && result.success) {
const selectedPins = await getSelectionList(kPinDataContextName);
const selectedPinValues: IMapPin[] = await Promise.all(
selectedPins.map(async (pin: any) => {
const pinItem = await getCaseByID(kPinDataContextName, pin.caseID);
if (pinItem.success) {
const pinValues = pinItem.values;
const pinCase = (pinValues as any).case;
return {
id: pinCase.id,
lat: pinCase.values.pinLat,
long: pinCase.values.pinLong,
color: pinCase.values.pinColor,
};
}
return null;
})
);
pluginState.setSelectedPins(selectedPinValues);
}
});

// Set up a listener for case selection
addDataContextChangeListener(kDataContextName, async notification => {
const { operation, result } = notification.values;
if (operation === "selectCases" && result.success) {
const selectedCases = await getSelectionList(kDataContextName);
const selectedPinCases = selectedCases.filter((sCase: any) => sCase.collectionName === kMapPinsCollectionName);
const selectedCaseValues: any[] = await Promise.all(
selectedPinCases.map(async (sCase: any) => {
const caseItem = await getCaseByID(kDataContextName, sCase.caseID);
if (caseItem.success) {
const caseValues = caseItem.values;
return {
id: caseValues.id,
label: caseValues.case.values.label,
pinColor: caseValues.case.values.pinColor,
};
}
return null;
})
);
pluginState.setSelectedCases(selectedCaseValues);
}
});
}

export async function createOrUpdateMap(title: string, url?: string): Promise<void> {
Expand Down Expand Up @@ -209,3 +260,26 @@
{ colormap: colorMap });
return updateColorMap;
};

export const getSelectionList = async (dataContext: string) => {
const selectionList = await sendMessage("get", `dataContext[${dataContext}].selectionList`);
if (selectionList.success) {
return selectionList.values;
} else {
console.error("Error getting selection list");
return [];
}
};

export const deleteSelectionList = async (dataContext: string) => {
await sendMessage("create", `dataContext[${dataContext}].selectionList`, []);
};

export const createSelectionList = async (dataContext: string, selectedCaseIds: string[]) => {
await sendMessage("create", `dataContext[${dataContext}].selectionList`, selectedCaseIds);
};

export const updateSelectionList = async (dataContext: string, selectedCaseIds: string[]) => {
const result = await sendMessage("update", `dataContext[${dataContext}].selectionList`, selectedCaseIds);
return result;
};
Loading