Skip to content

[FEATURE] Add annotation support#120

Draft
Gladorme wants to merge 8 commits into
perses:mainfrom
Gladorme:annotations
Draft

[FEATURE] Add annotation support#120
Gladorme wants to merge 8 commits into
perses:mainfrom
Gladorme:annotations

Conversation

@Gladorme
Copy link
Copy Markdown
Member

@Gladorme Gladorme commented Apr 27, 2026

Description

Adding Annotation support with Provider, Editor, ...

PR related to:

Screenshots

image

Checklist

  • Pull request has a descriptive title and context useful to a reviewer.
  • Pull request title follows the [<catalog_entry>] <commit message> naming convention using one of the
    following catalog_entry values: FEATURE, ENHANCEMENT, BUGFIX, BREAKINGCHANGE, DOC,IGNORE.
  • All commits have DCO signoffs.

UI Changes

  • Changes that impact the UI include screenshots and/or screencasts of the relevant changes.
  • Code follows the UI guidelines.
  • E2E tests are stable and unlikely to be flaky.
    See e2e docs for more details. Common issues include:
    • Is the data inconsistent? You need to mock API requests.
    • Does the time change? You need to use consistent time values or mock time utilities.
    • Does it have loading states? You need to wait for loading to complete.

Signed-off-by: Guillaume LADORME <Gladorme@users.noreply.github.com>
Signed-off-by: Guillaume LADORME <Gladorme@users.noreply.github.com>
Signed-off-by: Guillaume LADORME <Gladorme@users.noreply.github.com>
Signed-off-by: Guillaume LADORME <Gladorme@users.noreply.github.com>
Signed-off-by: Guillaume LADORME <Gladorme@users.noreply.github.com>
Signed-off-by: Guillaume LADORME <Gladorme@users.noreply.github.com>
Signed-off-by: Guillaume LADORME <Gladorme@users.noreply.github.com>
Signed-off-by: Guillaume LADORME <Gladorme@users.noreply.github.com>
Comment on lines +44 to +51
const errors: string[] = [];

/** Annotation names must be unique */
const annotationNames = annotationSpecs.map((annotationSpec) => annotationSpec.display.name);
const uniqueAnnotationNames = new Set(annotationNames);
if (annotationNames.length !== uniqueAnnotationNames.size) {
errors.push('Annotation names must be unique');
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The error message Annotation names must be unique is vague.
The captured error should clarify what exact annotations are redundant.
You can either .join(',') the redundant or push individual errors into the array.
It should be feasible to collect the duplicates by O(N)

Comment on lines +31 to +32
import AddIcon from 'mdi-material-ui/Plus';
import { Action } from '@perses-dev/core';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Action is available in Perses/Shared/Components
Please avoid using Core

import { Action } from '@perses-dev/components';

import { ValidationProvider, AnnotationEditorForm } from '@perses-dev/plugin-system';
import { useDiscardChangesConfirmationDialog } from '../../context';

function getValidation(annotationSpecs: AnnotationSpec[]): { isValid: boolean; errors: string[] } {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The function name is vague. getValidation sounds like a function which returns a validation function.
Here the function simply validates the annotationSpecs. So, it could be validateAnnotationSpecs

Comment on lines +123 to +143
const changeAnnotationOrder = (index: number, direction: 'up' | 'down'): void => {
setAnnotationSpecs((draft) => {
if (direction === 'up') {
const prevElement = draft[index - 1];
const currentElement = draft[index];
if (index === 0 || !prevElement || !currentElement) {
return;
}
draft[index - 1] = currentElement;
draft[index] = prevElement;
} else {
const nextElement = draft[index + 1];
const currentElement = draft[index];
if (index === draft.length - 1 || !nextElement || !currentElement) {
return;
}
draft[index + 1] = currentElement;
draft[index] = nextElement;
}
});
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The code could be shortened and optimized by generating the target indexes dynamically.
Also, the code should probably annotationEditIdx

const changeAnnotationOrder = (index: number, direction: 'up' | 'down'): void => {
  const step = direction === 'up' ? -1 : 1;

  setAnnotationSpecs((draft) => {
    const current = draft[index];
    const adjacent = draft[index + step];

    if (!current || !adjacent) {
      return;
    }

    draft[index + step] = current;
    draft[index] = adjacent;
  });
  setAnnotationEditIdx(index + step);  
};

Comment on lines +18 to +37
export function AnnotationHydrationWrapper({ children }: AnnotationHydrationWrapperProps): ReactNode {
const annotationSpecs = useAnnotationSpecs();
const { setAnnotationState } = useAnnotationActions();
const annotations: Array<UseQueryResult<AnnotationData[]>> = useAnnotations(annotationSpecs);

useEffect(() => {
for (const [index, definition] of annotationSpecs.entries()) {
const query = annotations[index] ?? null;
if (query) {
setAnnotationState(definition.display.name, {
data: query.data ?? null,
isPending: query.isLoading,
error: (query?.error as Error) ?? null,
});
}
}
}, [annotationSpecs, annotations, setAnnotationState]);

return <>{children}</>;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment on lines +1 to +2
// Copyright 2025 The Perses Authors
// Licensed under the Apache License, Version 2.0 (the "License");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should the file be removed?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants