diff --git a/app/assets/javascripts/ml/model_registry/apps/show_ml_model.vue b/app/assets/javascripts/ml/model_registry/apps/show_ml_model.vue index 4f77d9c481768ccca4d216f12d737300ab08c5d9..afb877f2107f6c6aef2932b401d87fa7e7192c5b 100644 --- a/app/assets/javascripts/ml/model_registry/apps/show_ml_model.vue +++ b/app/assets/javascripts/ml/model_registry/apps/show_ml_model.vue @@ -186,6 +186,9 @@ export default { showModelLatestVersion() { return Boolean(this.model?.latestVersion); }, + showDefaultExperiment() { + return this.model?.defaultExperimentPath; + }, }, methods: { goTo(name) { @@ -220,6 +223,8 @@ export default { latestVersionTitle: s__('MlModelRegistry|Latest version'), authorTitle: s__('MlModelRegistry|Publisher'), noneText: __('None'), + experimentTitle: s__('MlModelRegistry|Experiment'), + defaultExperimentPath: s__('MlModelRegistry|Default experiment'), }, modelVersionEntity: MODEL_ENTITIES.modelVersion, ROUTE_DETAILS, @@ -326,6 +331,19 @@ export default { <span v-else>{{ $options.i18n.noneText }}</span> </div> </div> + <div v-if="showDefaultExperiment" class="gl-mt-5"> + <div class="gl-text-lg gl-font-bold" data-testid="sidebar-experiment-title"> + {{ $options.i18n.experimentTitle }} + </div> + <div class="gl-pt-2 gl-text-subtle" data-testid="sidebar-experiment-label"> + <gl-link + data-testid="sidebar-latest-experiment-link" + :href="model.defaultExperimentPath" + > + {{ $options.i18n.defaultExperimentPath }} + </gl-link> + </div> + </div> <div class="gl-mt-5"> <div class="gl-text-lg gl-font-bold">{{ $options.i18n.latestVersionTitle }}</div> <div class="gl-pt-2 gl-text-subtle" data-testid="sidebar-latest-version"> diff --git a/app/assets/javascripts/ml/model_registry/graphql/queries/get_model.query.graphql b/app/assets/javascripts/ml/model_registry/graphql/queries/get_model.query.graphql index 06dcfeecb5c1a3854ef866c273eca86551b26218..4d6b1683204c826bcc7acc109b60e1bfd17f6672 100644 --- a/app/assets/javascripts/ml/model_registry/graphql/queries/get_model.query.graphql +++ b/app/assets/javascripts/ml/model_registry/graphql/queries/get_model.query.graphql @@ -13,6 +13,7 @@ query getModel($id: MlModelID!) { name versionCount candidateCount + defaultExperimentPath latestVersion { id createdAt diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 4f36ec83756b4214566071e0945ca860f7c3092f..1d02c2cbd42e64f84ff48c4bb77295c8bca5849e 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -35319,6 +35319,9 @@ msgstr "" msgid "MlModelRegistry|Creating models, model versions and candidates is also possible using the MLflow client:" msgstr "" +msgid "MlModelRegistry|Default experiment" +msgstr "" + msgid "MlModelRegistry|Delete model" msgstr "" diff --git a/spec/frontend/ml/model_registry/apps/show_ml_model_spec.js b/spec/frontend/ml/model_registry/apps/show_ml_model_spec.js index d9374c03d042b952d00b3435912e937209a66678..89e2998a44df8036a057dc02a1ba8535cd94d572 100644 --- a/spec/frontend/ml/model_registry/apps/show_ml_model_spec.js +++ b/spec/frontend/ml/model_registry/apps/show_ml_model_spec.js @@ -359,6 +359,8 @@ describe('ml/model_registry/apps/show_ml_model', () => { const findAvatar = () => wrapper.findComponent(GlAvatar); const findLatestVersionLink = () => wrapper.findByTestId('sidebar-latest-version-link'); const findVersionCount = () => wrapper.findByTestId('sidebar-version-count'); + const findExperimentTitle = () => wrapper.findByTestId('sidebar-experiment-title'); + const findExperiment = () => wrapper.findByTestId('sidebar-experiment-label'); it('displays sidebar author link', () => { expect(findSidebarAuthorLink().attributes('href')).toBe('path/to/user'); @@ -388,6 +390,22 @@ describe('ml/model_registry/apps/show_ml_model', () => { expect(findVersionCount().text()).toBe('1'); }); + describe('displays experiment information', () => { + it('displays experiment title', () => { + expect(findExperimentTitle().text()).toBe('Experiment'); + }); + + it('displays experiment label', () => { + expect(findExperiment().text()).toBe('Default experiment'); + }); + + it('shows a link to the default experiment', () => { + expect(findExperiment().findComponent(GlLink).attributes('href')).toBe( + 'path/to/experiment', + ); + }); + }); + describe('when model does not get loaded', () => { const error = new Error('Failure!'); beforeEach(() => createWrapper({ modelDetailsResolver: jest.fn().mockRejectedValue(error) })); @@ -403,6 +421,11 @@ describe('ml/model_registry/apps/show_ml_model', () => { it('does not display sidebar version count', () => { expect(findVersionCount().text()).toBe('None'); }); + + it('does not display sidebar experiment information', () => { + expect(findExperimentTitle().exists()).toBe(false); + expect(findExperiment().exists()).toBe(false); + }); }); }); }); diff --git a/spec/frontend/ml/model_registry/graphql_mock_data.js b/spec/frontend/ml/model_registry/graphql_mock_data.js index 299990666491f62c537a235c6c13bec058a38435..ea0c16323910b38be9b977b78643570d118e64ad 100644 --- a/spec/frontend/ml/model_registry/graphql_mock_data.js +++ b/spec/frontend/ml/model_registry/graphql_mock_data.js @@ -392,6 +392,7 @@ export const model = { avatarUrl: 'path/to/avatar', webUrl: 'path/to/user', }, + defaultExperimentPath: 'path/to/experiment', description: 'A model description', descriptionHtml: 'A model description', name: 'gitlab_amazing_model', @@ -408,6 +409,7 @@ export const modelWithNoVersion = { createdAt: '2023-12-06T12:41:48Z', description: 'A model description', descriptionHtml: 'A model description', + defaultExperimentPath: 'path/to/experiment', author: { id: 'gid://gitlab/User/1', name: 'name',