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

TSK-212: add notification on issue created #2325

Merged
merged 8 commits into from
Oct 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 12 additions & 0 deletions packages/ui/src/components/icons/CheckCircle.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script lang="ts">
export let size: 'small' | 'medium' | 'large'
export let fill: string = 'currentColor'
</script>

<svg class="svg-{size}" viewBox="0 0 16 16" {fill} xmlns="http://www.w3.org/2000/svg">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M8 15C11.866 15 15 11.866 15 8C15 4.13401 11.866 1 8 1C4.13401 1 1 4.13401 1 8C1 11.866 4.13401 15 8 15ZM11.7836 6.42901C12.0858 6.08709 12.0695 5.55006 11.7472 5.22952C11.4248 4.90897 10.9186 4.9263 10.6164 5.26821L7.14921 9.19122L5.3315 7.4773C5.00127 7.16593 4.49561 7.19748 4.20208 7.54777C3.90855 7.89806 3.93829 8.43445 4.26852 8.74581L6.28032 10.6427C6.82041 11.152 7.64463 11.1122 8.13886 10.553L11.7836 6.42901Z"
/>
</svg>
8 changes: 4 additions & 4 deletions packages/ui/src/components/icons/Info.svelte
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<!--
// Copyright © 2020 Anticrm Platform Contributors.
//
//
// 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">
export let size: 'tiny' | 'small' | 'medium' | 'large'
const fill: string = 'currentColor'
export let fill: string = 'currentColor'
</script>

<svg class="svg-{size}" {fill} viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
Expand Down
26 changes: 26 additions & 0 deletions packages/ui/src/components/notifications/Notification.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script lang="ts">
import { onDestroy } from 'svelte'

import { Notification } from './Notification'
import store from './store'

export let notification: Notification

const { id, closeTimeout } = notification

const removeNotificationHandler = () => store.removeNotification(id)

let timeout: number | null = null

if (closeTimeout) {
timeout = setTimeout(removeNotificationHandler, closeTimeout)
}

onDestroy(() => {
if (closeTimeout && timeout) {
clearTimeout(timeout)
}
})
</script>

<svelte:component this={notification.component} {notification} onRemove={removeNotificationHandler} />
15 changes: 15 additions & 0 deletions packages/ui/src/components/notifications/Notification.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { NotificationPosition } from './NotificationPosition'
import { NotificationSeverity } from './NotificationSeverity'
import { AnyComponent } from '../../types'

export interface Notification {
id: string
title: string
component: AnyComponent
subTitle?: string
subTitlePostfix?: string
position: NotificationPosition
severity?: NotificationSeverity
params?: { [key: string]: any }
closeTimeout?: number
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export enum NotificationPosition {
BottomLeft,
BottomRight,
TopLeft,
TopRight
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export enum NotificationSeverity {
Info,
Success,
Warning,
Error
}
51 changes: 51 additions & 0 deletions packages/ui/src/components/notifications/Notifications.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<script lang="ts">
import Notification from './Notification.svelte'
import { NotificationPosition } from './NotificationPosition'
import store from './store'

const positionByClassName = {
'bottom-left': NotificationPosition.BottomLeft,
'bottom-right': NotificationPosition.BottomRight,
'top-left': NotificationPosition.TopLeft,
'top-right': NotificationPosition.TopRight
}
</script>

<slot />
<div class="notifications">
{#each Object.entries(positionByClassName) as [className, position]}
<div class={className} style:z-index={9999}>
{#each $store as notification (notification.id)}
{#if notification.position === position}
<Notification {notification} />
{/if}
{/each}
</div>
{/each}
</div>

<style lang="scss">
.top-left {
position: fixed;
top: 0;
left: 0;
}

.top-right {
position: fixed;
top: 0;
right: 0;
}

.bottom-left {
position: fixed;
bottom: 0;
left: 0;
}

.bottom-right {
position: fixed;
bottom: 0;
right: 0;
}
</style>
34 changes: 34 additions & 0 deletions packages/ui/src/components/notifications/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Writable } from 'svelte/store'
import { generateId } from '@hcengineering/core'

import { Notification } from './Notification'
import { NotificationPosition } from './NotificationPosition'
import { NotificationSeverity } from './NotificationSeverity'

export const addNotification = (notification: Notification, store: Writable<Notification[]>): void => {
if (notification === undefined || notification === null) {
return
}

const { update } = store

const newNotification = {
severity: NotificationSeverity.Info,
...notification,
id: generateId()
}

update((notifications: Notification[]) =>
[NotificationPosition.TopRight, NotificationPosition.TopLeft].includes(newNotification.position)
? [newNotification, ...notifications]
: [...notifications, newNotification]
)
}

export const removeNotification = (notificationId: string, { update }: Writable<Notification[]>): void => {
if (notificationId === '') {
return
}

update((notifications) => notifications.filter(({ id }) => id !== notificationId))
}
12 changes: 12 additions & 0 deletions packages/ui/src/components/notifications/store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { writable } from 'svelte/store'

import { Notification } from './Notification'
import { addNotification, removeNotification } from './actions'

const store = writable<Notification[]>([])

export default {
subscribe: store.subscribe,
addNotification: (notification: Notification) => addNotification(notification, store),
removeNotification: (notificationId: string) => removeNotification(notificationId, store)
}
6 changes: 6 additions & 0 deletions packages/ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export { default as IconDetailsFilled } from './components/icons/DetailsFilled.s
export { default as IconScale } from './components/icons/Scale.svelte'
export { default as IconScaleFull } from './components/icons/ScaleFull.svelte'
export { default as IconOpen } from './components/icons/Open.svelte'
export { default as IconCheckCircle } from './components/icons/CheckCircle.svelte'

export { default as PanelInstance } from './components/PanelInstance.svelte'
export { default as Panel } from './components/Panel.svelte'
Expand All @@ -148,6 +149,11 @@ export { default as ListView } from './components/ListView.svelte'
export { default as ToggleButton } from './components/ToggleButton.svelte'
export { default as ExpandCollapse } from './components/ExpandCollapse.svelte'
export { default as BarDashboard } from './components/BarDashboard.svelte'
export { default as Notifications } from './components/notifications/Notifications.svelte'
export { default as notificationsStore } from './components/notifications/store'
export { NotificationPosition } from './components/notifications/NotificationPosition'
export { NotificationSeverity } from './components/notifications/NotificationSeverity'
export { Notification } from './components/notifications/Notification'

export * from './types'
export * from './location'
Expand Down
2 changes: 2 additions & 0 deletions plugins/tracker-assets/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
"Members": "Members",
"Inbox": "Inbox",
"MyIssues": "My issues",
"ViewIssue": "View issue",
"IssueCreated": "Issue Created",
"Issues": "Issues",
"Views": "Views",
"Active": "Active",
Expand Down
4 changes: 3 additions & 1 deletion plugins/tracker-assets/lang/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"Open": "Открыть",
"Members": "Участиники",
"Inbox": "Входящие",
"ViewIssue": "Открыть задачу",
"IssueCreated": "Задача создана",
"MyIssues": "Мои задачи",
"Issues": "Задачи",
"Views": "Отображения",
Expand Down Expand Up @@ -143,7 +145,7 @@
"FilterIsEither": "является ли любой из",
"FilterStatesCount": "{value, plural, =1 {1 state} other {# states}}",
"Assigned": "Назначенные",
"Created": "Созданные",
"Created": "{value, plural, =1 {Создана} other {Созданные}}",
"Subscribed": "Отслеживаемые",

"Relations": "Зависимости",
Expand Down
30 changes: 25 additions & 5 deletions plugins/tracker-resources/src/components/CreateIssue.svelte
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<!--
// Copyright © 2022 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.
-->
Expand All @@ -17,7 +17,7 @@
import chunter from '@hcengineering/chunter'
import { Employee } from '@hcengineering/contact'
import core, { Account, AttachedData, Doc, generateId, Ref, SortingOrder, WithLookup } from '@hcengineering/core'
import { getResource } from '@hcengineering/platform'
import { getResource, translate } from '@hcengineering/platform'
import { Card, createQuery, getClient, KeyedAttribute, MessageBox, SpaceSelector } from '@hcengineering/presentation'
import tags, { TagElement, TagReference } from '@hcengineering/tags'
import {
Expand All @@ -42,7 +42,11 @@
Label,
Menu,
showPopup,
Spinner
Spinner,
NotificationPosition,
NotificationSeverity,
Notification,
notificationsStore
} from '@hcengineering/ui'
import view from '@hcengineering/view'
import { ObjectBox } from '@hcengineering/view-resources'
Expand All @@ -59,6 +63,7 @@
import SetParentIssueActionPopup from './SetParentIssueActionPopup.svelte'
import SprintSelector from './sprints/SprintSelector.svelte'
import IssueTemplateChilds from './templates/IssueTemplateChilds.svelte'
import IssueNotification from './issues/IssueNotification.svelte'

export let space: Ref<Team>
export let status: Ref<IssueStatus> | undefined = undefined
Expand Down Expand Up @@ -394,6 +399,21 @@
}
}

const notification: Notification = {
title: tracker.string.IssueCreated,
subTitle: getTitle(object.title),
severity: NotificationSeverity.Success,
position: NotificationPosition.BottomRight,
component: IssueNotification,
closeTimeout: 10000,
params: {
issueId: objectId,
subTitlePostfix: (await translate(tracker.string.Created, { value: 1 })).toLowerCase()
}
}

notificationsStore.addNotification(notification)

objectId = generateId()
resetObject()
}
Expand Down
5 changes: 3 additions & 2 deletions plugins/tracker-resources/src/components/ModeSelector.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { Button } from '@hcengineering/ui'

export let mode: string
export let config: [string, IntlString][]
export let config: [string, IntlString, object][]
export let onChange: (_mode: string) => void

function getButtonShape (i: number) {
Expand All @@ -21,10 +21,11 @@

<div class="itemsContainer">
<div class="flex-center">
{#each config as [_mode, label], i}
{#each config as [_mode, label, params], i}
<div class="buttonWrapper">
<Button
{label}
labelParams={params}
size="small"
on:click={() => onChange(_mode)}
selected={_mode === mode}
Expand Down
Loading