Some checks failed
CD / Deploy to Test (push) Blocked by required conditions
CD / Smoke tests against Test (push) Blocked by required conditions
CD / Promote to Int (push) Blocked by required conditions
CI / Auth e2e pack (push) Blocked by required conditions
CI / Import/export fidelity gate (push) Blocked by required conditions
CI / Build container images (push) Blocked by required conditions
CD / Build and push images (push) Has been cancelled
CI / Lint, typecheck, test (push) Has been cancelled
The sidebar now presents pages as a collapsible tree built from parentId (folder view) or grouped under the hierarchical label tree (label view, read-only; multi-label pages appear under each label, untagged ones in an 'unlabeled' group). The pond owner sets the default via a new sidebarView pond setting (PATCH-merged like the other keys); every user can override it locally (ui.sidebar.view.<pondId>), and the toggle sits above the page list. Collapse state persists per pond. New pages created while a page is open become its children — the inline form says so and sends parentId. Reordering (buttons and drag-between) now operates within one sibling group; the label filter stays a folder-view feature and falls back to the flat list while active, so the filtered order is never mistaken for a partial tree. SidebarContent is keyed by pond id so the per-pond localStorage hooks mount with the right key. e2e hooks (.sidebar__pages, .sidebar__page, reorder buttons) kept; reorder/labels/content packs green locally, plus a live smoke of nesting, collapse persistence, and both views. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
62 lines
1.9 KiB
TypeScript
62 lines
1.9 KiB
TypeScript
import type { SidebarViewMode } from '@dorfteich/shared';
|
|
import { SIDEBAR_VIEW_MODES } from '@dorfteich/shared';
|
|
import { useQueryClient } from '@tanstack/react-query';
|
|
import { useState } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
import { FormError, FormSuccess } from '../components/forms';
|
|
import { apiPatch } from '../lib/api';
|
|
|
|
/**
|
|
* The pond's default sidebar view (issue #108): folders (page tree) or
|
|
* labels. Owner-set; every member can still override it locally via the
|
|
* sidebar toggle. Rides the generic pond PATCH like CommentPolicySetting.
|
|
*/
|
|
export function SidebarViewSetting({
|
|
pondId,
|
|
pondSlug,
|
|
value,
|
|
}: {
|
|
pondId: string;
|
|
pondSlug: string;
|
|
value: SidebarViewMode;
|
|
}): React.JSX.Element {
|
|
const { t } = useTranslation();
|
|
const queryClient = useQueryClient();
|
|
const [error, setError] = useState<unknown>(null);
|
|
const [saved, setSaved] = useState(false);
|
|
|
|
const save = async (view: SidebarViewMode): Promise<void> => {
|
|
setError(null);
|
|
setSaved(false);
|
|
try {
|
|
await apiPatch(`/ponds/${pondId}`, { sidebarView: view });
|
|
await queryClient.invalidateQueries({ queryKey: ['pond', pondSlug] });
|
|
setSaved(true);
|
|
} catch (err) {
|
|
setError(err);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="sidebar-view-setting">
|
|
<FormError error={error} />
|
|
<p className="sidebar-view-setting__hint">{t('layout.sidebar.view.defaultHint')}</p>
|
|
<label>
|
|
{t('layout.sidebar.view.defaultLabel')}{' '}
|
|
<select
|
|
value={value}
|
|
onChange={(event) => void save(event.target.value as SidebarViewMode)}
|
|
>
|
|
{SIDEBAR_VIEW_MODES.map((mode) => (
|
|
<option key={mode} value={mode}>
|
|
{t(`layout.sidebar.view.${mode}`)}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</label>
|
|
{saved && <FormSuccess message={t('layout.sidebar.view.saved')} />}
|
|
</div>
|
|
);
|
|
}
|