Skip to content

Commit

Permalink
Merge pull request #1007 from MTES-MCT/feat-add-analysis-dashboard
Browse files Browse the repository at this point in the history
Add analysis dashboard
  • Loading branch information
Falinor authored Dec 4, 2024
2 parents dfa5b32 + 60a4adf commit 98ae0af
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 34 deletions.
2 changes: 2 additions & 0 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import LoginView from './views/Login/LoginView';
import ForgottenPasswordView from './views/Account/ForgottenPasswordView';
import ResetPasswordView from './views/Account/ResetPasswordView';
import NotFoundView from './views/NotFoundView';
import AnalysisView from './views/Analysis/AnalysisView';

const router = createBrowserRouter(
createRoutesFromElements(
Expand All @@ -40,6 +41,7 @@ const router = createBrowserRouter(
path="/parc-de-logements/campagnes/:id"
element={<CampaignView />}
/>
<Route path="/analyses" element={<AnalysisView />} />
<Route path="/groupes/:id" element={<GroupView />} />
<Route path="/campagnes" element={<CampaignsListView />} />
<Route path="/campagnes/:id" element={<CampaignView />} />
Expand Down
8 changes: 1 addition & 7 deletions frontend/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { Header as DSFRHeader } from '@codegouvfr/react-dsfr/Header';
import { useMatomo } from '@jonkoops/matomo-tracker-react';
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import LoadingBar from 'react-redux-loading-bar';

Expand All @@ -17,15 +15,10 @@ import { Container } from '../_dsfr';
function Header() {
const location = useLocation();
const dispatch = useAppDispatch();
const { trackPageView } = useMatomo();
const { isAdmin, isVisitor, isAuthenticated } = useUser();

const { authUser } = useAppSelector((state) => state.authentication);

useEffect(() => {
trackPageView({});
}, [location]); //eslint-disable-line react-hooks/exhaustive-deps

function displayName(): string {
return authUser
? authUser.user.firstName && authUser.user.lastName
Expand Down Expand Up @@ -120,6 +113,7 @@ function Header() {
isAuthenticated
? [
getMainNavigationItem(UserNavItems.HousingList),
getMainNavigationItem(UserNavItems.Analysis),
getMainNavigationItem(UserNavItems.Campaign),
getMainNavigationItem(UserNavItems.Resources)
]
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/Header/SmallHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ function SmallHeader() {
isAuthenticated
? [
getMainNavigationItem(UserNavItems.HousingList),
getMainNavigationItem(UserNavItems.Analysis),
getMainNavigationItem(UserNavItems.Campaign),
getMainNavigationItem(UserNavItems.Resources)
]
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/models/UserNavItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export enum UserNavItems {
Campaign,
HousingList,
Resources,
Analysis
}

export interface UserNavItem {
Expand All @@ -17,6 +18,8 @@ export const getUserNavItem = (userNavItem: UserNavItems): UserNavItem => {
return { url: '/parc-de-logements', label: 'Parc de logements' };
case UserNavItems.Resources:
return { url: '/ressources', label: 'Ressources' };
case UserNavItems.Analysis:
return { url: '/analyses', label: 'Analyses' };
default:
return { url: '/', label: 'Accueil' };
}
Expand Down
15 changes: 5 additions & 10 deletions frontend/src/services/dashboard.service.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
import { DashboardDTO, Resource } from '@zerologementvacant/models';
import { zlvApi } from './api.service';

interface FindOneOptions {
id: Resource;
}

type Resource = '6-utilisateurs-de-zlv-sur-votre-structure' | '7-autres-structures-de-votre-territoires-inscrites-sur-zlv';

interface Dashboard {
url: string;
}

export const dashboardApi = zlvApi.injectEndpoints({
endpoints: (builder) => ({
findOneDashboard: builder.query<Dashboard, FindOneOptions>({
findOneDashboard: builder.query<DashboardDTO, FindOneOptions>({
query: (opts) => `dashboards/${opts.id}`,
providesTags: (result, error, arg) => [{ type: 'Stats', id: arg.id }],
}),
}),
providesTags: (result, error, arg) => [{ type: 'Stats', id: arg.id }]
})
})
});

export const { useFindOneDashboardQuery } = dashboardApi;
19 changes: 19 additions & 0 deletions frontend/src/views/Analysis/AnalysisView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useDocumentTitle } from '../../hooks/useDocumentTitle';
import MainContainer from '../../components/MainContainer/MainContainer';
import { useFindOneDashboardQuery } from '../../services/dashboard.service';

function AnalysisView() {
useDocumentTitle('Analyse');

const { data: dashboard } = useFindOneDashboardQuery({
id: '13-analyses'
});

return (
<MainContainer>
<iframe src={dashboard?.url} width="100%" height={600} title="Analyses" />
</MainContainer>
);
}

export default AnalysisView;
10 changes: 10 additions & 0 deletions packages/models/src/DashboardDTO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export interface DashboardDTO {
url: string;
}

export const RESOURCE_VALUES = [
'6-utilisateurs-de-zlv-sur-votre-structure',
'7-autres-structures-de-votre-territoires-inscrites-sur-zlv',
'13-analyses'
] as const;
export type Resource = (typeof RESOURCE_VALUES)[number];
1 change: 1 addition & 0 deletions packages/models/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export * from './CampaignCount';
export * from './CampaignDTO';
export * from './ContactPoint';
export * from './DraftDTO';
export * from './DashboardDTO';
export * from './DatafoncierHousing';
export * from './DatafoncierOwner';
export * from './EnergyConsumption';
Expand Down
34 changes: 21 additions & 13 deletions server/src/controllers/dashboardController.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,42 @@
import { Request, Response } from 'express';
import { AuthenticatedRequest } from 'express-jwt';
import { param, ValidationChain } from 'express-validator';
import { constants } from 'http2';
import jwt from 'jsonwebtoken';

import {
DashboardDTO,
Resource,
RESOURCE_VALUES
} from '@zerologementvacant/models';
import config from '~/infra/config';
import { param, ValidationChain } from 'express-validator';
import { createURL, getResource, Resource } from '~/models/DashboardApi';
import { createURL, getResource } from '~/models/DashboardApi';

async function findOne(request: Request, response: Response): Promise<void> {
const { auth, params } = request as AuthenticatedRequest;
async function findOne(
request: Request<{ id: Resource }>,
response: Response<DashboardDTO>
): Promise<void> {
const { auth, params } = request as AuthenticatedRequest<{ id: Resource }>;

const payload = {
resource: {
dashboard: getResource(params.id as Resource),
dashboard: getResource(params.id)
},
params: {
id: auth.establishmentId,
},
id: auth.establishmentId
}
};
const token = await sign(payload);
const dashboard = {
url: createURL({
domain: config.metabase.domain,
token,
}),
token
})
};
response.status(constants.HTTP_STATUS_OK).json(dashboard);
}
const findOneValidators: ValidationChain[] = [
param('id').isIn(['6-utilisateurs-de-zlv-sur-votre-structure', '7-autres-structures-de-votre-territoires-inscrites-sur-zlv']),
param('id').isIn(RESOURCE_VALUES)
];

function sign(payload: any): Promise<string> {
Expand All @@ -38,19 +46,19 @@ function sign(payload: any): Promise<string> {
config.metabase.token,
{
algorithm: 'HS256',
expiresIn: '10m',
expiresIn: '10m'
},
(err, token) => {
if (err) {
return reject(err);
}
return resolve(token ?? '');
},
}
);
});
}

export default {
findOne,
findOneValidators,
findOneValidators
};
8 changes: 4 additions & 4 deletions server/src/models/DashboardApi.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
export interface DashboardApi {
url: string;
}
import { Resource } from '@zerologementvacant/models';

export type Resource = '6-utilisateurs-de-zlv-sur-votre-structure' | '7-autres-structures-de-votre-territoires-inscrites-sur-zlv';
// No need for DashboardApi

export function getResource(id: Resource): number {
switch (id) {
case '6-utilisateurs-de-zlv-sur-votre-structure':
return 6;
case '7-autres-structures-de-votre-territoires-inscrites-sur-zlv':
return 7;
case '13-analyses':
return 13;
}
}

Expand Down

0 comments on commit 98ae0af

Please sign in to comment.