Skip to content

Commit

Permalink
TSK-212: add notification on issue created (#2325)
Browse files Browse the repository at this point in the history
Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
  • Loading branch information
kristina-fefelova authored Oct 31, 2022
1 parent bfcbb73 commit 15c2aa8
Show file tree
Hide file tree
Showing 19 changed files with 406 additions and 27 deletions.
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

0 comments on commit 15c2aa8

Please sign in to comment.