NIFI-14979: Deduping the referenced parameters in the property value tooltip. (#10315)

This closes #10315
diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/tooltips/property-value-tip/property-value-tip.component.spec.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/tooltips/property-value-tip/property-value-tip.component.spec.ts
index 118cf59..d39f043 100644
--- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/tooltips/property-value-tip/property-value-tip.component.spec.ts
+++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/tooltips/property-value-tip/property-value-tip.component.spec.ts
@@ -110,7 +110,7 @@
             expect(names).toEqual(['PARAM_A']);
         });
 
-        it('should capture multiple occurrences of the same parameter', () => {
+        it('should deduplicate multiple occurrences of the same parameter', () => {
             const data: PropertyValueTipInput = {
                 property: {
                     property: 'prop',
@@ -123,9 +123,29 @@
             component.data = data;
             fixture.detectChanges();
 
-            expect(component.parameterReferences.length).toBe(2);
+            expect(component.parameterReferences.length).toBe(1);
             expect(component.parameterReferences[0].name).toBe('PARAM_A');
-            expect(component.parameterReferences[1].name).toBe('PARAM_A');
+        });
+
+        it('should deduplicate parameters while preserving different parameter references', () => {
+            const data: PropertyValueTipInput = {
+                property: {
+                    property: 'prop',
+                    value: "#{PARAM_A} then #{PARAM_B} and #{PARAM_A} again and #{'PARAM_B'}",
+                    descriptor: buildDescriptor()
+                },
+                parameters: [
+                    { parameter: { name: 'PARAM_A', description: '', sensitive: false, value: 'a' } },
+                    { parameter: { name: 'PARAM_B', description: '', sensitive: false, value: 'b' } }
+                ]
+            };
+
+            component.data = data;
+            fixture.detectChanges();
+
+            expect(component.parameterReferences.length).toBe(2);
+            const names = component.parameterReferences.map((p) => p.name).sort();
+            expect(names).toEqual(['PARAM_A', 'PARAM_B']);
         });
 
         it('should handle null or empty property values', () => {
diff --git a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/tooltips/property-value-tip/property-value-tip.component.ts b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/tooltips/property-value-tip/property-value-tip.component.ts
index b02bda9..405e889 100644
--- a/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/tooltips/property-value-tip/property-value-tip.component.ts
+++ b/nifi-frontend/src/main/frontend/apps/nifi/src/app/ui/common/tooltips/property-value-tip/property-value-tip.component.ts
@@ -65,6 +65,8 @@
             }, '');
             this.parameterRegex = new RegExp(allParamsRegex, 'gm');
 
+            const addedParameterNames = new Set<string>();
+
             let matched;
             while ((matched = this.parameterRegex.exec(propertyValue)) !== null) {
                 // pull out the parameter name matched from the capturing groups, ignore any quote group
@@ -73,9 +75,10 @@
                 // get the Parameter object that was matched
                 const param = parameters.find((param) => param.name === paramName);
 
-                // if matched, add it to the list of parameter references
-                if (param) {
+                // if matched and not already added, add it to the list of parameter references
+                if (param && !addedParameterNames.has(param.name)) {
                     this.parameterReferences.push(param);
+                    addedParameterNames.add(param.name);
                 }
             }
         }