diff --git a/app/docker/components/datatables/secrets-datatable/secretsDatatable.html b/app/docker/components/datatables/secrets-datatable/secretsDatatable.html
deleted file mode 100644
index db5eee7c0..000000000
--- a/app/docker/components/datatables/secrets-datatable/secretsDatatable.html
+++ /dev/null
@@ -1,170 +0,0 @@
-
diff --git a/app/docker/components/datatables/secrets-datatable/secretsDatatable.js b/app/docker/components/datatables/secrets-datatable/secretsDatatable.js
deleted file mode 100644
index 840a98fc2..000000000
--- a/app/docker/components/datatables/secrets-datatable/secretsDatatable.js
+++ /dev/null
@@ -1,14 +0,0 @@
-angular.module('portainer.docker').component('secretsDatatable', {
- templateUrl: './secretsDatatable.html',
- controller: 'GenericDatatableController',
- bindings: {
- titleText: '@',
- titleIcon: '@',
- dataset: '<',
- tableKey: '@',
- orderBy: '@',
- reverseOrder: '<',
- removeAction: '<',
- refreshCallback: '<',
- },
-});
diff --git a/app/docker/models/secret.js b/app/docker/models/secret.js
deleted file mode 100644
index aea1d7c56..000000000
--- a/app/docker/models/secret.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import { ResourceControlViewModel } from '@/react/portainer/access-control/models/ResourceControlViewModel';
-
-export function SecretViewModel(data) {
- this.Id = data.ID;
- this.CreatedAt = data.CreatedAt;
- this.UpdatedAt = data.UpdatedAt;
- this.Version = data.Version.Index;
- this.Name = data.Spec.Name;
- this.Labels = data.Spec.Labels;
-
- if (data.Portainer) {
- if (data.Portainer.ResourceControl) {
- this.ResourceControl = new ResourceControlViewModel(data.Portainer.ResourceControl);
- }
- }
-}
diff --git a/app/docker/models/secret.ts b/app/docker/models/secret.ts
new file mode 100644
index 000000000..8473d8df5
--- /dev/null
+++ b/app/docker/models/secret.ts
@@ -0,0 +1,36 @@
+import { Secret } from 'docker-types/generated/1.41';
+
+import { ResourceControlViewModel } from '@/react/portainer/access-control/models/ResourceControlViewModel';
+import { PortainerMetadata } from '@/react/docker/types';
+import { IResource } from '@/react/docker/components/datatable-helpers/createOwnershipColumn';
+
+export class SecretViewModel implements IResource {
+ Id: string;
+
+ CreatedAt: string;
+
+ UpdatedAt: string;
+
+ Version: number;
+
+ Name: string;
+
+ Labels: Record;
+
+ ResourceControl?: ResourceControlViewModel;
+
+ constructor(data: Secret & { Portainer?: PortainerMetadata }) {
+ this.Id = data.ID || '';
+ this.CreatedAt = data.CreatedAt || '';
+ this.UpdatedAt = data.UpdatedAt || '';
+ this.Version = data.Version?.Index || 0;
+ this.Name = data.Spec?.Name || '';
+ this.Labels = data.Spec?.Labels || {};
+
+ if (data.Portainer?.ResourceControl) {
+ this.ResourceControl = new ResourceControlViewModel(
+ data.Portainer.ResourceControl
+ );
+ }
+ }
+}
diff --git a/app/docker/react/components/index.ts b/app/docker/react/components/index.ts
index d35300f99..f7c6ecbb5 100644
--- a/app/docker/react/components/index.ts
+++ b/app/docker/react/components/index.ts
@@ -22,6 +22,7 @@ import { AgentHostBrowser } from '@/react/docker/host/BrowseView/AgentHostBrowse
import { AgentVolumeBrowser } from '@/react/docker/volumes/BrowseView/AgentVolumeBrowser';
import { ProcessesDatatable } from '@/react/docker/containers/StatsView/ProcessesDatatable';
import { ScaleServiceButton } from '@/react/docker/services/ListView/ServicesDatatable/columns/schedulingMode/ScaleServiceButton';
+import { SecretsDatatable } from '@/react/docker/secrets/ListView/SecretsDatatable';
import { containersModule } from './containers';
@@ -132,6 +133,10 @@ const ngModule = angular
'dockerServicesDatatableScaleServiceButton',
r2a(withUIRouter(withCurrentUser(ScaleServiceButton)), ['service'])
)
- .component('dockerEventsDatatable', r2a(EventsDatatable, ['dataset']));
+ .component('dockerEventsDatatable', r2a(EventsDatatable, ['dataset']))
+ .component(
+ 'dockerSecretsDatatable',
+ r2a(withUIRouter(SecretsDatatable), ['dataset', 'onRefresh', 'onRemove'])
+ );
export const componentsModule = ngModule.name;
diff --git a/app/docker/views/secrets/secrets.html b/app/docker/views/secrets/secrets.html
index 23e0e9175..d286ee28d 100644
--- a/app/docker/views/secrets/secrets.html
+++ b/app/docker/views/secrets/secrets.html
@@ -1,5 +1,7 @@
+
+
();
+
+const columns = [
+ buildNameColumn('Name', 'Id', '.secret'),
+ columnHelper.accessor((item) => isoDate(item.CreatedAt), {
+ header: 'Creation Date',
+ }),
+ createOwnershipColumn(),
+];
+
+interface TableSettings extends BasicTableSettings, RefreshableTableSettings {}
+
+const storageKey = 'docker-secrets';
+const store = createPersistedStore(
+ storageKey,
+ undefined,
+ (set) => ({
+ ...refreshableSettings(set),
+ })
+);
+
+export function SecretsDatatable({
+ dataset,
+ onRemove,
+ onRefresh,
+}: {
+ dataset?: Array;
+ onRemove(items: Array): void;
+ onRefresh(): Promise;
+}) {
+ const tableState = useTableState(store, storageKey);
+ useRepeater(tableState.autoRefreshRate, onRefresh);
+
+ return (
+ (
+
+ )}
+ renderTableSettings={() => (
+
+ tableState.setAutoRefreshRate(value)}
+ />
+
+ )}
+ />
+ );
+}
+
+function TableActions({
+ selectedItems,
+ onRemove,
+}: {
+ selectedItems: Array;
+ onRemove(items: Array): void;
+}) {
+ return (
+
+
+
+
+
+ );
+}