Skip to content

Commit

Permalink
refact: move badge to a separate component
Browse files Browse the repository at this point in the history
  • Loading branch information
edelclaux committed Sep 26, 2024
1 parent a0c1b4a commit d0371ae
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 65 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<span
class="badge badge-secondary"
[style]="symbologyAsCSS"
matTooltip="{{ tooltip }}"
>
{{ text }}
</span>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.badge {
--bgColor: #ffffff; // Default value
--textColor: #444; // Default value

display: flex;
flex-flow: row nowrap;
white-space: nowrap;
gap: 0.25rem;
text-transform: uppercase;
font-weight: bold;

background-color: var(--bgColor);
border: 2px solid color-mix(in srgb, var(--bgColor) 80%, black);
color: var(--textColor);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { CommonModule } from '@angular/common';
import { Component, Input, OnInit } from '@angular/core';
import { GN2CommonModule } from '@geonature_common/GN2Common.module';

// ////////////////////////////////////////////////////////////////////////////
// helper method
// ////////////////////////////////////////////////////////////////////////////

function isHexadecimalColor(color: string) {
return /^#[0-9A-F]{6}$/i.test(color);
}

function computeContrastColor(backgroundColor: string) {
// Convertir la couleur en un format RGB
const r = parseInt(backgroundColor.slice(1, 3), 16);
const g = parseInt(backgroundColor.slice(3, 5), 16);
const b = parseInt(backgroundColor.slice(5, 7), 16);

// Calculer la luminosité
const luminance = 0.299 * r + 0.587 * g + 0.114 * b;

// Retourner une couleur claire ou foncée selon la luminosité
return luminance < 128 ? '#ffffff' : '#444';
}

function colorToCSS(color: string) {
return `--bgColor: ${color}; --textColor: ${computeContrastColor(color)};`;
}

// ////////////////////////////////////////////////////////////////////////////
// Badge parameters
// ////////////////////////////////////////////////////////////////////////////

export interface BadgeSymbology {
color?: string;
}

// ////////////////////////////////////////////////////////////////////////////
// helper method
// ////////////////////////////////////////////////////////////////////////////

@Component({
standalone: true,
selector: 'badge',
templateUrl: 'badge.component.html',
styleUrls: ['badge.component.scss'],
imports: [CommonModule, GN2CommonModule],
})
export class BadgeComponent {
@Input()
text: string;

@Input()
tooltip: string;

symbologyAsCSS: string;

@Input()
set symbology(symbology: BadgeSymbology | null) {
this.symbologyAsCSS = '';
if (!symbology) {
return;
}
if (!isHexadecimalColor(symbology.color)) {
console.warn(`[badge] ${symbology.color} is not a valid hexadecimal color`);
return;
}
this.symbologyAsCSS = colorToCSS(symbology.color);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
<div class="Status">
<div class="Status__header">Statuts</div>
<div class="Status__badges">
<span
class="badge badge-secondary"
*ngFor="let status of status; let isLast = last"
[style]="status.symbologyAsCSS"
matTooltip="{{ status.tooltip }}"
>
{{ status.badge }}
</span>
<badge
*ngFor="let status of status"
[tooltip]="status.tooltip"
[text]="status.badge"
[symbology]="status.symbology"
/>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,5 @@
width: 100%;
gap: $gap;
line-height: inherit;
--bgColor: #ffffff; // Default value
--textColor: #444; // Default value
.badge {
display: flex;
flex-flow: row nowrap;
white-space: nowrap;
gap: $gap / 2;
text-transform: uppercase;
font-weight: bold;
background-color: var(--bgColor);
border: 2px solid color-mix(in srgb, var(--bgColor) 80%, black);
color: var(--textColor);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,25 @@ import { Component, Input, OnInit } from '@angular/core';
import { Taxon } from '@geonature_common/form/taxonomy/taxonomy.component';
import { GN2CommonModule } from '@geonature_common/GN2Common.module';
import { TaxonSheetService } from '../../taxon-sheet.service';
import { BadgeComponent, BadgeSymbology } from './badge.component';

interface Status {
badge: string;
tooltip: string;
symbologyAsCSS: string;
symbology: BadgeSymbology | null;
}

function computeContrastColor(backgroundColor: string) {
// Convertir la couleur en un format RGB
const r = parseInt(backgroundColor.slice(1, 3), 16);
const g = parseInt(backgroundColor.slice(3, 5), 16);
const b = parseInt(backgroundColor.slice(5, 7), 16);

// Calculer la luminosité
const luminance = 0.299 * r + 0.587 * g + 0.114 * b;

// Retourner une couleur claire ou foncée selon la luminosité
return luminance < 128 ? '#ffffff' : '#444';
}

function colorToCSS(color: string) {
return `--bgColor: ${color}; --textColor: ${computeContrastColor(color)};`;
}

@Component({
standalone: true,
selector: 'status',
templateUrl: 'status.component.html',
styleUrls: ['status.component.scss'],
imports: [CommonModule, GN2CommonModule],
imports: [CommonModule, GN2CommonModule, BadgeComponent],
})
export class StatusComponent implements OnInit {
_taxon: Taxon | null;
_symbology: Array<{
types: Array<string>;
values: Record<
string,
{
symbologyAsCSSStyle: string;
}
>;
values: Record<string, BadgeSymbology>;
}>;
status: Array<Status> = [];

Expand All @@ -55,33 +33,27 @@ export class StatusComponent implements OnInit {
if (!symbology || !symbology.symbologies) {
return;
}
for (const symbologyItem of symbology.symbologies) {
const values = {};
for (const key of Object.keys(symbologyItem.values)) {
values[key] = {
symbologyAsCSSStyle: colorToCSS(symbologyItem.values[key].color),
};
}
this._symbology.push({
types: symbologyItem.types,
values: values,
});
}
this._symbology = symbology.symbologies;

this.computeStatus();
});
this._tss.fetchStatusSymbology();
}

_getSymbologyAsCSSStyle(type: string, value: string): string {
_getSymbologyAsBadgeSymbology(type: string, value: string): BadgeSymbology | null {
if (!this._symbology) {
return '';
return null;
}
const symbologieItem = this._symbology.find((item) => item.types.includes(type));
if (!symbologieItem) {
return '';
return null;
}

return symbologieItem.values[value]?.symbologyAsCSSStyle ?? '';
if (!('color' in symbologieItem.values[value])) {
return null;
}
return {
color: symbologieItem.values[value].color,
};
}

@Input()
Expand All @@ -106,7 +78,7 @@ export class StatusComponent implements OnInit {
this.status.push({
badge: badgeValue,
tooltip: `${status.cd_type_statut} : ${value.display} - ${text.full_citation}`,
symbologyAsCSS: this._getSymbologyAsCSSStyle(status.cd_type_statut, value.code_statut),
symbology: this._getSymbologyAsBadgeSymbology(status.cd_type_statut, value.code_statut),
});
}
}
Expand Down

0 comments on commit d0371ae

Please sign in to comment.