feat: adds ability to copy data from across locales (#8203)
### What? Adds ability to copy data from one locale to another at a document level. ### How? For any localized collection, you will find a new option in the document controls called `Copy to Locale`. This option will open a drawer, from here you can select your origin and destination locales. If data already exists in the destination locale, you can choose to: 1. Overwrite this data (this will copy any empty fields in your origin locale) 2. Not overwrite existing data (this will only copy data into empty fields in the destination locale) --------- Co-authored-by: Jarrod Flesch <jarrodmflesch@gmail.com>
This commit is contained in:
committed by
GitHub
parent
61d6614746
commit
601759d967
@@ -31,5 +31,21 @@ export const NestedToArrayAndBlock: CollectionConfig = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'topLevelArray',
|
||||
type: 'array',
|
||||
localized: false,
|
||||
fields: [
|
||||
{
|
||||
name: 'localizedText',
|
||||
type: 'text',
|
||||
localized: true,
|
||||
},
|
||||
{
|
||||
name: 'notLocalizedText',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
14
test/localization/collections/NoLocalizedFields/index.ts
Normal file
14
test/localization/collections/NoLocalizedFields/index.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import type { CollectionConfig } from 'payload'
|
||||
|
||||
export const noLocalizedFieldsCollectionSlug = 'no-localized-fields'
|
||||
|
||||
export const NoLocalizedFieldsCollection: CollectionConfig = {
|
||||
slug: noLocalizedFieldsCollectionSlug,
|
||||
fields: [
|
||||
{
|
||||
name: 'text',
|
||||
type: 'text',
|
||||
localized: false,
|
||||
},
|
||||
],
|
||||
}
|
||||
31
test/localization/collections/RichText/index.ts
Normal file
31
test/localization/collections/RichText/index.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import type { CollectionConfig } from 'payload/types'
|
||||
|
||||
import { lexicalEditor, TreeViewFeature } from '@payloadcms/richtext-lexical'
|
||||
import { slateEditor } from '@payloadcms/richtext-slate'
|
||||
|
||||
export const richTextSlug = 'richText'
|
||||
|
||||
export const RichTextCollection: CollectionConfig = {
|
||||
slug: richTextSlug,
|
||||
fields: [
|
||||
{
|
||||
type: 'richText',
|
||||
name: 'richText',
|
||||
label: 'Rich Text',
|
||||
localized: true,
|
||||
editor: slateEditor({
|
||||
admin: {
|
||||
elements: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: 'lexical',
|
||||
type: 'richText',
|
||||
localized: true,
|
||||
editor: lexicalEditor({
|
||||
features: ({ defaultFeatures }) => [...defaultFeatures, TreeViewFeature()],
|
||||
}),
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -13,6 +13,8 @@ import { LocalizedWithinLocalized } from './collections/LocalizedWithinLocalized
|
||||
import { NestedArray } from './collections/NestedArray/index.js'
|
||||
import { NestedFields } from './collections/NestedFields/index.js'
|
||||
import { NestedToArrayAndBlock } from './collections/NestedToArrayAndBlock/index.js'
|
||||
import { NoLocalizedFieldsCollection } from './collections/NoLocalizedFields/index.js'
|
||||
import { RichTextCollection } from './collections/RichText/index.js'
|
||||
import { Tab } from './collections/Tab/index.js'
|
||||
import {
|
||||
blocksWithLocalizedSameName,
|
||||
@@ -54,6 +56,7 @@ export default buildConfigWithDefaults({
|
||||
},
|
||||
},
|
||||
collections: [
|
||||
RichTextCollection,
|
||||
BlocksCollection,
|
||||
NestedArray,
|
||||
NestedFields,
|
||||
@@ -119,6 +122,7 @@ export default buildConfigWithDefaults({
|
||||
},
|
||||
],
|
||||
},
|
||||
NoLocalizedFieldsCollection,
|
||||
ArrayCollection,
|
||||
{
|
||||
fields: [
|
||||
@@ -392,6 +396,16 @@ export default buildConfigWithDefaults({
|
||||
],
|
||||
slug: 'global-array',
|
||||
},
|
||||
{
|
||||
fields: [
|
||||
{
|
||||
name: 'text',
|
||||
localized: true,
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
slug: 'global-text',
|
||||
},
|
||||
],
|
||||
localization: {
|
||||
defaultLocale,
|
||||
|
||||
@@ -3,7 +3,6 @@ import type { Page } from '@playwright/test'
|
||||
import { expect, test } from '@playwright/test'
|
||||
import { openDocControls } from 'helpers/e2e/openDocControls.js'
|
||||
import path from 'path'
|
||||
import { wait } from 'payload/shared'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
import type { PayloadTestSDK } from '../helpers/sdk/index.js'
|
||||
@@ -18,7 +17,10 @@ import {
|
||||
import { AdminUrlUtil } from '../helpers/adminUrlUtil.js'
|
||||
import { initPayloadE2ENoConfig } from '../helpers/initPayloadE2ENoConfig.js'
|
||||
import { POLL_TOPASS_TIMEOUT, TEST_TIMEOUT_LONG } from '../playwright.config.js'
|
||||
import { nestedToArrayAndBlockCollectionSlug } from './collections/NestedToArrayAndBlock/index.js'
|
||||
import { richTextSlug } from './collections/RichText/index.js'
|
||||
import {
|
||||
defaultLocale,
|
||||
englishTitle,
|
||||
localizedPostsSlug,
|
||||
spanishLocale,
|
||||
@@ -40,7 +42,6 @@ const { beforeAll, describe } = test
|
||||
let url: AdminUrlUtil
|
||||
let urlWithRequiredLocalizedFields: AdminUrlUtil
|
||||
|
||||
const defaultLocale = 'en'
|
||||
const title = 'english title'
|
||||
const spanishTitle = 'spanish title'
|
||||
const arabicTitle = 'arabic title'
|
||||
@@ -49,13 +50,15 @@ const description = 'description'
|
||||
let page: Page
|
||||
let payload: PayloadTestSDK<Config>
|
||||
let serverURL: string
|
||||
let richTextURL: AdminUrlUtil
|
||||
|
||||
describe('Localization', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig({ dirname }))
|
||||
;({ payload, serverURL } = await initPayloadE2ENoConfig<Config>({ dirname }))
|
||||
|
||||
url = new AdminUrlUtil(serverURL, localizedPostsSlug)
|
||||
richTextURL = new AdminUrlUtil(serverURL, richTextSlug)
|
||||
urlWithRequiredLocalizedFields = new AdminUrlUtil(serverURL, withRequiredLocalizedFields)
|
||||
|
||||
const context = await browser.newContext()
|
||||
@@ -251,6 +254,149 @@ describe('Localization', () => {
|
||||
await expect(page.locator('#field-children .rs__menu')).toContainText('spanish-relation2')
|
||||
})
|
||||
})
|
||||
|
||||
describe('copy localized data', () => {
|
||||
test('should show Copy To Locale button and drawer', async () => {
|
||||
await changeLocale(page, defaultLocale)
|
||||
await createAndSaveDoc(page, url, { description, title })
|
||||
await openCopyToLocaleDrawer(page)
|
||||
await expect(page.locator('.copy-locale-data__content')).toBeVisible()
|
||||
})
|
||||
|
||||
test('should copy data to correct locale', async () => {
|
||||
await createAndSaveDoc(page, url, { title })
|
||||
|
||||
await openCopyToLocaleDrawer(page)
|
||||
await setToLocale(page, 'Spanish')
|
||||
await runCopy(page)
|
||||
|
||||
await expect(page.locator('#field-title')).toHaveValue(title)
|
||||
})
|
||||
|
||||
test('should copy rich text data to correct locale', async () => {
|
||||
await changeLocale(page, defaultLocale)
|
||||
await page.goto(richTextURL.create)
|
||||
const richTextField = page.locator('#field-richText')
|
||||
const richTextContent = '<p>This is rich text in English</p>'
|
||||
await richTextField.fill(richTextContent)
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
await openCopyToLocaleDrawer(page)
|
||||
await setToLocale(page, 'Spanish')
|
||||
await runCopy(page)
|
||||
|
||||
await expect(richTextField).toContainText(richTextContent)
|
||||
})
|
||||
|
||||
test('should copy nested array to locale', async () => {
|
||||
const sampleText = 'Copy this text'
|
||||
const nestedArrayURL = new AdminUrlUtil(serverURL, nestedToArrayAndBlockCollectionSlug)
|
||||
await page.goto(nestedArrayURL.create)
|
||||
await changeLocale(page, 'ar')
|
||||
const addArrayRow = page.locator('.array-field__add-row')
|
||||
await addArrayRow.click()
|
||||
|
||||
const arrayField = page.locator('#field-topLevelArray__0__localizedText')
|
||||
await expect(arrayField).toBeVisible()
|
||||
await arrayField.fill(sampleText)
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
await openCopyToLocaleDrawer(page)
|
||||
await setToLocale(page, 'English')
|
||||
await runCopy(page)
|
||||
|
||||
await expect(arrayField).toHaveValue(sampleText)
|
||||
})
|
||||
|
||||
test('should default source locale to current locale', async () => {
|
||||
await changeLocale(page, spanishLocale)
|
||||
await createAndSaveDoc(page, url, { title })
|
||||
await openCopyToLocaleDrawer(page)
|
||||
|
||||
const fromLocaleField = page.locator('#field-fromLocale')
|
||||
await expect(fromLocaleField).toContainText('Spanish')
|
||||
await page.locator('.drawer-close-button').click()
|
||||
})
|
||||
|
||||
test('should not overwrite existing data when overwrite is unchecked', async () => {
|
||||
await changeLocale(page, defaultLocale)
|
||||
await createAndSaveDoc(page, url, { title: englishTitle, description })
|
||||
|
||||
await changeLocale(page, spanishLocale)
|
||||
await fillValues({ title: spanishTitle, description: 'Spanish description' })
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
await changeLocale(page, defaultLocale)
|
||||
await openCopyToLocaleDrawer(page)
|
||||
await setToLocale(page, 'Spanish')
|
||||
const overwriteCheckbox = page.locator('#field-overwriteExisting')
|
||||
await expect(overwriteCheckbox).not.toBeChecked()
|
||||
await runCopy(page)
|
||||
|
||||
await expect(page.locator('#field-title')).toHaveValue(spanishTitle)
|
||||
await expect(page.locator('#field-description')).toHaveValue('Spanish description')
|
||||
})
|
||||
|
||||
test('should overwrite existing data when overwrite is checked', async () => {
|
||||
await changeLocale(page, defaultLocale)
|
||||
await createAndSaveDoc(page, url, { title: englishTitle, description })
|
||||
await changeLocale(page, spanishLocale)
|
||||
await fillValues({ title: spanishTitle })
|
||||
await saveDocAndAssert(page)
|
||||
await changeLocale(page, defaultLocale)
|
||||
|
||||
await openCopyToLocaleDrawer(page)
|
||||
await setToLocale(page, 'Spanish')
|
||||
const overwriteCheckbox = page.locator('#field-overwriteExisting')
|
||||
await overwriteCheckbox.click()
|
||||
await runCopy(page)
|
||||
|
||||
await expect(page.locator('#field-title')).toHaveValue(englishTitle)
|
||||
})
|
||||
|
||||
test('should not include current locale in toLocale options', async () => {
|
||||
await changeLocale(page, defaultLocale)
|
||||
await createAndSaveDoc(page, url, { title })
|
||||
await openCopyToLocaleDrawer(page)
|
||||
const toLocaleDropdown = page.locator('#field-toLocale')
|
||||
await toLocaleDropdown.click()
|
||||
|
||||
const options = await page
|
||||
.locator('.rs__option')
|
||||
.evaluateAll((els) => els.map((el) => el.textContent))
|
||||
|
||||
await expect.poll(() => options).not.toContain('English')
|
||||
await page.locator('.drawer-close-button').click()
|
||||
})
|
||||
|
||||
test('should handle back to back copies', async () => {
|
||||
await changeLocale(page, defaultLocale)
|
||||
await createAndSaveDoc(page, url, { title })
|
||||
|
||||
await openCopyToLocaleDrawer(page)
|
||||
await setToLocale(page, 'Spanish')
|
||||
await runCopy(page)
|
||||
await expect(page.locator('#field-title')).toHaveValue(title)
|
||||
|
||||
await openCopyToLocaleDrawer(page)
|
||||
await setToLocale(page, 'Hungarian')
|
||||
await runCopy(page)
|
||||
await expect(page.locator('#field-title')).toHaveValue(title)
|
||||
})
|
||||
|
||||
test('should throw error if unsaved data', async () => {
|
||||
await createAndSaveDoc(page, url, { title })
|
||||
await fillValues({ title: 'updated' })
|
||||
const docControls = page.locator('.doc-controls__popup')
|
||||
await docControls.click()
|
||||
|
||||
const copyButton = page.locator('#copy-locale-data__button')
|
||||
await expect(copyButton).toBeVisible()
|
||||
await copyButton.click()
|
||||
|
||||
await expect(page.locator('.payload-toast-container')).toContainText('unsaved')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
async function fillValues(data: Partial<LocalizedPost>) {
|
||||
@@ -263,3 +409,31 @@ async function fillValues(data: Partial<LocalizedPost>) {
|
||||
await page.locator('#field-description').fill(descVal)
|
||||
}
|
||||
}
|
||||
|
||||
async function runCopy(page) {
|
||||
const copyDrawerClose = page.locator('.copy-locale-data__sub-header button')
|
||||
await expect(copyDrawerClose).toBeVisible()
|
||||
await copyDrawerClose.click()
|
||||
}
|
||||
|
||||
async function createAndSaveDoc(page, url, values) {
|
||||
await page.goto(url.create)
|
||||
await fillValues(values)
|
||||
await saveDocAndAssert(page)
|
||||
}
|
||||
|
||||
async function openCopyToLocaleDrawer(page) {
|
||||
const docControls = page.locator('.doc-controls__popup')
|
||||
await docControls.click()
|
||||
const copyButton = page.locator('#copy-locale-data__button')
|
||||
await expect(copyButton).toBeVisible()
|
||||
await copyButton.click()
|
||||
await expect(page.locator('.copy-locale-data__content')).toBeVisible()
|
||||
}
|
||||
|
||||
async function setToLocale(page, locale) {
|
||||
const toField = page.locator('#field-toLocale')
|
||||
await toField.click({ delay: 100 })
|
||||
const options = page.locator('.rs__option')
|
||||
await options.locator(`text=${locale}`).click()
|
||||
}
|
||||
|
||||
@@ -11,11 +11,13 @@ export interface Config {
|
||||
users: UserAuthOperations;
|
||||
};
|
||||
collections: {
|
||||
richText: RichText;
|
||||
'blocks-fields': BlocksField;
|
||||
'nested-arrays': NestedArray;
|
||||
'nested-field-tables': NestedFieldTable;
|
||||
users: User;
|
||||
'localized-posts': LocalizedPost;
|
||||
'no-localized-fields': NoLocalizedField;
|
||||
'array-fields': ArrayField;
|
||||
'localized-required': LocalizedRequired;
|
||||
'with-localized-relationship': WithLocalizedRelationship;
|
||||
@@ -33,11 +35,13 @@ export interface Config {
|
||||
};
|
||||
collectionsJoins: {};
|
||||
collectionsSelect: {
|
||||
richText: RichTextSelect<false> | RichTextSelect<true>;
|
||||
'blocks-fields': BlocksFieldsSelect<false> | BlocksFieldsSelect<true>;
|
||||
'nested-arrays': NestedArraysSelect<false> | NestedArraysSelect<true>;
|
||||
'nested-field-tables': NestedFieldTablesSelect<false> | NestedFieldTablesSelect<true>;
|
||||
users: UsersSelect<false> | UsersSelect<true>;
|
||||
'localized-posts': LocalizedPostsSelect<false> | LocalizedPostsSelect<true>;
|
||||
'no-localized-fields': NoLocalizedFieldsSelect<false> | NoLocalizedFieldsSelect<true>;
|
||||
'array-fields': ArrayFieldsSelect<false> | ArrayFieldsSelect<true>;
|
||||
'localized-required': LocalizedRequiredSelect<false> | LocalizedRequiredSelect<true>;
|
||||
'with-localized-relationship': WithLocalizedRelationshipSelect<false> | WithLocalizedRelationshipSelect<true>;
|
||||
@@ -58,17 +62,19 @@ export interface Config {
|
||||
};
|
||||
globals: {
|
||||
'global-array': GlobalArray;
|
||||
'global-text': GlobalText;
|
||||
};
|
||||
globalsSelect: {
|
||||
'global-array': GlobalArraySelect<false> | GlobalArraySelect<true>;
|
||||
'global-text': GlobalTextSelect<false> | GlobalTextSelect<true>;
|
||||
};
|
||||
locale: 'en' | 'es' | 'pt' | 'ar' | 'hu';
|
||||
user: User & {
|
||||
collection: 'users';
|
||||
};
|
||||
jobs?: {
|
||||
jobs: {
|
||||
tasks: unknown;
|
||||
workflows?: unknown;
|
||||
workflows: unknown;
|
||||
};
|
||||
}
|
||||
export interface UserAuthOperations {
|
||||
@@ -89,6 +95,35 @@ export interface UserAuthOperations {
|
||||
password: string;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "richText".
|
||||
*/
|
||||
export interface RichText {
|
||||
id: string;
|
||||
richText?:
|
||||
| {
|
||||
[k: string]: unknown;
|
||||
}[]
|
||||
| null;
|
||||
lexical?: {
|
||||
root: {
|
||||
type: string;
|
||||
children: {
|
||||
type: string;
|
||||
version: number;
|
||||
[k: string]: unknown;
|
||||
}[];
|
||||
direction: ('ltr' | 'rtl') | null;
|
||||
format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | '';
|
||||
indent: number;
|
||||
version: number;
|
||||
};
|
||||
[k: string]: unknown;
|
||||
} | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "blocks-fields".
|
||||
@@ -118,6 +153,21 @@ export interface BlocksField {
|
||||
blockType: 'blockInsideBlock';
|
||||
}[]
|
||||
| null;
|
||||
nonLocalizedBlocksField?:
|
||||
| {
|
||||
array?:
|
||||
| {
|
||||
link?: {
|
||||
label?: string | null;
|
||||
};
|
||||
id?: string | null;
|
||||
}[]
|
||||
| null;
|
||||
id?: string | null;
|
||||
blockName?: string | null;
|
||||
blockType: 'blockInsideBlock';
|
||||
}[]
|
||||
| null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
@@ -244,6 +294,16 @@ export interface User {
|
||||
lockUntil?: string | null;
|
||||
password?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "no-localized-fields".
|
||||
*/
|
||||
export interface NoLocalizedField {
|
||||
id: string;
|
||||
text?: string | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "array-fields".
|
||||
@@ -419,6 +479,13 @@ export interface Nested {
|
||||
blockType: 'block';
|
||||
}[]
|
||||
| null;
|
||||
topLevelArray?:
|
||||
| {
|
||||
localizedText?: string | null;
|
||||
notLocalizedText?: string | null;
|
||||
id?: string | null;
|
||||
}[]
|
||||
| null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
@@ -559,6 +626,10 @@ export interface LocalizedWithinLocalized {
|
||||
export interface PayloadLockedDocument {
|
||||
id: string;
|
||||
document?:
|
||||
| ({
|
||||
relationTo: 'richText';
|
||||
value: string | RichText;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'blocks-fields';
|
||||
value: string | BlocksField;
|
||||
@@ -579,6 +650,10 @@ export interface PayloadLockedDocument {
|
||||
relationTo: 'localized-posts';
|
||||
value: string | LocalizedPost;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'no-localized-fields';
|
||||
value: string | NoLocalizedField;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'array-fields';
|
||||
value: string | ArrayField;
|
||||
@@ -665,6 +740,16 @@ export interface PayloadMigration {
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "richText_select".
|
||||
*/
|
||||
export interface RichTextSelect<T extends boolean = true> {
|
||||
richText?: T;
|
||||
lexical?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "blocks-fields_select".
|
||||
@@ -701,6 +786,26 @@ export interface BlocksFieldsSelect<T extends boolean = true> {
|
||||
blockName?: T;
|
||||
};
|
||||
};
|
||||
nonLocalizedBlocksField?:
|
||||
| T
|
||||
| {
|
||||
blockInsideBlock?:
|
||||
| T
|
||||
| {
|
||||
array?:
|
||||
| T
|
||||
| {
|
||||
link?:
|
||||
| T
|
||||
| {
|
||||
label?: T;
|
||||
};
|
||||
id?: T;
|
||||
};
|
||||
id?: T;
|
||||
blockName?: T;
|
||||
};
|
||||
};
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
@@ -821,6 +926,15 @@ export interface LocalizedPostsSelect<T extends boolean = true> {
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "no-localized-fields_select".
|
||||
*/
|
||||
export interface NoLocalizedFieldsSelect<T extends boolean = true> {
|
||||
text?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "array-fields_select".
|
||||
@@ -965,6 +1079,13 @@ export interface NestedSelect<T extends boolean = true> {
|
||||
blockName?: T;
|
||||
};
|
||||
};
|
||||
topLevelArray?:
|
||||
| T
|
||||
| {
|
||||
localizedText?: T;
|
||||
notLocalizedText?: T;
|
||||
id?: T;
|
||||
};
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
@@ -1169,6 +1290,16 @@ export interface GlobalArray {
|
||||
updatedAt?: string | null;
|
||||
createdAt?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "global-text".
|
||||
*/
|
||||
export interface GlobalText {
|
||||
id: string;
|
||||
text?: string | null;
|
||||
updatedAt?: string | null;
|
||||
createdAt?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "global-array_select".
|
||||
@@ -1184,6 +1315,16 @@ export interface GlobalArraySelect<T extends boolean = true> {
|
||||
createdAt?: T;
|
||||
globalType?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "global-text_select".
|
||||
*/
|
||||
export interface GlobalTextSelect<T extends boolean = true> {
|
||||
text?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
globalType?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "auth".
|
||||
|
||||
Reference in New Issue
Block a user