diff --git a/app/portainer/components/datatables/registries-datatable/registriesDatatable.html b/app/portainer/components/datatables/registries-datatable/registriesDatatable.html
index 3f974ea5c..e9f4c07ff 100644
--- a/app/portainer/components/datatables/registries-datatable/registriesDatatable.html
+++ b/app/portainer/components/datatables/registries-datatable/registriesDatatable.html
@@ -77,10 +77,12 @@
- DockerHub (anonymous)
+
+
+
|
+
+
|
- docker.io |
- - |
({
enabled,
@@ -51,3 +52,15 @@ export function useUpdateSettingsMutation() {
)
);
}
+
+export function useUpdateDefaultRegistrySettingsMutation() {
+ const queryClient = useQueryClient();
+
+ return useMutation(
+ (payload: Partial) => updateDefaultRegistry(payload),
+ mutationOptions(
+ withInvalidate(queryClient, [['settings']]),
+ withError('Unable to update default registry settings')
+ )
+ );
+}
diff --git a/app/portainer/settings/settings.service.ts b/app/portainer/settings/settings.service.ts
index a266d8a2d..620c02f02 100644
--- a/app/portainer/settings/settings.service.ts
+++ b/app/portainer/settings/settings.service.ts
@@ -2,7 +2,7 @@ import { PublicSettingsViewModel } from '@/portainer/models/settings';
import axios, { parseAxiosError } from '../services/axios';
-import { PublicSettingsResponse, Settings } from './types';
+import { DefaultRegistry, PublicSettingsResponse, Settings } from './types';
export async function getPublicSettings() {
try {
@@ -38,6 +38,19 @@ export async function updateSettings(settings: Partial) {
}
}
+export async function updateDefaultRegistry(
+ defaultRegistry: Partial
+) {
+ try {
+ await axios.put(buildUrl('default_registry'), defaultRegistry);
+ } catch (e) {
+ throw parseAxiosError(
+ e as Error,
+ 'Unable to update default registry settings'
+ );
+ }
+}
+
function buildUrl(subResource?: string, action?: string) {
let url = 'settings';
if (subResource) {
diff --git a/app/portainer/settings/types.ts b/app/portainer/settings/types.ts
index 3616eb802..d7d54e41b 100644
--- a/app/portainer/settings/types.ts
+++ b/app/portainer/settings/types.ts
@@ -89,6 +89,10 @@ enum AuthenticationMethod {
type Feature = string;
+export interface DefaultRegistry {
+ Hide: boolean;
+}
+
export interface Settings {
LogoURL: string;
BlackListedLabels: Pair[];
diff --git a/app/react/portainer/registries/ListView/DefaultRegistry/DefaultRegistryAction.tsx b/app/react/portainer/registries/ListView/DefaultRegistry/DefaultRegistryAction.tsx
new file mode 100644
index 000000000..3b1c19e75
--- /dev/null
+++ b/app/react/portainer/registries/ListView/DefaultRegistry/DefaultRegistryAction.tsx
@@ -0,0 +1,81 @@
+import {
+ usePublicSettings,
+ useUpdateDefaultRegistrySettingsMutation,
+} from 'Portainer/settings/queries';
+import { notifySuccess } from 'Portainer/services/notifications';
+import { FeatureId } from 'Portainer/feature-flags/enums';
+
+import { isLimitedToBE } from '@/portainer/feature-flags/feature-flags.service';
+
+import { Tooltip } from '@@/Tip/Tooltip';
+import { Button } from '@@/buttons';
+import { Icon } from '@@/Icon';
+import { BEFeatureIndicator } from '@@/BEFeatureIndicator';
+
+export function DefaultRegistryAction() {
+ const settingsQuery = usePublicSettings({
+ select: (settings) => settings.DefaultRegistry?.Hide,
+ });
+ const defaultRegistryMutation = useUpdateDefaultRegistrySettingsMutation();
+
+ if (!settingsQuery.isSuccess) {
+ return null;
+ }
+ const hideDefaultRegistry = settingsQuery.data;
+
+ const isLimited = isLimitedToBE(FeatureId.HIDE_DOCKER_HUB_ANONYMOUS);
+
+ return (
+ <>
+ {!hideDefaultRegistry ? (
+
+
+
+ {isLimited ? null : (
+
+ )}
+
+ ) : (
+
+
+
+
+ )}
+ >
+ );
+
+ function handleShowOrHide(hideDefaultRegistry: boolean) {
+ defaultRegistryMutation.mutate(
+ {
+ Hide: hideDefaultRegistry,
+ },
+ {
+ onSuccess() {
+ notifySuccess(
+ 'Success',
+ 'Default registry Settings updated successfully'
+ );
+ },
+ }
+ );
+ }
+}
diff --git a/app/react/portainer/registries/ListView/DefaultRegistry/DefaultRegistryDomain.tsx b/app/react/portainer/registries/ListView/DefaultRegistry/DefaultRegistryDomain.tsx
new file mode 100644
index 000000000..16af67530
--- /dev/null
+++ b/app/react/portainer/registries/ListView/DefaultRegistry/DefaultRegistryDomain.tsx
@@ -0,0 +1,18 @@
+import clsx from 'clsx';
+import { usePublicSettings } from 'Portainer/settings/queries';
+
+export function DefaultRegistryDomain() {
+ const settingsQuery = usePublicSettings({
+ select: (settings) => settings.DefaultRegistry?.Hide,
+ });
+
+ return (
+
+ docker.io
+
+ );
+}
diff --git a/app/react/portainer/registries/ListView/DefaultRegistry/DefaultRegistryName.tsx b/app/react/portainer/registries/ListView/DefaultRegistry/DefaultRegistryName.tsx
new file mode 100644
index 000000000..7c242cc19
--- /dev/null
+++ b/app/react/portainer/registries/ListView/DefaultRegistry/DefaultRegistryName.tsx
@@ -0,0 +1,18 @@
+import { usePublicSettings } from 'Portainer/settings/queries';
+import clsx from 'clsx';
+
+export function DefaultRegistryName() {
+ const settingsQuery = usePublicSettings({
+ select: (settings) => settings.DefaultRegistry?.Hide,
+ });
+
+ return (
+
+ Docker Hub (anonymous)
+
+ );
+}
diff --git a/app/react/portainer/registries/ListView/DefaultRegistry/index.ts b/app/react/portainer/registries/ListView/DefaultRegistry/index.ts
new file mode 100644
index 000000000..127dd0af1
--- /dev/null
+++ b/app/react/portainer/registries/ListView/DefaultRegistry/index.ts
@@ -0,0 +1,3 @@
+export { DefaultRegistryAction } from './DefaultRegistryAction';
+export { DefaultRegistryDomain } from './DefaultRegistryDomain';
+export { DefaultRegistryName } from './DefaultRegistryName';