mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-29 13:05:08 +02:00
UBER-134: Back references (#3233)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
@@ -71,6 +71,7 @@
|
||||
import SetDueDateActionPopup from './SetDueDateActionPopup.svelte'
|
||||
import SetParentIssueActionPopup from './SetParentIssueActionPopup.svelte'
|
||||
import SubIssues from './SubIssues.svelte'
|
||||
import { createBacklinks } from '@hcengineering/chunter-resources'
|
||||
|
||||
export let space: Ref<Project>
|
||||
export let status: Ref<IssueStatus> | undefined = undefined
|
||||
@@ -400,6 +401,9 @@
|
||||
issueUrl: currentProject && generateIssueShortLink(getIssueId(currentProject, value as Issue))
|
||||
})
|
||||
|
||||
// Create an backlink to document
|
||||
await createBacklinks(client, _id, tracker.class.Issue, _id, object.description)
|
||||
|
||||
draftController.remove()
|
||||
resetObject()
|
||||
descriptionBox?.removeDraft(false)
|
||||
@@ -607,6 +611,7 @@
|
||||
alwaysEdit
|
||||
showButtons={false}
|
||||
emphasized
|
||||
enableBackReferences={true}
|
||||
bind:content={object.description}
|
||||
placeholder={tracker.string.IssueDescriptionPlaceholder}
|
||||
on:changeSize={() => dispatch('changeContent')}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { AttachmentStyleBoxEditor } from '@hcengineering/attachment-resources'
|
||||
import { updateBacklinks } from '@hcengineering/chunter-resources'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { Component } from '@hcengineering/tracker'
|
||||
import { EditBox } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import tracker from '../../plugin'
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
export let object: Component
|
||||
|
||||
@@ -23,14 +24,16 @@
|
||||
rawLabel = object.label
|
||||
}
|
||||
|
||||
onMount(() => dispatch('open', { ignoreKeys: ['label'] }))
|
||||
onMount(() => dispatch('open', { ignoreKeys: ['label', 'description', 'attachments'] }))
|
||||
|
||||
$: descriptionKey = client.getHierarchy().getAttribute(tracker.class.Component, 'description')
|
||||
let descriptionBox: AttachmentStyleBoxEditor
|
||||
</script>
|
||||
|
||||
<EditBox
|
||||
bind:value={rawLabel}
|
||||
placeholder={tracker.string.Component}
|
||||
kind="large-style"
|
||||
focusable
|
||||
on:blur={() => {
|
||||
const trimmedLabel = rawLabel.trim()
|
||||
|
||||
@@ -41,3 +44,16 @@
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<div class="w-full mt-6">
|
||||
<AttachmentStyleBoxEditor
|
||||
focusIndex={30}
|
||||
{object}
|
||||
key={{ key: 'description', attr: descriptionKey }}
|
||||
bind:this={descriptionBox}
|
||||
placeholder={tracker.string.IssueDescriptionPlaceholder}
|
||||
updateBacklinks={(doc, description) => {
|
||||
updateBacklinks(client, doc._id, doc._class, doc._id, description)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
bind:content={object.description}
|
||||
placeholder={tracker.string.ComponentDescriptionPlaceholder}
|
||||
emphasized
|
||||
showButtons={false}
|
||||
/>
|
||||
<svelte:fragment slot="pool">
|
||||
<EmployeeBox
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { AttachmentStyledBox } from '@hcengineering/attachment-resources'
|
||||
import { Class, Data, Doc, Ref, WithLookup } from '@hcengineering/core'
|
||||
import { AttachmentStyleBoxEditor } from '@hcengineering/attachment-resources'
|
||||
import { Class, Doc, Ref, WithLookup } from '@hcengineering/core'
|
||||
import notification from '@hcengineering/notification'
|
||||
import { Panel } from '@hcengineering/panel'
|
||||
import { getResource } from '@hcengineering/platform'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import presentation, { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import setting, { settingId } from '@hcengineering/setting'
|
||||
import type { Issue, Project } from '@hcengineering/tracker'
|
||||
import {
|
||||
@@ -43,6 +43,7 @@
|
||||
import CopyToClipboard from './CopyToClipboard.svelte'
|
||||
import SubIssueSelector from './SubIssueSelector.svelte'
|
||||
import SubIssues from './SubIssues.svelte'
|
||||
import { updateBacklinks } from '@hcengineering/chunter-resources'
|
||||
|
||||
export let _id: Ref<Issue>
|
||||
export let _class: Ref<Class<Issue>>
|
||||
@@ -58,7 +59,7 @@
|
||||
let title = ''
|
||||
let description = ''
|
||||
let innerWidth: number
|
||||
let descriptionBox: AttachmentStyledBox
|
||||
let descriptionBox: AttachmentStyleBoxEditor
|
||||
let showAllMixins: boolean
|
||||
|
||||
const notificationClient = getResource(notification.function.GetNotificationClient).then((res) => res())
|
||||
@@ -82,8 +83,7 @@
|
||||
_class,
|
||||
{ _id },
|
||||
async (result) => {
|
||||
if (saveTrigger !== undefined && lastId !== _id) {
|
||||
clearTimeout(saveTrigger)
|
||||
if (lastId !== _id) {
|
||||
await save()
|
||||
}
|
||||
;[issue] = result
|
||||
@@ -102,36 +102,15 @@
|
||||
|
||||
let saved = false
|
||||
async function save () {
|
||||
clearTimeout(saveTrigger)
|
||||
if (!issue || !canSave) {
|
||||
return
|
||||
}
|
||||
|
||||
const updates: Partial<Data<Issue>> = {}
|
||||
const trimmedTitle = title.trim()
|
||||
|
||||
if (trimmedTitle.length > 0 && trimmedTitle !== issue.title) {
|
||||
updates.title = trimmedTitle
|
||||
await client.update(issue, { title: trimmedTitle })
|
||||
}
|
||||
|
||||
if (description !== issue.description) {
|
||||
updates.description = description
|
||||
}
|
||||
|
||||
if (Object.keys(updates).length > 0) {
|
||||
await client.update(issue, updates)
|
||||
saved = true
|
||||
setTimeout(() => {
|
||||
saved = false
|
||||
}, 5000)
|
||||
}
|
||||
await descriptionBox.createAttachments()
|
||||
}
|
||||
|
||||
let saveTrigger: any
|
||||
function triggerSave (): void {
|
||||
clearTimeout(saveTrigger)
|
||||
saveTrigger = setTimeout(save, 5000)
|
||||
}
|
||||
|
||||
function showMenu (ev?: Event): void {
|
||||
@@ -151,6 +130,8 @@
|
||||
// If it is embedded
|
||||
$: lastCtx = $contextStore.getLastContext()
|
||||
$: isContextEnabled = lastCtx?.mode === 'editor' || lastCtx?.mode === 'browser'
|
||||
|
||||
$: descriptionKey = client.getHierarchy().getAttribute(tracker.class.Issue, 'description')
|
||||
</script>
|
||||
|
||||
{#if !embedded}
|
||||
@@ -165,21 +146,21 @@
|
||||
{#if issue !== undefined}
|
||||
<Panel
|
||||
object={issue}
|
||||
isHeader
|
||||
isHeader={false}
|
||||
isAside={true}
|
||||
isSub={false}
|
||||
withoutActivity={false}
|
||||
{embedded}
|
||||
withoutTitle
|
||||
bind:innerWidth
|
||||
on:open
|
||||
on:close={() => dispatch('close')}
|
||||
>
|
||||
<svelte:fragment slot="navigator">
|
||||
<UpDownNavigator element={issue} />
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="header">
|
||||
<span class="fs-title select-text-i">
|
||||
{#if !embedded}
|
||||
<UpDownNavigator element={issue} />
|
||||
{/if}
|
||||
|
||||
<span class="ml-4 fs-title select-text-i">
|
||||
{#if embedded}
|
||||
<DocNavLink object={issue}>
|
||||
{#if issueId}{issueId}{/if}
|
||||
@@ -187,11 +168,10 @@
|
||||
{:else if issueId}{issueId}{/if}
|
||||
</span>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="tools">
|
||||
<svelte:fragment slot="pre-utils">
|
||||
{#if saved}
|
||||
<Label label={tracker.string.Saved} />
|
||||
<Label label={presentation.string.Saved} />
|
||||
{/if}
|
||||
<Button icon={IconMoreH} kind={'transparent'} size={'medium'} on:click={showMenu} />
|
||||
</svelte:fragment>
|
||||
|
||||
{#if parentIssue}
|
||||
@@ -212,26 +192,19 @@
|
||||
focus={!embedded}
|
||||
/>
|
||||
<div class="w-full mt-6">
|
||||
{#key issue._id}
|
||||
<AttachmentStyledBox
|
||||
focusIndex={30}
|
||||
bind:this={descriptionBox}
|
||||
useAttachmentPreview={true}
|
||||
objectId={_id}
|
||||
_class={tracker.class.Issue}
|
||||
space={issue.space}
|
||||
alwaysEdit
|
||||
on:attached={(e) => descriptionBox.saveNewAttachment(e.detail)}
|
||||
on:detached={(e) => descriptionBox.removeAttachmentById(e.detail)}
|
||||
showButtons
|
||||
on:blur={save}
|
||||
on:changeContent={triggerSave}
|
||||
maxHeight={'card'}
|
||||
focusable
|
||||
bind:content={description}
|
||||
placeholder={tracker.string.IssueDescriptionPlaceholder}
|
||||
/>
|
||||
{/key}
|
||||
<AttachmentStyleBoxEditor
|
||||
focusIndex={30}
|
||||
object={issue}
|
||||
key={{ key: 'description', attr: descriptionKey }}
|
||||
bind:this={descriptionBox}
|
||||
placeholder={tracker.string.IssueDescriptionPlaceholder}
|
||||
on:saved={(evt) => {
|
||||
saved = evt.detail
|
||||
}}
|
||||
updateBacklinks={(doc, description) => {
|
||||
updateBacklinks(client, doc._id, doc._class, doc._id, description)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
@@ -250,8 +223,8 @@
|
||||
<span slot="actions-label" class="select-text">
|
||||
{#if issueId}{issueId}{/if}
|
||||
</span>
|
||||
<svelte:fragment slot="actions">
|
||||
<div class="flex-grow" />
|
||||
<svelte:fragment slot="utils">
|
||||
<Button icon={IconMoreH} kind={'transparent'} size={'medium'} on:click={showMenu} />
|
||||
{#if issueId}
|
||||
<CopyToClipboard issueUrl={generateIssueShortLink(issueId)} {issueId} />
|
||||
{/if}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
import { EditBox } from '@hcengineering/ui'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import tracker from '../../plugin'
|
||||
import { AttachmentStyleBoxEditor } from '@hcengineering/attachment-resources'
|
||||
import { updateBacklinks } from '@hcengineering/chunter-resources'
|
||||
|
||||
export let object: Milestone
|
||||
|
||||
@@ -36,14 +38,15 @@
|
||||
rawLabel = object.label
|
||||
}
|
||||
|
||||
onMount(() => dispatch('open', { ignoreKeys: ['label'] }))
|
||||
onMount(() => dispatch('open', { ignoreKeys: ['label', 'description', 'attachments'] }))
|
||||
$: descriptionKey = client.getHierarchy().getAttribute(tracker.class.Component, 'description')
|
||||
let descriptionBox: AttachmentStyleBoxEditor
|
||||
</script>
|
||||
|
||||
<EditBox
|
||||
bind:value={rawLabel}
|
||||
placeholder={tracker.string.MilestoneNamePlaceholder}
|
||||
kind="large-style"
|
||||
focusable
|
||||
on:blur={async () => {
|
||||
const trimmedLabel = rawLabel.trim()
|
||||
|
||||
@@ -54,3 +57,16 @@
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
<div class="w-full mt-6">
|
||||
<AttachmentStyleBoxEditor
|
||||
focusIndex={30}
|
||||
{object}
|
||||
key={{ key: 'description', attr: descriptionKey }}
|
||||
bind:this={descriptionBox}
|
||||
placeholder={tracker.string.IssueDescriptionPlaceholder}
|
||||
updateBacklinks={(doc, description) => {
|
||||
updateBacklinks(client, doc._id, doc._class, doc._id, description)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import tracker from '../../plugin'
|
||||
import MilestoneStatusSelector from './MilestoneStatusSelector.svelte'
|
||||
import { createBacklinks } from '@hcengineering/chunter-resources'
|
||||
|
||||
export let space: Ref<Project>
|
||||
const dispatch = createEventDispatcher()
|
||||
@@ -37,7 +38,9 @@
|
||||
}
|
||||
|
||||
async function onSave () {
|
||||
await client.createDoc(tracker.class.Milestone, space, object)
|
||||
const _id = await client.createDoc(tracker.class.Milestone, space, object)
|
||||
// Create an backlink to document
|
||||
await createBacklinks(client, _id, tracker.class.Milestone, _id, object.description ?? '')
|
||||
}
|
||||
|
||||
const handleComponentStatusChanged = (newMilestoneStatus: MilestoneStatus | undefined) => {
|
||||
@@ -71,6 +74,7 @@
|
||||
bind:content={object.description}
|
||||
placeholder={tracker.string.ComponentDescriptionPlaceholder}
|
||||
emphasized
|
||||
showButtons={false}
|
||||
/>
|
||||
<svelte:fragment slot="pool">
|
||||
<MilestoneStatusSelector
|
||||
|
||||
@@ -13,23 +13,21 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { AttachmentDocList } from '@hcengineering/attachment-resources'
|
||||
import { Class, Data, Doc, Ref, WithLookup } from '@hcengineering/core'
|
||||
import { AttachmentStyleBoxEditor } from '@hcengineering/attachment-resources'
|
||||
import { Class, Doc, Ref, WithLookup } from '@hcengineering/core'
|
||||
import notification from '@hcengineering/notification'
|
||||
import { Panel } from '@hcengineering/panel'
|
||||
import { getResource } from '@hcengineering/platform'
|
||||
import presentation, { MessageViewer, createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import setting, { settingId } from '@hcengineering/setting'
|
||||
import tags from '@hcengineering/tags'
|
||||
import type { IssueTemplate, IssueTemplateChild, Project } from '@hcengineering/tracker'
|
||||
import {
|
||||
Button,
|
||||
EditBox,
|
||||
IconAttachment,
|
||||
IconEdit,
|
||||
Icon,
|
||||
IconMoreH,
|
||||
Label,
|
||||
Scroller,
|
||||
getCurrentResolvedLocation,
|
||||
navigate,
|
||||
showPopup
|
||||
@@ -38,12 +36,13 @@
|
||||
import { createEventDispatcher, onDestroy, onMount } from 'svelte'
|
||||
import tracker from '../../plugin'
|
||||
|
||||
import { StyledTextBox } from '@hcengineering/text-editor'
|
||||
import { updateBacklinks } from '@hcengineering/chunter-resources'
|
||||
import SubIssueTemplates from './IssueTemplateChilds.svelte'
|
||||
import TemplateControlPanel from './TemplateControlPanel.svelte'
|
||||
|
||||
export let _id: Ref<IssueTemplate>
|
||||
export let _class: Ref<Class<IssueTemplate>>
|
||||
export let embedded = false
|
||||
|
||||
let lastId: Ref<Doc> = _id
|
||||
const query = createQuery()
|
||||
@@ -55,8 +54,8 @@
|
||||
let title = ''
|
||||
let description = ''
|
||||
let innerWidth: number
|
||||
let isEditing = false
|
||||
let descriptionBox: StyledTextBox
|
||||
|
||||
let descriptionBox: AttachmentStyleBoxEditor
|
||||
|
||||
const notificationClient = getResource(notification.function.GetNotificationClient).then((res) => res())
|
||||
|
||||
@@ -88,48 +87,19 @@
|
||||
)
|
||||
|
||||
$: canSave = title.trim().length > 0
|
||||
$: isDescriptionEmpty = !new DOMParser().parseFromString(description, 'text/html').documentElement.innerText?.trim()
|
||||
|
||||
function edit (ev: MouseEvent) {
|
||||
ev.preventDefault()
|
||||
|
||||
isEditing = true
|
||||
}
|
||||
|
||||
function cancelEditing (ev: MouseEvent) {
|
||||
ev.preventDefault()
|
||||
|
||||
isEditing = false
|
||||
|
||||
if (template) {
|
||||
title = template.title
|
||||
description = template.description
|
||||
}
|
||||
}
|
||||
|
||||
async function save (ev: MouseEvent) {
|
||||
ev.preventDefault()
|
||||
let saved = false
|
||||
|
||||
async function save () {
|
||||
if (!template || !canSave) {
|
||||
return
|
||||
}
|
||||
|
||||
const updates: Partial<Data<IssueTemplate>> = {}
|
||||
const trimmedTitle = title.trim()
|
||||
|
||||
if (trimmedTitle.length > 0 && trimmedTitle !== template.title) {
|
||||
updates.title = trimmedTitle
|
||||
await client.update(template, { title: trimmedTitle })
|
||||
}
|
||||
|
||||
if (description !== template.description) {
|
||||
updates.description = description
|
||||
}
|
||||
|
||||
if (Object.keys(updates).length > 0) {
|
||||
await client.update(template, updates)
|
||||
}
|
||||
await descriptionBox.createAttachments()
|
||||
isEditing = false
|
||||
}
|
||||
|
||||
function showMenu (ev?: Event): void {
|
||||
@@ -170,106 +140,72 @@
|
||||
children: evt.detail
|
||||
})
|
||||
}
|
||||
$: descriptionKey = client.getHierarchy().getAttribute(tracker.class.IssueTemplate, 'description')
|
||||
</script>
|
||||
|
||||
{#if template !== undefined}
|
||||
<Panel
|
||||
object={template}
|
||||
isHeader
|
||||
isHeader={false}
|
||||
isAside={true}
|
||||
isSub={false}
|
||||
withoutActivity={isEditing}
|
||||
withoutActivity={false}
|
||||
{embedded}
|
||||
bind:innerWidth
|
||||
on:open
|
||||
on:close={() => dispatch('close')}
|
||||
>
|
||||
<svelte:fragment slot="navigator">
|
||||
<UpDownNavigator element={template} />
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="header">
|
||||
<span class="fs-title">
|
||||
{#if !embedded}
|
||||
<UpDownNavigator element={template} />
|
||||
{/if}
|
||||
|
||||
<div class="ml-2">
|
||||
<Icon icon={tracker.icon.IssueTemplates} size={'small'} />
|
||||
</div>
|
||||
<span class="fs-title flex-row-center">
|
||||
{template.title}
|
||||
</span>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="tools">
|
||||
{#if isEditing}
|
||||
<Button kind={'transparent'} label={presentation.string.Cancel} on:click={cancelEditing} />
|
||||
<Button disabled={!canSave} label={presentation.string.Save} on:click={save} />
|
||||
{:else}
|
||||
<Button icon={IconEdit} kind={'transparent'} size={'medium'} on:click={edit} />
|
||||
<Button icon={IconMoreH} kind={'transparent'} size={'medium'} on:click={showMenu} />
|
||||
|
||||
<EditBox bind:value={title} placeholder={tracker.string.IssueTitlePlaceholder} kind="large-style" on:blur={save} />
|
||||
<div class="w-full mt-6">
|
||||
<AttachmentStyleBoxEditor
|
||||
focusIndex={30}
|
||||
object={template}
|
||||
key={{ key: 'description', attr: descriptionKey }}
|
||||
bind:this={descriptionBox}
|
||||
placeholder={tracker.string.IssueDescriptionPlaceholder}
|
||||
on:saved={(evt) => {
|
||||
saved = evt.detail
|
||||
}}
|
||||
updateBacklinks={(doc, description) => {
|
||||
updateBacklinks(client, doc._id, doc._class, doc._id, description)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
{#key template._id && currentProject !== undefined}
|
||||
{#if currentProject !== undefined}
|
||||
<SubIssueTemplates
|
||||
maxHeight="limited"
|
||||
project={template.space}
|
||||
bind:children={template.children}
|
||||
on:create-issue={createIssue}
|
||||
on:update-issue={updateIssue}
|
||||
on:update-issues={updateIssues}
|
||||
/>
|
||||
{/if}
|
||||
{/key}
|
||||
</div>
|
||||
|
||||
<svelte:fragment slot="pre-utils">
|
||||
{#if saved}
|
||||
<Label label={tracker.string.Saved} />
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
|
||||
{#if isEditing}
|
||||
<Scroller>
|
||||
<div class="popupPanel-body__main-content py-10 clear-mins content">
|
||||
<EditBox
|
||||
bind:value={title}
|
||||
maxWidth="53.75rem"
|
||||
placeholder={tracker.string.IssueTitlePlaceholder}
|
||||
kind="large-style"
|
||||
/>
|
||||
<div class="flex-between mt-6">
|
||||
<div class="flex-grow">
|
||||
<StyledTextBox
|
||||
bind:this={descriptionBox}
|
||||
alwaysEdit
|
||||
showButtons
|
||||
maxHeight={'card'}
|
||||
bind:content={description}
|
||||
placeholder={tracker.string.IssueDescriptionPlaceholder}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="tool"
|
||||
on:click={() => {
|
||||
descriptionBox.attach()
|
||||
}}
|
||||
>
|
||||
<IconAttachment size={'large'} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Scroller>
|
||||
{:else}
|
||||
<span class="title select-text">{title}</span>
|
||||
<div class="mt-6 description-preview select-text">
|
||||
{#if isDescriptionEmpty}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="placeholder" on:click={edit}>
|
||||
<Label label={tracker.string.IssueDescriptionPlaceholder} />
|
||||
</div>
|
||||
{:else}
|
||||
<MessageViewer message={description} />
|
||||
{/if}
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
{#key template._id && currentProject !== undefined}
|
||||
{#if currentProject !== undefined}
|
||||
<SubIssueTemplates
|
||||
maxHeight="limited"
|
||||
project={template.space}
|
||||
bind:children={template.children}
|
||||
on:create-issue={createIssue}
|
||||
on:update-issue={updateIssue}
|
||||
on:update-issues={updateIssues}
|
||||
/>
|
||||
{/if}
|
||||
{/key}
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
<AttachmentDocList value={template} />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<span slot="actions-label"> ID </span>
|
||||
<svelte:fragment slot="actions">
|
||||
<div class="flex-grow" />
|
||||
<!-- {#if issueId}
|
||||
<CopyToClipboard issueUrl={generateIssueShortLink(issueId)} {issueId} />
|
||||
{/if} -->
|
||||
<svelte:fragment slot="utils">
|
||||
<Button icon={IconMoreH} kind={'transparent'} size={'medium'} on:click={showMenu} />
|
||||
<Button
|
||||
icon={setting.icon.Setting}
|
||||
kind={'transparent'}
|
||||
|
||||
Reference in New Issue
Block a user