diff --git a/app/docker/components/datatables/configs-datatable/configsDatatable.html b/app/docker/components/datatables/configs-datatable/configsDatatable.html
deleted file mode 100644
index 44336e121..000000000
--- a/app/docker/components/datatables/configs-datatable/configsDatatable.html
+++ /dev/null
@@ -1,170 +0,0 @@
-
diff --git a/app/docker/components/datatables/configs-datatable/configsDatatable.js b/app/docker/components/datatables/configs-datatable/configsDatatable.js
deleted file mode 100644
index 569281fcc..000000000
--- a/app/docker/components/datatables/configs-datatable/configsDatatable.js
+++ /dev/null
@@ -1,14 +0,0 @@
-angular.module('portainer.docker').component('configsDatatable', {
- templateUrl: './configsDatatable.html',
- controller: 'GenericDatatableController',
- bindings: {
- titleText: '@',
- titleIcon: '@',
- dataset: '<',
- tableKey: '@',
- orderBy: '@',
- reverseOrder: '<',
- removeAction: '<',
- refreshCallback: '<',
- },
-});
diff --git a/app/docker/react/components/index.ts b/app/docker/react/components/index.ts
index 3e0d0a977..84f32e0bf 100644
--- a/app/docker/react/components/index.ts
+++ b/app/docker/react/components/index.ts
@@ -18,6 +18,7 @@ import { InsightsBox } from '@/react/components/InsightsBox';
import { BetaAlert } from '@/react/portainer/environments/update-schedules/common/BetaAlert';
import { ImagesDatatable } from '@/react/docker/images/ListView/ImagesDatatable/ImagesDatatable';
import { EventsDatatable } from '@/react/docker/events/EventsDatatables';
+import { ConfigsDatatable } from '@/react/docker/configs/ListView/ConfigsDatatable';
const ngModule = angular
.module('portainer.docker.react.components', [])
@@ -82,6 +83,14 @@ const ngModule = angular
'onRemove',
])
)
+ .component(
+ 'dockerConfigsDatatable',
+ r2a(withUIRouter(ConfigsDatatable), [
+ 'dataset',
+ 'onRemoveClick',
+ 'onRefresh',
+ ])
+ )
.component('dockerEventsDatatable', r2a(EventsDatatable, ['dataset']));
export const componentsModule = ngModule.name;
diff --git a/app/docker/views/configs/configs.html b/app/docker/views/configs/configs.html
index 0f64783d6..ee4727bbe 100644
--- a/app/docker/views/configs/configs.html
+++ b/app/docker/views/configs/configs.html
@@ -1,15 +1,3 @@
-
+
diff --git a/app/react/docker/configs/ListView/ConfigsDatatable/ConfigsDatatable.tsx b/app/react/docker/configs/ListView/ConfigsDatatable/ConfigsDatatable.tsx
new file mode 100644
index 000000000..86c13349e
--- /dev/null
+++ b/app/react/docker/configs/ListView/ConfigsDatatable/ConfigsDatatable.tsx
@@ -0,0 +1,62 @@
+import { Clipboard, Plus, Trash2 } from 'lucide-react';
+
+import { Datatable, TableSettingsMenu } from '@@/datatables';
+import { TableSettingsMenuAutoRefresh } from '@@/datatables/TableSettingsMenuAutoRefresh';
+import { useRepeater } from '@@/datatables/useRepeater';
+import { Button } from '@@/buttons';
+import { Link } from '@@/Link';
+import { useTableState } from '@@/datatables/useTableState';
+
+import { DockerConfig } from '../../types';
+
+import { columns } from './columns';
+import { createStore } from './store';
+
+interface Props {
+ dataset: Array;
+ onRemoveClick: (configs: Array) => void;
+ onRefresh: () => Promise;
+}
+
+const storageKey = 'docker_configs';
+const settingsStore = createStore(storageKey);
+
+export function ConfigsDatatable({ dataset, onRefresh, onRemoveClick }: Props) {
+ const tableState = useTableState(settingsStore, storageKey);
+
+ useRepeater(tableState.autoRefreshRate, onRefresh);
+
+ return (
+ (
+
+ tableState.setAutoRefreshRate(value)}
+ />
+
+ )}
+ renderTableActions={(selectedRows) => (
+
+
+
+
+ )}
+ />
+ );
+}
diff --git a/app/react/docker/configs/ListView/ConfigsDatatable/columns.tsx b/app/react/docker/configs/ListView/ConfigsDatatable/columns.tsx
new file mode 100644
index 000000000..ac08b2478
--- /dev/null
+++ b/app/react/docker/configs/ListView/ConfigsDatatable/columns.tsx
@@ -0,0 +1,22 @@
+import { createColumnHelper } from '@tanstack/react-table';
+
+import { isoDate } from '@/portainer/filters/filters';
+import { createOwnershipColumn } from '@/react/docker/components/datatable-helpers/createOwnershipColumn';
+
+import { buildNameColumn } from '@@/datatables/NameCell';
+
+import { DockerConfig } from '../../types';
+
+const columnHelper = createColumnHelper();
+
+export const columns = [
+ buildNameColumn('Name', 'Id', 'docker.configs.config'),
+ columnHelper.accessor('CreatedAt', {
+ header: 'Creation Date',
+ cell: ({ getValue }) => {
+ const date = getValue();
+ return ;
+ },
+ }),
+ createOwnershipColumn(),
+];
diff --git a/app/react/docker/configs/ListView/ConfigsDatatable/index.ts b/app/react/docker/configs/ListView/ConfigsDatatable/index.ts
new file mode 100644
index 000000000..b8aa1e3bc
--- /dev/null
+++ b/app/react/docker/configs/ListView/ConfigsDatatable/index.ts
@@ -0,0 +1 @@
+export { ConfigsDatatable } from './ConfigsDatatable';
diff --git a/app/react/docker/configs/ListView/ConfigsDatatable/store.ts b/app/react/docker/configs/ListView/ConfigsDatatable/store.ts
new file mode 100644
index 000000000..66672630a
--- /dev/null
+++ b/app/react/docker/configs/ListView/ConfigsDatatable/store.ts
@@ -0,0 +1,16 @@
+import {
+ BasicTableSettings,
+ createPersistedStore,
+ refreshableSettings,
+ RefreshableTableSettings,
+} from '@@/datatables/types';
+
+export interface TableSettings
+ extends BasicTableSettings,
+ RefreshableTableSettings {}
+
+export function createStore(storageKey: string) {
+ return createPersistedStore(storageKey, 'name', (set) => ({
+ ...refreshableSettings(set),
+ }));
+}
diff --git a/app/react/docker/configs/types.ts b/app/react/docker/configs/types.ts
new file mode 100644
index 000000000..489fd3b4f
--- /dev/null
+++ b/app/react/docker/configs/types.ts
@@ -0,0 +1,8 @@
+import { ResourceControlViewModel } from '@/react/portainer/access-control/models/ResourceControlViewModel';
+
+export type DockerConfig = {
+ Id: string;
+ Name: string;
+ CreatedAt: string;
+ ResourceControl?: ResourceControlViewModel;
+};