diff --git a/app/docker/__module.js b/app/docker/__module.js
index cb9383bcf..ed9ad294a 100644
--- a/app/docker/__module.js
+++ b/app/docker/__module.js
@@ -188,8 +188,7 @@ angular.module('portainer.docker', ['portainer.app', reactModule]).config([
url: '/events',
views: {
'content@': {
- templateUrl: './views/events/events.html',
- controller: 'EventsController',
+ component: 'eventsListView',
},
},
data: {
diff --git a/app/docker/react/views/index.ts b/app/docker/react/views/index.ts
index 6205f0b22..9c3f8b95f 100644
--- a/app/docker/react/views/index.ts
+++ b/app/docker/react/views/index.ts
@@ -5,6 +5,7 @@ import { r2a } from '@/react-tools/react2angular';
import { withCurrentUser } from '@/react-tools/withCurrentUser';
import { withUIRouter } from '@/react-tools/withUIRouter';
import { DashboardView } from '@/react/docker/DashboardView/DashboardView';
+import { ListView } from '@/react/docker/events/ListView';
import { containersModule } from './containers';
@@ -14,6 +15,7 @@ export const viewsModule = angular
'dockerDashboardView',
r2a(withUIRouter(withCurrentUser(DashboardView)), [])
)
+ .component('eventsListView', r2a(withUIRouter(withCurrentUser(ListView)), []))
.component(
'networkDetailsView',
r2a(withUIRouter(withCurrentUser(NetworksItemView)), [])
diff --git a/app/docker/services/systemService.js b/app/docker/services/systemService.js
index ed02d2c00..9c945527d 100644
--- a/app/docker/services/systemService.js
+++ b/app/docker/services/systemService.js
@@ -1,8 +1,6 @@
import { ping } from '@/react/docker/proxy/queries/usePing';
import { getInfo } from '@/react/docker/proxy/queries/useInfo';
import { getVersion } from '@/react/docker/proxy/queries/useVersion';
-import { getEvents } from '@/react/docker/proxy/queries/useEvents';
-import { EventViewModel } from '../models/event';
angular.module('portainer.docker').factory('SystemService', SystemServiceFactory);
@@ -14,15 +12,5 @@ function SystemServiceFactory(AngularToReact) {
info: useAxios(injectEnvironmentId(getInfo)), // dashboard + docker host view + docker host browser + swarm inspect views + stateManager (update endpoint state)
ping: useAxios(ping), // docker/__module onEnter abstract /docker subpath
version: useAxios(injectEnvironmentId(getVersion)), // docker host view + swarm inspect view + stateManager (update endpoint state)
- events: useAxios(injectEnvironmentId(eventsAngularJS)), // events list
};
-
- /**
- * @param {EnvironmentId} environmentId Injected
- * @param {{since: string; until: string;}} param1
- */
- async function eventsAngularJS(environmentId, { since, until }) {
- const data = await getEvents(environmentId, { since, until });
- return data.map((e) => new EventViewModel(e));
- }
}
diff --git a/app/docker/views/events/events.html b/app/docker/views/events/events.html
deleted file mode 100644
index b85942243..000000000
--- a/app/docker/views/events/events.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/app/docker/views/events/eventsController.js b/app/docker/views/events/eventsController.js
deleted file mode 100644
index 3864eabc0..000000000
--- a/app/docker/views/events/eventsController.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import moment from 'moment';
-
-angular.module('portainer.docker').controller('EventsController', [
- '$scope',
- 'Notifications',
- 'SystemService',
- function ($scope, Notifications, SystemService) {
- function initView() {
- const since = moment().subtract(24, 'hour').unix();
- const until = moment().unix();
-
- SystemService.events({ since, until })
- .then(function success(data) {
- $scope.events = data;
- })
- .catch(function error(err) {
- Notifications.error('Failure', err, 'Unable to load events');
- });
- }
-
- initView();
- },
-]);
diff --git a/app/react/docker/events/EventsDatatables.tsx b/app/react/docker/events/EventsDatatables.tsx
index e79f65407..36d356fd1 100644
--- a/app/react/docker/events/EventsDatatables.tsx
+++ b/app/react/docker/events/EventsDatatables.tsx
@@ -1,5 +1,6 @@
import { createColumnHelper } from '@tanstack/react-table';
import { Clock } from 'lucide-react';
+import { EventMessage } from 'docker-types/generated/1.41';
import { isoDateFromTimestamp } from '@/portainer/filters/filters';
@@ -7,26 +8,22 @@ import { Datatable } from '@@/datatables';
import { createPersistedStore } from '@@/datatables/types';
import { useTableState } from '@@/datatables/useTableState';
-type DockerEvent = {
- Time: number;
- Type: string;
- Details: string;
-};
+import { createEventDetails } from './model';
-const columnHelper = createColumnHelper();
+const columnHelper = createColumnHelper();
export const columns = [
- columnHelper.accessor('Time', {
+ columnHelper.accessor('time', {
header: 'Date',
cell: ({ getValue }) => {
const value = getValue();
return isoDateFromTimestamp(value);
},
}),
- columnHelper.accessor('Type', {
+ columnHelper.accessor((c) => c.Type, {
header: 'Type',
}),
- columnHelper.accessor('Details', {
+ columnHelper.accessor((c) => createEventDetails(c), {
header: 'Details',
}),
];
@@ -37,12 +34,17 @@ const settingsStore = createPersistedStore(tableKey, {
desc: true,
});
-export function EventsDatatable({ dataset }: { dataset: Array }) {
+export function EventsDatatable({
+ dataset,
+}: {
+ dataset?: Array;
+}) {
const tableState = useTableState(settingsStore, tableKey);
return (
+
+
+
+ >
+ );
+}
+
+function useDateRange() {
+ return useState(() => {
+ const since = moment().subtract(24, 'hour').unix();
+ const until = moment().unix();
+
+ return { since, until };
+ })[0];
+}
diff --git a/app/docker/models/event.ts b/app/react/docker/events/model.ts
similarity index 93%
rename from app/docker/models/event.ts
rename to app/react/docker/events/model.ts
index 95b171140..437ed3ebb 100644
--- a/app/docker/models/event.ts
+++ b/app/react/docker/events/model.ts
@@ -87,7 +87,7 @@ const templates: EventToTemplateMap = {
},
};
-function createEventDetails(event: EventMessage) {
+export function createEventDetails(event: EventMessage) {
const eventType = event.Type ?? '';
// An action can be `action:extra`
@@ -118,17 +118,3 @@ function createEventDetails(event: EventMessage) {
return details + extra;
}
-
-export class EventViewModel {
- Time: EventMessage['time'];
-
- Type: EventMessage['Type'];
-
- Details: string;
-
- constructor(data: EventMessage) {
- this.Time = data.time;
- this.Type = data.Type;
- this.Details = createEventDetails(data);
- }
-}
diff --git a/app/react/docker/events/types.ts b/app/react/docker/events/types.ts
new file mode 100644
index 000000000..9d9cd92de
--- /dev/null
+++ b/app/react/docker/events/types.ts
@@ -0,0 +1,5 @@
+export type DockerEvent = {
+ Time: number;
+ Type: string;
+ Details: string;
+};
diff --git a/app/react/docker/proxy/queries/query-keys.ts b/app/react/docker/proxy/queries/query-keys.ts
index 2439c835e..d11da4230 100644
--- a/app/react/docker/proxy/queries/query-keys.ts
+++ b/app/react/docker/proxy/queries/query-keys.ts
@@ -3,4 +3,6 @@ import { EnvironmentId } from '@/react/portainer/environments/types';
export const queryKeys = {
base: (environmentId: EnvironmentId) =>
[environmentId, 'docker', 'proxy'] as const,
+ events: (environmentId: EnvironmentId, params?: object) =>
+ [...queryKeys.base(environmentId), 'events', params] as const,
};
diff --git a/app/react/docker/proxy/queries/useEvents.ts b/app/react/docker/proxy/queries/useEvents.ts
index 35e8d6cc9..88e637886 100644
--- a/app/react/docker/proxy/queries/useEvents.ts
+++ b/app/react/docker/proxy/queries/useEvents.ts
@@ -1,4 +1,5 @@
import { EventMessage } from 'docker-types/generated/1.41';
+import { useQuery } from '@tanstack/react-query';
import axios, {
jsonObjectsToArrayHandler,
@@ -7,16 +8,26 @@ import axios, {
import { EnvironmentId } from '@/react/portainer/environments/types';
import { buildDockerProxyUrl } from './buildDockerProxyUrl';
+import { queryKeys } from './query-keys';
+
+type Params = { since?: number; until?: number };
+
+export function useEvents(
+ environmentId: EnvironmentId,
+ { params }: { params?: Params } = {}
+) {
+ return useQuery({
+ queryKey: [...queryKeys.events(environmentId, params)],
+ queryFn: () => getEvents(environmentId, params),
+ });
+}
/**
* Raw docker API proxy
- * @param environmentId
- * @param param1
- * @returns
*/
export async function getEvents(
environmentId: EnvironmentId,
- { since, until }: { since: string; until: string }
+ { since, until }: Params = {}
) {
try {
const { data } = await axios.get(