Skip to content

Commit

Permalink
Merge pull request #3 from multinet-app/add-network-subsetter
Browse files Browse the repository at this point in the history
Add network subsetter
  • Loading branch information
JackWilb authored Dec 20, 2022
2 parents 275bd38 + 72e5ff5 commit b0a391c
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 0 deletions.
7 changes: 7 additions & 0 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@ export {}
declare module '@vue/runtime-core' {
export interface GlobalComponents {
LoginMenu: typeof import('./src/components/LoginMenu.vue')['default']
NetworkSubsetter: typeof import('./src/components/NetworkSubsetter.vue')['default']
VAvatar: typeof import('vuetify/lib')['VAvatar']
VBtn: typeof import('vuetify/lib')['VBtn']
VCard: typeof import('vuetify/lib')['VCard']
VCardText: typeof import('vuetify/lib')['VCardText']
VCardTitle: typeof import('vuetify/lib')['VCardTitle']
VDivider: typeof import('vuetify/lib')['VDivider']
VIcon: typeof import('vuetify/lib')['VIcon']
VList: typeof import('vuetify/lib')['VList']
VListItem: typeof import('vuetify/lib')['VListItem']
VListItemAction: typeof import('vuetify/lib')['VListItemAction']
VMenu: typeof import('vuetify/lib')['VMenu']
VOverlay: typeof import('vuetify/lib')['VOverlay']
VRow: typeof import('vuetify/lib')['VRow']
VSlider: typeof import('vuetify/lib')['VSlider']
}
}
82 changes: 82 additions & 0 deletions src/components/NetworkSubsetter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<template>
<div>
<v-row
align="center"
justify="center"
>
<v-overlay
absolute
>
<v-card>
<v-card-title>Network Too Large</v-card-title>
<v-card-text>
The network you are loading is too large to visualize in this tool. Please select one of the following options:
</v-card-text>
<v-card>
<v-divider />
<v-card-text>
<div>Choose a random subset of nodes</div>
<v-slider
v-model="subsetAmount"
:max="maxSubsetSize"
:min="minSubsetSize"
step="10"
ticks
thumb-label
thumb-color="primary"
>
<template v-slot:append>
<v-btn
color="primary"
class="mt-0 pt-0"
@click="subset"
>subset</v-btn>
</template>
</v-slider>
</v-card-text>
<v-divider />
</v-card>
</v-card>
</v-overlay>
</v-row>
</div>
</template>

<script setup lang="ts">
import { multinetApi } from 'multinet';
import { ref } from 'vue';
import { LoadError, Network } from '../types';
import { subsetNetwork } from '../utils/queryUtils';
const props = defineProps<{
workspaceName: string;
minSubsetSize: number;
maxSubsetSize: number;
nodeTableNames: string[];
edgeTableName: string;
loadError: LoadError;
setLoadError: (a: LoadError) => void;
networkName: string;
api: ReturnType<typeof multinetApi>;
}>();
const emit = defineEmits<{
(e: 'networkUpdated', network: Network): void
}>()
const subsetAmount = ref(0);
async function subset() {
const newNetwork = await subsetNetwork(
props.workspaceName,
subsetAmount.value,
props.nodeTableNames,
props.edgeTableName,
props.loadError,
props.setLoadError,
props.networkName,
props.api,
);
emit('networkUpdated', newNetwork);
}
</script>
2 changes: 2 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import LoginMenu from './components/LoginMenu.vue';
import NetworkSubsetter from './components/NetworkSubsetter.vue';

export {
LoginMenu,
NetworkSubsetter,
};
26 changes: 26 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { TableRow } from 'multinet';

export interface Node extends TableRow {
type: string;
neighbors: string[];
degreeCount: number;
children?: Node[];
parentPosition?: number;
[propName: string]: unknown;
}

export interface Edge extends TableRow {
_from: string;
_to: string;
[propName: string]: unknown;
}

export interface Network {
nodes: Node[];
edges: Edge[];
}

export interface LoadError {
message: string;
href: string;
}
46 changes: 46 additions & 0 deletions src/utils/queryUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { LoadError, Network } from '../types';
import { multinetApi } from 'multinet';

export async function subsetNetwork(
workspaceName: string,
subsetAmount: number,
nodeTableNames: string[],
edgeTableName: string,
loadError: LoadError,
setLoadError: (a: LoadError) => void,
networkName: string,
api: ReturnType<typeof multinetApi>
) {
const aqlQuery = `let nodes = (FOR n in [${nodeTableNames}][**] LIMIT ${subsetAmount} RETURN n) let edges = (FOR e in ${edgeTableName} filter e._from in nodes[**]._id && e._to in nodes[**]._id RETURN e)
RETURN {"nodes": nodes[**], edges}`;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
let newAQLNetwork: Network = { nodes: [], edges: []};

try {
newAQLNetwork = (await api.aql(workspaceName, { query: aqlQuery, bind_vars: {} }) as Network[])[0];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
if (error.status === 400) {
setLoadError({
message: error.statusText,
href: 'https://multinet.app',
});
} else {
setLoadError({
message: 'An unexpected error ocurred',
href: 'https://multinet.app',
});
}
} finally {
if (loadError.message === 'The network you are loading is too large' && typeof newAQLNetwork === 'undefined') {
// Catches CORS errors, issues when DB/API are down, etc.
setLoadError({
message: 'There was a network issue when getting data',
href: `./?workspace=${workspaceName}&network=${networkName}`,
});
}
}

return newAQLNetwork;
}

0 comments on commit b0a391c

Please sign in to comment.