Add category rename and drag-and-drop reordering in edit mode
- Edit toggle behind the "Kategorien" title enables an edit mode. - In edit mode all category tiles become inline rename fields (no outline, distinct background, small margins); articles and "new article" are hidden. - Rename via PATCH /api/category/:id; reorder via PUT /api/category/order (parentId + categoryIds) with SortableJS. - Only call backend when order actually changed; revert DOM order on error so further dragging keeps working. - Redux: renameCategory + reorderCategories thunks, renameMode state.
This commit is contained in:
@@ -168,6 +168,27 @@ export const renameCategory = createAsyncThunk(
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* Reorder sibling categories (new order of children under the current parent).
|
||||
* `PUT /api/category/order` → 200 { categoryIds: number[] }
|
||||
*/
|
||||
export const reorderCategories = createAsyncThunk(
|
||||
'category/reorder',
|
||||
async ({ categoryIds }, { rejectWithValue, getState }) => {
|
||||
try {
|
||||
const ids = requireArray(categoryIds, 'categoryIds');
|
||||
const parentId = getState().category.currentCategoryId;
|
||||
requireDefined(parentId, 'currentCategoryId');
|
||||
const data = await category.reorder(parentId, ids);
|
||||
requireObject(data, 'PUT /api/category/order');
|
||||
requireArray(data.categoryIds, 'categoryIds');
|
||||
return { parentId, categoryIds: requireArray(data.categoryIds, 'categoryIds') };
|
||||
} catch (err) {
|
||||
return catchBackendError(rejectWithValue)(err);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
export const deleteCategory = createAsyncThunk(
|
||||
'category/delete',
|
||||
async (categoryId, { rejectWithValue }) => {
|
||||
@@ -309,6 +330,26 @@ const categorySlice = createSlice({
|
||||
: row,
|
||||
);
|
||||
})
|
||||
.addCase(reorderCategories.fulfilled, (state, action) => {
|
||||
const { parentId, categoryIds } = action.payload;
|
||||
if (!state.categories) return;
|
||||
const parentKey = String(parentId);
|
||||
const idToSort = new Map(
|
||||
categoryIds.map((id, index) => [String(id), index]),
|
||||
);
|
||||
for (const node of Object.values(state.categories)) {
|
||||
if (
|
||||
node.parentId != null &&
|
||||
String(node.parentId) === parentKey &&
|
||||
idToSort.has(String(node.id))
|
||||
) {
|
||||
state.categories[String(node.id)] = {
|
||||
...node,
|
||||
sort: idToSort.get(String(node.id)),
|
||||
};
|
||||
}
|
||||
}
|
||||
})
|
||||
.addCase(createArticle.fulfilled, (state, action) => {
|
||||
const created = action.payload;
|
||||
if (created == null) return;
|
||||
|
||||
Reference in New Issue
Block a user