Skip to content

Commit

Permalink
Release: contenus et fichiers avec accents
Browse files Browse the repository at this point in the history
Release: contenus et fichiers avec accents
  • Loading branch information
derfurth authored Apr 28, 2022
2 parents 9361001 + d1bcbda commit 788e5ea
Show file tree
Hide file tree
Showing 36 changed files with 2,003 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {Story, Meta} from '@storybook/react';
// import { action } from '@storybook/addon-actions';
import {Critere, TCritereProps} from './Critere';
import fixture from './fixture.json';

export default {
component: Critere,
} as Meta;

const Template: Story<TCritereProps> = args => (
<Critere parcours={fixture.parcours1} {...args} />
);

export const CritereSimple = Template.bind({});
CritereSimple.args = {
critere: fixture.parcours1.criteres[0],
};

export const CritereSimpleRempli = Template.bind({});
CritereSimpleRempli.args = {
critere: {...fixture.parcours1.criteres[0], rempli: true},
};

export const CritereAction = Template.bind({});
CritereAction.args = {
critere: fixture.parcours1.criteres[1],
};

export const CritereActionRempli = Template.bind({});
CritereActionRempli.args = {
critere: {
...fixture.parcours1.criteres[1],
criteres: fixture.parcours1.criteres[1].criteres.map(c => ({
...c,
rempli: true,
})),
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import {
makeCollectiviteReferentielUrl,
makeCollectiviteActionUrl,
ReferentielParamOption,
REGLEMENTS,
} from 'app/paths';
import {CritereActionTable} from './CritereActionTable';
import {CritereLabellisation, ParcoursLabellisation} from './types';

export type TCritereProps = {
parcours: ParcoursLabellisation;
critere: CritereLabellisation;
};

/**
* Affiche un critère
*/
export const Critere = (props: TCritereProps) => {
const {parcours, critere} = props;
const {collectivite_id: collectiviteId, referentiel} = parcours;
const referentielId = referentiel as ReferentielParamOption;

// critère associé à une action
if ('action_id' in critere) {
return <Formulation {...props} />;
}

// critère associé à des pré-requis liés aux actions
if ('criteres' in critere) {
return (
<>
<Formulation {...props} />
<CritereActionTable
{...critere}
className="fr-my-4w"
onClickRow={actionId => {
window.document.open(
makeCollectiviteActionUrl({
collectiviteId,
referentielId,
actionId,
})
);
}}
/>
</>
);
}

// critère nécessitant l'ajout d'un ou plusieurs fichiers
if ('fichiers' in critere) {
return (
<>
<Formulation {...props} />
</>
);
}

// critère "simple"
const {rempli} = critere;
return (
<>
<Formulation {...props} />
{rempli ? (
<i className="flex fr-icon fr-fi-checkbox-circle-fill before:text-[#5FD68C] before:pr-3 fr-text--sm fr-mb-0 fr-ml-3w">
Terminé
</i>
) : (
<a
className="fr-link fr-link--icon-right fr-fi-arrow-right-line fr-mb-2w"
target="_blank"
href={makeCollectiviteReferentielUrl({
collectiviteId,
referentielId,
})}
>
Mettre à jour
</a>
)}
</>
);
};

/**
* Affiche le libellé d'un critère
*/
const reReglement = /\{le règlement du label\}/;
const Formulation = (props: TCritereProps) => {
const {critere, parcours} = props;
const {referentiel} = parcours;
const {formulation} = critere;

// cas particulier : ajouter un lien vers le règlement du label
const matchReglement = formulation.match(reReglement);
let html = formulation;
if (matchReglement?.length) {
html = formulation.replace(
matchReglement[0],
`<a href="${REGLEMENTS[referentiel]}" target="_blank" rel="noopener">le règlement du label</a>`
);
}

return <li className="fr-mb-1w" dangerouslySetInnerHTML={{__html: html}} />;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.critere-action-table {
border-radius: 8px;
border-width: 8px;
border-color: var(--background-disabled-grey);
width: 100%;
font-size: 0.875rem;
line-height: 1.25rem;
}

.critere-action-table table {
width: 100%;
border-collapse: separate;
border-spacing: 0 1px;
background-color: var(--background-disabled-grey);
}

.critere-action-table th {
text-align: left;
padding-top: 1rem;
padding-bottom: 1rem;
}
@media (min-width: 36em) {
.critere-action-table th {
white-space: nowrap;
}
}

.critere-action-table tbody tr {
background-color: var(--background-default-grey);
cursor: pointer;
}
.critere-action-table tbody tr:hover {
background-color: var(--background-alt-grey);
cursor: pointer;
}

.critere-action-table td {
padding-top: 1rem;
padding-bottom: 1rem;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {Story, Meta} from '@storybook/react';
import {
CritereActionTable,
TCritereActionTableProps,
} from './CritereActionTable';
import fixture from './fixture.json';

export default {
component: CritereActionTable,
} as Meta;

const Template: Story<TCritereActionTableProps> = args => (
<CritereActionTable {...args} />
);

export const Exemple1 = Template.bind({});
Exemple1.args = fixture.parcours1.criteres[1];
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import './CritereActionTable.css';
import {CritereLabellisationListeActions} from './types';

export type TCritereActionTableProps = CritereLabellisationListeActions & {
className?: string;
onClickRow: (action_id: string) => void;
};

/**
* Affiche le tableau des critères associés à des actions
*/
export const CritereActionTable = (props: TCritereActionTableProps) => {
const {className, criteres} = props;
return (
<div className={`critere-action-table ${className || ''}`}>
<table>
<thead>
<tr>
<th className="pl-10" colSpan={3}>
Sous-action ou tâche
</th>
<th className="pr-6">Statut ou score requis</th>
</tr>
</thead>
<tbody>
{criteres.map(({id}, index) => (
<CritereActionRow key={id} rowIndex={index} {...props} />
))}
</tbody>
</table>
</div>
);
};

/** Affiche une ligne du tableau */
const CritereActionRow = (
props: TCritereActionTableProps & {rowIndex: number}
) => {
const {rowIndex, criteres, onClickRow} = props;
const {action_id, formulation, statut_ou_score, rempli} = criteres[rowIndex];

// extrait l'id d'action sans le préfixe
const actionId = action_id.split('_').pop();

return (
<tr onClick={() => onClickRow(action_id)}>
<td className="text-center w-[56px]">
{rempli ? (
<i className="fr-icon fr-fi-checkbox-circle-fill before:text-[#5FD68C]" />
) : null}
</td>
<td className="text-right text-xs w-[40px] text-grey625">
<span>{actionId}</span>
</td>
<td className="pl-4 pr-8">{formulation}</td>
<td>{statut_ou_score}</td>
</tr>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {Story, Meta} from '@storybook/react';
// import { action } from '@storybook/addon-actions';
import {
CriteresLabellisation,
TCriteresLabellisationProps,
} from './CriteresLabellisation';
import fixture from './fixture.json';

export default {
component: CriteresLabellisation,
} as Meta;

const Template: Story<TCriteresLabellisationProps> = args => (
<CriteresLabellisation {...args} />
);

export const PremiereEtoile = Template.bind({});
PremiereEtoile.args = {
parcours: fixture.parcours1,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {ParcoursLabellisation} from './types';
import {Critere} from './Critere';

export type TCriteresLabellisationProps = {
parcours: ParcoursLabellisation;
};

/**
* Affiche la liste des critères à remplir pour un niveau de labellisation
*/
export const CriteresLabellisation = (props: TCriteresLabellisationProps) => {
const {parcours} = props;
const {criteres} = parcours;
return (
<>
<h2>Critères de labellisation</h2>
<ul>
{criteres.map(critere => (
<Critere key={critere.id} critere={critere} parcours={parcours} />
))}
</ul>
</>
);
};
Loading

0 comments on commit 788e5ea

Please sign in to comment.