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

View File

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