diff --git a/client/public/locales/en/translation.json b/client/public/locales/en/translation.json index 2b7b436d0d..edcbefc65d 100644 --- a/client/public/locales/en/translation.json +++ b/client/public/locales/en/translation.json @@ -178,6 +178,7 @@ "blockedDeleteTarget": "Cannot delete {{what}} because it is associated with a target.", "defaultBlockedDelete": "Cannot delete {{what}} because it is associated with another object.", "cannotDeleteApplicationsAssignedToMigrationWave": "Cannot delete applications that are assigned to a migration wave.", + "cannotDeleteNonEmptyTagCategory": "Cannot delete a tag category that contains tags.", "continueConfirmation": "Yes, continue", "copyAssessmentAndReviewBody": "Some of the selected target applications have an in-progress or complete assessment/review. By continuing, the existing assessment(s)/review(s) will be replaced by the copied assessment/review. Do you wish to continue?", "copyAssessmentAndReviewQuestion": "Copy assessment and review?", diff --git a/client/src/app/pages/controls/tags/components/tag-table.tsx b/client/src/app/pages/controls/tags/components/tag-table.tsx index 4f27cc3108..6bc612288a 100644 --- a/client/src/app/pages/controls/tags/components/tag-table.tsx +++ b/client/src/app/pages/controls/tags/components/tag-table.tsx @@ -8,19 +8,10 @@ import { Tbody, Td, ActionsColumn, - IAction, - IRow, - IRowData, } from "@patternfly/react-table"; import { Tag, TagCategory } from "@app/api/models"; import "./tag-table.css"; -const ENTITY_FIELD = "entity"; - -const getRow = (rowData: IRowData): Tag => { - return rowData[ENTITY_FIELD]; -}; - export interface TabTableProps { tagCategory: TagCategory; onEdit: (tag: Tag) => void; @@ -28,66 +19,42 @@ export interface TabTableProps { } export const TagTable: React.FC = ({ - tagCategory: tagCategory, + tagCategory, onEdit, onDelete, }) => { const { t } = useTranslation(); - const rows: IRow[] = []; - (tagCategory.tags || []) - .sort((a, b) => a.name.localeCompare(b.name)) - .forEach((item) => { - rows.push({ - [ENTITY_FIELD]: item, - noPadding: true, - cells: [ - { - title: item.name, - }, - ], - }); - }); - - const editRow = (row: Tag) => { - onEdit(row); - }; - - const deleteRow = (row: Tag) => { - onDelete(row); - }; - - const defaultActions = (tag: IRowData): IAction[] => [ - { - title: t("actions.edit"), - onClick: () => editRow(getRow(tag)), - }, - { - title: t("actions.delete"), - onClick: () => deleteRow(getRow(tag)), - }, - ]; - return ( - + - {rows.map((row: IRow) => { - const rowActions = defaultActions(row); - return ( - - {row.cells?.map((cell: any) => )} + {(tagCategory.tags || []) + .sort((a, b) => a.name.localeCompare(b.name)) + .map((tag) => ( + + - ); - })} + ))}
{t("terms.tagName")}
{cell.title}
{tag.name} - {rowActions && } + onEdit(tag), + }, + { + title: t("actions.delete"), + onClick: () => onDelete(tag), + }, + ]} + />
); diff --git a/client/src/app/pages/controls/tags/tags.tsx b/client/src/app/pages/controls/tags/tags.tsx index c2bbad551e..19361cf990 100644 --- a/client/src/app/pages/controls/tags/tags.tsx +++ b/client/src/app/pages/controls/tags/tags.tsx @@ -26,7 +26,11 @@ import { } from "@patternfly/react-table"; import { CubesIcon } from "@patternfly/react-icons"; -import { dedupeFunction, getAxiosErrorMessage } from "@app/utils/utils"; +import { + dedupeFunction, + getAxiosErrorMessage, + localeNumericCompare, +} from "@app/utils/utils"; import { Tag, TagCategory } from "@app/api/models"; import { FilterToolbar, FilterType } from "@app/components/FilterToolbar"; import { @@ -53,6 +57,7 @@ import { import { useLocalTableControls } from "@app/hooks/table-controls"; import { RBAC, controlsWriteScopes, RBAC_TYPE } from "@app/rbac"; import { TagTable } from "./components/tag-table"; +import i18n from "@app/i18n"; export const Tags: React.FC = () => { const { t } = useTranslation(); @@ -177,10 +182,9 @@ export const Tags: React.FC = () => { categoryKey: "tags", title: t("terms.name"), type: FilterType.multiselect, - placeholderText: - t("actions.filterBy", { - what: t("terms.name").toLowerCase(), - }) + "...", + placeholderText: t("actions.filterBy", { + what: t("terms.name").toLowerCase(), + }), getItemValue: (item) => { const tagCategoryNames = item.name?.toString() || ""; const tagNames = item?.tags @@ -191,23 +195,18 @@ export const Tags: React.FC = () => { }, selectOptions: dedupeFunction( tagCategories - ?.map((tagCategory) => tagCategory?.tags) - .flat() + ?.flatMap((tagCategory) => tagCategory?.tags ?? []) .filter((tag) => tag && tag.name) - .map((tag) => ({ key: tag?.name, value: tag?.name })) + .map((tag) => ({ key: tag.name, value: tag.name })) .concat( tagCategories?.map((tagCategory) => ({ key: tagCategory?.name, value: tagCategory?.name, - })) + })) ?? [] + ) + .sort((a, b) => + localeNumericCompare(a.value, b.value, i18n.language) ) - .sort((a, b) => { - if (a.value && b.value) { - return a?.value.localeCompare(b?.value); - } else { - return 0; - } - }) ), }, { @@ -264,9 +263,6 @@ export const Tags: React.FC = () => { expansionDerivedState: { isCellExpanded }, } = tableControls; - const categoryColor = - tagCategoryToUpdate?.colour || - getTagCategoryFallbackColor(tagCategoryToUpdate); return ( <> { setTagCategoryModalState(tagCategory)} onDelete={() => setTagCategoryToDelete(tagCategory)} />