Skip to content

Commit

Permalink
Updated Matches table layout
Browse files Browse the repository at this point in the history
Signed-off-by: Omkar Phansopkar <omkarphansopkar@gmail.com>
  • Loading branch information
OmkarPh committed Nov 7, 2023
1 parent 5c8794f commit 5c24602
Show file tree
Hide file tree
Showing 15 changed files with 219 additions and 270 deletions.
62 changes: 20 additions & 42 deletions src/components/LicenseEntity/LicenseEntity.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import ReactJson from "@microlink/react-json-view";
import { AgGridReact } from "ag-grid-react";
import React, { useEffect, useState } from "react";
import React from "react";

import {
ActiveLicenseEntity,
Expand All @@ -10,16 +10,10 @@ import {
DEFAULT_FILE_REGION_COL_DEF,
DetectionFileRegionCols,
} from "./FileRegionTableCols";
import {
DEFAULT_MATCHES_COL_DEF,
LicenseDetectionMatchCols,
LicenseClueMatchCols,
MATCH_COLS,
} from "./MatchesTableCols";
import { MatchedTextProvider } from "./MatchedTextContext";
import { useWorkbenchDB } from "../../contexts/dbContext";
import { ScanOptionKeys } from "../../utils/parsers";
import { ColumnApi } from "ag-grid-community";
import LicenseMatchesTable from "./LicenseMatchesTable";
import { LicenseTypes } from "../../services/workbenchDB.types";
import { useWorkbenchDB } from "../../contexts/dbContext";

import "./licenseEntity.css";
import "../../styles/entityCommonStyles.css";
Expand All @@ -30,19 +24,8 @@ interface LicenseDetectionEntityProps {
}
const LicenseEntity = (props: LicenseDetectionEntityProps) => {
const { activeLicenseEntity, activeLicenseTodo } = props;
const { scanInfo } = useWorkbenchDB();
const [matchesTableColumnApi, setMatchesTableColumnApi] =
useState<ColumnApi | null>(null);

useEffect(() => {
if (!scanInfo || !matchesTableColumnApi) return;
matchesTableColumnApi.setColumnVisible(
MATCH_COLS.matched_text.colId,
Boolean(scanInfo.optionsMap.get(ScanOptionKeys.LICENSE_TEXT)) ||
matches[0]?.matched_text?.length > 0 ||
false
);
}, [scanInfo, matchesTableColumnApi]);
const { scanInfo } = useWorkbenchDB();

const license = activeLicenseEntity?.license;
const matches = activeLicenseEntity?.license?.matches;
Expand Down Expand Up @@ -122,26 +105,6 @@ const LicenseEntity = (props: LicenseDetectionEntityProps) => {
</div>
)}
</div>
<br />
<MatchedTextProvider>
<b>Matches</b>
<AgGridReact
rowData={matches}
columnDefs={
activeLicenseEntity.type === "detection"
? LicenseDetectionMatchCols
: LicenseClueMatchCols
}
onGridReady={(params) => setMatchesTableColumnApi(params.columnApi)}
className="ag-theme-alpine ag-grid-customClass entity-table"
ensureDomOrder
enableCellTextSelection
pagination={false}
defaultColDef={DEFAULT_MATCHES_COL_DEF}
/>
</MatchedTextProvider>
<br />
<br />
<b>File regions</b>
<AgGridReact
rowData={file_regions}
Expand All @@ -156,6 +119,21 @@ const LicenseEntity = (props: LicenseDetectionEntityProps) => {
defaultColDef={DEFAULT_FILE_REGION_COL_DEF}
/>
<br />
<b>Matches</b>
<LicenseMatchesTable
matchesInfo={{
licenseType:
activeLicenseEntity.type === "detection"
? LicenseTypes.DETECTION
: LicenseTypes.CLUE,
matches: matches,
}}
showLIcenseText={
Boolean(scanInfo.optionsMap.get(ScanOptionKeys.LICENSE_TEXT)) ||
matches[0]?.matched_text?.length > 0 ||
false
}
/>
<div className="raw-info-section">
Raw license {activeLicenseEntity.type}
<ReactJson
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
import React, { useMemo } from "react";
import CoreLink from "../../CoreLink/CoreLink";
import {
LICENSE_EXPRESSIONS_CONJUNCTIONS,
parseTokensFromExpression,
} from "../../../../services/models/databaseUtils";
import CoreLink from "../../../../components/CoreLink/CoreLink";
} from "../../../services/models/databaseUtils";
import {
LicenseClueMatch,
LicenseDetectionMatch,
} from "../../../services/importedJsonTypes";

const DEBUG_URLS = false;

interface LicenseExpressionRendererProps {
value: string;
spdxLicense?: boolean;
data: {
license_expression: string;
license_expression_spdx: string;
license_expression_keys: {
key: string;
licensedb_url: string;
scancode_url: string;
}[];
license_expression_spdx_keys: {
key: string;
spdx_url: string;
}[];
};
interface MatchLicenseExpressionRendererProps {
matchInfo:
| {
spdxLicense: false;
match: LicenseClueMatch;
}
| {
spdxLicense: true;
match: LicenseDetectionMatch;
};
}

interface ParsedTokens {
Expand All @@ -31,31 +29,26 @@ interface ParsedTokens {
}

const MatchLicenseExpressionRenderer = (
props: LicenseExpressionRendererProps
props: MatchLicenseExpressionRendererProps
) => {
const { spdxLicense, data } = props;
const { matchInfo } = props;

const {
license_expression,
license_expression_spdx,
license_expression_keys,
license_expression_spdx_keys,
} = data;
const { license_expression, license_expression_keys } = matchInfo.match;

const parsedComponents = useMemo<ParsedTokens[]>(() => {
if (!license_expression) return [];

let newParsedComponents: ParsedTokens[];
if (spdxLicense) {
if (matchInfo.spdxLicense) {
const licenseExpressionSpdxKeysMap = new Map(
// Handle deferred state update to ag data grid
(license_expression_spdx_keys || []).map((expKey) => [
(matchInfo.match.license_expression_spdx_keys || []).map((expKey) => [
expKey.key,
expKey,
])
);
newParsedComponents = parseTokensFromExpression(
license_expression_spdx
matchInfo.match.license_expression_spdx
).map((token) => {
const tokenInfo = licenseExpressionSpdxKeysMap.get(token);
if (tokenInfo) {
Expand Down Expand Up @@ -84,7 +77,7 @@ const MatchLicenseExpressionRenderer = (
);
}
return newParsedComponents;
}, [data]);
}, [matchInfo]);

return (
<>
Expand Down
35 changes: 35 additions & 0 deletions src/components/LicenseEntity/LicenseMatchCells/MatchedText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from "react";
import { useMatchedTextContext } from "../MatchedTextContext";
import CoreLink from "../../CoreLink/CoreLink";
import { LicenseMatch } from "../../../services/importedJsonTypes";

interface MatchedTextRendererProps {
value: string;
match: LicenseMatch;
}

const MatchedTextRenderer = (props: MatchedTextRendererProps) => {
const { value, match } = props;
const { openDiffWindow } = useMatchedTextContext();

const trimmedText = value;

return (
<CoreLink
key={value}
onClick={() =>
value &&
openDiffWindow(
value,
match.rule_identifier,
match.start_line,
match.match_coverage
)
}
>
{trimmedText}
</CoreLink>
);
};

export default MatchedTextRenderer;
105 changes: 105 additions & 0 deletions src/components/LicenseEntity/LicenseMatchesTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import React from "react";
import {
LicenseClueMatch,
LicenseDetectionMatch,
} from "../../services/importedJsonTypes";
import { Table } from "react-bootstrap";
import MatchedTextRenderer from "./LicenseMatchCells/MatchedText";
import MatchLicenseExpressionRenderer from "./LicenseMatchCells/MatchLicenseExpression";
import CoreLink from "../CoreLink/CoreLink";
import { LicenseTypes } from "../../services/workbenchDB.types";
import { MatchedTextProvider } from "./MatchedTextContext";

interface LicenseMatchProps {
showLIcenseText?: boolean;
matchesInfo:
| {
licenseType: LicenseTypes.DETECTION;
matches: LicenseDetectionMatch[];
}
| {
licenseType: LicenseTypes.CLUE;
matches: LicenseClueMatch[];
};
}
const LicenseMatchesTable = (props: LicenseMatchProps) => {
const { matchesInfo, showLIcenseText } = props;

return (
<MatchedTextProvider>
<div>
{matchesInfo.matches.map((match) => (
<div className="matches-table-container">
<Table size="sm" bordered>
<tbody>
<tr>
<td>License Expression</td>
<td>
<MatchLicenseExpressionRenderer
matchInfo={{
match: match,
spdxLicense: false,
}}
/>
</td>
</tr>
{showLIcenseText && (
<tr className="matched-text-row">
<td>Matched Text</td>
<td>
<div>
<MatchedTextRenderer
match={match}
value={match.matched_text}
/>
</div>
</td>
</tr>
)}
<tr>
<td>Score</td>
<td>{match.score}</td>
</tr>
<tr>
<td>Matched length</td>
<td>{match.matched_length}</td>
</tr>
<tr>
<td>Match Coverage</td>
<td>{match.match_coverage}</td>
</tr>
<tr>
<td>Matcher</td>
<td>{match.matcher}</td>
</tr>
<tr>
<td>Rule URL</td>
<td>
<CoreLink href={match.rule_url} external>
{match.rule_identifier}
</CoreLink>
</td>
</tr>
{matchesInfo.licenseType === LicenseTypes.DETECTION && (
<tr>
<td>License Expression SPDX</td>
<td>
<MatchLicenseExpressionRenderer
matchInfo={{
match: match,
spdxLicense: true,
}}
/>
</td>
</tr>
)}
</tbody>
</Table>
</div>
))}
</div>
</MatchedTextProvider>
);
};

export default LicenseMatchesTable;
Loading

0 comments on commit 5c24602

Please sign in to comment.