diff --git a/ee/app/assets/javascripts/ai/catalog/graphql/mutations/create_ai_catalog_item_consumer.mutation.graphql b/ee/app/assets/javascripts/ai/catalog/graphql/mutations/create_ai_catalog_item_consumer.mutation.graphql index 9a236375954634d0dae5f5156505bb8f2cd14dde..3e901a1647ceb9dd793cc3fc6a2dcd9d587eb9a2 100644 --- a/ee/app/assets/javascripts/ai/catalog/graphql/mutations/create_ai_catalog_item_consumer.mutation.graphql +++ b/ee/app/assets/javascripts/ai/catalog/graphql/mutations/create_ai_catalog_item_consumer.mutation.graphql @@ -3,13 +3,19 @@ mutation createAiCatalogItemConsumer($input: AiCatalogItemConsumerCreateInput!) errors itemConsumer { id + item { + id + itemType + } project { id name + webPath } group { id name + webPath } } } diff --git a/ee/app/assets/javascripts/ai/catalog/pages/ai_catalog_agents_show.vue b/ee/app/assets/javascripts/ai/catalog/pages/ai_catalog_agents_show.vue index 5090d67e9b15ff38cf812fe73d1dc446e21767d6..389590e70aa82a0176e02c60a19a41b283bf3290 100644 --- a/ee/app/assets/javascripts/ai/catalog/pages/ai_catalog_agents_show.vue +++ b/ee/app/assets/javascripts/ai/catalog/pages/ai_catalog_agents_show.vue @@ -3,6 +3,7 @@ import { GlAlert, GlButton, GlExperimentBadge } from '@gitlab/ui'; import { s__, sprintf } from '~/locale'; import { InternalEvents } from '~/tracking'; import * as Sentry from '~/sentry/sentry_browser_wrapper'; +import { visitUrl } from '~/lib/utils/url_utility'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import PageHeading from '~/vue_shared/components/page_heading.vue'; import { @@ -19,7 +20,7 @@ import { VERSION_PINNED_GROUP, } from 'ee/ai/catalog/constants'; import ErrorsAlert from '~/vue_shared/components/errors_alert.vue'; -import { prerequisitesError } from '../utils'; +import { prerequisitesError, createLinkToItemConsumer } from '../utils'; import AiCatalogItemActions from '../components/ai_catalog_item_actions.vue'; import AiCatalogItemView from '../components/ai_catalog_item_view.vue'; import aiCatalogAgentQuery from '../graphql/queries/ai_catalog_agent.query.graphql'; @@ -167,9 +168,21 @@ export default { return; } - const name = data.aiCatalogItemConsumerCreate.itemConsumer[targetType]?.name || ''; + const createdItemConsumer = data.aiCatalogItemConsumerCreate.itemConsumer; + const href = createLinkToItemConsumer(createdItemConsumer, targetTypeLabel); - this.$toast.show(sprintf(s__('AICatalog|Agent enabled in %{name}.'), { name })); + const { name } = createdItemConsumer[targetTypeLabel]; + + this.$toast.show(sprintf(s__('AICatalog|Agent enabled in %{name}.'), { name }), { + action: { + text: sprintf(s__('AICatalog|View in %{targetTypeLabel}'), { targetTypeLabel }), + href, + onClick: (e) => { + e?.preventDefault(); + visitUrl(href); + }, + }, + }); } } catch (error) { this.errors = [ diff --git a/ee/app/assets/javascripts/ai/catalog/pages/ai_catalog_flows_show.vue b/ee/app/assets/javascripts/ai/catalog/pages/ai_catalog_flows_show.vue index 923d91c5ed229524c197031e42ee7192035f6018..d4800a029249dbe2b14ba36d7177bf6ec6b6e636 100644 --- a/ee/app/assets/javascripts/ai/catalog/pages/ai_catalog_flows_show.vue +++ b/ee/app/assets/javascripts/ai/catalog/pages/ai_catalog_flows_show.vue @@ -3,6 +3,7 @@ import { GlAlert, GlButton, GlExperimentBadge } from '@gitlab/ui'; import { s__, sprintf } from '~/locale'; import { InternalEvents } from '~/tracking'; import * as Sentry from '~/sentry/sentry_browser_wrapper'; +import { visitUrl } from '~/lib/utils/url_utility'; import PageHeading from '~/vue_shared/components/page_heading.vue'; import { AI_CATALOG_CONSUMER_TYPE_GROUP, @@ -19,7 +20,7 @@ import { } from 'ee/ai/catalog/constants'; import ErrorsAlert from '~/vue_shared/components/errors_alert.vue'; import FoundationalIcon from 'ee/ai/components/foundational_icon.vue'; -import { prerequisitesError } from '../utils'; +import { prerequisitesError, createLinkToItemConsumer } from '../utils'; import AiCatalogItemActions from '../components/ai_catalog_item_actions.vue'; import AiCatalogItemView from '../components/ai_catalog_item_view.vue'; import aiCatalogFlowQuery from '../graphql/queries/ai_catalog_flow.query.graphql'; @@ -160,9 +161,21 @@ export default { return; } - const name = data.aiCatalogItemConsumerCreate.itemConsumer[targetType]?.name || ''; + const createdItemConsumer = data.aiCatalogItemConsumerCreate.itemConsumer; + const href = createLinkToItemConsumer(createdItemConsumer, targetTypeLabel); - this.$toast.show(sprintf(s__('AICatalog|Flow enabled in %{name}.'), { name })); + const { name } = createdItemConsumer[targetTypeLabel]; + + this.$toast.show(sprintf(s__('AICatalog|Flow enabled in %{name}.'), { name }), { + action: { + text: sprintf(s__('AICatalog|View in %{targetTypeLabel}'), { targetTypeLabel }), + href, + onClick: (e) => { + e?.preventDefault(); + visitUrl(href); + }, + }, + }); } } catch (error) { this.errors = [ diff --git a/ee/app/assets/javascripts/ai/catalog/utils.js b/ee/app/assets/javascripts/ai/catalog/utils.js index 0cf62f96bc59f4c68ff2bbcfc10679bc47640cf1..18923762452754db832278b95f63b5217934a53a 100644 --- a/ee/app/assets/javascripts/ai/catalog/utils.js +++ b/ee/app/assets/javascripts/ai/catalog/utils.js @@ -1,5 +1,7 @@ import { sprintf } from '~/locale'; import { helpPagePath } from '~/helpers/help_page_helper'; +import { getIdFromGraphQLId } from '~/graphql_shared/utils'; +import { AI_CATALOG_ITEM_PLURAL_LABELS } from './constants'; export const prerequisitesPath = helpPagePath('user/duo_agent_platform/ai_catalog', { anchor: 'view-the-ai-catalog', @@ -17,6 +19,23 @@ export const prerequisitesError = (message, params = {}) => { ); }; +/** + * Returns a link to a specific agent or flow. + * + * @param {Object} itemConsumer - Must include: + * - `project` or `group` object with a `webPath` property + * - `item` object with `id` and `itemType` properties + * @param {String} targetNamespace either `project` or `group` + */ +export const createLinkToItemConsumer = (itemConsumer, targetNamespace) => { + const namespaceConsumer = itemConsumer[targetNamespace]; + const webPath = namespaceConsumer?.webPath || ''; + const id = getIdFromGraphQLId(itemConsumer.item.id); + const itemTypePath = AI_CATALOG_ITEM_PLURAL_LABELS[itemConsumer.item.itemType]; + + return `${webPath}/-/automate/${itemTypePath}/${id}`; +}; + /** * Note that this utility method *does not* use the `pinnedItemVersion`. */ diff --git a/ee/app/assets/javascripts/ai/duo_agents_platform/pages/agents/ai_agents_index.vue b/ee/app/assets/javascripts/ai/duo_agents_platform/pages/agents/ai_agents_index.vue index f0b61b92ed30b7730da6716359bcb0d8cb1ccfd4..b3d7b8e38b35577dcb89a393317d6ef259cc7b6b 100644 --- a/ee/app/assets/javascripts/ai/duo_agents_platform/pages/agents/ai_agents_index.vue +++ b/ee/app/assets/javascripts/ai/duo_agents_platform/pages/agents/ai_agents_index.vue @@ -1,6 +1,7 @@