change(ui) - session list icons

This commit is contained in:
Shekar Siri 2022-08-11 10:50:36 +02:00
parent 762d0fad53
commit ccaf869ce9
6 changed files with 111 additions and 19 deletions

View file

@ -6,6 +6,10 @@ import DashboardSvg from '../../../svg/dashboard-icn.svg';
import LoaderSVG from '../../../svg/openreplay-preloader.svg';
import SignalGreenSvg from '../../../svg/signal-green.svg';
import SignalRedSvg from '../../../svg/signal-red.svg';
import NoBookmarks from '../../../svg/ca-no-bookmarked-session.svg';
import NoLiveSessions from '../../../svg/ca-no-live-sessions.svg';
import NoSessions from '../../../svg/ca-no-sessions.svg';
import NoSessionsInVault from '../../../svg/ca-no-sessions-in-vault.svg';
export enum ICONS {
DASHBOARD_ICON = 'dashboard-icn',
@ -14,7 +18,11 @@ export enum ICONS {
NO_RESULTS = 'no-results',
LOADER = 'openreplay-preloader',
SIGNAL_GREEN = 'signal-green',
SIGNAL_RED = 'signal-red'
SIGNAL_RED = 'signal-red',
NO_BOOKMARKS = 'ca-no-bookmarked-session',
NO_LIVE_SESSIONS = 'ca-no-live-sessions',
NO_SESSIONS = 'ca-no-sessions',
NO_SESSIONS_IN_VAULT = 'ca-no-sessions-in-vault'
}
interface Props {
@ -26,28 +34,32 @@ function AnimatedSVG(props: Props) {
const renderSvg = () => {
switch (name) {
case ICONS.LOADER:
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={LoaderSVG} />
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={LoaderSVG} />;
case ICONS.DASHBOARD_ICON:
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={DashboardSvg} />
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={DashboardSvg} />;
case ICONS.EMPTY_STATE:
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={EmptyStateSvg} />
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={EmptyStateSvg} />;
case ICONS.LOGO_SMALL:
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={LogoSmall} />
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={LogoSmall} />;
case ICONS.NO_RESULTS:
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={NoResultsSVG} />
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={NoResultsSVG} />;
case ICONS.SIGNAL_GREEN:
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={SignalGreenSvg} />
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={SignalGreenSvg} />;
case ICONS.SIGNAL_RED:
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={SignalRedSvg} />
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={SignalRedSvg} />;
case ICONS.NO_BOOKMARKS:
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={NoBookmarks} />;
case ICONS.NO_LIVE_SESSIONS:
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={NoLiveSessions} />;
case ICONS.NO_SESSIONS:
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={NoSessions} />;
case ICONS.NO_SESSIONS_IN_VAULT:
return <object style={{ width: size + 'px' }} type="image/svg+xml" data={NoSessionsInVault} />;
default:
return null;
}
}
return (
<div>
{renderSvg()}
</div>
);
};
return <div>{renderSvg()}</div>;
}
export default AnimatedSVG;
export default AnimatedSVG;

View file

@ -20,17 +20,38 @@ interface Props {
updateCurrentPage: (page: number) => void;
setScrollPosition: (scrollPosition: number) => void;
fetchSessions: () => void;
activeTab: any;
isEnterprise?: boolean;
}
function SessionList(props: Props) {
const { loading, list, currentPage, total, filters, lastPlayedSessionId, metaList } = props;
const { loading, list, currentPage, total, filters, lastPlayedSessionId, metaList, activeTab, isEnterprise = false } = props;
const _filterKeys = filters.map((i: any) => i.key);
const hasUserFilter = _filterKeys.includes(FilterKey.USERID) || _filterKeys.includes(FilterKey.USERANONYMOUSID);
const isBookmark = activeTab.type === 'bookmark';
const isVault = isBookmark && isEnterprise;
const NO_CONTENT = React.useMemo(() => {
if (isBookmark && !isEnterprise) {
return {
icon: ICONS.NO_BOOKMARKS,
message: 'You have no bookmarks',
};
} else if (isVault) {
return {
icon: ICONS.NO_SESSIONS_IN_VAULT,
message: 'You have no sessions in your vault',
};
}
return {
icon: ICONS.NO_SESSIONS,
message: activeTab.type === 'all' ? 'You have no sessions' : 'You have no sessions with ' + activeTab.name,
};
}, [isBookmark, isVault, activeTab]);
useEffect(() => {
const { scrollY } = props;
window.scrollTo(0, scrollY);
if (total === 0) {
props.fetchSessions()
props.fetchSessions();
}
return () => {
@ -51,9 +72,10 @@ function SessionList(props: Props) {
<NoContent
title={
<div className="flex items-center justify-center flex-col">
<AnimatedSVG name={ICONS.NO_RESULTS} size={170} />
<AnimatedSVG name={NO_CONTENT.icon} size={170} />
<div className="mt-2" />
<NoContentMessage />
<div className="text-center text-gray-600">{NO_CONTENT.message}</div>
{/* <NoContentMessage /> */}
</div>
}
subtext={<div>Please try changing your search parameters.</div>}
@ -97,6 +119,8 @@ export default connect(
currentPage: state.getIn(['search', 'currentPage']) || 1,
total: state.getIn(['sessions', 'total']) || 0,
scrollY: state.getIn(['search', 'scrollY']),
activeTab: state.getIn(['search', 'activeTab']),
isEnterprise: state.getIn(['user', 'account', 'edition']) === 'ee',
}),
{ updateCurrentPage, addFilterByKeyAndValue, setScrollPosition, fetchSessions }
)(SessionList);

View file

@ -0,0 +1,14 @@
<svg viewBox="0 0 250 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="250" height="100" rx="13.1579" fill="#3EAAAF" fill-opacity="0.08"/>
<rect opacity="0.6" x="85.8947" y="28.579" width="138.158" height="14.4737" rx="6.57895" fill="#3EAAAF" fill-opacity="0.5"/>
<rect opacity="0.3" x="85.8947" y="54.8948" width="46.0526" height="14.4737" rx="6.57895" fill="#3EAAAF" fill-opacity="0.5"/>
<g clip-path="url(#clip0_2_27)">
<path d="M52.5 58C55.8152 58 58.9946 56.683 61.3388 54.3388C63.683 51.9946 65 48.8152 65 45.5C65 42.1848 63.683 39.0054 61.3388 36.6612C58.9946 34.317 55.8152 33 52.5 33C49.1848 33 46.0054 34.317 43.6612 36.6612C41.317 39.0054 40 42.1848 40 45.5C40 48.8152 41.317 51.9946 43.6612 54.3388C46.0054 56.683 49.1848 58 52.5 58V58ZM50.9375 43.1562C50.9375 44.45 50.2375 45.5 49.375 45.5C48.5125 45.5 47.8125 44.45 47.8125 43.1562C47.8125 41.8625 48.5125 40.8125 49.375 40.8125C50.2375 40.8125 50.9375 41.8625 50.9375 43.1562ZM46.6953 52.4266C46.5159 52.323 46.385 52.1523 46.3313 51.9522C46.2777 51.7521 46.3058 51.5388 46.4094 51.3594C47.0264 50.2901 47.9141 49.4022 48.9833 48.785C50.0526 48.1678 51.2655 47.8432 52.5 47.8438C53.7345 47.8435 54.9473 48.1683 56.0164 48.7854C57.0856 49.4025 57.9734 50.2903 58.5906 51.3594C58.6926 51.5387 58.7195 51.7511 58.6654 51.9502C58.6114 52.1493 58.4808 52.3189 58.3021 52.4221C58.1234 52.5252 57.9112 52.5535 57.7118 52.5008C57.5123 52.4481 57.3418 52.3186 57.2375 52.1406C56.7576 51.3088 56.0671 50.6182 55.2354 50.1381C54.4037 49.6581 53.4603 49.4057 52.5 49.4062C51.5397 49.4057 50.5963 49.6581 49.7646 50.1381C48.9329 50.6182 48.2424 51.3088 47.7625 52.1406C47.6589 52.3201 47.4883 52.451 47.2881 52.5046C47.088 52.5582 46.8747 52.5302 46.6953 52.4266ZM55.625 45.5C54.7625 45.5 54.0625 44.45 54.0625 43.1562C54.0625 41.8625 54.7625 40.8125 55.625 40.8125C56.4875 40.8125 57.1875 41.8625 57.1875 43.1562C57.1875 44.45 56.4875 45.5 55.625 45.5Z" fill="#3EAAAF" fill-opacity="0.5"/>
</g>
<path d="M31.875 28.875C31.875 27.0516 32.5993 25.303 33.8886 24.0136C35.178 22.7243 36.9266 22 38.75 22H66.25C68.0734 22 69.822 22.7243 71.1114 24.0136C72.4007 25.303 73.125 27.0516 73.125 28.875V75.2812C73.1248 75.5921 73.0404 75.8972 72.8805 76.1639C72.7207 76.4305 72.4916 76.6489 72.2175 76.7956C71.9434 76.9424 71.6347 77.012 71.3241 76.9971C71.0136 76.9823 70.7129 76.8835 70.4541 76.7113L52.5 67.0347L34.5459 76.7113C34.2871 76.8835 33.9864 76.9823 33.6759 76.9971C33.3653 77.012 33.0566 76.9424 32.7825 76.7956C32.5084 76.6489 32.2793 76.4305 32.1195 76.1639C31.9596 75.8972 31.8752 75.5921 31.875 75.2812V28.875ZM38.75 25.4375C37.8383 25.4375 36.964 25.7997 36.3193 26.4443C35.6747 27.089 35.3125 27.9633 35.3125 28.875V72.0706L51.5478 63.5387C51.8299 63.351 52.1612 63.2509 52.5 63.2509C52.8388 63.2509 53.1701 63.351 53.4522 63.5387L69.6875 72.0706V28.875C69.6875 27.9633 69.3253 27.089 68.6807 26.4443C68.036 25.7997 67.1617 25.4375 66.25 25.4375H38.75Z" fill="#3EAAAF" fill-opacity="0.5"/>
<defs>
<clipPath id="clip0_2_27">
<rect width="25" height="25" fill="white" transform="translate(40 33)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3 KiB

View file

@ -0,0 +1,15 @@
<svg viewBox="0 0 250 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="250" height="100" rx="13.1579" fill="#3EAAAF" fill-opacity="0.08"/>
<rect opacity="0.6" x="86.8421" y="28.579" width="138.158" height="14.4737" rx="6.57895" fill="#3EAAAF" fill-opacity="0.5"/>
<rect opacity="0.3" x="86.8421" y="54.8948" width="46.0526" height="14.4737" rx="6.57895" fill="#3EAAAF" fill-opacity="0.5"/>
<g clip-path="url(#clip0_2_44)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M71.047 68.047C65.9884 73.1055 59.1276 75.9474 51.9737 75.9474C44.8198 75.9474 37.959 73.1055 32.9004 68.047C27.8419 62.9884 25 56.1276 25 48.9737C25 41.8198 27.8419 34.959 32.9004 29.9004C37.959 24.8419 44.8198 22 51.9737 22C57.1003 22 62.0765 23.4594 66.3467 26.1483C65.4733 27.1904 64.9474 28.5338 64.9474 30C64.9474 33.3137 67.6336 36 70.9474 36C72.4136 36 73.7569 35.4741 74.7991 34.6006C77.4879 38.8709 78.9474 43.847 78.9474 48.9737C78.9474 56.1276 76.1055 62.9884 71.047 68.047ZM45.2303 48.9737C47.0914 48.9737 48.602 46.7079 48.602 43.9161C48.602 41.1243 47.0914 38.8586 45.2303 38.8586C43.3691 38.8586 41.8586 41.1243 41.8586 43.9161C41.8586 46.7079 43.3691 48.9737 45.2303 48.9737ZM38.6623 62.8968C38.7781 63.3287 39.0606 63.6969 39.4478 63.9205C39.835 64.144 40.2951 64.2046 40.727 64.0889C41.1589 63.9732 41.5271 63.6907 41.7507 63.3035C42.7861 61.5086 44.2762 60.0182 46.0709 58.9823C47.8656 57.9465 49.9015 57.4017 51.9737 57.403C54.0458 57.4017 56.0818 57.9465 57.8764 58.9823C59.6711 60.0182 61.1612 61.5086 62.1967 63.3035C62.4219 63.6875 62.7898 63.9669 63.2202 64.0807C63.6506 64.1945 64.1085 64.1334 64.494 63.9108C64.8796 63.6882 65.1614 63.3222 65.278 62.8926C65.3947 62.4629 65.3366 62.0046 65.1166 61.6176C63.7847 59.3106 61.8688 57.395 59.5617 56.0633C57.2546 54.7315 54.6376 54.0307 51.9737 54.0312C49.3097 54.03 46.6924 54.7306 44.3851 56.0624C42.0779 57.3941 40.1622 59.3102 38.8308 61.6176C38.6072 62.0048 38.5466 62.465 38.6623 62.8968ZM55.3454 43.9161C55.3454 46.7079 56.8559 48.9737 58.7171 48.9737C60.5783 48.9737 62.0888 46.7079 62.0888 43.9161C62.0888 41.1243 60.5783 38.8586 58.7171 38.8586C56.8559 38.8586 55.3454 41.1243 55.3454 43.9161Z" fill="#3EAAAF" fill-opacity="0.5"/>
</g>
<circle opacity="0.7" cx="70.9474" cy="30" r="5" fill="#3EAAAF" fill-opacity="0.5"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M145.872 57.1005C145.617 56.9984 145.337 56.9734 145.068 57.0286C144.799 57.0838 144.552 57.2167 144.358 57.4109C144.164 57.6051 144.031 57.852 143.976 58.121C143.921 58.39 143.946 58.6693 144.048 58.9242L149.659 72.9529C149.76 73.204 149.931 73.4207 150.152 73.5769C150.372 73.733 150.634 73.822 150.904 73.8331C151.174 73.8443 151.442 73.777 151.675 73.6395C151.908 73.502 152.096 73.3001 152.217 73.0582L154.153 69.1876L158.387 73.4243C158.65 73.6874 159.007 73.8351 159.379 73.8349C159.751 73.8348 160.108 73.6869 160.371 73.4236C160.634 73.1604 160.782 72.8034 160.782 72.4313C160.781 72.0591 160.633 71.7023 160.37 71.4392L156.135 67.2026L160.007 65.268C160.248 65.1469 160.45 64.9586 160.587 64.7258C160.724 64.4929 160.791 64.2255 160.78 63.9555C160.768 63.6856 160.679 63.4246 160.523 63.204C160.367 62.9834 160.151 62.8126 159.9 62.712L145.872 57.1005Z" fill="#3EAAAF" fill-opacity="0.5"/>
<defs>
<clipPath id="clip0_2_44">
<rect width="53.9474" height="53.9474" fill="white" transform="translate(25 22)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -0,0 +1,14 @@
<svg viewBox="0 0 250 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="250" height="100" rx="13.1579" fill="#3EAAAF" fill-opacity="0.08"/>
<rect opacity="0.6" x="86.8947" y="29.579" width="138.158" height="14.4737" rx="6.57895" fill="#3EAAAF" fill-opacity="0.5"/>
<rect opacity="0.3" x="86.8947" y="55.8948" width="46.0526" height="14.4737" rx="6.57895" fill="#3EAAAF" fill-opacity="0.5"/>
<g clip-path="url(#clip0_2_20)">
<path d="M54 67C58.5087 67 62.8327 65.2089 66.0208 62.0208C69.2089 58.8327 71 54.5087 71 50C71 45.4913 69.2089 41.1673 66.0208 37.9792C62.8327 34.7911 58.5087 33 54 33C49.4913 33 45.1673 34.7911 41.9792 37.9792C38.7911 41.1673 37 45.4913 37 50C37 54.5087 38.7911 58.8327 41.9792 62.0208C45.1673 65.2089 49.4913 67 54 67V67ZM51.875 46.8125C51.875 48.572 50.923 50 49.75 50C48.577 50 47.625 48.572 47.625 46.8125C47.625 45.053 48.577 43.625 49.75 43.625C50.923 43.625 51.875 45.053 51.875 46.8125ZM46.1056 59.4201C45.8616 59.2792 45.6835 59.0472 45.6106 58.775C45.5377 58.5028 45.5759 58.2128 45.7168 57.9688C46.5559 56.5145 47.7632 55.3069 49.2174 54.4676C50.6715 53.6282 52.321 53.1867 54 53.1875C55.6789 53.1872 57.3283 53.6289 58.7823 54.4682C60.2364 55.3075 61.4438 56.5148 62.2832 57.9688C62.4219 58.2127 62.4585 58.5015 62.385 58.7723C62.3115 59.0431 62.1338 59.2738 61.8909 59.414C61.6479 59.5543 61.3593 59.5928 61.088 59.5211C60.8168 59.4494 60.5849 59.2733 60.443 59.0312C59.7904 57.9 58.8513 56.9607 57.7202 56.3079C56.5891 55.655 55.306 55.3117 54 55.3125C52.694 55.3117 51.4109 55.655 50.2798 56.3079C49.1487 56.9607 48.2096 57.9 47.557 59.0312C47.4161 59.2753 47.184 59.4533 46.9118 59.5263C46.6397 59.5992 46.3497 59.561 46.1056 59.4201ZM58.25 50C57.077 50 56.125 48.572 56.125 46.8125C56.125 45.053 57.077 43.625 58.25 43.625C59.423 43.625 60.375 45.053 60.375 46.8125C60.375 48.572 59.423 50 58.25 50Z" fill="#3EAAAF" fill-opacity="0.5"/>
</g>
<path d="M28.375 28.0625C28.375 26.7198 28.9084 25.4322 29.8578 24.4828C30.8072 23.5334 32.0948 23 33.4375 23H73.9375C75.2802 23 76.5678 23.5334 77.5172 24.4828C78.4666 25.4322 79 26.7198 79 28.0625V71.9375C79 73.2802 78.4666 74.5678 77.5172 75.5172C76.5678 76.4666 75.2802 77 73.9375 77H33.4375C32.0948 77 30.8072 76.4666 29.8578 75.5172C28.9084 74.5678 28.375 73.2802 28.375 71.9375V66.875H26.6875C26.2399 66.875 25.8107 66.6972 25.4943 66.3807C25.1778 66.0643 25 65.6351 25 65.1875C25 64.7399 25.1778 64.3107 25.4943 63.9943C25.8107 63.6778 26.2399 63.5 26.6875 63.5H28.375V51.6875H26.6875C26.2399 51.6875 25.8107 51.5097 25.4943 51.1932C25.1778 50.8768 25 50.4476 25 50C25 49.5524 25.1778 49.1232 25.4943 48.8068C25.8107 48.4903 26.2399 48.3125 26.6875 48.3125H28.375V36.5H26.6875C26.2399 36.5 25.8107 36.3222 25.4943 36.0057C25.1778 35.6893 25 35.2601 25 34.8125C25 34.3649 25.1778 33.9357 25.4943 33.6193C25.8107 33.3028 26.2399 33.125 26.6875 33.125H28.375V28.0625ZM33.4375 26.375C32.9899 26.375 32.5607 26.5528 32.2443 26.8693C31.9278 27.1857 31.75 27.6149 31.75 28.0625V71.9375C31.75 72.3851 31.9278 72.8143 32.2443 73.1307C32.5607 73.4472 32.9899 73.625 33.4375 73.625H73.9375C74.3851 73.625 74.8143 73.4472 75.1307 73.1307C75.4472 72.8143 75.625 72.3851 75.625 71.9375V28.0625C75.625 27.6149 75.4472 27.1857 75.1307 26.8693C74.8143 26.5528 74.3851 26.375 73.9375 26.375H33.4375Z" fill="#3EAAAF" fill-opacity="0.5"/>
<defs>
<clipPath id="clip0_2_20">
<rect width="34" height="34" fill="white" transform="translate(37 33)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

@ -0,0 +1,13 @@
<svg viewBox="0 0 250 100" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="250" height="100" rx="13.1579" fill="#3EAAAF" fill-opacity="0.08"/>
<rect opacity="0.6" x="86.8421" y="29.579" width="138.158" height="14.4737" rx="6.57895" fill="#3EAAAF" fill-opacity="0.5"/>
<rect opacity="0.3" x="86.8421" y="55.8948" width="46.0526" height="14.4737" rx="6.57895" fill="#3EAAAF" fill-opacity="0.5"/>
<g clip-path="url(#clip0_1_2)">
<path d="M51.9737 76.9474C59.1276 76.9474 65.9884 74.1055 71.047 69.047C76.1055 63.9884 78.9474 57.1276 78.9474 49.9737C78.9474 42.8198 76.1055 35.959 71.047 30.9004C65.9884 25.8419 59.1276 23 51.9737 23C44.8198 23 37.959 25.8419 32.9004 30.9004C27.8419 35.959 25 42.8198 25 49.9737C25 57.1276 27.8419 63.9884 32.9004 69.047C37.959 74.1055 44.8198 76.9474 51.9737 76.9474V76.9474ZM48.602 44.9161C48.602 47.7079 47.0914 49.9737 45.2303 49.9737C43.3691 49.9737 41.8586 47.7079 41.8586 44.9161C41.8586 42.1243 43.3691 39.8586 45.2303 39.8586C47.0914 39.8586 48.602 42.1243 48.602 44.9161ZM39.4478 64.9205C39.0606 64.6969 38.7781 64.3287 38.6623 63.8968C38.5466 63.465 38.6072 63.0048 38.8308 62.6176C40.1622 60.3102 42.0779 58.3941 44.3851 57.0624C46.6923 55.7306 49.3097 55.03 51.9737 55.0313C54.6376 55.0307 57.2546 55.7316 59.5617 57.0633C61.8688 58.395 63.7847 60.3106 65.1166 62.6176C65.3366 63.0046 65.3947 63.4629 65.278 63.8926C65.1614 64.3222 64.8796 64.6882 64.494 64.9108C64.1085 65.1334 63.6506 65.1945 63.2202 65.0807C62.7898 64.9669 62.4219 64.6875 62.1967 64.3035C61.1612 62.5086 59.6711 61.0182 57.8764 59.9823C56.0818 58.9465 54.0458 58.4017 51.9737 58.403C49.9015 58.4017 47.8656 58.9465 46.0709 59.9823C44.2762 61.0182 42.7861 62.5086 41.7507 64.3035C41.5271 64.6906 41.1589 64.9732 40.727 65.0889C40.2951 65.2046 39.835 65.144 39.4478 64.9205ZM58.7171 49.9737C56.8559 49.9737 55.3454 47.7079 55.3454 44.9161C55.3454 42.1243 56.8559 39.8586 58.7171 39.8586C60.5783 39.8586 62.0888 42.1243 62.0888 44.9161C62.0888 47.7079 60.5783 49.9737 58.7171 49.9737Z" fill="#3EAAAF" fill-opacity="0.5"/>
</g>
<defs>
<clipPath id="clip0_1_2">
<rect width="53.9474" height="53.9474" fill="white" transform="translate(25 23)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB