diff --git a/src/app/applications/application-detail/application-detail.component.html b/src/app/applications/application-detail/application-detail.component.html index 1bff90fd..cee8771f 100644 --- a/src/app/applications/application-detail/application-detail.component.html +++ b/src/app/applications/application-detail/application-detail.component.html @@ -41,6 +41,7 @@
+ {{ "APPLICATION.METADATA-FIELD.METADATA" | translate }} +
+ @for (key of Object.keys(metadata); track key; let i = $index) { ++ {{ i + 1 }}: {{ key }} + {{ metadata[key] }} +
+ } +} diff --git a/src/app/shared/components/metadata-details/metadata-details.component.ts b/src/app/shared/components/metadata-details/metadata-details.component.ts index 67ff019c..b330eddd 100644 --- a/src/app/shared/components/metadata-details/metadata-details.component.ts +++ b/src/app/shared/components/metadata-details/metadata-details.component.ts @@ -5,6 +5,7 @@ import { ApplicationDeviceType } from "@applications/models/application-device-t import { TranslateService } from "@ngx-translate/core"; import { toPascalKebabCase } from "@shared/helpers/string.helper"; import { ControlledProperty } from "@shared/models/controlled-property.model"; +import { Metadata } from "@shared/types/metadata"; @Component({ selector: "app-metadata-details", @@ -26,6 +27,7 @@ export class MetadataDetailsComponent implements OnInit { @Input() hardware?: string; @Input() controlledProperties?: ControlledProperty[]; @Input() deviceTypes?: ApplicationDeviceType[]; + @Input() metadata?: Metadata; controlledPropertyText: string; deviceTypeText: string; @@ -48,4 +50,6 @@ export class MetadataDetailsComponent implements OnInit { .join(", "); }); } + + protected readonly Object = Object; } diff --git a/src/app/shared/helpers/metadata.helper.ts b/src/app/shared/helpers/metadata.helper.ts new file mode 100644 index 00000000..8b038448 --- /dev/null +++ b/src/app/shared/helpers/metadata.helper.ts @@ -0,0 +1,39 @@ +import { KeyValue } from "@shared/types/tuple.type"; +import { Metadata } from "@shared/types/metadata"; +import { TranslatableError } from "@shared/translatable-error"; + +export const metadataToKeyValueList = (metadata: object, shouldThrowOnError = false): KeyValue[] => { + try { + const tags: KeyValue[] = []; + + for (const key of Object.keys(metadata)) { + tags.push({ key, value: metadata[key] }); + } + + return tags; + } catch (error) { + if (shouldThrowOnError) { + throw error; + } + } +}; + +export const keyValueListToMetadata = (pairs: KeyValue[]): Metadata => { + const metadata = {} + + for (const pair of pairs) { + const key = pair.key?.trim(); + const value = pair.value?.trim(); + if (!key) { + throw new TranslatableError("ERROR.METADATA-EMPTY-KEY"); + } else if (key in metadata) { + throw new TranslatableError("ERROR.METADATA-DUPLICATE-KEY", { key }); + } + if (!value) { + throw new TranslatableError("ERROR.METADATA-EMPTY-VALUE", { key }); + } + metadata[key] = value + } + + return metadata; +}; diff --git a/src/app/shared/translatable-error.ts b/src/app/shared/translatable-error.ts new file mode 100644 index 00000000..4e9c3258 --- /dev/null +++ b/src/app/shared/translatable-error.ts @@ -0,0 +1,12 @@ +import { InterpolationParameters } from "@ngx-translate/core"; + +export class TranslatableError extends Error { + constructor( + msg: string, + public readonly context?: InterpolationParameters + ) { + super(msg); + // Set the prototype explicitly. + Object.setPrototypeOf(this, TranslatableError.prototype); + } +} diff --git a/src/app/shared/types/metadata.ts b/src/app/shared/types/metadata.ts new file mode 100644 index 00000000..bd55cad8 --- /dev/null +++ b/src/app/shared/types/metadata.ts @@ -0,0 +1 @@ +export type Metadata = Record