Skip to content

Commit 92c8996

Browse files
rodrigoeadannyrb
authored andcommitted
feat: Notification Service (#1011)
* WIP - Notification Service * add snackbar provider into the main App component * feat: Notification Service * revert unmodified file * Update DicomHtmlViewport.js * update css classnames * revert toolbarRow * fix revert toolbarRow * styles adjustments and hide method * remove unecessary default options * minor fixes * fix long truncated messages * move SnackbarContext to ui project, rename, export
1 parent f07dca5 commit 92c8996

8 files changed

Lines changed: 417 additions & 10 deletions

File tree

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
.sb-container {
2+
position: fixed;
3+
width: var(--snackbar-size);
4+
padding: 20px;
5+
z-index: var(--snackbar-zIndex);
6+
box-sizing: border-box;
7+
height: auto;
8+
}
9+
10+
.sb-topLeft {
11+
top: 0;
12+
bottom: auto;
13+
left: 0;
14+
right: auto;
15+
}
16+
17+
.sb-topCenter {
18+
left: 50%;
19+
top: 0;
20+
bottom: auto;
21+
transform: translateX(-50%);
22+
}
23+
24+
.sb-topRight {
25+
top: 0;
26+
bottom: auto;
27+
left: auto;
28+
right: 0;
29+
}
30+
31+
.sb-bottomLeft {
32+
top: auto;
33+
bottom: 0px;
34+
left: 0px;
35+
right: auto;
36+
}
37+
38+
.sb-bottomCenter {
39+
left: 50%;
40+
bottom: 0;
41+
top: auto;
42+
transform: translateX(-50%);
43+
}
44+
45+
.sb-bottomRight {
46+
top: auto;
47+
bottom: 0px;
48+
left: auto;
49+
right: 0px;
50+
margin: 10px 0 0;
51+
}
52+
53+
.sb-topLeft .sb-item,
54+
.sb-topCenter .sb-item,
55+
.sb-topRight .sb-item {
56+
margin: 10px 0 0;
57+
}
58+
59+
.sb-bottomLeft .sb-item,
60+
.sb-bottomCenter .sb-item,
61+
.sb-bottomRight .sb-item {
62+
margin: 0 0 10px;
63+
}
64+
65+
.sb-closeBtn {
66+
height: 20px;
67+
opacity: 1;
68+
overflow: hidden;
69+
padding: 2px;
70+
text-align: center;
71+
text-shadow: none;
72+
width: 20px;
73+
cursor: pointer;
74+
position: absolute;
75+
right: 5px;
76+
top: 5px;
77+
transition: all 0.3s ease;
78+
background: rgba(255, 255, 255, 0.6);
79+
border-radius: 100%;
80+
}
81+
82+
.sb-closeBtn:hover {
83+
background: #fff;
84+
}
85+
86+
.sb-closeIcon {
87+
display: block;
88+
font-size: 0;
89+
height: 100%;
90+
line-height: 0;
91+
overflow: hidden;
92+
position: relative;
93+
width: 100%;
94+
}
95+
96+
.sb-closeIcon:after,
97+
.sb-closeIcon:before {
98+
content: ' ';
99+
display: block;
100+
height: 2px;
101+
transition: all 0.3s ease;
102+
width: 12px;
103+
background-color: #222;
104+
opacity: 1;
105+
position: absolute;
106+
}
107+
108+
.sb-closeIcon:before {
109+
left: 4px;
110+
top: 3px;
111+
112+
transform: rotate(45deg);
113+
transform-origin: 0px 50%;
114+
}
115+
116+
.sb-closeIcon:after {
117+
right: 3px;
118+
top: 5px;
119+
transform: rotate(-45deg);
120+
transform-origin: calc(100% - 3px) 50%;
121+
}
122+
123+
.sb-title {
124+
font-size: 16px;
125+
font-weight: bold;
126+
}
127+
128+
.sb-message {
129+
font-size: 14px;
130+
word-break: break-all;
131+
}
132+
133+
.sb-item {
134+
position: relative;
135+
transition: height 300ms ease;
136+
animation: fadein 1s;
137+
padding: 20px;
138+
color: white;
139+
overflow: hidden;
140+
border-radius: 4px;
141+
box-shadow: 0 6px 10px 0 rgba(0, 0, 0, 0.2), 0 1px 18px 0 rgba(0, 0, 0, 0.12),
142+
0 3px 5px -1px rgba(0, 0, 0, 0.14);
143+
}
144+
145+
.sb-item a {
146+
color: white;
147+
text-decoration: underline;
148+
}
149+
150+
.sb-container .sb-hidden {
151+
padding-top: 0;
152+
padding-bottom: 0;
153+
margin-bottom: 0;
154+
height: 0;
155+
opacity: 0;
156+
transition: all 300ms ease;
157+
}
158+
159+
.sb-success {
160+
background-color: var(--snackbar-success);
161+
}
162+
163+
.sb-error {
164+
background-color: var(--snackbar-error);
165+
}
166+
167+
.sb-warning {
168+
background-color: var(--snackbar-warning);
169+
}
170+
171+
.sb-info {
172+
background-color: var(--snackbar-info);
173+
}
174+
175+
@keyframes fadein {
176+
from {
177+
opacity: 0;
178+
top: 30px;
179+
}
180+
to {
181+
opacity: 1;
182+
top: 0;
183+
}
184+
}
185+
186+
/* Internet Explorer */
187+
@-ms-keyframes fadein {
188+
from {
189+
opacity: 0;
190+
top: 30px;
191+
}
192+
to {
193+
opacity: 1;
194+
top: 0;
195+
}
196+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import React from 'react';
2+
import SnackbarItem from './SnackbarItem';
3+
import './Snackbar.css';
4+
import { useSnackbarContext } from '../../utils/SnackbarProvider';
5+
6+
const SnackbarContainer = () => {
7+
const { snackbarItems, hide } = useSnackbarContext();
8+
9+
const renderItem = item => {
10+
return <SnackbarItem key={item.itemId} options={item} onClose={hide} />;
11+
};
12+
13+
if (!snackbarItems) {
14+
return null;
15+
}
16+
17+
const renderItems = () => {
18+
const items = {
19+
topLeft: [],
20+
topCenter: [],
21+
topRight: [],
22+
bottomLeft: [],
23+
bottomCenter: [],
24+
bottomRight: [],
25+
};
26+
27+
snackbarItems.map(item => {
28+
items[item.position].push(item);
29+
});
30+
31+
return (
32+
<div>
33+
{Object.keys(items).map(pos => {
34+
if (!items[pos].length) {
35+
return null;
36+
}
37+
38+
return (
39+
<div key={pos} className={`sb-container sb-${pos}`}>
40+
{items[pos].map(item => (
41+
<div key={item.id}>{renderItem(item)}</div>
42+
))}
43+
</div>
44+
);
45+
})}
46+
</div>
47+
);
48+
};
49+
50+
return <>{renderItems()}</>;
51+
};
52+
53+
export default SnackbarContainer;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import React, { useState, useEffect } from 'react';
2+
3+
const SnackbarItem = ({ options, onClose }) => {
4+
const handleClose = () => {
5+
onClose(options.id);
6+
};
7+
8+
useEffect(() => {
9+
if (options.autoClose) {
10+
setTimeout(() => {
11+
handleClose();
12+
}, options.duration);
13+
}
14+
}, []);
15+
16+
return (
17+
<div
18+
className={`${options.visible ? '' : 'sb-hidden'} sb-${
19+
options.type
20+
} sb-item`}
21+
>
22+
<span className="sb-closeBtn" onClick={handleClose}>
23+
<span className="sb-closeIcon">x</span>
24+
</span>
25+
{options.title && <div className="sb-title">{options.title}</div>}
26+
{options.message && <div className="sb-message">{options.message}</div>}
27+
</div>
28+
);
29+
};
30+
31+
export default SnackbarItem;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default {
2+
INFO: 'info',
3+
WARNING: 'warning',
4+
SUCCESS: 'success',
5+
ERROR: 'error',
6+
};

platform/ui/src/index.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ import { ScrollableArea } from './ScrollableArea/ScrollableArea.js';
3232
import Toolbar from './viewer/Toolbar.js';
3333
import ToolbarButton from './viewer/ToolbarButton.js';
3434
import ViewerbaseDragDropContext from './utils/viewerbaseDragDropContext.js';
35+
import SnackbarProvider, {
36+
useSnackbarContext,
37+
withSnackbar,
38+
} from './utils/SnackbarProvider';
3539

3640
export {
3741
ICONS,
@@ -68,4 +72,7 @@ export {
6872
UserPreferences,
6973
UserPreferencesModal,
7074
ViewerbaseDragDropContext,
75+
SnackbarProvider,
76+
useSnackbarContext,
77+
withSnackbar,
7178
};

0 commit comments

Comments
 (0)