Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document and format #383

Merged
merged 2 commits into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 37 additions & 33 deletions src/APIInterface.mjs
Original file line number Diff line number Diff line change
@@ -1,42 +1,46 @@

// Interface for handling function called from the tubemap frontend
// Abstract class expecting different implmentations of the following functions
// Substituting different subclasses should allow the functions to give the same result
// Substituting different subclasses should allow the functions to give the same result
export class APIInterface {
// Takes in and process a tube map view(viewTarget) from the tubemap container
// Expects a object to be returned with the necessary information to draw a tubemap from vg
// object should contain keys: graph, gam, region, coloredNodes
async getChunkedData(viewTarget) {
throw new Error("getChunkedData function not implemented");
}
// Takes in and process a tube map view(viewTarget) from the tubemap container.
// Expects a object to be returned with the necessary information to draw a tubemap from vg
// object should contain keys: graph, gam, region, coloredNodes.
// cancelSignal is an AbortSignal that can be used to cancel the request.
async getChunkedData(viewTarget, cancelSignal) {
throw new Error("getChunkedData function not implemented");
}

// Returns files used to determine what options are available in the track picker
// Returns object with keys: files, bedFiles
async getFilenames() {
throw new Error("getFilenames function not implemented");
}
// Returns files used to determine what options are available in the track picker.
// Returns object with keys: files, bedFiles.
// cancelSignal is an AbortSignal that can be used to cancel the request.
async getFilenames(cancelSignal) {
throw new Error("getFilenames function not implemented");
}

// Takes in a bedfile path or a url pointing to a raw bed file
// Returns object with key: bedRegions
// bedRegions contains information extrapolated from each line of the bedfile
async getBedRegions(bedFile) {
throw new Error("getBedRegions function not implemented");
}
// Takes in a bedfile path or a url pointing to a raw bed file.
// Returns object with key: bedRegions.
// bedRegions contains information extrapolated from each line of the bedfile.
// cancelSignal is an AbortSignal that can be used to cancel the request.
async getBedRegions(bedFile, cancelSignal) {
throw new Error("getBedRegions function not implemented");
}

// Takes in a graphFile path
// Returns object with key: pathNames
// Returns pathnames available in a graphfile
async getPathNames(graphFile) {
throw new Error("getPathNames function not implemented");
}
// Takes in a graphFile path.
// Returns object with key: pathNames.
// Returns pathnames available in a graphfile.
// cancelSignal is an AbortSignal that can be used to cancel the request.
async getPathNames(graphFile, cancelSignal) {
throw new Error("getPathNames function not implemented");
}

// Expects a bed file(or url) and a chunk name
// Attempts to download tracks associated with the chunk name from the bed file if it is a URL
// Returns object with key: tracks
// Returns tracks found from local directories as a tracks object
async getChunkTracks(bedFile, chunk) {
throw new Error("getChunkTracks function not implemented");
}
// Expects a bed file(or url) and a chunk name.
// Attempts to download tracks associated with the chunk name from the bed file if it is a URL.
// Returns object with key: tracks.
// Returns tracks found from local directories as a tracks object.
// cancelSignal is an AbortSignal that can be used to cancel the request.
async getChunkTracks(bedFile, chunk, cancelSignal) {
throw new Error("getChunkTracks function not implemented");
}
}

export default APIInterface;
export default APIInterface;
3 changes: 1 addition & 2 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ input[type="file"] {
border-color: #b61515;
}


.btn-secondary {
background-color: #868e96;
border-color: #868e96;
Expand Down Expand Up @@ -218,7 +217,7 @@ input[type="file"] {

/* Close Popup */

.closePopup{
.closePopup {
align-items: center;
scale: 0.7;
border-radius: 50%;
Expand Down
45 changes: 23 additions & 22 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,11 @@ import ServerAPI from "./ServerAPI.mjs";
const EXAMPLE_TRACKS = [
// Fake tracks for the generated examples.
// TODO: Move over there.
{"files": [{"type": "graph", "name": "fakeGraph"}]},
{"files": [{"type": "read", "name": "fakeReads"}]}
{ files: [{ type: "graph", name: "fakeGraph" }] },
{ files: [{ type: "read", name: "fakeReads" }] },
];

function getColorSchemesFromTracks(tracks) {

let schemes = [];

for (const key in tracks) {
Expand All @@ -33,13 +32,13 @@ function getColorSchemesFromTracks(tracks) {
if (tracks[key].trackColorSettings !== undefined) {
schemes[key] = tracks[key].trackColorSettings;
} else if (tracks[key].trackType === "read") {
schemes[key] = {...config.defaultReadColorPalette};
schemes[key] = { ...config.defaultReadColorPalette };
} else {
schemes[key] = {...config.defaultHaplotypeColorPalette};
schemes[key] = { ...config.defaultHaplotypeColorPalette };
}
}
}

return schemes;
}

Expand All @@ -49,7 +48,7 @@ class App extends Component {

this.APIInterface = new ServerAPI(props.apiUrl);

console.log('App component starting up with API URL: ' + props.apiUrl)
console.log("App component starting up with API URL: " + props.apiUrl);

// Set defaultViewTarget to either URL params (if present) or the first example
this.defaultViewTarget =
Expand Down Expand Up @@ -100,23 +99,21 @@ class App extends Component {
!isEqual(this.state.viewTarget, newViewTarget) ||
this.state.dataOrigin !== dataOriginTypes.API
) {

console.log("Adopting view target: ", newViewTarget)
console.log("Adopting view target: ", newViewTarget);

this.setState((state) => {
// Make sure we have color schemes.
let newColorSchemes = getColorSchemesFromTracks(newViewTarget.tracks);


console.log("Adopting color schemes: ", newColorSchemes)
console.log("Adopting color schemes: ", newColorSchemes);

return {
viewTarget: newViewTarget,
dataOrigin: dataOriginTypes.API,
visOptions: {
...state.visOptions,
colorSchemes: newColorSchemes,
}
colorSchemes: newColorSchemes,
},
};
});
}
Expand Down Expand Up @@ -150,21 +147,21 @@ class App extends Component {
// index is the index in the tracks array of the track to operate on. For now,
// haplotypes and paths are lumped together as track 0 here, with up to two
// tracks of reads afterward; eventually this will follow the indexing of the real
// tracks array.
// tracks array.
//
// value is the value to set. For "mainPalette" and "auxPalette" this is the name
// of a color palette, such as "reds".
setColorSetting = (key, index, value) => {
this.setState((state) => {
let newcolors = [...state.visOptions.colorSchemes]
let newcolors = [...state.visOptions.colorSchemes];
if (newcolors[index] === undefined) {
// Handle the set call from example data maybe coming before we set up any nonempty real tracks.
// TODO: Come up with a better way to do this.
newcolors[index] = {...config.defaultReadColorPalette};
newcolors[index] = { ...config.defaultReadColorPalette };
}
newcolors[index] = {...newcolors[index], [key]: value};
console.log('Set index ' + index + ' key ' + key + ' to ' + value);
console.log('New colors: ', newcolors);
newcolors[index] = { ...newcolors[index], [key]: value };
console.log("Set index " + index + " key " + key + " to " + value);
console.log("New colors: ", newcolors);
return {
visOptions: {
...state.visOptions,
Expand All @@ -175,7 +172,7 @@ class App extends Component {
};

setDataOrigin = (dataOrigin) => {
this.setState({dataOrigin});
this.setState({ dataOrigin });
};

render() {
Expand All @@ -200,14 +197,18 @@ class App extends Component {
/>
<CustomizationAccordion
visOptions={this.state.visOptions}
tracks={this.state.dataOrigin === dataOriginTypes.API ? this.state.viewTarget.tracks : EXAMPLE_TRACKS}
tracks={
this.state.dataOrigin === dataOriginTypes.API
? this.state.viewTarget.tracks
: EXAMPLE_TRACKS
}
toggleFlag={this.toggleVisOptionFlag}
handleMappingQualityCutoffChange={
this.handleMappingQualityCutoffChange
}
setColorSetting={this.setColorSetting}
/>
<Footer/>
<Footer />
</div>
);
}
Expand Down
12 changes: 6 additions & 6 deletions src/App.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import App from "./App";

import { fetchAndParse } from "./fetchAndParse";


// We want to be able to replace the `fetchAndParse` that *other* files see,
// and we want to use *different* implementations for different tests in this
// file. We can mock it with Jest, but Jest will move this call before the
Expand All @@ -17,12 +16,12 @@ import { fetchAndParse } from "./fetchAndParse";

// Register the given replacement function to be called instead of fetchAndParse.
function setFetchAndParseMock(replacement) {
globalThis["__App.test.js_fetchAndParse_mock"] = replacement
globalThis["__App.test.js_fetchAndParse_mock"] = replacement;
}

// Remove any replacement function and go back to the real fetchAndParse.
function clearFetchAndParseMock() {
globalThis["__App.test.js_fetchAndParse_mock"] = undefined
globalThis["__App.test.js_fetchAndParse_mock"] = undefined;
}

jest.mock("./fetchAndParse", () => {
Expand All @@ -31,14 +30,15 @@ jest.mock("./fetchAndParse", () => {
// Ge tthe real fetchAndParse
const { fetchAndParse } = jest.requireActual("./fetchAndParse");
// Grab the replacement or the real one if no replacement is set
let functionToUse = globalThis["__App.test.js_fetchAndParse_mock"] ?? fetchAndParse;
let functionToUse =
globalThis["__App.test.js_fetchAndParse_mock"] ?? fetchAndParse;
// Give it any arguments we got and return its return value.
return functionToUse.apply(this, arguments);
};
}
// When someone asks for this module, hand them these contents instead.
return {
__esModule: true,
fetchAndParse: fetchAndParseDispatcher
fetchAndParse: fetchAndParseDispatcher,
};
});

Expand Down
Loading
Loading