Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tags loading #792

Merged
merged 35 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
271d792
loadingtree
xIrusux Nov 26, 2024
8cce388
show loading indicator next to tag while loading mutation
xIrusux Nov 27, 2024
6b768fd
adjust checkbox to be unresponsive while loading
xIrusux Nov 27, 2024
d0cbdd1
refactor away from hook
xIrusux Nov 27, 2024
3303f5a
fix promise error
xIrusux Dec 2, 2024
287cacb
propper tag handling for Tags
xIrusux Dec 2, 2024
da2b40a
proper manage possible tags separate from element applied tags
xIrusux Dec 2, 2024
5dc7e59
error snack bar also on unassign
xIrusux Dec 2, 2024
41a056b
undo optimistic loading on fairlure
xIrusux Dec 2, 2024
e63b350
invalidate tags cache when reopening item
xIrusux Dec 3, 2024
eb456c0
Merge branch '1.x' of github.com:pimcore/studio-ui-bundle into tags-l…
xIrusux Dec 3, 2024
de4c99a
Apply latest automatic api client updates
xIrusux Dec 3, 2024
8c21688
Automatic frontend build
xIrusux Dec 3, 2024
0e4ab00
update tags as it seems like we dont need to be caring for tag ids in…
xIrusux Dec 3, 2024
b762e0f
update tags as it seems like we dont need to be caring for tag ids in…
xIrusux Dec 3, 2024
bc296df
getElementDetailTag is not required for invalidating Notes and Events…
xIrusux Dec 4, 2024
5461120
fix invalidation tag notes and events
xIrusux Dec 4, 2024
0b0fabf
tag tags simplified
xIrusux Dec 4, 2024
2c2d77f
Merge branch 'tags-loading' of github.com:pimcore/studio-ui-bundle in…
xIrusux Dec 4, 2024
e85e129
Automatic frontend build
xIrusux Dec 4, 2024
4c82436
improve tag deleting and move away from optimistic loading
xIrusux Dec 5, 2024
ae197c0
no longer send get to update
xIrusux Dec 9, 2024
f3fb96f
refactoring to second hooks complete
xIrusux Dec 9, 2024
94e7cb9
refactoring functions half way
xIrusux Dec 10, 2024
f0c58ec
tags deletion topic functional
xIrusux Dec 10, 2024
5133a8a
clean up ready to merge
xIrusux Dec 10, 2024
c068129
clean up ready to merge
xIrusux Dec 11, 2024
1ac2aac
fix sorting problem
xIrusux Dec 11, 2024
d669068
Merge branch 'tags-loading' of github.com:pimcore/studio-ui-bundle in…
xIrusux Dec 11, 2024
9f15e43
Automatic frontend build
xIrusux Dec 11, 2024
7369991
merge
xIrusux Dec 11, 2024
461d478
fix error after merge
xIrusux Dec 11, 2024
0f63378
if assigning or unassigning is failing re create previous state
xIrusux Dec 11, 2024
9ecafd2
merge
xIrusux Dec 11, 2024
0d31ab8
Automatic frontend build
xIrusux Dec 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions assets/js/src/core/app/api/pimcore/tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ export const tagNames = {
PROPERTIES: 'PROPERTIES',
SCHEDULES: 'SCHEDULES',
DEPENDENCIES: 'DEPENDENCIES',
NOTES_AND_EVENTS: 'NOTES_AND_EVENTS'
NOTES_AND_EVENTS: 'NOTES_AND_EVENTS',
TAGS: 'TAGS',
ELEMENT_TAGS: 'ELEMENT_TAGS'
}

export const providingTags = {
Expand Down Expand Up @@ -69,7 +71,10 @@ export const providingTags = {
ELEMENT_WORKFLOW: (elementType: ElementType, id: number) => [getElementDetailTag(elementType, id), tagNames.WORKFLOW],
VERSIONS_DETAIL: (id: number) => [{ type: tagNames.VERSIONS, id }, tagNames.VERSIONS],
ELEMENT_NOTES_AND_EVENTS: (elementType: ElementType, id: number) => [getElementDetailTag(elementType, id), tagNames.NOTES_AND_EVENTS],
NOTES_AND_EVENTS_ID: (id: number) => [tagNames.NOTES_AND_EVENTS, { type: tagNames.NOTES_AND_EVENTS, id }]
NOTES_AND_EVENTS_ID: (id: number) => [tagNames.NOTES_AND_EVENTS, { type: tagNames.NOTES_AND_EVENTS, id }],
ELEMENT_TAGS: (elementType: ElementType, id: number) => [getElementDetailTag(elementType, id), tagNames.ELEMENT_TAGS],
ELEMENT_TAGS_ID: (id: number) => [tagNames.ELEMENT_TAGS, { type: tagNames.ELEMENT_TAGS, id }],
TAGS_ID: (id: number) => [tagNames.TAGS, { type: tagNames.TAGS, id }]
}

export const invalidatingTags = {
Expand All @@ -94,7 +99,10 @@ export const invalidatingTags = {
ELEMENT_WORKFLOW: (elementType: ElementType, id: number) => [getElementDetailTag(elementType, id)],
NOTES_AND_EVENTS_ID: (id: number) => [{ type: tagNames.NOTES_AND_EVENTS, id }],
VERSIONS_DETAIL: (id: number) => [{ type: tagNames.VERSIONS, id }],
ELEMENT_NOTES_AND_EVENTS: (elementType: ElementType, id: number) => [getElementDetailTag(elementType, id), tagNames.NOTES_AND_EVENTS]
ELEMENT_NOTES_AND_EVENTS: (elementType: ElementType, id: number) => [getElementDetailTag(elementType, id), tagNames.NOTES_AND_EVENTS],
ELEMENT_TAGS: (elementType: ElementType, id: number) => [getElementDetailTag(elementType, id), tagNames.ELEMENT_TAGS],
ELEMENT_TAGS_ID: (id: number) => [tagNames.ELEMENT_TAGS, { type: tagNames.ELEMENT_TAGS, id }],
TAGS_ID: (id: number) => [tagNames.TAGS, { type: tagNames.TAGS, id }]
}

const getElementDetailTag = (elementType: ElementType, id: number): Tag => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@
* @license https://github.com/pimcore/studio-ui-bundle/blob/1.x/LICENSE.md POCL and PCL
*/

import { useTagGetCollectionQuery } from '@Pimcore/modules/element/editor/shared-tab-manager/tabs/tags/tags-api-slice.gen'
import React, { type Key } from 'react'
import { Content } from '@Pimcore/components/content/content'
import { Flex } from '@Pimcore/components/flex/flex'
import { TreeElement } from '@Pimcore/components/tree-element/tree-element'
import {
useCreateTreeStructure
} from '@Pimcore/modules/element/editor/shared-tab-manager/tabs/tags/components/tags-tree/hooks/use-create-tree-structure'

createTreeStructure
} from '@Pimcore/modules/element/editor/shared-tab-manager/tabs/tags/components/tags-tree/create-tree-structure'
import {
useTagGetCollectionQuery
} from '@Pimcore/modules/element/editor/shared-tab-manager/tabs/tags/tags-api-slice-enhanced'
export const TagsTreeFiltersContainer = ({ addOrUpdateFieldFilter, checkedKeys, setCheckedKeys }: { addOrUpdateFieldFilter: (value: any) => void, checkedKeys: any, setCheckedKeys: any }): React.JSX.Element => {
const { data: tags, isLoading: tagsLoading } = useTagGetCollectionQuery({
page: 1,
pageSize: 9999
})
const { createTreeStructure } = useCreateTreeStructure()

if (tagsLoading) {
return <Content loading />
Expand All @@ -35,7 +35,7 @@ export const TagsTreeFiltersContainer = ({ addOrUpdateFieldFilter, checkedKeys,
return <div>Failed to load tags</div>
}

const treeData = createTreeStructure({ tags: tags.items })
const treeData = createTreeStructure({ tags: tags.items, loadingNodes: new Set<string>() })

const handleCheck = (currentCheckedKeys: { checked: Key[], halfChecked: Key[] }): void => {
const checkedKeysList = currentCheckedKeys.checked
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* 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 {
type TagGetCollectionApiResponse
} from '@Pimcore/modules/element/editor/shared-tab-manager/tabs/tags/tags-api-slice.gen'
import type { TreeDataNode } from 'antd'
import { Icon } from '@Pimcore/components/icon/icon'
import { LoadingOutlined } from '@ant-design/icons'
import React from 'react'

export const createTreeStructure = ({ tags, loadingNodes }: { tags: NonNullable<TagGetCollectionApiResponse['items']>, loadingNodes: Set<string> }): TreeDataNode[] => {
const getTitle = (tagText: string | undefined, isLoading: boolean): React.ReactNode => {
if (tagText === undefined || tagText === null || tagText.trim() === '') {
return isLoading
? (
<span>
<LoadingOutlined style={ { marginLeft: 8 } } />
</span>
)
: null
}

return (
<React.Fragment>
<span>{tagText}</span>
{isLoading && (
<LoadingOutlined style={ { marginLeft: 8 } } />
)}
</React.Fragment>
)
}

function treeWalker (tags: NonNullable<TagGetCollectionApiResponse['items']>): TreeDataNode[] {
return tags.map((tag) => {
const isLoading = loadingNodes.has(tag.id!.toString())
return {
key: tag.id!.toString(),
title: getTitle(tag.text, isLoading),
icon: Icon({
value: 'tag-02'
}),
disableCheckbox: isLoading,
children: tag.hasChildren === true ? treeWalker(tag.children!) : []
}
})
}

return [{
key: 'root',
title: 'All Tags',
icon: Icon({
value: 'folder'
}),
children: tags.length > 0 ? treeWalker(tags) : []
}]
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,11 @@
* @license https://github.com/pimcore/studio-ui-bundle/blob/1.x/LICENSE.md POCL and PCL
*/

import React, { type Key } from 'react'
import React, { type Key, useState } from 'react'
import {
type Tag,
type TagAssignToElementApiArg,
useTagAssignToElementMutation,
useTagUnassignFromElementMutation
type TagAssignToElementApiArg
} from '@Pimcore/modules/element/editor/shared-tab-manager/tabs/tags/tags-api-slice.gen'
import {
useCreateTreeStructure
} from '@Pimcore/modules/element/editor/shared-tab-manager/tabs/tags/components/tags-tree/hooks/use-create-tree-structure'
import {
useOptimisticUpdate
} from '@Pimcore/modules/element/editor/shared-tab-manager/tabs/tags/hooks/use-optimistic-update'
Expand All @@ -29,6 +24,15 @@ import { Flex } from '@Pimcore/components/flex/flex'
import { TreeElement } from '@Pimcore/components/tree-element/tree-element'
import { SearchInput } from '@Pimcore/components/search-input/search-input'
import { type TreeProps } from 'antd'
import {
createTreeStructure
} from '@Pimcore/modules/element/editor/shared-tab-manager/tabs/tags/components/tags-tree/create-tree-structure'
import { t } from 'i18next'
import { useMessage } from '@Pimcore/components/message/useMessage'
import {
useTagAssignToElementMutation,
useTagUnassignFromElementMutation
} from '@Pimcore/modules/element/editor/shared-tab-manager/tabs/tags/tags-api-slice-enhanced'

export interface TagsTreeProps {
elementId: number
Expand All @@ -40,13 +44,22 @@ export interface TagsTreeProps {
setDefaultCheckedTags: (tags: React.Key[]) => void
}

export const TagsTree = ({ elementId, elementType, tags, setFilter, isLoading, defaultCheckedTags, setDefaultCheckedTags }: TagsTreeProps): React.JSX.Element => {
const { createTreeStructure } = useCreateTreeStructure()
const treeData = createTreeStructure({ tags })
export const TagsTree = ({
elementId,
elementType,
tags,
setFilter,
isLoading,
defaultCheckedTags,
setDefaultCheckedTags
}: TagsTreeProps): React.JSX.Element => {
const { updateTagsForElementByTypeAndId } = useOptimisticUpdate()
const messageApi = useMessage()
const flatTags = flattenArray(tags)
const [assignTag] = useTagAssignToElementMutation()
const [loadingNodes, setLoadingNodes] = useState<Set<string>>(new Set())
const [unassignTag] = useTagUnassignFromElementMutation()
const treeData = createTreeStructure({ tags, loadingNodes })

const applyTagsToElement = async (checkedTags: Key[]): Promise<void> => {
updateTagsForElementByTypeAndId({
Expand Down Expand Up @@ -95,8 +108,12 @@ export const TagsTree = ({ elementId, elementType, tags, setFilter, isLoading, d
}
}

const handleCheck: TreeProps['onCheck'] = async (checkedKeys: { checked: Key[], halfChecked: Key[] }, info): Promise<void> => {
const handleCheck: TreeProps['onCheck'] = async (checkedKeys: {
checked: Key[]
halfChecked: Key[]
}, info): Promise<void> => {
const tagId = Number(info.node.key)
setLoadingNodes((prev) => new Set(prev).add(String(tagId)))

void applyTagsToElement(checkedKeys.checked)

Expand All @@ -105,7 +122,24 @@ export const TagsTree = ({ elementId, elementType, tags, setFilter, isLoading, d
? await assignTagToElement(tagId)
: await removeTagFromElement(tagId)
} catch (e) {
void applyTagsToElement(checkedKeys.checked.filter((key) => key !== tagId))
console.log('----> here', (checkedKeys.checked))
const errorMessage = info.checked
? t('failed-to-assign-tag-to-element')
: t('failed-to-un-assign-tag-to-element')
// eslint-disable-next-line @typescript-eslint/no-floating-promises
messageApi.error({
content: errorMessage,
type: 'error',
duration: 5
})

void applyTagsToElement(checkedKeys.checked.filter((key) => key !== String(tagId)))
} finally {
setLoadingNodes((prev) => {
const newSet = new Set(prev)
newSet.delete(String(tagId))
return newSet
})
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ export const useOptimisticUpdate = (): UseOptimisticUpdateReturn => {
)
)
}

return {
updateTagsForElementByTypeAndId
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
*/

import {
type TagBatchOperationToElementsByTypeAndIdApiArg,
useTagBatchOperationToElementsByTypeAndIdMutation
type TagBatchOperationToElementsByTypeAndIdApiArg
} from '@Pimcore/modules/element/editor/shared-tab-manager/tabs/tags/tags-api-slice.gen'
import { useElementContext } from '@Pimcore/modules/element/hooks/use-element-context'
import { useJobs } from '@Pimcore/modules/execution-engine/hooks/useJobs'
import { createJob } from '@Pimcore/modules/execution-engine/jobs/tag-assign/factory'
import { defaultTopics, topics } from '@Pimcore/modules/execution-engine/topics'
import {
useTagBatchOperationToElementsByTypeAndIdMutation
} from '@Pimcore/modules/element/editor/shared-tab-manager/tabs/tags/tags-api-slice-enhanced'

interface UseShortcutActionsReturn {
removeAndApplyTagsToChildren: () => Promise<void>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* 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 { invalidatingTags, providingTags, type Tag, tagNames } from '@Pimcore/app/api/pimcore/tags'
import { api as baseApi } from './tags-api-slice.gen'

export const api = baseApi.enhanceEndpoints({
addTagTypes: [tagNames.TAGS, tagNames.ASSET_DETAIL, tagNames.DATA_OBJECT_DETAIL],
endpoints: {
tagGetCollection: {
providesTags: (result, error, args) => {
const tags: Tag[] = []
// all possible tags that can be applied
if (result?.items !== undefined && result.items !== null) {
result.items.forEach((assignedTag) => {
if (assignedTag.id !== undefined) {
tags.push(...providingTags.TAGS_ID(assignedTag.id))
}
})
}

return tags
}
},
tagAssignToElement: {
invalidatesTags: (result, error, args) => invalidatingTags.ELEMENT_TAGS_ID(args.id)
},
tagUnassignFromElement: {
invalidatesTags: (result, error, args) => invalidatingTags.ELEMENT_TAGS_ID(args.id)
},
tagBatchOperationToElementsByTypeAndId: {
// when tags from folder are applied to children assets or data objects
invalidatesTags: (result, error, args) => invalidatingTags.ELEMENT_TAGS(args.elementType, args.id)
},
tagGetCollectionForElementByTypeAndId: {
providesTags: (result, error, args) => {
const tags: Tag[] = []
// all tags that are applied to an element
const items = Array.isArray(result?.items) ? result.items : []
items.forEach((assignedTag) => {
if (assignedTag.id !== undefined) {
tags.push(...providingTags.ELEMENT_TAGS(args.elementType, assignedTag.id))
}
})

return tags
}
}
}
})

export type * from './tags-api-slice.gen'
export const { useTagGetCollectionQuery, useTagAssignToElementMutation, useTagUnassignFromElementMutation, useTagGetCollectionForElementByTypeAndIdQuery, useTagBatchOperationToElementsByTypeAndIdMutation } = api
Loading