Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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: 12 additions & 0 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,18 @@ func (a *App) BuildMenu(keyboardService service.KeyboardService) *menu.Menu {
runtime.EventsEmit(a.ctx, string(entities.ActionIncludeComponent))
})

// Ignore submenu
IgnoreMenu := ActionsMenu.AddSubmenu("Ignore")
IgnoreMenu.AddText("Ignore file", nil, func(cd *menu.CallbackData) {
runtime.EventsEmit(a.ctx, string(entities.ActionIgnoreFile))
})
IgnoreMenu.AddText("Ignore folder", nil, func(cd *menu.CallbackData) {
runtime.EventsEmit(a.ctx, string(entities.ActionIgnoreFolder))
})
IgnoreMenu.AddText("Ignore component", nil, func(cd *menu.CallbackData) {
runtime.EventsEmit(a.ctx, string(entities.ActionIgnoreComponent))
})

// Dismiss submenu
DismissMenu := ActionsMenu.AddSubmenu("Dismiss")
DismissMenu.AddText("Dismiss file", nil, func(cd *menu.CallbackData) {
Expand Down
3 changes: 2 additions & 1 deletion backend/entities/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ type FilterAction string

const (
Include FilterAction = "include"
Ignore FilterAction = "ignore"
Remove FilterAction = "remove"
Replace FilterAction = "replace"
)
Expand All @@ -95,7 +96,7 @@ type ComponentFilterDTO struct {
Path string `json:"path,omitempty"`
Purl string `json:"purl,omitempty"`
Usage string `json:"usage,omitempty"`
Action FilterAction `json:"action" validate:"required,eq=include|eq=remove|eq=replace"`
Action FilterAction `json:"action" validate:"required,eq=include|eq=ignore|eq=remove|eq=replace"`
Comment string `json:"comment,omitempty"`
ReplaceWith string `json:"replace_with,omitempty" validate:"omitempty,valid-purl"`
License string `json:"license,omitempty"`
Expand Down
6 changes: 6 additions & 0 deletions backend/entities/keyboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ const (
ActionIncludeFile Action = "includeFile"
ActionIncludeComponent Action = "includeComponent"
ActionIncludeFolder Action = "includeFolder"
ActionIgnoreFile Action = "ignoreFile"
ActionIgnoreComponent Action = "ignoreComponent"
ActionIgnoreFolder Action = "ignoreFolder"
ActionDismissFile Action = "dismissFile"
ActionDismissComponent Action = "dismissComponent"
ActionDismissFolder Action = "dismissFolder"
Expand Down Expand Up @@ -100,6 +103,9 @@ var AllShortcutActions = []struct {
{ActionIncludeFile, "IncludeFile"},
{ActionIncludeComponent, "IncludeComponent"},
{ActionIncludeFolder, "IncludeFolder"},
{ActionIgnoreFile, "IgnoreFile"},
{ActionIgnoreComponent, "IgnoreComponent"},
{ActionIgnoreFolder, "IgnoreFolder"},
{ActionDismissFile, "DismissFile"},
{ActionDismissComponent, "DismissComponent"},
{ActionDismissFolder, "DismissFolder"},
Expand Down
16 changes: 15 additions & 1 deletion backend/entities/scanoss_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ type SizesSkipSettings struct {

type Bom struct {
Include []ComponentFilter `json:"include,omitempty"`
Ignore []ComponentFilter `json:"ignore,omitempty"`
Remove []ComponentFilter `json:"remove,omitempty"`
Replace []ComponentFilter `json:"replace,omitempty"`
}
Expand All @@ -87,6 +88,7 @@ type ComponentFilter struct {

type InitialFilters struct {
Include []ComponentFilter
Ignore []ComponentFilter
Remove []ComponentFilter
Replace []ComponentFilter
}
Expand Down Expand Up @@ -195,10 +197,11 @@ func (sf *SettingsFile) Equal(other *SettingsFile) (bool, error) {

func (sf *SettingsFile) GetResultWorkflowState(result Result) WorkflowState {
included, _ := sf.IsResultIncluded(result)
ignored, _ := sf.IsResultIgnored(result)
removed, _ := sf.IsResultRemoved(result)
replaced, _ := sf.IsResultReplaced(result)

if included || removed || replaced {
if included || ignored || removed || replaced {
return Completed
}

Expand All @@ -209,6 +212,10 @@ func (sf *SettingsFile) IsResultIncluded(result Result) (bool, int) {
return sf.IsResultInList(result, sf.Bom.Include)
}

func (sf *SettingsFile) IsResultIgnored(result Result) (bool, int) {
return sf.IsResultInList(result, sf.Bom.Ignore)
}

func (sf *SettingsFile) IsResultRemoved(result Result) (bool, int) {
return sf.IsResultInList(result, sf.Bom.Remove)
}
Expand Down Expand Up @@ -242,6 +249,9 @@ func (sf *SettingsFile) GetResultFilterConfig(result Result) FilterConfig {
if included, i := sf.IsResultIncluded(result); included {
filterAction = Include
filterType = getResultFilterType(sf.Bom.Include[i])
} else if ignored, i := sf.IsResultIgnored(result); ignored {
filterAction = Ignore
filterType = getResultFilterType(sf.Bom.Ignore[i])
} else if removed, i := sf.IsResultRemoved(result); removed {
filterAction = Remove
filterType = getResultFilterType(sf.Bom.Remove[i])
Expand Down Expand Up @@ -274,6 +284,10 @@ func (sf *SettingsFile) GetBomEntryFromResult(result Result) ComponentFilter {
return sf.Bom.Include[i]
}

if ignored, i := sf.IsResultIgnored(result); ignored {
return sf.Bom.Ignore[i]
}

if removed, i := sf.IsResultRemoved(result); removed {
return sf.Bom.Remove[i]
}
Expand Down
8 changes: 7 additions & 1 deletion backend/repository/scanoss_settings_repository_json_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ func (r *ScanossSettingsJsonRepository) AddBomEntry(newEntry entities.ComponentF
targetList = &sf.Bom.Remove
case "include":
targetList = &sf.Bom.Include
case "ignore":
targetList = &sf.Bom.Ignore
case "replace":
targetList = &sf.Bom.Replace
default:
Expand All @@ -173,6 +175,7 @@ func (r *ScanossSettingsJsonRepository) removeDuplicatesFromAllLists(newEntry en

sf.Bom.Remove = removeDuplicatesFromList(sf.Bom.Remove, newEntry)
sf.Bom.Include = removeDuplicatesFromList(sf.Bom.Include, newEntry)
sf.Bom.Ignore = removeDuplicatesFromList(sf.Bom.Ignore, newEntry)
sf.Bom.Replace = removeDuplicatesFromList(sf.Bom.Replace, newEntry)
}

Expand All @@ -196,6 +199,7 @@ func isDuplicate(entry, newEntry entities.ComponentFilter) bool {
func (r *ScanossSettingsJsonRepository) ClearAllFilters() error {
sf := r.GetSettings()
sf.Bom.Include = []entities.ComponentFilter{}
sf.Bom.Ignore = []entities.ComponentFilter{}
sf.Bom.Remove = []entities.ComponentFilter{}
sf.Bom.Replace = []entities.ComponentFilter{}
return nil
Expand All @@ -205,13 +209,15 @@ func (r *ScanossSettingsJsonRepository) GetDeclaredPurls() []string {
sf := r.GetSettings()

includedComponents := extractPurlsFromBom(sf.Bom.Include)
ignoredComponents := extractPurlsFromBom(sf.Bom.Ignore)
removedComponents := extractPurlsFromBom(sf.Bom.Remove)
replacedComponents := extractPurlsFromBom(sf.Bom.Replace)

totalLength := len(includedComponents) + len(removedComponents) + len(replacedComponents)
totalLength := len(includedComponents) + len(ignoredComponents) + len(removedComponents) + len(replacedComponents)
declaredPurls := make([]string, 0, totalLength)

declaredPurls = append(declaredPurls, includedComponents...)
declaredPurls = append(declaredPurls, ignoredComponents...)
declaredPurls = append(declaredPurls, removedComponents...)
declaredPurls = append(declaredPurls, replacedComponents...)

Expand Down
11 changes: 10 additions & 1 deletion backend/service/component_service_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ func (s *ComponentServiceImpl) setInitialFilters() {
Action: entities.Include,
})
}
for _, ignore := range initialFilters.Ignore {
s.initialFilters = append(s.initialFilters, entities.ComponentFilterDTO{
Path: ignore.Path,
Purl: ignore.Purl,
Usage: string(ignore.Usage),
Action: entities.Ignore,
})
}
for _, remove := range initialFilters.Remove {
s.initialFilters = append(s.initialFilters, entities.ComponentFilterDTO{
Path: remove.Path,
Expand All @@ -99,10 +107,11 @@ func (s *ComponentServiceImpl) ClearAllFilters() error {

func (s *ComponentServiceImpl) GetInitialFilters() entities.InitialFilters {
sf := s.scanossSettingsRepo.GetSettings()
include, remove, replace := sf.Bom.Include, sf.Bom.Remove, sf.Bom.Replace
include, ignore, remove, replace := sf.Bom.Include, sf.Bom.Ignore, sf.Bom.Remove, sf.Bom.Replace

return entities.InitialFilters{
Include: include,
Ignore: ignore,
Remove: remove,
Replace: replace,
}
Expand Down
41 changes: 40 additions & 1 deletion frontend/src/components/FilterComponentActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
* SOFTWARE.
*/

import { Check, EyeOff, PackageMinus, Replace } from 'lucide-react';
import { Ban, Check, EyeOff, PackageMinus, Replace } from 'lucide-react';
import { useCallback, useMemo, useState } from 'react';

import useKeyboardShortcut from '@/hooks/useKeyboardShortcut';
Expand Down Expand Up @@ -122,6 +122,11 @@ export default function FilterComponentActions() {
includeFolder: createModalActionHandler(FilterAction.Include, 'folder'),
includeComponent: createModalActionHandler(FilterAction.Include, 'component'),

// Ignore: file applies directly, others open modal
ignoreFile: createDirectActionHandler(FilterAction.Ignore),
ignoreFolder: createModalActionHandler(FilterAction.Ignore, 'folder'),
ignoreComponent: createModalActionHandler(FilterAction.Ignore, 'component'),

// Dismiss: file applies directly, others open modal
dismissFile: createDirectActionHandler(FilterAction.Remove),
dismissFolder: createModalActionHandler(FilterAction.Remove, 'folder'),
Expand Down Expand Up @@ -149,6 +154,11 @@ export default function FilterComponentActions() {
useKeyboardShortcut(KEYBOARD_SHORTCUTS.includeComponent.keys, handlers.includeComponent, { enabled: filterEnabled });
useKeyboardShortcut(KEYBOARD_SHORTCUTS.includeFolder.keys, handlers.includeFolder, { enabled: filterEnabled });

// Ignore
useKeyboardShortcut(KEYBOARD_SHORTCUTS.ignoreFile.keys, handlers.ignoreFile, { enabled: filterEnabled });
useKeyboardShortcut(KEYBOARD_SHORTCUTS.ignoreComponent.keys, handlers.ignoreComponent, { enabled: filterEnabled });
useKeyboardShortcut(KEYBOARD_SHORTCUTS.ignoreFolder.keys, handlers.ignoreFolder, { enabled: filterEnabled });

// Dismiss
useKeyboardShortcut(KEYBOARD_SHORTCUTS.dismissFile.keys, handlers.dismissFile, { enabled: filterEnabled });
useKeyboardShortcut(KEYBOARD_SHORTCUTS.dismissComponent.keys, handlers.dismissComponent, { enabled: filterEnabled });
Expand All @@ -170,6 +180,10 @@ export default function FilterComponentActions() {
[entities.Action.IncludeFile]: handlers.includeFile,
[entities.Action.IncludeComponent]: handlers.includeComponent,
[entities.Action.IncludeFolder]: handlers.includeFolder,
// Ignore
[entities.Action.IgnoreFile]: handlers.ignoreFile,
[entities.Action.IgnoreComponent]: handlers.ignoreComponent,
[entities.Action.IgnoreFolder]: handlers.ignoreFolder,
// Dismiss
[entities.Action.DismissFile]: handlers.dismissFile,
[entities.Action.DismissComponent]: handlers.dismissComponent,
Expand Down Expand Up @@ -214,6 +228,31 @@ export default function FilterComponentActions() {
</MenubarContent>
</MenubarMenu>

{/* Ignore */}
<MenubarMenu>
<MenubarTrigger
disabled={isDisabled}
className="flex h-full w-14 flex-col items-center justify-center gap-1 rounded-none px-2 py-1 data-[state=open]:bg-accent"
>
<span className="text-xs">Ignore</span>
<Ban className="h-5 w-5 stroke-gray-500" />
</MenubarTrigger>
<MenubarContent align="start" className="min-w-[180px]">
<MenubarItem onSelect={handlers.ignoreFile}>
File
<MenubarShortcut>G</MenubarShortcut>
</MenubarItem>
<MenubarItem onSelect={handlers.ignoreFolder}>
Folder
<MenubarShortcut>Alt+Shift+G</MenubarShortcut>
</MenubarItem>
<MenubarItem onSelect={handlers.ignoreComponent}>
Component
<MenubarShortcut>Shift+G</MenubarShortcut>
</MenubarItem>
</MenubarContent>
</MenubarMenu>

{/* Dismiss */}
<MenubarMenu>
<MenubarTrigger
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/lib/shortcuts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,21 @@ export const KEYBOARD_SHORTCUTS: Record<entities.Action, KeyboardShortcut> = {
description: 'Open include dialog with folder selected',
keys: 'alt+shift+i',
},
[entities.Action.IgnoreFile]: {
name: 'Ignore file',
description: 'Ignore file directly',
keys: 'g, f5',
},
[entities.Action.IgnoreComponent]: {
name: 'Ignore component',
description: 'Open ignore dialog with component selected',
keys: 'shift+g, shift+f5',
},
[entities.Action.IgnoreFolder]: {
name: 'Ignore folder',
description: 'Open ignore dialog with folder selected',
keys: 'alt+shift+g',
},
[entities.Action.DismissFile]: {
name: 'Dismiss file',
description: 'Dismiss file directly',
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/modules/components/domain/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export enum FilterAction {
export type FilterBy = 'path' | 'purl';

export const filterActionLabelMap: Record<FilterAction, string> = {
[FilterAction.Ignore]: 'Omit / Skip',
[FilterAction.Ignore]: 'Ignore',
[FilterAction.Include]: 'Include',
[FilterAction.Remove]: 'Dismiss',
[FilterAction.Replace]: 'Replace',
Expand Down
15 changes: 11 additions & 4 deletions frontend/wailsjs/go/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ export namespace entities {
IncludeFile = "includeFile",
IncludeComponent = "includeComponent",
IncludeFolder = "includeFolder",
IgnoreFile = "ignoreFile",
IgnoreComponent = "ignoreComponent",
IgnoreFolder = "ignoreFolder",
DismissFile = "dismissFile",
DismissComponent = "dismissComponent",
DismissFolder = "dismissFolder",
Expand Down Expand Up @@ -50,16 +53,18 @@ export namespace entities {
}
export class Bom {
include?: ComponentFilter[];
ignore?: ComponentFilter[];
remove?: ComponentFilter[];
replace?: ComponentFilter[];

static createFrom(source: any = {}) {
return new Bom(source);
}

constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.include = this.convertValues(source["include"], ComponentFilter);
this.ignore = this.convertValues(source["ignore"], ComponentFilter);
this.remove = this.convertValues(source["remove"], ComponentFilter);
this.replace = this.convertValues(source["replace"], ComponentFilter);
}
Expand Down Expand Up @@ -409,16 +414,18 @@ export namespace entities {
}
export class InitialFilters {
Include: ComponentFilter[];
Ignore: ComponentFilter[];
Remove: ComponentFilter[];
Replace: ComponentFilter[];

static createFrom(source: any = {}) {
return new InitialFilters(source);
}

constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.Include = this.convertValues(source["Include"], ComponentFilter);
this.Ignore = this.convertValues(source["Ignore"], ComponentFilter);
this.Remove = this.convertValues(source["Remove"], ComponentFilter);
this.Replace = this.convertValues(source["Replace"], ComponentFilter);
}
Expand Down
Loading