Skip to content

Commit

Permalink
✨ Enable linking to other languages #1438
Browse files Browse the repository at this point in the history
  • Loading branch information
fernandolucchesi committed Jan 12, 2023
1 parent 293a03a commit f194f97
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 30 deletions.
12 changes: 12 additions & 0 deletions studio/helpers/referenceFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@ export const filterByPages = ({ document }: { document: SanityDocument }) => {
}
}

export const filterByPagesInOtherLanguages = ({ document }: { document: SanityDocument }) => {
const lang = langOrDefault(document._lang)

return {
filter: `(_type match 'route_*' && !(_type match $routeLang)) || _type in ['news', 'localNews', 'magazine'] && _lang != $lang`,
params: {
routeLang: `route_${lang}*`,
lang: lang,
},
}
}

export const filterByRouteNewsAndTitle = ({ document }: { document: SanityDocument }) => {
const lang = langOrDefault(document._lang)
const title = document.title || ''
Expand Down
14 changes: 7 additions & 7 deletions studio/schemas/editors/blockContentType.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React from 'react'
import { ExternalLinkRenderer, SuperScriptRenderer, SubScriptRenderer } from '../components'
import { link, attach_file, external_link } from '@equinor/eds-icons'
import { IconSuperScript, IconSubScript, EdsIcon } from '../../icons'
import type { BlockFieldType } from '../../types/schemaTypes'
import routes from '../routes'
import { filterByPages, filterByRouteAndNewsInOtherLanguages } from '../../helpers/referenceFilters'
import { attach_file, external_link, link } from '@equinor/eds-icons'
import type { Rule, ValidationContext } from '@sanity/types'
import { filterByPages, filterByRouteAndNewsInOtherLanguages } from '../../helpers/referenceFilters'
import { EdsIcon, IconSubScript, IconSuperScript } from '../../icons'
import { Flags } from '../../src/lib/datasetHelpers'
import type { BlockFieldType } from '../../types/schemaTypes'
import { ExternalLinkRenderer, SubScriptRenderer, SuperScriptRenderer } from '../components'
import routes from '../routes'

export type BlockContentProps = {
h1?: boolean
Expand Down Expand Up @@ -155,6 +154,7 @@ export const configureBlockContent = (options: BlockContentProps = {}): BlockFie
},
{
title: 'Reference',
// Oh no! There is a typo here :(
name: 'referenceToOtherLanguange',
type: 'reference',
to: [...newsType, ...routes],
Expand Down
52 changes: 46 additions & 6 deletions studio/schemas/objects/linkSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import { link } from '@equinor/eds-icons'
import type { Reference, Rule, ValidationContext } from '@sanity/types'
import { filterByPages, filterByPagesInOtherLanguages } from '../../helpers/referenceFilters'
import { EdsIcon } from '../../icons'
import { validateInternalOrExternalUrl } from '../validations/validateInternalOrExternalUrl'
import type { Rule, ValidationContext, Reference } from '@sanity/types'
import { Flags } from '../../src/lib/datasetHelpers'
import routes from '../routes'
import { validateInternalOrExternalUrl } from '../validations/validateInternalOrExternalUrl'
import { AnchorLinkDescription } from './anchorReferenceField'
import { filterByPages } from '../../helpers/referenceFilters'
import { Flags } from '../../src/lib/datasetHelpers'
// eslint-disable-next-line import/no-unresolved
import client from 'part:@sanity/base/client'

export type ReferenceTarget = {
type: string
}

export type LinkSelector = {
_type: 'linkSelector'
linkToOtherLanguage?: boolean
reference?: Reference
referenceToOtherLanguage?: Reference
url?: string
label?: string
ariaLabel?: string
Expand Down Expand Up @@ -52,19 +56,54 @@ const LinkField = {
},
],
fields: [
{

This comment has been minimized.

Copy link
@SvSven

SvSven Jan 17, 2023

Contributor

Should this have an initialValue of false?

This comment has been minimized.

Copy link
@fernandolucchesi

fernandolucchesi Jan 17, 2023

Author Contributor

It is the same bc the logic is checking for true, so undefined | false falls into the same group
image.

This comment has been minimized.

Copy link
@SvSven

SvSven Jan 19, 2023

Contributor

Yeah and we need that for backward compatibility - I never like the way Sanity has undefined by default 😬
But if it works it works 🤷‍♀️

name: 'linkToOtherLanguage',
type: 'boolean',
title: 'Link to a different language',
hidden: !Flags.IS_DEV,
description: 'Use this if you want to create a link to a page of a different language',
},
{
name: 'reference',
title: 'Internal link',
description: 'Use this field to reference an internal page.',
type: 'reference',
hidden: ({ parent }: { parent: LinkSelector }) => parent.linkToOtherLanguage,
validation: (Rule: Rule) =>
Rule.custom(async (value: any, context: ValidationContext) => {
const { parent, document } = context as { parent: LinkSelector; document: { _lang?: string } }
if (parent.linkToOtherLanguage) return true
const referenceLang = await client.fetch(
/* groq */ `*[_id == $id][0]{"lang": coalesce(content->_lang, _lang)}.lang`,
{
id: value._ref,
},
)
if (Flags.IS_DEV && document._lang !== referenceLang)
return 'Reference must have the same language as the document'
return validateInternalOrExternalUrl(value, parent.url)
}),
to: defaultReferenceTargets,
options: {
filter: filterByPages,
disableNew: true,
},
},
{
name: 'referenceToOtherLanguage',
title: 'Internal link',
description: 'Use this field to reference an internal page.',
type: 'reference',
hidden: ({ parent }: { parent: LinkSelector }) => !parent.linkToOtherLanguage,
validation: (Rule: Rule) =>
Rule.custom((value: any, context: ValidationContext) => {
const { parent } = context as { parent: LinkSelector }
if (!parent.linkToOtherLanguage) return true
return validateInternalOrExternalUrl(value, parent.url)
}),
to: defaultReferenceTargets,
options: {
filter: filterByPages,
filter: filterByPagesInOtherLanguages,
disableNew: true,
},
},
Expand All @@ -76,7 +115,8 @@ const LinkField = {
validation: (Rule: Rule) =>
Rule.uri({ scheme: ['http', 'https', 'tel', 'mailto'] }).custom((value: any, context: ValidationContext) => {
const { parent } = context as { parent: LinkSelector }
return validateInternalOrExternalUrl(value, parent.reference)
const connectedField = parent.linkToOtherLanguage ? parent.referenceToOtherLanguage : parent.reference
return validateInternalOrExternalUrl(value, connectedField)
}),
},
{
Expand Down
24 changes: 20 additions & 4 deletions web/lib/queries/common/actions/linkSelectorFields.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
import slugReference from '../slugReference'

const lang = /* groq */ `
select(_type match 'route_*' =>
content->_lang,
_lang
)
`

export const linkReferenceFields = /* groq */ `
{
"type": _type,
"slug": ${slugReference},
"lang": ${lang},
}
`

const linkSelectorFields = /* groq */ `
_type == "linkSelector" => {
"id": _key,
Expand All @@ -8,10 +23,11 @@ _type == "linkSelector" => {
),
label,
ariaLabel,
"link": reference-> {
"type": _type,
"slug": ${slugReference}
},
"link": select(
linkToOtherLanguage == true =>
referenceToOtherLanguage->${linkReferenceFields},
reference->${linkReferenceFields},
),
"href": url,
anchorReference,
}
Expand Down
18 changes: 9 additions & 9 deletions web/lib/queries/common/pageContentFields.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { noDrafts, sameLang } from './langAndDrafts'
import slugReference from './slugReference'
import markDefs from './blockEditorMarks'
import linkSelectorFields from './actions/linkSelectorFields'
import downloadableFileFields from './actions/downloadableFileFields'
import downloadableImageFields from './actions/downloadableImageFields'
import { eventPromotionFields, pastEventsQuery, futureEventsQuery } from './eventPromotion'
import linkSelectorFields, { linkReferenceFields } from './actions/linkSelectorFields'
import markDefs from './blockEditorMarks'
import { eventPromotionFields, futureEventsQuery, pastEventsQuery } from './eventPromotion'
import { noDrafts, sameLang } from './langAndDrafts'
import promoteMagazine from './promotions/promoteMagazine'
import { publishDateTimeQuery } from './publishDateTime'

Expand Down Expand Up @@ -146,10 +145,11 @@ const pageContentFields = /* groq */ `
"label": link.label,
"ariaLabel": link.ariaLabel,
"anchorReference": link.anchorReference,
"link": link.reference-> {
"type": _type,
"slug": ${slugReference}
},
"link": select(
link.linkToOtherLanguage == true =>
link.referenceToOtherLanguage->${linkReferenceFields},
link.reference->${linkReferenceFields},
),
"href": link.url,
"type": select(
defined(link.url) => "externalUrl",
Expand Down
7 changes: 5 additions & 2 deletions web/pageComponents/shared/ButtonLink.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import NextLink from 'next/link'
import { ButtonLink as Link } from '@components'
import NextLink from 'next/link'
import { Flags } from '../../common/helpers/datasetHelpers'
import { getUrlFromAction } from '../../common/helpers/getUrlFromAction'
import { getLocaleFromName } from '../../lib/localization'
import type { LinkData } from '../../types/types'

export const ButtonLink = ({ action, ...rest }: { action: LinkData }) => {
Expand All @@ -14,8 +16,9 @@ export const ButtonLink = ({ action, ...rest }: { action: LinkData }) => {

// If the URL is a static AEM page it should behave as an internal link in the web
if (type === 'internalUrl') {
const locale = getLocaleFromName(action.link?.lang)
return (
<NextLink passHref href={url} legacyBehavior>
<NextLink passHref locale={Flags.IS_DEV ? locale : undefined} href={url} legacyBehavior>
<Link aria-label={ariaLabel} {...rest}>
{label}
</Link>
Expand Down
4 changes: 2 additions & 2 deletions web/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
SanityImageCrop,
SanityImageHotspot,
SanityImageObject,
SanityImageSource,
SanityImageSource
} from '@sanity/image-url/lib/types/types'

export type CaptionData = {
Expand Down Expand Up @@ -33,7 +33,7 @@ export type LinkData = {
id?: string
label: string
ariaLabel?: string
link?: { slug: string; type: string }
link?: { slug: string; type: string, lang: string }
href?: string
extension?: string
fileName?: string
Expand Down

0 comments on commit f194f97

Please sign in to comment.