2022-10-31 19:08:57 +00:00
|
|
|
<script lang="ts">
|
2023-08-02 04:42:43 +00:00
|
|
|
import { getMetadata } from '@hcengineering/platform'
|
2023-09-04 17:06:34 +00:00
|
|
|
import presentation, { copyTextToClipboard, createQuery } from '@hcengineering/presentation'
|
2023-01-18 05:14:59 +00:00
|
|
|
import { Issue, IssueStatus } from '@hcengineering/tracker'
|
2022-10-31 19:08:57 +00:00
|
|
|
import {
|
2023-01-18 05:14:59 +00:00
|
|
|
AnySvelteComponent,
|
2022-10-31 19:08:57 +00:00
|
|
|
Button,
|
|
|
|
Icon,
|
2023-01-18 05:14:59 +00:00
|
|
|
IconCheckCircle,
|
2022-10-31 19:08:57 +00:00
|
|
|
IconClose,
|
|
|
|
IconInfo,
|
2023-01-18 05:14:59 +00:00
|
|
|
Notification,
|
|
|
|
NotificationSeverity,
|
2023-04-11 10:05:22 +00:00
|
|
|
navigate,
|
|
|
|
parseLocation
|
2022-10-31 19:08:57 +00:00
|
|
|
} from '@hcengineering/ui'
|
2023-09-04 17:06:34 +00:00
|
|
|
import view from '@hcengineering/view'
|
2023-01-18 05:14:59 +00:00
|
|
|
import { fade } from 'svelte/transition'
|
2022-10-31 19:08:57 +00:00
|
|
|
|
2023-09-04 17:06:34 +00:00
|
|
|
import { statusStore } from '@hcengineering/view-resources'
|
2022-10-31 19:08:57 +00:00
|
|
|
import tracker from '../../plugin'
|
2023-01-18 05:14:59 +00:00
|
|
|
import IssuePresenter from './IssuePresenter.svelte'
|
|
|
|
import IssueStatusIcon from './IssueStatusIcon.svelte'
|
2022-10-31 19:08:57 +00:00
|
|
|
|
2022-11-24 17:29:37 +00:00
|
|
|
export let notification: Notification
|
2022-10-31 19:08:57 +00:00
|
|
|
export let onRemove: () => void
|
|
|
|
|
|
|
|
const issueQuery = createQuery()
|
|
|
|
|
|
|
|
let issue: Issue | undefined
|
|
|
|
let status: IssueStatus | undefined
|
|
|
|
|
|
|
|
const { title, subTitle, severity, params } = notification
|
|
|
|
|
|
|
|
$: issueQuery.query(
|
|
|
|
tracker.class.Issue,
|
2023-01-18 05:14:59 +00:00
|
|
|
{ _id: params?.issueId },
|
2022-10-31 19:08:57 +00:00
|
|
|
(res) => {
|
|
|
|
issue = res[0]
|
|
|
|
},
|
|
|
|
{ limit: 1 }
|
|
|
|
)
|
|
|
|
|
|
|
|
$: if (issue?.status !== undefined) {
|
2023-09-04 17:06:34 +00:00
|
|
|
status = $statusStore.get(issue.status)
|
2022-10-31 19:08:57 +00:00
|
|
|
}
|
|
|
|
|
2023-01-18 05:14:59 +00:00
|
|
|
const getIcon = (): AnySvelteComponent | undefined => {
|
2022-10-31 19:08:57 +00:00
|
|
|
switch (severity) {
|
|
|
|
case NotificationSeverity.Success:
|
|
|
|
return IconCheckCircle
|
|
|
|
case NotificationSeverity.Error:
|
|
|
|
case NotificationSeverity.Info:
|
|
|
|
case NotificationSeverity.Warning:
|
|
|
|
return IconInfo
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const getIconColor = () => {
|
|
|
|
switch (severity) {
|
|
|
|
case NotificationSeverity.Success:
|
|
|
|
return '#34db80'
|
|
|
|
case NotificationSeverity.Error:
|
|
|
|
return '#eb5757'
|
|
|
|
case NotificationSeverity.Info:
|
|
|
|
return '#93caf3'
|
|
|
|
case NotificationSeverity.Warning:
|
|
|
|
return '#f2994a'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const handleIssueOpened = () => {
|
2023-04-11 10:05:22 +00:00
|
|
|
if (params?.issueUrl) {
|
|
|
|
const url = new URL(params?.issueUrl)
|
2023-08-02 04:42:43 +00:00
|
|
|
const frontUrl = getMetadata(presentation.metadata.FrontUrl) ?? window.location.origin
|
2023-04-11 10:05:22 +00:00
|
|
|
|
2023-08-02 04:42:43 +00:00
|
|
|
if (url.origin === frontUrl) {
|
2023-04-11 10:05:22 +00:00
|
|
|
navigate(parseLocation(url))
|
|
|
|
}
|
2022-10-31 19:08:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
onRemove()
|
|
|
|
}
|
2022-12-16 07:10:52 +00:00
|
|
|
const handleCopyUrl = () => {
|
|
|
|
if (issue) {
|
|
|
|
copyTextToClipboard(params?.issueUrl)
|
|
|
|
}
|
|
|
|
}
|
2023-01-18 05:14:59 +00:00
|
|
|
$: icon = getIcon()
|
2022-10-31 19:08:57 +00:00
|
|
|
</script>
|
|
|
|
|
2023-05-01 17:27:14 +00:00
|
|
|
<div class="notify-container" in:fade out:fade>
|
|
|
|
<div class="flex-between">
|
|
|
|
<div class="flex-row-center">
|
|
|
|
{#if icon}
|
|
|
|
<div class="mr-2"><Icon {icon} size="medium" fill={getIconColor()} /></div>
|
|
|
|
{/if}
|
|
|
|
<span class="overflow-label fs-bold caption-color">{title}</span>
|
2022-10-31 19:08:57 +00:00
|
|
|
</div>
|
2023-07-06 07:01:27 +00:00
|
|
|
<Button icon={IconClose} kind="ghost" size="small" on:click={onRemove} />
|
2022-10-31 19:08:57 +00:00
|
|
|
</div>
|
|
|
|
|
2023-05-01 17:27:14 +00:00
|
|
|
<div class="content flex-row-center flex-wrap gap-2 reverse">
|
2023-09-04 17:06:34 +00:00
|
|
|
{#if status && issue}
|
|
|
|
<IssueStatusIcon value={status} space={issue.space} size="small" />
|
2023-05-01 17:27:14 +00:00
|
|
|
{/if}
|
|
|
|
{#if issue}
|
|
|
|
<IssuePresenter value={issue} />
|
|
|
|
{/if}
|
|
|
|
<span class="overflow-label">
|
|
|
|
{subTitle}
|
|
|
|
</span>
|
|
|
|
<span class="content-dark-color">
|
|
|
|
{params?.subTitlePostfix}
|
|
|
|
</span>
|
|
|
|
</div>
|
2023-05-10 11:40:50 +00:00
|
|
|
<div class="flex-between gap-2">
|
2023-05-01 17:27:14 +00:00
|
|
|
<Button label={tracker.string.ViewIssue} on:click={handleIssueOpened} />
|
2023-05-19 02:13:35 +00:00
|
|
|
<Button icon={view.icon.CopyLink} label={tracker.string.CopyIssueUrl} on:click={handleCopyUrl} />
|
2022-10-31 19:08:57 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<style lang="scss">
|
2023-05-01 17:27:14 +00:00
|
|
|
.notify-container {
|
2022-10-31 19:08:57 +00:00
|
|
|
overflow: hidden;
|
|
|
|
display: flex;
|
2023-05-01 17:27:14 +00:00
|
|
|
flex-direction: column;
|
|
|
|
margin: 0.75rem;
|
|
|
|
padding: 0.5rem;
|
|
|
|
min-width: 25rem;
|
2023-05-10 15:45:54 +00:00
|
|
|
max-width: 35rem;
|
2023-05-01 17:27:14 +00:00
|
|
|
min-height: 7rem;
|
|
|
|
color: var(--theme-caption-color);
|
|
|
|
background-color: var(--theme-popup-color);
|
|
|
|
border: 1px solid var(--theme-popup-divider);
|
|
|
|
border-radius: 0.5rem;
|
|
|
|
box-shadow: var(--theme-popup-shadow);
|
|
|
|
|
|
|
|
.content {
|
|
|
|
flex-grow: 1;
|
|
|
|
margin: 1rem 0 1.25rem;
|
|
|
|
padding: 0 1rem;
|
|
|
|
// border: 1px solid var(--theme-divider-color);
|
|
|
|
border-radius: 0.5rem;
|
|
|
|
}
|
2022-10-31 19:08:57 +00:00
|
|
|
}
|
|
|
|
</style>
|