u
This commit is contained in:
@@ -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}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -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}
|
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user