Skip to content

Commit b37a4b3

Browse files
committed
feat: collapse license text by default
- prevent license text from taking up vertical space by introducing toggle button to show/hide it - rename "package" to "component" for OSS naming consistency - make sure icon button keyboard-focus style is separate from click-focus style Signed-off-by: Maxim Stykow <maxim.stykow@tngtech.com>
1 parent 47e0d6d commit b37a4b3

File tree

9 files changed

+108
-58
lines changed

9 files changed

+108
-58
lines changed

src/Frontend/Components/App/App.style.ts

+14
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,20 @@ export const theme = createTheme({
7070
},
7171
},
7272
components: {
73+
MuiInputBase: {
74+
styleOverrides: {
75+
root: {
76+
minHeight: '36px !important',
77+
},
78+
},
79+
},
80+
MuiToggleButton: {
81+
styleOverrides: {
82+
root: {
83+
padding: '5px',
84+
},
85+
},
86+
},
7387
MuiSwitch: {
7488
styleOverrides: {
7589
switchBase: {

src/Frontend/Components/AttributionForm/LicenseSubPanel/LicenseSubPanel.tsx

+67-42
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
// SPDX-FileCopyrightText: TNG Technology Consulting GmbH <https://www.tngtech.com>
33
//
44
// SPDX-License-Identifier: Apache-2.0
5+
import NotesIcon from '@mui/icons-material/Notes';
6+
import { Badge, ToggleButton } from '@mui/material';
57
import MuiBox from '@mui/material/Box';
68
import { sortBy } from 'lodash';
7-
import { useMemo } from 'react';
9+
import { useMemo, useState } from 'react';
810

911
import { PackageInfo } from '../../../../shared/shared-types';
1012
import { text } from '../../../../shared/text';
@@ -46,6 +48,7 @@ export function LicenseSubPanel({
4648
hidden,
4749
config,
4850
}: LicenseSubPanelProps) {
51+
const [showLicenseText, setShowLicenseText] = useState(false);
4952
const dispatch = useAppDispatch();
5053
const frequentLicenseTexts = useAppSelector(getFrequentLicensesTexts);
5154
const frequentLicensesNames = useAppSelector(getFrequentLicensesNameOrder);
@@ -71,47 +74,69 @@ export function LicenseSubPanel({
7174

7275
return hidden ? null : (
7376
<MuiBox>
74-
<PackageAutocomplete
75-
attribute={'licenseName'}
76-
title={text.attributionColumn.licenseName}
77-
packageInfo={packageInfo}
78-
readOnly={!onEdit}
79-
showHighlight={showHighlight}
80-
onEdit={onEdit}
81-
endAdornment={config?.licenseName?.endIcon}
82-
defaults={defaultLicenses}
83-
color={config?.licenseName?.color}
84-
focused={config?.licenseName?.focused}
85-
/>
86-
<TextBox
87-
readOnly={!onEdit}
88-
placeholder={defaultLicenseText}
89-
sx={classes.licenseText}
90-
maxRows={8}
91-
minRows={3}
92-
color={config?.licenseText?.color}
93-
focused={config?.licenseText?.focused}
94-
multiline
95-
expanded={expanded}
96-
title={
97-
defaultLicenseText
98-
? text.attributionColumn.licenseTextDefault
99-
: text.attributionColumn.licenseText
100-
}
101-
text={packageInfo.licenseText}
102-
handleChange={({ target: { value } }) =>
103-
onEdit?.(() =>
104-
dispatch(
105-
setTemporaryDisplayPackageInfo({
106-
...packageInfo,
107-
licenseText: value,
108-
wasPreferred: undefined,
109-
}),
110-
),
111-
)
112-
}
113-
endIcon={config?.licenseText?.endIcon}
114-
/>
77+
<MuiBox display={'flex'} alignItems={'center'} gap={'8px'}>
78+
<PackageAutocomplete
79+
attribute={'licenseName'}
80+
title={text.attributionColumn.licenseName}
81+
packageInfo={packageInfo}
82+
readOnly={!onEdit}
83+
showHighlight={showHighlight}
84+
onEdit={onEdit}
85+
endAdornment={config?.licenseName?.endIcon}
86+
defaults={defaultLicenses}
87+
color={config?.licenseName?.color}
88+
focused={config?.licenseName?.focused}
89+
/>
90+
{!expanded && (
91+
<ToggleButton
92+
value={'license-text'}
93+
selected={showLicenseText}
94+
onChange={() => setShowLicenseText((prev) => !prev)}
95+
size={'small'}
96+
aria-label="license-text-toggle-button"
97+
>
98+
<Badge
99+
anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}
100+
color={'info'}
101+
variant={'dot'}
102+
invisible={!packageInfo.licenseText}
103+
>
104+
<NotesIcon />
105+
</Badge>
106+
</ToggleButton>
107+
)}
108+
</MuiBox>
109+
{(showLicenseText || expanded) && (
110+
<TextBox
111+
readOnly={!onEdit}
112+
placeholder={defaultLicenseText}
113+
sx={classes.licenseText}
114+
maxRows={8}
115+
minRows={3}
116+
color={config?.licenseText?.color}
117+
focused={config?.licenseText?.focused}
118+
multiline
119+
expanded={expanded}
120+
title={
121+
defaultLicenseText
122+
? text.attributionColumn.licenseTextDefault
123+
: text.attributionColumn.licenseText
124+
}
125+
text={packageInfo.licenseText}
126+
handleChange={({ target: { value } }) =>
127+
onEdit?.(() =>
128+
dispatch(
129+
setTemporaryDisplayPackageInfo({
130+
...packageInfo,
131+
licenseText: value,
132+
wasPreferred: undefined,
133+
}),
134+
),
135+
)
136+
}
137+
endIcon={config?.licenseText?.endIcon}
138+
/>
139+
)}
115140
</MuiBox>
116141
);
117142
}

src/Frontend/Components/AttributionForm/__tests__/AttributionForm.test.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ describe('AttributionForm', () => {
200200
expect(screen.queryByLabelText('Url icon')).not.toBeInTheDocument();
201201
});
202202

203-
it('shows default license text placeholder when frequent license name selected and no custom license text entered', () => {
203+
it('shows default license text placeholder when frequent license name selected and no custom license text entered', async () => {
204204
const defaultLicenseText = faker.lorem.paragraphs();
205205
const packageInfo = faker.opossum.packageInfo();
206206
renderComponent(
@@ -215,6 +215,8 @@ describe('AttributionForm', () => {
215215
},
216216
);
217217

218+
await userEvent.click(screen.getByLabelText('license-text-toggle-button'));
219+
218220
expect(
219221
screen.getByRole('textbox', {
220222
name: text.attributionColumn.licenseTextDefault,
@@ -228,7 +230,7 @@ describe('AttributionForm', () => {
228230
).not.toBeInTheDocument();
229231
});
230232

231-
it('does not show default license text placeholder when custom license text entered', () => {
233+
it('does not show default license text placeholder when custom license text entered', async () => {
232234
const defaultLicenseText = faker.lorem.paragraphs();
233235
const packageInfo = faker.opossum.packageInfo({
234236
licenseText: faker.lorem.paragraphs(),
@@ -245,6 +247,8 @@ describe('AttributionForm', () => {
245247
},
246248
);
247249

250+
await userEvent.click(screen.getByLabelText('license-text-toggle-button'));
251+
248252
expect(
249253
screen.getByRole('textbox', {
250254
name: text.attributionColumn.licenseText,

src/Frontend/Components/GoToLinkButton/__tests__/GoToLinkButton.test.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
// SPDX-FileCopyrightText: Nico Carl <nicocarl@protonmail.com>
44
//
55
// SPDX-License-Identifier: Apache-2.0
6-
import { fireEvent, screen } from '@testing-library/react';
7-
import { act } from 'react-dom/test-utils';
6+
import { act, fireEvent, screen } from '@testing-library/react';
87

98
import { BaseUrlsForSources } from '../../../../shared/shared-types';
109
import { setBaseUrlsForSources } from '../../../state/actions/resource-actions/all-views-simple-actions';

src/Frontend/Components/IconButton/IconButton.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export function IconButton(props: IconButtonProps) {
4141
disabled={props.disabled}
4242
data-testid={props['data-testid']}
4343
sx={{
44-
'&:focus': {
44+
'&.Mui-focusVisible': {
4545
background: OpossumColors.middleBlue,
4646
},
4747
}}

src/e2e-tests/__tests__/comparing-attribution-with-origin.test.ts

+3
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ test('reverts all changes and applies reverted state to temporary package info',
9393
await diffPopup.revertAllButton.click();
9494
await diffPopup.applyButton.click();
9595
await diffPopup.assert.isHidden();
96+
await attributionDetails.attributionForm.licenseTextToggleButton.click();
9697
await attributionDetails.attributionForm.assert.matchesPackageInfo(
9798
manualPackageInfo2,
9899
);
@@ -132,6 +133,7 @@ test('reverts single fields correctly', async ({
132133
await diffPopup.revertAllButton.click();
133134
await diffPopup.applyButton.click();
134135
await diffPopup.assert.isHidden();
136+
await attributionDetails.attributionForm.licenseTextToggleButton.click();
135137
await attributionDetails.attributionForm.assert.matchesPackageInfo(
136138
manualPackageInfo2,
137139
);
@@ -170,6 +172,7 @@ test('handles pending license and copyright changes in temporary package info co
170172
await attributionDetails.attributionForm.selectAttributionType(
171173
AttributionType.ThirdParty,
172174
);
175+
await attributionDetails.attributionForm.licenseTextToggleButton.click();
173176
await attributionDetails.attributionForm.assert.matchesPackageInfo(
174177
manualPackageInfo2,
175178
);

src/e2e-tests/__tests__/updating-attributions.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ test('allows user to update an attribution on the selected resource only', async
133133
await attributionDetails.assert.saveButtonIsDisabled();
134134
await attributionDetails.assert.revertButtonIsDisabled();
135135

136+
await attributionDetails.attributionForm.licenseTextToggleButton.click();
136137
await attributionDetails.attributionForm.licenseText.fill(
137138
newPackageInfo.licenseText!,
138139
);

src/e2e-tests/page-objects/AttributionForm.ts

+4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export class AttributionForm {
2121
readonly copyright: Locator;
2222
readonly licenseName: Locator;
2323
readonly licenseText: Locator;
24+
readonly licenseTextToggleButton: Locator;
2425
readonly attributionType: Locator;
2526
readonly addAuditingOptionButton: Locator;
2627
readonly auditingOptionsMenu: {
@@ -81,6 +82,9 @@ export class AttributionForm {
8182
exact: true,
8283
},
8384
);
85+
this.licenseTextToggleButton = this.node.getByLabel(
86+
'license-text-toggle-button',
87+
);
8488
this.licenseText = this.node.getByLabel(
8589
text.attributionColumn.licenseText,
8690
{ exact: true },

src/shared/text.ts

+11-11
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ export const text = {
1212
copyToClipboard: 'Copy to clipboard',
1313
copyToClipboardSuccess: 'Copied to clipboard',
1414
currentLicenseInformation: 'Current License Information',
15-
currentPackageCoordinates: 'Current Package Coordinates',
15+
currentPackageCoordinates: 'Current Component Coordinates',
1616
delete: 'Delete',
1717
description: 'Description',
18-
enrichFailure: 'No package found with these coordinates',
18+
enrichFailure: 'No component found with these coordinates',
1919
enrichNoop: 'No more information found',
2020
enrichSuccess: 'Added information where possible',
2121
fromAttributions: 'From Attributions',
@@ -30,23 +30,23 @@ export const text = {
3030
link: 'Link as attribution on selected resource',
3131
noLinkToOpen: 'No link to open. Please enter a URL.',
3232
occurrence: 'occurrence',
33-
openLinkInBrowser: 'Open repository URL in browser',
33+
openLinkInBrowser: 'Open component URL in browser',
3434
openSourceInsights: 'Open Source Insights',
3535
origin: 'Origin',
3636
originalLicenseInformation: 'Original License Information',
37-
originalPackageCoordinates: 'Original Package Coordinates',
37+
originalPackageCoordinates: 'Original Component Coordinates',
3838
originallyFrom: 'Originally from ',
39-
packageCoordinates: 'Package Coordinates',
40-
packageName: 'Package Name',
41-
packageNamespace: 'Package Namespace',
42-
packageType: 'Package Type',
43-
packageVersion: 'Package Version',
39+
packageCoordinates: 'Component Coordinates',
40+
packageName: 'Component Name',
41+
packageNamespace: 'Component Namespace',
42+
packageType: 'Component Type',
43+
packageVersion: 'Component Version',
4444
pasteFromClipboard: 'Paste from clipboard',
4545
pasteFromClipboardFailed: 'Clipboard does not contain a valid PURL',
4646
pasteFromClipboardSuccess: 'Pasted from clipboard',
4747
purl: 'PURL',
4848
replace: 'Use as replacement',
49-
repositoryUrl: 'Repository URL',
49+
repositoryUrl: 'Component URL',
5050
restore: 'Restore',
5151
revert: 'Revert',
5252
save: 'Save',
@@ -197,7 +197,7 @@ export const text = {
197197
excludedFromNotice: 'Excluded from Notice',
198198
firstParty: 'First Party',
199199
highConfidence: 'High Confidence',
200-
incompleteCoordinates: 'Incomplete Package Coordinates',
200+
incompleteCoordinates: 'Incomplete Component Coordinates',
201201
incompleteLegal: 'Incomplete Legal Information',
202202
lowConfidence: 'Low Confidence',
203203
modifiedPreferred: 'Modified Previously Preferred',

0 commit comments

Comments
 (0)