Skip to content

Commit

Permalink
Merge pull request #2480 from opossum-tool/feat-move-multi-select-act…
Browse files Browse the repository at this point in the history
…ions

feat: move multi-select actions out of context menu
  • Loading branch information
mstykow authored Jan 11, 2024
2 parents e36d5d8 + 7280504 commit a33317b
Show file tree
Hide file tree
Showing 76 changed files with 2,448 additions and 3,035 deletions.
6 changes: 1 addition & 5 deletions USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,6 @@ The `Attribution Details Column`, if editable, shows the following buttons:
- _Delete_, deletes the attribution of the selected resource only.
- _Delete Globally_, (shown only if the attribution of the selected resource is also linked to other resources)
deletes the attribution for all the linked resources.
- _Mark for replacement_, allows to mark an attribution for replacement. After marking an attribution.
One can navigate to another attribution and press the _Replace marked_ button. This opens a popup. In the popup,
clicking the _Replace_ button removes the marked attribution and replaces it by the currently selected one.

The _SAVE_ / _SAVE GLOBALLY_ and _Revert_ buttons are disabled if no change has been made.

Expand All @@ -301,8 +298,7 @@ the respective attribution.
The `Attribution Details Column`, when a signal is selected, shows the _HIDE_ button. It can be used to hide the given
signal in the App for the current input/output files, and it will not have any consequence in the DB. When clicking _HIDE_ for a merged signal, all individual signals that make up the merged signal are hidden.

Instead of the buttons, the context menu can be used to execute all available actions out of _Delete_,
_Delete Globally_, _Confirm_, _Confirm Globally_, _Mark for replacement_, _Hide_ and _Show Resources_. To open the
Instead of the buttons, the context menu can be used to execute all available actions out of _Delete_, _Confirm_, _Hide_ and _Show Resources_. To open the
context menu, right-click a signal or an attribution, e.g. in the `Attributions Sub-Panel`, `Signals Sub-Panel` or
`Attribution List`.

Expand Down
Binary file modified docs/user_guide_screenshots/attribution_view.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/user_guide_screenshots/report_view.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// SPDX-FileCopyrightText: TNG Technology Consulting GmbH <https://www.tngtech.com>
//
// SPDX-License-Identifier: Apache-2.0
import { ReactElement } from 'react';

import {
Attributions,
AttributionsToHashes,
Expand All @@ -23,10 +21,8 @@ interface SyncAccordionPanelProps {
['aria-label']?: string;
}

export function SyncAccordionPanel(
props: SyncAccordionPanelProps,
): ReactElement {
const [activeSorting] = useActiveSortingInAuditView();
export function SyncAccordionPanel(props: SyncAccordionPanelProps) {
const { activeSorting } = useActiveSortingInAuditView();

const [sortedPackageCardIds, displayPackageInfosWithCount] =
getExternalDisplayPackageInfosWithCount(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function AllAttributionsPanel(
props: AllAttributionsPanelProps,
): ReactElement {
const dispatch = useAppDispatch();
const [activeSorting] = useActiveSortingInAuditView();
const { activeSorting } = useActiveSortingInAuditView();

function getPackageCard(packageCardId: string): ReactElement | null {
const displayPackageInfo = props.displayPackageInfos[packageCardId];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,9 @@
// SPDX-License-Identifier: Apache-2.0
import { screen } from '@testing-library/react';

import {
Attributions,
Resources,
ResourcesToAttributions,
} from '../../../../shared/shared-types';
import { ButtonText } from '../../../enums/enums';
import { Attributions } from '../../../../shared/shared-types';
import { setSelectedResourceId } from '../../../state/actions/resource-actions/audit-view-simple-actions';
import { loadFromFile } from '../../../state/actions/resource-actions/load-actions';
import {
clickOnButtonInPackageContextMenu,
expectButtonInPackageContextMenu,
expectGlobalOnlyContextMenuForNotPreselectedAttribution,
testCorrectMarkAndUnmarkForReplacementInContextMenu,
} from '../../../test-helpers/context-menu-test-helpers';
import { getParsedInputFileEnrichedWithTestData } from '../../../test-helpers/general-test-helpers';
import { renderComponent } from '../../../test-helpers/render';
import { DisplayPackageInfos } from '../../../types/types';
Expand Down Expand Up @@ -126,101 +115,4 @@ describe('The AllAttributionsPanel', () => {
expect(screen.getByText('React, 2.0')).toBeInTheDocument();
expect(screen.getByText('Vue, 3.0')).toBeInTheDocument();
});

// eslint-disable-next-line jest/expect-expect
it('shows correct replace attribution buttons in the context menu', () => {
const testResources: Resources = {
root: { src: { file_1: 1, file_2: 1 } },
file: 1,
};
const testManualDisplayPackageInfos: DisplayPackageInfos = {
[testPackageCardId1]: {
packageName: 'jQuery',
packageVersion: '16.0.0',
comments: ['ManualPackage'],
attributionIds: ['uuid_1'],
},
[testPackageCardId2]: {
packageName: 'React',
packageVersion: '16.0.0',
comments: ['ManualPackage'],
attributionIds: ['uuid_2'],
},
[testPackageCardId3]: {
packageName: 'Vue',
packageVersion: '16.0.0',
comments: ['ManualPackage'],
preSelected: true,
attributionIds: ['uuid_3'],
},
};
const testManualAttributions: Attributions = {
uuid_1: {
packageName: 'jQuery',
packageVersion: '16.0.0',
comment: 'ManualPackage',
},
uuid_2: {
packageName: 'React',
packageVersion: '16.0.0',
comment: 'ManualPackage',
},
uuid_3: {
packageName: 'Vue',
packageVersion: '16.0.0',
comment: 'ManualPackage',
preSelected: true,
},
};
const testResourcesToManualAttributions: ResourcesToAttributions = {
'/root/src/file_1': ['uuid_1'],
'/root/src/file_2': ['uuid_2', 'uuid_3'],
};

renderComponent(
<AllAttributionsPanel
displayPackageInfos={testManualDisplayPackageInfos}
isAddToPackageEnabled={true}
/>,
{
actions: [
loadFromFile(
getParsedInputFileEnrichedWithTestData({
resources: testResources,
manualAttributions: testManualAttributions,
resourcesToManualAttributions: testResourcesToManualAttributions,
}),
),
],
},
);

expectGlobalOnlyContextMenuForNotPreselectedAttribution(
screen,
'jQuery, 16.0.0',
);

testCorrectMarkAndUnmarkForReplacementInContextMenu(
screen,
'jQuery, 16.0.0',
);

clickOnButtonInPackageContextMenu(
screen,
'jQuery, 16.0.0',
ButtonText.MarkForReplacement,
);

expectButtonInPackageContextMenu(
screen,
'Vue, 16.0.0',
ButtonText.ReplaceMarked,
);

expectGlobalOnlyContextMenuForNotPreselectedAttribution(
screen,
'React, 16.0.0',
true,
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,12 @@
//
// SPDX-License-Identifier: Apache-2.0
import { FrequentLicenseName } from '../../../shared/shared-types';
import { View } from '../../enums/enums';
import { ADD_NEW_ATTRIBUTION_BUTTON_ID } from '../../shared-constants';
import {
addResolvedExternalAttribution,
removeResolvedExternalAttribution,
} from '../../state/actions/resource-actions/audit-view-simple-actions';
import { saveManualAndResolvedAttributionsToFile } from '../../state/actions/resource-actions/save-actions';
import { AppThunkDispatch } from '../../state/types';
import { PanelPackage } from '../../types/types';
import { isExternalPackagePanel } from '../../util/is-external-package-panel';

export function getResolvedToggleHandler(
attributionIds: Array<string>,
Expand Down Expand Up @@ -65,73 +61,3 @@ export function getLicenseTextLabelText(
}`
: 'License Text (to appear in attribution document)';
}

export interface MergeButtonDisplayState {
hideMarkForReplacementButton: boolean;
hideUnmarkForReplacementButton: boolean;
hideReplaceMarkedByButton: boolean;
deactivateReplaceMarkedByButton: boolean;
hideMarkAsPreferredButton: boolean;
hideUnmarkAsPreferredButton: boolean;
}

export function getMergeButtonsDisplayState(currentState: {
attributionIdMarkedForReplacement: string;
targetAttributionId: string;
selectedAttributionId: string;
packageInfoWereModified: boolean;
targetAttributionIsPreSelected: boolean;
targetAttributionIsExternalAttribution: boolean;
isPreferenceFeatureEnabled?: boolean;
attributionIsPreferred?: boolean;
view?: View;
}): MergeButtonDisplayState {
const anyAttributionMarkedForReplacement =
currentState.attributionIdMarkedForReplacement !== '';
const targetAttributionIsMarkedForReplacement =
currentState.targetAttributionId ===
currentState.attributionIdMarkedForReplacement;
const selectedAttributionIsPartOfMerge =
currentState.selectedAttributionId ===
currentState.attributionIdMarkedForReplacement ||
currentState.selectedAttributionId === currentState.targetAttributionId;

return {
hideMarkForReplacementButton:
currentState.targetAttributionIsExternalAttribution ||
targetAttributionIsMarkedForReplacement,
hideUnmarkForReplacementButton:
currentState.targetAttributionIsExternalAttribution ||
!anyAttributionMarkedForReplacement ||
!targetAttributionIsMarkedForReplacement,
hideReplaceMarkedByButton:
currentState.targetAttributionIsExternalAttribution ||
!anyAttributionMarkedForReplacement ||
targetAttributionIsMarkedForReplacement,
deactivateReplaceMarkedByButton:
(selectedAttributionIsPartOfMerge &&
currentState.packageInfoWereModified) ||
currentState.targetAttributionIsPreSelected,
hideMarkAsPreferredButton:
!currentState.isPreferenceFeatureEnabled ||
!currentState.selectedAttributionId ||
Boolean(currentState.attributionIsPreferred),
hideUnmarkAsPreferredButton:
!currentState.isPreferenceFeatureEnabled ||
!currentState.selectedAttributionId ||
!currentState.attributionIsPreferred,
};
}

export function getSelectedManualAttributionIdForAuditView(
selectedPackage: PanelPackage | null,
): string {
if (
selectedPackage &&
!isExternalPackagePanel(selectedPackage.panel) &&
selectedPackage.packageCardId !== ADD_NEW_ATTRIBUTION_BUTTON_ID
) {
return selectedPackage.displayPackageInfo.attributionIds[0];
}
return '';
}
31 changes: 14 additions & 17 deletions src/Frontend/Components/AttributionColumn/AuditingOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export function AuditingOptions({ packageInfo, isEditable }: Props) {
setAnchorEl={setAnchorEl}
options={options.filter(({ interactive }) => interactive)}
sx={{ marginTop: '8px' }}
multiple
/>
</>
) : null;
Expand All @@ -62,22 +63,18 @@ export function AuditingOptions({ packageInfo, isEditable }: Props) {
}

function renderSelectedOptions() {
return options.map(
(
{ label, icon, deleteIcon, selected, onDelete, interactive, id },
index,
) =>
selected ? (
<MuiChip
key={index}
label={label}
size={'small'}
icon={icon}
onDelete={interactive ? onDelete : undefined}
data-testid={`auditing-option-${id}`}
deleteIcon={deleteIcon}
/>
) : null,
);
return options
.filter(({ selected }) => selected)
.map(({ label, icon, deleteIcon, onDelete, interactive, id }, index) => (
<MuiChip
key={index}
label={label}
size={'small'}
icon={icon}
onDelete={interactive ? onDelete : undefined}
data-testid={`auditing-option-${id}`}
deleteIcon={deleteIcon}
/>
));
}
}
Loading

0 comments on commit a33317b

Please sign in to comment.