diff --git a/api/projects/tags/migrations/0007_alter_tag_color.py b/api/projects/tags/migrations/0007_alter_tag_color.py new file mode 100644 index 000000000000..3b2ef5282bdf --- /dev/null +++ b/api/projects/tags/migrations/0007_alter_tag_color.py @@ -0,0 +1,22 @@ +# Generated by Django 4.2.16 on 2024-11-08 18:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("tags", "0006_alter_tag_type"), + ] + + operations = [ + migrations.AlterField( + model_name="tag", + name="color", + field=models.CharField( + default="#6837FC", + help_text="Hexadecimal value of the tag color", + max_length=10, + ), + ), + ] diff --git a/api/projects/tags/models.py b/api/projects/tags/models.py index 35c75eecfb7e..076245248043 100644 --- a/api/projects/tags/models.py +++ b/api/projects/tags/models.py @@ -13,7 +13,7 @@ class TagType(models.Choices): class Tag(AbstractBaseExportableModel): label = models.CharField(max_length=100) color = models.CharField( - max_length=10, help_text="Hexadecimal value of the tag color" + max_length=10, help_text="Hexadecimal value of the tag color", default="#6837FC" ) description = models.CharField(max_length=512, blank=True, null=True) project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="tags") diff --git a/frontend/common/constants.ts b/frontend/common/constants.ts index 1c5f7d5f22c6..ecb4b967560c 100644 --- a/frontend/common/constants.ts +++ b/frontend/common/constants.ts @@ -452,6 +452,7 @@ export default { githubIssue: 'GitHub Issue', githubPR: 'Github PR', }, + defaultTagColor: '#3d4db6', isCustomFlagsmithUrl: Project.flagsmithClientAPI !== 'https://edge.api.flagsmith.com/api/v1/', modals: { diff --git a/frontend/common/utils/utils.tsx b/frontend/common/utils/utils.tsx index 7412795f691f..4b98764d802c 100644 --- a/frontend/common/utils/utils.tsx +++ b/frontend/common/utils/utils.tsx @@ -23,6 +23,7 @@ import WarningMessage from 'components/WarningMessage' import Constants from 'common/constants' import Format from './format' import { defaultFlags } from 'common/stores/default-flags' +import Color from 'color' const semver = require('semver') @@ -110,11 +111,23 @@ const Utils = Object.assign({}, require('./base/_utils'), { return typeof value === 'number' }, + colour( + c: string, + fallback = Constants.defaultTagColor, + ): InstanceType { + let res: Color + try { + res = Color(c) + } catch (_) { + res = Color(fallback) + } + return res + }, + copyFeatureName: (featureName: string) => { navigator.clipboard.writeText(featureName) toast('Copied to clipboard') }, - displayLimitAlert(type: string, percentage: number | undefined) { const envOrProject = type === 'segment overrides' ? 'environment' : 'project' diff --git a/frontend/web/components/FeatureAction.tsx b/frontend/web/components/FeatureAction.tsx index 57c69b2091ef..377e78aba8b8 100644 --- a/frontend/web/components/FeatureAction.tsx +++ b/frontend/web/components/FeatureAction.tsx @@ -176,12 +176,12 @@ export const FeatureAction: FC = ({ protectedTags?.length > 1 ? 's' : '' } ${protectedTags ?.map((tag) => { - const tagColor = getTagColor(tag) + const tagColor = Utils.colour(getTagColor(tag)) return ` + )};color:${tagColor.darken(0.1)};'> ${tag.label} ` }) diff --git a/frontend/web/components/ToggleChip.js b/frontend/web/components/ToggleChip.js index b59b28706ef9..96a81b75ce7c 100644 --- a/frontend/web/components/ToggleChip.js +++ b/frontend/web/components/ToggleChip.js @@ -1,19 +1,20 @@ import React from 'react' import cx from 'classnames' -import color from 'color' import Icon from './Icon' +import Utils from 'common/utils/utils' export default function (props) { + const colour = Utils.colour(props.color) return ( = ({ selected, tag, }) => { - const tagColor = getTagColor(tag, selected) + const tagColor = Utils.colour(getTagColor(tag, selected)) if (isDot) { return (
) @@ -72,9 +71,9 @@ const Tag: FC = ({ } }} style={{ - backgroundColor: `${color(tagColor).fade(0.92)}`, - border: `1px solid ${color(tagColor).fade(0.76)}`, - color: `${color(tagColor).darken(0.1)}`, + backgroundColor: `${tagColor.fade(0.92)}`, + border: `1px solid ${tagColor.fade(0.76)}`, + color: `${tagColor.darken(0.1)}`, }} className={cx('chip', className)} > diff --git a/frontend/web/components/tags/TagContent.tsx b/frontend/web/components/tags/TagContent.tsx index e2d0b2bddee7..de2d3d775d0e 100644 --- a/frontend/web/components/tags/TagContent.tsx +++ b/frontend/web/components/tags/TagContent.tsx @@ -1,6 +1,5 @@ import React, { FC } from 'react' import { Tag as TTag } from 'common/types/responses' -import color from 'color' import Format from 'common/utils/format' import { IonIcon } from '@ionic/react' import { alarmOutline, lockClosed } from 'ionicons/icons' @@ -10,6 +9,7 @@ import OrganisationStore from 'common/stores/organisation-store' import Utils from 'common/utils/utils' import classNames from 'classnames' import Icon from 'components/Icon' +import Color from 'color' type TagContent = { tag: Partial } @@ -26,15 +26,10 @@ const renderIcon = ( tagLabel: string, isPermanent: boolean, ) => { + const darkened = tagColor.darken(0.1).string() switch (tagType) { case 'STALE': - return ( - - ) + return case 'GITHUB': switch (tagLabel) { case 'PR Open': @@ -53,13 +48,7 @@ const renderIcon = ( return } default: - return isPermanent ? ( - - ) : null + return isPermanent ? : null } } @@ -90,16 +79,14 @@ const getTooltip = (tag: TTag | undefined) => { tooltip = 'Features marked with this tag are not monitored for staleness and have deletion protection.' } - const tagColor = getTagColor(tag, false) + const tagColor = Utils.colour(getTagColor(tag, false)) if (isTruncated) { return `
= ({ tag }) => { })} > {tagLabel} - {renderIcon(tag.type!, tag.color!, tag.label!, tag.is_permanent)} + {renderIcon(tag.type!, Utils.colour(tag.color), tag.label!)} } >