feat(translation): Improve translation alert in empty languages state (#14464)
**What** When there is no languages configured, the translation page will show a proper alert on the page that is more visible and actionable
This commit is contained in:
committed by
GitHub
parent
b300a93345
commit
d54589751c
6
.changeset/many-balloons-rest.md
Normal file
6
.changeset/many-balloons-rest.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/dashboard": patch
|
||||||
|
"@medusajs/ui": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
feat(translation): Improve translation alert in empty languages state
|
||||||
@@ -9444,9 +9444,17 @@
|
|||||||
},
|
},
|
||||||
"noLocalesTip": {
|
"noLocalesTip": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"noLocalesTipConfigureAction": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["heading", "subtitle", "noLocalesTip"]
|
"required": [
|
||||||
|
"heading",
|
||||||
|
"subtitle",
|
||||||
|
"noLocalesTip",
|
||||||
|
"noLocalesTipConfigureAction"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"completion": {
|
"completion": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
|||||||
@@ -2540,7 +2540,8 @@
|
|||||||
"activeLocales": {
|
"activeLocales": {
|
||||||
"heading": "Languages",
|
"heading": "Languages",
|
||||||
"subtitle": "Activated translations",
|
"subtitle": "Activated translations",
|
||||||
"noLocalesTip": "Configure at least one locale to start translating your data"
|
"noLocalesTip": "Configure at least one language to start translating your data",
|
||||||
|
"noLocalesTipConfigureAction": "Configure"
|
||||||
},
|
},
|
||||||
"completion": {
|
"completion": {
|
||||||
"heading": "Translated fields",
|
"heading": "Translated fields",
|
||||||
|
|||||||
@@ -2480,7 +2480,8 @@
|
|||||||
"activeLocales": {
|
"activeLocales": {
|
||||||
"heading": "Idiomas",
|
"heading": "Idiomas",
|
||||||
"subtitle": "Traducciones activas",
|
"subtitle": "Traducciones activas",
|
||||||
"noLocalesTip": "Configura al menos un idioma para empezar a traducir tu información"
|
"noLocalesTip": "Configura al menos un lenguaje para empezar a traducir tu información",
|
||||||
|
"noLocalesTipConfigureAction": "Configurar"
|
||||||
},
|
},
|
||||||
"completion": {
|
"completion": {
|
||||||
"heading": "Textos traducidos",
|
"heading": "Textos traducidos",
|
||||||
|
|||||||
@@ -1,17 +1,10 @@
|
|||||||
import { PencilSquare, Language } from "@medusajs/icons"
|
import { Language } from "@medusajs/icons"
|
||||||
import {
|
import { HttpTypes } from "@medusajs/types"
|
||||||
Container,
|
import { Container, Heading, Text, Tooltip } from "@medusajs/ui"
|
||||||
Heading,
|
import { useCallback, useState } from "react"
|
||||||
IconButton,
|
|
||||||
InlineTip,
|
|
||||||
Text,
|
|
||||||
Tooltip,
|
|
||||||
} from "@medusajs/ui"
|
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { IconAvatar } from "../../../../../components/common/icon-avatar"
|
import { IconAvatar } from "../../../../../components/common/icon-avatar"
|
||||||
import { HttpTypes } from "@medusajs/types"
|
import { LinkButton } from "../../../../../components/common/link-button"
|
||||||
import { useCallback, useState } from "react"
|
|
||||||
import { useNavigate } from "react-router-dom"
|
|
||||||
|
|
||||||
type ActiveLocalesSectionProps = {
|
type ActiveLocalesSectionProps = {
|
||||||
locales: HttpTypes.AdminLocale[]
|
locales: HttpTypes.AdminLocale[]
|
||||||
@@ -21,13 +14,8 @@ export const ActiveLocalesSection = ({
|
|||||||
locales,
|
locales,
|
||||||
}: ActiveLocalesSectionProps) => {
|
}: ActiveLocalesSectionProps) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const navigate = useNavigate()
|
|
||||||
const [isHovered, setIsHovered] = useState(false)
|
const [isHovered, setIsHovered] = useState(false)
|
||||||
|
|
||||||
const handleManageLocales = useCallback(() => {
|
|
||||||
navigate("/settings/translations/add-locales")
|
|
||||||
}, [navigate])
|
|
||||||
|
|
||||||
const renderLocales = useCallback(() => {
|
const renderLocales = useCallback(() => {
|
||||||
const maxLocalesToDetail = 2
|
const maxLocalesToDetail = 2
|
||||||
if (locales.length <= maxLocalesToDetail) {
|
if (locales.length <= maxLocalesToDetail) {
|
||||||
@@ -46,18 +34,26 @@ export const ActiveLocalesSection = ({
|
|||||||
<Container className="flex flex-col p-0">
|
<Container className="flex flex-col p-0">
|
||||||
<div className="flex items-center justify-between px-6 py-4">
|
<div className="flex items-center justify-between px-6 py-4">
|
||||||
<Heading level="h2">{t("translations.activeLocales.heading")}</Heading>
|
<Heading level="h2">{t("translations.activeLocales.heading")}</Heading>
|
||||||
<IconButton variant="transparent" onClick={handleManageLocales}>
|
<LinkButton
|
||||||
<PencilSquare></PencilSquare>
|
variant="interactive"
|
||||||
</IconButton>
|
className="text-ui-fg-subtle hover:text-ui-fg-subtle-hover"
|
||||||
|
to="/settings/translations/add-locales"
|
||||||
|
>
|
||||||
|
{t("translations.activeLocales.noLocalesTipConfigureAction")}
|
||||||
|
</LinkButton>
|
||||||
</div>
|
</div>
|
||||||
<div className="px-1 pb-1">
|
{hasLocales && (
|
||||||
{hasLocales ? (
|
<div className="px-1 pb-1">
|
||||||
<Tooltip
|
<Tooltip
|
||||||
open={isHovered}
|
open={isHovered}
|
||||||
content={
|
content={
|
||||||
<div className="flex flex-col gap-y-1 p-1">
|
<div className="flex flex-col gap-y-1 p-1">
|
||||||
{locales.map((locale) => (
|
{locales.map((locale) => (
|
||||||
<Text key={locale.code} size="small" weight="plus">
|
<Text
|
||||||
|
key={locale.code}
|
||||||
|
size="base"
|
||||||
|
className="text-ui-fg-subtle"
|
||||||
|
>
|
||||||
{locale.name}
|
{locale.name}
|
||||||
</Text>
|
</Text>
|
||||||
))}
|
))}
|
||||||
@@ -82,12 +78,8 @@ export const ActiveLocalesSection = ({
|
|||||||
</div>
|
</div>
|
||||||
</Container>
|
</Container>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
) : (
|
</div>
|
||||||
<InlineTip label="Tip">
|
)}
|
||||||
{t("translations.activeLocales.noLocalesTip")}
|
|
||||||
</InlineTip>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import { Container, Heading, Text } from "@medusajs/ui"
|
import { Alert, Button, Container, Heading, Text } from "@medusajs/ui"
|
||||||
import { TwoColumnPage } from "../../../components/layout/pages"
|
import { useCallback, useMemo } from "react"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
|
import { useNavigate } from "react-router-dom"
|
||||||
|
import { TwoColumnPageSkeleton } from "../../../components/common/skeleton"
|
||||||
|
import { TwoColumnPage } from "../../../components/layout/pages"
|
||||||
import {
|
import {
|
||||||
useStore,
|
useStore,
|
||||||
useTranslationSettings,
|
useTranslationSettings,
|
||||||
@@ -9,8 +12,6 @@ import {
|
|||||||
import { ActiveLocalesSection } from "./components/active-locales-section/active-locales-section"
|
import { ActiveLocalesSection } from "./components/active-locales-section/active-locales-section"
|
||||||
import { TranslationListSection } from "./components/translation-list-section/translation-list-section"
|
import { TranslationListSection } from "./components/translation-list-section/translation-list-section"
|
||||||
import { TranslationsCompletionSection } from "./components/translations-completion-section/translations-completion-section"
|
import { TranslationsCompletionSection } from "./components/translations-completion-section/translations-completion-section"
|
||||||
import { TwoColumnPageSkeleton } from "../../../components/common/skeleton"
|
|
||||||
import { useMemo } from "react"
|
|
||||||
|
|
||||||
export type TranslatableEntity = {
|
export type TranslatableEntity = {
|
||||||
label: string
|
label: string
|
||||||
@@ -22,6 +23,7 @@ export type TranslatableEntity = {
|
|||||||
|
|
||||||
export const TranslationList = () => {
|
export const TranslationList = () => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const navigate = useNavigate()
|
||||||
|
|
||||||
const { store, isPending, isError, error } = useStore()
|
const { store, isPending, isError, error } = useStore()
|
||||||
const {
|
const {
|
||||||
@@ -88,6 +90,10 @@ export const TranslationList = () => {
|
|||||||
)
|
)
|
||||||
}, [translatable_fields, statistics])
|
}, [translatable_fields, statistics])
|
||||||
|
|
||||||
|
const handleManageLocales = useCallback(() => {
|
||||||
|
navigate("/settings/translations/add-locales")
|
||||||
|
}, [navigate])
|
||||||
|
|
||||||
const isReady =
|
const isReady =
|
||||||
!!store &&
|
!!store &&
|
||||||
!isPending &&
|
!isPending &&
|
||||||
@@ -115,6 +121,25 @@ export const TranslationList = () => {
|
|||||||
{t("translations.subtitle")}
|
{t("translations.subtitle")}
|
||||||
</Text>
|
</Text>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
|
{!hasLocales && (
|
||||||
|
<Alert
|
||||||
|
variant="info"
|
||||||
|
className="bg-ui-bg-base flex items-center px-6 py-4"
|
||||||
|
>
|
||||||
|
<div className="flex items-center justify-between gap-x-2">
|
||||||
|
<p>{t("translations.activeLocales.noLocalesTip")}.</p>
|
||||||
|
<Button
|
||||||
|
onClick={handleManageLocales}
|
||||||
|
size="small"
|
||||||
|
variant="secondary"
|
||||||
|
>
|
||||||
|
{t("translations.activeLocales.noLocalesTipConfigureAction")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
<TranslationListSection
|
<TranslationListSection
|
||||||
entities={translatableEntities}
|
entities={translatableEntities}
|
||||||
hasLocales={hasLocales}
|
hasLocales={hasLocales}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export const Alert = React.forwardRef<HTMLDivElement, AlertProps>(
|
|||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={clx(
|
className={clx(
|
||||||
"bg-ui-bg-subtle text-pretty txt-compact-small grid items-start gap-x-2 rounded-lg border p-3",
|
"bg-ui-bg-subtle txt-compact-small grid items-start gap-x-2 text-pretty rounded-lg border p-3",
|
||||||
{
|
{
|
||||||
"grid-cols-[20px_1fr]": !dismissible,
|
"grid-cols-[20px_1fr]": !dismissible,
|
||||||
"grid-cols-[20px_1fr_20px]": dismissible,
|
"grid-cols-[20px_1fr_20px]": dismissible,
|
||||||
@@ -77,7 +77,7 @@ export const Alert = React.forwardRef<HTMLDivElement, AlertProps>(
|
|||||||
"text-ui-tag-neutral-icon": variant === "info",
|
"text-ui-tag-neutral-icon": variant === "info",
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
<div>{children}</div>
|
<div className="w-full">{children}</div>
|
||||||
{dismissible && (
|
{dismissible && (
|
||||||
<IconButton
|
<IconButton
|
||||||
size="2xsmall"
|
size="2xsmall"
|
||||||
|
|||||||
Reference in New Issue
Block a user