diff --git a/src/automats/deliveryEditorAutomat.js b/src/automats/deliveryEditorAutomat.js
index ff4621e..71914c9 100644
--- a/src/automats/deliveryEditorAutomat.js
+++ b/src/automats/deliveryEditorAutomat.js
@@ -375,6 +375,24 @@ export function createDeliveryEditorAutomat(options = {}) {
automat.actions.removeLineitem(payload);
},
+ /**
+ * Moves a lineitem from one index to another.
+ * @param {number} fromIndex Source index.
+ * @param {number} toIndex Target index.
+ * @returns {void}
+ */
+ moveLineitem(fromIndex, toIndex) {
+ const currentLines = automat.state.lines ?? [];
+ if (fromIndex < 0 || fromIndex >= currentLines.length || toIndex < 0 || toIndex >= currentLines.length) return;
+ const nextLines = [...currentLines];
+ const [item] = nextLines.splice(fromIndex, 1);
+ nextLines.splice(toIndex, 0, item);
+ automat.setState({
+ lines: nextLines,
+ lineitems: nextLines,
+ });
+ },
+
/** Clears all lines from the editor. @returns {void} */
clearLineitems() {
automat.setState({
diff --git a/src/automats/manifestDraftAutomat.js b/src/automats/manifestDraftAutomat.js
index c5feea7..743f611 100644
--- a/src/automats/manifestDraftAutomat.js
+++ b/src/automats/manifestDraftAutomat.js
@@ -284,6 +284,17 @@ export function getManifestDirtyDetails(current, baseline) {
if (curLines.length !== baseLines.length) {
fields.lines = true;
+ } else {
+ for (let i = 0; i < curLines.length; i++) {
+ const cl = curLines[i];
+ const bl = baseLines[i];
+ const clIdentifier = cl?.key ?? (cl?.id != null ? `id-${cl.id}` : null);
+ const blIdentifier = bl?.key ?? (bl?.id != null ? `id-${bl.id}` : null);
+ if (clIdentifier && blIdentifier && clIdentifier !== blIdentifier) {
+ fields.lines = true;
+ break;
+ }
+ }
}
for (let i = 0; i < curLines.length; i++) {
diff --git a/src/components/manifest/ManifestForm.jsx b/src/components/manifest/ManifestForm.jsx
index fb0c8b9..fce6a22 100644
--- a/src/components/manifest/ManifestForm.jsx
+++ b/src/components/manifest/ManifestForm.jsx
@@ -96,6 +96,7 @@ class ManifestForm extends PureComponent {
this.handleCloseArticleSearch = this.handleCloseArticleSearch.bind(this);
this.handleAssignArticleForLine = this.handleAssignArticleForLine.bind(this);
this.handleRemoveLine = this.handleRemoveLine.bind(this);
+ this.handleMoveLine = this.handleMoveLine.bind(this);
this.handleRemoveAllLines = this.handleRemoveAllLines.bind(this);
this.handleSave = this.handleSave.bind(this);
this.handlePdfUpload = this.handlePdfUpload.bind(this);
@@ -701,6 +702,19 @@ class ManifestForm extends PureComponent {
});
}
+ handleMoveLine(key, delta) {
+ this.setState((prev) => {
+ const fromIndex = prev.lines.findIndex((l) => l.key === key);
+ if (fromIndex < 0) return null;
+ const toIndex = fromIndex + delta;
+ if (toIndex < 0 || toIndex >= prev.lines.length) return null;
+ const next = [...prev.lines];
+ const [item] = next.splice(fromIndex, 1);
+ next.splice(toIndex, 0, item);
+ return { lines: next, isDirty: true };
+ });
+ }
+
handleRemoveAllLines() {
this.setState({ lines: [] });
}
@@ -998,6 +1012,7 @@ class ManifestForm extends PureComponent {
onAddArticleLine={this.handleAddArticleLine}
onSearchArticle={this.handleOpenArticleSearchForLine}
onRemoveLine={this.handleRemoveLine}
+ onMoveLine={this.handleMoveLine}
onRemoveAllLines={this.handleRemoveAllLines}
onSave={() => void this.handleSave()}
/>
diff --git a/src/components/manifest/ManifestFormLine.jsx b/src/components/manifest/ManifestFormLine.jsx
index 57fee87..decb278 100644
--- a/src/components/manifest/ManifestFormLine.jsx
+++ b/src/components/manifest/ManifestFormLine.jsx
@@ -11,6 +11,8 @@ import TextField from '@mui/material/TextField';
import Tooltip from '@mui/material/Tooltip';
import Typography from '@mui/material/Typography';
import DeleteOutlinedIcon from '@mui/icons-material/DeleteOutlined';
+import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
+import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
import HelpOutlineIcon from '@mui/icons-material/HelpOutlineOutlined';
import Inventory2OutlinedIcon from '@mui/icons-material/Inventory2Outlined';
import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined';
@@ -40,6 +42,8 @@ class ManifestFormLine extends PureComponent {
fallbackSuppliers: [],
};
this.handleRemove = this.handleRemove.bind(this);
+ this.handleMoveUp = this.handleMoveUp.bind(this);
+ this.handleMoveDown = this.handleMoveDown.bind(this);
this.handleBlur = this.handleBlur.bind(this);
this.handleCreateArticle = this.handleCreateArticle.bind(this);
this.handleSearchArticle = this.handleSearchArticle.bind(this);
@@ -121,6 +125,14 @@ class ManifestFormLine extends PureComponent {
this.props.onRemove(this.props.line.key);
}
+ handleMoveUp() {
+ this.props.onMove?.(this.props.line.key, -1);
+ }
+
+ handleMoveDown() {
+ this.props.onMove?.(this.props.line.key, 1);
+ }
+
handleBlur(e, columnId) {
if (columnId === 'sku' && this.props.onSkuBlur) {
this.props.onSkuBlur(this.props.line.key, e.target.value);
@@ -971,15 +983,62 @@ class ManifestFormLine extends PureComponent {
{this.renderField(col, colIdx, columns.length)}
))}
-
-
-
-
+
+
+ {this.props.onMove && (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )}
+
+
+
+
+
+
+
+
diff --git a/src/components/manifest/ManifestLines.jsx b/src/components/manifest/ManifestLines.jsx
index c13c42d..7b2c1a2 100644
--- a/src/components/manifest/ManifestLines.jsx
+++ b/src/components/manifest/ManifestLines.jsx
@@ -28,6 +28,7 @@ class ManifestLines extends PureComponent {
onLineChange,
onAddLine,
onRemoveLine,
+ onMoveLine,
onRemoveAllLines,
columns = LINE_COLUMNS,
supplierArticlesMap = {},
@@ -98,7 +99,7 @@ class ManifestLines extends PureComponent {
{col.label}
))}
-
+
@@ -138,6 +139,9 @@ class ManifestLines extends PureComponent {
supplierArticleBusy={Boolean(busySupplierArticleLineKeys[lineKey])}
onChange={onLineChange}
onRemove={onRemoveLine}
+ onMove={onMoveLine}
+ isFirstLine={index === 0}
+ isLastLine={index === lines.length - 1}
onSkuBlur={onSkuBlur}
onCreateArticle={onCreateArticle}
onSearchArticle={onSearchArticle}
diff --git a/src/routes/lieferung/neu.jsx b/src/routes/lieferung/neu.jsx
index f5d7a41..535aa03 100644
--- a/src/routes/lieferung/neu.jsx
+++ b/src/routes/lieferung/neu.jsx
@@ -99,6 +99,7 @@ class LieferungNeuPage extends PureComponent {
this.handleAddLine = this.handleAddLine.bind(this);
this.handleAddArticleLine = this.handleAddArticleLine.bind(this);
this.handleRemoveLine = this.handleRemoveLine.bind(this);
+ this.handleMoveLine = this.handleMoveLine.bind(this);
this.handleRemoveAllLines = this.handleRemoveAllLines.bind(this);
this.handleSave = this.handleSave.bind(this);
this.handlePdfUpload = this.handlePdfUpload.bind(this);
@@ -541,6 +542,13 @@ class LieferungNeuPage extends PureComponent {
this.automat.actions.removeLineitem(index >= 0 ? index : key);
}
+ handleMoveLine(key, delta) {
+ const fromIndex = this.findLineIndex(key);
+ if (fromIndex < 0) return;
+ const toIndex = fromIndex + delta;
+ this.automat.actions.moveLineitem(fromIndex, toIndex);
+ }
+
handleRemoveAllLines() {
this.automat.actions.clearLineitems();
}
@@ -1340,6 +1348,7 @@ class LieferungNeuPage extends PureComponent {
onAddLine={this.handleAddLine}
onAddArticleLine={this.handleAddArticleLine}
onRemoveLine={this.handleRemoveLine}
+ onMoveLine={this.handleMoveLine}
onRemoveAllLines={this.handleRemoveAllLines}
onSave={() => void this.handleSave()}
onCreateArticle={this.handleCreateArticleForLine}