Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
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 @@ -233,11 +233,14 @@ import { VariantTabManager } from '@Pimcore/modules/data-object/editor/types/var
import { DynamicTypeIconSetPimcoreDefault } from '@Pimcore/components/icon-selector/dynamic-types/definitions/pimcore-default-icons/dynamic-type-icon-set-pimcore-default'
import { DynamicTypeIconSetTwemoji } from '@Pimcore/components/icon-selector/dynamic-types/definitions/pimcore-twemoji-icons/dynamic-type-icon-set-twemoji'
import { DynamicTypeIconSetRegistry } from '@Pimcore/components/icon-selector/dynamic-types/registry/dynamic-type-icon-set-registry'
import { DynamicTypeGridCellClassificationStore } from '@Pimcore/modules/element/dynamic-types/definitions/grid-cell/types/classificationstore/dynamic-type-grid-cell-classificationstore'
import { TypeRegistry } from '@Pimcore/modules/element/editor/services/type-registry'
import { IconLibrary } from '@Pimcore/modules/icon-library/services/icon-library'
import { DynamicTypeWidgetTypeElementTree } from '@Pimcore/modules/widget-editor/dynmic-types/definitions/dynamic-type-widget-type-element-tree'
import { DynamicTypeWidgetTypeRegistry } from '@Pimcore/modules/widget-editor/dynmic-types/registry/dynamic-type-widget-type-registry'
import { WidgetRegistry } from '@Pimcore/modules/widget-manager/services/widget-registry'
import { DynamicTypeFieldFilterClassificationStore } from '@Pimcore/modules/element/dynamic-types/definitions/field-filters/types/classification-store/dynamic-type-field-filter-classification-store'
import { DynamicTypeBatchEditClassificationStore } from '@Pimcore/modules/element/dynamic-types/definitions/batch-edits/types/classification-store/dynamic-type-batch-edit-classification-store'

// Component registry
container.bind(serviceIds['App/ComponentRegistry/ComponentRegistry']).to(ComponentRegistry).inSingletonScope()
Expand Down Expand Up @@ -306,6 +309,7 @@ container.bind(serviceIds['DynamicTypes/FieldFilter/Date']).to(DynamicTypeFieldF
container.bind(serviceIds['DynamicTypes/FieldFilter/Boolean']).to(DynamicTypeFieldFilterBoolean).inSingletonScope()
container.bind(serviceIds['DynamicTypes/FieldFilter/BooleanSelect']).to(DynamicTypeFieldFilterBooleanSelect).inSingletonScope()
container.bind(serviceIds['DynamicTypes/FieldFilter/Consent']).to(DynamicTypeFieldFilterConsent).inSingletonScope()
container.bind(serviceIds['DynamicTypes/FieldFilter/ClassificationStore']).to(DynamicTypeFieldFilterClassificationStore).inSingletonScope()
// dynamic types batch edit
container.bind(serviceIds['DynamicTypes/BatchEditRegistry']).to(DynamicTypeBatchEditRegistry).inSingletonScope()
container.bind(serviceIds['DynamicTypes/BatchEdit/Text']).to(DynamicTypeBatchEditText).inSingletonScope()
Expand All @@ -314,6 +318,7 @@ container.bind(serviceIds['DynamicTypes/BatchEdit/Datetime']).to(DynamicTypeBatc
container.bind(serviceIds['DynamicTypes/BatchEdit/Select']).to(DynamicTypeBatchEditSelect).inSingletonScope()
container.bind(serviceIds['DynamicTypes/BatchEdit/Checkbox']).to(DynamicTypeBatchEditCheckbox).inSingletonScope()
container.bind(serviceIds['DynamicTypes/BatchEdit/ElementDropzone']).to(DynamicTypeBatchEditElementDropzone).inSingletonScope()
container.bind(serviceIds['DynamicTypes/BatchEdit/ClassificationStore']).to(DynamicTypeBatchEditClassificationStore).inSingletonScope()
container.bind(serviceIds['DynamicTypes/BatchEdit/DataObjectAdapter']).to(DynamicTypeBatchEditDataObjectAdapter).inSingletonScope()
container.bind(serviceIds['DynamicTypes/BatchEdit/DataObjectObjectBrick']).to(DynamicTypeBatchEditDataObjectObjectBrick).inSingletonScope()

Expand Down Expand Up @@ -352,6 +357,7 @@ container.bind(serviceIds['DynamicTypes/GridCell/Element']).to(DynamicTypeGridCe
container.bind(serviceIds['DynamicTypes/GridCell/LanguageSelect']).to(DynamicTypeGridCellLanguageSelect).inSingletonScope()
container.bind(serviceIds['DynamicTypes/GridCell/Translate']).to(DynamicTypeGridCellTranslate).inSingletonScope()
container.bind(serviceIds['DynamicTypes/GridCell/DataObjectAdapter']).to(DynamicTypeGridCellDataObjectAdapter).inSingletonScope()
container.bind(serviceIds['DynamicTypes/GridCell/ClassificationStore']).to(DynamicTypeGridCellClassificationStore).inSingletonScope()
container.bind(serviceIds['DynamicTypes/GridCell/DataObjectObjectBrick']).to(DynamicTypeGridCellDataObjectObjectBrick).inSingletonScope()
container.bind(serviceIds['DynamicTypes/GridCell/DataObjectAdvanced']).to(DynamicTypeGridCellDataObjectAdvanced).inSingletonScope()
container.bind(serviceIds['DynamicTypes/GridCell/String']).to(DynamicTypeGridCellString).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 @@ -109,13 +109,15 @@ export const serviceIds = {
'DynamicTypes/FieldFilter/Boolean': 'DynamicTypes/FieldFilter/Boolean',
'DynamicTypes/FieldFilter/BooleanSelect': 'DynamicTypes/FieldFilter/BooleanSelect',
'DynamicTypes/FieldFilter/Consent': 'DynamicTypes/FieldFilter/Consent',
'DynamicTypes/FieldFilter/ClassificationStore': 'DynamicTypes/FieldFilter/ClassificationStore',

'DynamicTypes/BatchEdit/Text': 'DynamicTypes/BatchEdit/Text',
'DynamicTypes/BatchEdit/TextArea': 'DynamicTypes/BatchEdit/TextArea',
'DynamicTypes/BatchEdit/Datetime': 'DynamicTypes/BatchEdit/Datetime',
'DynamicTypes/BatchEdit/Select': 'DynamicTypes/BatchEdit/Select',
'DynamicTypes/BatchEdit/Checkbox': 'DynamicTypes/BatchEdit/Checkbox',
'DynamicTypes/BatchEdit/ElementDropzone': 'DynamicTypes/BatchEdit/ElementDropzone',
'DynamicTypes/BatchEdit/ClassificationStore': 'DynamicTypes/BatchEdit/ClassificationStore',
'DynamicTypes/BatchEdit/DataObjectAdapter': 'DynamicTypes/BatchEdit/DataObjectAdapter',
'DynamicTypes/BatchEdit/DataObjectObjectBrick': 'DynamicTypes/BatchEdit/DataObjectObjectBrick',

Expand Down Expand Up @@ -153,6 +155,7 @@ export const serviceIds = {
'DynamicTypes/GridCell/LanguageSelect': 'DynamicTypes/GridCell/LanguageSelect',
'DynamicTypes/GridCell/Translate': 'DynamicTypes/GridCell/Translate',
'DynamicTypes/GridCell/DataObjectAdapter': 'DynamicTypes/GridCell/DataObjectAdapter',
'DynamicTypes/GridCell/ClassificationStore': 'DynamicTypes/GridCell/ClassificationStore',
'DynamicTypes/GridCell/DataObjectAdvanced': 'DynamicTypes/GridCell/DataObjectAdvanced',
'DynamicTypes/GridCell/DataObjectObjectBrick': 'DynamicTypes/GridCell/DataObjectObjectBrick',

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import React, { createContext, useEffect, useMemo, useState } from 'react'

export interface IDynamicFilter {
id: string
translationKey: string
type: string
data: any
frontendType?: string
Expand All @@ -36,7 +37,7 @@ export interface DynamicFilterProviderProps extends Omit<DynamicFilterData, 'set
children: React.ReactNode
}

export const DynamicFilterProvider = ({ children, id, type, data, onChange, frontendType, config }: DynamicFilterProviderProps): React.JSX.Element => {
export const DynamicFilterProvider = ({ children, id, type, translationKey, data, onChange, frontendType, config }: DynamicFilterProviderProps): React.JSX.Element => {
const [_data, _setData] = useState<DynamicFilterData['data']>(data)

useEffect(() => {
Expand All @@ -51,7 +52,7 @@ export const DynamicFilterProvider = ({ children, id, type, data, onChange, fron
}

return useMemo(() => (
<DynamicFilterContext.Provider value={ { id, type, data: _data, setData, frontendType, config } }>
<DynamicFilterContext.Provider value={ { id, translationKey, type, data: _data, setData, frontendType, config } }>
{children}
</DynamicFilterContext.Provider>
), [id, type, _data, frontendType, config, children])
Expand Down
15 changes: 13 additions & 2 deletions assets/js/src/core/components/field-filters/field-filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,27 @@ export const FieldFilters = ({ data, onChange }: FieldFiltersProps): React.JSX.E
}

const onRemoveClick = (filter: IDynamicFilter): void => {
if (filter.type === 'dataobject.classificationstore') {
setData(_data.filter((f) => !(f.id === filter.id && f.config?.keyId === filter.config?.keyId && f.config?.groupId === filter.config?.groupId)))
return
}

setData(_data.filter((f) => f.id !== filter.id))
}

const items: StackListProps['items'] = _data.map((filter) => {
let key = filter.id

if (filter.type === 'dataobject.classificationstore') {
key = `${filter.id}-${JSON.stringify({ keyId: filter.config.keyId, groupId: filter.config?.groupId })}`
}

return {
id: filter.id,
key: filter.id,
key,
title: filter.id,
children: <Tooltip title={ filter.nameTooltip }>
<Tag>{filter.id}</Tag>
<Tag>{filter.translationKey}</Tag>
</Tooltip>,
body: (
<DynamicFilter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export type StackListItemType = (typeof StackListItemTypes)[keyof typeof StackLi

export interface StackListItemProps {
id: UniqueIdentifier
key?: string
type?: StackListItemType
sortable?: boolean
renderLeftToolbar?: React.ReactNode
Expand Down
10 changes: 5 additions & 5 deletions assets/js/src/core/components/stack-list/stack-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ export const StackList = ({ items, onItemsChange, sortable }: StackListProps): R
<div className={ cn('stack-list', styles.stackList) }>
{sortable === true && (
<DndContext onDragEnd={ onDragEnd }>
<SortableContext items={ itemsState.map((item) => item.id) }>
<SortableContext items={ itemsState.map((item) => item.key ?? item.id) }>
{itemsState.map((item) => (
<div
className="stack-list__item"
key={ item.id }
key={ item.key ?? item.id }
>
<StackListItem { ...item } />
</div>
Expand All @@ -51,7 +51,7 @@ export const StackList = ({ items, onItemsChange, sortable }: StackListProps): R
{itemsState.map((item) => (
<div
className="stack-list__item"
key={ item.id }
key={ item.key ?? item.id }
>
<StackListItem { ...item } />
</div>
Expand All @@ -66,8 +66,8 @@ export const StackList = ({ items, onItemsChange, sortable }: StackListProps): R

if (over !== null && active.id !== over.id) {
setItems((items) => {
const oldIndex = items.findIndex((item) => item.id === active.id)
const newIndex = items.findIndex((item) => item.id === over.id)
const oldIndex = items.findIndex((item) => item.key ?? item.id === active.id)
const newIndex = items.findIndex((item) => item.key ?? item.id === over.id)

const newItems = arrayMove(items, oldIndex, newIndex)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,7 @@ export const {
useClassificationStoreGetLayoutByCollectionQuery,
useLazyClassificationStoreGetLayoutByCollectionQuery,
useClassificationStoreGetLayoutByGroupQuery,
useLazyClassificationStoreGetLayoutByGroupQuery
useLazyClassificationStoreGetLayoutByGroupQuery,
useClassificationStoreGetLayoutByKeyQuery,
useLazyClassificationStoreGetLayoutByKeyQuery
} = api
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,19 @@ const injectedRtkApi = api
}),
providesTags: ["Classification Store"],
}),
classificationStoreGetLayoutByKey: build.query<
ClassificationStoreGetLayoutByKeyApiResponse,
ClassificationStoreGetLayoutByKeyApiArg
>({
query: (queryArg) => ({
url: `/pimcore-studio/api/classification-store/layout-by-key/${queryArg.keyId}`,
params: {
objectId: queryArg.objectId,
fieldName: queryArg.fieldName,
},
}),
providesTags: ["Classification Store"],
}),
}),
overrideExisting: false,
});
Expand Down Expand Up @@ -162,6 +175,16 @@ export type ClassificationStoreGetLayoutByGroupApiArg = {
/** Field Name */
fieldName: string;
};
export type ClassificationStoreGetLayoutByKeyApiResponse =
/** status 200 Layout definition */ ClassificationStoreCollection2;
export type ClassificationStoreGetLayoutByKeyApiArg = {
/** object ID */
objectId?: number;
/** KeyId of the Key ID */
keyId: number;
/** Field Name */
fieldName: string;
};
export type ClassificationStoreCollection = {
/** AdditionalAttributes */
additionalAttributes?: {
Expand Down Expand Up @@ -250,4 +273,5 @@ export const {
useClassificationStoreGetKeyGroupRelationsQuery,
useClassificationStoreGetLayoutByCollectionQuery,
useClassificationStoreGetLayoutByGroupQuery,
useClassificationStoreGetLayoutByKeyQuery,
} = injectedRtkApi;
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { useJobs } from '@Pimcore/modules/execution-engine/hooks/useJobs'
import { useDataObjectBatchDeleteMutation } from '@Pimcore/modules/data-object/data-object-api-slice.gen'
import { useElementContext } from '@Pimcore/modules/element/hooks/use-element-context'
import { useRefreshGrid } from '@Pimcore/modules/element/actions/refresh-grid/use-refresh-grid'
import { ClassificationStoreModalProvider } from '@Pimcore/modules/element/dynamic-types/definitions/objects/data-related/components/classification-store/provider/classifcation-store-modal-provider'

export const BatchActions = (): React.JSX.Element => {
const rowSelection = useRowSelectionOptional()
Expand Down Expand Up @@ -133,12 +134,14 @@ export const BatchActions = (): React.JSX.Element => {
setOpen={ setXlsxModalOpen }
/>

<BatchEditProvider>
<BatchEditModal
batchEditModalOpen={ batchEditModalOpen }
setBatchEditModalOpen={ setBatchEditModalOpen }
/>
</BatchEditProvider>
<ClassificationStoreModalProvider>
<BatchEditProvider>
<BatchEditModal
batchEditModalOpen={ batchEditModalOpen }
setBatchEditModalOpen={ setBatchEditModalOpen }
/>
</BatchEditProvider>
</ClassificationStoreModalProvider>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,21 @@ export const BatchEditListContainer = (): React.JSX.Element => {
// @todo infer selected language from grid config when available
const selectedLanguage = batchEdit.locale ?? settings.requiredLanguages[0]

const batchEditTitle = 'fieldDefinition' in batchEdit.config ? (batchEdit.config.fieldDefinition as { title: string }).title : batchEdit.key
const key = batchEdit.type === 'dataobject.classificationstore' ? `${batchEdit.key}-${(batchEdit.config as { keyId: number }).keyId}-${(batchEdit.config as { groupId: number }).groupId}` : batchEdit.key

return ({
id: batchEdit.key,
children: <Tag>{t(`${batchEdit.key}`)}</Tag>,
id: `${batchEdit.key}`,
key,
children: <Tag>{t(`${batchEditTitle}`)}</Tag>,
renderRightToolbar: <ButtonGroup items={
[...(batchEdit.localizable
? [
<LanguageSelection
key="language-selection"
languages={ languages }
onSelectLanguage={ (language) => {
updateLocale(batchEdit.key, transformLanguage(language))
updateLocale(batchEdit, transformLanguage(language))
} }
selectedLanguage={ selectedLanguage }
/>
Expand All @@ -51,7 +55,7 @@ export const BatchEditListContainer = (): React.JSX.Element => {
icon={ { value: 'close' } }
key={ 'remove' }
onClick={ () => {
removeBatchEdit(batchEdit.key)
removeBatchEdit(batchEdit)
} }
/>
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
* @license Pimcore Open Core License (POCL)
*/

/* eslint-disable max-lines */

import React, { useEffect, useMemo } from 'react'
import { isUndefined } from 'lodash'
import { ModalFooter } from '@Pimcore/components/modal/footer/modal-footer'
Expand Down Expand Up @@ -39,6 +41,9 @@ import { useRefreshGrid } from '@Pimcore/modules/element/actions/refresh-grid/us
import { filterDropdownItems, hasSelectableItems } from './utils/dropdown-filter'
import { FieldCollectionProvider } from '@Pimcore/modules/element/dynamic-types/definitions/objects/data-related/components/field-collection/providers/field-collection-provider'
import { useClassDefinitionSelection } from '../../decorator/class-definition-selection/context-layer/provider/use-class-definition-selection'
import { useClassificationStoreModal } from '@Pimcore/modules/element/dynamic-types/definitions/objects/data-related/components/classification-store/provider/classifcation-store-modal-provider'
import { TabId } from '@Pimcore/modules/element/dynamic-types/definitions/objects/data-related/components/classification-store/types'
import { type ClassificationStoreModalProps } from '@Pimcore/modules/element/dynamic-types/definitions/objects/data-related/components/classification-store/components/classification-store-modal/classification-store-modal'

export interface BatchEditModalProps {
batchEditModalOpen: boolean
Expand All @@ -47,7 +52,7 @@ export interface BatchEditModalProps {

export const BatchEditModal = ({ batchEditModalOpen, setBatchEditModalOpen }: BatchEditModalProps): React.JSX.Element => {
const { getAvailableColumnsDropdown } = useAvailableColumns()
const { batchEdits, addOrUpdateBatchEdit, resetBatchEdits } = useBatchEdit()
const { batchEdits, addOrUpdateBatchEdit, addOrUpdateBatchEdits, resetBatchEdits } = useBatchEdit()
const [form] = Form.useForm()
const { selectedRows } = useRowSelection()
const [patchObjectsInFolder, { error: folderPatchError, isError: isFolderPatchError, isSuccess: isFolderPatchSuccess }] = useDataObjectPatchFolderByIdMutation()
Expand All @@ -63,6 +68,8 @@ export const BatchEditModal = ({ batchEditModalOpen, setBatchEditModalOpen }: Ba
const { refreshGrid } = useRefreshGrid(elementType)
const classDefinitionSelection = useClassDefinitionSelection()
const selectedClassDefinition = classDefinitionSelection.selectedClassDefinition
const { openModal } = useClassificationStoreModal({ onUpdate: onClassificationStoreUpdate })
const { availableColumns } = useAvailableColumns()

const resetModal = (): void => {
resetBatchEdits()
Expand All @@ -89,7 +96,63 @@ export const BatchEditModal = ({ batchEditModalOpen, setBatchEditModalOpen }: Ba
}
}, [isFolderPatchSuccess, isIdPatchSuccess])

function onClassificationStoreUpdate (data): void {
const fieldDefinition = data.modalContext
const baseColumn = availableColumns.find(col => col.key === fieldDefinition.name && col.type === 'dataobject.classificationstore')

if (baseColumn === undefined) {
throw new Error('Could not find base column for classification store field ' + fieldDefinition.name)
}

const columnsToAdd: AvailableColumn[] = []

if (data.type === 'group-by-key') {
data.data.forEach((item) => {
const itemDefinition = item.definition
let alreadyInBatchEdits = false

batchEdits.forEach((batchEdit) => {
if (batchEdit.key === baseColumn.key && (batchEdit.config as { keyId: string, groupId: string })?.keyId === item.id && (batchEdit.config as { keyId: string, groupId: string })?.groupId === item.groupId) {
alreadyInBatchEdits = true
}
})

if (alreadyInBatchEdits) {
return
}

columnsToAdd.push({
...baseColumn,
key: `${baseColumn.key}`,
frontendType: itemDefinition?.fieldtype,
config: {
keyId: item.id,
groupId: item.groupId,
fieldDefinition: itemDefinition
}
})
})

addOrUpdateBatchEdits(columnsToAdd)
}
}

const onColumnClick = (column: AvailableColumn): void => {
if (column.type === 'dataobject.classificationstore') {
if (!('fieldDefinition' in column.config)) {
throw new Error('Field definition is missing in config')
}

const fieldDefinition = column.config?.fieldDefinition as ClassificationStoreModalProps

openModal({
...fieldDefinition,
fieldName: column.key,
allowedTabs: [TabId.GroupByKey]
})
return
}

addOrUpdateBatchEdit(column, undefined)
}

Expand Down
Loading