Skip to content

Commit aa2dcd1

Browse files
committed
feat: opossumui-2.0
- change default font - improve color scheme and add background wave - merge audit and attribution view to reduce duplication and context switching - group packages by either being an attribution or signal - replace resource popup with new panel to display linked resources - replace file search popup with in-component search fields - introduce bulk actions for signals - add filtering for signals - add filter by license name - add filter for different kinds of incompleteness - highlight incomplete attributions and the missing attributes at all times - improve feature to replace attributions by letting the user select the replacement directly in audit view - improved report view (sticky first column, better display of information, improved scrolling behavior) - generate autocomplete suggestions from filtered signals and attributions and deduplicate attribute values - update user guide to reflect changes closes #2524 Signed-off-by: Maxim Stykow <maxim.stykow@tngtech.com>
1 parent 8c3f899 commit aa2dcd1

File tree

367 files changed

+8863
-19928
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

367 files changed

+8863
-19928
lines changed

USER_GUIDE.md

+113-220
Large diffs are not rendered by default.
-123 KB
Binary file not shown.
-179 KB
Loading
-273 KB
Binary file not shown.
-81.1 KB
Binary file not shown.
-16.4 KB
Binary file not shown.
Binary file not shown.
-4.8 KB
Binary file not shown.
236 KB
Loading
-631 KB
Binary file not shown.
Binary file not shown.
9.32 KB
Loading

package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
"dependencies": {
99
"@emotion/react": "^11.11.3",
1010
"@emotion/styled": "^11.11.0",
11+
"@fontsource-variable/karla": "^5.0.19",
1112
"@mui/icons-material": "^5.15.10",
1213
"@mui/material": "^5.15.10",
1314
"@mui/system": "^5.15.9",
1415
"@reduxjs/toolkit": "^2.2.1",
1516
"@tanstack/react-query": "^5.21.7",
1617
"compare-versions": "^6.1.0",
1718
"dayjs": "^1.11.10",
18-
"electron-devtools-installer": "^3.2.0",
1919
"electron-log": "^5.1.1",
2020
"electron-settings": "^4.0.2",
2121
"fast-csv": "^5.0.1",
@@ -56,7 +56,6 @@
5656
"@testing-library/user-event": "^14.5.2",
5757
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
5858
"@types/babel__core": "^7.20.5",
59-
"@types/electron-devtools-installer": "^2.2.5",
6059
"@types/jest": "^29.5.12",
6160
"@types/js-yaml": "^4.0.9",
6261
"@types/lodash": "^4.14.202",

public/icons/wave.svg

+9
Loading

renovate.json5

+7-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
'dayjs',
3030
'dotenv',
3131
'electron',
32-
'electron-devtools-installer',
3332
'electron-log',
3433
'electron-playwright-helpers',
3534
'electron-settings',
@@ -98,6 +97,13 @@
9897
matchUpdateTypes: ['minor', 'patch'],
9998
automerge: true,
10099
},
100+
{
101+
matchPackagePrefixes: ['@fontsource-variable/'],
102+
groupName: 'fontsource dependencies',
103+
groupSlug: 'fontsource',
104+
matchUpdateTypes: ['minor', 'patch'],
105+
automerge: true,
106+
},
101107
{
102108
matchPackagePrefixes: ['@tanstack/'],
103109
groupName: 'Tanstack dependencies',

src/ElectronBackend/app.ts

-14
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
//
44
// SPDX-License-Identifier: Apache-2.0
55
import { app } from 'electron';
6-
import installExtension, {
7-
REACT_DEVELOPER_TOOLS,
8-
REDUX_DEVTOOLS,
9-
} from 'electron-devtools-installer';
106

117
import { main } from './main/main';
128

@@ -15,13 +11,3 @@ app.on('ready', main);
1511
app.on('window-all-closed', () => {
1612
app.quit();
1713
});
18-
19-
app.on('ready', () => {
20-
if (!app.isPackaged) {
21-
[REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS].forEach((extension) => {
22-
installExtension(extension)
23-
.then((name) => console.log(`Added Extension: ${name}`))
24-
.catch((err) => console.log('An error occurred: ', err));
25-
});
26-
}
27-
});

src/ElectronBackend/input/__tests__/parseFile.test.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,9 @@ const correctOutput: OpossumOutputFile = {
124124
resolvedExternalAttributions: [],
125125
};
126126

127-
const correctParsedOuput: ParsedOpossumOutputFile = {
127+
const correctParsedOutput: ParsedOpossumOutputFile = {
128128
...correctOutput,
129-
resolvedExternalAttributions: new Set(),
129+
resolvedExternalAttributions: [],
130130
};
131131

132132
describe('parseOpossumFile', () => {
@@ -154,7 +154,7 @@ describe('parseOpossumFile', () => {
154154
opossumFilePath,
155155
)) as ParsedOpossumInputAndOutput;
156156
expect(parsingResult.input).toStrictEqual(correctInput);
157-
expect(parsingResult.output).toStrictEqual(correctParsedOuput);
157+
expect(parsingResult.output).toStrictEqual(correctParsedOutput);
158158
});
159159

160160
it('returns JSONParsingError on an incorrect .opossum file', async () => {
@@ -248,7 +248,7 @@ describe('parseOutputJsonFile', () => {
248248

249249
const attributions = parseOutputJsonFile(attributionPath);
250250

251-
expect(attributions).toStrictEqual(correctParsedOuput);
251+
expect(attributions).toStrictEqual(correctParsedOutput);
252252
});
253253

254254
it('throws when reading an incorrect file', async () => {
@@ -272,7 +272,7 @@ describe('parseOutputJsonFile', () => {
272272
'cff9095a-5c24-46e6-b84d-cc8596b17c58',
273273
);
274274
const parsedFileContentWithWrongProjectId: ParsedOpossumOutputFile = set(
275-
cloneDeep(correctParsedOuput),
275+
cloneDeep(correctParsedOutput),
276276
'metadata.projectId',
277277
'cff9095a-5c24-46e6-b84d-cc8596b17c58',
278278
);

src/ElectronBackend/input/importFromFile.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,11 @@ export async function loadInputAndOutputFromFilePath(
177177
attributionsToResources: externalAttributionsToResources,
178178
},
179179
frequentLicenses,
180-
resolvedExternalAttributions: parsedOutputData.resolvedExternalAttributions,
181-
attributionBreakpoints: new Set(
182-
parsedInputData.attributionBreakpoints ?? [],
180+
resolvedExternalAttributions: new Set(
181+
parsedOutputData.resolvedExternalAttributions,
183182
),
184-
filesWithChildren: new Set(parsedInputData.filesWithChildren ?? []),
183+
attributionBreakpoints: new Set(parsedInputData.attributionBreakpoints),
184+
filesWithChildren: new Set(parsedInputData.filesWithChildren),
185185
baseUrlsForSources: sanitizeRawBaseUrlsForSources(
186186
parsedInputData.baseUrlsForSources,
187187
),

src/ElectronBackend/input/parseFile.ts

+38-55
Original file line numberDiff line numberDiff line change
@@ -31,52 +31,52 @@ export async function parseOpossumFile(
3131
): Promise<
3232
ParsedOpossumInputAndOutput | JsonParsingError | InvalidDotOpossumFileError
3333
> {
34-
let parsedInputData: unknown;
35-
let parsedOutputData: unknown = null;
36-
let jsonParsingError: JsonParsingError | null = null;
37-
let invalidDotOpossumFileError: InvalidDotOpossumFileError | null = null;
34+
let parsedInputData: ParsedOpossumInputFile;
35+
let parsedOutputData: ParsedOpossumOutputFile | null = null;
3836

3937
const zip: fflate.Unzipped = await readZipAsync(opossumFilePath);
38+
4039
if (!zip[INPUT_FILE_NAME]) {
41-
invalidDotOpossumFileError = {
40+
return {
4241
filesInArchive: Object.keys(zip)
4342
.map((fileName) => `'${fileName}'`)
4443
.join(', '),
4544
type: 'invalidDotOpossumFileError',
46-
};
47-
} else {
48-
getGlobalBackendState().inputFileRaw = zip[INPUT_FILE_NAME];
49-
const inputJson = fflate.strFromU8(zip[INPUT_FILE_NAME]);
45+
} satisfies InvalidDotOpossumFileError;
46+
}
47+
48+
getGlobalBackendState().inputFileRaw = zip[INPUT_FILE_NAME];
49+
50+
try {
51+
parsedInputData = JSON.parse(fflate.strFromU8(zip[INPUT_FILE_NAME]));
52+
jsonSchemaValidator.validate(
53+
parsedInputData,
54+
OpossumInputFileSchema,
55+
validationOptions,
56+
);
57+
} catch (err) {
58+
return {
59+
message: `Error: ${opossumFilePath} does not contain a valid input file.\n Original error message: ${err?.toString()}`,
60+
type: 'jsonParsingError',
61+
} satisfies JsonParsingError;
62+
}
63+
64+
if (zip[OUTPUT_FILE_NAME]) {
5065
try {
51-
parsedInputData = parseAndValidateJson(inputJson, OpossumInputFileSchema);
66+
const outputJson = fflate.strFromU8(zip[OUTPUT_FILE_NAME]);
67+
parsedOutputData = parseOutputJsonContent(outputJson, opossumFilePath);
5268
} catch (err) {
53-
jsonParsingError = {
54-
message: `Error: ${opossumFilePath} does not contain a valid input file.\n Original error message: ${err?.toString()}`,
69+
return {
70+
message: `Error: ${opossumFilePath} does not contain a valid output file.\n${err?.toString()}`,
5571
type: 'jsonParsingError',
56-
};
57-
}
58-
59-
if (zip[OUTPUT_FILE_NAME]) {
60-
try {
61-
const outputJson = fflate.strFromU8(zip[OUTPUT_FILE_NAME]);
62-
parsedOutputData = parseOutputJsonContent(outputJson, opossumFilePath);
63-
} catch (err) {
64-
jsonParsingError = {
65-
message: `Error: ${opossumFilePath} does not contain a valid output file.\n${err?.toString()}`,
66-
type: 'jsonParsingError',
67-
};
68-
}
72+
} satisfies JsonParsingError;
6973
}
7074
}
7175

72-
return jsonParsingError
73-
? jsonParsingError
74-
: invalidDotOpossumFileError
75-
? invalidDotOpossumFileError
76-
: {
77-
input: parsedInputData as ParsedOpossumInputFile,
78-
output: parsedOutputData as ParsedOpossumOutputFile,
79-
};
76+
return {
77+
input: parsedInputData,
78+
output: parsedOutputData,
79+
};
8080
}
8181

8282
async function readZipAsync(opossumFilePath: string): Promise<fflate.Unzipped> {
@@ -160,34 +160,17 @@ export function parseOutputJsonContent(
160160
fileContent: string,
161161
filePath: fs.PathLike,
162162
): ParsedOpossumOutputFile {
163-
let outputJsonContent;
164163
try {
165-
outputJsonContent = parseAndValidateJson(
166-
fileContent,
164+
const jsonContent = JSON.parse(fileContent);
165+
jsonSchemaValidator.validate(
166+
jsonContent,
167167
OpossumOutputFileSchema,
168+
validationOptions,
168169
);
170+
return jsonContent;
169171
} catch (err) {
170172
throw new Error(
171173
`Error: ${filePath.toString()} contains an invalid output file.\n Original error message: ${err?.toString()}`,
172174
);
173175
}
174-
175-
const resolvedExternalAttributions = (
176-
outputJsonContent as Record<string, unknown>
177-
).resolvedExternalAttributions;
178-
return {
179-
...(outputJsonContent as Record<string, unknown>),
180-
resolvedExternalAttributions: resolvedExternalAttributions
181-
? new Set(resolvedExternalAttributions as Array<string>)
182-
: new Set(),
183-
} as ParsedOpossumOutputFile;
184-
}
185-
186-
function parseAndValidateJson(
187-
content: string,
188-
schema: typeof OpossumInputFileSchema | typeof OpossumOutputFileSchema,
189-
): unknown {
190-
const jsonContent = JSON.parse(content);
191-
jsonSchemaValidator.validate(jsonContent, schema, validationOptions);
192-
return jsonContent;
193176
}

src/ElectronBackend/input/parseInputData.ts

+1
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ export function serializeAttributions(
223223
count,
224224
followUp,
225225
id,
226+
relation,
226227
resources,
227228
source,
228229
suffix,

src/ElectronBackend/main/menu.ts

+1-32
Original file line numberDiff line numberDiff line change
@@ -258,37 +258,6 @@ export async function createMenu(mainWindow: BrowserWindow): Promise<Menu> {
258258
accelerator: 'CmdOrCtrl+A',
259259
role: 'selectAll',
260260
},
261-
{ type: 'separator' },
262-
{
263-
icon: getIconBasedOnTheme(
264-
'icons/search-white.png',
265-
'icons/search-black.png',
266-
),
267-
label: 'Search for Files and Directories',
268-
accelerator: 'CmdOrCtrl+F',
269-
click(): void {
270-
if (isFileLoaded(getGlobalBackendState())) {
271-
webContents.send(AllowedFrontendChannels.ShowSearchPopup, {
272-
showSearchPopup: true,
273-
});
274-
}
275-
},
276-
},
277-
{
278-
icon: getIconBasedOnTheme(
279-
'icons/location-searching-white.png',
280-
'icons/location-searching-black.png',
281-
),
282-
label: 'Locate Signals',
283-
accelerator: 'CmdOrCtrl+L',
284-
click(): void {
285-
if (isFileLoaded(getGlobalBackendState())) {
286-
webContents.send(AllowedFrontendChannels.ShowLocatorPopup, {
287-
showSearchPopup: true,
288-
});
289-
}
290-
},
291-
},
292261
],
293262
},
294263
{
@@ -356,7 +325,7 @@ export async function createMenu(mainWindow: BrowserWindow): Promise<Menu> {
356325
);
357326
void UserSettings.set('qaMode', false);
358327
},
359-
visible: qaMode,
328+
visible: !!qaMode,
360329
},
361330
],
362331
},

src/ElectronBackend/main/user-settings.ts

+2-14
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,14 @@
44
// SPDX-License-Identifier: Apache-2.0
55
import { BrowserWindow } from 'electron';
66
import settings from 'electron-settings';
7-
import { isEqual } from 'lodash';
87

98
import { AllowedFrontendChannels } from '../../shared/ipc-channels';
109
import { UserSettings as IUserSettings } from '../../shared/shared-types';
1110

1211
export class UserSettings {
1312
public static async init() {
14-
const current: Partial<IUserSettings> = await settings.get();
15-
const reset = process.argv.includes('--reset');
16-
17-
const updated = {
18-
...current,
19-
showProjectStatistics: reset
20-
? false
21-
: current.showProjectStatistics ?? true,
22-
qaMode: reset ? false : current.qaMode ?? false,
23-
} satisfies IUserSettings;
24-
25-
if (!isEqual(current, updated)) {
26-
await settings.set(updated);
13+
if (process.argv.includes('--reset')) {
14+
await settings.set({});
2715
}
2816
}
2917

src/ElectronBackend/types/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export interface ParsedOpossumOutputFile {
6262
};
6363
manualAttributions: RawAttributions;
6464
resourcesToAttributions: ResourcesToAttributions;
65-
resolvedExternalAttributions: Set<string>;
65+
resolvedExternalAttributions: Array<string> | undefined;
6666
}
6767

6868
export interface ParsedOpossumInputAndOutput {

0 commit comments

Comments
 (0)