1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-10 15:47:32 +00:00

Resolve "Name elements in the element modal"

This commit is contained in:
Peter Evans 2024-03-01 14:14:55 +00:00 committed by Jérémie Pardou
parent 55672c2117
commit a8695a5883
5 changed files with 383 additions and 19 deletions
web-frontend
locales
modules/builder
test/unit/builder

View file

@ -5,7 +5,9 @@
"wrong": "Something went wrong",
"none": "None",
"free": "Free",
"comingSoon": "Coming soon..."
"comingSoon": "Coming soon...",
"table": "Table",
"link": "Link"
},
"action": {
"upload": "Upload",

View file

@ -2,7 +2,9 @@
<a class="select__item-link" @click="$emit('click')">
<span class="select__item-name">
<i :class="`${elementType.iconClass} select__item-icon`"></i>
<span class="select__item-name-text">{{ elementType.name }}</span>
<span class="select__item-name-text">{{
elementType.getDisplayName(element, applicationContext)
}}</span>
</span>
</a>
</template>
@ -10,6 +12,7 @@
<script>
export default {
name: 'ElementsListItem',
inject: ['builder', 'page', 'mode'],
props: {
element: {
type: Object,
@ -20,6 +23,14 @@ export default {
elementType() {
return this.$registry.get('element', this.element.type)
},
applicationContext() {
return {
builder: this.builder,
page: this.page,
mode: this.mode,
element: this.element,
}
},
},
}
</script>

View file

@ -387,7 +387,7 @@ export class FormDataProviderType extends DataProviderType {
parseInt(elementId)
)
const elementType = this.app.$registry.get('element', element.type)
const name = elementType.getFormDataName(element, applicationContext)
const name = elementType.getDisplayName(element, applicationContext)
const order = this.app.store.getters['element/getElementPosition'](
page,
element

View file

@ -86,6 +86,17 @@ export class ElementType extends Registerable {
return []
}
/**
* Returns a display name for this element, so it can be distinguished from
* other elements of the same type.
* @param {object} element - The element we want to get a display name for.
* @param {object} applicationContext - The context of the current application
* @returns {string} this element's display name.
*/
getDisplayName(element, applicationContext) {
return this.name
}
getEvents() {
return this.events.map((EventType) => new EventType(this.app))
}
@ -277,25 +288,21 @@ export class FormElementType extends ElementType {
}
/**
* This name is used by the data explorer to show the form element.
*
* @param element - The form element instance
* @param applicationContext - The context of the current application
* @returns {string} - The name of the form element
* Returns a display name for this element, so it can be distinguished from
* other elements of the same type.
* @param {object} element - The element we want to get a display name for.
* @param {object} applicationContext
* @returns {string} this element's display name.
*/
getFormDataName(element, applicationContext) {
getDisplayName(element, applicationContext) {
if (element.label) {
return this.resolveFormula(element.label, applicationContext)
const resolvedName = this.resolveFormula(
element.label,
applicationContext
)
return resolvedName.length ? resolvedName : this.name
}
return this.generateFromDataName(element, applicationContext)
}
generateFromDataName(element, applicationContext) {
const elementPosition = this.app.store.getters[
'element/getElementPosition'
](applicationContext.page, element, true)
return `${this.name} ${elementPosition}`
return this.name
}
afterCreate(element, page) {
@ -348,6 +355,17 @@ export class InputTextElementType extends FormElementType {
return 'string'
}
getDisplayName(element, applicationContext) {
const displayValue =
element.label || element.default_value || element.placeholder
if (displayValue && displayValue.length) {
const resolvedName = this.resolveFormula(displayValue, applicationContext)
return resolvedName.length ? resolvedName : this.name
}
return this.name
}
getInitialFormDataValue(element, applicationContext) {
return this.resolveFormula(element.default_value, {
element,
@ -380,6 +398,17 @@ export class HeadingElementType extends ElementType {
get generalFormComponent() {
return HeadingElementForm
}
getDisplayName(element, applicationContext) {
if (element.value && element.value.length) {
const resolvedName = this.resolveFormula(
element.value,
applicationContext
)
return resolvedName.length ? resolvedName : this.name
}
return this.name
}
}
export class TextElementType extends ElementType {
@ -406,6 +435,17 @@ export class TextElementType extends ElementType {
get generalFormComponent() {
return TextElementForm
}
getDisplayName(element, applicationContext) {
if (element.value && element.value.length) {
const resolvedName = this.resolveFormula(
element.value,
applicationContext
)
return resolvedName.length ? resolvedName : this.name
}
return this.name
}
}
export class LinkElementType extends ElementType {
@ -436,6 +476,37 @@ export class LinkElementType extends ElementType {
isInError({ element, builder }) {
return pathParametersInError(element, builder)
}
getDisplayName(element, applicationContext) {
let displayValue = ''
let destination = ''
if (element.navigation_type === 'page') {
const builder = applicationContext.builder
const destinationPage = builder.pages.find(
({ id }) => id === element.navigate_to_page_id
)
if (destinationPage) {
destination = `${destinationPage.name}`
}
} else if (element.navigation_type === 'custom') {
destination = this.resolveFormula(
element.navigate_to_url,
applicationContext
)
}
if (destination) {
destination = ` -> ${destination}`
}
if (element.value) {
displayValue = this.resolveFormula(element.value, applicationContext)
}
return displayValue
? `${displayValue}${destination}`
: `${this.name}${destination}`
}
}
export class ImageElementType extends ElementType {
@ -462,6 +533,17 @@ export class ImageElementType extends ElementType {
get generalFormComponent() {
return ImageElementForm
}
getDisplayName(element, applicationContext) {
if (element.alt_text && element.alt_text.length) {
const resolvedName = this.resolveFormula(
element.alt_text,
applicationContext
)
return resolvedName.length ? resolvedName : this.name
}
return this.name
}
}
export class ButtonElementType extends ElementType {
@ -492,6 +574,17 @@ export class ButtonElementType extends ElementType {
get events() {
return [ClickEvent]
}
getDisplayName(element, applicationContext) {
if (element.value && element.value.length) {
const resolvedName = this.resolveFormula(
element.value,
applicationContext
)
return resolvedName.length ? resolvedName : this.name
}
return this.name
}
}
export class TableElementType extends ElementType {
@ -559,6 +652,19 @@ export class TableElementType extends ElementType {
})
return collectionFieldsInError.includes(true)
}
getDisplayName(element, { page }) {
let displayValue = ''
if (element.data_source_id) {
const dataSource = this.app.store.getters[
'dataSource/getPageDataSourceById'
](page, element.data_source_id)
displayValue = dataSource
? `${dataSource.name} ${this.name.toLowerCase()}`
: ''
}
return displayValue.length ? displayValue : this.name
}
}
export class DropdownElementType extends FormElementType {
@ -596,6 +702,17 @@ export class DropdownElementType extends FormElementType {
...applicationContext,
})
}
getDisplayName(element, applicationContext) {
const displayValue =
element.label || element.default_value || element.placeholder
if (displayValue && displayValue.length) {
const resolvedName = this.resolveFormula(displayValue, applicationContext)
return resolvedName.length ? resolvedName : this.name
}
return this.name
}
}
export class FormContainerElementType extends ContainerElementType {
@ -703,4 +820,12 @@ export class IFrameElementType extends ElementType {
get generalFormComponent() {
return IFrameElementForm
}
getDisplayName(element, applicationContext) {
if (element.url && element.url.length) {
const resolvedName = this.resolveFormula(element.url, applicationContext)
return resolvedName.length ? resolvedName : this.name
}
return this.name
}
}

View file

@ -0,0 +1,226 @@
import { ElementType } from '@baserow/modules/builder/elementTypes'
import { TestApp } from '@baserow/test/helpers/testApp'
describe('elementTypes tests', () => {
const testApp = new TestApp()
const contextBlankParam = { page: { parameters: { id: '' } } }
describe('elementType getDisplayName permutation tests', () => {
test('ElementType returns the name by default', () => {
const elementType = new ElementType()
expect(elementType.getDisplayName({}, {})).toBe(null)
})
test('ColumnElementType returns the name by default', () => {
const elementType = testApp.getRegistry().get('element', 'column')
expect(elementType.getDisplayName({}, {})).toBe('elementType.column')
})
test('InputTextElementType label and default_value variations', () => {
const elementType = testApp.getRegistry().get('element', 'input_text')
expect(elementType.getDisplayName({ label: "'First name'" }, {})).toBe(
'First name'
)
expect(
elementType.getDisplayName(
{ default_value: "'Enter a first name'" },
{}
)
).toBe('Enter a first name')
expect(
elementType.getDisplayName(
{ placeholder: "'Choose a first name...'" },
{}
)
).toBe('Choose a first name...')
// If a formula resolves to a blank string, fallback to the name.
expect(
elementType.getDisplayName(
{ label: "get('page_parameter.id')" },
contextBlankParam
)
).toBe(elementType.name)
expect(elementType.getDisplayName({}, {})).toBe(elementType.name)
})
test('DropdownElementType label, default_value & placeholder variations', () => {
const elementType = testApp.getRegistry().get('element', 'dropdown')
expect(elementType.getDisplayName({ label: "'Animals'" }, {})).toBe(
'Animals'
)
expect(elementType.getDisplayName({ default_value: "'Horse'" }, {})).toBe(
'Horse'
)
expect(
elementType.getDisplayName({ default_value: "'Choose an animal'" }, {})
).toBe('Choose an animal')
// If a formula resolves to a blank string, fallback to the name.
expect(
elementType.getDisplayName(
{ label: "get('page_parameter.id')" },
contextBlankParam
)
).toBe(elementType.name)
expect(elementType.getDisplayName({}, {})).toBe(elementType.name)
})
test('CheckboxElementType with and without a label to use', () => {
const elementType = testApp.getRegistry().get('element', 'checkbox')
expect(elementType.getDisplayName({ label: "'Active'" }, {})).toBe(
'Active'
)
// If a formula resolves to a blank string, fallback to the name.
expect(
elementType.getDisplayName(
{ label: "get('page_parameter.id')" },
contextBlankParam
)
).toBe(elementType.name)
expect(elementType.getDisplayName({}, {})).toBe(elementType.name)
})
test('HeadingElementType with and without a value to use', () => {
const elementType = testApp.getRegistry().get('element', 'heading')
expect(elementType.getDisplayName({ value: "'A heading'" }, {})).toBe(
'A heading'
)
// If a formula resolves to a blank string, fallback to the name.
expect(
elementType.getDisplayName(
{ value: "get('page_parameter.id')" },
contextBlankParam
)
).toBe(elementType.name)
expect(elementType.getDisplayName({}, {})).toBe(elementType.name)
})
test('TextElementType with and without a value to use', () => {
const elementType = testApp.getRegistry().get('element', 'text')
expect(elementType.getDisplayName({ value: "'Some text'" }, {})).toBe(
'Some text'
)
// If a formula resolves to a blank string, fallback to the name.
expect(
elementType.getDisplayName(
{ value: "get('page_parameter.id')" },
contextBlankParam
)
).toBe(elementType.name)
expect(elementType.getDisplayName({}, {})).toBe(elementType.name)
})
test('LinkElementType page and custom URL variations', () => {
const elementType = testApp.getRegistry().get('element', 'link')
const applicationContext = {
builder: {
pages: [{ id: 1, name: 'Contact Us' }],
},
}
expect(
elementType.getDisplayName(
{
navigate_to_page_id: 1,
navigation_type: 'page',
},
applicationContext
)
).toBe('elementType.link -> Contact Us')
// If we were not able to find the page, we fall back to trying for a value.
expect(
elementType.getDisplayName(
{
value: "'Click me'",
navigate_to_page_id: 2,
navigation_type: 'page',
},
applicationContext
)
).toBe('Click me')
// If we were not able to find the page, and there's no value, we fall back to the name.
expect(
elementType.getDisplayName(
{
navigate_to_page_id: 2,
navigation_type: 'page',
},
applicationContext
)
).toBe(elementType.name)
expect(
elementType.getDisplayName(
{
navigation_type: 'custom',
navigate_to_url: "'https://baserow.io'",
value: "'Link name'",
},
applicationContext
)
).toBe('Link name -> https://baserow.io')
})
test('ImageElementType with and without alt text to use', () => {
const elementType = testApp.getRegistry().get('element', 'image')
expect(
elementType.getDisplayName({ alt_text: "'Baserow logo'" }, {})
).toBe('Baserow logo')
// If a formula resolves to a blank string, fallback to the name.
expect(
elementType.getDisplayName(
{ alt_text: "get('page_parameter.id')" },
contextBlankParam
)
).toBe(elementType.name)
expect(elementType.getDisplayName({}, {})).toBe(elementType.name)
})
test('ButtonElementType with and without value to use', () => {
const elementType = testApp.getRegistry().get('element', 'button')
expect(elementType.getDisplayName({ value: "'Click me'" }, {})).toBe(
'Click me'
)
// If a formula resolves to a blank string, fallback to the name.
expect(
elementType.getDisplayName(
{ value: "get('page_parameter.id')" },
contextBlankParam
)
).toBe(elementType.name)
expect(elementType.getDisplayName({}, {})).toBe(elementType.name)
})
test('TableElementType with and without data_source_id to use', () => {
const elementType = testApp.getRegistry().get('element', 'table')
const page = {
id: 1,
name: 'Contact Us',
dataSources: [
{ id: 1, type: 'local_baserow_list_rows', name: 'Customers' },
],
}
const applicationContext = {
page,
builder: { pages: [page] },
}
expect(
elementType.getDisplayName({ data_source_id: 1 }, applicationContext)
).toBe('Customers elementtype.table')
// In the event we don't find the data source.
expect(
elementType.getDisplayName({ data_source_id: 2 }, applicationContext)
).toBe(elementType.name)
expect(elementType.getDisplayName({}, applicationContext)).toBe(
elementType.name
)
})
test('FormContainerElementType returns the name by default', () => {
const elementType = testApp.getRegistry().get('element', 'form_container')
expect(elementType.getDisplayName({}, {})).toBe(elementType.name)
})
test('IFrameElementType with and without a url to use', () => {
const elementType = testApp.getRegistry().get('element', 'iframe')
expect(
elementType.getDisplayName(
{ url: "'https://www.youtube.com/watch?v=dQw4w9WgXcQ'" },
{}
)
).toBe('https://www.youtube.com/watch?v=dQw4w9WgXcQ')
expect(elementType.getDisplayName({}, {})).toBe(elementType.name)
})
})
})