From cf4046fa83d03710c65263f0b482ec4c565a0c9d Mon Sep 17 00:00:00 2001 From: fdegier <fdegier@gitlab.com> Date: Tue, 3 Dec 2024 11:27:10 +0100 Subject: [PATCH] Model registry: Add Experiment to model card Changelog: added # Conflicts: # app/assets/javascripts/ml/model_registry/apps/show_ml_model.vue --- .../ml/model_registry/apps/show_ml_model.vue | 18 +++++++++++++++ .../graphql/queries/get_model.query.graphql | 1 + locale/gitlab.pot | 3 +++ .../model_registry/apps/show_ml_model_spec.js | 23 +++++++++++++++++++ .../ml/model_registry/graphql_mock_data.js | 2 ++ 5 files changed, 47 insertions(+) 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 4f77d9c481768..afb877f2107f6 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 06dcfeecb5c1a..4d6b1683204c8 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 4f36ec83756b4..1d02c2cbd42e6 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 d9374c03d042b..89e2998a44df8 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 299990666491f..ea0c16323910b 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', -- GitLab