From 6d5ae6725799ca3985f80032fcd33b03f585c1c0 Mon Sep 17 00:00:00 2001 From: Florie Guibert Date: Fri, 6 Jun 2025 12:59:13 +1000 Subject: [PATCH 1/3] chore: Add AI catalog page behind FF Behind `:global_ai_catalog` feature flag --- .../javascripts/ai/catalog/ai_catalog_app.vue | 3 + .../graphql/user_workflows.query.graphql | 12 ++ app/assets/javascripts/ai/catalog/index.js | 67 +++++++ .../ai/catalog/pages/ai_catalog_index.vue | 41 ++++ .../ai/catalog/router/constants.js | 1 + .../javascripts/ai/catalog/router/index.js | 14 ++ .../pages/explore/ai_catalog/index.js | 3 + .../explore/ai_catalog_controller.rb | 18 ++ app/views/explore/ai_catalog/show.html.haml | 3 + .../development/global_ai_catalog.yml | 8 + config/routes/explore.rb | 1 + lib/sidebars/explore/menus/ai_catalog_menu.rb | 34 ++++ lib/sidebars/explore/panel.rb | 1 + locale/gitlab.pot | 12 ++ .../explore/ai_catalog_controller_spec.rb | 188 ++++++++++++++++++ spec/frontend/ai/catalog/index_spec.js | 45 +++++ .../ai/catalog/pages/ai_catalog_index_spec.js | 111 +++++++++++ .../explore/menus/ai_catalog_menu_spec.rb | 70 +++++++ .../navbar_structure_context.rb | 4 + 19 files changed, 636 insertions(+) create mode 100644 app/assets/javascripts/ai/catalog/ai_catalog_app.vue create mode 100644 app/assets/javascripts/ai/catalog/graphql/user_workflows.query.graphql create mode 100644 app/assets/javascripts/ai/catalog/index.js create mode 100644 app/assets/javascripts/ai/catalog/pages/ai_catalog_index.vue create mode 100644 app/assets/javascripts/ai/catalog/router/constants.js create mode 100644 app/assets/javascripts/ai/catalog/router/index.js create mode 100644 app/assets/javascripts/pages/explore/ai_catalog/index.js create mode 100644 app/controllers/explore/ai_catalog_controller.rb create mode 100644 app/views/explore/ai_catalog/show.html.haml create mode 100644 config/feature_flags/development/global_ai_catalog.yml create mode 100644 lib/sidebars/explore/menus/ai_catalog_menu.rb create mode 100644 spec/controllers/explore/ai_catalog_controller_spec.rb create mode 100644 spec/frontend/ai/catalog/index_spec.js create mode 100644 spec/frontend/ai/catalog/pages/ai_catalog_index_spec.js create mode 100644 spec/lib/sidebars/explore/menus/ai_catalog_menu_spec.rb diff --git a/app/assets/javascripts/ai/catalog/ai_catalog_app.vue b/app/assets/javascripts/ai/catalog/ai_catalog_app.vue new file mode 100644 index 00000000000000..98240aef8109ab --- /dev/null +++ b/app/assets/javascripts/ai/catalog/ai_catalog_app.vue @@ -0,0 +1,3 @@ + diff --git a/app/assets/javascripts/ai/catalog/graphql/user_workflows.query.graphql b/app/assets/javascripts/ai/catalog/graphql/user_workflows.query.graphql new file mode 100644 index 00000000000000..0f02a5cf39cc03 --- /dev/null +++ b/app/assets/javascripts/ai/catalog/graphql/user_workflows.query.graphql @@ -0,0 +1,12 @@ +query userWorkflows { + currentUser @client { + id + workflows { + nodes { + id + type + name + } + } + } +} diff --git a/app/assets/javascripts/ai/catalog/index.js b/app/assets/javascripts/ai/catalog/index.js new file mode 100644 index 00000000000000..3bd0b8d3c2cee5 --- /dev/null +++ b/app/assets/javascripts/ai/catalog/index.js @@ -0,0 +1,67 @@ +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; + +import { s__ } from '~/locale'; +import createDefaultClient from '~/lib/graphql'; +import { cacheConfig, resolvers } from '~/ci/catalog/graphql/settings'; + +import AiCatalogApp from './ai_catalog_app.vue'; +import { createRouter } from './router'; + +import userWorkflowsQuery from './graphql/user_workflows.query.graphql'; + +export const initAiCatalog = (selector = '#js-ai-catalog') => { + const el = document.querySelector(selector); + + if (!el) { + return null; + } + + const { dataset } = el; + const { aiCatalogIndexPath } = dataset; + + Vue.use(VueApollo); + + const apolloProvider = new VueApollo({ + defaultClient: createDefaultClient(resolvers, cacheConfig), + }); + + /* eslint-disable @gitlab/require-i18n-strings */ + apolloProvider.clients.defaultClient.cache.writeQuery({ + query: userWorkflowsQuery, + data: { + currentUser: { + id: 1, + workflows: { + nodes: [ + { + id: 1, + name: 'Workflow 1', + type: 'Type 1', + }, + { + id: 2, + name: 'Workflow 2', + type: 'Type 2', + }, + ], + }, + }, + }, + }); + /* eslint-enable @gitlab/require-i18n-strings */ + + return new Vue({ + el, + name: 'AiCatalogApp', + router: createRouter(aiCatalogIndexPath), + apolloProvider, + provide: { + pageTitle: s__('AI|AI Catalog'), + pageDescription: s__('AI|A catalog of AI agents and workflows.'), + }, + render(h) { + return h(AiCatalogApp); + }, + }); +}; diff --git a/app/assets/javascripts/ai/catalog/pages/ai_catalog_index.vue b/app/assets/javascripts/ai/catalog/pages/ai_catalog_index.vue new file mode 100644 index 00000000000000..04865f3e9d995b --- /dev/null +++ b/app/assets/javascripts/ai/catalog/pages/ai_catalog_index.vue @@ -0,0 +1,41 @@ + + diff --git a/app/assets/javascripts/ai/catalog/router/constants.js b/app/assets/javascripts/ai/catalog/router/constants.js new file mode 100644 index 00000000000000..9186c11f44510b --- /dev/null +++ b/app/assets/javascripts/ai/catalog/router/constants.js @@ -0,0 +1 @@ +export const AI_CATALOG_INDEX = 'ai-catalog'; diff --git a/app/assets/javascripts/ai/catalog/router/index.js b/app/assets/javascripts/ai/catalog/router/index.js new file mode 100644 index 00000000000000..be2b393803ab64 --- /dev/null +++ b/app/assets/javascripts/ai/catalog/router/index.js @@ -0,0 +1,14 @@ +import Vue from 'vue'; +import VueRouter from 'vue-router'; +import AiCatalogIndex from '../pages/ai_catalog_index.vue'; +import { AI_CATALOG_INDEX } from './constants'; + +Vue.use(VueRouter); + +export const createRouter = (base) => { + return new VueRouter({ + base, + mode: 'history', + routes: [{ name: AI_CATALOG_INDEX, path: '', component: AiCatalogIndex, alias: '/ai-catalog' }], + }); +}; diff --git a/app/assets/javascripts/pages/explore/ai_catalog/index.js b/app/assets/javascripts/pages/explore/ai_catalog/index.js new file mode 100644 index 00000000000000..cc2c37a7b92a95 --- /dev/null +++ b/app/assets/javascripts/pages/explore/ai_catalog/index.js @@ -0,0 +1,3 @@ +import { initAiCatalog } from '~/ai/catalog/'; + +initAiCatalog(); diff --git a/app/controllers/explore/ai_catalog_controller.rb b/app/controllers/explore/ai_catalog_controller.rb new file mode 100644 index 00000000000000..4d1f242b35d5e8 --- /dev/null +++ b/app/controllers/explore/ai_catalog_controller.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module Explore + class AiCatalogController < Explore::ApplicationController + feature_category :not_owned # rubocop:todo Gitlab/AvoidFeatureCategoryNotOwned -- unknown + before_action :check_feature_flag + + def index + render 'show' + end + + private + + def check_feature_flag + render_404 unless Feature.enabled?(:global_ai_catalog, current_user) + end + end +end diff --git a/app/views/explore/ai_catalog/show.html.haml b/app/views/explore/ai_catalog/show.html.haml new file mode 100644 index 00000000000000..0cfbcf90a095b9 --- /dev/null +++ b/app/views/explore/ai_catalog/show.html.haml @@ -0,0 +1,3 @@ +- page_title _('AI Catalog') + +#js-ai-catalog{ data: { ai_catalog_index_path: explore_ai_catalog_index_path } } diff --git a/config/feature_flags/development/global_ai_catalog.yml b/config/feature_flags/development/global_ai_catalog.yml new file mode 100644 index 00000000000000..78c5e06f6bdd19 --- /dev/null +++ b/config/feature_flags/development/global_ai_catalog.yml @@ -0,0 +1,8 @@ +--- +name: global_ai_catalog +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/193705 +rollout_issue_url: +milestone: '18.2' +type: development +group: group::workflow catalog +default_enabled: false diff --git a/config/routes/explore.rb b/config/routes/explore.rb index 7716015babaab8..4576db9074b657 100644 --- a/config/routes/explore.rb +++ b/config/routes/explore.rb @@ -15,6 +15,7 @@ get '/' => 'catalog#index', as: :catalog_index get '/*full_path' => 'catalog#show', as: :catalog, constraints: { full_path: /.*/ } end + resources :ai_catalog, only: [:index], path: 'ai-catalog' resources :snippets, only: [:index] root to: 'projects#index' end diff --git a/lib/sidebars/explore/menus/ai_catalog_menu.rb b/lib/sidebars/explore/menus/ai_catalog_menu.rb new file mode 100644 index 00000000000000..406f34820b43b4 --- /dev/null +++ b/lib/sidebars/explore/menus/ai_catalog_menu.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Sidebars # rubocop: disable Gitlab/BoundedContexts -- unknown + module Explore + module Menus + class AiCatalogMenu < ::Sidebars::Menu + override :link + def link + explore_ai_catalog_index_path + end + + override :title + def title + _('AI Catalog') + end + + override :sprite_icon + def sprite_icon + 'tanuki-ai' + end + + override :render? + def render? + Feature.enabled?(:global_ai_catalog, current_user) + end + + override :active_routes + def active_routes + { controller: ['explore/ai_catalog'] } + end + end + end + end +end diff --git a/lib/sidebars/explore/panel.rb b/lib/sidebars/explore/panel.rb index a50e18fd0ff0d3..970719e3d3efd6 100644 --- a/lib/sidebars/explore/panel.rb +++ b/lib/sidebars/explore/panel.rb @@ -24,6 +24,7 @@ def add_menus add_menu(Sidebars::Explore::Menus::ProjectsMenu.new(context)) add_menu(Sidebars::Explore::Menus::GroupsMenu.new(context)) add_menu(Sidebars::Explore::Menus::CatalogMenu.new(context)) + add_menu(Sidebars::Explore::Menus::AiCatalogMenu.new(context)) add_menu(Sidebars::Explore::Menus::TopicsMenu.new(context)) add_menu(Sidebars::Explore::Menus::SnippetsMenu.new(context)) end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index f177ec32cd9037..8fae884eb62692 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2308,6 +2308,9 @@ msgstr "" msgid "AI Agent was successfully deleted" msgstr "" +msgid "AI Catalog" +msgstr "" + msgid "AI Gateway" msgstr "" @@ -2395,6 +2398,15 @@ msgstr "" msgid "AISummary|View summary" msgstr "" +msgid "AI|A catalog of AI agents and workflows." +msgstr "" + +msgid "AI|AI Catalog" +msgstr "" + +msgid "AI|AI Workflows Catalog" +msgstr "" + msgid "AI|Accept & Insert" msgstr "" diff --git a/spec/controllers/explore/ai_catalog_controller_spec.rb b/spec/controllers/explore/ai_catalog_controller_spec.rb new file mode 100644 index 00000000000000..14b3f8ed30d093 --- /dev/null +++ b/spec/controllers/explore/ai_catalog_controller_spec.rb @@ -0,0 +1,188 @@ +# frozen_string_literal: true + +require 'spec_helper' + +# rubocop:disable RSpec/FeatureCategory -- unknown +RSpec.describe Explore::AiCatalogController, :with_current_organization, feature_category: :not_owned do + describe 'GET #index' do + context 'when global_ai_catalog feature flag is enabled' do + before do + stub_feature_flags(global_ai_catalog: true) + end + + context 'when user is signed in' do + let_it_be(:user) { create(:user) } + + before do + sign_in(user) + end + + it 'responds with success' do + get :index + + expect(response).to have_gitlab_http_status(:ok) + end + + it 'renders the show template' do + get :index + + expect(response).to render_template('show') + end + + it 'uses the explore layout' do + get :index + + expect(response).to render_template(layout: 'explore') + end + end + + context 'when user is not signed in' do + it 'responds with success' do + get :index + + expect(response).to have_gitlab_http_status(:ok) + end + + it 'renders the show template' do + get :index + + expect(response).to render_template('show') + end + + it 'uses the explore layout' do + get :index + + expect(response).to render_template(layout: 'explore') + end + end + + context 'when public visibility is restricted' do + before do + stub_application_setting(restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC]) + end + + context 'when user is signed in' do + let_it_be(:user) { create(:user) } + + before do + sign_in(user) + end + + it 'responds with success' do + get :index + + expect(response).to have_gitlab_http_status(:ok) + end + + it 'renders the show template' do + get :index + + expect(response).to render_template('show') + end + end + + context 'when user is not signed in' do + it 'redirects to login page' do + get :index + + expect(response).to redirect_to new_user_session_path + end + end + end + end + + context 'when global_ai_catalog feature flag is disabled' do + before do + stub_feature_flags(global_ai_catalog: false) + end + + context 'when user is signed in' do + let_it_be(:user) { create(:user) } + + before do + sign_in(user) + end + + it 'renders 404' do + get :index + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'when user is not signed in' do + it 'renders 404' do + get :index + + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + + context 'when global_ai_catalog feature flag is enabled for specific user' do + let_it_be(:enabled_user) { create(:user) } + let_it_be(:disabled_user) { create(:user) } + + before do + stub_feature_flags(global_ai_catalog: enabled_user) + end + + context 'when enabled user is signed in' do + before do + sign_in(enabled_user) + end + + it 'responds with success' do + get :index + + expect(response).to have_gitlab_http_status(:ok) + end + + it 'renders the show template' do + get :index + + expect(response).to render_template('show') + end + end + + context 'when disabled user is signed in' do + before do + sign_in(disabled_user) + end + + it 'renders 404' do + get :index + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'when user is not signed in' do + it 'renders 404' do + get :index + + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + end + + describe 'feature category' do + it 'has the correct feature category' do + expect(described_class.feature_category_for_action(:index)).to eq(:not_owned) + end + end + + describe 'inheritance' do + it 'inherits from Explore::ApplicationController' do + expect(described_class.superclass).to eq(Explore::ApplicationController) + end + end + + describe 'before_actions' do + it 'includes check_feature_flag before action' do + expect(described_class._process_action_callbacks.map(&:filter)).to include(:check_feature_flag) + end + end +end +# rubocop:enable RSpec/FeatureCategory diff --git a/spec/frontend/ai/catalog/index_spec.js b/spec/frontend/ai/catalog/index_spec.js new file mode 100644 index 00000000000000..ead86976433911 --- /dev/null +++ b/spec/frontend/ai/catalog/index_spec.js @@ -0,0 +1,45 @@ +import { createWrapper } from '@vue/test-utils'; + +import { initAiCatalog } from '~/ai/catalog/index'; +import AiCatalogApp from '~/ai/catalog/ai_catalog_app.vue'; +import * as Router from '~/ai/catalog/router'; + +describe('AI Catalog Index', () => { + let mockElement; + let wrapper; + + const findAiCatalog = () => wrapper.findComponent(AiCatalogApp); + + afterEach(() => { + mockElement = null; + }); + + describe('initAiCatalog', () => { + beforeEach(() => { + mockElement = document.createElement('div'); + mockElement.id = 'js-ai-catalog'; + mockElement.dataset.aiCatalogIndexPath = '/ai/catalog'; + document.body.appendChild(mockElement); + + jest.spyOn(Router, 'createRouter'); + + wrapper = createWrapper(initAiCatalog(`#${mockElement.id}`)); + }); + + it('renders the AiCatalog component', () => { + expect(findAiCatalog().exists()).toBe(true); + }); + + it('creates router with correct base path', () => { + initAiCatalog(); + + expect(Router.createRouter).toHaveBeenCalledWith('/ai/catalog'); + }); + }); + + describe('When the element does not exist', () => { + it('returns `null`', () => { + expect(initAiCatalog('foo')).toBeNull(); + }); + }); +}); diff --git a/spec/frontend/ai/catalog/pages/ai_catalog_index_spec.js b/spec/frontend/ai/catalog/pages/ai_catalog_index_spec.js new file mode 100644 index 00000000000000..ae3398147c84f0 --- /dev/null +++ b/spec/frontend/ai/catalog/pages/ai_catalog_index_spec.js @@ -0,0 +1,111 @@ +import { GlSkeletonLoader } from '@gitlab/ui'; + +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import waitForPromises from 'helpers/wait_for_promises'; + +import AiCatalogIndex from '~/ai/catalog/pages/ai_catalog_index.vue'; + +describe('AiCatalogIndex', () => { + let wrapper; + + const mockWorkflowsData = [ + { + id: 1, + name: 'Test Workflow 1', + type: 'Type A', + }, + { + id: 2, + name: 'Test Workflow 2', + type: 'Type B', + }, + { + id: 3, + name: 'Test Workflow 3', + type: 'Type C', + }, + ]; + + const emptyWorkflowsData = []; + + const createComponent = ({ loading = false, mockData = mockWorkflowsData } = {}) => { + wrapper = shallowMountExtended(AiCatalogIndex, { + data() { + return { userWorkflows: mockData }; + }, + mocks: { + $apollo: { + queries: { + userWorkflows: { + loading, + }, + }, + }, + }, + }); + + return waitForPromises(); + }; + + const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader); + const findTitle = () => wrapper.find('h1'); + const findAllParagraphs = () => wrapper.findAll('p'); + + describe('component initialization', () => { + it('renders the page title', async () => { + await createComponent(); + + expect(findTitle().text()).toBe('AI Workflows Catalog'); + }); + }); + + describe('loading state', () => { + it('shows skeleton loader when loading', () => { + createComponent({ loading: true }); + + expect(findSkeletonLoader().exists()).toBe(true); + expect(findAllParagraphs()).toHaveLength(0); + }); + }); + + describe('with workflow data', () => { + beforeEach(async () => { + await createComponent(); + }); + + it('displays workflow names and types correctly', () => { + const paragraphs = findAllParagraphs(); + + // Should have 6 paragraphs total (2 per workflow: name and type) + expect(paragraphs).toHaveLength(6); + + // Check workflow names (even indices: 0, 2, 4) + expect(paragraphs.at(0).text()).toBe('Test Workflow 1'); + expect(paragraphs.at(2).text()).toBe('Test Workflow 2'); + expect(paragraphs.at(4).text()).toBe('Test Workflow 3'); + + // Check workflow types (odd indices: 1, 3, 5) + expect(paragraphs.at(1).text()).toBe('Type A'); + expect(paragraphs.at(3).text()).toBe('Type B'); + expect(paragraphs.at(5).text()).toBe('Type C'); + }); + + it('does not show skeleton loader', () => { + expect(findSkeletonLoader().exists()).toBe(false); + }); + }); + + describe('with empty workflow data', () => { + beforeEach(async () => { + await createComponent({ mockData: emptyWorkflowsData }); + }); + + it('renders no workflow paragraphs', () => { + expect(findAllParagraphs()).toHaveLength(0); + }); + + it('does not show skeleton loader', () => { + expect(findSkeletonLoader().exists()).toBe(false); + }); + }); +}); diff --git a/spec/lib/sidebars/explore/menus/ai_catalog_menu_spec.rb b/spec/lib/sidebars/explore/menus/ai_catalog_menu_spec.rb new file mode 100644 index 00000000000000..8eded5a99e7810 --- /dev/null +++ b/spec/lib/sidebars/explore/menus/ai_catalog_menu_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::Explore::Menus::AiCatalogMenu, feature_category: :navigation do + let_it_be(:current_user) { build(:user) } + let_it_be(:user) { build(:user) } + + let(:context) { Sidebars::Context.new(current_user: current_user, container: user) } + + subject(:menu_item) { described_class.new(context) } + + describe '#link' do + it 'matches the expected path pattern' do + expect(menu_item.link).to match %r{explore/ai-catalog} + end + end + + describe '#title' do + it 'returns the correct title' do + expect(menu_item.title).to eq 'AI Catalog' + end + + it 'returns a translated string' do + expect(menu_item.title).to be_a(String) + end + end + + describe '#sprite_icon' do + it 'returns the correct icon' do + expect(menu_item.sprite_icon).to eq 'tanuki-ai' + end + end + + describe '#active_routes' do + it 'returns the correct active routes' do + expect(menu_item.active_routes).to eq({ controller: ['explore/ai_catalog'] }) + end + end + + describe '#render?' do + context 'when global_ai_catalog feature flag is enabled' do + before do + stub_feature_flags(global_ai_catalog: true) + end + + it 'renders the menu' do + expect(menu_item.render?).to be(true) + end + end + + context 'when global_ai_catalog feature flag is disabled' do + before do + stub_feature_flags(global_ai_catalog: false) + end + + it 'does not render the menu' do + expect(menu_item.render?).to be(false) + end + end + end + + describe 'feature flag integration' do + it 'calls Feature.enabled? with correct parameters' do + expect(Feature).to receive(:enabled?).with(:global_ai_catalog, current_user) + + menu_item.render? + end + end +end diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb index b86ac9448e9aa2..6ab76866c9918c 100644 --- a/spec/support/shared_contexts/navbar_structure_context.rb +++ b/spec/support/shared_contexts/navbar_structure_context.rb @@ -302,6 +302,10 @@ nav_item: _("CI/CD Catalog"), nav_sub_items: [] }, + { + nav_item: _("AI Catalog"), + nav_sub_items: [] + }, { nav_item: _("Topics"), nav_sub_items: [] -- GitLab From 36d80945ecbbe139380c00fa2e7c2e5a99f32b8d Mon Sep 17 00:00:00 2001 From: Florie Guibert Date: Thu, 12 Jun 2025 10:37:59 +1000 Subject: [PATCH 2/3] chore: Add AI catalog page behind FF Review feedback --- app/assets/javascripts/ai/catalog/index.js | 8 +- .../ai/catalog/pages/ai_catalog_index.vue | 2 +- .../ai/catalog/router/constants.js | 2 +- .../javascripts/ai/catalog/router/index.js | 11 +- .../explore/ai_catalog_controller.rb | 6 +- .../{show.html.haml => index.html.haml} | 0 lib/sidebars/explore/menus/ai_catalog_menu.rb | 2 +- locale/gitlab.pot | 6 - .../explore/ai_catalog_controller_spec.rb | 134 ++++++++---------- spec/frontend/ai/catalog/index_spec.js | 2 +- .../ai/catalog/pages/ai_catalog_index_spec.js | 2 +- .../explore/menus/ai_catalog_menu_spec.rb | 16 +-- .../navbar_structure_context.rb | 2 +- 13 files changed, 76 insertions(+), 117 deletions(-) rename app/views/explore/ai_catalog/{show.html.haml => index.html.haml} (100%) diff --git a/app/assets/javascripts/ai/catalog/index.js b/app/assets/javascripts/ai/catalog/index.js index 3bd0b8d3c2cee5..a4245863ca80f5 100644 --- a/app/assets/javascripts/ai/catalog/index.js +++ b/app/assets/javascripts/ai/catalog/index.js @@ -1,9 +1,7 @@ import Vue from 'vue'; import VueApollo from 'vue-apollo'; -import { s__ } from '~/locale'; import createDefaultClient from '~/lib/graphql'; -import { cacheConfig, resolvers } from '~/ci/catalog/graphql/settings'; import AiCatalogApp from './ai_catalog_app.vue'; import { createRouter } from './router'; @@ -23,7 +21,7 @@ export const initAiCatalog = (selector = '#js-ai-catalog') => { Vue.use(VueApollo); const apolloProvider = new VueApollo({ - defaultClient: createDefaultClient(resolvers, cacheConfig), + defaultClient: createDefaultClient(), }); /* eslint-disable @gitlab/require-i18n-strings */ @@ -56,10 +54,6 @@ export const initAiCatalog = (selector = '#js-ai-catalog') => { name: 'AiCatalogApp', router: createRouter(aiCatalogIndexPath), apolloProvider, - provide: { - pageTitle: s__('AI|AI Catalog'), - pageDescription: s__('AI|A catalog of AI agents and workflows.'), - }, render(h) { return h(AiCatalogApp); }, diff --git a/app/assets/javascripts/ai/catalog/pages/ai_catalog_index.vue b/app/assets/javascripts/ai/catalog/pages/ai_catalog_index.vue index 04865f3e9d995b..b96f32c7e106b2 100644 --- a/app/assets/javascripts/ai/catalog/pages/ai_catalog_index.vue +++ b/app/assets/javascripts/ai/catalog/pages/ai_catalog_index.vue @@ -27,7 +27,7 @@ export default {