3030
3131import { opPhaseIconData , toDOMString } from '@openproject/octicons-angular' ;
3232import { DisplayField } from 'core-app/shared/components/fields/display/display-field.module' ;
33+ import { HalResource } from 'core-app/features/hal/resources/hal-resource' ;
3334import { ProjectPhaseResource } from 'core-app/features/hal/resources/project-phase-resource' ;
3435
3536export class ProjectPhaseDisplayField extends DisplayField {
@@ -51,42 +52,40 @@ export class ProjectPhaseDisplayField extends DisplayField {
5152 * The icon is wrapped in a span element with the correct css class set for coloring
5253 * the icon in the color defined for the definition.
5354 *
55+ * @param phaseDefinitionId The ID of the phase definition (used for CSS class)
56+ * @param addPadding Whether to add right margin padding
5457 * @return {HTMLElement } The HTML span element containing the project phase icon.
5558 * @see phaseIcon
5659 */
57- public static phaseIconByName ( phaseName ?:string , addPadding = true ) {
60+ public static phaseIconById ( phaseDefinitionId ?:string , addPadding = true ) {
5861 const icon = document . createElement ( 'span' ) ;
5962
60- if ( phaseName ) {
63+ if ( phaseDefinitionId ) {
6164 if ( addPadding ) {
6265 icon . classList . add ( 'mr-1' ) ;
6366 }
6467
65- icon . setAttribute ( 'data-test-selector' , `project-phase-icon ${ phaseName } ` ) ;
68+ icon . setAttribute ( 'data-test-selector' , `project-phase-icon phase-definition- ${ phaseDefinitionId } ` ) ;
6669
6770 icon . innerHTML = toDOMString (
6871 opPhaseIconData ,
6972 'small' ,
7073 { 'aria-hidden' : 'true' , class : 'octicon' } ,
7174 ) ;
7275
73- // Use a base64 encoded string of the project phase name to access the definition's color.
74- // That way the frontend does not have to load the definitions to get the color.
75- // The name is guaranteed to be unique.
76- // The = signs at the end of the base64 string are replaced with _ to make it a valid class name.
77- // This needs to be kept in sync with the ColorsHelper#project_phase_color_css method in the backend.
78- icon . classList . add ( `__hl_inline_project_phase_definition_${ btoa ( phaseName ) . replace ( / = / g, '_' ) } ` ) ;
76+ // Use the phase definition ID for the CSS class.
77+ // This is more robust than using the name as it avoids issues with special characters.
78+ icon . classList . add ( `__hl_inline_project_phase_definition_${ phaseDefinitionId } ` ) ;
7979 }
8080
8181 return icon ;
8282 }
8383
8484 /**
85- * @see phaseIconByName
85+ * @see phaseIconById
8686 */
8787 protected phaseIcon ( ) :HTMLElement {
88- const projectPhase = this . attribute as ProjectPhaseResource ;
89-
90- return ProjectPhaseDisplayField . phaseIconByName ( projectPhase ?. name ) ;
88+ const definition = this . resource . projectPhaseDefinition as HalResource ;
89+ return ProjectPhaseDisplayField . phaseIconById ( definition ?. id ?? undefined ) ;
9190 }
9291}
0 commit comments