Skip to content

Commit

Permalink
More refactoring and linting improvement. Fix Cytoscape test.
Browse files Browse the repository at this point in the history
  • Loading branch information
KonradHoeffner committed Oct 24, 2023
1 parent a4b1d25 commit ea02790
Show file tree
Hide file tree
Showing 17 changed files with 52 additions and 58 deletions.
5 changes: 4 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
"@typescript-eslint/no-explicit-any": ["off"],
"@typescript-eslint/no-this-alias": ["warn", { "allowedNames": ["thisView"] }],
"@typescript-eslint/no-shadow": ["warn"],
"@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }],
"@typescript-eslint/consistent-type-imports": ["error"],
"@typescript-eslint/consistent-type-exports": ["error"],
"no-shadow": ["off"],
"no-console": ["off"],
"no-duplicate-imports": ["error"],
Expand All @@ -45,6 +48,7 @@
"eol-last": ["error"],
"import/no-default-export": ["warn"],
"import/no-cycle": ["warn"],
"import/no-unresolved": ["error"],
"max-len": ["warn", 245],
"padded-blocks": ["error", "never"],
"space-in-parens": ["error"],
Expand All @@ -55,7 +59,6 @@
"no-control-regex": ["off"],
"curly": ["warn"],
"camelcase": ["warn"],
"@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }],
"prefer-const": ["warn"],
"comma-style": ["error", "last"],
"class-methods-use-this": ["off"],
Expand Down
2 changes: 1 addition & 1 deletion js/browser/chaptersearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import * as sparql from "../sparql";
import * as util from "./util";
import * as language from "../lang/language";
import { Graph } from "./graph";
import type { Graph } from "./graph";
import MicroModal from "micromodal";

const chapters: Map<string, Array<string>> = new Map();
Expand Down
2 changes: 1 addition & 1 deletion js/browser/contextmenu.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/** Creates the circular context menu that can be opened on top of a node/edge.
Needs to be initialized before it can be used via the default export function.*/
import { flatHelp } from "../help";
import { MenuItem } from "./menuItem";
import type { MenuItem } from "./menuItem";
import cytoscape from "cytoscape";
//{ Collection, EdgeSingular, NodeSingular, SingularElementReturnValue } from "cytoscape";
import contextMenus from "cytoscape-context-menus";
Expand Down
4 changes: 2 additions & 2 deletions js/browser/contextmenuEdges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import * as util from "./util";
import { EDGE } from "../edge";
import * as language from "../lang/language";
import { Graph } from "./graph";
import { ContextMenu, MenuItem } from "./contextmenu";
import { type MenuItem, ContextMenu } from "./contextmenu";
import log from "loglevel";
import { EdgeSingular } from "cytoscape";
import type { EdgeSingular } from "cytoscape";

/** Creates a human readable string of the triple that an edge represents.
* @param edge - the edge, whose label is determined
Expand Down
2 changes: 1 addition & 1 deletion js/browser/contextmenuNodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as rdf from "../rdf";
import { NODE } from "../node";
import * as util from "./util";
import { Graph, Direction } from "./graph";
import { ContextMenu, MenuItem } from "./contextmenu";
import { type MenuItem, ContextMenu } from "./contextmenu";
import * as sparql from "../sparql";
import * as language from "../lang/language";

Expand Down
15 changes: 8 additions & 7 deletions js/browser/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import * as language from "../lang/language";
import { progress } from "./progress";
import { View } from "./view";
import MicroModal from "micromodal";
import cytoscape, { Collection, NodeCollection, EdgeCollection, NodeSingular } from "cytoscape";
import type { Core, Collection, NodeCollection, EdgeCollection, NodeSingular } from "cytoscape";
import cytoscape from "cytoscape"; //eslint-disable-line no-duplicate-imports
import type { Menu } from "./menu";
import log from "loglevel";

Expand All @@ -27,11 +28,11 @@ export enum Direction {

/** Cytoscape.js Graph Class with path operations and styling. */
export class Graph {
cy: cytoscape.Core;
selectedNode: cytoscape.NodeSingular | null = null;
cy: Core;
selectedNode: NodeSingular | null = null;
starMode: boolean = false;
matchComponents: Array<cytoscape.Collection> = [];
pathSource: cytoscape.NodeSingular | null = null;
matchComponents: Array<Collection> = [];
pathSource: NodeSingular | null = null;
container: HTMLElement;
instancesLoaded: boolean = false;
menu: Menu = null;
Expand Down Expand Up @@ -84,7 +85,7 @@ export class Graph {
}
/**
@param eles - the elements to assign the star mode css class to */
static starStyle(eles: cytoscape.Collection): void {
static starStyle(eles: Collection): void {
eles.removeClass("hidden");
//eles.addClass('starmode');
eles.select();
Expand Down Expand Up @@ -587,7 +588,7 @@ export class Graph {
}
/**Show close matches of the given nodes.
* @param nodes - the nodes whose close matches are shown */
showCloseMatch(nodes: cytoscape.NodeCollection): void {
showCloseMatch(nodes: NodeCollection): void {
const edges = nodes.connectedEdges(".unfiltered").filter('[pl="closeMatch"]'); // ,[pl="narrowMatch"],[pl="narrowMatch"]
const matches = edges.connectedNodes(".unfiltered");
log.debug(
Expand Down
2 changes: 1 addition & 1 deletion js/browser/load.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** Module for loading files both locally from the server and via upload from the client.*/
import { View } from "./view";
import { ViewJson, Session } from "./interface";
import type { ViewJson, Session } from "./interface";
import { config } from "../config";
import { fromJSON } from "./state";
import { VERSION } from "./util";
Expand Down
6 changes: 3 additions & 3 deletions js/browser/save.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/** Lets the user save files generated from the loaded graph. */
import { ViewJson, Session } from "./interface";
import type { ViewJson, Session } from "./interface";
import { config } from "../config";
import { toJSON } from "./state";
import { View, State } from "./view";
import { View, type State } from "./view";
import { VERSION } from "./util";
import { Graph } from "./graph";
import type { Graph } from "./graph";
import log from "loglevel";
import c from "cytoscape";
import svg from "cytoscape-svg";
Expand Down
1 change: 1 addition & 0 deletions js/browser/state.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/** Application State, e.g. which filters and options are activated, which is imported from and exported to JSON. */
import { Filter } from "./filter";
import { menu } from "./menu";
import { VERSION } from "./util";
Expand Down
9 changes: 5 additions & 4 deletions js/browser/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { edgeCommands } from "./contextmenuEdges";
import { goldenLayout } from "./viewLayout";
import { toJSON } from "./state";
import log from "loglevel";
import { ComponentConfig, ContentItem } from "golden-layout";
import type { ComponentConfig, ContentItem } from "golden-layout";

let viewCount: number = 0; // only used for the name, don't decrement on destroy to prevent name conflicts

Expand All @@ -31,16 +31,17 @@ function traverse(x: ContentItem, depth: number): Array<ContentItem> {
return removeTabsArray;
}

export interface State {
interface ViewState {
title: string;
graph: Graph;
name: string;
cy: cytoscape.Core;
}

/** Tab that shows a graph. */
export class View {
initialized: Promise<void>;
state: State;
state: ViewState;
readonly cyContainer: HTMLDivElement = document.createElement("div");
element: HTMLElement;
cxtMenu: ContextMenu;
Expand All @@ -53,7 +54,7 @@ export class View {

/** Returns the state of the active (focussed) view.
@returns The state of the active (focussed) view. */
static activeState(): State {
static activeState(): ViewState {
return (viewLayout as any).selectedItem?.getActiveContentItem()?.config?.componentState;
}

Expand Down
2 changes: 1 addition & 1 deletion js/config.dist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Copy to js/config.ts after checkout and adapt to your preferences.
*/

import { LogLevelDesc } from "loglevel";
import type { LogLevelDesc } from "loglevel";

export const config = {
defaultSubOntologies: ["meta", "bb", "ob", "ciox", "he", "it4it"],
Expand Down
21 changes: 8 additions & 13 deletions js/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import { timer } from "./timer";
import { NODE } from "./node";
import { config } from "./config";
import log from "loglevel";
import cytoscape, { ElementDefinition, LayoutOptions, NodeCollection } from "cytoscape";
import type { ElementDefinition, LayoutOptions, NodeCollection, Layouts, Position } from "cytoscape";
import cytoscape from "cytoscape"; //eslint-disable-line no-duplicate-imports
import cytoscapeeuler from "cytoscape-euler";
cytoscape.use(cytoscapeeuler);

const ANIMATE_THRESHOLD = 500;

let activeLayout: cytoscape.Layouts;
let activeLayout: Layouts;

/**
@param layoutName - Cytoscape.js layout name
Expand Down Expand Up @@ -52,7 +53,7 @@ export function positions(nodes: NodeCollection): Array<Array<number>> {

/** @param nodes - the nodes whose center is returned
@returns the center point of the nodes */
function center(nodes: cytoscape.NodeCollection): cytoscape.Position {
function center(nodes: NodeCollection): Position {
const c = { x: 0.0, y: 0.0 };
for (let i = 0; i < nodes.length; i++) {
const pos = nodes[i].position();
Expand All @@ -76,20 +77,14 @@ function center(nodes: cytoscape.NodeCollection): cytoscape.Position {
run(cy,{"name":"grid"},new Set(["meta","ciox"]))
```
*/
export async function run(
cy: cytoscape.Core,
layoutConfig: LayoutOptions,
subs?: Array<string>,
separateSubs: boolean = false,
save: boolean = false
): Promise<boolean> {
export async function run(cy: Core, layoutConfig: LayoutOptions, subs?: Array<string>, separateSubs: boolean = false, save: boolean = false): Promise<boolean> {
if (cy.nodes().size() === 0) {
log.warn("layout.js#run: Graph empty. Nothing to layout.");
return false;
}
const layoutTimer = timer("layout");
if (separateSubs) {
const sources: Set<cytoscape.ElementDefinition> = new Set();
const sources: Set<ElementDefinition> = new Set();
const virtualEdges: Array<ElementDefinition> = [];

const nodes = cy.nodes();
Expand Down Expand Up @@ -168,7 +163,7 @@ in pos are set to position `{x:0,y:0}`, positions without matching node id are i
@returns whether the layout could be successfully applied
@example `presetLayout(cy,[["http://www.snik.eu...",{"x":0,"y":0}],...]);`
*/
export async function presetLayout(cy: cytoscape.Core, pos: Array<cytoscape.Position>): Promise<boolean> {
export async function presetLayout(cy: Core, pos: Array<Position>): Promise<boolean> {
const map = new Map(pos as any);
let hits = 0;
let misses = 0;
Expand Down Expand Up @@ -318,7 +313,7 @@ export function eulerVariable(len)
*/

/** Layout for compound graphs */
export const cose: cytoscape.LayoutOptions = {
export const cose: LayoutOptions = {
name: "cose",
animate: true,
refresh: 50,
Expand Down
12 changes: 6 additions & 6 deletions js/loadGraphFromSparql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as sparql from "./sparql";
import { timer } from "./timer";
import { config } from "./config";
import log from "loglevel";
import cytoscape, { ElementDefinition } from "cytoscape";
import type { ElementDefinition, Core } from "cytoscape";

interface ClassBinding {
src: { value: string };
Expand Down Expand Up @@ -83,7 +83,7 @@ function parseLabels(s: string): object {
* @param from - a SPARQL FROM clause defining where to load the classes from
* @returns nodes - representing the classes
*/
async function createClassNodes(from: string): Promise<Array<cytoscape.ElementDefinition>> {
async function createClassNodes(from: string): Promise<Array<ElementDefinition>> {
const bindings = await selectClasses(from);

const nodes: Array<ElementDefinition> = [];
Expand Down Expand Up @@ -146,7 +146,7 @@ async function selectInstances(from: string): Promise<Array<object>> {
@returns cytoscape nodes for the instances */
async function createInstanceNodes(from: string): Promise<Array<object>> {
const json = await selectInstances(from);
const nodes: Array<cytoscape.ElementDefinition> = [];
const nodes: Array<ElementDefinition> = [];
for (let i = 0; i < json.length; i++) {
nodes.push({
group: "nodes",
Expand Down Expand Up @@ -210,7 +210,7 @@ async function selectTriples(from: string, fromNamed: string, instances: boolean
* @param virtual - whether to select virtual triples from domain and range statements
* @returns SPARQL query result object
*/
async function createEdges(from: string, fromNamed: string, instances: boolean, virtual: boolean): Promise<Array<cytoscape.ElementDefinition>> {
async function createEdges(from: string, fromNamed: string, instances: boolean, virtual: boolean): Promise<Array<ElementDefinition>> {
const json = await selectTriples(from, fromNamed, instances, virtual);
const edges: Array<ElementDefinition> = [];
for (let i = 0; i < json.length; i++) {
Expand Down Expand Up @@ -238,7 +238,7 @@ async function createEdges(from: string, fromNamed: string, instances: boolean,
* @param instances - whether to load instances in addition to the classes
* @returns an array of nodes
*/
async function createNodes(from: string, instances: boolean): Promise<Array<cytoscape.ElementDefinition>> {
async function createNodes(from: string, instances: boolean): Promise<Array<ElementDefinition>> {
if (!instances) {
return createClassNodes(from);
}
Expand All @@ -256,7 +256,7 @@ async function createNodes(from: string, instances: boolean): Promise<Array<cyto
@example
loadGraphFromSparql(cy,new Set(["meta","bb"]))
*/
export async function loadGraphFromSparql(cy: cytoscape.Core, graphs: Array<string>, instances: boolean = false, virtual: boolean = false): Promise<void> {
export async function loadGraphFromSparql(cy: Core, graphs: Array<string>, instances: boolean = false, virtual: boolean = false): Promise<void> {
log.debug(`Loading graph from endpoint ${config.sparql.endpoint} with graphs ${graphs}.`);
const from = graphs.map((g) => `FROM <${g}>`).reduce((a, b) => a + "\n" + b, "");
const fromNamed = from.replace(/FROM/g, "FROM NAMED");
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"c8": "^8.0.1",
"eslint": "^8.51.0",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-mocha": "^10.2.0",
"eslint-plugin-tsdoc": "^0.2.17",
"husky": "^8.0.3",
"lint-staged": "^15.0.1",
Expand Down Expand Up @@ -64,7 +65,7 @@
"preview": "vite preview",
"test": "vitest run",
"vitest": "vitest",
"lint": "eslint js --ext .ts",
"lint": "eslint js test --ext .ts",
"typecheck": "tsc --noEmit",
"doc": "typedoc --plugin typedoc-plugin-merge-modules",
"prepare": "husky install"
Expand Down
13 changes: 5 additions & 8 deletions test/cytoscape.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import * as layout from "../js/layout";
import { loadGraphFromSparql } from "../js/loadGraphFromSparql";
import { SNIK } from "../js/sparql";
import cytoscape from "cytoscape";
import euler from "cytoscape-euler";
import "isomorphic-fetch";
cytoscape.use(euler);
import chai from "chai";
const assert = chai.assert;

Expand All @@ -20,22 +18,21 @@ describe("cytoscape", () => {
test("load graph from SPARQL", async () => {
await loadGraphFromSparql(cy, graphs);
assert.closeTo(cy.nodes().size(), 1134, 100);
console.log("sparql");
});
test("calculate layout", async () => {
// Causes "TypeError: Cannot read property 'pos' of undefined"
// see https://github.com/cytoscape/cytoscape.js-euler/issues/14
//layout.run(cy,layout.euler,subs);
assert(await layout.run(cy, layout.euler, subs));
// cose is more realistic for SNIK Graph but takes over a minute
//assert(layout.run(cy,layout.cose,subs));
//assert(await layout.run(cy,layout.cose,subs));
// use the faster grid layout
await layout.run(cy, layout.grid, subs);
//await layout.run(cy, layout.grid);

const nodes = cy.nodes();
for (let i = 0; i < nodes.size(); i++) {
for (let j = i + 1; j < nodes.size(); j += 10) {
assert(
JSON.stringify(nodes[i].position()) !== JSON.stringify(nodes[j].position()),
"2 nodes at the same position " + JSON.stringify(nodes[i].position())
`2 nodes ${i} and ${j} at the same position ` + JSON.stringify(nodes[i].position())
);
}
}
Expand Down
9 changes: 2 additions & 7 deletions test/fuse.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { executionAsyncId } from "async_hooks";
import { should } from "chai";
import "isomorphic-fetch";
import { search, createIndex } from "../js/fuse";
//import chai from "chai";
//chai.should();
//const assert = chai.assert;
import { search, createIndex } from "../js/fuseSearch";
console.groupCollapsed;

const SEARCH = {
Expand All @@ -22,7 +17,7 @@ describe("fuse#search", () => {
for (const key in SEARCH) {
const uris = (await search(key)).map((x) => x.item.uri);
const expectedUris = SEARCH[key];
if (expectedUris.length == 1) {
if (expectedUris.length === 1) {
expect(uris).toEqual(expectedUris);
} else {
expect(uris).toEqual(expect.arrayContaining(expectedUris));
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@
"out": "doc",
"readme": "none"
},
"include": ["js/**/*", "globals.d.ts"],
"include": ["js/**/*", "test/**/*", "globals.d.ts"],
"exclude": ["node_modules"]
}

0 comments on commit ea02790

Please sign in to comment.