ra-audit-log
Display event lists and audit logs, keep track of user actions, and get an overview of the activity of your admin.

Test it live in the Enterprise Edition Storybook.
Overview
This module introduces 3 new components:
<Timeline>shows a list of all recent changes in the admin. It's a great component for dashboards.<RecordTimeline>shows a list of all recent changes for a given record, usually embedded in a<Show>or<Edit>view.<EventList>is a ready-to-useListcomponent for navigating in your admin history, complete with filters and pagination.
It exposes one new hook:
useRecordEventsfetches events related to a record
ra-audit-log also provides a data provider helper called addEventsForMutations to create events client-side, in case you don't do it on the server side.
Setup
Installation
npm install --save @react-admin/ra-audit-log
# or
yarn add @react-admin/ra-audit-log
Tip: ra-audit-log is part of the React-Admin Enterprise Edition, and hosted in a private npm registry. You need to subscribe to one of the Enterprise Edition plans to access this package.
Event Format
This package expects you to store and expose one "event" for each change triggered by a user action.
Event records must contain the following properties:
iddateauthorresourceaction
Here is a typical event:
{
date: '2020-09-08 15:01:00',
author: {
id: 567,
fullName: 'John Doe',
avatar: 'https://myavatar.com',
},
resource: 'posts',
action: 'create',
payload: { title: 'foo', body: 'bar' }
}
We recommend that you create event logs server-side, i.e. add a new event record each time a user performs a mutation (create, update, delete, updateMany, deleteMany). Typically, you can achieve this using a proxy server, a database trigger, or a middleware in your API server. Then, it's your responsibility to expose an API for these events and to update your dataProvider so that it can access events like any other resource.
Client-Side Tracking
You can choose to let ra-audit-log create events for you. In this case, each mutation performed by a user will trigger a call to dataProvider.create('events', [event details]). We call this feature client-side tracking.
To enable client-side tracking, build a new dataProvider by calling the addEventsForMutations helper function with your original dataProvider and your authProvider:
import { addEventsForMutations } from '@react-admin/ra-audit-log';
import simpleRestProvider from 'ra-data-simple-rest';
import authProvider from './authProvider';
const dataProvider = addEventsForMutations(
simpleRestProvider('http://path.to.my.api/'),
authProvider
);
import { addEventsForMutations } from "@react-admin/ra-audit-log";
import simpleRestProvider from "ra-data-simple-rest";
import authProvider from "./authProvider";
const dataProvider = addEventsForMutations(simpleRestProvider("http://path.to.my.api/"), authProvider);
Your authProvider must have a getIdentity method, which returns an object containing the id, the fullName and optionally the avatar (an image URL) for the current logged user:
const authProvider = {
// login: () => {},
// logout: () => {},
// ...,
getIdentity: () =>
Promise.resolve({
id: 567,
fullName: 'John Doe',
avatar: 'https://myavatar.com',
}),
};
const authProvider = {
// login: () => {},
// logout: () => {},
// ...,
getIdentity: () =>
Promise.resolve({
id: 567,
fullName: "John Doe",
avatar: "https://myavatar.com",
}),
};
When enabled, after each successful mutation, the client-side tracking wrapper adds a new event. For instance:
// when your app calls
dataProvider.update('orders', {
id: 123,
data: { status: 'delivered' },
previousData: { id: 123, status: 'received' },
});
// the wrapper calls
dataProvider.create('events', {
date: '2020-09-08 15:01:00',
author: {
id: 567,
fullName: 'John Doe',
avatar: 'https://myavatar.com',
},
resource: 'orders',
action: 'update',
payload: {
id: 123,
data: { status: 'delivered' },
previousData: { id: 123, status: 'received' },
},
});
// when your app calls
dataProvider.update("orders", {
id: 123,
data: { status: "delivered" },
previousData: { id: 123, status: "received" },
});
// the wrapper calls
dataProvider.create("events", {
date: "2020-09-08 15:01:00",
author: {
id: 567,
fullName: "John Doe",
avatar: "https://myavatar.com",
},
resource: "orders",
action: "update",
payload: {
id: 123,
data: { status: "delivered" },
previousData: { id: 123, status: "received" },
},
});
The addEventsForMutations function accepts the following options:
name: the name of the event logs resource (defaults toevents)
import { addEventsForMutations } from '@react-admin/ra-audit-log';
import simpleRestProvider from 'ra-data-simple-rest';
import authProvider from './authProvider';
const dataProvider = addEventsForMutations(
simpleRestProvider('http://path.to.my.api/'),
authProvider,
{ name: 'events' }
);
import { addEventsForMutations } from "@react-admin/ra-audit-log";
import simpleRestProvider from "ra-data-simple-rest";
import authProvider from "./authProvider";
const dataProvider = addEventsForMutations(simpleRestProvider("http://path.to.my.api/"), authProvider, {
name: "events",
});
resources: the resources and mutations you want to track with events. It can be an array of resource names or an array of arrays defining both the resource and the dataProvider calls to track
import { addEventsForMutations } from '@react-admin/ra-audit-log';
import simpleRestProvider from 'ra-data-simple-rest';
import authProvider from './authProvider';
const dataProvider = addEventsForMutations(
simpleRestProvider('http://path.to.my.api/'),
authProvider,
{
resources: [
// create an event for all known mutations on posts
'posts',
// create an event only for create and update on comments, but not for delete, deleteMany or updateMany
['comments', ['create', 'update']],
],
}
);
import { addEventsForMutations } from "@react-admin/ra-audit-log";
import simpleRestProvider from "ra-data-simple-rest";
import authProvider from "./authProvider";
const dataProvider = addEventsForMutations(simpleRestProvider("http://path.to.my.api/"), authProvider, {
resources: [
// create an event for all known mutations on posts
"posts",
// create an event only for create and update on comments, but not for delete, deleteMany or updateMany
["comments", ["create", "update"]],
],
});
shouldAudit: as an alternative toresources, you can specify a function which, given a dataProvider method name (create,update, etc.) and the arguments it was called with, should returntrueto create an event. This allows to target custom dataProvider methods:
import { addEventsForMutations } from '@react-admin/ra-audit-log';
import simpleRestProvider from 'ra-data-simple-rest';
import authProvider from './authProvider';
const dataProvider = addEventsForMutations(
simpleRestProvider('http://path.to.my.api/'),
authProvider,
{
shouldAudit: (action, ...args) => {
if (action === 'myCustomMethod') {
return true;
}
},
}
);
import { addEventsForMutations } from "@react-admin/ra-audit-log";
import simpleRestProvider from "ra-data-simple-rest";
import authProvider from "./authProvider";
const dataProvider = addEventsForMutations(simpleRestProvider("http://path.to.my.api/"), authProvider, {
shouldAudit: (action, ...args) => {
if (action === "myCustomMethod") {
return true;
}
},
});
Translations
In order to have correct labels on the <Timeline> and <EventList> components, you have to set up the internationalization with the provided translations or your own. Check out the Internationalization section below for detailed steps.
<Timeline>

The <Timeline> component displays a list of events, the most recent first, grouped by day. It's the ideal component for checking the recent activity of an admin.
It accepts the following props:
records: An array of eventsisLoading: Optional. Boolean, indicating whether the data is loading for the first time.children: Optional. Component rendered for each group of audit logs.groupLogs: Optional. A function called with the audit logs and the locale. Must return groups.skeleton: Optional. The element to display whileisLoadingistrue.
Basic Usage
It's your responsibility to get the events from the dataProvider and pass them to <Timeline>.
import { useGetList } from 'react-admin';
import { Timeline } from '@react-admin/ra-audit-log';
const Dashboard = () => {
const { data, isLoading } = useGetList(
'events',
{ page: 1, perPage: 25 },
{ field: 'date', order: 'desc' }
);
return <Timeline isLoading={isLoading} records={data} />;
};
import { useGetList } from "react-admin";
import { Timeline } from "@react-admin/ra-audit-log";
const Dashboard = () => {
const { data, isLoading } = useGetList("events", { page: 1, perPage: 25 }, { field: "date", order: "desc" });
return <Timeline isLoading={isLoading} records={data} />;
};
Custom Group Component
By default, <Timeline> uses the <TimelineGroup> component to render each group. You can use your own component instead by passing it as the <Timeline> child. In this component, use the useTimelineGroup hook to grab the group information.
import { useGetList } from 'react-admin';
import { Timeline, useTimelineGroup } from '@react-admin/ra-audit-log';
const Dashboard = () => {
const { data, isLoading } = useGetList(
'audit-logs',
{ page: 1, perPage: 25 },
{ field: 'date', order: 'desc' }
);
return (
<Timeline isLoading={isLoading} records={data}>
<MyTimelineGroup />
</Timeline>
);
};
const MyTimelineGroup = () => {
const { label, records } = useTimelineGroup();
return (
<article>
<h1>{label}</h1>
<ul>
{records.map(record => (
<li>{JSON.stringify(record)}</li>
))}
</ul>
</article>
);
};
import { useGetList } from "react-admin";
import { Timeline, useTimelineGroup } from "@react-admin/ra-audit-log";
const Dashboard = () => {
const { data, isLoading } = useGetList("audit-logs", { page: 1, perPage: 25 }, { field: "date", order: "desc" });
return (
<Timeline isLoading={isLoading} records={data}>
<MyTimelineGroup />
</Timeline>
);
};
const MyTimelineGroup = () => {
const { label, records } = useTimelineGroup();
return (
<article>
<h1>{label}</h1>
<ul>
{records.map((record) => (
<li>{JSON.stringify(record)}</li>
))}
</ul>
</article>
);
};
Custom Item Component
<TimelineGroup> renders each event using the <TimelineItem> component. You can replace it with your own component instead, by passing it as a child to <TimelineGroup>. Use the useRecordContext hook to grab the event record.
import { useGetList, useRecordContext } from 'react-admin';
import {
AuditLogLabel,
Timeline,
TimelineItem,
TimelineItemProps,
TimelineGroup,
useTimeline,
} from '@react-admin/ra-audit-log';
const Dashboard = () => {
const { data, isLoading } = useGetList(
'audit-logs',
{ page: 1, perPage: 25 },
{ field: 'date', order: 'desc' }
);
return (
<Timeline isLoading={isLoading} records={data}>
<MyTimelineGroup />
</Timeline>
);
};
const MyTimelineGroup = () => {
return (
<TimelineGroup>
<MyTimelineItem />
</TimelineGroup>
);
};
const MyTimelineItem = (props: TimelineItemProps) => {
const record = useRecordContext(props.record);
return (
<ListItem>
<ListItemText
primary={record.author.fullName}
secondary={<AuditLogLabel />}
/>
</ListItem>
);
};
import { useGetList, useRecordContext } from "react-admin";
import { AuditLogLabel, Timeline, TimelineGroup } from "@react-admin/ra-audit-log";
const Dashboard = () => {
const { data, isLoading } = useGetList("audit-logs", { page: 1, perPage: 25 }, { field: "date", order: "desc" });
return (
<Timeline isLoading={isLoading} records={data}>
<MyTimelineGroup />
</Timeline>
);
};
const MyTimelineGroup = () => {
return (
<TimelineGroup>
<MyTimelineItem />
</TimelineGroup>
);
};
const MyTimelineItem = (props) => {
const record = useRecordContext(props.record);
return (
<ListItem>
<ListItemText primary={record.author.fullName} secondary={<AuditLogLabel />} />
</ListItem>
);
};
Custom skeleton
You may want to display more items in the skeleton while data is loading.
import { useGetList } from 'react-admin';
import { Timeline, TimelineSkeleton } from '@react-admin/ra-audit-log';
const Dashboard = () => {
const { data, isLoading } = useGetList(
'events',
{ page: 1, perPage: 25 },
{ field: 'date', order: 'desc' }
);
return (
<Timeline
isLoading={isLoading}
records={data}
skeleton={<TimelineSkeleton length={50} />}
/>
);
};
import { useGetList } from "react-admin";
import { Timeline, TimelineSkeleton } from "@react-admin/ra-audit-log";
const Dashboard = () => {
const { data, isLoading } = useGetList("events", { page: 1, perPage: 25 }, { field: "date", order: "desc" });
return <Timeline isLoading={isLoading} records={data} skeleton={<TimelineSkeleton length={50} />} />;
};
<RecordTimeline>

The <RecordTimeline> component is a specialized version of the <Timeline>. It accepts the same props except records and isLoading. It will fetch the event related to the current record. This record can be either the one from the current RecordContext (set by react-admin components) or the one specified using the record prop.
It accepts the following props:
record: Optional. The record for which to fetch the eventsresource: Optional. The resource.eventResource: Optional. The resource for the events.children: Optional. Component rendered for each group of audit logs.groupLogs: Optional. A function called with the audit logs and the locale. Must return groups.skeleton: Optional. The element to display whileisLoadingistrue.
Usage
You can use the <RecordTimeline> as an aside for an <Edit> view:
import { Edit, EditProps, SimpleForm, TextField } from 'react-admin';
import { RecordTimeline } from '@react-admin/ra-audit-log';
const ProductEdit = (props: EditProps) => {
return (
<Edit {...props} aside={<RecordTimeline />}>
<SimpleForm>
<TextField source="name" />
</SimpleForm>
</Edit>
);
};
import { Edit, SimpleForm, TextField } from "react-admin";
import { RecordTimeline } from "@react-admin/ra-audit-log";
const ProductEdit = (props) => {
return (
<Edit {...props} aside={<RecordTimeline />}>
<SimpleForm>
<TextField source="name" />
</SimpleForm>
</Edit>
);
};
useRecordEvents
This hook can be used to fetch events related to a record. It accepts the following options:
record: Optional. The record for which to fetch the events. Will be inferred from the RecordContext if not providedresource: Optional. The resource of the record. Will be inferred from the ResourceContext if not providedeventResource: Optional. The resource for the events. Defaults toeventspage: Optional. The page of events to fetch. Defaults to 1perPage: Optional. The number of events to fetch. Defaults to 25sort: Optional. The field used to sort the events. Defaults todateorder: Optional. The order into which to sort the events. Defaults toDESC
It returns the same object as the useGetListhook, containing the following properties:
data: An array of recordsisLoading: A boolean indicating whether the list is currently loadingerror: An object containing an error when one occurs
<EventList>
The <EventList> component is a full-featured List component for events, pre-configured with a Datagrid and a filter sidebar.

Basic Usage
Use the <EventList> component as the list prop of the events <Resource>:
// In App.js
import { Admin, Resource } from 'react-admin';
import { EventList } from '@react-admin/ra-audit-log';
export const App = () => (
<Admin>
<Resource name="events" list={EventList} />
</Admin>
);
// In App.js
import { Admin, Resource } from "react-admin";
import { EventList } from "@react-admin/ra-audit-log";
export const App = () => (
<Admin>
<Resource name="events" list={EventList} />
</Admin>
);
In addition to the usual List props, <EventList> accepts the following props:
eventResource: The name of the events resource. Defaults toevents.authorResource: You can optionally provide the resource name for the authors of the events.ra-audit-logwill use it to create links to authors.dateFilters: A map of date filters to replace the default ones.
Events Resource
<EventList> allows users to filter events by resource, exluding the events resource itself. By default, it excludes the events resource. If you used a different resource name for events, use the eventResource prop to change it:
// In App.js
import { Admin, Resource } from 'react-admin';
import { MyEventList } from './evenList';
export const App = () => (
<Admin>
<Resource name="audit-logs" list={MyEventList} />
</Admin>
);
// in ./eventList.js
import { ListProps } from 'react-admin';
import { EventList } from '@react-admin/ra-audit-log';
export const MyEventList = (props: ListProps) => (
<EventList eventResource="audit-logs" />
);
// In App.js
import { Admin, Resource } from "react-admin";
import { MyEventList } from "./evenList";
export const App = () => (
<Admin>
<Resource name="audit-logs" list={MyEventList} />
</Admin>
);
import { EventList } from "@react-admin/ra-audit-log";
export const MyEventList = (props) => <EventList eventResource="audit-logs" />;
Authors Resource
You can provide a resource name for the authors of the events. <EventList> uses it to render links to each author in the list, and an AutocompleteArrayInput to filter them.
Without authors resource:

With authors resource:

Use the authorResource prop to set the author resource in the <EventList>:
// In App.js
import { Admin, Resource } from 'react-admin';
import { MyEventList } from './evenList';
export const App = () => (
<Admin>
<Resource name="events" list={MyEventList} />
</Admin>
);
// In ./eventList.js
import { ListProps } from 'react-admin';
import { EventList } from '@react-admin/ra-audit-log';
export const MyEventList = (props: ListProps) => (
<EventList authorResource="users" />
);
// In App.js
import { Admin, Resource } from "react-admin";
import { MyEventList } from "./evenList";
export const App = () => (
<Admin>
<Resource name="events" list={MyEventList} />
</Admin>
);
import { EventList } from "@react-admin/ra-audit-log";
export const MyEventList = (props) => <EventList authorResource="users" />;
Date Filters
By default, @react-admin/ra-audit-log provides filters for the following date ranges:
- Today
- Last week
- Last month
- Last quarter
You can provide your own set of date filters by using the dateFilters prop:
// In App.js
import { Admin, Resource } from 'react-admin';
import { MyEventList } from './evenList';
export const App = () => (
<Admin>
<Resource name="events" list={MyEventList} />
</Admin>
);
// In ./eventList.js
import { ListProps } from 'react-admin';
import { DefaultDateFilters, EventList } from '@react-admin/ra-audit-log';
const dateFilters = {
...DefaultDateFilters,
'This Year': () => startOfYear(new Date()).toISOString(),
};
export const MyEventList = (props: ListProps) => (
<EventList dateFilters={dateFilters} />
);
// In App.js
import { Admin, Resource } from "react-admin";
import { MyEventList } from "./evenList";
export const App = () => (
<Admin>
<Resource name="events" list={MyEventList} />
</Admin>
);
import { DefaultDateFilters, EventList } from "@react-admin/ra-audit-log";
const dateFilters = {
...DefaultDateFilters,
"This Year": () => startOfYear(new Date()).toISOString(),
};
export const MyEventList = (props) => <EventList dateFilters={dateFilters} />;
Internationalization
ra-audit-log provides translations for English (raAuditLogLanguageEnglish) and French (raAuditLogLanguageFrench).
The interface in English looks like this:

The interface in French looks like this:

You should merge these translations with the other interface messages before passing them to your i18nProvider:
import { mergeTranslations } from 'react-admin';
import polyglotI18nProvider from 'ra-i18n-polyglot';
import englishMessages from 'ra-language-english';
import frenchMessages from 'ra-language-french';
import {
raAuditLogLanguageEnglish,
raAuditLogLanguageFrench,
} from '@react-admin/ra-audit-log';
const i18nProvider = polyglotI18nProvider(locale =>
locale === 'en'
? mergeTranslations(englishMessages, raAuditLogLanguageEnglish)
: mergeTranslations(frenchMessages, raAuditLogLanguageFrench)
);
import { mergeTranslations } from "react-admin";
import polyglotI18nProvider from "ra-i18n-polyglot";
import englishMessages from "ra-language-english";
import frenchMessages from "ra-language-french";
import { raAuditLogLanguageEnglish, raAuditLogLanguageFrench } from "@react-admin/ra-audit-log";
const i18nProvider = polyglotI18nProvider((locale) =>
locale === "en"
? mergeTranslations(englishMessages, raAuditLogLanguageEnglish)
: mergeTranslations(frenchMessages, raAuditLogLanguageFrench)
);
The event field names are translatable. ra-audit-log uses the react-admin resource and field name translation system. This is an example of an English translation file:
// in i18n/en.js
export default {
resources: {
events: {
name: 'Log |||| Log',
fields: {
date: 'Date',
author: 'Author',
resource: 'Resource',
action: 'Action',
},
},
},
};
// in i18n/en.js
export default {
resources: {
events: {
name: "Log |||| Log",
fields: {
date: "Date",
author: "Author",
resource: "Resource",
action: "Action",
},
},
},
};
ra-audit-log also supports internationalization for the textual representation of the event action.
If available, ra-audit-log uses the translation with the key ra-audit-log.event.[resource].[action], where resource and action are replaced with the actual resource and action names. For example: ra-audit-log.event.posts.create.
If not available, it will fall back to the following translation key: ra-audit-log.event.[action], where action is replaced with the actual action name. For example: ra-audit-log.event.create.
In all cases, the following variables are available for interpolation in the translated string:
name: the name of the record targeted by the action if available. It will be the first available property on the record in this list:name,label,title,reference, orid.resource: the name of the event resourceids: the list of the record identifiers if the action was targeting many (deleteMany,updateManyfor example).all_fields: the complete list of the fields which were modified in anupdateaction.fields: the list of the fields which were modified in anupdateaction. Limited to a maximum of two. To be used with thesmart_countvariable.smart_count: The number of updated fields in addition of the two available in thefieldvariable. This allows to display messages like:Update field Name, Category and 5 others.
Building Blocks
Would you want to create your own <EventList> component, we provide some building blocks you might reuse:
-
<EventListFilter>: A component to pass to the listfilterprop. It includes the author, date, and resource filters. -
<AuthorInput>: An input used to filter events by authors. It's a basic TextInput unless theauthorResourceprop is provided. In this case, it's a<ReferenceArrayInput>with an<AutocompleteArrayInput>. -
<EventDateInput>: An input used to filter events by date. It provides the default date filters presented before. It accepts adateFiltersprop similar to the<EventList>. -
<ResourceInput>: An input used to filter events by resource. It's an<AutocompleteArrayInput>which lists all the resources declared in the<Admin>component but the events. -
<EventFilterList>: A component to pass to the listasideprop. It includes the author, date, and resource filters presented as a sidebar. -
<AuthorFilterList>: A filter sidebar part used to filter events by authors. It's a basic TextInput unless theauthorResourceprop is provided. In this case, it's a<ReferenceArrayInput>with an<AutocompleteArrayInput>. -
<EventFilterList>: A filter sidebar part used to filter events by date. It provides the default date filters presented before and displayed as filter list items. It accepts adateFiltersprop similar to the<EventList>. -
<ResourceFilterList>: A filter sidebar part used to filter events by resource. It's an<AutocompleteArrayInput>which lists all the resources declared in theAdmincomponent but the events. -
<ActionField>: A react-admin field that displays a formated text for the event action. -
<AuthorField>: A react-admin field that displays the event authors. If theauthorResourceprop is provided, it uses a<ReferenceField>and will show a link to the author. -
<AvatarField>: A react-admin field that displays the author avatar with a fallback to a material-ui icon. -
<ResourceField>: A react-admin field that displays the event resource. The resource name is translated like in react-admin. It will use the resource label option if available.
CHANGELOG
v4.0.4
2023-04-26
- (fix) Fix
<EventList>props type to makechildrenoptional.
v4.0.3
2022-11-02
- (fix) Fix
useRecordEventsraises an error if called with no parameter
v4.0.2
2022-09-27
- (fix) Fix
RecordTimelinedoes not accept custom children - (doc) Fix type of
authorfield in events
v4.0.1
2022-06-08
- (fix) Update peer dependencies ranges (support React 18)
v4.0.0
2022-06-07
- Upgrade to react-admin v4
Breaking Changes
The <Timeline loaded> prop has been renamed to <Timeline isLoading>. Same for the <RecordTimeline> component.
-<Timeline loaded={false} records={records} />
+<Timeline isLoading records={records} />
-<Timeline loaded records={records} />
+<Timeline records={records} />
v2.5.2
2021-11-12
- (fix)
EventListno longer fails ondeleteevents.
v2.5.1
2021-09-16
- (fix)
updateManyanddeleteManynow create an event log for each targeted record with the singular related action, respectivelyupdateanddelete.
v2.5.0
2021-09-14
- (feat) Export
<EventDatagrid>andEventListPropsto allow easier customEventList
v2.4.1
2021-07-08
- (fix) Fix TimelineItem might trigger an error on logout
v2.4.0
2021-07-07
- (feat) updateMany and deleteMany now create an event log for each targeted record
v2.3.1
2021-06-29
- (fix) Update peer dependencies ranges (support react 17)
v2.3.0
2021-06-28
- (feat)
<Timeline>now has askeletonprop which accept an element, allowing you to customize the skeleton UI displayed while loading. - (feat)
<RecordTimeline>now takes less space and draw less attention. - (feat)
<RecordTimeline>now displays the names of the fields which were updated for any update event record.
v2.0.2
2021-04-20
- (fix) Add missing date-fns dependency
v2.0.1
2021-04-12
- (fix) Make Resource and Event Inputs Resettable
v2.0.0
2021-03-22
- (feat) Introduce
<RecordTimeline>component - (feat) Introduce
useRecordEventshook
Breaking Change:
- (feat) Refactor
useEventLabelto accept avariantprop instead of theinlineprop
-useEventLabel({ inline: true })
+useEventLabel({ variant: 'inline' })
v1.0.3
2021-03-22
- (fix) Fix ra-audit-log published without built files
v1.0.2
2021-03-19
- (fix) Add a better screencast to showcase the package
v1.0.1
2021-03-18
- (fix) Fix Filters in Sidebar erase existing filters
- (fix) Fix Filters in Sidebar initial values
- (fix) Fix Filters in Sidebar display
v1.0.0
2021-03-17
- First release