Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { addMessageNotification } from 'uiSrc/slices/app/notifications'
import successMessages from 'uiSrc/components/notifications/success-messages'
import { VALID_TAG_KEY_REGEX, VALID_TAG_VALUE_REGEX } from './constants'
import { TagInputField } from './TagInputField'
import { getInvalidTagErrors } from './utils'
import styles from './styles.module.scss'

export type ManageTagsModalProps = {
Expand Down Expand Up @@ -55,7 +56,8 @@ export const ManageTagsModal = ({
() =>
tags.some(
(tag) =>
!VALID_TAG_KEY_REGEX.test(tag.key) || !VALID_TAG_VALUE_REGEX.test(tag.value),
!VALID_TAG_KEY_REGEX.test(tag.key) ||
!VALID_TAG_VALUE_REGEX.test(tag.value),
),
[tags],
)
Expand Down Expand Up @@ -150,17 +152,12 @@ export const ManageTagsModal = ({
</div>
<div className={styles.tagFormBody}>
{tags.map((tag, index) => {
const isKeyInvalid =
Boolean(tag.key) &&
(!VALID_TAG_KEY_REGEX.test(tag.key) ||
tags.some((t, i) => i !== index && t.key === tag.key))
const isValueInvalid =
Boolean(tag.value) && !VALID_TAG_VALUE_REGEX.test(tag.value)
const [keyError, valueError] = getInvalidTagErrors(tags, index)

return (
<div key={`tag-row-${index}`} className={styles.tagFormRow}>
<TagInputField
isInvalid={isKeyInvalid}
errorMessage={keyError}
value={tag.key}
currentTagKeys={currentTagKeys}
onChange={(value) => {
Expand All @@ -169,8 +166,8 @@ export const ManageTagsModal = ({
rightContent={<>:</>}
/>
<TagInputField
isInvalid={isValueInvalid}
disabled={!tag.key || isKeyInvalid}
errorMessage={valueError}
disabled={!tag.key || Boolean(keyError)}
value={tag.value}
currentTagKeys={currentTagKeys}
suggestedTagKey={tag.key}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
import React, { useState } from 'react'
import { EuiFieldText, EuiToolTip } from '@elastic/eui'

import { INVALID_FIELD_MESSAGE } from './constants'
import { TagSuggestions } from './TagSuggestions'

type TagInputFieldProps = {
value: string
isInvalid: boolean
disabled?: boolean
currentTagKeys: Set<string>
suggestedTagKey?: string
rightContent?: React.ReactNode
errorMessage?: string
onChange: (value: string) => void
}

export const TagInputField = ({
value,
isInvalid,
disabled,
currentTagKeys,
suggestedTagKey,
rightContent,
errorMessage,
onChange,
}: TagInputFieldProps) => {
const isInvalid = Boolean(errorMessage)
const [isFocused, setIsFocused] = useState(false)

return (
<div>
<EuiToolTip content={isInvalid && INVALID_FIELD_MESSAGE} position="top">
<EuiToolTip content={errorMessage} position="top">
<div>
<EuiFieldText
value={value}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ export const presetTagSuggestions: {
},
]

export const VALID_TAG_KEY_REGEX = /^[a-zA-Z0-9\-_.@:+ ]{1,64}$/
export const VALID_TAG_VALUE_REGEX = /^[a-zA-Z0-9\-_.@:+ ]{1,128}$/
export const INVALID_FIELD_MESSAGE =
'Tag should have unique keys and can only have letters, numbers, spaces, and these special characters: “- _ . + @ :”. Max characters length is 64 for keys and 128 for values.'
export const MAX_KEY_LENGTH = 64
export const MAX_VALUE_LENGTH = 128

export const VALID_TAG_KEY_REGEX = new RegExp(`^[a-zA-Z0-9\\-_.@:+ ]{1,${MAX_KEY_LENGTH}}$`)
export const VALID_TAG_VALUE_REGEX = new RegExp(`^[a-zA-Z0-9\\-_.@:+ ]{1,${MAX_VALUE_LENGTH}}$`)

export const INVALID_FIELD_MESSAGE = 'Tag can only have letters, numbers, spaces, and these special characters: “- _ . + @ :”'
export const INVALID_FIELD_UNIQUE_KEY_MESSAGE = 'Key should be unique'
export const INVALID_FIELD_MAX_KEY_LENGTH_MESSAGE = `Key must be under ${MAX_KEY_LENGTH} characters`
export const INVALID_FIELD_MAX_VALUE_LENGTH_MESSAGE = `Value must be under ${MAX_VALUE_LENGTH} characters`
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {
MAX_KEY_LENGTH,
MAX_VALUE_LENGTH,
VALID_TAG_KEY_REGEX,
VALID_TAG_VALUE_REGEX,
INVALID_FIELD_MESSAGE,
INVALID_FIELD_UNIQUE_KEY_MESSAGE,
INVALID_FIELD_MAX_KEY_LENGTH_MESSAGE,
INVALID_FIELD_MAX_VALUE_LENGTH_MESSAGE,
} from './constants'

export function getInvalidTagErrors(
tags: { key: string; value: string }[],
index: number,
): (string | undefined)[] {
const tag = tags[index]

let keyError: string | undefined
let valueError: string | undefined

if (tag?.key) {
if (tag.key.length > MAX_KEY_LENGTH) {
keyError = INVALID_FIELD_MAX_KEY_LENGTH_MESSAGE
} else if (!VALID_TAG_KEY_REGEX.test(tag.key)) {
keyError = INVALID_FIELD_MESSAGE
} else if (tags.some((t, i) => i !== index && t.key === tag.key)) {
keyError = INVALID_FIELD_UNIQUE_KEY_MESSAGE
}
}

if (tag?.value) {
if (tag.value.length > MAX_VALUE_LENGTH) {
valueError = INVALID_FIELD_MAX_VALUE_LENGTH_MESSAGE
} else if (!VALID_TAG_VALUE_REGEX.test(tag.value)) {
valueError = INVALID_FIELD_MESSAGE
}
}

return [keyError, valueError]
}
Loading