u
This commit is contained in:
@@ -87,6 +87,37 @@ export const printerjob = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/printerjob/cancel-all
|
||||||
|
* Cancels all pending/processing jobs, optionally scoped to an agentprinter.
|
||||||
|
* Falls back to listing and cancelling individual jobs if needed.
|
||||||
|
* @param {{ agentprinterId?: number }} [payload]
|
||||||
|
* → { success: true, cancelledCount: number, jobs: PrinterJob[] }
|
||||||
|
*/
|
||||||
|
async cancelAll({ agentprinterId } = {}) {
|
||||||
|
try {
|
||||||
|
return await http('/api/printerjob/cancel-all', {
|
||||||
|
method: 'POST',
|
||||||
|
body: agentprinterId != null ? { agentprinterId: Number(agentprinterId) } : {},
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
if (err?.status === 404) {
|
||||||
|
const { printerjobs = [] } = await this.list({ agentprinterId });
|
||||||
|
const cancellable = printerjobs.filter(
|
||||||
|
(j) => j.state === 'pending' || j.state === 'processing',
|
||||||
|
);
|
||||||
|
if (cancellable.length === 0) return { success: true, cancelledCount: 0, jobs: [] };
|
||||||
|
const results = await Promise.all(cancellable.map((j) => this.cancel(j.id)));
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
cancelledCount: results.length,
|
||||||
|
jobs: results.map((r) => r.printerjob),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DELETE /api/printerjob/:id
|
* DELETE /api/printerjob/:id
|
||||||
* → { success: true, deletedJob: PrinterJob }
|
* → { success: true, deletedJob: PrinterJob }
|
||||||
|
|||||||
@@ -881,6 +881,10 @@ const actions = {
|
|||||||
return printerjobApi.sendTestZpl(agentprinterId, options);
|
return printerjobApi.sendTestZpl(agentprinterId, options);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async cancelAllPrinterJobs(agentprinterId) {
|
||||||
|
return printerjobApi.cancelAll({ agentprinterId });
|
||||||
|
},
|
||||||
|
|
||||||
async createZplJob(payload) {
|
async createZplJob(payload) {
|
||||||
return printerjobApi.createZplJob(payload);
|
return printerjobApi.createZplJob(payload);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -212,6 +212,7 @@ class AppSidebar extends PureComponent {
|
|||||||
>
|
>
|
||||||
<OnlinePrinterIcons />
|
<OnlinePrinterIcons />
|
||||||
<UserMenu />
|
<UserMenu />
|
||||||
|
<ChatFab />
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
@@ -430,7 +431,6 @@ export default function AppShell() {
|
|||||||
</Suspense>
|
</Suspense>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<ChatFab />
|
|
||||||
<ChatDrawer />
|
<ChatDrawer />
|
||||||
<PinnedAppletFabs pathname={pathname} />
|
<PinnedAppletFabs pathname={pathname} />
|
||||||
<PinnedAppletDialog />
|
<PinnedAppletDialog />
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import Menu from '@mui/material/Menu';
|
|||||||
import MenuItem from '@mui/material/MenuItem';
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import PrintOutlinedIcon from '@mui/icons-material/PrintOutlined';
|
import PrintOutlinedIcon from '@mui/icons-material/PrintOutlined';
|
||||||
|
import CancelScheduleSendOutlinedIcon from '@mui/icons-material/CancelScheduleSendOutlined';
|
||||||
import SettingsIcon from '@mui/icons-material/Settings';
|
import SettingsIcon from '@mui/icons-material/Settings';
|
||||||
import { enqueueSnackbar } from 'notistack';
|
import { enqueueSnackbar } from 'notistack';
|
||||||
import companyAutomat from '../automats/companyAutomat';
|
import companyAutomat from '../automats/companyAutomat';
|
||||||
@@ -27,10 +28,12 @@ export default class OnlinePrinterIcons extends PureComponent {
|
|||||||
: [],
|
: [],
|
||||||
menuAnchor: null,
|
menuAnchor: null,
|
||||||
testingId: null,
|
testingId: null,
|
||||||
|
cancellingId: null,
|
||||||
};
|
};
|
||||||
this.handleOpenMenu = this.handleOpenMenu.bind(this);
|
this.handleOpenMenu = this.handleOpenMenu.bind(this);
|
||||||
this.handleCloseMenu = this.handleCloseMenu.bind(this);
|
this.handleCloseMenu = this.handleCloseMenu.bind(this);
|
||||||
this.handleTestPrint = this.handleTestPrint.bind(this);
|
this.handleTestPrint = this.handleTestPrint.bind(this);
|
||||||
|
this.handleCancelAllJobs = this.handleCancelAllJobs.bind(this);
|
||||||
this.handleOpenPrinterSettings = this.handleOpenPrinterSettings.bind(this);
|
this.handleOpenPrinterSettings = this.handleOpenPrinterSettings.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,6 +128,29 @@ export default class OnlinePrinterIcons extends PureComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async handleCancelAllJobs(printer) {
|
||||||
|
if (!printer?.id) return;
|
||||||
|
this.setState({ cancellingId: printer.id });
|
||||||
|
try {
|
||||||
|
const res = await companyAutomat.actions.cancelAllPrinterJobs(printer.id);
|
||||||
|
const count = res?.cancelledCount ?? 0;
|
||||||
|
if (count > 0) {
|
||||||
|
enqueueSnackbar(
|
||||||
|
`${count} Druckauftrag/Druckaufträge für ${printer.model || 'Drucker'} abgebrochen.`,
|
||||||
|
{ variant: 'info' },
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
enqueueSnackbar(`Keine offenen Aufträge für ${printer.model || 'Drucker'}.`, {
|
||||||
|
variant: 'info',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
notifyError(err);
|
||||||
|
} finally {
|
||||||
|
this.setState({ cancellingId: null, menuAnchor: null });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleOpenPrinterSettings() {
|
handleOpenPrinterSettings() {
|
||||||
this.handleCloseMenu();
|
this.handleCloseMenu();
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
@@ -133,7 +159,7 @@ export default class OnlinePrinterIcons extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { menuAnchor, testingId } = this.state;
|
const { menuAnchor, testingId, cancellingId } = this.state;
|
||||||
const onlinePrinters = this.getOnlinePrinters();
|
const onlinePrinters = this.getOnlinePrinters();
|
||||||
|
|
||||||
if (onlinePrinters.length === 0) {
|
if (onlinePrinters.length === 0) {
|
||||||
@@ -266,7 +292,7 @@ export default class OnlinePrinterIcons extends PureComponent {
|
|||||||
|
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => void this.handleTestPrint(activePrinter)}
|
onClick={() => void this.handleTestPrint(activePrinter)}
|
||||||
disabled={testingId === activePrinter?.id}
|
disabled={testingId === activePrinter?.id || cancellingId === activePrinter?.id}
|
||||||
>
|
>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<PrintOutlinedIcon fontSize="small" color="primary" />
|
<PrintOutlinedIcon fontSize="small" color="primary" />
|
||||||
@@ -277,6 +303,19 @@ export default class OnlinePrinterIcons extends PureComponent {
|
|||||||
/>
|
/>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => void this.handleCancelAllJobs(activePrinter)}
|
||||||
|
disabled={cancellingId === activePrinter?.id || testingId === activePrinter?.id}
|
||||||
|
>
|
||||||
|
<ListItemIcon>
|
||||||
|
<CancelScheduleSendOutlinedIcon fontSize="small" color="error" />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText
|
||||||
|
primary={cancellingId === activePrinter?.id ? 'Wird abgebrochen…' : 'Alle Aufträge abbrechen'}
|
||||||
|
secondary="Warteschlange leeren"
|
||||||
|
/>
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
<MenuItem onClick={this.handleOpenPrinterSettings}>
|
<MenuItem onClick={this.handleOpenPrinterSettings}>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<SettingsIcon fontSize="small" />
|
<SettingsIcon fontSize="small" />
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import Fab from '@mui/material/Fab';
|
import Avatar from '@mui/material/Avatar';
|
||||||
|
import IconButton from '@mui/material/IconButton';
|
||||||
import Badge from '@mui/material/Badge';
|
import Badge from '@mui/material/Badge';
|
||||||
import Tooltip from '@mui/material/Tooltip';
|
|
||||||
import CircularProgress from '@mui/material/CircularProgress';
|
import CircularProgress from '@mui/material/CircularProgress';
|
||||||
import ChatRoundedIcon from '@mui/icons-material/ChatRounded';
|
|
||||||
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
|
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
|
||||||
import AutoAwesomeRoundedIcon from '@mui/icons-material/AutoAwesomeRounded';
|
import AutoAwesomeRoundedIcon from '@mui/icons-material/AutoAwesomeRounded';
|
||||||
import HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded';
|
import HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded';
|
||||||
@@ -70,144 +69,161 @@ export default class ChatFab extends PureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={(theme) => ({
|
sx={{
|
||||||
position: 'fixed',
|
px: { xs: 0.5, sm: 1, lg: 1.5 },
|
||||||
bottom: { xs: 20, sm: 28 },
|
py: { xs: 0.5, lg: 1 },
|
||||||
left: { xs: 20, lg: 164 },
|
alignSelf: { xs: 'center', lg: 'flex-start' },
|
||||||
zIndex: theme.zIndex.speedDial || 1050,
|
display: 'flex',
|
||||||
})}
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ position: 'relative' }}>
|
<Box sx={{ position: 'relative', display: 'inline-flex' }}>
|
||||||
{/* Animated pulsing halo when awaiting user answer */}
|
{/* Animated pulsing halo when awaiting user answer */}
|
||||||
{hasPendingAsk && !isOpen && (
|
{hasPendingAsk && !isOpen && (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: -8,
|
top: -4,
|
||||||
left: -8,
|
left: -4,
|
||||||
right: -8,
|
right: -4,
|
||||||
bottom: -8,
|
bottom: -4,
|
||||||
borderRadius: '50%',
|
|
||||||
bgcolor: CHAT_BUSY,
|
|
||||||
opacity: 0.5,
|
|
||||||
animation: 'fabAskPulse 1.5s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
|
||||||
'@keyframes fabAskPulse': {
|
|
||||||
'0%': { transform: 'scale(0.95)', opacity: 0.8 },
|
|
||||||
'50%': { transform: 'scale(1.35)', opacity: 0.12 },
|
|
||||||
'100%': { transform: 'scale(0.95)', opacity: 0.8 },
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Animated pulsating halo when model is busy thinking/working */}
|
|
||||||
{!hasPendingAsk && isBusy && !isOpen && (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
position: 'absolute',
|
|
||||||
top: -6,
|
|
||||||
left: -6,
|
|
||||||
right: -6,
|
|
||||||
bottom: -6,
|
|
||||||
borderRadius: '50%',
|
|
||||||
bgcolor: 'warning.main',
|
|
||||||
opacity: 0.4,
|
|
||||||
animation: 'fabPulse 1.6s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
|
||||||
'@keyframes fabPulse': {
|
|
||||||
'0%': { transform: 'scale(0.95)', opacity: 0.7 },
|
|
||||||
'50%': { transform: 'scale(1.25)', opacity: 0.15 },
|
|
||||||
'100%': { transform: 'scale(0.95)', opacity: 0.7 },
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Circular spinner ring when model is busy */}
|
|
||||||
{!hasPendingAsk && isBusy && !isOpen && (
|
|
||||||
<CircularProgress
|
|
||||||
size={66}
|
|
||||||
thickness={2.5}
|
|
||||||
sx={{
|
|
||||||
position: 'absolute',
|
|
||||||
top: -6,
|
|
||||||
left: -6,
|
|
||||||
color: CHAT_BUSY,
|
|
||||||
pointerEvents: 'none',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Badge
|
|
||||||
badgeContent={hasPendingAsk ? '?' : undefined}
|
|
||||||
color={hasPendingAsk ? 'error' : isBusy ? 'warning' : 'default'}
|
|
||||||
variant={hasPendingAsk ? 'standard' : 'dot'}
|
|
||||||
invisible={!hasPendingAsk && !isBusy}
|
|
||||||
overlap="circular"
|
|
||||||
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
|
|
||||||
sx={{
|
|
||||||
'& .MuiBadge-badge': hasPendingAsk
|
|
||||||
? {
|
|
||||||
bgcolor: RED,
|
|
||||||
color: WHITE,
|
|
||||||
fontWeight: 900,
|
|
||||||
fontSize: '0.85rem',
|
|
||||||
minWidth: 22,
|
|
||||||
height: 22,
|
|
||||||
borderRadius: '50%',
|
borderRadius: '50%',
|
||||||
boxShadow: `0 2px 10px ${RED_GLOW}`,
|
bgcolor: CHAT_BUSY,
|
||||||
animation: 'badgePop 1.5s ease infinite',
|
opacity: 0.5,
|
||||||
'@keyframes badgePop': {
|
animation: 'fabAskPulse 1.5s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
||||||
'0%, 100%': { transform: 'scale(1)' },
|
'@keyframes fabAskPulse': {
|
||||||
'50%': { transform: 'scale(1.2)' },
|
'0%': { transform: 'scale(0.95)', opacity: 0.8 },
|
||||||
|
'50%': { transform: 'scale(1.35)', opacity: 0.12 },
|
||||||
|
'100%': { transform: 'scale(0.95)', opacity: 0.8 },
|
||||||
},
|
},
|
||||||
}
|
}}
|
||||||
: undefined,
|
/>
|
||||||
}}
|
)}
|
||||||
>
|
|
||||||
<Fab
|
{/* Animated pulsating halo when model is busy thinking/working */}
|
||||||
color="primary"
|
{!hasPendingAsk && isBusy && !isOpen && (
|
||||||
aria-label={ariaLabel}
|
<Box
|
||||||
|
sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: -4,
|
||||||
|
left: -4,
|
||||||
|
right: -4,
|
||||||
|
bottom: -4,
|
||||||
|
borderRadius: '50%',
|
||||||
|
bgcolor: 'warning.main',
|
||||||
|
opacity: 0.4,
|
||||||
|
animation: 'fabPulse 1.6s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
||||||
|
'@keyframes fabPulse': {
|
||||||
|
'0%': { transform: 'scale(0.95)', opacity: 0.7 },
|
||||||
|
'50%': { transform: 'scale(1.25)', opacity: 0.15 },
|
||||||
|
'100%': { transform: 'scale(0.95)', opacity: 0.7 },
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Circular spinner ring when model is busy */}
|
||||||
|
{!hasPendingAsk && isBusy && !isOpen && (
|
||||||
|
<CircularProgress
|
||||||
|
size={38}
|
||||||
|
thickness={3}
|
||||||
|
sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: -3,
|
||||||
|
left: -3,
|
||||||
|
color: CHAT_BUSY,
|
||||||
|
pointerEvents: 'none',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<IconButton
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
sx={(theme) => ({
|
aria-label={ariaLabel}
|
||||||
width: 54,
|
sx={{ p: 0, width: 32, height: 32, borderRadius: '50%' }}
|
||||||
height: 54,
|
|
||||||
boxShadow: hasPendingAsk
|
|
||||||
? CHAT_FAB_SHADOW_PENDING
|
|
||||||
: isBusy
|
|
||||||
? CHAT_FAB_SHADOW_BUSY
|
|
||||||
: CHAT_FAB_SHADOW_IDLE,
|
|
||||||
background: hasPendingAsk
|
|
||||||
? CHAT_FAB_PENDING
|
|
||||||
: isBusy
|
|
||||||
? CHAT_FAB_BUSY
|
|
||||||
: `linear-gradient(135deg, ${theme.palette.primary.main} 0%, ${theme.palette.primary.dark} 100%)`,
|
|
||||||
})}
|
|
||||||
>
|
>
|
||||||
{isOpen ? (
|
<Badge
|
||||||
<CloseRoundedIcon sx={{ fontSize: 24 }} />
|
badgeContent={hasPendingAsk ? '?' : undefined}
|
||||||
) : hasPendingAsk ? (
|
color={hasPendingAsk ? 'error' : isBusy ? 'warning' : 'default'}
|
||||||
<HelpOutlineRoundedIcon
|
variant={hasPendingAsk ? 'standard' : 'dot'}
|
||||||
sx={{
|
invisible={!hasPendingAsk && !isBusy}
|
||||||
fontSize: 26,
|
overlap="circular"
|
||||||
animation: 'fabWiggle 2s ease infinite',
|
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
|
||||||
'@keyframes fabWiggle': {
|
sx={{
|
||||||
'0%, 100%': { transform: 'rotate(0deg)' },
|
'& .MuiBadge-badge': hasPendingAsk
|
||||||
'15%': { transform: 'rotate(-12deg)' },
|
? {
|
||||||
'30%': { transform: 'rotate(12deg)' },
|
bgcolor: RED,
|
||||||
'45%': { transform: 'rotate(-8deg)' },
|
color: WHITE,
|
||||||
'60%': { transform: 'rotate(0deg)' },
|
fontWeight: 900,
|
||||||
},
|
fontSize: '0.75rem',
|
||||||
}}
|
minWidth: 18,
|
||||||
/>
|
height: 18,
|
||||||
) : isBusy ? (
|
borderRadius: '50%',
|
||||||
<AutoAwesomeRoundedIcon sx={{ fontSize: 24 }} />
|
boxShadow: `0 2px 8px ${RED_GLOW}`,
|
||||||
) : (
|
animation: 'badgePop 1.5s ease infinite',
|
||||||
<ChatRoundedIcon sx={{ fontSize: 24 }} />
|
'@keyframes badgePop': {
|
||||||
)}
|
'0%, 100%': { transform: 'scale(1)' },
|
||||||
</Fab>
|
'50%': { transform: 'scale(1.2)' },
|
||||||
</Badge>
|
},
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Avatar
|
||||||
|
sx={(theme) => ({
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
bgcolor: hasPendingAsk
|
||||||
|
? CHAT_FAB_PENDING
|
||||||
|
: isBusy
|
||||||
|
? CHAT_FAB_BUSY
|
||||||
|
: isOpen
|
||||||
|
? theme.palette.primary.main
|
||||||
|
: `linear-gradient(135deg, ${theme.palette.primary.main} 0%, ${theme.palette.primary.dark} 100%)`,
|
||||||
|
background: hasPendingAsk
|
||||||
|
? CHAT_FAB_PENDING
|
||||||
|
: isBusy
|
||||||
|
? CHAT_FAB_BUSY
|
||||||
|
: isOpen
|
||||||
|
? theme.palette.primary.main
|
||||||
|
: `linear-gradient(135deg, ${theme.palette.primary.main} 0%, ${theme.palette.primary.dark} 100%)`,
|
||||||
|
color: WHITE,
|
||||||
|
transition: 'all 0.2s ease',
|
||||||
|
boxShadow: hasPendingAsk
|
||||||
|
? CHAT_FAB_SHADOW_PENDING
|
||||||
|
: isBusy
|
||||||
|
? CHAT_FAB_SHADOW_BUSY
|
||||||
|
: isOpen
|
||||||
|
? `0 2px 8px rgba(0,0,0,0.25)`
|
||||||
|
: 'none',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{isOpen ? (
|
||||||
|
<CloseRoundedIcon sx={{ fontSize: 18 }} />
|
||||||
|
) : hasPendingAsk ? (
|
||||||
|
<HelpOutlineRoundedIcon
|
||||||
|
sx={{
|
||||||
|
fontSize: 18,
|
||||||
|
animation: 'fabWiggle 2s ease infinite',
|
||||||
|
'@keyframes fabWiggle': {
|
||||||
|
'0%, 100%': { transform: 'rotate(0deg)' },
|
||||||
|
'15%': { transform: 'rotate(-12deg)' },
|
||||||
|
'30%': { transform: 'rotate(12deg)' },
|
||||||
|
'45%': { transform: 'rotate(-8deg)' },
|
||||||
|
'60%': { transform: 'rotate(0deg)' },
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : isBusy ? (
|
||||||
|
<AutoAwesomeRoundedIcon sx={{ fontSize: 18 }} />
|
||||||
|
) : (
|
||||||
|
<AutoAwesomeRoundedIcon sx={{ fontSize: 18 }} />
|
||||||
|
)}
|
||||||
|
</Avatar>
|
||||||
|
</Badge>
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user