),
+}));
+
jest.mock(
'../../pages/Configuration/EditLoginConfiguration/EditLoginConfigurationPage',
() => ({
@@ -540,4 +545,10 @@ describe('SettingsRouter services routes', () => {
expect(await screen.findByText('ServicesPage')).toBeInTheDocument();
expect(screen.queryByText('NotFound')).not.toBeInTheDocument();
});
+
+ it('renders DefaultAppModePage for the preferences app mode route', async () => {
+ renderAt('/settings/preferences/appMode');
+
+ expect(await screen.findByText('DefaultAppModePage')).toBeInTheDocument();
+ });
});
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/SettingsRouter.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/SettingsRouter.tsx
index 5f4d4518dedf..d4ae31d5f7a3 100644
--- a/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/SettingsRouter.tsx
+++ b/openmetadata-ui/src/main/resources/ui/src/components/AppRouter/SettingsRouter.tsx
@@ -77,6 +77,12 @@ const DataAssetRulesPage = withPageSuspenseFallback(
)
);
+const DefaultAppModePage = withPageSuspenseFallback(
+ React.lazy(
+ () => import('../../pages/Settings/DefaultAppModePage/DefaultAppModePage')
+ )
+);
+
const EditLoginConfiguration = withPageSuspenseFallback(
React.lazy(
() =>
@@ -931,6 +937,17 @@ const SettingsRouter = () => {
GlobalSettingOptions.LEARNING_RESOURCES
)}
/>
+
+
+
+ }
+ path={getSettingPathRelative(
+ GlobalSettingsMenuCategory.PREFERENCES,
+ GlobalSettingOptions.APP_MODE
+ )}
+ />
}
path={getSettingPathRelative(GlobalSettingsMenuCategory.SSO)}
diff --git a/openmetadata-ui/src/main/resources/ui/src/constants/GlobalSettings.constants.ts b/openmetadata-ui/src/main/resources/ui/src/constants/GlobalSettings.constants.ts
index 135f3377f0c1..3c33e9b3f5ac 100644
--- a/openmetadata-ui/src/main/resources/ui/src/constants/GlobalSettings.constants.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/constants/GlobalSettings.constants.ts
@@ -105,4 +105,5 @@ export enum GlobalSettingOptions {
WORKFLOW_DEFINITIONS = 'workflow-definitions',
LEARNING_RESOURCES = 'learning-resources',
COLUMN = 'column',
+ APP_MODE = 'appMode',
}
diff --git a/openmetadata-ui/src/main/resources/ui/src/hooks/useAppRoutesRegistry.test.ts b/openmetadata-ui/src/main/resources/ui/src/hooks/useAppRoutesRegistry.test.ts
index d5622fa3ade0..c040e4e75bd0 100644
--- a/openmetadata-ui/src/main/resources/ui/src/hooks/useAppRoutesRegistry.test.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/hooks/useAppRoutesRegistry.test.ts
@@ -12,6 +12,7 @@
*/
import { act, ComponentType } from 'react';
+import { DEFAULT_APP_MODE } from '../constants/appMode.constants';
import { useAppRoutesRegistry } from './useAppRoutesRegistry';
const FakeRoutes: ComponentType = () => null;
@@ -87,3 +88,47 @@ describe('useAppRoutesRegistry', () => {
expect(useAppRoutesRegistry.getState().routes).toBe(before);
});
});
+
+describe('metadata', () => {
+ const Component = () => null;
+
+ beforeEach(() => {
+ useAppRoutesRegistry.setState({ routes: {}, metadata: {} });
+ });
+
+ it('registerRoutes stores explicit metadata', () => {
+ useAppRoutesRegistry.getState().registerRoutes('ai', Component, {
+ labelKey: 'label.ai',
+ });
+
+ expect(useAppRoutesRegistry.getState().metadata.ai).toEqual({
+ labelKey: 'label.ai',
+ });
+ });
+
+ it('registerRoutes falls back to the mode-keyed default when metadata omitted', () => {
+ useAppRoutesRegistry.getState().registerRoutes(DEFAULT_APP_MODE, Component);
+
+ expect(useAppRoutesRegistry.getState().metadata[DEFAULT_APP_MODE]).toEqual({
+ labelKey: 'label.default',
+ });
+ });
+
+ it('registerRoutes falls back to a generic metadata for unknown modes when metadata omitted', () => {
+ useAppRoutesRegistry.getState().registerRoutes('custom-mode', Component);
+
+ expect(useAppRoutesRegistry.getState().metadata['custom-mode']).toEqual({
+ labelKey: 'label.app-mode',
+ });
+ });
+
+ it('unregisterRoutes removes both routes and metadata', () => {
+ useAppRoutesRegistry.getState().registerRoutes('ai', Component, {
+ labelKey: 'label.ai',
+ });
+ useAppRoutesRegistry.getState().unregisterRoutes('ai');
+
+ expect(useAppRoutesRegistry.getState().routes.ai).toBeUndefined();
+ expect(useAppRoutesRegistry.getState().metadata.ai).toBeUndefined();
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/hooks/useAppRoutesRegistry.ts b/openmetadata-ui/src/main/resources/ui/src/hooks/useAppRoutesRegistry.ts
index 8ba3f0c324f7..acd2ad12ff94 100644
--- a/openmetadata-ui/src/main/resources/ui/src/hooks/useAppRoutesRegistry.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/hooks/useAppRoutesRegistry.ts
@@ -13,6 +13,7 @@
import { ComponentType } from 'react';
import { create } from 'zustand';
+import { AI_APP_MODE, DEFAULT_APP_MODE } from '../constants/appMode.constants';
/**
* Runtime registry of authenticated-routes components keyed by AppMode.
@@ -31,9 +32,21 @@ import { create } from 'zustand';
* fallback that runs whenever no other mode is active or registered.
*/
+export interface AppModeMetadata {
+ /** i18n key for the human-readable label. */
+ labelKey: string;
+ /** Optional SVG component for pickers. */
+ icon?: React.ComponentType>;
+}
+
interface AppRoutesRegistryStore {
routes: Record;
- registerRoutes: (mode: string, component: ComponentType) => void;
+ metadata: Record;
+ registerRoutes: (
+ mode: string,
+ component: ComponentType,
+ metadata?: AppModeMetadata
+ ) => void;
/**
* Remove a previously-registered mode. Use when the source plugin
* becomes unavailable mid-session (e.g., admin uninstalls the app)
@@ -44,18 +57,36 @@ interface AppRoutesRegistryStore {
unregisterRoutes: (mode: string) => void;
}
+// Fallback so callers that predate the metadata arg still yield a
+// sensible label. Explicit metadata always wins.
+const FALLBACK_METADATA: Record = {
+ [DEFAULT_APP_MODE]: { labelKey: 'label.default' },
+ [AI_APP_MODE]: { labelKey: 'label.ai' },
+};
+
+const GENERIC_METADATA: AppModeMetadata = { labelKey: 'label.app-mode' };
+
export const useAppRoutesRegistry = create((set) => ({
routes: {},
- registerRoutes: (mode, component) =>
- set((state) => ({ routes: { ...state.routes, [mode]: component } })),
+ metadata: {},
+ registerRoutes: (mode, component, metadata) =>
+ set((state) => ({
+ routes: { ...state.routes, [mode]: component },
+ metadata: {
+ ...state.metadata,
+ [mode]: metadata ?? FALLBACK_METADATA[mode] ?? GENERIC_METADATA,
+ },
+ })),
unregisterRoutes: (mode) =>
set((state) => {
- if (!(mode in state.routes)) {
+ if (!(mode in state.routes) && !(mode in state.metadata)) {
return state;
}
- const next = { ...state.routes };
- delete next[mode];
+ const nextRoutes = { ...state.routes };
+ delete nextRoutes[mode];
+ const nextMetadata = { ...state.metadata };
+ delete nextMetadata[mode];
- return { routes: next };
+ return { routes: nextRoutes, metadata: nextMetadata };
}),
}));
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ar-sa.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ar-sa.json
index 5237f0850d62..3998df61afc8 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ar-sa.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ar-sa.json
@@ -715,6 +715,7 @@
"december": "ديسمبر",
"decision": "قرار",
"default": "افتراضي",
+ "default-app-mode": "وضع التطبيق الافتراضي",
"default-persona": "شخصية افتراضية",
"default-role": "دور افتراضي",
"define-it": "حدّده",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "لا توجد منتجات بيانات بعد",
"no-data-products-yet-description": "أنشئ أول منتج بيانات لجعل مجموعات البيانات الموثوقة متاحة للاكتشاف والوصول.",
"no-description": "لا يوجد وصف",
+ "no-default": "لا يوجد افتراضي",
"no-diff-available": "لا يوجد فرق متاح",
"no-dimension": "لا بُعد",
"no-domains-yet": "لا توجد نطاقات بعد",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "مسار ملف نتائج تشغيل dbt لاستخراج معلومات نتائج الاختبار.",
"dbt-run-result-http-path-message": "يقوم dbt بتشغيل النتائج على مسار http لاستخراج نتائج الاختبار.",
"deeply-understand-table-relations-message": "احصل على منتجي ومستهلكي البيانات في منصة واحدة وقم بتسريع الإنتاجية. يصبح التعاون أفضل مع الأشخاص والبيانات من أدوات متعددة في موقع مركزي.",
+ "default-app-mode-description": "وضع «الانطباع الأول» للمستخدمين الذين لم يختاروا وضعًا بعد. لا تزال تفضيلات المستخدم وأوضاع التطبيق على مستوى الشخصية تتفوق على هذا الوضع الافتراضي.",
"default-persona-removed-successfully": "تمت إزالة الشخصية الافتراضية بنجاح.",
"default-persona-set-successfully": "تم تعيين الشخصية الافتراضية بنجاح.",
"default-persona-update-error": "فشل تحديث الشخصية الافتراضية. الرجاء المحاولة مرة أخرى.",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "نحو {{formattedCount}} رمزًا",
"persona-context-truncated-count": "تم اقتطاع {{count}}",
"persona-context-version-restored": "تمت استعادة سياق الذكاء الاصطناعي إلى الإصدار v{{version}}",
+ "persona-default-app-mode-description": "وضع التطبيق الذي ينتقل إليه مستخدمو هذه الشخصية عندما لا يختارون وضعهم الافتراضي الخاص بهم. لا تزال تفضيلات المستخدم تتفوق على هذا الإعداد.",
"persona-preference-updated": "تم تحديث تفضيل الشخصية بنجاح!",
"persona-updated-successfully": "تم تحديث الشخصية بنجاح.",
"personal-access-token": "رمز الوصول الشخصي المميز",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json
index f7748cb9b56c..e751b16e3c66 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json
@@ -715,6 +715,7 @@
"december": "Dezember",
"decision": "Entscheidung",
"default": "Standard",
+ "default-app-mode": "Standard-App-Modus",
"default-persona": "Standard-Persona",
"default-role": "Standardrolle",
"define-it": "Definieren",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "Noch keine Datenprodukte",
"no-data-products-yet-description": "Erstellen Sie Ihr erstes Datenprodukt, um vertrauenswürdige Datensätze für Entdeckung und Zugriff verfügbar zu machen.",
"no-description": "Keine Beschreibung",
+ "no-default": "Kein Standard",
"no-diff-available": "Keine Unterschiede verfügbar",
"no-dimension": "Keine Dimension",
"no-domains-yet": "Noch keine Domänen",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": " Pfad zu den Ergebnisdateien von dbt-Runs, um Informationen zu den Testergebnissen zu extrahieren.",
"dbt-run-result-http-path-message": "dbt führt die Ergebnisse auf einem HTTP-Pfad aus, um die Testergebnisse zu extrahieren.",
"deeply-understand-table-relations-message": "Erhalten Sie die Produzenten und Verbraucher von Daten auf einer einzigen Plattform und steigern Sie die Produktivität. Die Zusammenarbeit wird besser mit Menschen und Daten aus verschiedenen Tools an zentraler Stelle.",
+ "default-app-mode-description": "Der 'erste Eindruck'-Modus für Nutzer, die noch keinen ausgewählt haben. Benutzereinstellungen und Persona-spezifische App-Modi haben weiterhin Vorrang vor dieser Standardeinstellung.",
"default-persona-removed-successfully": "Standard-Persona wurde erfolgreich entfernt.",
"default-persona-set-successfully": "Standard-Persona wurde erfolgreich gesetzt.",
"default-persona-update-error": "Fehler beim Aktualisieren der Standard-Persona. Bitte versuchen Sie es erneut.",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "~{{formattedCount}} Tokens",
"persona-context-truncated-count": "{{count}} gekürzt",
"persona-context-version-restored": "KI-Kontext auf v{{version}} wiederhergestellt",
+ "persona-default-app-mode-description": "Legt fest, in welchem Anwendungsmodus Nutzer dieser Persona landen, wenn sie keinen eigenen Standard gewählt haben. Benutzereinstellungen haben weiterhin Vorrang vor dieser Einstellung.",
"persona-preference-updated": "Persona-Einstellung erfolgreich aktualisiert!",
"persona-updated-successfully": "Persona erfolgreich aktualisiert.",
"personal-access-token": "Persönlicher Zugriffstoken",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json
index 1c7a9d10f1cd..34edec4321f1 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json
@@ -715,6 +715,7 @@
"december": "December",
"decision": "Decision",
"default": "Default",
+ "default-app-mode": "Default App Mode",
"default-persona": "Default Persona",
"default-role": "Default Role",
"define-it": "Define it",
@@ -1693,6 +1694,7 @@
"no-data-found": "No data found",
"no-data-products-yet": "No Data Products Yet",
"no-data-products-yet-description": "Create your first data product to make trusted datasets available for discovery and access.",
+ "no-default": "No default",
"no-description": "No description",
"no-diff-available": "No diff available",
"no-dimension": "No Dimension",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "dbt run results file path to extract the test results information.",
"dbt-run-result-http-path-message": "dbt runs the results on an http path to extract the test results.",
"deeply-understand-table-relations-message": "Get the Producers and Consumers of data in a single platform and accelerate productivity. Collaboration just gets better with people and data from multiple tools in a centralized location.",
+ "default-app-mode-description": "The 'first impression' mode for users who haven't picked one. User preferences and persona-level app modes still win over this default.",
"default-persona-removed-successfully": "Default persona has been removed successfully.",
"default-persona-set-successfully": "Default persona has been set successfully.",
"default-persona-update-error": "Failed to update default persona. Please try again.",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "~{{formattedCount}} tokens",
"persona-context-truncated-count": "{{count}} truncated",
"persona-context-version-restored": "AI context restored to v{{version}}",
+ "persona-default-app-mode-description": "Which application mode users in this Persona land in when they haven't chosen their own default. User preferences still win over this setting.",
"persona-preference-updated": "Persona preference updated successfully!",
"persona-updated-successfully": "Persona updated successfully.",
"personal-access-token": "Personal Access Token",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json
index f09fe6befb29..afff9ee727ae 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json
@@ -715,6 +715,7 @@
"december": "Diciembre",
"decision": "Decisión",
"default": "Por defecto",
+ "default-app-mode": "Modo de aplicación predeterminado",
"default-persona": "Persona por defecto",
"default-role": "Rol por defecto",
"define-it": "Defínela",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "Aún no hay productos de datos",
"no-data-products-yet-description": "Crea tu primer producto de datos para que los conjuntos de datos confiables estén disponibles para su descubrimiento y acceso.",
"no-description": "Sin descripción",
+ "no-default": "Sin predeterminado",
"no-diff-available": "Sin diferencia disponible",
"no-dimension": "Sin dimensión",
"no-domains-yet": "Aún no hay dominios",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "Ruta del archivo de resultados de ejecución de dbt para extraer la información de los resultados de prueba.",
"dbt-run-result-http-path-message": "dbt ejecuta los resultados en una ruta http para extraer los resultados de prueba.",
"deeply-understand-table-relations-message": "Comprenda profundamente las relaciones de tabla; gracias al linaje a nivel de columna.",
+ "default-app-mode-description": "El modo de «primera impresión» para los usuarios que no han elegido uno. Las preferencias del usuario y los modos de aplicación a nivel de persona siguen prevaleciendo sobre este valor predeterminado.",
"default-persona-removed-successfully": "La persona predeterminada se ha eliminado correctamente.",
"default-persona-set-successfully": "La persona predeterminada se ha establecido correctamente.",
"default-persona-update-error": "Error al actualizar la persona predeterminada. Inténtelo de nuevo.",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "~{{formattedCount}} tokens",
"persona-context-truncated-count": "{{count}} truncados",
"persona-context-version-restored": "Contexto de IA restaurado a v{{version}}",
+ "persona-default-app-mode-description": "El modo de aplicación en el que aterrizan los usuarios de esta Persona cuando no han elegido su propio valor predeterminado. Las preferencias del usuario siguen prevaleciendo sobre esta configuración.",
"persona-preference-updated": "Preferencia de persona actualizada exitosamente!",
"persona-updated-successfully": "Persona actualizada exitosamente.",
"personal-access-token": "Token de Acceso Personal",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json
index 71f8427be54c..ffd98259ba6a 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json
@@ -715,6 +715,7 @@
"december": "Décembre",
"decision": "Décision",
"default": "Défaut",
+ "default-app-mode": "Mode d'application par défaut",
"default-persona": "Persona par Défaut",
"default-role": "Rôle par Défaut",
"define-it": "Définissez-la",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "Aucun Produit de Données pour le moment",
"no-data-products-yet-description": "Créez votre premier produit de données pour rendre des jeux de données fiables disponibles à la découverte et à l'accès.",
"no-description": "Aucune description",
+ "no-default": "Aucun par défaut",
"no-diff-available": "Aucune différence disponible",
"no-dimension": "Aucune dimension",
"no-domains-yet": "Aucun domaine pour le moment",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "chemin du fichier run results de dbt pour extraire les informations des résultats de test.",
"dbt-run-result-http-path-message": "chemin HTTP du fichier run results dbt pour extraire les résultats de test.",
"deeply-understand-table-relations-message": "Comprenez en profondeur la relation entre vos tables avec la traçabilité au niveau de la colonne.",
+ "default-app-mode-description": "Le mode de « première impression » pour les utilisateurs qui n'en ont pas choisi. Les préférences utilisateur et les modes d'application au niveau de la persona restent prioritaires sur ce mode par défaut.",
"default-persona-removed-successfully": "La persona par défaut a été supprimée avec succès.",
"default-persona-set-successfully": "La persona par défaut a été définie avec succès.",
"default-persona-update-error": "Échec de la mise à jour de la persona par défaut. Veuillez réessayer.",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "~{{formattedCount}} jetons",
"persona-context-truncated-count": "{{count}} tronqués",
"persona-context-version-restored": "Contexte IA restauré à la v{{version}}",
+ "persona-default-app-mode-description": "Le mode d'application dans lequel arrivent les utilisateurs de cette Persona lorsqu'ils n'ont pas choisi leur propre valeur par défaut. Les préférences utilisateur restent prioritaires sur ce paramètre.",
"persona-preference-updated": "Préférence de persona mise à jour avec succès!",
"persona-updated-successfully": "Persona mise à jour avec succès.",
"personal-access-token": "Jeton d'Accès Personnel (PAT)",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/gl-es.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/gl-es.json
index ace9ea696227..16d98815b51a 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/gl-es.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/gl-es.json
@@ -715,6 +715,7 @@
"december": "Decembro",
"decision": "Decisión",
"default": "Predeterminado",
+ "default-app-mode": "Modo de aplicación predeterminado",
"default-persona": "Persoa predeterminada",
"default-role": "Rol Predeterminado",
"define-it": "Defínea",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "Aínda non hai produtos de datos",
"no-data-products-yet-description": "Crea o teu primeiro produto de datos para que os conxuntos de datos fiables estean dispoñibles para o seu descubrimento e acceso.",
"no-description": "Sen descrición",
+ "no-default": "Sen predeterminado",
"no-diff-available": "Non hai diferenzas dispoñibles",
"no-dimension": "Sen dimensión",
"no-domains-yet": "Aínda non hai dominios",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "Ruta do ficheiro de resultados dbt para extraer a información dos resultados das probas.",
"dbt-run-result-http-path-message": "dbt executa os resultados nunha ruta http para extraer a información dos resultados das probas.",
"deeply-understand-table-relations-message": "Obtén aos Produtores e Consumidores de datos nunha única plataforma e acelera a produtividade. A colaboración mellora cando persoas e datos de múltiples ferramentas están centralizados nun único lugar.",
+ "default-app-mode-description": "O modo de «primeira impresión» para os usuarios que aínda non elixiron un. As preferencias do usuario e os modos de aplicación a nivel de persona seguen prevalecendo sobre este valor predeterminado.",
"default-persona-removed-successfully": "A persona predeterminada elimináronse correctamente.",
"default-persona-set-successfully": "A persona predeterminada establecéronse correctamente.",
"default-persona-update-error": "Erro ao actualizar a persona predeterminada. Téntao de novo.",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "~{{formattedCount}} tokens",
"persona-context-truncated-count": "{{count}} truncados",
"persona-context-version-restored": "Contexto de IA restaurado á v{{version}}",
+ "persona-default-app-mode-description": "O modo de aplicación no que aterran os usuarios desta Persona cando non escolleron o seu propio valor predeterminado. As preferencias do usuario seguen prevalecendo sobre esta configuración.",
"persona-preference-updated": "Preferencia de persona actualizada correctamente!",
"persona-updated-successfully": "Persona actualizada correctamente.",
"personal-access-token": "Token de Acceso Persoal",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json
index 57e9d5b93c61..38db4d5320c0 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json
@@ -715,6 +715,7 @@
"december": "דצמבר",
"decision": "החלטה",
"default": "ברירת מחדל",
+ "default-app-mode": "מצב אפליקציה ברירת מחדל",
"default-persona": "פרסונה ברירת מחדל",
"default-role": "תפקיד ברירת מחדל",
"define-it": "הגדירו אותו",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "אין עדיין מוצרי נתונים",
"no-data-products-yet-description": "צור את מוצר הנתונים הראשון שלך כדי להנגיש מערכי נתונים מהימנים לגילוי ולגישה.",
"no-description": "-",
+ "no-default": "אין ברירת מחדל",
"no-diff-available": "אין הבדל זמין",
"no-dimension": "אין מימד",
"no-domains-yet": "עדיין אין דומיינים",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "נתיב קובץ תוצאות dbt run לחשיפת מידע על תוצאות הבדיקה.",
"dbt-run-result-http-path-message": "תוצאות dbt run בנתיב http לחשיפת מידע על תוצאות הבדיקה.",
"deeply-understand-table-relations-message": "קבל את המפיקים והצרכנים של נתונים בפלטפורמה אחת והאצה את הפרודוקטיביות. השתפר ביכולת לשתף פעולה עם אנשים ונתונים מכלים מרובים במקום מרכזי.",
+ "default-app-mode-description": "מצב ה\"רושם הראשוני\" למשתמשים שלא בחרו מצב משלהם. העדפות המשתמש ומצבי האפליקציה בהתאם לפרסונה עדיין גוברים על ברירת המחדל הזו.",
"default-persona-removed-successfully": "פרסונה ברירת המחדל הוסרה בהצלחה.",
"default-persona-set-successfully": "פרסונה ברירת המחדל הוגדרה בהצלחה.",
"default-persona-update-error": "נכשל לעדכן פרסונה ברירת מחדל. אנא נסה שוב.",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "כ־{{formattedCount}} אסימונים",
"persona-context-truncated-count": "{{count}} קוצרו",
"persona-context-version-restored": "הקשר ה-AI שוחזר לגרסה v{{version}}",
+ "persona-default-app-mode-description": "מצב האפליקציה שאליו מגיעים משתמשי הפרסונה הזו כאשר לא בחרו ברירת מחדל משלהם. העדפות המשתמש עדיין גוברות על הגדרה זו.",
"persona-preference-updated": "העדפת אישיות עודכנה בהצלחה!",
"persona-updated-successfully": "Persona עודכנה בהצלחה.",
"personal-access-token": "אסימון גישה אישי",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json
index ea6fcaf1e0b8..3cf29d36440d 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json
@@ -715,6 +715,7 @@
"december": "12月",
"decision": "判断",
"default": "デフォルト",
+ "default-app-mode": "デフォルトのアプリモード",
"default-persona": "デフォルトペルソナ",
"default-role": "デフォルトロール",
"define-it": "定義する",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "データ製品はまだありません",
"no-data-products-yet-description": "最初のデータプロダクトを作成して、信頼できるデータセットを検出とアクセスに利用できるようにしましょう。",
"no-description": "説明なし",
+ "no-default": "デフォルトなし",
"no-diff-available": "差分はありません",
"no-dimension": "ディメンションなし",
"no-domains-yet": "ドメインはまだありません",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "dbt 実行結果ファイルのパス(テスト結果の取得に使用)",
"dbt-run-result-http-path-message": "dbt がテスト結果を取得する HTTP パスで実行されます。",
"deeply-understand-table-relations-message": "カラムレベルのリネージによって、テーブル間の関係をより深く理解できます。",
+ "default-app-mode-description": "まだ選択していないユーザー向けの「最初の印象」となるモードです。ユーザーの設定やペルソナ単位のアプリモードは、このデフォルト設定より優先されます。",
"default-persona-removed-successfully": "デフォルトペルソナが正常に削除されました。",
"default-persona-set-successfully": "デフォルトペルソナが正常に設定されました。",
"default-persona-update-error": "デフォルトペルソナの更新に失敗しました。再試行してください。",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "約 {{formattedCount}} トークン",
"persona-context-truncated-count": "{{count}} 件省略",
"persona-context-version-restored": "AI コンテキストを v{{version}} に復元しました",
+ "persona-default-app-mode-description": "このペルソナのユーザーが自分のデフォルトを選択していない場合に入るアプリケーションモードです。ユーザーの設定はこの設定よりも優先されます。",
"persona-preference-updated": "ペルソナ設定が正常に更新されました!",
"persona-updated-successfully": "Persona が正常に更新されました。",
"personal-access-token": "パーソナルアクセストークン",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ko-kr.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ko-kr.json
index a30afb32e3d7..1c0c8cf9f228 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ko-kr.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ko-kr.json
@@ -715,6 +715,7 @@
"december": "12월",
"decision": "결정",
"default": "기본값",
+ "default-app-mode": "기본 앱 모드",
"default-persona": "기본 페르소나",
"default-role": "기본 역할",
"define-it": "정의하기",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "아직 데이터 제품이 없습니다.",
"no-data-products-yet-description": "첫 번째 데이터 제품을 만들어 신뢰할 수 있는 데이터셋을 검색하고 액세스할 수 있도록 하세요.",
"no-description": "설명 없음",
+ "no-default": "기본 없음",
"no-diff-available": "차이점을 찾을 수 없습니다",
"no-dimension": "차원 없음",
"no-domains-yet": "아직 도메인이 없습니다",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "테스트 결과 정보를 추출하기 위한 dbt 실행 결과 파일 경로입니다.",
"dbt-run-result-http-path-message": "dbt는 테스트 결과를 추출하기 위해 http 경로에서 결과를 실행합니다.",
"deeply-understand-table-relations-message": "단일 플랫폼에서 데이터의 생산자와 소비자를 파악하고 생산성을 향상시키세요. 중앙 집중식 위치에서 여러 도구의 사람들과 데이터로 협업이 더욱 좋아집니다.",
+ "default-app-mode-description": "아직 모드를 선택하지 않은 사용자를 위한 '첫인상' 모드입니다. 사용자 환경설정과 페르소나 수준의 앱 모드가 이 기본값보다 우선합니다.",
"default-persona-removed-successfully": "기본 페르소나가 성공적으로 제거되었습니다.",
"default-persona-set-successfully": "기본 페르소나가 성공적으로 설정되었습니다.",
"default-persona-update-error": "기본 페르소나 업데이트에 실패했습니다. 다시 시도해 주세요.",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "약 {{formattedCount}}토큰",
"persona-context-truncated-count": "{{count}}개 잘림",
"persona-context-version-restored": "AI 컨텍스트가 v{{version}}(으)로 복원됨",
+ "persona-default-app-mode-description": "이 페르소나의 사용자가 자신의 기본값을 선택하지 않았을 때 진입하는 애플리케이션 모드입니다. 사용자 환경설정이 이 설정보다 우선합니다.",
"persona-preference-updated": "페르소나 설정이 성공적으로 업데이트되었습니다!",
"persona-updated-successfully": "Persona가 성공적으로 업데이트되었습니다.",
"personal-access-token": "개인 접근 토큰",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/mr-in.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/mr-in.json
index ecfe5e7dc7ae..2c21ad6973cd 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/mr-in.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/mr-in.json
@@ -715,6 +715,7 @@
"december": "डिसेंबर",
"decision": "निर्णय",
"default": "मूलभूत",
+ "default-app-mode": "मूलभूत अॅप मोड",
"default-persona": "मूलभूत व्यक्तिमत्व",
"default-role": "डीफॉल्ट भूमिका",
"define-it": "ते परिभाषित करा",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "अद्याप डेटा उत्पादने नाहीत",
"no-data-products-yet-description": "शोध आणि प्रवेशासाठी विश्वासार्ह डेटासेट उपलब्ध करण्यासाठी तुमचे पहिले डेटा उत्पादन तयार करा.",
"no-description": "वर्णन नाही",
+ "no-default": "कोणताही मूलभूत नाही",
"no-diff-available": "कोणताही फरक उपलब्ध नाही",
"no-dimension": "कोणतेही परिमाण नाही",
"no-domains-yet": "अद्याप कोणतेही डोमेन नाहीत",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "चाचणी परिणाम माहिती काढण्यासाठी dbt रन परिणाम फाइल पथ.",
"dbt-run-result-http-path-message": "चाचणी परिणाम काढण्यासाठी dbt परिणाम http पथ चालवतो.",
"deeply-understand-table-relations-message": "डेटा उत्पादक आणि ग्राहकांना एका प्लॅटफॉर्मवर मिळवा आणि उत्पादकता वाढवा. एक केंद्रीकृत ठिकाणी एकाधिक साधनांमधील लोक आणि डेटासह सहयोग फक्त चांगले होते.",
+ "default-app-mode-description": "जे वापरकर्ते अद्याप मोड निवडलेले नाहीत त्यांच्यासाठी \"पहिली छाप\" मोड. वापरकर्ता प्राधान्ये आणि व्यक्तिमत्व-स्तरीय अॅप मोड अजूनही या मूलभूत सेटिंगपेक्षा वरचढ असतात.",
"default-persona-removed-successfully": "डीफॉल्ट व्यक्तिमत्व यशस्वीरित्या काढले गेले.",
"default-persona-set-successfully": "डीफॉल्ट व्यक्तिमत्व यशस्वीरित्या सेट केले गेले.",
"default-persona-update-error": "डीफॉल्ट व्यक्तिमत्व अपडेट करण्यात अयशस्वी. कृपया पुन्हा प्रयत्न करा.",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "सुमारे {{formattedCount}} टोकन",
"persona-context-truncated-count": "{{count}} संक्षिप्त",
"persona-context-version-restored": "AI संदर्भ v{{version}} वर पुनर्संचयित केला",
+ "persona-default-app-mode-description": "जेव्हा या व्यक्तिमत्वातील वापरकर्त्यांनी स्वतःचा मूलभूत मोड निवडलेला नसतो, तेव्हा ते कोणत्या अॅप्लिकेशन मोडमध्ये येतात हे ठरवते. वापरकर्ता प्राधान्ये अजूनही या सेटिंगपेक्षा वरचढ असतात.",
"persona-preference-updated": "व्यक्तिमत्व प्राधान्य यशस्वीरित्या अद्ययावत केले!",
"persona-updated-successfully": "Persona यशस्वीरित्या अद्ययावत केले.",
"personal-access-token": "वैयक्तिक प्रवेश टोकन",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json
index 5a2df65eb658..b0eead1a4bae 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json
@@ -715,6 +715,7 @@
"december": "december",
"decision": "Beslissing",
"default": "Standaard",
+ "default-app-mode": "Standaard app-modus",
"default-persona": "Standaardpersona",
"default-role": "Standaard rol",
"define-it": "Definieer het",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "Nog geen dataproducten",
"no-data-products-yet-description": "Maak uw eerste dataproduct om vertrouwde datasets beschikbaar te maken voor ontdekking en toegang.",
"no-description": "Geen beschrijving",
+ "no-default": "Geen standaard",
"no-diff-available": "Geen verschil beschikbaar",
"no-dimension": "Geen dimensie",
"no-domains-yet": "Nog geen domeinen",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "Pad naar dbt-uitvoerresultatenbestand om informatie over testresultaten te extraheren.",
"dbt-run-result-http-path-message": "dbt voert de resultaten uit op een http-pad om de testresultaten te extraheren.",
"deeply-understand-table-relations-message": "Begrijp de producenten en consumenten van data op één platform en versnel productiviteit. Samenwerking wordt alleen maar beter met mensen en data van meerdere tools op één centrale locatie.",
+ "default-app-mode-description": "De 'eerste indruk'-modus voor gebruikers die nog geen modus hebben gekozen. Gebruikersvoorkeuren en persona-specifieke app-modi hebben nog steeds voorrang boven deze standaardinstelling.",
"default-persona-removed-successfully": "Standaard persona is succesvol verwijderd.",
"default-persona-set-successfully": "Standaard persona is succesvol ingesteld.",
"default-persona-update-error": "Fout bij het bijwerken van standaard persona. Probeer opnieuw.",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "~{{formattedCount}} tokens",
"persona-context-truncated-count": "{{count}} afgekapt",
"persona-context-version-restored": "AI-context hersteld naar v{{version}}",
+ "persona-default-app-mode-description": "De applicatiemodus waarin gebruikers van deze Persona terechtkomen wanneer ze geen eigen standaard hebben gekozen. Gebruikersvoorkeuren hebben nog steeds voorrang boven deze instelling.",
"persona-preference-updated": "Persoonlijkheidsvoorkeur succesvol bijgewerkt!",
"persona-updated-successfully": "Persona succesvol bijgewerkt.",
"personal-access-token": "Persoonlijke toegangstoken",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pr-pr.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pr-pr.json
index bcf53aac26fb..6649c7e4b878 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pr-pr.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pr-pr.json
@@ -715,6 +715,7 @@
"december": "دسامبر",
"decision": "تصمیم",
"default": "پیشفرض",
+ "default-app-mode": "حالت برنامه پیشفرض",
"default-persona": "شخصیت پیشفرض",
"default-role": "نقش پیشفرض",
"define-it": "آن را تعریف کنید",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "هنوز محصول دادهای وجود ندارد",
"no-data-products-yet-description": "اولین محصول داده خود را بسازید تا مجموعهدادههای معتبر برای کشف و دسترسی در دسترس قرار گیرند.",
"no-description": "بدون توضیح",
+ "no-default": "بدون پیشفرض",
"no-diff-available": "هیچ تفاوتی موجود نیست",
"no-dimension": "بدون بعد",
"no-domains-yet": "هنوز هیچ دامنهای وجود ندارد",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "مسیر فایل نتایج اجرای dbt برای استخراج اطلاعات نتایج تست.",
"dbt-run-result-http-path-message": "dbt نتایج را در یک مسیر http اجرا میکند تا نتایج تست را استخراج کند.",
"deeply-understand-table-relations-message": "پروducers و مصرفکنندگان داده را در یک پلتفرم واحد دریافت کنید و بهرهوری را تسریع کنید. همکاری با افراد و دادهها از ابزارهای مختلف در یک مکان متمرکز بهبود مییابد.",
+ "default-app-mode-description": "حالت «اولین برداشت» برای کاربرانی که هنوز حالتی انتخاب نکردهاند. تنظیمات کاربر و حالتهای برنامه در سطح پرسونا همچنان بر این حالت پیشفرض اولویت دارند.",
"default-persona-removed-successfully": "ਡਿਫਾਲਟ ਸ਼ਖਸੀਅਤ ਸਫਲਤਾਪੂਰਵਕ ਹਟਾ ਦਿੱਤੀ ਗਈ.",
"default-persona-set-successfully": "ਡਿਫਾਲਟ ਸ਼ਖਸੀਅਤ ਸਫਲਤਾਪੂਰਵਕ ਸੈੱਟ ਕਰ ਦਿੱਤੀ ਗਈ.",
"default-persona-update-error": "ਡਿਫਾਲਟ ਸ਼ਖਸੀਅਤ ਨੂੰ ਅਪਡੇਟ ਕਰਨ ਵਿੱਚ ਅਸਫਲ. ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ.",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "حدود {{formattedCount}} توکن",
"persona-context-truncated-count": "{{count}} مورد کوتاه شد",
"persona-context-version-restored": "زمینه هوش مصنوعی به نسخه v{{version}} بازیابی شد",
+ "persona-default-app-mode-description": "حالت برنامهای که کاربران این پرسونا در صورتیکه پیشفرض خود را انتخاب نکرده باشند وارد آن میشوند. تنظیمات کاربر همچنان بر این تنظیم اولویت دارد.",
"persona-preference-updated": "ترجیح شخصیت با موفقیت بهروزرسانی شد!",
"persona-updated-successfully": "Persona با موفقیت بهروزرسانی شد.",
"personal-access-token": "توکن دسترسی شخصی.",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json
index 8ef4ce6dbafe..ffe41a8c1ae3 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json
@@ -715,6 +715,7 @@
"december": "Dezembro",
"decision": "Decisão",
"default": "Padrão",
+ "default-app-mode": "Modo do aplicativo padrão",
"default-persona": "Perfil Padrão",
"default-role": "Função Padrão",
"define-it": "Defina-a",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "Ainda não há produtos de dados",
"no-data-products-yet-description": "Crie seu primeiro produto de dados para disponibilizar conjuntos de dados confiáveis para descoberta e acesso.",
"no-description": "Sem descrição",
+ "no-default": "Sem padrão",
"no-diff-available": "Nenhuma diferença disponível",
"no-dimension": "Sem dimensão",
"no-domains-yet": "Ainda não há domínios",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "Caminho do arquivo de resultados da execução dbt para extrair as informações dos resultados dos testes.",
"dbt-run-result-http-path-message": "dbt executa os resultados em um caminho http para extrair as informações dos resultados dos testes.",
"deeply-understand-table-relations-message": "Obtenha os Produtores e Consumidores de dados em uma única plataforma e acelere a produtividade. A colaboração fica ainda melhor com pessoas e dados de múltiplas ferramentas em um local centralizado.",
+ "default-app-mode-description": "O modo de \"primeira impressão\" para usuários que ainda não escolheram um. As preferências do usuário e os modos de aplicativo definidos por persona ainda têm prioridade sobre este padrão.",
"default-persona-removed-successfully": "Persona padrão foi removida com sucesso.",
"default-persona-set-successfully": "Persona padrão foi definida com sucesso.",
"default-persona-update-error": "Falha ao atualizar persona padrão. Tente novamente.",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "~{{formattedCount}} tokens",
"persona-context-truncated-count": "{{count}} truncados",
"persona-context-version-restored": "Contexto de IA restaurado para v{{version}}",
+ "persona-default-app-mode-description": "O modo de aplicativo em que os usuários desta Persona entram quando não escolheram seu próprio padrão. As preferências do usuário ainda têm prioridade sobre esta configuração.",
"persona-preference-updated": "Preferência de persona atualizada com sucesso!",
"persona-updated-successfully": "Persona atualizada com sucesso.",
"personal-access-token": "Token de Acesso Pessoal",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-pt.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-pt.json
index 1b9e2e80a58e..8fb946cab8eb 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-pt.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-pt.json
@@ -715,6 +715,7 @@
"december": "Dezembro",
"decision": "Decisão",
"default": "Padrão",
+ "default-app-mode": "Modo da aplicação padrão",
"default-persona": "Perfil Padrão",
"default-role": "Função Padrão",
"define-it": "Defina-a",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "Ainda sem Produtos de Dados",
"no-data-products-yet-description": "Crie o seu primeiro produto de dados para disponibilizar conjuntos de dados fiáveis para descoberta e acesso.",
"no-description": "Sem descrição",
+ "no-default": "Sem padrão",
"no-diff-available": "Nenhuma diferença disponível",
"no-dimension": "Sem dimensão",
"no-domains-yet": "Ainda não existem domínios",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "Caminho do arquivo de resultados da execução dbt para extrair as informações dos resultados dos testes.",
"dbt-run-result-http-path-message": "dbt executa os resultados em um caminho http para extrair as informações dos resultados dos testes.",
"deeply-understand-table-relations-message": "Obtenha os Produtores e Consumidores de dados em uma única plataforma e acelere a produtividade. A colaboração fica ainda melhor com pessoas e dados de múltiplas ferramentas em um local centralizado.",
+ "default-app-mode-description": "O modo de \"primeira impressão\" para utilizadores que ainda não escolheram um. As preferências do utilizador e os modos de aplicação definidos por persona continuam a ter prioridade sobre este padrão.",
"default-persona-removed-successfully": "Persona predefinida foi removida com sucesso.",
"default-persona-set-successfully": "Persona predefinida foi definida com sucesso.",
"default-persona-update-error": "Falha ao actualizar persona predefinida. Tente novamente.",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "~{{formattedCount}} tokens",
"persona-context-truncated-count": "{{count}} truncados",
"persona-context-version-restored": "Contexto de IA restaurado para v{{version}}",
+ "persona-default-app-mode-description": "O modo de aplicação em que os utilizadores desta Persona entram quando não escolheram o seu próprio padrão. As preferências do utilizador continuam a ter prioridade sobre esta definição.",
"persona-preference-updated": "Preferência de persona atualizada com sucesso!",
"persona-updated-successfully": "Persona atualizada com sucesso.",
"personal-access-token": "Token de Acesso Pessoal",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json
index 1d0048674388..aeb5352fa2b0 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json
@@ -715,6 +715,7 @@
"december": "Декабрь",
"decision": "Решение",
"default": "По умолчанию",
+ "default-app-mode": "Режим приложения по умолчанию",
"default-persona": "Персона по умолчанию",
"default-role": "Роль по умолчанию",
"define-it": "Определите её",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "Пока нет Дата-Продуктов",
"no-data-products-yet-description": "Создайте свой первый дата-продукт, чтобы надёжные наборы данных стали доступны для обнаружения и доступа.",
"no-description": "Нет описания",
+ "no-default": "Нет умолчания",
"no-diff-available": "Нет различий",
"no-dimension": "Без измерения",
"no-domains-yet": "Домены ещё не добавлены",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "путь к файлу результатов запуска dbt для извлечения информации о результатах тестирования.",
"dbt-run-result-http-path-message": "dbt запускает результаты по http-пути для извлечения результатов теста.",
"deeply-understand-table-relations-message": "Отслеживайте связи между таблицами на уровне отдельных столбцов",
+ "default-app-mode-description": "Режим «первого впечатления» для пользователей, которые ещё не выбрали свой режим. Настройки пользователя и режимы приложения на уровне персоны всё равно имеют приоритет над этим значением по умолчанию.",
"default-persona-removed-successfully": "Персона по умолчанию была успешно удалена.",
"default-persona-set-successfully": "Персона по умолчанию была успешно установлена.",
"default-persona-update-error": "Не удалось обновить персону по умолчанию. Попробуйте снова.",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "~{{formattedCount}} токенов",
"persona-context-truncated-count": "Сокращено: {{count}}",
"persona-context-version-restored": "Контекст ИИ восстановлен до v{{version}}",
+ "persona-default-app-mode-description": "Режим приложения, в который попадают пользователи этой Персоны, если они не выбрали собственный режим по умолчанию. Настройки пользователя всё равно имеют приоритет над этой настройкой.",
"persona-preference-updated": "Предпочтения персонажа успешно обновлены!",
"persona-updated-successfully": "Persona успешно обновлена.",
"personal-access-token": "Персональный токен доступа",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/sv-se.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/sv-se.json
index 9efde887bc1b..fc838afe09ae 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/sv-se.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/sv-se.json
@@ -715,6 +715,7 @@
"december": "December",
"decision": "Beslut",
"default": "Standard",
+ "default-app-mode": "Standardappläge",
"default-persona": "Standardpersona",
"default-role": "Standardroll",
"define-it": "Definiera det",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "Inga dataprodukter ännu",
"no-data-products-yet-description": "Skapa din första dataprodukt för att göra betrodda datauppsättningar tillgängliga för upptäckt och åtkomst.",
"no-description": "Ingen beskrivning",
+ "no-default": "Ingen standard",
"no-diff-available": "Ingen diff tillgänglig",
"no-dimension": "Ingen dimension",
"no-domains-yet": "Inga domäner ännu",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "Sökväg till dbt-körningsresultatfil för att extrahera information om testresultaten.",
"dbt-run-result-http-path-message": "dbt kör resultaten på en http-sökväg för att extrahera testresultaten.",
"deeply-understand-table-relations-message": "Få producenterna och konsumenterna av data på en enda plattform och öka produktiviteten. Samarbetet blir ännu bättre med människor och data från flera verktyg på en central plats.",
+ "default-app-mode-description": "Läget för 'första intrycket' för användare som inte har valt ett eget läge. Användarinställningar och personanivåns applägen har fortfarande företräde framför denna standard.",
"default-persona-removed-successfully": "Standardpersonan togs bort.",
"default-persona-set-successfully": "Standardpersonan angavs.",
"default-persona-update-error": "Det gick inte att uppdatera standardpersonan. Försök igen.",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "~{{formattedCount}} token",
"persona-context-truncated-count": "{{count}} trunkerade",
"persona-context-version-restored": "AI-kontext återställd till v{{version}}",
+ "persona-default-app-mode-description": "Vilket applikationsläge användare i denna Persona hamnar i när de inte har valt sitt eget standardläge. Användarinställningar har fortfarande företräde framför denna inställning.",
"persona-preference-updated": "Personainställningen har uppdaterats!",
"persona-updated-successfully": "Personan har uppdaterats.",
"personal-access-token": "Personal Access Token",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/th-th.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/th-th.json
index e338bea49b18..b049ee08f784 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/th-th.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/th-th.json
@@ -715,6 +715,7 @@
"december": "ธันวาคม",
"decision": "การตัดสินใจ",
"default": "ค่าเริ่มต้น",
+ "default-app-mode": "โหมดแอปเริ่มต้น",
"default-persona": "บุคลิกภาพเริ่มต้น",
"default-role": "บทบาทเริ่มต้น",
"define-it": "กำหนดนิยาม",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "ยังไม่มีผลิตภัณฑ์ข้อมูล",
"no-data-products-yet-description": "สร้างผลิตภัณฑ์ข้อมูลชิ้นแรกของคุณเพื่อให้ชุดข้อมูลที่เชื่อถือได้พร้อมสำหรับการค้นพบและการเข้าถึง",
"no-description": "ไม่มีคำอธิบาย",
+ "no-default": "ไม่มีค่าเริ่มต้น",
"no-diff-available": "ไม่มีการเปลี่ยนแปลงที่พร้อมใช้งาน",
"no-dimension": "ไม่มีมิติ",
"no-domains-yet": "โดเมนยังไม่มี",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "เส้นทางไฟล์ผลลัพธ์การรัน dbt สำหรับดึงข้อมูลผลการทดสอบ",
"dbt-run-result-http-path-message": "dbt รันผลลัพธ์บนเส้นทาง http เพื่อดึงข้อมูลผลการทดสอบ",
"deeply-understand-table-relations-message": "เข้าใจการเชื่อมโยงข้อมูลในตารางอย่างลึกซึ้งโดยการรับผู้ผลิตและผู้บริโภคของข้อมูลในแพลตฟอร์มเดียว และเพิ่มประสิทธิภาพการผลิต การร่วมมือจะดีขึ้นด้วยผู้คนและข้อมูลจากเครื่องมือหลายชนิดในสถานที่ศูนย์กลาง",
+ "default-app-mode-description": "โหมด 'ความประทับใจแรก' สำหรับผู้ใช้ที่ยังไม่ได้เลือกโหมดของตนเอง การตั้งค่าที่ผู้ใช้เลือกไว้และโหมดแอปในระดับเพอร์โซนายังคงมีความสำคัญเหนือค่าเริ่มต้นนี้",
"default-persona-removed-successfully": "บุคลิกภาพเริ่มต้นถูกลบเรียบร้อยแล้ว",
"default-persona-set-successfully": "บุคลิกภาพเริ่มต้นถูกตั้งค่าเรียบร้อยแล้ว",
"default-persona-update-error": "ไม่สามารถอัปเดตบุคลิกภาพเริ่มต้น กรุณาลองใหม่อีกครั้ง",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "ประมาณ {{formattedCount}} โทเค็น",
"persona-context-truncated-count": "ตัดทอน {{count}} รายการ",
"persona-context-version-restored": "กู้คืนบริบท AI เป็น v{{version}} แล้ว",
+ "persona-default-app-mode-description": "โหมดแอปพลิเคชันที่ผู้ใช้ในเพอร์โซนานี้จะเข้าสู่เมื่อยังไม่ได้เลือกค่าเริ่มต้นของตนเอง การตั้งค่าที่ผู้ใช้เลือกไว้ยังคงมีความสำคัญเหนือการตั้งค่านี้",
"persona-preference-updated": "อัปเดตการตั้งค่าบุคลิกภาพสำเร็จแล้ว!",
"persona-updated-successfully": "Persona อัปเดตสำเร็จแล้ว!",
"personal-access-token": "โทเค็นการเข้าถึงส่วนบุคคล",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/tr-tr.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/tr-tr.json
index 9dd33b2c59d1..4ac238a9d2f9 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/tr-tr.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/tr-tr.json
@@ -715,6 +715,7 @@
"december": "Aralık",
"decision": "Karar",
"default": "Varsayılan",
+ "default-app-mode": "Varsayılan Uygulama Modu",
"default-persona": "Varsayılan Persona",
"default-role": "Varsayılan Rol",
"define-it": "Tanımlayın",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "Henüz Veri Ürünü Yok",
"no-data-products-yet-description": "Güvenilir veri kümelerini keşfedilebilir ve erişilebilir hale getirmek için ilk veri ürününüzü oluşturun.",
"no-description": "Açıklama yok",
+ "no-default": "Varsayılan yok",
"no-diff-available": "Fark mevcut değil",
"no-dimension": "Boyut yok",
"no-domains-yet": "Henüz etki alanı yok",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "Test sonuçları bilgilerini çıkarmak için dbt çalıştırma sonuçları dosya yolu.",
"dbt-run-result-http-path-message": "Test sonuçlarını çıkarmak için dbt, sonuçları bir http yolunda çalıştırır.",
"deeply-understand-table-relations-message": "Veri Üreticilerini ve Tüketicilerini tek bir platformda edinin ve üretkenliği hızlandırın. İşbirliği, merkezi bir konumda birden fazla araçtan gelen kişiler ve verilerle daha da iyi hale gelir.",
+ "default-app-mode-description": "Henüz bir mod seçmemiş kullanıcılar için 'ilk izlenim' modudur. Kullanıcı tercihleri ve persona düzeyindeki uygulama modları bu varsayılana göre önceliklidir.",
"default-persona-removed-successfully": "Varsayılan kişilik başarıyla kaldırıldı.",
"default-persona-set-successfully": "Varsayılan kişilik başarıyla ayarlandı.",
"default-persona-update-error": "Varsayılan kişilik güncellenemedi. Lütfen tekrar deneyin.",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "~{{formattedCount}} token",
"persona-context-truncated-count": "{{count}} kısaltıldı",
"persona-context-version-restored": "AI bağlamı v{{version}} sürümüne geri yüklendi",
+ "persona-default-app-mode-description": "Bu Persona'daki kullanıcıların kendi varsayılanlarını seçmedikleri durumda hangi uygulama moduna yönlendirileceğini belirler. Kullanıcı tercihleri bu ayara göre önceliklidir.",
"persona-preference-updated": "Kişilik tercihi başarıyla güncellendi!",
"persona-updated-successfully": "Persona başarıyla güncellendi.",
"personal-access-token": "Kişisel Erişim Anahtarı",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json
index 0f8f4298febf..4bd600183103 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json
@@ -715,6 +715,7 @@
"december": "十二月",
"decision": "决定",
"default": "默认",
+ "default-app-mode": "默认应用模式",
"default-persona": "默认用户角色",
"default-role": "默认角色",
"define-it": "定义指标",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "尚无数据产品",
"no-data-products-yet-description": "创建您的第一个数据产品,让可信数据集可供发现和访问。",
"no-description": "无描述",
+ "no-default": "无默认",
"no-diff-available": "没有可用的差异",
"no-dimension": "无维度",
"no-domains-yet": "暂无域",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "dbt 运行结果文件路径, 用于提取测试结果信息",
"dbt-run-result-http-path-message": "dbt 运行结果 http 路径, 用于提取测试结果信息",
"deeply-understand-table-relations-message": "通过列级血缘关系图, 深入了解数据表之间的关系",
+ "default-app-mode-description": "为尚未选择模式的用户提供的「第一印象」模式。用户偏好设置和角色级别的应用模式仍优先于此默认设置。",
"default-persona-removed-successfully": "默认角色已成功移除。",
"default-persona-set-successfully": "默认角色已成功设置。",
"default-persona-update-error": "更新默认角色失败。请重试。",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "约 {{formattedCount}} 个令牌",
"persona-context-truncated-count": "已截断 {{count}} 项",
"persona-context-version-restored": "AI 上下文已恢复到 v{{version}}",
+ "persona-default-app-mode-description": "当此角色下的用户未选择自己的默认模式时,他们将进入的应用模式。用户偏好设置仍优先于此设置。",
"persona-preference-updated": "角色偏好设置已成功更新!",
"persona-updated-successfully": "Persona 已成功更新。",
"personal-access-token": "个人访问令牌",
diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-tw.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-tw.json
index 9860b3b500de..f12f11111306 100644
--- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-tw.json
+++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-tw.json
@@ -715,6 +715,7 @@
"december": "十二月",
"decision": "決策",
"default": "預設",
+ "default-app-mode": "預設應用程式模式",
"default-persona": "預設角色",
"default-role": "預設角色",
"define-it": "定義指標",
@@ -1694,6 +1695,7 @@
"no-data-products-yet": "尚無資料產品",
"no-data-products-yet-description": "建立您的第一個資料產品,讓受信任的資料集可供探索與存取。",
"no-description": "無描述",
+ "no-default": "無預設",
"no-diff-available": "無可用差異",
"no-dimension": "無維度",
"no-domains-yet": "尚無領域",
@@ -3246,6 +3248,7 @@
"dbt-result-file-path": "dbt 執行結果檔案路徑,用於擷取測試結果資訊。",
"dbt-run-result-http-path-message": "dbt 在 http 路徑上執行結果以擷取測試結果。",
"deeply-understand-table-relations-message": "在單一平台中獲取資料的生產者和消費者,並加速生產力。透過將來自多個工具的人員和資料集中在一個位置,協作變得更好。",
+ "default-app-mode-description": "為尚未選擇模式的使用者提供的「第一印象」模式。使用者偏好設定與角色層級的應用程式模式仍優先於此預設設定。",
"default-persona-removed-successfully": "預設角色已成功移除。",
"default-persona-set-successfully": "預設角色已成功設定。",
"default-persona-update-error": "更新預設角色失敗。請再試一次。",
@@ -4051,6 +4054,7 @@
"persona-context-token-estimate": "約 {{formattedCount}} 個權杖",
"persona-context-truncated-count": "已截斷 {{count}} 項",
"persona-context-version-restored": "AI 上下文已還原至 v{{version}}",
+ "persona-default-app-mode-description": "當此角色下的使用者尚未選擇自己的預設模式時,他們將進入的應用程式模式。使用者偏好設定仍優先於此設定。",
"persona-preference-updated": "角色偏好設定已成功更新!",
"persona-updated-successfully": "Persona 已成功更新。",
"personal-access-token": "個人存取權杖",
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/Settings/DefaultAppModePage/DefaultAppModePage.test.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/Settings/DefaultAppModePage/DefaultAppModePage.test.tsx
new file mode 100644
index 000000000000..6c195e11fc84
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/Settings/DefaultAppModePage/DefaultAppModePage.test.tsx
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2026 Collate.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { fireEvent, render, screen, waitFor } from '@testing-library/react';
+import {
+ AI_APP_MODE,
+ DEFAULT_APP_MODE,
+} from '../../../constants/appMode.constants';
+import { useAppRoutesRegistry } from '../../../hooks/useAppRoutesRegistry';
+import * as api from '../../../rest/settingConfigAPI';
+import * as toastUtils from '../../../utils/ToastUtils';
+import DefaultAppModePage from './DefaultAppModePage';
+
+jest.mock('../../../rest/settingConfigAPI');
+jest.mock('../../../utils/ToastUtils', () => ({
+ showErrorToast: jest.fn(),
+ showSuccessToast: jest.fn(),
+}));
+
+// Uses the global react-i18next mock from setupTests.js (`t: (key) => key`),
+// so assertions below match against raw i18n keys rather than human-readable
+// English strings — consistent with every other suite in this repo, and it
+// catches a typo'd/nonexistent key that a canned translations map would hide.
+const mockGet = api.getAppConfiguration as jest.Mock;
+const mockPatch = api.patchAppConfiguration as jest.Mock;
+const mockShowSuccessToast = toastUtils.showSuccessToast as jest.Mock;
+
+const Component = () => null;
+
+describe('DefaultAppModePage', () => {
+ beforeEach(() => {
+ useAppRoutesRegistry.setState({ routes: {}, metadata: {} });
+ useAppRoutesRegistry
+ .getState()
+ .registerRoutes(DEFAULT_APP_MODE, Component, {
+ labelKey: 'label.default',
+ });
+ mockGet.mockResolvedValue({ defaultAppMode: null });
+ mockPatch.mockResolvedValue({ defaultAppMode: 'ai' });
+ });
+
+ it('renders "No default" and every registered mode as radios', async () => {
+ useAppRoutesRegistry
+ .getState()
+ .registerRoutes(AI_APP_MODE, Component, { labelKey: 'label.ai' });
+ render();
+ await waitFor(() => expect(mockGet).toHaveBeenCalled());
+
+ expect(
+ screen.getByRole('radio', { name: 'label.no-default' })
+ ).toBeInTheDocument();
+ expect(
+ screen.getByRole('radio', { name: 'label.default' })
+ ).toBeInTheDocument();
+ expect(
+ screen.getByRole('radio', { name: 'label.ai' })
+ ).toBeInTheDocument();
+ });
+
+ it('marks "No default" selected initially when defaultAppMode is null', async () => {
+ render();
+ await waitFor(() => expect(mockGet).toHaveBeenCalled());
+
+ expect(
+ screen.getByRole('radio', { name: 'label.no-default' })
+ ).toBeChecked();
+ });
+
+ it('Save button is disabled until the value changes', async () => {
+ render();
+ await waitFor(() => expect(mockGet).toHaveBeenCalled());
+
+ const save = screen.getByRole('button', { name: 'label.save' });
+
+ expect(save).toBeDisabled();
+
+ fireEvent.click(screen.getByRole('radio', { name: 'label.default' }));
+
+ expect(save).toBeEnabled();
+ });
+
+ it('Save calls patchAppConfiguration with the new value and shows the correct success toast key', async () => {
+ useAppRoutesRegistry
+ .getState()
+ .registerRoutes(AI_APP_MODE, Component, { labelKey: 'label.ai' });
+ render();
+ await waitFor(() => expect(mockGet).toHaveBeenCalled());
+
+ fireEvent.click(screen.getByRole('radio', { name: 'label.ai' }));
+ fireEvent.click(screen.getByRole('button', { name: 'label.save' }));
+
+ await waitFor(() =>
+ expect(mockPatch).toHaveBeenCalledWith({ defaultAppMode: 'ai' })
+ );
+
+ // Guards against the toast call regressing to a nonexistent i18n key
+ // (e.g. a typo'd `server.entity-updated-successfully`) — a future typo
+ // here fails this assertion instead of silently rendering the raw key.
+ expect(mockShowSuccessToast).toHaveBeenCalledWith(
+ 'server.entity-updated-success'
+ );
+ });
+});
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/Settings/DefaultAppModePage/DefaultAppModePage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/Settings/DefaultAppModePage/DefaultAppModePage.tsx
new file mode 100644
index 000000000000..a01aee8135b7
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/Settings/DefaultAppModePage/DefaultAppModePage.tsx
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2026 Collate.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import {
+ Box,
+ Button,
+ RadioButton,
+ RadioGroup,
+ Typography,
+} from '@openmetadata/ui-core-components';
+import { AxiosError } from 'axios';
+import { useEffect, useMemo, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { DefaultAppMode } from '../../../generated/api/configuration/appConfiguration';
+import { useAppRoutesRegistry } from '../../../hooks/useAppRoutesRegistry';
+import {
+ getAppConfiguration,
+ patchAppConfiguration,
+} from '../../../rest/settingConfigAPI';
+import { showErrorToast, showSuccessToast } from '../../../utils/ToastUtils';
+
+// Sentinel value for the "no tenant default" radio option — the wire value
+// for that choice is `null`, but native form controls can't carry `null` as
+// a value, so we translate at the option/handler boundary only. Namespaced
+// so it can never collide with a real registry mode key.
+const NO_DEFAULT_VALUE = '__no_default__';
+
+interface AppModeOption {
+ value: string;
+ labelKey: string;
+}
+
+const DefaultAppModePage: React.FC = () => {
+ const { t } = useTranslation();
+ const pageTitle = t('label.default-app-mode');
+ const metadata = useAppRoutesRegistry((state) => state.metadata);
+ const [initialValue, setInitialValue] = useState(NO_DEFAULT_VALUE);
+ const [currentValue, setCurrentValue] = useState(NO_DEFAULT_VALUE);
+ const [isLoading, setIsLoading] = useState(true);
+ const [isSaving, setIsSaving] = useState(false);
+
+ const options = useMemo(() => {
+ const modeOptions = Object.entries(metadata).map(([value, m]) => ({
+ value,
+ labelKey: m.labelKey,
+ }));
+
+ return [
+ { value: NO_DEFAULT_VALUE, labelKey: 'label.no-default' },
+ ...modeOptions,
+ ];
+ }, [metadata]);
+
+ useEffect(() => {
+ let isMounted = true;
+
+ getAppConfiguration()
+ .then((config) => {
+ if (!isMounted) {
+ return;
+ }
+ const initial = config?.defaultAppMode ?? NO_DEFAULT_VALUE;
+ setInitialValue(initial);
+ setCurrentValue(initial);
+ })
+ .catch((error: AxiosError) => showErrorToast(error))
+ .finally(() => {
+ if (isMounted) {
+ setIsLoading(false);
+ }
+ });
+
+ return () => {
+ isMounted = false;
+ };
+ }, []);
+
+ const isDirty = currentValue !== initialValue;
+
+ const handleSave = async () => {
+ setIsSaving(true);
+ try {
+ // The registry sources generic runtime mode keys (any string a plugin
+ // registers), while the wire schema still types this field against the
+ // fixed `DefaultAppMode` enum. This cast is the boundary translation
+ // for that mismatch; the backend setting itself stores any string.
+ const defaultAppMode =
+ currentValue === NO_DEFAULT_VALUE
+ ? null
+ : (currentValue as unknown as DefaultAppMode);
+ await patchAppConfiguration({ defaultAppMode });
+ setInitialValue(currentValue);
+ showSuccessToast(
+ t('server.entity-updated-success', { entity: pageTitle })
+ );
+ } catch (error) {
+ showErrorToast(error as AxiosError);
+ } finally {
+ setIsSaving(false);
+ }
+ };
+
+ return (
+
+
+ {pageTitle}
+
+
+ {t('message.default-app-mode-description')}
+
+
+ {options.map((option) => (
+
+ ))}
+
+
+
+
+
+ );
+};
+
+export default DefaultAppModePage;
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/GlobalSettingsClassBase.test.ts b/openmetadata-ui/src/main/resources/ui/src/utils/GlobalSettingsClassBase.test.ts
index 0f0780099335..7d6c532d22ac 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/GlobalSettingsClassBase.test.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/GlobalSettingsClassBase.test.ts
@@ -517,6 +517,7 @@ describe('GlobalSettingsClassBase', () => {
'preferences.lineageConfig',
'preferences.om-url-config',
'preferences.dataAssetRules',
+ 'preferences.appMode',
];
preferenceKeys.forEach((key) => {
@@ -554,6 +555,41 @@ describe('GlobalSettingsClassBase', () => {
expect(dataAssetRules?.isBeta).toBe(true);
});
+ it('should gate the default app mode entry on admin only', () => {
+ (userPermissions.hasViewPermissions as jest.Mock).mockReturnValue(false);
+
+ const resultAdmin =
+ globalSettingsClassBase.getGlobalSettingsMenuWithPermission(
+ mockNoPermissions,
+ true
+ );
+
+ const preferencesCategoryAdmin = resultAdmin.find(
+ (item) => item.key === 'preferences'
+ );
+ const appModeItemAdmin = preferencesCategoryAdmin?.items?.find(
+ (item) => item.key === 'preferences.appMode'
+ );
+
+ expect(appModeItemAdmin).toBeDefined();
+ expect(appModeItemAdmin?.isProtected).toBe(true);
+
+ const resultNonAdmin =
+ globalSettingsClassBase.getGlobalSettingsMenuWithPermission(
+ mockNoPermissions,
+ false
+ );
+
+ const preferencesCategoryNonAdmin = resultNonAdmin.find(
+ (item) => item.key === 'preferences'
+ );
+ const appModeItemNonAdmin = preferencesCategoryNonAdmin?.items?.find(
+ (item) => item.key === 'preferences.appMode'
+ );
+
+ expect(appModeItemNonAdmin?.isProtected).toBe(false);
+ });
+
it('should call userPermissions.hasViewPermissions with correct arguments', () => {
(userPermissions.hasViewPermissions as jest.Mock).mockReturnValue(true);
diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/GlobalSettingsClassBase.ts b/openmetadata-ui/src/main/resources/ui/src/utils/GlobalSettingsClassBase.ts
index 5842d9380499..c16c3e36fb25 100644
--- a/openmetadata-ui/src/main/resources/ui/src/utils/GlobalSettingsClassBase.ts
+++ b/openmetadata-ui/src/main/resources/ui/src/utils/GlobalSettingsClassBase.ts
@@ -14,6 +14,7 @@ import { ReactComponent as AdminIcon } from '../assets/svg/admin-colored.svg';
import { ReactComponent as APICollectionIcon } from '../assets/svg/api-collection-colored.svg';
import { ReactComponent as APIEndpointIcon } from '../assets/svg/api-endpoints-colored.svg';
import { ReactComponent as IconAPI } from '../assets/svg/apis-colored.svg';
+import { ReactComponent as AppModeIcon } from '../assets/svg/app-mode.svg';
import { ReactComponent as ApplicationIcon } from '../assets/svg/application-colored.svg';
import { ReactComponent as BotIcon } from '../assets/svg/bot-colored.svg';
import { ReactComponent as ChartIcon } from '../assets/svg/chart-colored.svg';
@@ -680,6 +681,13 @@ class GlobalSettingsClassBase {
key: `${GlobalSettingsMenuCategory.PREFERENCES}.${GlobalSettingOptions.LEARNING_RESOURCES}`,
icon: LearningIcon,
},
+ {
+ label: t('label.default-app-mode'),
+ description: t('message.default-app-mode-description'),
+ isProtected: Boolean(isAdminUser),
+ key: `${GlobalSettingsMenuCategory.PREFERENCES}.${GlobalSettingOptions.APP_MODE}`,
+ icon: AppModeIcon,
+ },
],
},
{