Загрузка данных
import React from 'react';
import { useDispatch } from 'react-redux';
import { Z_INDEX } from '@configs/appConfig';
import features from '@features';
import { useAppSelect } from '@hooks/useAppSelector';
import { useLocalisation } from '@hooks/useLocalisation';
import { HelpCenter } from '@modules/HelpCenter';
import { ModalRoot } from '@modules/ModalRoot';
import { ModalsContainer } from '@modules/ModalsContainer';
import { useAddressDepositWithdrawalFormHotkey } from '@modules/MXT/AddressDepositWithdrawalForm/hooks';
import { useDepositFormHotkey } from '@modules/MXT/DepositForm/hooks/useDepositFormHotkey';
import { NewsWorkspace } from '@modules/NewsWorkspace/NewsWorkspace';
import { isSidebarOpenSelector } from '@store/selectors/modals';
import { savedWorkspacesSelector, workspaceWidgetsSelector } from '@store/selectors/workspaces';
import { closeSidebarModal, openSidebarModal } from '@store/slices/modals';
import { WorkspaceErrorHandler } from '@terminal/desktop/components/WorkspaceErrorHandler';
import { Sidebar } from '@uikit/Sidebar';
import { EmptyWorkspace } from './components/EmptyWorkspace/EmptyWorkspace';
import { Header } from './components/Header';
import { Profile } from './components/Profile';
import { SidebarContent } from './components/SidebarContent';
import StartPage from './components/StartPage';
import styles from './desktop.module.scss';
import { WorkspaceContainer } from './workspaces/components/WorkspaceContainer';
import { Workspace } from './workspaces/default';
import { Workspace as NewWorkspace } from './workspaces/mesh';
export const DesktopContent: React.FC = () => {
const hasSavedWorkspaces = useAppSelect((state) => savedWorkspacesSelector(state).length > 0);
const noWidgets = useAppSelect((state) => workspaceWidgetsSelector(state).length === 0);
const isSidebarOpen = useAppSelect(isSidebarOpenSelector);
const dispatch = useDispatch();
useDepositFormHotkey();
useAddressDepositWithdrawalFormHotkey();
const onCloseSidebar = () => {
dispatch(closeSidebarModal());
};
const localisation = useLocalisation();
const isCurrentWorkspaceHelpCenterWidgets = useAppSelect(
(state) =>
state.workspaces.workspaces.find(
({ isCurrent, name, isNew }) => isCurrent && !isNew && name === localisation.helpCenter,
)?.isAddWidgets,
);
const isCurrentWorkspaceNewsWidgets = useAppSelect(
(state) =>
state.workspaces.workspaces.find(
({ isCurrent, name, isNew }) => isCurrent && !isNew && name === localisation.news,
)?.isAddWidgets,
);
const isCurrentWorkspaceSupportWidgets = useAppSelect(
(state) =>
state.workspaces.workspaces.find(
({ isCurrent, name, isNew }) => isCurrent && !isNew && name === localisation.profile,
)?.isAddWidgets,
);
const isShowCurrentWidgets: boolean = useAppSelect(
(state) => state.workspaces.workspaces.find(({ isCurrent, code }) => isCurrent && !code)?.isAddWidgets ?? false,
);
const isCurrentWorkspaceNew = useAppSelect(
({ workspaces }) => workspaces.workspaces.find(({ isCurrent }) => isCurrent)?.isNew,
);
const handleToggle = () => {
if (isSidebarOpen) {
dispatch(closeSidebarModal());
} else {
dispatch(openSidebarModal());
}
};
return (
<>
<Header />
<div className={styles['main-workspace-wrapper']}>
{isSidebarOpen && (
<Sidebar
className={styles['sidebar-container-main']}
sidebarBodyClassName={styles['sidebar-body-main']}
width={550}
open={isSidebarOpen}
onClose={onCloseSidebar}
zIndex={Z_INDEX.APP_SIDEBAR}
>
<SidebarContent />
</Sidebar>
)}
<WorkspaceContainer isMobileView={false}>
{isShowCurrentWidgets && noWidgets && hasSavedWorkspaces && !isCurrentWorkspaceNew && (
<EmptyWorkspace onAddWidgetClick={handleToggle} />
)}
{isShowCurrentWidgets && noWidgets && isCurrentWorkspaceNew && (
<div className={styles['start-page']}>
<StartPage />
</div>
)}
<WorkspaceErrorHandler isMobileView={false}>
{features.meshLayout ? <NewWorkspace /> : <Workspace />}
</WorkspaceErrorHandler>
</WorkspaceContainer>
{isCurrentWorkspaceHelpCenterWidgets === false && <HelpCenter />}
{isCurrentWorkspaceNewsWidgets === false && <NewsWorkspace />}
{isCurrentWorkspaceSupportWidgets === false && <Profile />}
<ModalsContainer />
<ModalRoot />
</div>
</>
);
};
import React from 'react';
import { Button } from '@uikit/Button';
import styles from '../../desktop.module.scss';
import { useStableKeys } from '../StartPage/components/MiniTile';
// TODO: перенести в радар
interface IEmptyWorkspace {
onAddWidgetClick: React.MouseEventHandler<HTMLButtonElement>;
}
export const EmptyWorkspace: React.FC<IEmptyWorkspace> = ({ onAddWidgetClick }) => {
const dotKeysEmptyState = useStableKeys('empty-state-dot', 12);
const lineKeysEmptyState = useStableKeys('empty-state-line', 6);
return (
<div className={styles['start-view']}>
<div className={styles['grid-container']}>
<div className={styles.block}>
<img
src="/images/Candles.png"
alt="Candles small"
className={styles['candle-image']}
/>
</div>
<div className={styles.block}>
<div className={styles.smallGrid}>
{dotKeysEmptyState.map((key) => (
<div
key={key}
className={styles.dot}
/>
))}
</div>
</div>
<div className={styles.block}>
<div className={styles.lineGroup}>
{lineKeysEmptyState.map((key) => (
<div
key={key}
className={styles.line}
/>
))}
</div>
</div>
<div className={styles.block}>
<img
src="/images/Chart.png"
alt="Chart small"
className={styles['candle-image']}
/>
</div>
</div>
<div className={styles['main-title']}>Нет открытых виджетов</div>
<div className={styles['main-text']}>Добавьте виджеты или используйте шаблон рабочего стола</div>
<Button
variant="filled-primary"
onClick={onAddWidgetClick}
iconEnabled="start"
Icon="plus"
text="Виджет"
/>
</div>
);
};
import { Loader } from '@components/Loader';
import React from 'react';
import './loader.scss';
import { Spinner } from '@components/Spinner';
import { TextMad } from '@components/TextMad';
export function Loader(): JSX.Element {
return (
<div className="loader-container">
<Spinner />
<div className="text-holder">
<TextMad>Данные загружаются</TextMad>
<TextMad>Пожалуйста подождите</TextMad>
</div>
</div>
);
}
@import 'colors.scss';
.main-workspace-wrapper {
flex: 1;
width: 100%;
position: relative;
background-color: red;
min-height: 0;
}
.main-workspace {
background-color: $background-bottom;
overflow: hidden;
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
.start-view {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
height: 100%;
margin-top: 12%;
.grid-container {
display: grid;
gap: 4px;
grid-template-columns: repeat(2, auto);
cursor: pointer;
.block {
background-color: $surface-button-basis-secondary;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
height: 54px;
width: 127px;
overflow: hidden;
.candle-image {
position: relative;
top: 6px;
width: 50px;
opacity: 0.6;
transition: all 0.4s ease;
mix-blend-mode: screen;
filter: brightness(1.4);
}
.smallGrid {
display: grid;
grid-template-columns: repeat(4, auto);
gap: 10px;
transition: all 0.4s ease;
}
.dot {
width: 2px;
height: 2px;
border-radius: 50%;
background-color: $surface-icon-basis-disabled;
transition: all 0.4s ease;
}
.lineGroup {
display: flex;
flex-direction: column;
justify-content: center;
margin: 12px;
gap: 5px;
border-radius: 1px;
transition: all 0.4s ease;
}
.line {
height: 1px;
width: 39px;
background-color: $surface-icon-basis-disabled;
transition: background-color 0.2s ease;
}
}
&:hover .candle-image {
transform: scale(1.2) translateY(-3px);
}
&:hover .line {
background-color: $surface-icon-basis-muted-secondary;
width: 45px;
}
&:hover .smallGrid,
&:hover .lineGroup {
transform: scale(1.15);
}
&:hover .lineGroup {
gap: 6px;
}
&:hover .smallGrid {
transform: scale(1.4);
}
&:hover .block {
background-color: $action-surface-hover;
}
}
.main-title {
font-size: 32px;
line-height: 36px;
color: var(--thm-text-button-primary);
margin-top: 32px;
}
.main-text {
font-size: 14px;
line-height: 16px;
color: var(--thm-text-button-primary);
margin: 24px 0 32px 0;
}
.bottom-text {
font-size: 12px;
line-height: 16px;
color: var(--thm-text-button-primary);
margin-top: 20px;
}
}
.connect-side-block {
height: 100%;
width: 50%;
position: absolute;
top: 0;
background-color: $terminal-bauhaus;
opacity: 0.5;
}
}
.main-workspace-mobile {
display: none;
}
.sidebar-container-main {
:global {
.ant-drawer-body {
padding: 0 24px 24px 24px;
}
}
}
.sidebar-body-main {
&::-webkit-scrollbar {
width: 8px;
}
}
.start-page {
height: 100%;
box-sizing: border-box;
padding-block: 100px 32px;
overflow-y: auto;
}