Some checks failed
Deploy Nyla Frontend to Integration / deploy (push) Failing after 52s
182 lines
6 KiB
TypeScript
182 lines
6 KiB
TypeScript
// Copyright (c) 2026 PowerOn AG
|
|
// All rights reserved.
|
|
/**
|
|
* FeatureView Page
|
|
*
|
|
* Generische Feature-View-Komponente.
|
|
* Rendert den entsprechenden Content basierend auf Feature-Code und View.
|
|
*/
|
|
|
|
import React from 'react';
|
|
import { useLocation } from 'react-router-dom';
|
|
import { hideFeatureOutlet } from '../config/keepAliveRoutes';
|
|
import { useCurrentInstance } from '../hooks/useCurrentInstance';
|
|
import { useCanViewFeatureView } from '../hooks/useInstancePermissions';
|
|
// Trustee Views
|
|
// Note: TrusteeOrganisationsView and TrusteeContractsView removed - Feature-Instanz = Organisation
|
|
// Note: TrusteePositionsView/TrusteeDocumentsView are no longer mounted directly here -
|
|
// they live as tabs inside TrusteeDataTablesView (and that file imports them).
|
|
import { TrusteeDashboardView } from './views/trustee/TrusteeDashboardView';
|
|
import { TrusteeInstanceRolesView } from './views/trustee/TrusteeInstanceRolesView';
|
|
import { TrusteeImportProcessView } from './views/trustee/TrusteeImportProcessView';
|
|
import { TrusteeAccountingSettingsView } from './views/trustee/TrusteeAccountingSettingsView';
|
|
import { TrusteeAnalyseView } from './views/trustee/TrusteeAnalyseView';
|
|
import { TrusteeAbschlussView } from './views/trustee/TrusteeAbschlussView';
|
|
import { TrusteeDataTablesView } from './views/trustee/TrusteeDataTablesView';
|
|
|
|
// RealEstate Views
|
|
import { RealEstatePekView, RealEstateInstanceRolesPlaceholder } from './views/realestate';
|
|
|
|
// Workspace Views
|
|
import { WorkspacePage } from './views/workspace/WorkspacePage';
|
|
import { WorkspaceEditorPage } from './views/workspace/WorkspaceEditorPage';
|
|
import { WorkspaceSettingsPage } from './views/workspace/WorkspaceSettingsPage';
|
|
|
|
// Teamsbot Views
|
|
import { TeamsbotDashboardView } from './views/teamsbot/TeamsbotDashboardView';
|
|
import { TeamsbotAssistantView } from './views/teamsbot/TeamsbotAssistantView';
|
|
import { TeamsbotModulesView } from './views/teamsbot/TeamsbotModulesView';
|
|
import { TeamsbotSessionView } from './views/teamsbot/TeamsbotSessionView';
|
|
import { TeamsbotSettingsView } from './views/teamsbot/TeamsbotSettingsView';
|
|
|
|
// Neutralization Views
|
|
import { NeutralizationView } from './views/neutralization';
|
|
|
|
// CommCoach Views
|
|
import { CommcoachDashboardView, CommcoachAssistantView, CommcoachModulesView, CommcoachSessionView, CommcoachSettingsView } from './views/commcoach';
|
|
|
|
// Redmine Views
|
|
import { RedmineSettingsView, RedmineStatsView, RedmineBrowserView } from './views/redmine';
|
|
|
|
import styles from './FeatureView.module.css';
|
|
|
|
import { useLanguage } from '../providers/language/LanguageContext';
|
|
|
|
// Generic/Fallback
|
|
const NotFound: React.FC = () => {
|
|
const { t } = useLanguage();
|
|
return (
|
|
<div className={styles.notFound}>
|
|
<h2>{t('Seite nicht gefunden')}</h2>
|
|
<p>{t('Diese Ansicht existiert nicht oder')}</p>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const AccessDenied: React.FC = () => {
|
|
const { t } = useLanguage();
|
|
return (
|
|
<div className={styles.accessDenied}>
|
|
<h2>{t('Zugriff verweigert')}</h2>
|
|
<p>{t('Du hast keine Berechtigung für')}</p>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
// =============================================================================
|
|
// VIEW REGISTRY
|
|
// =============================================================================
|
|
|
|
type ViewComponent = React.FC;
|
|
|
|
const VIEW_COMPONENTS: Record<string, Record<string, ViewComponent>> = {
|
|
trustee: {
|
|
dashboard: TrusteeDashboardView,
|
|
'data-tables': TrusteeDataTablesView,
|
|
'instance-roles': TrusteeInstanceRolesView,
|
|
'import-process': TrusteeImportProcessView,
|
|
settings: TrusteeAccountingSettingsView,
|
|
analyse: TrusteeAnalyseView,
|
|
abschluss: TrusteeAbschlussView,
|
|
},
|
|
realestate: {
|
|
dashboard: RealEstatePekView,
|
|
'instance-roles': RealEstateInstanceRolesPlaceholder,
|
|
},
|
|
workspace: {
|
|
dashboard: WorkspacePage,
|
|
editor: WorkspaceEditorPage,
|
|
settings: WorkspaceSettingsPage,
|
|
},
|
|
teamsbot: {
|
|
dashboard: TeamsbotDashboardView,
|
|
assistant: TeamsbotAssistantView,
|
|
modules: TeamsbotModulesView,
|
|
sessions: TeamsbotSessionView,
|
|
settings: TeamsbotSettingsView,
|
|
},
|
|
neutralization: {
|
|
dashboard: NeutralizationView,
|
|
playground: NeutralizationView,
|
|
},
|
|
commcoach: {
|
|
dashboard: CommcoachDashboardView,
|
|
assistant: CommcoachAssistantView,
|
|
modules: CommcoachModulesView,
|
|
session: CommcoachSessionView,
|
|
settings: CommcoachSettingsView,
|
|
},
|
|
redmine: {
|
|
stats: RedmineStatsView,
|
|
browser: RedmineBrowserView,
|
|
settings: RedmineSettingsView,
|
|
},
|
|
};
|
|
|
|
// =============================================================================
|
|
// FEATURE VIEW PAGE
|
|
// =============================================================================
|
|
|
|
interface FeatureViewPageProps {
|
|
view: string;
|
|
}
|
|
|
|
export const FeatureViewPage: React.FC<FeatureViewPageProps> = ({ view }) => {
|
|
const location = useLocation();
|
|
const { instance, featureCode, isValid } = useCurrentInstance();
|
|
|
|
// Berechtigungs-Check
|
|
const viewCode = `${featureCode}-${view}`;
|
|
const canView = useCanViewFeatureView(viewCode);
|
|
|
|
// Nicht valider Kontext
|
|
if (!isValid || !featureCode || !instance) {
|
|
return <NotFound />;
|
|
}
|
|
|
|
// Keine Berechtigung
|
|
if (!canView && view !== 'not-found') {
|
|
return <AccessDenied />;
|
|
}
|
|
|
|
// Workspace dashboard is rendered persistently by WorkspaceKeepAlive at MainLayout level;
|
|
// other workspace views (e.g. settings, editor) use the standard FeatureViewPage rendering.
|
|
if (featureCode === 'workspace' && view !== 'settings' && view !== 'editor') {
|
|
return null;
|
|
}
|
|
|
|
// Feature outlet is hidden for paths configured in KEEP_ALIVE_ROUTES (rendered in MainLayout).
|
|
// Add new persistent workspace URLs there if needed.
|
|
if (hideFeatureOutlet(location.pathname, location.search)) {
|
|
return null;
|
|
}
|
|
|
|
// View-Komponente finden
|
|
const featureViews = VIEW_COMPONENTS[featureCode];
|
|
if (!featureViews) {
|
|
return <NotFound />;
|
|
}
|
|
|
|
const ViewComponent = featureViews[view];
|
|
if (!ViewComponent) {
|
|
return <NotFound />;
|
|
}
|
|
|
|
return (
|
|
<div className={styles.featureView}>
|
|
<ViewComponent />
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default FeatureViewPage;
|