From 5da7628911d1b863c8c0323704f792caa7d888e8 Mon Sep 17 00:00:00 2001 From: Ivan-Koshan Date: Fri, 21 Feb 2025 09:54:48 +0200 Subject: [PATCH] Implement copy value mapper for the AttributeViewer --- .../attributeViewer.module.scss | 15 ------ .../Attributes/AttributeViewer/index.tsx | 46 +++++++------------ src/utils/attributes/attributes.tsx | 37 ++++++++++++++- 3 files changed, 53 insertions(+), 45 deletions(-) delete mode 100644 src/components/Attributes/AttributeViewer/attributeViewer.module.scss diff --git a/src/components/Attributes/AttributeViewer/attributeViewer.module.scss b/src/components/Attributes/AttributeViewer/attributeViewer.module.scss deleted file mode 100644 index 58e1f32a9..000000000 --- a/src/components/Attributes/AttributeViewer/attributeViewer.module.scss +++ /dev/null @@ -1,15 +0,0 @@ -@import 'src/resources/styles/app'; - -.copyContentButton { - margin: 0.5rem; - cursor: pointer; - color: $czertainly-blue; - font-size: small; - &:hover { - color: $brand-primary; - } - - &:active { - color: $brand-primary; - } -} diff --git a/src/components/Attributes/AttributeViewer/index.tsx b/src/components/Attributes/AttributeViewer/index.tsx index 93438e80f..9d8b10ce7 100644 --- a/src/components/Attributes/AttributeViewer/index.tsx +++ b/src/components/Attributes/AttributeViewer/index.tsx @@ -1,4 +1,3 @@ -import cx from 'classnames'; import CustomTable, { TableDataRow, TableHeader } from 'components/CustomTable'; import { selectors as enumSelectors, getEnumLabel } from 'ducks/enums'; import { useCallback, useMemo, useState } from 'react'; @@ -14,13 +13,12 @@ import { isCustomAttributeModelArray, } from 'types/attributes'; import { MetadataItemModel, MetadataModel } from 'types/locations'; -import { NameAndUuidDto, PlatformEnum, Resource } from 'types/openapi'; -import { getAttributeContent } from 'utils/attributes/attributes'; +import { AttributeContentType, NameAndUuidDto, PlatformEnum, Resource } from 'types/openapi'; +import { getAttributeContent, getAttributeCopyValue } from 'utils/attributes/attributes'; import { useCopyToClipboard } from 'utils/common-hooks'; import { actions as userInterfaceActions } from '../../../ducks/user-interface'; import ContentValueField from '../../Input/DynamicContent/ContentValueField'; import WidgetButtons, { WidgetButtonProps } from '../../WidgetButtons'; -import styles from './attributeViewer.module.scss'; export enum ATTRIBUTE_VIEWER_TYPE { ATTRIBUTE, @@ -57,28 +55,11 @@ export default function AttributeViewer({ const onCopyContentClick = useCallback( (attribute: AttributeResponseModel) => { - let textToCopy = ''; if (!attribute?.content?.length) return; - // if (attribute.content.length > 1) textToCopy = attribute?.content?.map((content) => content.data).join(', '); - // if (attribute.content.length === 1) textToCopy = attribute.content[0]?.reference.toString(); - // check if reference is there or if no reference then use .data to copy + const textToCopy = getAttributeCopyValue(attribute.contentType, attribute.content); - if (attribute.content.length > 1) { - textToCopy = attribute.content - .map((content) => { - if (content.reference) { - return content.reference; - } - return content.data; - }) - .join(', '); - } - if (attribute.content.length === 1) { - textToCopy = attribute.content[0]?.reference?.toString() || attribute.content[0]?.data.toString(); - } - - if (attribute) { + if (attribute && textToCopy) { copyToClipboard(textToCopy, 'Custom Attribute content was copied to clipboard', 'Failed to copy to clipboard'); } }, @@ -210,11 +191,18 @@ export default function AttributeViewer({ {getContent(attribute.contentType, attribute.content)} {resource && renderSourceObjectsButton(attribute, resource)} , - { - onCopyContentClick(attribute); - }} + { + onCopyContentClick(attribute); + }, + tooltip: 'Copy to clipboard', + }, + ]} />, ], }), @@ -254,7 +242,7 @@ export default function AttributeViewer({ } else { buttons.push({ icon: 'copy', - disabled: false, + disabled: AttributeContentType.Secret === attribute.contentType, tooltip: 'Copy to clipboard', onClick: () => { onCopyContentClick(attribute); diff --git a/src/utils/attributes/attributes.tsx b/src/utils/attributes/attributes.tsx index bb7cd32ef..a5ef1b085 100644 --- a/src/utils/attributes/attributes.tsx +++ b/src/utils/attributes/attributes.tsx @@ -7,7 +7,7 @@ import { isDataAttributeModel, } from 'types/attributes'; import { AttributeContentType, CodeBlockAttributeContent, FileAttributeContentData, SecretAttributeContent } from 'types/openapi'; -import { utf8ToBase64 } from 'utils/common-utils'; +import { base64ToUtf8, utf8ToBase64 } from 'utils/common-utils'; import { getFormattedDateTime } from 'utils/dateUtil'; import CodeBlock from '../../components/Attributes/CodeBlock'; @@ -22,6 +22,41 @@ export const attributeFieldNameTransform: { [name: string]: string } = { cryptographyProvider: 'Cryptography Provider', notificationProvider: 'Notification Provider', }; +export const getAttributeCopyValue = (contentType: AttributeContentType, content: BaseAttributeContentModel[] | undefined) => { + if (!content) return undefined; + + const mapping = (content: BaseAttributeContentModel): string | undefined => { + switch (contentType) { + case AttributeContentType.Codeblock: + if (typeof content.data === 'object' && 'code' in content.data) return base64ToUtf8(content.data.code); + return content.data.toString(); + case AttributeContentType.Credential: + if (typeof content.data === 'object' && 'name' in content.data) return content.data.name; + return content.data.toString(); + case AttributeContentType.File: + if (typeof content.data === 'object' && 'content' in content.data) return base64ToUtf8(content.data.content); + return content.data.toString(); + case AttributeContentType.Object: + return JSON.stringify(content.data); + case AttributeContentType.Boolean: + return content.data ? 'true' : 'false'; + case AttributeContentType.Time: + return content.data.toString(); + case AttributeContentType.Date: + return content.data.toString(); + case AttributeContentType.Datetime: + return getFormattedDateTime(content.data.toString()); + case AttributeContentType.Float: + case AttributeContentType.Integer: + case AttributeContentType.String: + case AttributeContentType.Text: + return content.data.toString(); + case AttributeContentType.Secret: + return undefined; + } + }; + return content.map(mapping).join(', '); +}; export const getAttributeContent = (contentType: AttributeContentType, content: BaseAttributeContentModel[] | undefined) => { if (!content) return 'Not set';