new features

This commit is contained in:
Matthias Hochmeister
2026-03-23 18:08:49 +01:00
parent e720c52896
commit 202a658b8d
4 changed files with 28 additions and 11 deletions

View File

@@ -36,12 +36,26 @@ INSERT INTO permissions (id, feature_group_id, label, description, sort_order) V
('admin:write', 'admin', 'Bearbeiten', 'Admin-Einstellungen ändern', 2) ('admin:write', 'admin', 'Bearbeiten', 'Admin-Einstellungen ändern', 2)
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
-- Re-seed wissen grants for all groups (in case they were cascade-deleted) -- Re-seed wissen + vikunja + dashboard grants for all dashboard groups
INSERT INTO group_permissions (authentik_group, permission_id) -- (these may have been cascade-deleted when feature groups were missing)
SELECT DISTINCT authentik_group, 'wissen:view' DO $$
FROM group_permissions DECLARE
WHERE authentik_group LIKE 'dashboard_%' grp TEXT;
ON CONFLICT DO NOTHING; BEGIN
FOR grp IN
SELECT DISTINCT authentik_group FROM group_permissions WHERE authentik_group LIKE 'dashboard_%'
LOOP
-- wissen permissions for everyone
INSERT INTO group_permissions (authentik_group, permission_id)
VALUES (grp, 'wissen:view'), (grp, 'wissen:widget_recent'), (grp, 'wissen:widget_search')
ON CONFLICT DO NOTHING;
-- dashboard widget permissions for everyone
INSERT INTO group_permissions (authentik_group, permission_id)
VALUES (grp, 'dashboard:widget_links'), (grp, 'dashboard:widget_banner')
ON CONFLICT DO NOTHING;
END LOOP;
END $$;
-- ═══════════════════════════════════════════════════════════════════════════ -- ═══════════════════════════════════════════════════════════════════════════
-- 1. New permissions -- 1. New permissions

View File

@@ -79,7 +79,9 @@ const BookStackRecentWidget: React.FC = () => {
const configured = data?.configured ?? false; const configured = data?.configured ?? false;
const pages = (data?.data ?? []).slice(0, 5); const pages = (data?.data ?? []).slice(0, 5);
if (!configured) { // Only show "nicht eingerichtet" when we got a successful response with configured=false
// (not when the request errored out with 403 etc.)
if (data && !configured) {
return ( return (
<Card sx={{ height: '100%' }}> <Card sx={{ height: '100%' }}>
<CardContent> <CardContent>

View File

@@ -75,7 +75,7 @@ const BookStackSearchWidget: React.FC = () => {
return () => { isMountedRef.current = false; }; return () => { isMountedRef.current = false; };
}, []); }, []);
const { data, isLoading: configLoading } = useQuery({ const { data, isLoading: configLoading, isError: configError } = useQuery({
queryKey: ['bookstack-recent'], queryKey: ['bookstack-recent'],
queryFn: () => bookstackApi.getRecent(), queryFn: () => bookstackApi.getRecent(),
refetchInterval: 5 * 60 * 1000, refetchInterval: 5 * 60 * 1000,
@@ -83,7 +83,8 @@ const BookStackSearchWidget: React.FC = () => {
}); });
// undefined while loading, true/false once known // undefined while loading, true/false once known
const configured = configLoading ? undefined : (data?.configured ?? false); // On error (e.g. 403), treat as configured to avoid "nicht eingerichtet" message
const configured = configLoading ? undefined : configError ? true : (data?.configured ?? false);
useEffect(() => { useEffect(() => {
if (debounceRef.current) clearTimeout(debounceRef.current); if (debounceRef.current) clearTimeout(debounceRef.current);

View File

@@ -187,7 +187,7 @@ function Dashboard() {
{/* Dienste Group */} {/* Dienste Group */}
<WidgetGroup title="Dienste" gridColumn="1 / -1"> <WidgetGroup title="Dienste" gridColumn="1 / -1">
{hasPermission('wissen:widget_recent') && widgetVisible('bookstackRecent') && ( {hasPermission('wissen:view') && widgetVisible('bookstackRecent') && (
<Fade in={!dataLoading} timeout={600} style={{ transitionDelay: '600ms' }}> <Fade in={!dataLoading} timeout={600} style={{ transitionDelay: '600ms' }}>
<Box> <Box>
<BookStackRecentWidget /> <BookStackRecentWidget />
@@ -195,7 +195,7 @@ function Dashboard() {
</Fade> </Fade>
)} )}
{hasPermission('wissen:widget_search') && widgetVisible('bookstackSearch') && ( {hasPermission('wissen:view') && widgetVisible('bookstackSearch') && (
<Fade in={!dataLoading} timeout={600} style={{ transitionDelay: '640ms' }}> <Fade in={!dataLoading} timeout={600} style={{ transitionDelay: '640ms' }}>
<Box> <Box>
<BookStackSearchWidget /> <BookStackSearchWidget />