Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tags personnalisés sur la fiche action #3440

Merged
merged 21 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
eb8a098
Ajout de tags de suivi personnalisés à la fiche action
mariheck Nov 7, 2024
f7ab0b3
fix: add libres tag to update
elisfainstein Nov 21, 2024
9fab0df
test: adapt to libre tag, probably temporary delete strategy
elisfainstein Nov 21, 2024
a0c7901
Corrige des problèmes de typage
mariheck Nov 22, 2024
9631909
fix: add forgotten columns
elisfainstein Nov 25, 2024
b2a8912
feature: add libres tag creation to update service
elisfainstein Nov 25, 2024
38bdfb9
feat: add user uuid directly from auth on libres tag update
elisfainstein Nov 25, 2024
5524925
refactor: add example comments + refactor into more expressive functions
elisfainstein Nov 26, 2024
cedce62
Ajoute le bouton Exporter dans les pages Indicateur
marc-rutkowski Nov 21, 2024
3fbbb70
Améliore le tri des données exportées
marc-rutkowski Nov 21, 2024
4d874fe
Evite que la colonne "type de données" soit vide
marc-rutkowski Nov 21, 2024
9ac57a3
Change le libellé et le style du bouton d'export des indicateurs
marc-rutkowski Nov 21, 2024
b64a327
fix: add libres tag to update
elisfainstein Nov 21, 2024
9cee14c
test: adapt to libre tag, probably temporary delete strategy
elisfainstein Nov 21, 2024
53ba5d2
feature: add libres tag creation to update service
elisfainstein Nov 25, 2024
f53fa8c
fix: insert libres tags in table in beforeAll
elisfainstein Nov 26, 2024
6b27077
refactor: remove useless clean hook in tests
elisfainstein Nov 27, 2024
53caac8
fix: fix fixture inserts for libre tag
elisfainstein Nov 27, 2024
f2bc1f0
Mise à jour des types de référentiels
mariheck Nov 28, 2024
64dc62d
Fix après rebase
mariheck Dec 5, 2024
3490f49
Corrige l'affichage des tags personnalisés
mariheck Dec 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28,863 changes: 8,762 additions & 20,101 deletions api_tests/lib/database.types.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import ActionPreuvePanel from 'ui/shared/actions/ActionPreuvePanel/ActionPreuveP

export type TPreuvesTableProps = {
tableData: TableData;
referentielId: Referentiel;
referentielId: Exclude<Referentiel, 'te' | 'te-test'>;
};

export type TCellProps = CellProps<ActionReferentiel>;
Expand Down Expand Up @@ -121,7 +121,7 @@ export const PreuvesTable = (props: TPreuvesTableProps) => {
title={(nom as string) || ''}
{...rowProps}
>
{row.cells.map(cell => {
{row.cells.map((cell) => {
const { key, ...cellProps } = cell.getCellProps();
return (
<div className="cell" key={key} {...cellProps}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
* par référentiel et niveau
*/

import {Tabs, Tab} from 'ui/shared/Tabs';
import {referentielToName} from 'app/labels';
import {Referentiel} from 'types/litterals';
import {useTableData} from './useTableData';
import {PreuvesTable} from './PreuvesTable';
import { Tabs, Tab } from 'ui/shared/Tabs';
import { referentielToName } from 'app/labels';
import { Referentiel } from 'types/litterals';
import { useTableData } from './useTableData';
import { PreuvesTable } from './PreuvesTable';

const REFERENTIELS: Referentiel[] = ['cae', 'eci'];
const REFERENTIELS: Exclude<Referentiel, 'te' | 'te-test'>[] = ['cae', 'eci'];

const PreuvesTab = (props: {referentielId: Referentiel}) => {
const PreuvesTab = (props: {
referentielId: Exclude<Referentiel, 'te' | 'te-test'>;
}) => {
const tableData = useTableData(props.referentielId);
return (
<PreuvesTable tableData={tableData} referentielId={props.referentielId} />
Expand All @@ -21,7 +23,7 @@ const PreuvesTab = (props: {referentielId: Referentiel}) => {
export const PreuvesTabs = () => {
return (
<Tabs>
{REFERENTIELS.map(referentielId => {
{REFERENTIELS.map((referentielId) => {
return (
<Tab
key={referentielId}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Referentiel} from 'types/litterals';
import {TPreuveAuditEtLabellisation} from 'ui/shared/preuves/Bibliotheque/types';
import { Referentiel } from 'types/litterals';
import { TPreuveAuditEtLabellisation } from 'ui/shared/preuves/Bibliotheque/types';

// groupe les preuves par référentiel
type TPreuvesParReferentiel = Record<
Expand All @@ -12,7 +12,7 @@ const groupeParReferentiel = (
preuves.reduce((dict, preuve) => {
const referentiel =
preuve.demande?.referentiel || preuve.audit?.referentiel;
if (!referentiel) {
if (!referentiel || referentiel === 'te' || referentiel === 'te-test') {
return dict;
}
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ const Description = ({ fiche }: FicheActionPdfProps) => {
description,
ressources,
instanceGouvernance,
libresTag,
} = fiche;

return (
<Card className="bg-primary-6 border-primary-6">
{/* Liste des thématiques et sous-thématiques sous forme de badges */}
{(thematiques?.length || sousThematiques?.length) && (
{(thematiques?.length ||
sousThematiques?.length ||
libresTag?.length) && (
<Stack direction="row" gap={2.5} className="flex-wrap gap-y-2">
{thematiques?.map((thematique) => (
<Badge key={thematique.id} title={thematique.nom} state="info" />
Expand All @@ -25,6 +28,9 @@ const Description = ({ fiche }: FicheActionPdfProps) => {
state="info"
/>
))}
{libresTag?.map((tagPerso) => (
<Badge key={tagPerso.id} title={tagPerso.nom} state="default" />
))}
</Stack>
)}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const FicheActionDescription = ({
description,
ressources,
instanceGouvernance,
libresTag,
} = fiche;

const {
Expand All @@ -55,11 +56,14 @@ const FicheActionDescription = ({
>
<div
className={classNames('flex justify-between items-start', {
'max-sm:-mb-4 -mb-8': !thematiques || !thematiques?.length,
'max-sm:-mb-4 -mb-8':
(!thematiques || !thematiques?.length) && !libresTag?.length,
})}
>
{/* Liste des thématiques et sous-thématiques sous forme de badges */}
{(thematiques?.length || sousThematiques?.length) && (
{(thematiques?.length ||
sousThematiques?.length ||
libresTag?.length) && (
<div className="flex flex-wrap gap-3">
{thematiques?.map((thematique) => (
<Badge
Expand All @@ -77,6 +81,14 @@ const FicheActionDescription = ({
state="info"
/>
))}
{libresTag?.map((tagPerso) => (
<Badge
key={tagPerso.id}
title={tagPerso.nom}
uppercase={false}
state="default"
/>
))}
</div>
)}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { FicheAction } from '@tet/api/plan-actions';
import ThematiquesDropdown from 'ui/dropdownLists/ThematiquesDropdown/ThematiquesDropdown';
import SousThematiquesDropdown from 'ui/dropdownLists/SousThematiquesDropdown/SousThematiquesDropdown';
import TagsSuiviPersoDropdown from 'ui/dropdownLists/TagsSuiviPersoDropdown/TagsSuiviPersoDropdown';
import { useCurrentCollectivite } from 'core-logic/hooks/useCurrentCollectivite';
import { getMaxLengthMessage } from 'utils/formatUtils';
import { Thematique } from '@tet/api/shared/domain';
Expand Down Expand Up @@ -67,7 +68,7 @@ const ModaleDescription = ({ fiche, updateFiche }: ModaleDescriptionProps) => {
</Field>

{/* Dropdown thématiques */}
<Field title="Thématique" className="col-span-2">
<Field title="Thématique">
<ThematiquesDropdown
values={editedFiche.thematiques?.map((t) => t.id)}
onChange={({ thematiques }) =>
Expand All @@ -80,7 +81,7 @@ const ModaleDescription = ({ fiche, updateFiche }: ModaleDescriptionProps) => {
</Field>

{/* Dropdown sous-thématiques */}
<Field title="Sous-thématique" className="col-span-2">
<Field title="Sous-thématique">
<SousThematiquesDropdown
thematiques={(editedFiche.thematiques ?? []).map(
(t: Thematique) => t.id
Expand All @@ -95,6 +96,16 @@ const ModaleDescription = ({ fiche, updateFiche }: ModaleDescriptionProps) => {
/>
</Field>

{/* Dropdown tags personnalisés */}
<Field title="Mes tags de suivi" className="col-span-2">
<TagsSuiviPersoDropdown
values={editedFiche.libresTag?.map((t) => t.id!)}
onChange={({ libresTag }) =>
setEditedFiche((prevState) => ({ ...prevState, libresTag }))
}
/>
</Field>

{/* Description */}
<Field
title="Description de l'action"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ import { Tooltip } from '@tet/ui';

export type TCellProps = CellProps<ActionReferentiel> & {
collectiviteId: number | null;
referentielId: ReferentielParamOption | null;
referentielId: Exclude<ReferentielParamOption, 'te' | 'te-test'> | null;
maxDepth?: number | null;
alwaysShowExpand?: boolean;
};

// décalage à gauche des lignes en fonction du niveau
const paddingByLevel: Record<ReferentielParamOption, Record<number, number>> = {
const paddingByLevel: Record<
Exclude<ReferentielParamOption, 'te' | 'te-test'>,
Record<number, number>
> = {
cae: {
1: 0,
2: 16,
Expand Down
4 changes: 3 additions & 1 deletion app.territoiresentransitions.react/src/app/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ const actionVueParam = 'actionVue';
const labellisationVueParam = 'labellisationVue';
export const thematiqueParam = 'thematiqueId';

export type ReferentielParamOption = 'cae' | 'eci';
export type ReferentielParamOption = 'cae' | 'eci' | 'te' | 'te-test';
export type IndicateurViewParamOption =
| 'cae'
| 'eci'
| 'te'
| 'te-test'
| 'crte'
| 'perso'
| 'cles'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {useEffect, useState} from 'react';
import { useEffect, useState } from 'react';
import {
actionDownToTache,
actionPreuve,
referentielDownToAction,
} from 'core-logic/api/procedures/referentielProcedures';
import {Referentiel} from 'types/litterals';
import {parentId} from 'utils/actions';
import { Referentiel } from 'types/litterals';
import { parentId } from 'utils/actions';
import {
ActionTitleRead,
actionTitleReadEndpoint,
Expand All @@ -25,7 +25,7 @@ export const useActionDownToTache = (
const [summaries, setSummaries] = useState<ActionDefinitionSummary[]>([]);

useEffect(() => {
actionDownToTache(referentiel, identifiant).then(definitions =>
actionDownToTache(referentiel, identifiant).then((definitions) =>
setSummaries(definitions)
);
}, [referentiel, identifiant]);
Expand All @@ -43,7 +43,7 @@ export const useReferentielDownToAction = (
const [summaries, setSummaries] = useState<ActionDefinitionSummary[]>([]);

useEffect(() => {
referentielDownToAction(referentiel).then(definitions =>
referentielDownToAction(referentiel).then((definitions) =>
setSummaries(definitions)
);
}, [referentiel]);
Expand All @@ -57,7 +57,7 @@ export const useActionPreuve = (actionId: string) => {
const [preuve, setPreuve] = useState<string>('...');

useEffect(() => {
actionPreuve(actionId).then(preuve => setPreuve(preuve.preuve));
actionPreuve(actionId).then((preuve) => setPreuve(preuve.preuve));
}, [actionId]);

return preuve;
Expand Down Expand Up @@ -119,7 +119,7 @@ export const useSortedActionSummaryChildren = (
[id: string]: ActionDefinitionSummary[];
} = {};

actions.forEach(act => {
actions.forEach((act) => {
if (sortedActions[act.phase]) {
sortedActions[act.phase].push(act);
} else {
Expand All @@ -130,22 +130,24 @@ export const useSortedActionSummaryChildren = (
}
});

return {sortedActions, count: actions.length};
return { sortedActions, count: actions.length };
};

/**
* Returns action titles relative to the scope
*/
export const useActionTitleList = (
scope: 'all' | 'cae' | 'eci'
scope: 'all' | 'cae' | 'eci' | 'te' | 'te-test'
): ActionTitleRead[] => {
const [actionTitles, setActionTitles] = useState<ActionTitleRead[]>([]);

useEffect(() => {
if (scope === 'all')
actionTitleReadEndpoint.getBy({}).then(setActionTitles);
else
actionTitleReadEndpoint.getBy({referentiel: scope}).then(setActionTitles);
actionTitleReadEndpoint
.getBy({ referentiel: scope })
.then(setActionTitles);
}, [scope]);

return actionTitles;
Expand All @@ -163,8 +165,8 @@ export const useActionSummary = (

useEffect(() => {
actionDefinitionSummaryReadEndpoint
.getBy({referentiel, identifiant})
.then(list => setActionSummary(list.length === 0 ? null : list[0]));
.getBy({ referentiel, identifiant })
.then((list) => setActionSummary(list.length === 0 ? null : list[0]));
}, [referentiel, identifiant]);

return actionSummary ?? null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const getScoreQueryKey = (

const fetchScoresForCollectiviteAndReferentiel = async (
collectiviteId: number,
referentiel: Referentiel
referentiel: Exclude<Referentiel, 'te' | 'te-test'>
): Promise<ActionScore[]> => {
const clientScores = await clientScoresReadEndpoint.getBy({
collectiviteId,
Expand All @@ -28,7 +28,9 @@ const fetchScoresForCollectiviteAndReferentiel = async (
};

// donne accès aux scores d'un référentiel
const useReferentielScores = (referentiel: Referentiel) => {
const useReferentielScores = (
referentiel: Exclude<Referentiel, 'te' | 'te-test'>
) => {
const collectiviteId = useCollectiviteId();

// écoute les changements
Expand Down
2 changes: 1 addition & 1 deletion app.territoiresentransitions.react/src/types/litterals.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// TODO : This should be defined in generated

export type Referentiel = 'eci' | 'cae';
export type Referentiel = 'eci' | 'cae' | 'te' | 'te-test';
export type ReferentielOfIndicateur = 'eci' | 'cae' | 'crte';
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Tag } from '@tet/api/shared/domain';
import { SelectMultipleProps } from '@tet/ui';
import SelectTags from '../tags/SelectTags';
import { useTagsSuiviPersoListe } from './useTagsSuiviPersoListe';
import { LibreTag } from '@tet/api/typeUtils';

type TagsSuiviPersoDropdownProps = Omit<
SelectMultipleProps,
'values' | 'onChange' | 'options'
> & {
values?: number[];
onChange: ({
libresTag,
selectedLibreTag,
}: {
libresTag: LibreTag[];
selectedLibreTag: LibreTag;
}) => void;
};

const TagsSuiviPersoDropdown = (props: TagsSuiviPersoDropdownProps) => {
const { data, refetch } = useTagsSuiviPersoListe();

return (
<SelectTags
{...props}
placeholder={props.placeholder ?? 'Créez un tag de suivi personnalisé'}
queryKey="tags_suivi_perso"
tagTableName="libre_tag"
optionsListe={data}
refetchOptions={refetch}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C'est déclenché dans quels cas le refetch sur ce composant ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lors de la création, suppression ou mise à jour d'un tag dans les options du dropdown

onChange={({ values, selectedValue }) => {
props.onChange({
libresTag: values,
selectedLibreTag: selectedValue,
});
}}
/>
);
};

export default TagsSuiviPersoDropdown;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Tag } from '@tet/api/shared/domain';
import { supabaseClient } from 'core-logic/api/supabase';
import { useCollectiviteId } from 'core-logic/hooks/params';
import { useQuery } from 'react-query';
import { objectToCamel } from 'ts-case-convert';

export const useTagsSuiviPersoListe = () => {
const collectiviteId = useCollectiviteId()!;

return useQuery(['tags_suivi_perso', collectiviteId], async () => {
const { error, data } = await supabaseClient
.from('libre_tag')
.select()
.eq('collectivite_id', collectiviteId)
.order('nom');

if (error) {
throw new Error(error.message);
}

return objectToCamel(data) as Tag[];
});
};
Loading
Loading