Skip to content

Commit

Permalink
feat: Add inputs search to editComponent (#209)
Browse files Browse the repository at this point in the history
* feat: Add inputs search to editComponent

* chore: proptypes
  • Loading branch information
rboixaderg authored Jan 17, 2024
1 parent 77bf12c commit 930e183
Show file tree
Hide file tree
Showing 16 changed files with 737 additions and 59 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
0.25.0
------
- feat: Add inputs search to editComponent

0.24.1
------
- fix: Render vocabulary field
Expand Down
46 changes: 46 additions & 0 deletions e2e/cypress/integration/gmi-type-content.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,52 @@ LOGIN_TYPES.forEach((loginType) => {
`[data-test='${TABS_PANEL_SELECTOS.prefixTabs}-properties']`
).click()

// Modify search item
cy.get(
`[data-test='${EDITABLE_FORM_SELECTORS.prefixEditableField}-brother_gmi']`
).click()
cy.get(`[data-test='wrapperSearchInputTest']`).click()
cy.findByText('Test GMI item 9').click()
cy.findByText('Save').click()
cy.get(NOTIFICATION_SELECTOR).should(
'contain',
`Field brother_gmi, updated!`
)
cy.findByText('Test GMI item 9').click()
cy.get(
`[data-test='${EDITABLE_FORM_SELECTORS.prefixEditableField}-brother_gmi']`
).click()
cy.get(`[data-test='wrapperSearchInputTest']`).click()
cy.findByText('Test GMI item 6').click()
cy.findByText('Save').click()
cy.get(NOTIFICATION_SELECTOR).should(
'contain',
`Field brother_gmi, updated!`
)

// Modify search item list
cy.get(
`[data-test='${EDITABLE_FORM_SELECTORS.prefixEditableField}-gmi_ids']`
).click()
cy.get(`[data-test='wrapperSearchInputTest']`).click()
cy.findByText('Test GMI item 9').click()
cy.findByText('Test GMI item 7').click()
cy.get(`[data-test='wrapperSearchInputTest']`).click()
cy.findByText('Save').click()
cy.get(NOTIFICATION_SELECTOR).should('contain', `Field gmi_ids, updated!`)
cy.findByText('Test GMI item 9')
cy.findByText('Test GMI item 7')
cy.get(
`[data-test='${EDITABLE_FORM_SELECTORS.prefixEditableField}-gmi_ids']`
).click()
cy.findAllByText('Test GMI item 9').within(() => {
cy.get('button').click()
})
cy.findByText('Save').click()
cy.get(NOTIFICATION_SELECTOR).should('contain', `Field gmi_ids, updated!`)
cy.findByText('Test GMI item 7')
cy.findByText('Test GMI item 9').should('not.exist')

// Upload file
cy.get(
`[data-test='${EDITABLE_FORM_SELECTORS.prefixEditableField}-file']`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,22 @@ class IGMI(interfaces.IFolder):
),
missing_value=[]
)

gmi_ids = schema.List(
title="GMI list",
value_type=schema.TextLine(),
default=[],
null=True,
blank=True,
widget="search_list",
labelProperty="title",
typeNameQuery="GMI",
)

brother_gmi = schema.Text(
title="Brother GMI",
widget="search",
typeNameQuery="GMI",
labelProperty="title",
required=False
)
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "0.24.1",
"version": "0.25.0",
"repository": {
"type": "git",
"url": "[email protected]:guillotinaweb/guillotina_react.git"
Expand Down
12 changes: 10 additions & 2 deletions src/guillo-gmi/components/behaviors/iattachment.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@ import React from 'react'
import { useTraversal } from '../../contexts'
import { EditableField } from '../fields/editableField'
import { Table } from '../ui'
import { useIntl } from 'react-intl'
import { genericMessages } from '../../locales/generic_messages'

export function IAttachment({ properties, values }) {
const intl = useIntl()
const Ctx = useTraversal()
const modifyContent = Ctx.hasPerm('guillotina.ModifyContent')

return (
<Table
headers={['Field', 'Value']}
headers={[
intl.formatMessage(genericMessages.property),
intl.formatMessage(genericMessages.value),
]}
className="is-striped is-fullwidth is-size-7"
>
{Object.keys(properties).map((key) => (
<tr key={'attachment_' + key}>
<td key={1}>{key}</td>
<td style={{ width: '150px' }} key={1}>
{key}
</td>
<td key={2}>
<EditableField
field={key}
Expand Down
12 changes: 10 additions & 2 deletions src/guillo-gmi/components/behaviors/idublincore.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React from 'react'
import { useTraversal } from '../../contexts'
import { EditableField } from '../fields/editableField'
import { Table } from '../ui'
import { useIntl } from 'react-intl'
import { genericMessages } from '../../locales/generic_messages'

const editableFields = [
'title',
Expand All @@ -11,17 +13,23 @@ const editableFields = [
]

export function IDublinCore({ properties, values }) {
const intl = useIntl()
const Ctx = useTraversal()
const modifyContent = Ctx.hasPerm('guillotina.ModifyContent')

return (
<Table
headers={['Field', 'Value']}
headers={[
intl.formatMessage(genericMessages.property),
intl.formatMessage(genericMessages.value),
]}
className="is-striped is-fullwidth is-size-7"
>
{Object.keys(properties).map((key) => (
<tr key={'dublin_' + key}>
<td key={1}>{key}</td>
<td style={{ width: '150px' }} key={1}>
{key}
</td>
<td key={2}>
<EditableField
field={key}
Expand Down
9 changes: 7 additions & 2 deletions src/guillo-gmi/components/behaviors/iimageattachment.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ export function IImageAttachment({ properties, values }) {

return (
<Table
headers={['Field', 'Value']}
headers={[
intl.formatMessage(genericMessages.property),
intl.formatMessage(genericMessages.value),
]}
className="is-striped is-fullwidth is-size-7"
>
{showConfirmToDelete && (
Expand All @@ -97,7 +100,9 @@ export function IImageAttachment({ properties, values }) {
)}
{values['image'] && (
<tr>
<td key={1}>{intl.formatMessage(genericMessages.image)}</td>
<td key={1} style={{ width: '150px' }}>
{intl.formatMessage(genericMessages.image)}
</td>
<td key={2}>
<div className="is-flex is-align-items-center">
<EditableField
Expand Down
9 changes: 7 additions & 2 deletions src/guillo-gmi/components/behaviors/imultiattachment.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ export function IMultiAttachment({ properties, values }) {

return (
<Table
headers={['Field', 'Value']}
headers={[
intl.formatMessage(genericMessages.property),
intl.formatMessage(genericMessages.value),
]}
className="is-striped is-fullwidth is-size-7"
>
{fileKeyToDelete && (
Expand All @@ -84,7 +87,9 @@ export function IMultiAttachment({ properties, values }) {

{Object.keys(values['files']).map((key) => (
<tr key={'multiattachment_' + key}>
<td key={1}>{key}</td>
<td key={1} style={{ width: '150px' }}>
{key}
</td>
<td key={2}>
<div className="is-flex is-align-items-center">
<EditableField
Expand Down
9 changes: 7 additions & 2 deletions src/guillo-gmi/components/behaviors/imultiimageattachment.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,10 @@ export function IMultiImageAttachment({ properties, values }) {

return (
<Table
headers={['Field', 'Value']}
headers={[
intl.formatMessage(genericMessages.property),
intl.formatMessage(genericMessages.value),
]}
className="is-striped is-fullwidth is-size-7"
>
{fileKeyToDelete && (
Expand All @@ -110,7 +113,9 @@ export function IMultiImageAttachment({ properties, values }) {

{Object.keys(values['images']).map((key) => (
<tr key={`multiimageattachment_${key}`}>
<td key={1}>{key}</td>
<td key={1} style={{ width: '150px' }}>
{key}
</td>
<td key={2}>
<div className="is-flex is-align-items-center">
<EditableField
Expand Down
55 changes: 54 additions & 1 deletion src/guillo-gmi/components/fields/editComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,63 @@ import { Input } from '../input/input'
import { InputList } from '../input/input_list'
import { get } from '../../lib/utils'
import { SelectVocabulary } from '../input/select_vocabulary'
import { SearchInputList } from '../input/search_input_list'
import { SearchInput } from '../input/search_input'
import { useTraversal } from '../../contexts'

export const EditComponent = React.forwardRef(
({ schema, val, setValue, dataTest, className, ...rest }, ref) => {
if (schema?.widget === 'textarea' || schema?.widget === 'richtext') {
const traversal = useTraversal()

if (schema?.widget === 'search_list') {
return (
<React.Fragment>
{rest.placeholder && (
<label className="label">{rest.placeholder}</label>
)}
<SearchInputList
value={val || []}
traversal={traversal}
className={className}
onChange={(ev) => setValue(ev)}
queryCondition={
schema?.queryCondition ? schema.queryCondition : 'title__in'
}
dataTest={dataTest}
path={schema.queryPath}
labelProperty={
schema?.labelProperty ? schema.labelProperty : 'title'
}
typeNameQuery={schema?.typeNameQuery ? schema.typeNameQuery : null}
{...rest}
/>
</React.Fragment>
)
} else if (schema?.widget === 'search') {
return (
<React.Fragment>
{rest.placeholder && (
<label className="label">{rest.placeholder}</label>
)}
<SearchInput
value={val}
traversal={traversal}
className={className}
onChange={(ev) => setValue(ev)}
queryCondition={
schema?.queryCondition ? schema.queryCondition : 'title__in'
}
dataTest={dataTest}
path={schema.queryPath}
labelProperty={
schema?.labelProperty ? schema.labelProperty : 'title'
}
typeNameQuery={schema?.typeNameQuery ? schema.typeNameQuery : null}
{...rest}
/>
</React.Fragment>
)
} else if (schema?.widget === 'textarea' || schema?.widget === 'richtext') {
return (
<Textarea
value={val || ''}
Expand Down
83 changes: 81 additions & 2 deletions src/guillo-gmi/components/fields/renderField.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import React from 'react'
import React, { useEffect, useState } from 'react'
import { DownloadField } from './downloadField'
import { useIntl } from 'react-intl'
import { useVocabulary } from '../../hooks/useVocabulary'
import { get } from '../../lib/utils'
import { buildQs } from '../../lib/search'
import { useTraversal } from '../../contexts'
import { useConfig } from '../../hooks/useConfig'

const plain = ['string', 'number', 'boolean']

Expand Down Expand Up @@ -49,6 +52,76 @@ const getDefaultValueEditableField = (intl) => {
})
}

export const SearchRenderField = ({ schema, value, modifyContent }) => {
const [valuesLabels, setValuesLabels] = useState([])
const [isLoadingData, setIsLoadingData] = useState(false)
const traversal = useTraversal()
const { SearchEngine } = useConfig()

useEffect(() => {
const fetchData = async (valuesToSearch) => {
setIsLoadingData(true)
let searchTermQs = []

const searchTermParsed = ['__or', `id=${valuesToSearch.join('%26id=')}`]
const { get: getSearch } = traversal.registry
const fnName = getSearch('searchEngineQueryParamsFunction', SearchEngine)
const qsParsed = traversal.client[fnName]({
path: traversal.path,
start: 0,
pageSize: 100,
withDepth: false,
})

if (searchTermParsed.length > 0 || qsParsed.length > 0) {
searchTermQs = buildQs([searchTermParsed, ...qsParsed])
}
const data = await traversal.client.search(
traversal.client.getContainerFromPath(traversal.path),
searchTermQs,
false,
false,
0,
100
)

const newValuesLabel = data.items.map((item) => {
return get(item, schema?.labelProperty ?? 'title', item.id)
})
setValuesLabels(newValuesLabel)
setIsLoadingData(false)
}

let valuesToSearch = value
if (typeof valuesToSearch === 'string') {
valuesToSearch = [valuesToSearch]
}

if (valuesToSearch !== undefined && valuesToSearch.length > 0) {
fetchData(valuesToSearch)
} else {
setValuesLabels([])
}
}, [value])

const getRenderValue = () => {
console.log('get render values', value, valuesLabels)
if (value === undefined) {
if (modifyContent) {
return DEFAULT_VALUE_EDITABLE_FIELD
}
return DEFAULT_VALUE_NO_EDITABLE_FIELD
}
if (isLoadingData) {
return 'Loading...'
}

return valuesLabels
}

return <RenderField value={getRenderValue()} />
}

export const VocabularyRenderField = ({ schema, value, modifyContent }) => {
const intl = useIntl()
const DEFAULT_VALUE_EDITABLE_FIELD = getDefaultValueEditableField(intl)
Expand Down Expand Up @@ -109,8 +182,14 @@ export function RenderFieldComponent({ schema, field, val, modifyContent }) {
} else if (schema?.items?.vocabularyName || schema?.vocabularyName) {
renderProps['Widget'] = VocabularyRenderField
renderProps['schema'] = schema
} else if (
schema?.widget === 'search' ||
schema?.widget === 'search_list'
) {
renderProps['Widget'] = SearchRenderField
renderProps['value'] = val
renderProps['schema'] = schema
}

return renderProps
}

Expand Down
Loading

0 comments on commit 930e183

Please sign in to comment.