Skip to content

Commit

Permalink
Add quantity value data object data types (#754)
Browse files Browse the repository at this point in the history
  • Loading branch information
markus-moser authored Nov 29, 2024
1 parent f3a5d75 commit 135e815
Show file tree
Hide file tree
Showing 49 changed files with 2,698 additions and 1,866 deletions.
2 changes: 1 addition & 1 deletion assets/build/api/docs.jsonopenapi.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions assets/js/src/core/app/config/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ import { DynamicTypeObjectLayoutFieldContainer } from '@Pimcore/modules/element/
import { DynamicTypeObjectDataInput } from '@Pimcore/modules/element/dynamic-types/defintinitions/objects/data-related/types/dynamic-type-object-data-input'
import { DynamicTypeObjectDataTextarea } from '@Pimcore/modules/element/dynamic-types/defintinitions/objects/data-related/types/dynamic-type-object-data-textarea'
import { DynamicTypeObjectDataPassword } from '@Pimcore/modules/element/dynamic-types/defintinitions/objects/data-related/types/dynamic-type-object-data-password'
import { DynamicTypeObjectDataInputQuantityValue } from '@Pimcore/modules/element/dynamic-types/defintinitions/objects/data-related/types/dynamic-type-object-data-input-quantity-value'
import { DynamicTypeObjectDataSelect } from '@Pimcore/modules/element/dynamic-types/defintinitions/objects/data-related/types/dynamic-type-object-data-select'
import { DynamicTypeObjectDataMultiSelect } from '@Pimcore/modules/element/dynamic-types/defintinitions/objects/data-related/types/dynamic-type-object-data-multiselect'
import { DynamicTypeObjectDataLanguage } from '@Pimcore/modules/element/dynamic-types/defintinitions/objects/data-related/types/dynamic-type-object-data-language'
Expand All @@ -88,6 +89,8 @@ import { DynamicTypeObjectDataBooleanSelect } from '@Pimcore/modules/element/dyn
import { DynamicTypeObjectDataNumeric } from '@Pimcore/modules/element/dynamic-types/defintinitions/objects/data-related/types/dynamic-type-object-data-numeric'
import { DynamicTypeObjectDataNumericRange } from '@Pimcore/modules/element/dynamic-types/defintinitions/objects/data-related/types/dynamic-type-object-data-numeric-range'
import { DynamicTypeObjectDataSlider } from '@Pimcore/modules/element/dynamic-types/defintinitions/objects/data-related/types/dynamic-type-object-data-slider'
import { DynamicTypeObjectDataQuantityValue } from '@Pimcore/modules/element/dynamic-types/defintinitions/objects/data-related/types/dynamic-type-object-data-quantity-value'
import { DynamicTypeObjectDataQuantityValueRange } from '@Pimcore/modules/element/dynamic-types/defintinitions/objects/data-related/types/dynamic-type-object-data-quantity-value-range'
import { DynamicTypeObjectDataConsent } from '@Pimcore/modules/element/dynamic-types/defintinitions/objects/data-related/types/dynamic-type-object-data-consent'
import { DynamicTypeObjectDataFirstname } from '@Pimcore/modules/element/dynamic-types/defintinitions/objects/data-related/types/dynamic-type-object-data-firstname'
import { DynamicTypeObjectDataLastname } from '@Pimcore/modules/element/dynamic-types/defintinitions/objects/data-related/types/dynamic-type-object-data-lastname'
Expand Down Expand Up @@ -214,6 +217,7 @@ container.bind(serviceIds['DynamicTypes/ObjectLayout/FieldContainer']).to(Dynami
container.bind(serviceIds['DynamicTypes/ObjectDataRegistry']).to(DynamicTypeObjectDataRegistry).inSingletonScope()
container.bind(serviceIds['DynamicTypes/ObjectData/Input']).to(DynamicTypeObjectDataInput).inSingletonScope()
container.bind(serviceIds['DynamicTypes/ObjectData/Textarea']).to(DynamicTypeObjectDataTextarea).inSingletonScope()
container.bind(serviceIds['DynamicTypes/ObjectData/InputQuantityValue']).to(DynamicTypeObjectDataInputQuantityValue).inSingletonScope()
container.bind(serviceIds['DynamicTypes/ObjectData/Password']).to(DynamicTypeObjectDataPassword).inSingletonScope()
container.bind(serviceIds['DynamicTypes/ObjectData/Select']).to(DynamicTypeObjectDataSelect).inSingletonScope()
container.bind(serviceIds['DynamicTypes/ObjectData/MultiSelect']).to(DynamicTypeObjectDataMultiSelect).inSingletonScope()
Expand All @@ -226,6 +230,8 @@ container.bind(serviceIds['DynamicTypes/ObjectData/BooleanSelect']).to(DynamicTy
container.bind(serviceIds['DynamicTypes/ObjectData/Numeric']).to(DynamicTypeObjectDataNumeric).inSingletonScope()
container.bind(serviceIds['DynamicTypes/ObjectData/NumericRange']).to(DynamicTypeObjectDataNumericRange).inSingletonScope()
container.bind(serviceIds['DynamicTypes/ObjectData/Slider']).to(DynamicTypeObjectDataSlider).inSingletonScope()
container.bind(serviceIds['DynamicTypes/ObjectData/QuantityValue']).to(DynamicTypeObjectDataQuantityValue).inSingletonScope()
container.bind(serviceIds['DynamicTypes/ObjectData/QuantityValueRange']).to(DynamicTypeObjectDataQuantityValueRange).inSingletonScope()
container.bind(serviceIds['DynamicTypes/ObjectData/Consent']).to(DynamicTypeObjectDataConsent).inSingletonScope()
container.bind(serviceIds['DynamicTypes/ObjectData/Firstname']).to(DynamicTypeObjectDataFirstname).inSingletonScope()
container.bind(serviceIds['DynamicTypes/ObjectData/Lastname']).to(DynamicTypeObjectDataLastname).inSingletonScope()
Expand Down
3 changes: 3 additions & 0 deletions assets/js/src/core/app/config/services/service-ids.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export const serviceIds = {
'DynamicTypes/ObjectData/Input': 'DynamicTypes/ObjectData/Input',
'DynamicTypes/ObjectData/Textarea': 'DynamicTypes/ObjectData/Textarea',
'DynamicTypes/ObjectData/Password': 'DynamicTypes/ObjectData/Password',
'DynamicTypes/ObjectData/InputQuantityValue': 'DynamicTypes/ObjectData/InputQuantityValue',
'DynamicTypes/ObjectData/Select': 'DynamicTypes/ObjectData/Select',
'DynamicTypes/ObjectData/MultiSelect': 'DynamicTypes/ObjectData/MultiSelect',
'DynamicTypes/ObjectData/Language': 'DynamicTypes/ObjectData/Language',
Expand All @@ -123,6 +124,8 @@ export const serviceIds = {
'DynamicTypes/ObjectData/Numeric': 'DynamicTypes/ObjectData/Numeric',
'DynamicTypes/ObjectData/NumericRange': 'DynamicTypes/ObjectData/NumericRange',
'DynamicTypes/ObjectData/Slider': 'DynamicTypes/ObjectData/Slider',
'DynamicTypes/ObjectData/QuantityValue': 'DynamicTypes/ObjectData/QuantityValue',
'DynamicTypes/ObjectData/QuantityValueRange': 'DynamicTypes/ObjectData/QuantityValueRange',
'DynamicTypes/ObjectData/Consent': 'DynamicTypes/ObjectData/Consent',
'DynamicTypes/ObjectData/Firstname': 'DynamicTypes/ObjectData/Firstname',
'DynamicTypes/ObjectData/Lastname': 'DynamicTypes/ObjectData/Lastname',
Expand Down
3 changes: 3 additions & 0 deletions assets/js/src/core/assets/icons/calculator.inline.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* Pimcore
*
* This source file is available under two different licenses:
* - Pimcore Open Core License (POCL)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license https://github.com/pimcore/studio-ui-bundle/blob/1.x/LICENSE.md POCL and PCL
*/

import {
useClassQuantityValueUnitConvertMutation,
useClassQuantityValueUnitListQuery
} from '@Pimcore/modules/class-definition/class-definition-slice.gen'
import { type DefaultOptionType } from 'rc-select/lib/Select'
import { useTranslation } from 'react-i18next'
import _ from 'lodash'

interface UseQuantityValueUnitsReturn {
getSelectOptions: (validUnits?: string[]) => DefaultOptionType[]
convertValue: (fromUnitId: string, toUnitId: string, value: number) => Promise<number | null>
getAbbreviation: (unitId: string) => string
}

export const useQuantityValueUnits = (): UseQuantityValueUnitsReturn => {
const { data: units } = useClassQuantityValueUnitListQuery()
const [convertQuantityValue] = useClassQuantityValueUnitConvertMutation()
const { t } = useTranslation()

const getSelectOptions = (validUnits?: string[]): DefaultOptionType[] => {
if (units?.items === undefined) {
return []
}

return units
.items
.filter(unit => validUnits === undefined || (unit.id !== null && validUnits.includes(unit.id)))
.map(unit => ({
label: unit.abbreviation === null ? unit.id : t(unit.abbreviation),
value: unit.id
}))
}

const convertValue = async (fromUnitId: string, toUnitId: string, value: number): Promise<number | null> => {
if (units?.items === undefined) {
return null
}
const fromUnit = units.items.find(unit => unit.id === fromUnitId)
const toUnit = units.items.find(unit => unit.id === toUnitId)
if (fromUnit === undefined || toUnit === undefined) {
return null
}
if (fromUnit.baseUnit === null || fromUnit.baseUnit !== toUnit.baseUnit) {
return null
}

const { data } = await convertQuantityValue({
convertParameters: {
fromUnitId,
toUnitId,
value
}
}).catch(() => {
throw new Error('Error converting quantity value.')
})

return data?.data ?? null
}

const getAbbreviation = (unitId: string): string => {
if (units?.items === undefined) {
return ''
}

const unit = units.items.find(unit => unit.id === unitId)
if (typeof unit?.abbreviation === 'string' && !_.isEmpty(unit.abbreviation)) {
return t(unit.abbreviation)
}
return unitId
}

return {
getSelectOptions,
convertValue,
getAbbreviation
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Pimcore
*
* This source file is available under two different licenses:
* - Pimcore Open Core License (POCL)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license https://github.com/pimcore/studio-ui-bundle/blob/1.x/LICENSE.md POCL and PCL
*/

/**
* Pimcore
*
* This source file is available under two different licenses:
* - Pimcore Open Core License (POCL)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license https://github.com/pimcore/studio-ui-bundle/blob/1.x/LICENSE.md POCL and PCL
*/

import { createStyles } from 'antd-style'

export const useStyles = createStyles(({ css, token }) => {
return {
select: css`
min-width: 100px;
`,
input: css`
min-width: 80px;
`
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/**
* Pimcore
*
* This source file is available under two different licenses:
* - Pimcore Open Core License (POCL)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license https://github.com/pimcore/studio-ui-bundle/blob/1.x/LICENSE.md POCL and PCL
*/

import React, { useEffect, useState } from 'react'
import { Flex } from '@Pimcore/components/flex/flex'
import { Input } from 'antd'
import _ from 'lodash'
import { useQuantityValueUnits } from '@Pimcore/modules/data-object/hooks/use-quantity-value-units'
import { Select } from '@Pimcore/components/select/select'
import { useTranslation } from 'react-i18next'
import { toCssDimension } from '@Pimcore/utils/css'
import { useStyles } from './input-quantity-value.styles'

export interface InputQuantityValueProps {
value?: InputQuantityValueValue | null
className?: string
onChange?: (value: InputQuantityValueValue | null) => void
validUnits?: string[] | null
width?: string | null
}

export interface InputQuantityValueValue {
value: string | null
unitId: string | null
}

export const InputQuantityValue = (props: InputQuantityValueProps): React.JSX.Element => {
const [value, setValue] = useState<InputQuantityValueValue>(props.value ?? { value: null, unitId: null })
const { getSelectOptions } = useQuantityValueUnits()
const { t } = useTranslation()
const { styles } = useStyles()

const onChangeInput = (e: React.ChangeEvent<HTMLInputElement>): void => {
const newValue = e.target.value

setValue({
...value,
value: _.isEmpty(newValue) ? null : newValue
})
}

const onChangeSelect = (unitId?: string): void => {
setValue({
...value,
unitId: _.isEmpty(unitId) ? null : (unitId ?? null)
})
}

useEffect(() => {
if (props.onChange !== undefined) {
props.onChange(value.value === null && value.unitId === null ? null : value)
}
}, [value])

return (
<Flex
align="center"
className={ props.className }
gap="small"
>
<Input
className={ styles.input }
onChange={ onChangeInput }
style={ { maxWidth: toCssDimension(props.width, 150) } }
value={ value?.value ?? undefined }
/>
<Select
allowClear
className={ styles.select }
onChange={ onChangeSelect }
optionFilterProp="label"
options={ getSelectOptions(props.validUnits ?? undefined) }
placeholder={ '(' + t('empty') + ')' }
showSearch
value={ value?.unitId ?? undefined }
/>
</Flex>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Pimcore
*
* This source file is available under two different licenses:
* - Pimcore Open Core License (POCL)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license https://github.com/pimcore/studio-ui-bundle/blob/1.x/LICENSE.md POCL and PCL
*/

/**
* Pimcore
*
* This source file is available under two different licenses:
* - Pimcore Open Core License (POCL)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license https://github.com/pimcore/studio-ui-bundle/blob/1.x/LICENSE.md POCL and PCL
*/

import { createStyles } from 'antd-style'

export const useStyles = createStyles(({ css, token }) => {
return {
select: css`
min-width: 100px;
`,
input: css`
min-width: 80px;
`
}
})
Loading

0 comments on commit 135e815

Please sign in to comment.