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

Will/lockfile explorer step3 #3741

Merged
merged 24 commits into from
Nov 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e5aec72
feat: persist bookmarks
william2958 Nov 9, 2022
49c1460
feat: improve user experience when dealing with peer dependencies
william2958 Nov 9, 2022
aa9cc90
feat: better css for layout
william2958 Nov 9, 2022
f2890d4
feat: add forward jumping
william2958 Nov 10, 2022
a8de0c0
feat: add dependency view panel
william2958 Nov 10, 2022
1c75df0
feat: add workspace slice
william2958 Nov 10, 2022
e70a266
chore: ms copyright
william2958 Nov 10, 2022
5fd0ca7
feat: UI improvements
william2958 Nov 10, 2022
800fe22
feat: finish UI
william2958 Nov 10, 2022
cfb6828
chore: eslint errors
william2958 Nov 11, 2022
65b9b87
chore: add changefile
william2958 Nov 11, 2022
5f93586
fix: websocket port
william2958 Nov 14, 2022
b221260
feat: fix some PR comments
william2958 Nov 17, 2022
90a88d2
feat: display modified package spec in tab header
william2958 Nov 17, 2022
b8aa434
feat: split filter into seperate values depending on tab
william2958 Nov 17, 2022
c993bf9
feat: move add bookmark button to top
william2958 Nov 17, 2022
18e4c37
chore: eslint errors
william2958 Nov 17, 2022
dd84f0f
feat: better ux
william2958 Nov 17, 2022
42145f7
chore: eslint
william2958 Nov 17, 2022
27ceaa6
feat: add better instructions to package json viewer
william2958 Nov 17, 2022
7dcdc64
chore: eslint
william2958 Nov 17, 2022
898082c
fix: ui buttons missing
william2958 Nov 17, 2022
6f4a8c7
chore: stop scrolling when entry is selected
william2958 Nov 17, 2022
053dfac
chore: tweak padding on bookmarks
william2958 Nov 17, 2022
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
12 changes: 7 additions & 5 deletions apps/lockfile-explorer-web/src/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
box-shadow: $ms-depth-shadow-8;
background-color: $ms-color-gray10;
padding: 24px;
width: calc(100% - 48px);
}

.ContainerCard {
Expand All @@ -15,15 +14,18 @@
display: flex;
flex-direction: row;
flex-wrap: nowrap;
padding: 24px;
& > * {
width: 100%;
}
}

.AppGrid {
flex-grow: 1;
}

.BodyContainer {
& > * + * {
margin-top: 24px;
}
height: 100vh;
display: flex;
flex-direction: column;
overflow-y: scroll;
}
28 changes: 13 additions & 15 deletions apps/lockfile-explorer-web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,22 @@ export const App = (): JSX.Element => {

return (
<div className={styles.AppContainer}>
<div className={styles.AppGrid}>
<div className="ms-Grid" dir="ltr">
<div className="ms-Grid-row">
<div className="ms-Grid-col ms-sm3">
<LockfileViewer />
</div>
<div className={`ms-Grid-col ms-sm7 ${styles.BodyContainer}`}>
<SelectedEntryPreview />
<PackageJsonViewer />
<LockfileEntryDetailsView />
</div>
<div className="ms-Grid-col ms-sm2">
<BookmarksSidebar />
</div>
<div className="ms-Grid" dir="ltr">
<div className="ms-Grid-row">
<div className={`ms-Grid-col ms-sm3 ${styles.BodyContainer}`}>
<LockfileViewer />
</div>
<div className={`ms-Grid-col ms-sm7 ${styles.BodyContainer}`}>
<SelectedEntryPreview />
<PackageJsonViewer />
<LockfileEntryDetailsView />
</div>
<div className={`ms-Grid-col ms-sm2 ${styles.BodyContainer}`}>
<LogoPanel />
<BookmarksSidebar />
</div>
</div>
</div>
<LogoPanel />
</div>
);
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
.BookmarksWrapper {
height: calc(100vh - 96px);
flex: 1;
margin: 12px 0;
}

.BookmarkEntry {
padding: 4px 8px;
padding: 4px 0;
margin-top: 8px;
cursor: pointer;
&:hover {
background: #dff6dd;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,21 @@ import { pushToStack, selectCurrentEntry } from '../../store/slices/entrySlice';
import { ReactNull } from '../../types/ReactNull';
import { LockfileEntry } from '../../parsing/LockfileEntry';
import { logDiagnosticInfo } from '../../helpers/logDiagnosticInfo';
import { displaySpecChanges } from '../../helpers/displaySpecChanges';

enum InfluencerTypes {
enum DependencyType {
Determinant,
TransitiveReferrer
}

interface IInfluencerType {
entry: LockfileEntry;
type: InfluencerTypes;
type: DependencyType;
}

export const LockfileEntryDetailsView = (): JSX.Element | ReactNull => {
const selectedEntry = useAppSelector(selectCurrentEntry);
const specChanges = useAppSelector((state) => state.workspace.specChanges);
const dispatch = useAppDispatch();

const [inspectDependency, setInspectDependency] = useState<LockfileDependency | null>(null);
Expand All @@ -36,14 +38,22 @@ export const LockfileEntryDetailsView = (): JSX.Element | ReactNull => {

const selectResolvedEntry = useCallback(
(dependencyToTrace) => () => {
if (inspectDependency && inspectDependency.name === dependencyToTrace.name) {
if (inspectDependency && inspectDependency.entryId === dependencyToTrace.entryId) {
if (dependencyToTrace.resolvedEntry) {
dispatch(pushToStack(dependencyToTrace.resolvedEntry));
} else {
logDiagnosticInfo('No resolved entry for dependency:', dependencyToTrace);
}
} else if (selectedEntry) {
console.log('dependency to trace: ', dependencyToTrace);
setInspectDependency(dependencyToTrace);

// Check if we need to calculate influencers.
// If the current dependencyToTrace is a peer dependency then we do
if (dependencyToTrace.dependencyType !== IDependencyType.PEER_DEPENDENCY) {
william2958 marked this conversation as resolved.
Show resolved Hide resolved
return;
}

// calculate influencers
const stack = [selectedEntry];
const determinants = new Set<LockfileEntry>();
Expand Down Expand Up @@ -74,7 +84,9 @@ export const LockfileEntryDetailsView = (): JSX.Element | ReactNull => {
// field.
console.error(
'Error analyzing influencers: A referrer appears to be missing its "transitivePeerDependencies" field in the YAML file: ',
referrer
dependencyToTrace,
referrer,
currEntry
);
}
for (const referrer of currEntry.referrers) {
Expand All @@ -91,13 +103,13 @@ export const LockfileEntryDetailsView = (): JSX.Element | ReactNull => {
for (const determinant of determinants.values()) {
influencers.push({
entry: determinant,
type: InfluencerTypes.Determinant
type: DependencyType.Determinant
});
}
for (const referrer of transitiveReferrers.values()) {
influencers.push({
entry: referrer,
type: InfluencerTypes.TransitiveReferrer
type: DependencyType.TransitiveReferrer
});
}
setInfluencers(influencers);
Expand All @@ -108,52 +120,99 @@ export const LockfileEntryDetailsView = (): JSX.Element | ReactNull => {

const selectResolvedReferencer = useCallback(
(referrer) => () => {
console.log('going to entry: ', referrer);
dispatch(pushToStack(referrer));
},
[selectedEntry]
);

const renderDependencyMetadata = (): JSX.Element | ReactNull => {
if (!inspectDependency) {
return ReactNull;
}
return (
<div className={`${appStyles.ContainerCard} ${styles.DependencyDetails}`}>
<div className={styles.DependencyDetailInfo}>
<h5>Selected&nbsp;Dependency: </h5>
<span>
{inspectDependency.name}: {inspectDependency.version}
</span>
</div>
<div className={styles.DependencyDetailInfo}>
<h5>package.json spec: </h5>
<span>
{inspectDependency.dependencyType === IDependencyType.PEER_DEPENDENCY
? `"${inspectDependency.peerDependencyMeta.version}" ${
inspectDependency.peerDependencyMeta.optional ? 'Optional' : 'Required'
} Peer`
: inspectDependency.version}
</span>
</div>
<div className={styles.DependencyDetailInfo}>
<h5>.pnpmfile.cjs: </h5>
<span>
{specChanges.has(inspectDependency.name)
? displaySpecChanges(specChanges, inspectDependency.name)
: 'No Effect'}
</span>
</div>
</div>
);
};

const renderPeerDependencies = (): JSX.Element | ReactNull => {
if (!selectedEntry) return ReactNull;
const peerDeps = selectedEntry.dependencies.filter(
(d) => d.dependencyType === IDependencyType.PEER_DEPENDENCY
);
if (!peerDeps.length) {
return (
<div className={appStyles.ContainerCard}>
<div className={`${appStyles.ContainerCard} ${styles.InfluencerList}`}>
<h5>No peer dependencies.</h5>
</div>
);
}
if (!inspectDependency || inspectDependency.dependencyType !== IDependencyType.PEER_DEPENDENCY) {
return (
<div>
<div className={`${appStyles.ContainerCard} ${styles.InfluencerList}`}>
<h5>Select a peer dependency to view its influencers</h5>
</div>
);
}

return (
<div className={appStyles.ContainerCard}>
<h5>Influencers:</h5>
<div className={`${appStyles.ContainerCard} ${styles.InfluencerList}`}>
<h5>Determinants:</h5>
{influencers
.filter((inf) => inf.type === InfluencerTypes.Determinant)
.filter((inf) => inf.type === DependencyType.Determinant)
.map(({ entry }) => (
<div key={entry.rawEntryId}>{entry.displayText}</div>
<a
className={styles.InfluencerEntry}
key={entry.rawEntryId}
onClick={selectResolvedReferencer(entry)}
>
{entry.displayText}
</a>
))}
<h5>Transitive Referencers:</h5>
{influencers
.filter((inf) => inf.type === InfluencerTypes.TransitiveReferrer)
.filter((inf) => inf.type === DependencyType.TransitiveReferrer)
.map(({ entry }) => (
<div key={entry.rawEntryId}>{entry.displayText}</div>
<a
className={styles.InfluencerEntry}
key={entry.rawEntryId}
onClick={selectResolvedReferencer(entry)}
>
{entry.displayText}
</a>
))}
</div>
);
};

if (!selectedEntry) {
return (
<div className={appStyles.ContainerCard}>
<div className={`${appStyles.ContainerCard} ${styles.InfluencerList}`}>
<h5>Select an entry to view its details</h5>
</div>
);
Expand Down Expand Up @@ -185,7 +244,7 @@ export const LockfileEntryDetailsView = (): JSX.Element | ReactNull => {
{selectedEntry.dependencies?.map((dependency: LockfileDependency) => (
<div
className={`${styles.DependencyItem} ${
inspectDependency?.name === dependency.name && styles.SelectedDependencyItem
inspectDependency?.entryId === dependency.entryId && styles.SelectedDependencyItem
}`}
key={dependency.entryId || dependency.name}
onClick={selectResolvedEntry(dependency)}
Expand All @@ -207,6 +266,7 @@ export const LockfileEntryDetailsView = (): JSX.Element | ReactNull => {
</div>
</div>
</div>
{renderDependencyMetadata()}
{renderPeerDependencies()}
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
.LockfileEntryListView {
display: flex;
justify-content: space-between;
height: 30%;
padding-top: 12px;
& > * {
width: calc(50% - 48px - 12px);
}
Expand Down Expand Up @@ -35,3 +37,33 @@
.SelectedDependencyItem {
background-color: #dff6dd;
}

.InfluencerList {
margin-top: 12px;
height: 10%;
overflow: scroll;
}

.DependencyDetails {
margin-top: 12px;
height: 4%;
overflow: scroll;
}

.InfluencerEntry {
display: block;
cursor: pointer;
&:hover {
color: #107c10;
text-decoration: underline;
}
}

.DependencyDetailInfo {
display: flex;
align-items: center;
span {
font-size: 12px;
margin-left: 4px;
}
}
Loading