u
This commit is contained in:
@@ -4,7 +4,7 @@ import SingleLineTextEdit from 'dashgui/SingleLineTextEdit';
|
|||||||
import { getCategoryState } from '../../../automats/categoryAutomat';
|
import { getCategoryState } from '../../../automats/categoryAutomat';
|
||||||
import artikelAutomat from '../../../automats/artikelAutomat';
|
import artikelAutomat from '../../../automats/artikelAutomat';
|
||||||
import { getCategoryBreadcrumbs, categoryDisplayName } from '../../../utils/categoryUtils';
|
import { getCategoryBreadcrumbs, categoryDisplayName } from '../../../utils/categoryUtils';
|
||||||
import { Box, Chip, IconButton } from '@mui/material';
|
import { Box, Chip, IconButton, Typography } from '@mui/material';
|
||||||
import AddIcon from '@mui/icons-material/Add';
|
import AddIcon from '@mui/icons-material/Add';
|
||||||
import CategoryPickerDialog from '../CategoryPickerDialog';
|
import CategoryPickerDialog from '../CategoryPickerDialog';
|
||||||
import { notifyError } from '../../../utils/notify';
|
import { notifyError } from '../../../utils/notify';
|
||||||
@@ -66,8 +66,9 @@ function categoryIdsChanged(a, b) {
|
|||||||
|
|
||||||
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 seoDiff = String(draft.seo ?? '').trim() !== String(saved.seo ?? '').trim();
|
||||||
const catDiff = categoryIdsChanged(draft.categoryIds, saved.categoryIds);
|
const catDiff = categoryIdsChanged(draft.categoryIds, saved.categoryIds);
|
||||||
return nameDiff || catDiff;
|
return nameDiff || seoDiff || catDiff;
|
||||||
}
|
}
|
||||||
|
|
||||||
function draftValid(draft) {
|
function draftValid(draft) {
|
||||||
@@ -207,10 +208,10 @@ class CategoryPills extends Component {
|
|||||||
|
|
||||||
class NameDisplay extends Component {
|
class NameDisplay extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { name, categoryIds } = this.props;
|
const { name, seo, categoryIds } = this.props;
|
||||||
return (
|
return (
|
||||||
<Box sx={columnSx}>
|
<Box sx={columnSx}>
|
||||||
<Box sx={{ flex: 1, display: 'flex', alignItems: 'center' }}>
|
<Box sx={{ flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
|
||||||
<SingleLineTextEdit
|
<SingleLineTextEdit
|
||||||
label="Name"
|
label="Name"
|
||||||
value={name}
|
value={name}
|
||||||
@@ -218,6 +219,13 @@ class NameDisplay extends Component {
|
|||||||
onChange={() => {}}
|
onChange={() => {}}
|
||||||
sx={articleNameFieldHiddenSx}
|
sx={articleNameFieldHiddenSx}
|
||||||
/>
|
/>
|
||||||
|
{seo ? (
|
||||||
|
<Box sx={{ px: 1.75, mt: -0.5, userSelect: 'text' }}>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{seo}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
) : null}
|
||||||
</Box>
|
</Box>
|
||||||
{(categoryIds?.length ?? 0) > 0 ? (
|
{(categoryIds?.length ?? 0) > 0 ? (
|
||||||
<CategoryPills categoryIds={categoryIds} editMode={false} />
|
<CategoryPills categoryIds={categoryIds} editMode={false} />
|
||||||
@@ -232,13 +240,15 @@ class NameEdit extends Component {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
name: props.name,
|
name: props.name,
|
||||||
|
seo: props.seo ?? '',
|
||||||
categoryIds: [...(props.categoryIds ?? [])],
|
categoryIds: [...(props.categoryIds ?? [])],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { onNameDraftChange, onCategoryIdsDraftChange } = this.props;
|
const { onNameDraftChange, onSeoDraftChange, onCategoryIdsDraftChange } = this.props;
|
||||||
onNameDraftChange?.(this.state.name);
|
onNameDraftChange?.(this.state.name);
|
||||||
|
onSeoDraftChange?.(this.state.seo);
|
||||||
onCategoryIdsDraftChange?.(this.state.categoryIds);
|
onCategoryIdsDraftChange?.(this.state.categoryIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,22 +257,35 @@ class NameEdit extends Component {
|
|||||||
this.props.onNameDraftChange?.(name);
|
this.props.onNameDraftChange?.(name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleSeoChange = (seo) => {
|
||||||
|
this.setState({ seo });
|
||||||
|
this.props.onSeoDraftChange?.(seo);
|
||||||
|
};
|
||||||
|
|
||||||
handleCategoryIdsChange = (categoryIds) => {
|
handleCategoryIdsChange = (categoryIds) => {
|
||||||
this.setState({ categoryIds });
|
this.setState({ categoryIds });
|
||||||
this.props.onCategoryIdsDraftChange?.(categoryIds);
|
this.props.onCategoryIdsDraftChange?.(categoryIds);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { name, categoryIds } = this.state;
|
const { name, seo, categoryIds } = this.state;
|
||||||
return (
|
return (
|
||||||
<Box sx={columnSx}>
|
<Box sx={columnSx}>
|
||||||
<Box sx={{ flex: 1, display: 'flex', alignItems: 'center' }}>
|
<Box sx={{ flex: 1, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
|
||||||
<SingleLineTextEdit
|
<SingleLineTextEdit
|
||||||
label="Name"
|
label="Name"
|
||||||
value={name}
|
value={name}
|
||||||
onChange={this.handleNameChange}
|
onChange={this.handleNameChange}
|
||||||
sx={articleNameFieldSx}
|
sx={articleNameFieldSx}
|
||||||
/>
|
/>
|
||||||
|
<Box sx={{ mt: 1 }}>
|
||||||
|
<SingleLineTextEdit
|
||||||
|
label="SEO"
|
||||||
|
value={seo}
|
||||||
|
size="small"
|
||||||
|
onChange={this.handleSeoChange}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<CategoryPills
|
<CategoryPills
|
||||||
categoryIds={categoryIds}
|
categoryIds={categoryIds}
|
||||||
@@ -279,6 +302,7 @@ export default class ArticleViewName extends PureComponent {
|
|||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
nameDraft: null,
|
nameDraft: null,
|
||||||
|
seoDraft: null,
|
||||||
categoryIdsDraft: null,
|
categoryIdsDraft: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -287,23 +311,33 @@ export default class ArticleViewName extends PureComponent {
|
|||||||
this.setState({ nameDraft: name });
|
this.setState({ nameDraft: name });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleSeoDraftChange = (seo) => {
|
||||||
|
this.setState({ seoDraft: seo });
|
||||||
|
};
|
||||||
|
|
||||||
handleCategoryIdsDraftChange = (categoryIds) => {
|
handleCategoryIdsDraftChange = (categoryIds) => {
|
||||||
this.setState({ categoryIdsDraft: categoryIds });
|
this.setState({ categoryIdsDraft: categoryIds });
|
||||||
};
|
};
|
||||||
|
|
||||||
handleSave = async () => {
|
handleSave = async () => {
|
||||||
const { article: articleData, onArticleUpdated } = this.props;
|
const { article: articleData, onArticleUpdated } = this.props;
|
||||||
const { nameDraft, categoryIdsDraft } = this.state;
|
const { nameDraft, seoDraft, categoryIdsDraft } = this.state;
|
||||||
const name = nameDraft.trim();
|
const name = nameDraft != null ? nameDraft.trim() : String(articleData.name ?? '').trim();
|
||||||
const categoryIds = categoryIdsDraft;
|
const seo = seoDraft != null ? seoDraft.trim() : String(articleData.seo ?? articleData.seoDescription ?? '').trim();
|
||||||
|
const categoryIds = categoryIdsDraft ?? (articleData.categoryIds ?? []);
|
||||||
|
|
||||||
const nameChanged = name !== String(articleData.name ?? '').trim();
|
const nameChanged = name !== String(articleData.name ?? '').trim();
|
||||||
|
const seoChanged = seo !== String(articleData.seo ?? articleData.seoDescription ?? '').trim();
|
||||||
const categoriesChanged = categoryIdsChanged(categoryIds, articleData.categoryIds);
|
const categoriesChanged = categoryIdsChanged(categoryIds, articleData.categoryIds);
|
||||||
|
|
||||||
let article = null;
|
let article = null;
|
||||||
|
|
||||||
if (nameChanged) {
|
if (nameChanged || seoChanged) {
|
||||||
const nameRes = await artikelAutomat.actions.update(articleData.sku, { name });
|
const updateBody = {};
|
||||||
article = nameRes.article;
|
if (nameChanged) updateBody.name = name;
|
||||||
|
if (seoChanged) updateBody.seo = seo;
|
||||||
|
const res = await artikelAutomat.actions.update(articleData.sku, updateBody);
|
||||||
|
article = res.article;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (categoriesChanged) {
|
if (categoriesChanged) {
|
||||||
@@ -312,17 +346,26 @@ export default class ArticleViewName extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (article) onArticleUpdated?.(article);
|
if (article) onArticleUpdated?.(article);
|
||||||
this.setState({ nameDraft: null, categoryIdsDraft: null });
|
this.setState({ nameDraft: null, seoDraft: null, categoryIdsDraft: null });
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { article: articleData } = this.props;
|
const { article: articleData } = this.props;
|
||||||
const { nameDraft, categoryIdsDraft } = this.state;
|
const { nameDraft, seoDraft, categoryIdsDraft } = this.state;
|
||||||
const savedCategoryIds = articleData.categoryIds ?? [];
|
const savedCategoryIds = articleData.categoryIds ?? [];
|
||||||
const value = { name: articleData.name ?? '', categoryIds: [...savedCategoryIds] };
|
const savedSeo = articleData.seo ?? articleData.seoDescription ?? '';
|
||||||
|
const value = {
|
||||||
|
name: articleData.name ?? '',
|
||||||
|
seo: savedSeo,
|
||||||
|
categoryIds: [...savedCategoryIds],
|
||||||
|
};
|
||||||
const draft =
|
const draft =
|
||||||
nameDraft != null && categoryIdsDraft != null
|
nameDraft != null && categoryIdsDraft != null
|
||||||
? { name: nameDraft, categoryIds: categoryIdsDraft }
|
? {
|
||||||
|
name: nameDraft,
|
||||||
|
seo: seoDraft ?? savedSeo,
|
||||||
|
categoryIds: categoryIdsDraft,
|
||||||
|
}
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -339,14 +382,17 @@ export default class ArticleViewName extends PureComponent {
|
|||||||
display={
|
display={
|
||||||
<NameDisplay
|
<NameDisplay
|
||||||
name={value.name}
|
name={value.name}
|
||||||
|
seo={value.seo}
|
||||||
categoryIds={value.categoryIds}
|
categoryIds={value.categoryIds}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
edit={
|
edit={
|
||||||
<NameEdit
|
<NameEdit
|
||||||
name={value.name}
|
name={value.name}
|
||||||
|
seo={value.seo}
|
||||||
categoryIds={value.categoryIds}
|
categoryIds={value.categoryIds}
|
||||||
onNameDraftChange={this.handleNameDraftChange}
|
onNameDraftChange={this.handleNameDraftChange}
|
||||||
|
onSeoDraftChange={this.handleSeoDraftChange}
|
||||||
onCategoryIdsDraftChange={this.handleCategoryIdsDraftChange}
|
onCategoryIdsDraftChange={this.handleCategoryIdsDraftChange}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,10 @@
|
|||||||
import { Component } from 'react';
|
import { Component } from 'react';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import Typography from '@mui/material/Typography';
|
|
||||||
|
|
||||||
function PanelValue({ label, children }) {
|
function PanelHtmlValue({ html }) {
|
||||||
if (children == null || children === '') return null;
|
|
||||||
return (
|
|
||||||
<Box sx={{ mb: 1 }}>
|
|
||||||
{label ? (
|
|
||||||
<Typography variant="caption" color="text.secondary" display="block">
|
|
||||||
{label}
|
|
||||||
</Typography>
|
|
||||||
) : null}
|
|
||||||
<Typography variant="body2" component="div">
|
|
||||||
{children}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function PanelHtmlValue({ label, html }) {
|
|
||||||
if (html == null || html === '') return null;
|
if (html == null || html === '') return null;
|
||||||
return (
|
return (
|
||||||
<Box sx={{ mb: 1.5 }}>
|
<Box sx={{ mb: 1.5 }}>
|
||||||
{label ? (
|
|
||||||
<Typography
|
|
||||||
variant="caption"
|
|
||||||
color="text.secondary"
|
|
||||||
display="block"
|
|
||||||
sx={{ mb: 0.5, fontWeight: 500 }}
|
|
||||||
>
|
|
||||||
{label}
|
|
||||||
</Typography>
|
|
||||||
) : null}
|
|
||||||
<Box
|
<Box
|
||||||
sx={(theme) => ({
|
sx={(theme) => ({
|
||||||
p: 1.5,
|
p: 1.5,
|
||||||
@@ -83,14 +56,7 @@ function PanelHtmlValue({ label, html }) {
|
|||||||
export default class ArticleSeoTab extends Component {
|
export default class ArticleSeoTab extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { article: articleData } = this.props;
|
const { article: articleData } = this.props;
|
||||||
const seo = articleData.seo ?? articleData.seoDescription;
|
|
||||||
const desc = articleData.desc ?? articleData.description;
|
const desc = articleData.desc ?? articleData.description;
|
||||||
return (
|
return <PanelHtmlValue html={desc} />;
|
||||||
<>
|
|
||||||
<PanelValue label="Slug">{articleData.slug}</PanelValue>
|
|
||||||
<PanelValue label="SEO">{seo}</PanelValue>
|
|
||||||
<PanelHtmlValue label="Beschreibung" html={desc} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user