Fix process issues (#2287)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2022-10-06 21:48:16 +07:00 committed by GitHub
parent b2b6b6de90
commit 4ed2f7ede2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 123 additions and 38 deletions

View File

@ -940,7 +940,7 @@ export function createModel (builder: Builder): void {
})
builder.mixin(tracker.class.IssueTemplate, core.class.Class, view.mixin.ClassFilters, {
filters: ['priority', 'assignee', 'project', 'sprint', 'estimation', 'modifiedOn']
filters: ['priority', 'assignee', 'project', 'sprint', 'modifiedOn']
})
builder.createDoc(

View File

@ -50,7 +50,7 @@ function $pull (document: Doc, keyval: Record<string, PropertyType>): void {
doc[key] = []
}
const arr = doc[key] as Array<any>
if (typeof keyval[key] === 'object') {
if (typeof keyval[key] === 'object' && keyval[key] !== null) {
const { $in } = keyval[key] as PullArray<PropertyType>
doc[key] = arr.filter((val) => {

View File

@ -45,10 +45,23 @@ let client: TxOperations
const txListeners: Array<(tx: Tx) => void> = []
/**
* @public
*/
export function addTxListener (l: (tx: Tx) => void): void {
txListeners.push(l)
}
/**
* @public
*/
export function removeTxListener (l: (tx: Tx) => void): void {
const pos = txListeners.findIndex((it) => it === l)
if (pos !== -1) {
txListeners.splice(pos, 1)
}
}
class UIClient extends TxOperations implements Client {
constructor (client: Client, private readonly liveQuery: LQ) {
super(client, getCurrentAccount()._id)
@ -59,10 +72,16 @@ class UIClient extends TxOperations implements Client {
}
}
/**
* @public
*/
export function getClient (): TxOperations {
return client
}
/**
* @public
*/
export function setClient (_client: Client): void {
liveQuery = new LQ(_client)
client = new UIClient(_client, liveQuery)
@ -73,6 +92,9 @@ export function setClient (_client: Client): void {
}
}
/**
* @public
*/
export class LiveQuery {
private oldClass: Ref<Class<Doc>> | undefined
private oldQuery: DocumentQuery<Doc> | undefined
@ -128,10 +150,16 @@ export class LiveQuery {
}
}
/**
* @public
*/
export function createQuery (dontDestroy?: boolean): LiveQuery {
return new LiveQuery(dontDestroy)
}
/**
* @public
*/
export function getFileUrl (file: string, size: IconSize = 'full'): string {
const uploadUrl = getMetadata(login.metadata.UploadUrl)
const token = getMetadata(login.metadata.LoginToken)
@ -139,6 +167,9 @@ export function getFileUrl (file: string, size: IconSize = 'full'): string {
return url
}
/**
* @public
*/
export async function getBlobURL (blob: Blob): Promise<string> {
return await new Promise((resolve) => {
const reader = new FileReader()
@ -148,6 +179,9 @@ export async function getBlobURL (blob: Blob): Promise<string> {
})
}
/**
* @public
*/
export async function copyTextToClipboard (text: string): Promise<void> {
try {
// Safari specific behavior
@ -162,9 +196,16 @@ export async function copyTextToClipboard (text: string): Promise<void> {
}
}
/**
* @public
*/
export type AttributeCategory = 'attribute' | 'inplace' | 'collection' | 'array'
/**
* @public
*/
export const AttributeCategoryOrder = { attribute: 0, inplace: 1, collection: 2, array: 2 }
/**
* @public
*/

View File

@ -132,12 +132,27 @@
templateQuery.unsubscribe()
}
function updateObject (template: IssueTemplate): void {
function tagAsRef (tag: TagElement): TagReference {
return {
_class: tags.class.TagReference,
_id: generateId() as Ref<TagReference>,
attachedTo: '' as Ref<Doc>,
attachedToClass: tracker.class.Issue,
collection: 'labels',
space: tags.space.Tags,
modifiedOn: 0,
modifiedBy: '' as Ref<Account>,
title: tag.title,
tag: tag._id,
color: tag.color
}
}
async function updateObject (template: IssueTemplate): Promise<void> {
if (object.template?.template === template._id) {
return
}
const { _class, _id, space, children, comments, attachments, labels, dueDate, ...templBase } = template
const { _class, _id, space, children, comments, attachments, labels: labels_, ...templBase } = template
subIssues = template.children
@ -148,6 +163,8 @@
template: template._id
}
}
const tagElements = await client.findAll(tags.class.TagElement, { _id: { $in: labels_ } })
labels = tagElements.map(tagAsRef)
}
function updateTemplate (template?: IssueTemplate): void {
if (template !== undefined) {
@ -304,7 +321,7 @@
rank: calcRank(lastOne, undefined),
comments: 0,
subIssues: 0,
dueDate: subIssue.dueDate,
dueDate: null,
parents: parentIssue
? [
{ parentId: objectId, parentTitle: value.title },
@ -313,7 +330,7 @@
]
: [{ parentId: objectId, parentTitle: value.title }],
reportedTime: 0,
estimation: object.estimation,
estimation: subIssue.estimation,
reports: 0,
relations: [],
childInfo: []
@ -405,22 +422,7 @@
}
function addTagRef (tag: TagElement): void {
labels = [
...labels,
{
_class: tags.class.TagReference,
_id: generateId() as Ref<TagReference>,
attachedTo: '' as Ref<Doc>,
attachedToClass: tracker.class.Issue,
collection: 'labels',
space: tags.space.Tags,
modifiedOn: 0,
modifiedBy: '' as Ref<Account>,
title: tag.title,
tag: tag._id,
color: tag.color
}
]
labels = [...labels, tagAsRef(tag)]
}
function handleTemplateChange (evt: CustomEvent<Ref<IssueTemplate>>): void {
if (templateId == null) {

View File

@ -27,6 +27,7 @@
import PriorityEditor from '../issues/PriorityEditor.svelte'
import ProjectSelector from '../ProjectSelector.svelte'
import SprintSelector from '../sprints/SprintSelector.svelte'
import EstimationEditor from './EstimationEditor.svelte'
import SubIssueTemplates from './IssueTemplateChilds.svelte'
export let space: Ref<Team>
@ -35,7 +36,6 @@
export let project: Ref<Project> | null = $activeProject ?? null
export let sprint: Ref<Sprint> | null = $activeSprint ?? null
const dueDate: number | undefined = undefined
let labels: TagElement[] = []
let objectId: Ref<IssueTemplate> = generateId()
@ -46,7 +46,6 @@
project: project,
sprint: sprint,
priority: priority,
dueDate: dueDate ?? null,
estimation: 0,
children: [],
labels: [],
@ -89,7 +88,6 @@
project: object.project,
sprint: object.sprint,
priority: object.priority,
dueDate: dueDate ?? null,
estimation: object.estimation,
children: object.children,
comments: 0,
@ -211,9 +209,7 @@
labels = labels.filter((it) => it._id !== evt.detail)
}}
/>
<!-- <EstimationEditor kind={'no-border'} size={'small'} value={object} /> -->
<!-- <NumberEditor kind={'no-border'} bind:value={dueDate} placeholder={tracker.string.DueDate}
focus={false} onChange={({ detail }) => (dueDate = detail) }/> -->
<EstimationEditor kind={'no-border'} size={'small'} value={object} />
<ProjectSelector value={object.project} onChange={handleProjectIdChanged} />
<SprintSelector value={object.sprint} onChange={handleSprintIdChanged} useProject={object.project ?? undefined} />
</div>

View File

@ -21,6 +21,7 @@
import presentation, { createQuery, getClient, MessageViewer } from '@hcengineering/presentation'
import setting, { settingId } from '@hcengineering/setting'
import type { IssueTemplate, IssueTemplateChild, Team } from '@hcengineering/tracker'
import tags from '@hcengineering/tags'
import {
Button,
EditBox,
@ -85,7 +86,7 @@
description = template.description
currentTeam = template.$lookup?.space
},
{ lookup: { space: tracker.class.Team } }
{ lookup: { space: tracker.class.Team, labels: tags.class.TagElement } }
)
$: canSave = title.trim().length > 0

View File

@ -13,6 +13,7 @@
// limitations under the License.
-->
<script lang="ts">
import { Data } from '@hcengineering/core'
import { getClient } from '@hcengineering/presentation'
import { IssueTemplate, IssueTemplateChild } from '@hcengineering/tracker'
import { Button, ButtonKind, ButtonSize, eventToHTMLElement, showPopup } from '@hcengineering/ui'
@ -20,7 +21,7 @@
import { createEventDispatcher } from 'svelte'
import tracker from '../../plugin'
export let value: IssueTemplateChild | IssueTemplate
export let value: IssueTemplateChild | IssueTemplate | Data<IssueTemplate>
export let isEditable: boolean = true
export let kind: ButtonKind = 'link'

View File

@ -14,7 +14,7 @@
-->
<script lang="ts">
import { generateId, Ref } from '@hcengineering/core'
import presentation, { getClient, KeyedAttribute } from '@hcengineering/presentation'
import presentation, { createQuery, getClient, KeyedAttribute } from '@hcengineering/presentation'
import tags, { TagElement, TagReference } from '@hcengineering/tags'
import { StyledTextArea } from '@hcengineering/text-editor'
import { IssuePriority, IssueTemplateChild, Project, Sprint } from '@hcengineering/tracker'
@ -38,6 +38,12 @@
let focusIssueTitle: () => void
let labels: TagElement[] = []
const labelsQuery = createQuery()
$: labelsQuery.query(tags.class.TagElement, { _id: { $in: childIssue?.labels ?? [] } }, (res) => {
labels = res
})
const key: KeyedAttribute = {
key: 'labels',
attr: client.getHierarchy().getAttribute(tracker.class.IssueTemplate, 'labels')
@ -51,7 +57,6 @@
assignee: null,
project: null,
priority: IssuePriority.NoPriority,
dueDate: null,
sprint: sprint,
estimation: 0
}

View File

@ -13,10 +13,11 @@
// limitations under the License.
-->
<script lang="ts">
import { Doc } from '@hcengineering/core'
import { Doc, generateId, Ref, WithLookup } from '@hcengineering/core'
import { AttributeBarEditor, createQuery, getClient, KeyedAttribute } from '@hcengineering/presentation'
import tags, { TagElement, TagReference } from '@hcengineering/tags'
import type { IssueTemplate } from '@hcengineering/tracker'
import { Label } from '@hcengineering/ui'
import { Component, Label } from '@hcengineering/ui'
import { getFiltredKeys, isCollectionAttr } from '@hcengineering/view-resources/src/utils'
import tracker from '../../plugin'
import AssigneeEditor from '../issues/AssigneeEditor.svelte'
@ -24,7 +25,7 @@
import ProjectEditor from '../projects/ProjectEditor.svelte'
import SprintEditor from '../sprints/SprintEditor.svelte'
export let issue: IssueTemplate
export let issue: WithLookup<IssueTemplate>
const query = createQuery()
let showIsBlocking = false
@ -45,6 +46,30 @@
}
$: updateKeys(['title', 'description', 'priority', 'number', 'assignee', 'project', 'sprint'])
const key: KeyedAttribute = {
key: 'labels',
attr: client.getHierarchy().getAttribute(tracker.class.IssueTemplate, 'labels')
}
let labelRefs: TagReference[] = []
$: labelIds = issue?.$lookup?.labels ?? []
$: if (labelIds !== undefined) {
labelRefs = (Array.isArray(labelIds) ? labelIds : [labelIds]).map(
(it) => ({ ...(it as unknown as TagReference), _id: generateId(), tag: it._id } as unknown as TagReference)
)
}
const onTagDelete = async (evt: CustomEvent<Ref<TagReference>>): Promise<void> => {
const itm = labelRefs.find((it) => it._id === evt.detail)
if (itm !== undefined) {
await client.update(issue, {
$pull: { labels: itm.tag as unknown as Ref<TagElement> }
})
}
}
</script>
<div class="content">
@ -58,10 +83,24 @@
</span>
<AssigneeEditor value={issue} />
<!-- <span class="labelTop">
<span class="labelTop">
<Label label={tracker.string.Labels} />
</span> -->
<!-- <Component is={tags.component.TagsAttributeEditor} props={{ object: issue, label: tracker.string.AddLabel }} /> -->
</span>
<Component
is={tags.component.TagsDropdownEditor}
props={{
kind: 'no-border',
items: labelRefs,
key,
targetClass: tracker.class.Issue,
countLabel: tracker.string.NumberLabels
}}
on:open={async (evt) => {
await client.update(issue, { $push: { labels: evt.detail._id } })
}}
on:delete={onTagDelete}
/>
<div class="divider" />