diff --git a/src/actions/audit-log-actions.js b/src/actions/audit-log-actions.js index 034956b8d..9a3923b2c 100644 --- a/src/actions/audit-log-actions.js +++ b/src/actions/audit-log-actions.js @@ -19,26 +19,22 @@ import { authErrorHandler, escapeFilterValue } from 'openstack-uicore-foundation/lib/utils/actions'; -import {getAccessTokenSafely} from '../utils/methods'; +import {getAccessTokenSafely,isNumericString, parseDateRangeFilter} from '../utils/methods'; export const CLEAR_LOG_PARAMS = 'CLEAR_LOG_PARAMS'; export const REQUEST_LOG = 'REQUEST_LOG'; export const RECEIVE_LOG = 'RECEIVE_LOG'; -export const getAuditLog = (entityFilter = [], term = null, page = 1, perPage = 100, order = null, orderDir = 1) => async (dispatch, getState) => { +export const getAuditLog = (entityFilter = [], term = null, page = 1, perPage = 100, order = null, orderDir = 1, filters = {}) => async (dispatch, getState) => { const {currentSummitState} = getState(); const accessToken = await getAccessTokenSafely(); const {currentSummit} = currentSummitState; - const filter = [`summit_id==${currentSummit.id}`]; + const summitTZ = currentSummit.time_zone.name; + const summitFilter = [`summit_id==${currentSummit.id}`]; dispatch(startLoading()); - if (term) { - const escapedTerm = escapeFilterValue(term); - filter.push(`user_email=@${escapedTerm},user_full_name=@${escapedTerm},action=@${escapedTerm}`); - } - const params = { page: page, per_page: perPage, @@ -46,7 +42,9 @@ export const getAuditLog = (entityFilter = [], term = null, page = 1, perPage = access_token: accessToken, }; - params['filter[]'] = [...filter, ...entityFilter]; + const parsedFilters = [...summitFilter, ...entityFilter, ...parseFilters(filters, term)]; + + params['filter[]'] = parsedFilters; // order if (order != null && orderDir != null) { @@ -59,13 +57,42 @@ export const getAuditLog = (entityFilter = [], term = null, page = 1, perPage = createAction(RECEIVE_LOG), `${window.API_BASE_URL}/api/v1/audit-logs`, authErrorHandler, - {page, perPage, order, orderDir, term} + {page, perPage, order, orderDir, term, summitTZ, filters} )(params)(dispatch).then(() => { dispatch(stopLoading()); } ); }; +const parseFilters = (filters, term = null) => { + const filter = []; + + if (filters.created_date_filter) { + parseDateRangeFilter(filter, filters.created_date_filter, 'created'); + } + + if (filters.hasOwnProperty('user_id_filter') && Array.isArray(filters.user_id_filter) + && filters.user_id_filter.length > 0) { + filter.push(`user_id==${filters.user_id_filter.map(t => t.id).join('||')}`); + } + + if (term) { + const escapedTerm = escapeFilterValue(term); + let searchString = ''; + + if (isNumericString(term)) { + searchString += `entity_id==${term}`; + } else { + searchString += `action=@${escapedTerm}` + } + + filter.push(searchString); + } + + + return filter; +} + export const clearAuditLogParams = () => async (dispatch, getState) => { dispatch(createAction(CLEAR_LOG_PARAMS)()); }; \ No newline at end of file diff --git a/src/components/audit-logs/index.js b/src/components/audit-logs/index.js index 4e6a81196..a1f8987b8 100644 --- a/src/components/audit-logs/index.js +++ b/src/components/audit-logs/index.js @@ -1,11 +1,26 @@ -import React, {useEffect} from "react"; -import {FreeTextSearch, Table} from "openstack-uicore-foundation/lib/components"; +import React, { useEffect, useState } from "react"; +import { FreeTextSearch, Table, Dropdown, MemberInput, DateTimePicker } from "openstack-uicore-foundation/lib/components"; import T from "i18n-react"; -import {Pagination} from "react-bootstrap"; -import {connect} from "react-redux"; -import {clearAuditLogParams, getAuditLog} from "../../actions/audit-log-actions"; +import { epochToMomentTimeZone } from 'openstack-uicore-foundation/lib/utils/methods' +import { Pagination } from "react-bootstrap"; +import { connect } from "react-redux"; +import { clearAuditLogParams, getAuditLog } from "../../actions/audit-log-actions"; + +const AuditLogs = ({ entityFilter = [], term, logEntries, perPage, lastPage, currentPage, order, orderDir, columns, getAuditLog, clearAuditLogParams, filters }) => { + + const defaultFilters = { + user_id_filter: [], + created_date_filter: Array(2).fill(null) + } + + const [enabledFilters, setEnabledFilters] = useState(Object.keys(filters).filter(e => Array.isArray(filters[e]) ? filters[e]?.some(e => e !== null) : filters[e]?.length > 0)); + const [auditLogFilters, setAuditLogFilters] = useState({ ...defaultFilters, ...filters }); + + const filters_ddl = [ + { label: 'Created', value: 'created_date_filter' }, + { label: 'Member', value: 'user_id_filter' }, + ] -const AuditLogs = ({entityFilter = [], term, logEntries, perPage, lastPage, currentPage, order, orderDir, columns, getAuditLog, clearAuditLogParams}) => { const audit_log_table_options = { sortCol: order, sortDir: orderDir, @@ -22,19 +37,57 @@ const AuditLogs = ({entityFilter = [], term, logEntries, perPage, lastPage, curr const show_columns = columns ? audit_log_columns.filter(c => columns.includes(c.columnKey)) : audit_log_columns; const handleSort = (index, key, dir, func) => { - getAuditLog(entityFilter, term, currentPage, perPage, key, dir); + getAuditLog(entityFilter, term, currentPage, perPage, key, dir, auditLogFilters); }; const handlePageChange = (page) => { - getAuditLog(entityFilter, term, page, perPage, order, orderDir); + getAuditLog(entityFilter, term, page, perPage, order, orderDir, auditLogFilters); }; const handleSearch = (newTerm) => { - getAuditLog(entityFilter, newTerm, currentPage, perPage, order, orderDir); + getAuditLog(entityFilter, newTerm, currentPage, perPage, order, orderDir, auditLogFilters); }; + const handleDDLSortByLabel = (ddlArray) => { + return ddlArray.sort((a, b) => a.label.localeCompare(b.label)); + } + + const handleFiltersChange = (ev) => { + const { value } = ev.target; + if (value.length < enabledFilters.length) { + if (value.length === 0) { + setEnabledFilters(value); + setAuditLogFilters(defaultFilters); + } else { + const removedFilter = enabledFilters.filter(e => !value.includes(e))[0]; + const defaultValue = Array.isArray(auditLogFilters[removedFilter]) ? [] : ''; + let newEventFilters = { ...auditLogFilters, [removedFilter]: defaultValue }; + setEnabledFilters(value); + setAuditLogFilters(newEventFilters); + } + } else { + setEnabledFilters(value); + } + } + + const handleChangeDateFilter = (ev, lastDate) => { + const { value, id } = ev.target; + const newDateFilter = auditLogFilters[id]; + + setAuditLogFilters({ ...auditLogFilters, [id]: lastDate ? [newDateFilter[0], value.unix()] : [value.unix(), newDateFilter[1]] }) + } + + const handleAuditLogFilterChange = (ev) => { + let { value, type, id } = ev.target; + setAuditLogFilters({ ...auditLogFilters, [id]: value }); + } + + const handleApplyAuditLogFilters = () => { + getAuditLog(entityFilter, term, currentPage, perPage, order, orderDir, auditLogFilters); + } + useEffect(() => { - getAuditLog(entityFilter, term, 1, perPage, order, orderDir); + getAuditLog(entityFilter, term, 1, perPage, order, orderDir, filters); return () => { clearAuditLogParams(); @@ -54,6 +107,73 @@ const AuditLogs = ({entityFilter = [], term, logEntries, perPage, lastPage, curr +