Skip to content

Conversation

@AshwinGajbhiye
Copy link

Description

Fixed TLP badge display issue where badges were showing only borders without background colors on the job report page.

This PR includes:

  • Frontend fix: Added backgroundColor and accessible text colors to TLP badge component
  • Backend fix: Added tlp field to JobSerializer so the API returns TLP value in job details

Changes made:

  • Added backgroundColor property to TLPTag component styling
  • Implemented accessible text color logic (black text for CLEAR/GREEN/AMBER, white text for RED) based on Copilot AI review suggestions
  • Added tlp field to JobSerializer to return TLP value in job details API response

Closes #3150

Type of change

  • Bug fix (non-breaking change which fixes an issue).
  • New feature (non-breaking change which adds functionality).
  • Breaking change (fix or feature that would cause existing functionality to not work as expected).

ScreenShot

Screenshot 2026-02-06 at 5 19 51 PM

Checklist

  • I have read and understood the rules about how to Contribute to this project
  • The pull request is for the branch develop
  • A new plugin (analyzer, connector, visualizer, playbook, pivot or ingestor) was added or changed, in which case:
    • I strictly followed the documentation "How to create a Plugin"
    • Usage file was updated. A link to the PR to the docs repo has been added as a comment here.
    • Advanced-Usage was updated (in case the plugin provides additional optional configuration). A link to the PR to the docs repo has been added as a comment here.
    • I have dumped the configuration from Django Admin using the dumpplugin command and added it in the project as a data migration. ("How to share a plugin with the community")
    • If a File analyzer was added and it supports a mimetype which is not already supported, you added a sample of that type inside the archive test_files.zip and you added the default tests for that mimetype in test_classes.py.
    • If you created a new analyzer and it is free (does not require any API key), please add it in the FREE_TO_USE_ANALYZERS playbook by following this guide.
    • Check if it could make sense to add that analyzer/connector to other freely available playbooks.
    • I have provided the resulting raw JSON of a finished analysis and a screenshot of the results.
    • If the plugin interacts with an external service, I have created an attribute called precisely url that contains this information. This is required for Health Checks (HEAD HTTP requests).
    • If a new analyzer has beed added, I have created a unittest for it in the appropriate dir. I have also mocked all the external calls, so that no real calls are being made while testing.
    • I have added that raw JSON sample to the get_mocker_response() method of the unittest class. This serves us to provide a valid sample for testing.
    • I have created the corresponding DataModel for the new analyzer following the documentation
  • I have inserted the copyright banner at the start of the file: # This file is a part of IntelOwl https://github.com/intelowlproject/IntelOwl # See the file 'LICENSE' for copying permission.
  • Please avoid adding new libraries as requirements whenever it is possible. Use new libraries only if strictly needed to solve the issue you are working for. In case of doubt, ask a maintainer permission to use a specific library.
  • If external libraries/packages with restrictive licenses were added, they were added in the Legal Notice section.
  • Linters (Black, Flake, Isort) gave 0 errors. If you have correctly installed pre-commit, it does these checks and adjustments on your behalf.
  • I have added tests for the feature/bug I solved (see tests folder). All the tests (new and old ones) gave 0 errors.
  • If the GUI has been modified:
    • I have provided a screenshot of the result in the PR.
    • I have created new frontend tests for the new component or updated existing ones.
  • After you had submitted the PR, if DeepSource, Django Doctors or other third-party linters have triggered any alerts during the CI checks, I have solved those alerts.

Important Rules

  • If you miss to compile the Checklist properly, your PR won't be reviewed by the maintainers.
  • Everytime you make changes to the PR and you think the work is done, you should explicitly ask for a review by using GitHub's reviewing system detailed here.

…loses intelowlproject#3150

- Added backgroundColor property to TLP badge component styling
- Implemented accessible text color logic (black for CLEAR/GREEN/AMBER, white for RED)
- Added tlp field to JobSerializer to return TLP value in job details API response
- Fixed issue where TLP badges showed only borders without background colors on job report page
Copilot AI review requested due to automatic review settings February 7, 2026 05:11
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes incorrect TLP badge rendering in the job report UI and ensures the job retrieve API returns the tlp field so the frontend can display it consistently (closes #3150).

Changes:

  • Add backgroundColor and explicit text color selection for TLPTag badges.
  • Include tlp in JobSerializer fields so /api/jobs/{id} returns the value.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
frontend/src/components/common/TLPTag.jsx Updates TLP badge styling (background + text color) used across job/investigation/plugin UIs.
api_app/serializers/job.py Adds tlp to the job retrieve serializer output.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 10 to 14
const badgeId = `tlptag-badge__${value}`;
const color = TLPColors?.[value] || "#dfe1e2";
const tooltipText = TLPDescriptions?.[value] || "invalid";
const textColorMap = {
CLEAR: "#000000",
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

badgeId is derived only from the TLP value, which will produce duplicate DOM ids whenever multiple rows/cards render the same TLP (common in job/investigation tables). Duplicate ids break HTML validity and can cause UncontrolledTooltip to attach to the wrong element. Consider generating a unique id per component instance (e.g., React useId()), or accept an explicit id prop and fall back to a unique default.

Copilot uses AI. Check for mistakes.
Comment on lines 13 to 29
@@ -18,7 +24,9 @@ export function TLPTag(props) {
style={{
borderRadius: 5,
userSelect: "none",
backgroundColor: color,
border: `1px solid ${color}`,
color: textColor,
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

The new background/text color styling logic isn’t covered by any frontend unit test (there are no existing tests exercising TLPTag). Since this component is reused across multiple pages, add a small Jest test to assert the rendered badge has the expected backgroundColor and text color for at least one light TLP (e.g. CLEAR) and RED.

Copilot uses AI. Check for mistakes.
- Replace simple value-based IDs with counter-based unique IDs to prevent duplicate DOM IDs when multiple badges with same TLP value are rendered
- Add comprehensive Jest tests for TLPTag component covering:
  * Background and text color rendering for all TLP levels (CLEAR, RED, GREEN, AMBER)
  * Unique ID generation for multiple instances
- Addresses Copilot review feedback for duplicate ID issue and missing test coverage
Copilot AI review requested due to automatic review settings February 7, 2026 07:46
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 14 to 60
// CLEAR should have white background (#ffffff) and black text
expect(badge).toHaveStyle({
backgroundColor: "#ffffff",
color: "#000000",
});
});

test("RED TLP renders with correct background and text color", () => {
const { container } = render(<TLPTag value="RED" />);

const badge = container.querySelector('[id^="tlptag-badge__RED"]');
expect(badge).toBeInTheDocument();
expect(badge).toHaveTextContent("RED");

// RED should have red background (#ff0033) and white text
expect(badge).toHaveStyle({
backgroundColor: "#ff0033",
color: "#FFFFFF",
});
});

test("GREEN TLP renders with correct background and text color", () => {
const { container } = render(<TLPTag value="GREEN" />);

const badge = container.querySelector('[id^="tlptag-badge__GREEN"]');
expect(badge).toBeInTheDocument();
expect(badge).toHaveTextContent("GREEN");

// GREEN should have green background (#33ff00) and black text
expect(badge).toHaveStyle({
backgroundColor: "#33ff00",
color: "#000000",
});
});

test("AMBER TLP renders with correct background and text color", () => {
const { container } = render(<TLPTag value="AMBER" />);

const badge = container.querySelector('[id^="tlptag-badge__AMBER"]');
expect(badge).toBeInTheDocument();
expect(badge).toHaveTextContent("AMBER");

// AMBER should have amber background (#ffc000) and black text
expect(badge).toHaveStyle({
backgroundColor: "#ffc000",
color: "#000000",
});
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

The tests hardcode TLP hex colors instead of asserting against the shared TLPColors constant. Using the constant (or another shared source of truth) would reduce duplication and keep the test aligned if the palette ever changes.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,81 @@
import React from "react";
import "@testing-library/jest-dom";
import { render, screen } from "@testing-library/react";
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

screen is imported from @testing-library/react but never used in this test file. Please remove the unused import to keep the test clean and avoid future lint noise if test files are ever added to the lint target.

Suggested change
import { render, screen } from "@testing-library/react";
import { render } from "@testing-library/react";

Copilot uses AI. Check for mistakes.
Copy link
Member

@mlodic mlodic left a comment

Choose a reason for hiding this comment

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

please address CI failures.

Also pull the most recent changes from develop and test it again because there were some GUI changes

- Import TLPColors constant to avoid hardcoding hex values in tests
- Remove unused screen import from @testing-library/react
- Addresses Copilot review feedback
- Replace postfix increment (idCounter++) with prefix increment (idCounter += 1)
- Maintains unique ID generation for TLP badges without ESLint violations
Copilot AI review requested due to automatic review settings February 8, 2026 08:37
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

frontend/src/components/common/TLPTag.jsx:40

  • {...rest} is spread after id={badgeId}, so a caller-provided id will override the badge's DOM id while the tooltip still targets badgeId, breaking the tooltip (and potentially reintroducing the original issue). Consider explicitly handling an id prop (use it for both the <Badge> and tooltip target) or ensure id cannot be overridden by moving {...rest} before id={badgeId} / omitting id from rest.
    <Badge
      id={badgeId}
      color={null}
      style={{
        borderRadius: 5,
        userSelect: "none",
        backgroundColor: color,
        border: `1px solid ${color}`,
        color: textColor,
      }}
      {...rest}
    >
      {value}
      <UncontrolledTooltip target={badgeId} placement="top" fade={false}>
        {tooltipText}
      </UncontrolledTooltip>

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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