Skip to content

[frontend] Save filters in the notifications datatable view #10288

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Apr 3, 2025
Merged
Show file tree
Hide file tree
Changes from 22 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
3 changes: 1 addition & 2 deletions opencti-platform/opencti-front/src/components/TextField.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ import TextFieldAskAI from '../private/components/common/form/TextFieldAskAI';
import StixDomainObjectDetectDuplicate from '../private/components/common/stix_domain_objects/StixDomainObjectDetectDuplicate';

const TextField = (props) => {
const { detectDuplicate, onBeforePaste, startAdornment, ...htmlProps } = props;
const { detectDuplicate, onBeforePaste, startAdornment, askAi, ...htmlProps } = props;
const {
form: { setFieldValue, setFieldTouched },
field: { name },
onChange,
onFocus,
onSubmit,
askAi,
} = props;
const internalOnChange = React.useCallback(
(event) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ type DataTableInternalToolbarProps = Pick<DataTableProps,
| 'handleCopy'
| 'removeAuthMembersEnabled'
| 'removeFromDraftEnabled'
| 'markAsReadEnabled'
> & {
taskScope?: string
globalSearch?: string;
Expand All @@ -120,6 +121,7 @@ const DataTableInternalToolbar = ({
globalSearch,
removeAuthMembersEnabled,
removeFromDraftEnabled,
markAsReadEnabled,
}: DataTableInternalToolbarProps) => {
const theme = useTheme<Theme>();

Expand Down Expand Up @@ -156,6 +158,7 @@ const DataTableInternalToolbar = ({
handleCopy={handleCopy}
removeAuthMembersEnabled={removeAuthMembersEnabled}
removeFromDraftEnabled={removeFromDraftEnabled}
markAsReadEnabled={markAsReadEnabled}
/>
</div>
);
Expand Down Expand Up @@ -215,6 +218,7 @@ const DataTable = (props: OCTIDataTableProps) => {
taskScope,
removeAuthMembersEnabled,
removeFromDraftEnabled,
markAsReadEnabled,
} = props;

const settingsMessagesBannerHeight = useSettingsMessagesBannerHeight();
Expand Down Expand Up @@ -269,6 +273,7 @@ const DataTable = (props: OCTIDataTableProps) => {
globalSearch={globalSearch}
removeAuthMembersEnabled={removeAuthMembersEnabled}
removeFromDraftEnabled={removeFromDraftEnabled}
markAsReadEnabled={markAsReadEnabled}
/>
)}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const DataTableHeader: FunctionComponent<DataTableHeaderProps> = ({
>
<div className={classes.label} onClick={throttleSortColumn}>
<Tooltip title={t_i18n(column.label)}>
{t_i18n(column.label).toUpperCase()}
<span>{t_i18n(column.label).toUpperCase()}</span>
</Tooltip>
{sortBy && (orderAsc ? <ArrowDropUp /> : <ArrowDropDown />)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,11 @@ const DataTableLine = ({

// Memoize link to avoid recomputations
let link = useMemo(() => useComputeLink(data), [data]);
if (redirectionMode && redirectionMode !== 'overview') {
if (redirectionMode && redirectionMode !== 'overview' && link !== undefined) {
link = `${link}/${redirectionMode}`;
}

const navigable = !disableNavigation && !onLineClick && !selectOnLineClick;
const navigable = !disableNavigation && !onLineClick && !selectOnLineClick && !!link;
const clickable = !!(navigable || selectOnLineClick || onLineClick);

const handleSelectLine = (event: React.MouseEvent) => {
Expand All @@ -137,7 +137,8 @@ const DataTableLine = ({
};

const handleNavigate = (event: React.MouseEvent) => {
if (!navigable) return;
if (!navigable || !link) return;

if (event.ctrlKey) {
window.open(link, '_blank');
} else {
Expand Down Expand Up @@ -241,7 +242,7 @@ const DataTableLine = ({
>
{actions && actions(data)}
{endsWithNavigate && (
<IconButton onClick={() => navigate(link)}>
<IconButton onClick={() => (link ? navigate(link) : undefined)}>
<KeyboardArrowRightOutlined />
</IconButton>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export interface DataTableContextProps {
useDataTable: ReturnType<DataTableProps['useDataTable']>
useDataCellHelpers: DataTableProps['useDataCellHelpers']
useDataTableToggle: ReturnType<DataTableProps['useDataTableToggle']>
useComputeLink: (entity: any) => string
useComputeLink: (entity: any) => string | undefined
useDataTableColumnsLocalStorage: ReturnType<DataTableProps['useDataTableColumnsLocalStorage']>
useDataTablePaginationLocalStorage: ReturnType<DataTableProps['useDataTablePaginationLocalStorage']>
onAddFilter: DataTableProps['onAddFilter']
Expand Down Expand Up @@ -111,7 +111,7 @@ export interface DataTableProps {
initialValue: LocalStorage,
ignoreUri?: boolean,
) => PaginationLocalStorage<T>
useComputeLink?: (entity: any) => string
useComputeLink?: (entity: any) => string | undefined
useDataTableToggle: (key: string) => {
selectedElements: Record<string, any>
deSelectedElements: Record<string, any>
Expand Down Expand Up @@ -139,6 +139,7 @@ export interface DataTableProps {
disableSelectAll?: boolean
removeAuthMembersEnabled?: boolean
removeFromDraftEnabled?: boolean
markAsReadEnabled?: boolean
selectOnLineClick?: boolean
onLineClick?: (line: any) => void
hideHeaders?: boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,17 @@ const SavedFilterButton = () => {
return (
<>
<Tooltip title={t_i18n('Save filter')}>
<IconButton
color="primary"
onClick={handleOpenDialog}
size="small"
disabled={!filters?.filters.length && !filters?.filterGroups.length}
aria-label={t_i18n('Save')}
>
<SaveOutlined />
</IconButton>
<span>
<IconButton
color="primary"
onClick={handleOpenDialog}
size="small"
disabled={!filters?.filters.length && !filters?.filterGroups.length}
aria-label={t_i18n('Save')}
>
<SaveOutlined />
</IconButton>
</span>
</Tooltip>

{isSavedDialogOpen && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
BrushOutlined,
CancelOutlined,
CenterFocusStrong,
CheckCircleOutlined,
ClearOutlined,
CloseOutlined,
ContentCopyOutlined,
Expand All @@ -44,6 +45,7 @@ import {
MoveToInboxOutlined,
RestoreOutlined,
TransformOutlined,
UnpublishedOutlined,
} from '@mui/icons-material';
import { BankMinus, BankPlus, CloudRefreshOutline, LabelOutline } from 'mdi-material-ui';
import Autocomplete from '@mui/material/Autocomplete';
Expand Down Expand Up @@ -196,11 +198,11 @@ const styles = (theme) => ({
},
});

const notMergableTypes = ['Playbook', 'Indicator', 'Note', 'Opinion', 'Label', 'Case-Template', 'Task', 'DeleteOperation', 'InternalFile', 'PublicDashboard', 'Workspace', 'DraftWorkspace'];
const notAddableTypes = ['Playbook', 'Label', 'Vocabulary', 'Case-Template', 'DeleteOperation', 'InternalFile', 'PublicDashboard', 'Workspace', 'DraftWorkspace'];
const notUpdatableTypes = ['Playbook', 'Label', 'Vocabulary', 'Case-Template', 'Task', 'DeleteOperation', 'InternalFile', 'PublicDashboard', 'Workspace', 'DraftWorkspace'];
const notScannableTypes = ['Playbook', 'Label', 'Vocabulary', 'Case-Template', 'Task', 'DeleteOperation', 'InternalFile', 'PublicDashboard', 'Workspace', 'DraftWorkspace'];
const notEnrichableTypes = ['Playbook', 'Label', 'Vocabulary', 'Case-Template', 'Task', 'DeleteOperation', 'InternalFile', 'PublicDashboard', 'Workspace', 'DraftWorkspace'];
const notMergableTypes = ['Playbook', 'Indicator', 'Note', 'Opinion', 'Label', 'Case-Template', 'Task', 'DeleteOperation', 'InternalFile', 'PublicDashboard', 'Workspace', 'DraftWorkspace', 'Notification'];
const notAddableTypes = ['Playbook', 'Label', 'Vocabulary', 'Case-Template', 'DeleteOperation', 'InternalFile', 'PublicDashboard', 'Workspace', 'DraftWorkspace', 'Notification'];
const notUpdatableTypes = ['Playbook', 'Label', 'Vocabulary', 'Case-Template', 'Task', 'DeleteOperation', 'InternalFile', 'PublicDashboard', 'Workspace', 'DraftWorkspace', 'Notification'];
const notScannableTypes = ['Playbook', 'Label', 'Vocabulary', 'Case-Template', 'Task', 'DeleteOperation', 'InternalFile', 'PublicDashboard', 'Workspace', 'DraftWorkspace', 'Notification'];
const notEnrichableTypes = ['Playbook', 'Label', 'Vocabulary', 'Case-Template', 'Task', 'DeleteOperation', 'InternalFile', 'PublicDashboard', 'Workspace', 'DraftWorkspace', 'Notification'];
const typesWithScore = [
'Stix-Cyber-Observable',
'Indicator',
Expand Down Expand Up @@ -249,7 +251,7 @@ const typesWithIndicatorTypes = ['Indicator'];
const typesWithPlatforms = ['Indicator'];

const typesWithoutStatus = ['Stix-Core-Object', 'Stix-Domain-Object', 'Stix-Cyber-Observable', 'Artifact', 'ExternalReference'];
const notShareableTypes = ['Playbook', 'Label', 'Vocabulary', 'Case-Template', 'DeleteOperation', 'InternalFile', 'PublicDashboard', 'Workspace', 'DraftWorkspace'];
const notShareableTypes = ['Playbook', 'Label', 'Vocabulary', 'Case-Template', 'DeleteOperation', 'InternalFile', 'PublicDashboard', 'Workspace', 'DraftWorkspace', 'Notification'];

const Transition = React.forwardRef((props, ref) => (
<Slide direction="up" ref={ref} {...props} />
Expand Down Expand Up @@ -607,7 +609,19 @@ class DataTableToolBar extends Component {
}
this.setState({ actionsInputs });
}

handleLaunchRead(read) {
const actions = [{
type: 'REPLACE',
context: {
field: 'is_read',
type: 'ATTRIBUTE',
values: [read ? 'true' : 'false'],
},
}];
this.setState({ actions }, () => {
this.handleOpenTask();
});
}
handleLaunchDelete() {
const actions = [{ type: 'DELETE', context: null }];
this.setState({ actions }, () => {
Expand Down Expand Up @@ -1779,6 +1793,7 @@ class DataTableToolBar extends Component {
deleteOperationEnabled,
removeAuthMembersEnabled,
removeFromDraftEnabled,
markAsReadEnabled,
warning,
warningMessage,
taskScope,
Expand Down Expand Up @@ -1910,6 +1925,36 @@ class DataTableToolBar extends Component {
</IconButton>
</div>
<div>
{markAsReadEnabled && (
<>
<Tooltip title={t('Mark as read')}>
<span>
<IconButton
aria-label={t('Mark as read')}
disabled={numberOfSelectedElements === 0 || this.state.processing}
onClick={this.handleLaunchRead.bind(this, true)}
color="success"
size="small"
>
<CheckCircleOutlined fontSize="small" />
</IconButton>
</span>
</Tooltip>
<Tooltip title={t('Mark as unread')}>
<span>
<IconButton
aria-label={t('Mark as unread')}
disabled={numberOfSelectedElements === 0 || this.state.processing}
onClick={this.handleLaunchRead.bind(this, false)}
color="warning"
size="small"
>
<UnpublishedOutlined fontSize="small" />
</IconButton>
</span>
</Tooltip>
</>
)}
{removeAuthMembersEnabled && (
<Security needs={[BYPASS]}>
<Tooltip title={t('Remove access restriction')}>
Expand Down Expand Up @@ -3058,6 +3103,7 @@ DataTableToolBar.propTypes = {
deleteOperationEnabled: PropTypes.bool,
removeAuthMembersEnabled: PropTypes.bool,
removeFromDraft: PropTypes.bool,
markAsReadEnabled: PropTypes.bool,
taskScope: PropTypes.string,
};

Expand Down
Loading