This commit is contained in:
seb
2026-07-31 09:09:34 +02:00
parent 84a7c6f7ef
commit 818d799f63
6 changed files with 21 additions and 38 deletions

View File

@@ -120,8 +120,7 @@ Backend mapping:
| Method | Signature | Returns |
| --- | --- | --- |
| `createUnderParent` | `({ googleAuthId, parentId, name })` | `{ id, parentId, sort, name }` |
| `updateParentId` | `(id, parentId)` | `void` |
| `delete` | `(id)` | `void` — blocked by FK if `categoryarticle` (or child categories) still reference it |
| `delete` | `({ googleAuthId, id })` | `void` — blocked by FK if `categoryarticle` or child categories remain |
| `getTreeForCompany` | `(googleAuthId, companyId)` | `{ languageId, tree, articles }` |
### `createUnderParent` (transaction)
@@ -131,6 +130,8 @@ Backend mapping:
3. `companyuser` for `(googleAuthId, companyId)`, else `Not authorized`
4. Insert `category` (next sibling `sort`) + `categorytext` (`name`, slugified `slug`, company default language)
All category mutations use `resolveCategoryAccess(googleAuthId, categoryId)` internally. Root category cannot be deleted.
`getTreeForCompany` throws `Not authorized` if `googleAuthId` is not a `companyuser` of `companyId`, and `Company not found` if the company is missing, has no `root_category_id`, or no `default_language_id`.
---
@@ -146,6 +147,7 @@ Backend mapping:
| `PUT /api/auth/selected-company` | `google_auth.setSelectedCompany(googleAuthId, companyId)` |
| `GET /api/category/tree?companyId=` | `category.getTreeForCompany(googleAuthId, companyId)` |
| `POST /api/category` | `category.createUnderParent({ googleAuthId, parentId, name })` |
| `DELETE /api/category/:id` | `category.delete({ googleAuthId, id })` |
---

View File

@@ -96,8 +96,7 @@ const MENU = {
label: 'category',
items: [
{ value: 'category.createUnderParent', label: 'createUnderParent', hint: 'googleAuthId, parentId, name → row' },
{ value: 'category.updateParentId', label: 'updateParentId', hint: 'id, parentId' },
{ value: 'category.delete', label: 'delete', hint: 'id' },
{ value: 'category.delete', label: 'delete', hint: 'googleAuthId, id' },
{ value: 'category.getTreeForCompany', label: 'getTreeForCompany', hint: 'googleAuthId, companyId → rows' },
],
},
@@ -320,23 +319,15 @@ async function runMethod(client, action) {
}),
];
}
case 'category.updateParentId': {
const id = await askInt('Category id');
if (id == null) return;
const parentRaw = await askText('parentId (null as empty)', {
placeholder: '',
validate: (v) =>
v?.trim() && !/^\d+$/.test(v.trim()) ? 'Integer or empty' : undefined,
});
if (parentRaw == null) return;
const parentId = parentRaw === '' ? null : Number(parentRaw);
await client.category.updateParentId(Number(id), parentId);
return ['ok', true];
}
case 'category.delete': {
const googleAuthId = await askInt('google_auth id');
if (googleAuthId == null) return;
const id = await askInt('Category id');
if (id == null) return;
await client.category.delete(Number(id));
await client.category.delete({
googleAuthId: Number(googleAuthId),
id: Number(id),
});
return ['ok', true];
}
case 'category.getTreeForCompany': {

View File

@@ -7,7 +7,6 @@ import companyDelete from './store/company/delete.js';
import companyList from './store/company/list.js';
import categoryGetTreeForCompany from './store/category/getTreeForCompany.js';
import categoryCreateUnderParent from './store/category/createUnderParent.js';
import categoryUpdateParentId from './store/category/updateParentId.js';
import categoryDelete from './store/category/delete.js';
import langCreate from './store/lang/create.js';
import langDelete from './store/lang/delete.js';
@@ -46,7 +45,6 @@ export default class LibDashStore {
this.category = {
getTreeForCompany: categoryGetTreeForCompany(pool),
createUnderParent: categoryCreateUnderParent(pool),
updateParentId: categoryUpdateParentId(pool),
delete: categoryDelete(pool),
};

View File

@@ -126,12 +126,6 @@ FROM category
WHERE parent_id = @parentId
`;
export const UPDATE_PARENT_ID = `
UPDATE category
SET parent_id = @parentId
WHERE id = @id
`;
export const DELETE = `
DELETE FROM category
WHERE id = @id

View File

@@ -1,7 +1,16 @@
import { DELETE } from '../../sql/category.js';
import resolveCategoryAccess from './resolveCategoryAccess.js';
export default function del(pool) {
return async (id) => {
const access = resolveCategoryAccess(pool);
return async ({ googleAuthId, id }) => {
const { rootCategoryId } = await access(googleAuthId, id);
if (id === rootCategoryId) {
throw new Error('Cannot delete root category');
}
await pool.request().input('id', id).query(DELETE);
};
}

View File

@@ -1,11 +0,0 @@
import { UPDATE_PARENT_ID } from '../../sql/category.js';
export default function updateParentId(pool) {
return async (id, parentId) => {
await pool
.request()
.input('id', id)
.input('parentId', parentId)
.query(UPDATE_PARENT_ID);
};
}