mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-26 13:47:26 +03:00
Tags action (#2997)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
parent
e4a53a1b37
commit
26b2a634fa
@ -27,8 +27,7 @@ export default mergeIds(tagsId, tags, {
|
|||||||
Tags: '' as AnyComponent,
|
Tags: '' as AnyComponent,
|
||||||
TagReferencePresenter: '' as AnyComponent,
|
TagReferencePresenter: '' as AnyComponent,
|
||||||
TagsItemPresenter: '' as AnyComponent,
|
TagsItemPresenter: '' as AnyComponent,
|
||||||
TagsFilter: '' as AnyComponent,
|
TagsFilter: '' as AnyComponent
|
||||||
TagsEditorPopup: '' as AnyComponent
|
|
||||||
},
|
},
|
||||||
string: {
|
string: {
|
||||||
TagElementLabel: '' as IntlString,
|
TagElementLabel: '' as IntlString,
|
||||||
|
@ -1509,6 +1509,58 @@ export function createModel (builder: Builder): void {
|
|||||||
tracker.action.SetSprint
|
tracker.action.SetSprint
|
||||||
)
|
)
|
||||||
|
|
||||||
|
createAction(
|
||||||
|
builder,
|
||||||
|
{
|
||||||
|
action: view.actionImpl.ShowPopup,
|
||||||
|
actionProps: {
|
||||||
|
component: tags.component.TagsEditorPopup,
|
||||||
|
element: 'top',
|
||||||
|
fillProps: {
|
||||||
|
_object: 'object'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
label: tracker.string.Labels,
|
||||||
|
icon: tags.icon.Tags,
|
||||||
|
keyBinding: ['keyL'],
|
||||||
|
input: 'focus',
|
||||||
|
category: tracker.category.Tracker,
|
||||||
|
target: tracker.class.Issue,
|
||||||
|
context: {
|
||||||
|
mode: ['context', 'browser'],
|
||||||
|
application: tracker.app.Tracker,
|
||||||
|
group: 'edit'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tracker.action.SetLabels
|
||||||
|
)
|
||||||
|
|
||||||
|
createAction(
|
||||||
|
builder,
|
||||||
|
{
|
||||||
|
action: view.actionImpl.ShowPopup,
|
||||||
|
actionProps: {
|
||||||
|
component: tags.component.ObjectsTagsEditorPopup,
|
||||||
|
element: 'top',
|
||||||
|
fillProps: {
|
||||||
|
_objects: 'objects'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
label: tracker.string.Labels,
|
||||||
|
icon: tags.icon.Tags,
|
||||||
|
keyBinding: ['keyL'],
|
||||||
|
input: 'selection',
|
||||||
|
category: tracker.category.Tracker,
|
||||||
|
target: tracker.class.Issue,
|
||||||
|
context: {
|
||||||
|
mode: ['context', 'browser'],
|
||||||
|
application: tracker.app.Tracker,
|
||||||
|
group: 'edit'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tracker.action.SetLabels
|
||||||
|
)
|
||||||
|
|
||||||
createAction(
|
createAction(
|
||||||
builder,
|
builder,
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2023 Hardcore Engineering Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License. You may
|
||||||
|
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
import { Doc, Ref } from '@hcengineering/core'
|
||||||
|
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||||
|
import tags, { TagElement, TagReference } from '@hcengineering/tags'
|
||||||
|
import TagsPopup from './TagsPopup.svelte'
|
||||||
|
|
||||||
|
export let objects: Doc[]
|
||||||
|
|
||||||
|
let selected: Ref<TagElement>[] = []
|
||||||
|
let tagRefs: TagReference[] = []
|
||||||
|
const query = createQuery()
|
||||||
|
$: query.query(tags.class.TagReference, { attachedTo: { $in: objects.map((p) => p._id) } }, (result) => {
|
||||||
|
tagRefs = result
|
||||||
|
const res: Record<Ref<TagElement>, TagReference> = {}
|
||||||
|
for (const value of result) {
|
||||||
|
const arr = (res as any)[value.tag] ?? []
|
||||||
|
arr.push(value)
|
||||||
|
;(res as any)[value.tag] = arr
|
||||||
|
}
|
||||||
|
const sel: Ref<TagElement>[] = []
|
||||||
|
for (const value in res) {
|
||||||
|
if ((res as any)[value].length === objects.length) {
|
||||||
|
sel.push(value as Ref<TagElement>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selected = sel
|
||||||
|
})
|
||||||
|
|
||||||
|
const client = getClient()
|
||||||
|
async function addRef ({ title, color, _id: tag }: TagElement): Promise<void> {
|
||||||
|
await Promise.all(
|
||||||
|
objects.map(async (object) => {
|
||||||
|
if (tagRefs.findIndex((p) => p.attachedTo === object._id) !== -1) return
|
||||||
|
await client.addCollection(tags.class.TagReference, object.space, object._id, object._class, 'labels', {
|
||||||
|
title,
|
||||||
|
color,
|
||||||
|
tag
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
async function removeTag (tag: TagElement): Promise<void> {
|
||||||
|
await Promise.all(
|
||||||
|
objects.map(async (object) => {
|
||||||
|
const tagRef = await client.findOne(tags.class.TagReference, { attachedTo: object._id, tag: tag._id })
|
||||||
|
if (tagRef) await client.remove(tagRef)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
async function onUpdate (event: CustomEvent<{ action: string; tag: TagElement }>) {
|
||||||
|
const result = event.detail
|
||||||
|
if (result === undefined) return
|
||||||
|
if (result.action === 'add') addRef(result.tag)
|
||||||
|
else if (result.action === 'remove') removeTag(result.tag)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<TagsPopup targetClass={objects[0]._class} {selected} on:update={onUpdate} />
|
@ -1,3 +1,17 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2023 Hardcore Engineering Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License. You may
|
||||||
|
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
//
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Doc, Ref } from '@hcengineering/core'
|
import { Doc, Ref } from '@hcengineering/core'
|
||||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||||
@ -20,7 +34,7 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
async function removeTag (tag: TagElement): Promise<void> {
|
async function removeTag (tag: TagElement): Promise<void> {
|
||||||
const tagRef = await client.findOne(tags.class.TagReference, { tag: tag._id })
|
const tagRef = await client.findOne(tags.class.TagReference, { tag: tag._id, attachedTo: object._id })
|
||||||
if (tagRef) await client.remove(tagRef)
|
if (tagRef) await client.remove(tagRef)
|
||||||
}
|
}
|
||||||
async function onUpdate (event: CustomEvent<{ action: string; tag: TagElement }>) {
|
async function onUpdate (event: CustomEvent<{ action: string; tag: TagElement }>) {
|
||||||
|
@ -31,6 +31,7 @@ import TagsAttributeEditor from './components/TagsAttributeEditor.svelte'
|
|||||||
import TagsEditorPopup from './components/TagsEditorPopup.svelte'
|
import TagsEditorPopup from './components/TagsEditorPopup.svelte'
|
||||||
import LabelsPresenter from './components/LabelsPresenter.svelte'
|
import LabelsPresenter from './components/LabelsPresenter.svelte'
|
||||||
import CreateTagElement from './components/CreateTagElement.svelte'
|
import CreateTagElement from './components/CreateTagElement.svelte'
|
||||||
|
import ObjectsTagsEditorPopup from './components/ObjectsTagsEditorPopup.svelte'
|
||||||
import { ObjQueryType } from '@hcengineering/core'
|
import { ObjQueryType } from '@hcengineering/core'
|
||||||
import { getRefs } from './utils'
|
import { getRefs } from './utils'
|
||||||
import { Filter } from '@hcengineering/view'
|
import { Filter } from '@hcengineering/view'
|
||||||
@ -67,7 +68,8 @@ export default async (): Promise<Resources> => ({
|
|||||||
TagElementCountPresenter,
|
TagElementCountPresenter,
|
||||||
TagsAttributeEditor,
|
TagsAttributeEditor,
|
||||||
TagsEditorPopup,
|
TagsEditorPopup,
|
||||||
LabelsPresenter
|
LabelsPresenter,
|
||||||
|
ObjectsTagsEditorPopup
|
||||||
},
|
},
|
||||||
actionImpl: {
|
actionImpl: {
|
||||||
Open: (value: TagElement, evt: MouseEvent) => {
|
Open: (value: TagElement, evt: MouseEvent) => {
|
||||||
|
@ -107,7 +107,9 @@ const tagsPlugin = plugin(tagsId, {
|
|||||||
TagsAttributeEditor: '' as AnyComponent,
|
TagsAttributeEditor: '' as AnyComponent,
|
||||||
TagsPresenter: '' as AnyComponent,
|
TagsPresenter: '' as AnyComponent,
|
||||||
LabelsPresenter: '' as AnyComponent,
|
LabelsPresenter: '' as AnyComponent,
|
||||||
TagElementPresenter: '' as AnyComponent
|
TagElementPresenter: '' as AnyComponent,
|
||||||
|
TagsEditorPopup: '' as AnyComponent,
|
||||||
|
ObjectsTagsEditorPopup: '' as AnyComponent
|
||||||
},
|
},
|
||||||
category: {
|
category: {
|
||||||
NoCategory: '' as Ref<TagCategory>
|
NoCategory: '' as Ref<TagCategory>
|
||||||
|
@ -504,7 +504,8 @@ export default plugin(trackerId, {
|
|||||||
NewSubIssue: '' as Ref<Action>,
|
NewSubIssue: '' as Ref<Action>,
|
||||||
EditWorkflowStatuses: '' as Ref<Action>,
|
EditWorkflowStatuses: '' as Ref<Action>,
|
||||||
EditProject: '' as Ref<Action>,
|
EditProject: '' as Ref<Action>,
|
||||||
SetSprint: '' as Ref<Action>
|
SetSprint: '' as Ref<Action>,
|
||||||
|
SetLabels: '' as Ref<Action>
|
||||||
},
|
},
|
||||||
project: {
|
project: {
|
||||||
DefaultProject: '' as Ref<Project>
|
DefaultProject: '' as Ref<Project>
|
||||||
|
Loading…
Reference in New Issue
Block a user