u
This commit is contained in:
@@ -3,9 +3,9 @@ import Autocomplete from '@mui/material/Autocomplete';
|
||||
import TextInput from '../../TextInput';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Box from '@mui/material/Box';
|
||||
import { EditablePanelTile } from 'dashgui/panels';
|
||||
import { EditablePanelTile, PanelTile } from 'dashgui/panels';
|
||||
import brandAutomat from '../../../automats/brandAutomat';
|
||||
import artikelAutomat from '../../../automats/artikelAutomat';
|
||||
import artikelAutomat, { getArticle } from '../../../automats/artikelAutomat';
|
||||
import { requireObject } from '../../../utils/apiShape';
|
||||
import { notifyError } from '../../../utils/notify';
|
||||
import InputAdornment from '@mui/material/InputAdornment';
|
||||
@@ -33,12 +33,13 @@ class PanelValue extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
function brandDraftValue(article) {
|
||||
function brandDraftValue(article, parentArticle) {
|
||||
const brand = article?.brand || parentArticle?.brand;
|
||||
return {
|
||||
name: article?.brand?.name ?? '',
|
||||
thumbHash: article?.brand?.thumbHash ?? null,
|
||||
thumbW: article?.brand?.thumbW ?? null,
|
||||
thumbH: article?.brand?.thumbH ?? null,
|
||||
name: brand?.name ?? '',
|
||||
thumbHash: brand?.thumbHash ?? null,
|
||||
thumbW: brand?.thumbW ?? null,
|
||||
thumbH: brand?.thumbH ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -128,12 +129,27 @@ export default class ArticleViewBrand extends PureComponent {
|
||||
this.unsub = brandAutomat.subscribe(this, (state) => ({
|
||||
brands: state.brands ?? [],
|
||||
}));
|
||||
const parentSku = this.props.article?.parentSku || this.props.article?.parent_sku;
|
||||
if (parentSku && !getArticle(parentSku)) {
|
||||
void artikelAutomat.actions.loadArticle(parentSku).catch(() => {});
|
||||
}
|
||||
this.unsubArtikel = artikelAutomat.subscribe(this, () => ({}));
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const parentSku = this.props.article?.parentSku || this.props.article?.parent_sku;
|
||||
const prevParentSku = prevProps.article?.parentSku || prevProps.article?.parent_sku;
|
||||
if (parentSku && parentSku !== prevParentSku && !getArticle(parentSku)) {
|
||||
void artikelAutomat.actions.loadArticle(parentSku).catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._cancelled = true;
|
||||
this.unsub?.();
|
||||
this.unsub = null;
|
||||
this.unsubArtikel?.();
|
||||
this.unsubArtikel = null;
|
||||
}
|
||||
|
||||
handleSave = async (draft) => {
|
||||
@@ -170,7 +186,40 @@ export default class ArticleViewBrand extends PureComponent {
|
||||
render() {
|
||||
const { article: articleData } = this.props;
|
||||
const { brands } = this.state;
|
||||
const value = brandDraftValue(articleData);
|
||||
const isChild = Boolean(
|
||||
articleData?.parentSku ||
|
||||
articleData?.parent_sku ||
|
||||
articleData?.parentArticleId != null ||
|
||||
articleData?.parentId != null ||
|
||||
articleData?.parent_id != null
|
||||
);
|
||||
|
||||
const parentSku = articleData?.parentSku || articleData?.parent_sku;
|
||||
const parentArticle = parentSku ? getArticle(parentSku) : null;
|
||||
const value = brandDraftValue(articleData, parentArticle);
|
||||
|
||||
if (isChild) {
|
||||
const brandObj = articleData?.brand || parentArticle?.brand || (value.name ? value : null);
|
||||
return (
|
||||
<PanelTile
|
||||
title="Marke"
|
||||
wide={1}
|
||||
minHeight={SECOND_ROW_MIN_HEIGHT}
|
||||
color={PURPLE_BG}
|
||||
>
|
||||
<PanelValue>
|
||||
{value.name ? (
|
||||
<BrandLabel
|
||||
brand={brandObj}
|
||||
name={value.name}
|
||||
size={22}
|
||||
typographyProps={{ variant: 'body2', fontWeight: 600 }}
|
||||
/>
|
||||
) : null}
|
||||
</PanelValue>
|
||||
</PanelTile>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<EditablePanelTile
|
||||
|
||||
@@ -85,10 +85,18 @@ export default class ArticleViewStock extends PureComponent {
|
||||
const hasWarehouses = warehouses.length > 0;
|
||||
|
||||
let totalVariantsStock = 0;
|
||||
let anyVariantTracksStock = false;
|
||||
if (isParent) {
|
||||
const children = Array.isArray(articleData?.children) ? articleData.children : [];
|
||||
for (const child of children) {
|
||||
const fullChild = getArticle(child.sku) || child;
|
||||
const tracks =
|
||||
fullChild.track_stock !== false &&
|
||||
fullChild.track_stock !== 0 &&
|
||||
fullChild.track_stock !== '0';
|
||||
if (tracks) {
|
||||
anyVariantTracksStock = true;
|
||||
}
|
||||
if (Array.isArray(fullChild.warehouses) && fullChild.warehouses.length > 0) {
|
||||
totalVariantsStock += fullChild.warehouses.reduce(
|
||||
(sum, wh) => sum + (Number(wh.stock) || 0),
|
||||
@@ -155,19 +163,21 @@ export default class ArticleViewStock extends PureComponent {
|
||||
</Typography>
|
||||
|
||||
{isParent ? (
|
||||
<Box sx={{ my: 0.75 }}>
|
||||
<Typography
|
||||
component="div"
|
||||
sx={{
|
||||
fontSize: '1.25rem',
|
||||
fontWeight: 700,
|
||||
lineHeight: 1.2,
|
||||
color: 'text.primary',
|
||||
}}
|
||||
>
|
||||
Alle Varianten zusammen: {formatStock(totalVariantsStock)}
|
||||
</Typography>
|
||||
</Box>
|
||||
anyVariantTracksStock || totalVariantsStock > 0 ? (
|
||||
<Box sx={{ my: 0.75 }}>
|
||||
<Typography
|
||||
component="div"
|
||||
sx={{
|
||||
fontSize: '1.25rem',
|
||||
fontWeight: 700,
|
||||
lineHeight: 1.2,
|
||||
color: 'text.primary',
|
||||
}}
|
||||
>
|
||||
Alle Varianten zusammen: {formatStock(totalVariantsStock)}
|
||||
</Typography>
|
||||
</Box>
|
||||
) : null
|
||||
) : isStueckliste ? (
|
||||
<Tooltip title="Virtueller Bestand – Anpassung erfolgt an den einzelnen Komponenten" arrow placement="top-start">
|
||||
<Box sx={{ my: 0.5 }}>
|
||||
|
||||
@@ -112,7 +112,19 @@ export default class ChatDrawer extends PureComponent {
|
||||
}, delay);
|
||||
};
|
||||
|
||||
updateGutterClass(isOpen) {
|
||||
if (typeof document === 'undefined') return;
|
||||
const html = document.documentElement;
|
||||
if (!html) return;
|
||||
if (isOpen) {
|
||||
html.classList.add('df-chat-open');
|
||||
} else {
|
||||
html.classList.remove('df-chat-open');
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateGutterClass(this.state.isOpen);
|
||||
if (this.state.isOpen) {
|
||||
if (chatAutomat.state.pendingInput != null) {
|
||||
this.focusInputAtEnd(150);
|
||||
@@ -177,7 +189,14 @@ export default class ChatDrawer extends PureComponent {
|
||||
}));
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (this.state.isOpen !== prevState.isOpen) {
|
||||
this.updateGutterClass(this.state.isOpen);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.updateGutterClass(false);
|
||||
if (this.focusTimeout) clearTimeout(this.focusTimeout);
|
||||
this.unsub?.();
|
||||
this.unsubSettings?.();
|
||||
@@ -1605,7 +1624,9 @@ export default class ChatDrawer extends PureComponent {
|
||||
anchor="right"
|
||||
open={isOpen}
|
||||
onClose={this.handleClose}
|
||||
disableScrollLock
|
||||
ModalProps={{
|
||||
disableScrollLock: true,
|
||||
disableEnforceFocus: true,
|
||||
}}
|
||||
sx={(theme) => ({
|
||||
|
||||
@@ -44,6 +44,15 @@ html {
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
/* While the assistant chat drawer is open on the right edge of the screen,
|
||||
the reserved scrollbar-gutter strip must read as white to seamlessly
|
||||
continue the drawer surface. */
|
||||
html.df-chat-open,
|
||||
html.df-chat-open body,
|
||||
html.df-chat-open #root {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
/* While any AppDialog is open, the reserved scrollbar-gutter strip must read
|
||||
as fog, not app background. AppDialog toggles `df-dialog-open` on <html>
|
||||
(ref-counted for stacked dialogs). The solid fog token is published by
|
||||
|
||||
Reference in New Issue
Block a user