Skip to content

Commit

Permalink
fix: ghost styling for peer dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
broofa committed Nov 14, 2021
1 parent 9263b63 commit 2cdfdc3
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 36 deletions.
13 changes: 7 additions & 6 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@ module.exports = {
}
},
rules: {
'arrow-parens': ['error', 'as-needed'],
'brace-style': ['error', '1tbs'],
eqeqeq: 'off',
'import/no-absolute-path': 'off',
'jsx-quotes': ['error', 'prefer-single'],
'multiline-ternary': 'off',
'no-mixed-operators': 'off',
'no-return-assign': 'off',
'no-var': ['error'],
'one-var': 'off',
'jsx-quotes': ['error', 'prefer-single'],
'multiline-ternary': 'off',
'react/prop-types': 'off', // TODO: Enable this
'space-before-function-paren': ['error', 'never'],
'no-mixed-operators': 'off',
eqeqeq: 'off',
'import/no-absolute-path': 'off',
'react/prop-types': 'off' // TODO: Enable this
}
};
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"eslint.format.enable": true
}
6 changes: 4 additions & 2 deletions css/Graph.scss
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ g.node {
fill: var(--bg0);
}

&.collapsed {
opacity: 0.5;
&.collapsed,
&.peer
{
opacity: 0.5
}

&.selected > path {
Expand Down
13 changes: 6 additions & 7 deletions js/App.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import React, { useState, useEffect } from 'react';
import Inspector from './Inspector';
import Graph from './Graph';
import { LoadActivity } from './util';
import Store from './Store';
import React, { useEffect, useState } from 'react';
import { Loader } from './Components';
import Graph from './Graph';
import Inspector from './Inspector';
import sharedStateHook from './sharedStateHook';

import Store from './Store';
import { LoadActivity } from './util';
import '/css/App.scss';

export const usePane = sharedStateHook('info', 'pane');
export const useInspectorOpen = sharedStateHook(true, 'inspectorOpen');
export const useQuery = sharedStateHook(queryFromLocation(), 'query');
export const useModule = sharedStateHook([], 'module');
export const useGraph = sharedStateHook([], 'graph');
export const useGraph = sharedStateHook(null, 'graph');
export const useColorize = sharedStateHook(false, 'colorize');
export const useIncludeDev = sharedStateHook(false, 'includeDev');
export const useExcludes = sharedStateHook([], 'excludes');
Expand Down
45 changes: 28 additions & 17 deletions js/Graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ export function hslFor(perc) {
* @returns {Promise<Map>} Map of key -> {module, level, dependencies}
*/
async function modulesForQuery(query, includeDev, moduleFilter) {
const graph = new Map();
const modules = new Map();

// Upstream dependency types for each module
const referenceTypes = new Map();

function _walk(module, level = 0) {
if (!module) return Promise.resolve(Error('Undefined module'));
Expand All @@ -72,18 +75,24 @@ async function modulesForQuery(query, includeDev, moduleFilter) {
}

// Skip modules we've already seen
if (module && graph.has(module.key)) return Promise.resolve();
if (module && modules.has(module.key)) return Promise.resolve();

// Get dependency [name, version, dependency type] entries
const depEntries = moduleFilter(module) ? getDependencyEntries(module, includeDev, level) : [];

// Create object that captures info about how this module fits in the dependency graph
const info = { module, level };
graph.set(module.key, info);
modules.set(module.key, info);

return Promise.all(
depEntries.map(async([name, version, type]) => {
const module = await store.getModule(name, version);

if (!referenceTypes.has(module.key)) {
referenceTypes.set(module.key, new Set());
}
referenceTypes.get(module.key).add(type);

if (type !== 'peerDependencies') {
await _walk(module, level + 1);
}
Expand All @@ -94,11 +103,11 @@ async function modulesForQuery(query, includeDev, moduleFilter) {
}

// Walk dependencies of each module in the query
return Promise.all(query.map(async(name) => {
return Promise.all(query.map(async name => {
const m = await store.getModule(name);
return m && _walk(m);
}))
.then(() => graph);
.then(() => ({ modules, referenceTypes }));
}

// Compose directed graph document (GraphViz notation)
Expand Down Expand Up @@ -323,11 +332,10 @@ export default function Graph(props) {
const [, setPane] = usePane();
const [, setInspectorOpen] = useInspectorOpen();
const [, setModule] = useModule();
const [, setGraph] = useGraph();
const [graph, setGraph] = useGraph();
const [excludes, setExcludes] = useExcludes();
const [colorize] = useColorize();

const [graphModules, setGraphModules] = useState();
const [zoom, setZoom] = useState(0);

// Signal for when Graph DOM changes
Expand Down Expand Up @@ -395,16 +403,13 @@ export default function Graph(props) {
// Effect: Fetch modules
useEffect(async() => {
const { signal, abort } = createAbortable();

setGraph([]);
setGraph(null);
setModule([]);

const modules = await modulesForQuery(query, includeDev, moduleFilter);
const newGraph = await modulesForQuery(query, includeDev, moduleFilter);
if (signal.aborted) return; // Check after async

setGraphModules(modules);
setGraph(modules);
setPane(modules.size ? 'graph' : 'info');
setGraph(newGraph);

return abort;
}, [query, includeDev, excludes]);
Expand All @@ -420,7 +425,7 @@ export default function Graph(props) {
const wasmBinary = await wasmBinaryPromise; // Avoid race if wasmBinary fetch hasn't completed
if (signal.aborted) return; // Check after all async stuff

const svgMarkup = graphModules?.size ? await graphviz.layout(composeDOT(graphModules), 'svg', 'dot', { wasmBinary }) : '<svg />';
const svgMarkup = graph?.modules.size ? await graphviz.layout(composeDOT(graph.modules), 'svg', 'dot', { wasmBinary }) : '<svg />';
if (signal.aborted) return; // Check after all async stuff

// Parse markup
Expand Down Expand Up @@ -459,6 +464,13 @@ export default function Graph(props) {

const m = store.cachedEntry(key);

const refTypes = graph?.referenceTypes.get(key);

// Style peer dependencies
if (refTypes?.has('peerDependencies') && refTypes.size === 1) {
el.classList.add('peer');
}

if (m?.package?.deprecated) {
el.classList.add('warning');
}
Expand All @@ -485,8 +497,7 @@ export default function Graph(props) {

select('#graph svg .node').node()?.scrollIntoView();

setGraph(graphModules);
setPane(graphModules?.size ? 'graph' : 'info');
setPane(graph?.modules.size ? 'graph' : 'info');

// Signal other hooks that graph DOM has changed
setDomSignal(domSignal + 1);
Expand All @@ -497,7 +508,7 @@ export default function Graph(props) {
finish();
abort();
};
}, [graphModules]);
}, [graph]);

// Effect: Colorize nodes
useEffect(() => {
Expand Down
6 changes: 4 additions & 2 deletions js/GraphPane.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,12 @@ export default function GraphPane({ graph, ...props }) {
const [excludes] = useExcludes();
const [includeDev, setIncludeDev] = useIncludeDev();

if (!graph?.modules) return <div>Loading</div>;

const occurances = {};
const maintainers = {};
let licenses = {};
for (const [, { module: { package: pkg, licenseString: license } }] of graph) {
for (const [, { module: { package: pkg, licenseString: license } }] of graph.modules) {
// Tally module occurances
occurances[pkg.name] = (occurances[pkg.name] || 0) + 1;

Expand Down Expand Up @@ -138,7 +140,7 @@ export default function GraphPane({ graph, ...props }) {
</div> : null
}

<Section title={simplur`${graph.size} Module[|s]`}>
<Section title={simplur`${graph.modules.size} Module[|s]`}>
<Tags>
{
Object.entries(occurances)
Expand Down
4 changes: 2 additions & 2 deletions js/InfoPane.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import { Pane, QueryLink } from './Inspector';
import { store, useQuery } from './App';
import { Pane, QueryLink } from './Inspector';
import '/css/InfoPane.scss';

// Get names of uploaded modules in session storage
Expand All @@ -15,7 +15,7 @@ export default function InfoPane(props) {
const [recents, setRecents] = useState(getFileEntries());

// Handle file selection via input
const onSelect = (ev) => {
const onSelect = ev => {
readFile(ev.target.files.item(0));

// Reset field
Expand Down

0 comments on commit 2cdfdc3

Please sign in to comment.