From 8fe848cbafaf0b786efffa28a2b4c5814fdcf652 Mon Sep 17 00:00:00 2001
From: Alexander Turinske <aturinske@gitlab.com>
Date: Fri, 22 Mar 2024 12:53:37 +0000
Subject: [PATCH] Disable file path input until project is selected

- update no project selected text
- add tooltip

EE: true

Changelog: changed
---
 .../action/code_block_file_path.vue           | 28 +++++++++++++++++--
 .../action/code_block_file_path_spec.js       | 10 +++++--
 locale/gitlab.pot                             |  6 ++++
 3 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/ee/app/assets/javascripts/security_orchestration/components/policy_editor/scan_execution/action/code_block_file_path.vue b/ee/app/assets/javascripts/security_orchestration/components/policy_editor/scan_execution/action/code_block_file_path.vue
index 6641b39e556b1..afedeba2f3cb7 100644
--- a/ee/app/assets/javascripts/security_orchestration/components/policy_editor/scan_execution/action/code_block_file_path.vue
+++ b/ee/app/assets/javascripts/security_orchestration/components/policy_editor/scan_execution/action/code_block_file_path.vue
@@ -5,9 +5,11 @@ import {
   GlInputGroupText,
   GlSprintf,
   GlFormInput,
+  GlTooltipDirective,
   GlTruncate,
 } from '@gitlab/ui';
 import { s__, __ } from '~/locale';
+import { BV_SHOW_TOOLTIP, BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
 import { getIdFromGraphQLId } from '~/graphql_shared/utils';
 import RefSelector from '~/ref/components/ref_selector.vue';
 import CodeBlockSourceSelector from 'ee/security_orchestration/components/policy_editor/scan_execution/action/code_block_source_selector.vue';
@@ -20,7 +22,7 @@ export default {
     filePathCopy: s__(
       'ScanExecutionPolicy|%{boldStart}Run%{boldEnd} %{typeSelector} from the project %{projectSelector} with ref %{refSelector}',
     ),
-    filePathPrependLabel: __('Select project'),
+    filePathPrependLabel: __('No project selected'),
     fileRefLabel: s__('ScanExecutionPolicy|Select ref'),
     filePathInputPlaceholder: s__('ScanExecutionPolicy|Link existing CI file'),
     filePathInputEmptyMessage: s__("ScanExecutionPolicy|The file path can't be empty"),
@@ -28,10 +30,12 @@ export default {
       "ScanExecutionPolicy|The file at that project, ref, and path doesn't exist",
     ),
     formGroupLabel: s__('ScanExecutionPolicy|file path group'),
+    tooltipText: s__('ScanExecutionPolicy|Select project first, and then insert a file path'),
   },
   refSelectorTranslations: {
     noRefSelected: __('default branch'),
   },
+  SELECTED_PROJECT_TOOLTIP: 'selected-project-tooltip',
   name: 'CodeBlockFilePath',
   components: {
     CodeBlockSourceSelector,
@@ -44,6 +48,7 @@ export default {
     GroupProjectsDropdown,
     RefSelector,
   },
+  directives: { GlTooltip: GlTooltipDirective },
   inject: ['namespacePath', 'rootNamespacePath', 'namespaceType'],
   props: {
     selectedType: {
@@ -107,6 +112,9 @@ export default {
     selectedProjectFullPath() {
       return this.selectedProject?.fullPath || this.$options.i18n.filePathPrependLabel;
     },
+    selectedProjectTooltip() {
+      return this.selectedProject?.fullPath || this.$options.i18n.tooltipText;
+    },
     groupProjectsPath() {
       return this.namespaceType === NAMESPACE_TYPES.GROUP
         ? this.namespacePath
@@ -126,6 +134,10 @@ export default {
     setSelectedRef(ref) {
       this.$emit('select-ref', ref);
     },
+    triggerTooltip(state) {
+      const EVENT = state ? BV_SHOW_TOOLTIP : BV_HIDE_TOOLTIP;
+      this.$root.$emit(EVENT, this.$options.SELECTED_PROJECT_TOOLTIP);
+    },
   },
 };
 </script>
@@ -196,12 +208,22 @@ export default {
               id="file-path"
               :placeholder="$options.i18n.filePathInputPlaceholder"
               :state="filePathState"
+              :disabled="!selectedProjectId"
               :value="filePath"
+              @mouseenter="triggerTooltip(true)"
+              @mouseleave="triggerTooltip(false)"
               @input="updatedFilePath"
             >
               <template #prepend>
-                <gl-input-group-text class="gl-max-w-26 gl-max-h-full!">
-                  <gl-truncate :text="selectedProjectFullPath" position="start" with-tooltip />
+                <gl-input-group-text
+                  v-gl-tooltip="{
+                    id: $options.SELECTED_PROJECT_TOOLTIP,
+                    title: selectedProjectTooltip,
+                  }"
+                  :class="{ 'gl-border-gray-100': !selectedProjectId }"
+                  class="gl-max-w-26 gl-max-h-full!"
+                >
+                  <gl-truncate :text="selectedProjectFullPath" position="start" />
                 </gl-input-group-text>
               </template>
             </gl-form-input-group>
diff --git a/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/action/code_block_file_path_spec.js b/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/action/code_block_file_path_spec.js
index b67e989682237..b227654b88153 100644
--- a/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/action/code_block_file_path_spec.js
+++ b/ee/spec/frontend/security_orchestration/components/policy_editor/scan_execution/action/code_block_file_path_spec.js
@@ -46,6 +46,8 @@ describe('CodeBlockFilePath', () => {
     it('renders file path', () => {
       expect(findFormGroup().exists()).toBe(true);
       expect(findFormInputGroup().exists()).toBe(true);
+      expect(findFormInputGroup().attributes().disabled).toBe('true');
+      expect(findTruncate().props('text')).toBe('No project selected');
     });
 
     it('renders ref input', () => {
@@ -77,17 +79,19 @@ describe('CodeBlockFilePath', () => {
     });
 
     it('renders selected project and ref selector', () => {
+      const fullPath = 'path/to/project';
+
       createComponent({
         propsData: {
           selectedProject: {
             id: PROJECT_ID,
-            fullPath: 'fullPath',
+            fullPath,
           },
           selectedRef: 'ref',
         },
       });
 
-      expect(findTruncate().props('text')).toBe('fullPath');
+      expect(findTruncate().props('text')).toBe(fullPath);
       expect(findRefSelector().exists()).toBe(true);
       expect(findFormInput().exists()).toBe(false);
       expect(findRefSelector().props()).toEqual(
@@ -99,6 +103,8 @@ describe('CodeBlockFilePath', () => {
         }),
       );
       expect(findGroupProjectsDropdown().props('selected')).toBe(PROJECT_ID);
+      expect(findFormInputGroup().attributes().disabled).toBe(undefined);
+      expect(findTruncate().props('text')).toBe(fullPath);
     });
 
     it('renders selected file path', () => {
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index fcab4053ad55e..f2b0e430e7b08 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -33463,6 +33463,9 @@ msgstr ""
 msgid "No prioritized labels yet!"
 msgstr ""
 
+msgid "No project selected"
+msgstr ""
+
 msgid "No project subscribes to the pipelines in this project."
 msgstr ""
 
@@ -44337,6 +44340,9 @@ msgstr ""
 msgid "ScanExecutionPolicy|Select or Create a Key"
 msgstr ""
 
+msgid "ScanExecutionPolicy|Select project first, and then insert a file path"
+msgstr ""
+
 msgid "ScanExecutionPolicy|Select ref"
 msgstr ""
 
-- 
GitLab