From 0834474a76fe2debed14f488e46da39e16b960e0 Mon Sep 17 00:00:00 2001 From: Jonathan Payne Date: Wed, 28 Oct 2026 11:31:26 -0400 Subject: [PATCH] OpenConceptLab/ocl_online#367 | Limit dialogs share one frame: Close first, then the next step PreviewLimitDialog had its own layout: the next-step button came first, had no new-tab icon, and the dismiss button said "Back to my project" even on the project list. Both limit dialogs now render through LimitDialog, which is QuotaDialog's layout: the title and close icon, what was refused, any message the connected service sends, then Close and the next-step button with its new-tab icon. QuotaDialog renders exactly as before. The dismiss string is no longer used, so it leaves all four languages. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01AaZ4qVXboeBSRvAQgQjdbs --- src/components/common/LimitDialog.jsx | 59 +++++++++++++++++++ src/components/common/QuotaDialog.jsx | 48 ++------------- .../map-projects/PreviewLimitDialog.jsx | 42 ++----------- src/i18n/locales/en/translations.json | 1 - src/i18n/locales/es/translations.json | 1 - src/i18n/locales/pt-BR/translations.json | 1 - src/i18n/locales/zh/translations.json | 1 - 7 files changed, 68 insertions(+), 85 deletions(-) create mode 100644 src/components/common/LimitDialog.jsx diff --git a/src/components/common/LimitDialog.jsx b/src/components/common/LimitDialog.jsx new file mode 100644 index 0000000..2032a87 --- /dev/null +++ b/src/components/common/LimitDialog.jsx @@ -0,0 +1,59 @@ +import React from 'react' +import { useTranslation } from 'react-i18next' +import DialogContent from '@mui/material/DialogContent' +import DialogActions from '@mui/material/DialogActions' +import Typography from '@mui/material/Typography' +import Button from '@mui/material/Button' +import OpenInNewIcon from '@mui/icons-material/OpenInNew' + +import Dialog from './Dialog' +import DialogTitle from './DialogTitle' +import CloseIconButton from './CloseIconButton' +import useLimitAction from './useLimitAction' + +// The frame every limit dialog shares: what was refused, then any next step +// the connected service sends (OpenConceptLab/ocl_online#367), which opens +// in a new tab. +const LimitDialog = ({open, onClose, errorCode, title, children}) => { + const { t } = useTranslation() + const { action, onActionClick } = useLimitAction(open, errorCode) + + return ( + + + {title} + + + + + {children} + + { + action?.message && + {action.message} + } + + + + { + action && + + } + + + ) +} + +export default LimitDialog diff --git a/src/components/common/QuotaDialog.jsx b/src/components/common/QuotaDialog.jsx index 8fb7004..19f9899 100644 --- a/src/components/common/QuotaDialog.jsx +++ b/src/components/common/QuotaDialog.jsx @@ -1,56 +1,16 @@ import React from 'react' import { useTranslation } from 'react-i18next' -import DialogContent from '@mui/material/DialogContent' -import DialogActions from '@mui/material/DialogActions' -import Typography from '@mui/material/Typography' -import Button from '@mui/material/Button' -import OpenInNewIcon from '@mui/icons-material/OpenInNew' -import Dialog from './Dialog' -import DialogTitle from './DialogTitle' -import CloseIconButton from './CloseIconButton' +import LimitDialog from './LimitDialog' import { isCapMeter } from './quotaErrors' -import useLimitAction from './useLimitAction' const QuotaDialog = ({open, onClose, errorCode, meter, surface}) => { const { t } = useTranslation() - const { action, onActionClick } = useLimitAction(open, errorCode) return ( - - - {t(isCapMeter(meter) ? 'quota.title_cap' : 'quota.title_quota')} - - - - - {t([`quota.consequence.${meter}.${surface}`, `quota.consequence.${meter}.default`, 'quota.consequence.generic'])} - - { - action?.message && - {action.message} - } - - - - { - action && - - } - - + + {t([`quota.consequence.${meter}.${surface}`, `quota.consequence.${meter}.default`, 'quota.consequence.generic'])} + ) } diff --git a/src/components/map-projects/PreviewLimitDialog.jsx b/src/components/map-projects/PreviewLimitDialog.jsx index 43220c4..b643981 100644 --- a/src/components/map-projects/PreviewLimitDialog.jsx +++ b/src/components/map-projects/PreviewLimitDialog.jsx @@ -1,50 +1,18 @@ import React from 'react' import { useTranslation } from 'react-i18next' -import Dialog from '@mui/material/Dialog' -import DialogTitle from '@mui/material/DialogTitle' -import DialogContent from '@mui/material/DialogContent' -import DialogActions from '@mui/material/DialogActions' -import Typography from '@mui/material/Typography' -import Button from '@mui/material/Button' -import CloseIconButton from '../common/CloseIconButton' -import useLimitAction from '../common/useLimitAction' +import LimitDialog from '../common/LimitDialog' import { PREVIEW_LIMIT_COPY_KEY } from './previewLimits' -// Says what the account can't use. Any next step comes from the connected -// service (OpenConceptLab/ocl_online#367) and opens in a new tab. +// Says what the account can't use. const PreviewLimitDialog = ({open, onClose, errorCode}) => { const { t } = useTranslation() - const { action, onActionClick } = useLimitAction(open, errorCode) const kind = PREVIEW_LIMIT_COPY_KEY[errorCode] || 'generic' return ( - - - {t('map_project.limit_unavailable_title')} - - - - - {t([`map_project.limit_unavailable_body_${kind}`, 'map_project.limit_unavailable_body_generic'])} - - { - action?.message && - {action.message} - } - - - { - action && - - } - - - + + {t([`map_project.limit_unavailable_body_${kind}`, 'map_project.limit_unavailable_body_generic'])} + ) } diff --git a/src/i18n/locales/en/translations.json b/src/i18n/locales/en/translations.json index a37b20f..3906869 100644 --- a/src/i18n/locales/en/translations.json +++ b/src/i18n/locales/en/translations.json @@ -327,7 +327,6 @@ "limit_unavailable_body_match_operations_not_entitled": "Your account can't run AutoMatch.", "limit_unavailable_body_projects_not_entitled": "Your account can't create map projects.", "limit_unavailable_body_generic": "This isn't available for your account.", - "preview_limit_dismiss": "Back to my project", "preview_config_unavailable_title": "This project uses preview-restricted settings", "preview_config_unavailable_org_projects": "Organization-owned Mapper projects are not part of your preview. Choose your personal namespace as the project owner.", "preview_config_unavailable_custom_algorithms": "Externally hosted algorithms are not part of your preview. Remove the custom algorithm before saving.", diff --git a/src/i18n/locales/es/translations.json b/src/i18n/locales/es/translations.json index 16fa038..d8cbc4d 100644 --- a/src/i18n/locales/es/translations.json +++ b/src/i18n/locales/es/translations.json @@ -311,7 +311,6 @@ "limit_unavailable_body_match_operations_not_entitled": "Tu cuenta no puede ejecutar AutoMatch.", "limit_unavailable_body_projects_not_entitled": "Tu cuenta no puede crear proyectos de mapeo.", "limit_unavailable_body_generic": "Esto no está disponible para tu cuenta.", - "preview_limit_dismiss": "Volver a mi proyecto", "preview_config_unavailable_title": "Este proyecto usa configuraciones restringidas de la vista previa", "preview_config_unavailable_org_projects": "Los proyectos de Mapper propiedad de una organización no forman parte de tu vista previa. Elige tu espacio de nombres personal como propietario del proyecto.", "preview_config_unavailable_custom_algorithms": "Los algoritmos externos no forman parte de tu vista previa. Elimina el algoritmo personalizado antes de guardar.", diff --git a/src/i18n/locales/pt-BR/translations.json b/src/i18n/locales/pt-BR/translations.json index c2fd265..3540ef2 100644 --- a/src/i18n/locales/pt-BR/translations.json +++ b/src/i18n/locales/pt-BR/translations.json @@ -327,7 +327,6 @@ "limit_unavailable_body_match_operations_not_entitled": "Sua conta não pode executar o AutoMatch.", "limit_unavailable_body_projects_not_entitled": "Sua conta não pode criar projetos de mapeamento.", "limit_unavailable_body_generic": "Isto não está disponível para sua conta.", - "preview_limit_dismiss": "Voltar ao meu projeto", "preview_config_unavailable_title": "Este projeto usa configurações restritas de prévia", "preview_config_unavailable_org_projects": "Projetos de Mapper pertencentes a organizações não fazem parte de sua prévia. Escolha seu namespace pessoal como proprietário do projeto.", "preview_config_unavailable_custom_algorithms": "Algoritmos hospedados externamente não fazem parte de sua prévia. Remova o algoritmo personalizado antes de salvar.", diff --git a/src/i18n/locales/zh/translations.json b/src/i18n/locales/zh/translations.json index 6358494..3852a6c 100644 --- a/src/i18n/locales/zh/translations.json +++ b/src/i18n/locales/zh/translations.json @@ -323,7 +323,6 @@ "limit_unavailable_body_match_operations_not_entitled": "你的账户无法运行 AutoMatch。", "limit_unavailable_body_projects_not_entitled": "你的账户无法创建映射项目。", "limit_unavailable_body_generic": "你的账户无法使用此功能。", - "preview_limit_dismiss": "返回我的项目", "preview_config_unavailable_title": "此项目使用了预览版受限设置", "preview_config_unavailable_org_projects": "组织拥有的 Mapper 项目不在你的预览范围内。请选择个人命名空间作为项目所有者。", "preview_config_unavailable_custom_algorithms": "外部托管算法不在你的预览范围内。请先移除自定义算法再保存。",