Skip to content

Commit

Permalink
Merge branch 'main' into TET-4053/tags-libres-filter
Browse files Browse the repository at this point in the history
  • Loading branch information
elisfainstein authored Jan 8, 2025
2 parents c166f2d + bc6ce98 commit 1ac4ba6
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { FicheResume } from 'packages/api/src/plan-actions';
import ActionsGroupeesMenu from '../ActionsGroupees/ActionsGroupeesMenu';
import EmptyFichePicto from '../FicheAction/FichesLiees/EmptyFichePicto';
import { useCreateFicheAction } from '../FicheAction/data/useCreateFicheAction';
import { useFicheActionCount } from '../FicheAction/data/useFicheActionCount';
import { useCreatePlanAction } from '../PlanAction/data/useUpsertAxe';

type sortByOptionsType = SortFichesAction & {
Expand Down Expand Up @@ -140,7 +141,7 @@ const FichesActionListe = ({
const { data, isLoading } = useFicheResumesFetch({
options: ficheResumesOptions,
});
const hasFiches = !!data?.data?.length;
const { count: hasFiches } = useFicheActionCount();

/** Gère les fiches sélectionnées pour les actions groupées */
const handleSelectFiche = (fiche: FicheResume) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,42 @@
import { makeCollectiviteIndicateursUrl } from '@/app/app/paths';
import { Button, Card } from '@/ui';

interface ComparezLaTrajectoireProps {
collectiviteId: number;
identifiantReferentiel: string;
readonly?: boolean;
}

/** Affiche l'encadré "Comparez la trajectoire SNBC à vos objectifs et vos résultats" */
export const ComparezLaTrajectoire = ({
collectiviteId,
identifiantReferentiel,
}: {
collectiviteId: number;
identifiantReferentiel: string;
}) => {
readonly = false,
}: ComparezLaTrajectoireProps) => {
return (
<Card>
<h5>Comparez la trajectoire SNBC à vos objectifs et vos résultats</h5>
<p className="text-sm font-normal">
Pour cela, il faut d&apos;abord{' '}
<b>compléter vos objectifs et vos résultats dans vos Indicateurs</b>.
Vous avez le choix d&apos;appliquer les données disponibles en open
data, ou bien de renseigner vos propres données.
</p>
{readonly ? (
<p className="text-sm font-normal">
Pour cela, il faut d&apos;abord{' '}
<b>
faire compléter vos objectifs et vos résultats dans vos Indicateurs
par un utilisateur en Edition ou Admin sur le profil de cette
collectivité
</b>
. L&apos;utilisateur pourra appliquer les données disponibles en open
data, ou bien renseigner ses propres données.
</p>
) : (
<p className="text-sm font-normal">
Pour cela, il faut d&apos;abord{' '}
<b>compléter vos objectifs et vos résultats dans vos Indicateurs</b>.
Vous avez le choix d&apos;appliquer les données disponibles en open
data, ou bien de renseigner vos propres données.
</p>
)}
<Button
disabled={readonly}
href={makeCollectiviteIndicateursUrl({
collectiviteId,
indicateurView: 'cae',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import { Alert, Button, Modal } from '@/ui';
import { DonneesCollectivite } from './DonneesCollectivite/DonneesCollectivite';

interface DonneesPartiellementDisponibles {
title?: string;
description?: string;
disabled?: boolean;
}

const DEFAULT_TITLE =
'Voici un premier calcul de votre trajectoire SNBC territorialisée, avec les données disponibles !';
const DEFAULT_DESC =
"Il manque des données pour certains secteurs : nous vous les mettrons à disposition prochainement. En attendant, complétez les données manquantes pour l'année 2015 afin de finaliser le calcul.";
"Il manque des données pour certains secteurs : complétez les données manquantes pour l'année 2015 afin de finaliser le calcul.";

/** Affiche l'avertissement "Données partiellement disponibles" */
export const DonneesPartiellementDisponibles = ({
title = DEFAULT_TITLE,
description = DEFAULT_DESC,
}: {
title?: string;
description?: string;
}) => {
disabled = false,
}: DonneesPartiellementDisponibles) => {
return (
<Alert
state="warning"
Expand All @@ -24,7 +28,9 @@ export const DonneesPartiellementDisponibles = ({
size="xl"
render={(props) => <DonneesCollectivite modalProps={props} />}
>
<Button size="sm">Compléter les données</Button>
<Button disabled={disabled} size="sm">
Compléter les données
</Button>
</Modal>
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import SpinnerLoader from '@/app/ui/shared/SpinnerLoader';
import { Alert, Button, Card, Modal, TrackPageView } from '@/ui';
import { useEffect } from 'react';
import { useQueryClient } from 'react-query';
import { useCurrentCollectivite } from '../../../../core-logic/hooks/useCurrentCollectivite';
import { CommuneNonSupportee } from './CommuneNonSupportee';
import { HELPDESK_URL } from './constants';
import { ReactComponent as DbErrorPicto } from './db-error.svg';
Expand Down Expand Up @@ -63,23 +64,45 @@ const TrajectoireContent = (props: {
* ne sont pas disponibles.
*/
const DonneesNonDispo = () => {
const collectivite = useCurrentCollectivite();

return (
<Card className="flex items-center my-16">
<DbErrorPicto />
<h2>Données disponibles insuffisantes pour le calcul</h2>
<p className="font-normal text-lg text-center">
Nous ne disposons pas encore des données suffisantes pour permettre le
calcul automatique de la trajectoire SNBC territorialisée de votre
collectivité. Vous pouvez néanmoins lancer un calcul en complétant les
données disponibles en open data avec vos propres données. Vous pourrez
ainsi visualiser facilement votre trajectoire SNBC territorialisée et la
comparer aux objectifs fixés et résultats observés.
</p>
{collectivite?.readonly ? (
<p className="font-normal text-lg text-center">
Nous ne disposons pas encore des données suffisantes pour permettre le
calcul automatique de la trajectoire SNBC territorialisé de votre
collectivité.{' '}
<b>
Un utilisateur en Edition ou Admin sur le profil de cette
collectivité
</b>{' '}
peut néanmoins lancer un calcul en complétant les données disponibles
en open data avec celles disponibles au sein de la collectivité. Vous
pourrez ensuite visualiser facilement votre trajectoire SNBC
territorialisée et la comparer aux objectifs fixés et résultats
observés.
</p>
) : (
<p className="font-normal text-lg text-center">
Nous ne disposons pas encore des données suffisantes pour permettre le
calcul automatique de la trajectoire SNBC territorialisée de votre
collectivité. Vous pouvez néanmoins lancer un calcul en complétant les
données disponibles en open data avec vos propres données. Vous
pourrez ainsi visualiser facilement votre trajectoire SNBC
territorialisée et la comparer aux objectifs fixés et résultats
observés.
</p>
)}
<Modal
size="xl"
render={(props) => <DonneesCollectivite modalProps={props} />}
>
<Button>Compléter mes données</Button>
<Button disabled={!collectivite || collectivite.readonly}>
Compléter mes données
</Button>
</Modal>
</Card>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,14 @@ export const TrajectoireCalculee = () => {
{
/** Avertissement "Données partiellement disponibles" */
!secteur && donneesSectoriellesIncompletes && (
<DonneesPartiellementDisponibles />
<DonneesPartiellementDisponibles
disabled={!collectivite || collectivite.readonly}
description={
!collectivite || collectivite.readonly
? "Il manque des données pour certains secteurs : un utilisateur en Edition ou Admin sur le profil de cette collectivité peut compléter les données manquantes pour l'année 2015 afin de finaliser le calcul"
: undefined
}
/>
)
}
{
Expand Down Expand Up @@ -187,7 +194,12 @@ export const TrajectoireCalculee = () => {
secteur && !valeursSecteur && (
<DonneesPartiellementDisponibles
title="Données non disponibles"
description="Nous ne disposons pas encore des données nécessaires pour calculer la trajectoire SNBC territorialisée de ce secteur. Nous y travaillons activement et espérons vous fournir ces informations très prochainement. En attendant, vous pouvez calculer dès maintenant votre trajectoire pour l’ensemble des secteurs en complétant les données déjà disponibles."
description={
!collectivite || collectivite.readonly
? 'Nous ne disposons pas encore des données nécessaires pour calculer la trajectoire SNBC territorialisée de ce secteur. Nous y travaillons activement et espérons vous fournir ces informations très prochainement. En attendant, un utilisateur en Edition ou Admin sur le profil de cette collectivité peut compléter les données déjà disponibles pour calculer la trajectoire pour l’ensemble des secteurs.'
: 'Nous ne disposons pas encore des données nécessaires pour calculer la trajectoire SNBC territorialisée de ce secteur. Nous y travaillons activement et espérons vous fournir ces informations très prochainement. En attendant, vous pouvez calculer dès maintenant votre trajectoire pour l’ensemble des secteurs en complétant les données déjà disponibles.'
}
disabled={!collectivite || collectivite.readonly}
/>
)
}
Expand All @@ -201,6 +213,7 @@ export const TrajectoireCalculee = () => {
<ComparezLaTrajectoire
collectiviteId={collectiviteId}
identifiantReferentiel={identifiant}
readonly={!collectivite || collectivite.readonly}
/>
)}
{secteur && <Methodologie secteur={secteur} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
SignInWithPasswordCredentials,
User,
} from '@supabase/supabase-js';
import { usePostHog } from 'posthog-js/react';
import {
createContext,
ReactNode,
Expand Down Expand Up @@ -109,6 +110,8 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {

const { data: userData = null } = useUserData(session);

const posthog = usePostHog();

useEffect(() => {
// écoute les changements d'état (connecté, déconnecté, etc.)
const {
Expand Down Expand Up @@ -139,12 +142,22 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
if (window.location.href.includes('localhost'))
environment = 'development';

if (posthog) {
posthog.identify(userData.id, {
email: userData.email,
user_id: userData.id,
});
}

if (environment === 'production' || environment === 'test') {
// @ts-expect-error - StonlyWidget is not defined
window.StonlyWidget('identify', userData.user_id);
}
} else {
clearCrispUserData();
if (posthog) {
posthog.reset();
}
}
}, [userData]);

Expand Down
3 changes: 3 additions & 0 deletions backend/src/auth/authorizations/permission.models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ export const Permission: Record<Role, PermissionOperation[]> = {
PermissionOperation.INDICATEURS_VISITE,
PermissionOperation.INDICATEURS_LECTURE,
PermissionOperation.INDICATEURS_TRAJECTOIRES_LECTURE,
PermissionOperation.INDICATEURS_TRAJECTOIRES_EDITION,
],
[Role.ADEME]: [
PermissionOperation.COLLECTIVITES_VISITE,
PermissionOperation.PLANS_FICHES_VISITE,
PermissionOperation.INDICATEURS_VISITE,
PermissionOperation.INDICATEURS_TRAJECTOIRES_LECTURE,
PermissionOperation.INDICATEURS_TRAJECTOIRES_EDITION,
],
[Role.LECTURE]: [
PermissionOperation.COLLECTIVITES_VISITE,
Expand All @@ -33,6 +35,7 @@ export const Permission: Record<Role, PermissionOperation[]> = {
PermissionOperation.INDICATEURS_VISITE,
PermissionOperation.INDICATEURS_LECTURE,
PermissionOperation.INDICATEURS_TRAJECTOIRES_LECTURE,
PermissionOperation.INDICATEURS_TRAJECTOIRES_EDITION,
],
[Role.EDITION]: [
PermissionOperation.COLLECTIVITES_VISITE,
Expand Down
2 changes: 1 addition & 1 deletion backend/src/auth/authorizations/roles/role.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export class RoleService {
.select()
.from(utilisateurSupportTable)
.where(eq(utilisateurSupportTable.userId, userId));
return result[0].support || false;
return (result.length && result[0]?.support) || false;
}

/**
Expand Down
13 changes: 10 additions & 3 deletions backend/src/indicateurs/trajectoires/trajectoire-snbc.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,19 +282,26 @@ describe('Calcul de trajectoire SNBC', () => {
});
}, 10000);

it(`Calcul sans droit suffisant (uniquement lecture)`, () => {
it(`Calcul sans droit suffisant - visite`, () => {
return request(app.getHttpServer())
.get('/trajectoires/snbc?collectiviteId=3895')
.get('/trajectoires/snbc?collectiviteId=3896')
.set('Authorization', `Bearer ${yoloDodoToken}`)
.expect(401)
.expect({
message:
"Droits insuffisants, l'utilisateur 17440546-f389-4d4f-bfdb-b0c94a1bd0f9 n'a pas l'autorisation indicateurs.trajectoires.edition sur la ressource Collectivité 3895",
"Droits insuffisants, l'utilisateur 17440546-f389-4d4f-bfdb-b0c94a1bd0f9 n'a pas l'autorisation indicateurs.trajectoires.lecture sur la ressource Collectivité 3896",
error: 'Unauthorized',
statusCode: 401,
});
});

it(`Calcul avec droit suffisant - lecture`, async () => {
return request(app.getHttpServer())
.get('/trajectoires/snbc?collectiviteId=3895')
.set('Authorization', `Bearer ${yoloDodoToken}`)
.expect(200);
}, 30000);

it(`Verification et calcul avec donnees completes`, async () => {
// Suppression de la trajectoire snbc existante si le test est joué plusieurs fois
await request(app.getHttpServer())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ export default class TrajectoiresSpreadsheetService {
const upsertedTrajectoireIndicateurValeurs =
await this.valeursService.upsertIndicateurValeurs(
indicateurValeursTrajectoireResultat,
tokenInfo
undefined // we don't want to check permission, we have already checked it and it's not the same
);

// Maintenant que les indicateurs ont été créés, on peut ajouter la collectivité au groupement
Expand Down
4 changes: 2 additions & 2 deletions backend/src/indicateurs/valeurs/crud-valeurs.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ export default class CrudValeursService {

async upsertIndicateurValeurs(
indicateurValeurs: IndicateurValeurInsert[],
tokenInfo: AuthenticatedUser
tokenInfo: AuthenticatedUser | undefined
): Promise<IndicateurValeur[]> {
if (tokenInfo) {
const collectiviteIds = [
Expand All @@ -331,7 +331,7 @@ export default class CrudValeursService {
}

this.logger.log(
`Upsert des ${indicateurValeurs.length} valeurs des indicateurs pour l'utilisateur ${tokenInfo.id} (role ${tokenInfo.role})`
`Upsert des ${indicateurValeurs.length} valeurs des indicateurs pour l'utilisateur ${tokenInfo?.id} (role ${tokenInfo?.role})`
);
// On doit distinguer les valeurs avec et sans métadonnées car la clause d'unicité est différente (onConflictDoUpdate)
const [indicateurValeursAvecMetadonnees, indicateurValeursSansMetadonnees] =
Expand Down

0 comments on commit 1ac4ba6

Please sign in to comment.