This commit is contained in:
seb
2026-08-05 18:17:48 +02:00
parent 0c12d99987
commit 1fda43b20d
2 changed files with 52 additions and 75 deletions

View File

@@ -54,21 +54,14 @@ class ArticleView extends Component {
} }
} }
refreshSearchCaches = () => {
void this.context.updateArticleIndex();
void this.context.updateCategoryTree();
};
handleArticleUpdated = (next) => { handleArticleUpdated = (next) => {
this.context.setArticle(next); this.context.setArticle(next);
this.setState({ article: next }); this.setState({ article: next });
this.refreshSearchCaches();
}; };
handleArticleDeleted = () => { handleArticleDeleted = () => {
const { navigate } = this.props; const { navigate } = this.props;
const { article, categories, rootCategoryId } = this.state; const { article, categories, rootCategoryId } = this.state;
this.refreshSearchCaches();
const categoryId = article?.categoryIds?.[0]; const categoryId = article?.categoryIds?.[0];
if (categories && rootCategoryId != null && categoryId != null) { if (categories && rootCategoryId != null && categoryId != null) {
navigate(buildCategoryPath(categories, rootCategoryId, categoryId)); navigate(buildCategoryPath(categories, rootCategoryId, categoryId));
@@ -96,8 +89,6 @@ class ArticleView extends Component {
<PanelTileGrid> <PanelTileGrid>
<ArticleViewName <ArticleViewName
article={article} article={article}
categories={categories}
rootCategoryId={rootCategoryId}
onArticleUpdated={this.handleArticleUpdated} onArticleUpdated={this.handleArticleUpdated}
/> />

View File

@@ -2,7 +2,6 @@ import { Component } from 'react';
import { EditablePanelTile } from '../../panels'; import { EditablePanelTile } from '../../panels';
import SingleLineTextEdit from '../../SingleLineTextEdit'; import SingleLineTextEdit from '../../SingleLineTextEdit';
import { StorageManagerContext } from '../../../api/storageManagerContext'; import { StorageManagerContext } from '../../../api/storageManagerContext';
import { requireObject } from '../../../utils/apiShape';
import { getCategoryBreadcrumbs } from '../../../store/categorySlice'; import { getCategoryBreadcrumbs } from '../../../store/categorySlice';
import { Box, Chip, IconButton } from '@mui/material'; import { Box, Chip, IconButton } from '@mui/material';
import AddIcon from '@mui/icons-material/Add'; import AddIcon from '@mui/icons-material/Add';
@@ -51,13 +50,18 @@ const columnSx = {
alignSelf: 'stretch', alignSelf: 'stretch',
}; };
function categoryIdsChanged(a, b) {
const aa = a ?? [];
const bb = b ?? [];
return (
aa.length !== bb.length ||
[...aa].map(String).sort().join(',') !== [...bb].map(String).sort().join(',')
);
}
function draftDirty(draft, saved) { function draftDirty(draft, saved) {
const nameDiff = draft.name.trim() !== String(saved.name ?? '').trim(); const nameDiff = draft.name.trim() !== String(saved.name ?? '').trim();
const a = draft.categoryIds ?? []; const catDiff = categoryIdsChanged(draft.categoryIds, saved.categoryIds);
const b = saved.categoryIds ?? [];
const catDiff =
a.length !== b.length ||
[...a].map(String).sort().join(',') !== [...b].map(String).sort().join(',');
return nameDiff || catDiff; return nameDiff || catDiff;
} }
@@ -83,6 +87,8 @@ function categoryLabels(categoryIds, categories, rootCategoryId) {
} }
class CategoryPills extends Component { class CategoryPills extends Component {
static contextType = StorageManagerContext;
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { pickerOpen: false }; this.state = { pickerOpen: false };
@@ -103,16 +109,10 @@ class CategoryPills extends Component {
}; };
render() { render() {
const { const { categoryIds, editMode, onCategoryIdsChange } = this.props;
categoryLabels: labels,
categoryIds,
categories,
rootCategoryId,
sku,
editMode,
onCategoryIdsChange,
} = this.props;
const { pickerOpen } = this.state; const { pickerOpen } = this.state;
const { categories, rootCategoryId } = this.context.getCategoryState() ?? {};
const labels = categoryLabels(categoryIds, categories, rootCategoryId);
return ( return (
<> <>
@@ -140,15 +140,16 @@ class CategoryPills extends Component {
</IconButton> </IconButton>
) : null} ) : null}
</Box> </Box>
<CategoryPickerDialog {editMode ? (
key={sku} <CategoryPickerDialog
open={pickerOpen} open={pickerOpen}
onClose={this.handleClosePicker} onClose={this.handleClosePicker}
categories={categories} categories={categories}
rootCategoryId={rootCategoryId} rootCategoryId={rootCategoryId}
currentCategoryIds={categoryIds} currentCategoryIds={categoryIds}
onSelect={onCategoryIdsChange} onSelect={onCategoryIdsChange}
/> />
) : null}
</> </>
); );
} }
@@ -156,8 +157,7 @@ class CategoryPills extends Component {
class NameDisplay extends Component { class NameDisplay extends Component {
render() { render() {
const { name, categoryIds, categories, rootCategoryId, sku } = this.props; const { name, categoryIds } = this.props;
const labels = categoryLabels(categoryIds, categories, rootCategoryId);
return ( return (
<Box sx={columnSx}> <Box sx={columnSx}>
<Box sx={{ flex: 1, display: 'flex', alignItems: 'center' }}> <Box sx={{ flex: 1, display: 'flex', alignItems: 'center' }}>
@@ -169,15 +169,8 @@ class NameDisplay extends Component {
sx={articleNameFieldHiddenSx} sx={articleNameFieldHiddenSx}
/> />
</Box> </Box>
{labels.length > 0 ? ( {(categoryIds?.length ?? 0) > 0 ? (
<CategoryPills <CategoryPills categoryIds={categoryIds} editMode={false} />
categoryLabels={labels}
categoryIds={categoryIds}
categories={categories}
rootCategoryId={rootCategoryId}
sku={sku}
editMode={false}
/>
) : null} ) : null}
</Box> </Box>
); );
@@ -186,34 +179,24 @@ class NameDisplay extends Component {
class NameEdit extends Component { class NameEdit extends Component {
render() { render() {
const { const { draft, onChange, inputRef, name, categoryIds } = this.props;
draft, const currentName = draft?.name ?? name;
onChange, const currentCategoryIds = draft?.categoryIds ?? categoryIds;
inputRef,
categories,
rootCategoryId,
sku,
} = this.props;
const labels = categoryLabels(draft.categoryIds, categories, rootCategoryId);
return ( return (
<Box sx={columnSx}> <Box sx={columnSx}>
<Box sx={{ flex: 1, display: 'flex', alignItems: 'center' }}> <Box sx={{ flex: 1, display: 'flex', alignItems: 'center' }}>
<SingleLineTextEdit <SingleLineTextEdit
inputRef={inputRef} inputRef={inputRef}
label="Name" label="Name"
value={draft.name} value={currentName}
onChange={(name) => onChange({ ...draft, name })} onChange={(nextName) => onChange({ ...draft, name: nextName })}
sx={articleNameFieldSx} sx={articleNameFieldSx}
/> />
</Box> </Box>
<CategoryPills <CategoryPills
categoryLabels={labels} categoryIds={currentCategoryIds}
categoryIds={draft.categoryIds}
categories={categories}
rootCategoryId={rootCategoryId}
sku={sku}
editMode editMode
onCategoryIdsChange={(categoryIds) => onChange({ ...draft, categoryIds })} onCategoryIdsChange={(nextIds) => onChange({ ...draft, categoryIds: nextIds })}
/> />
</Box> </Box>
); );
@@ -228,19 +211,26 @@ export default class ArticleViewName extends Component {
const store = this.context; const store = this.context;
const name = draft.name.trim(); const name = draft.name.trim();
const categoryIds = draft.categoryIds ?? []; const categoryIds = draft.categoryIds ?? [];
const nameChanged = name !== String(articleData.name ?? '').trim();
const categoriesChanged = categoryIdsChanged(categoryIds, articleData.categoryIds);
const [nameRes] = await Promise.all([ let article = null;
store.article.update(articleData.sku, { name }),
store.article.setCategories(articleData.sku, { categoryIds }),
]);
requireObject(nameRes, 'PATCH /api/article/:sku'); if (nameChanged) {
requireObject(nameRes.article, 'article'); const nameRes = await store.article.update(articleData.sku, { name });
onArticleUpdated?.(nameRes.article); article = nameRes.article;
}
if (categoriesChanged) {
const catRes = await store.article.setCategories(articleData.sku, { categoryIds });
article = catRes.article;
}
if (article) onArticleUpdated?.(article);
}; };
render() { render() {
const { article: articleData, categories, rootCategoryId } = this.props; const { article: articleData } = this.props;
const savedCategoryIds = articleData.categoryIds ?? []; const savedCategoryIds = articleData.categoryIds ?? [];
const value = { name: articleData.name ?? '', categoryIds: [...savedCategoryIds] }; const value = { name: articleData.name ?? '', categoryIds: [...savedCategoryIds] };
@@ -257,16 +247,12 @@ export default class ArticleViewName extends Component {
<NameDisplay <NameDisplay
name={value.name} name={value.name}
categoryIds={value.categoryIds} categoryIds={value.categoryIds}
categories={categories}
rootCategoryId={rootCategoryId}
sku={articleData.sku}
/> />
} }
edit={ edit={
<NameEdit <NameEdit
categories={categories} name={value.name}
rootCategoryId={rootCategoryId} categoryIds={value.categoryIds}
sku={articleData.sku}
/> />
} }
/> />