diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2024-01-03 18:11:11 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2024-01-03 18:11:11 +0300 |
commit | 5429e3d4e0d5f1601ff8989bcb26bd822b3c7c5a (patch) | |
tree | 0f08e912ce115cd8ad0a5bdc0717fc64aae59c85 /app/assets | |
parent | 3682bf2cf22082c9b57c99b50816fdfe98629792 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets')
7 files changed, 170 insertions, 3 deletions
diff --git a/app/assets/javascripts/ml/model_registry/apps/index.js b/app/assets/javascripts/ml/model_registry/apps/index.js index 92d159f68be..60fe5dfa804 100644 --- a/app/assets/javascripts/ml/model_registry/apps/index.js +++ b/app/assets/javascripts/ml/model_registry/apps/index.js @@ -1,5 +1,6 @@ import ShowMlModel from './show_ml_model.vue'; import ShowMlModelVersion from './show_ml_model_version.vue'; import IndexMlModels from './index_ml_models.vue'; +import NewMlModel from './new_ml_model.vue'; -export { ShowMlModel, ShowMlModelVersion, IndexMlModels }; +export { ShowMlModel, ShowMlModelVersion, IndexMlModels, NewMlModel }; diff --git a/app/assets/javascripts/ml/model_registry/apps/index_ml_models.vue b/app/assets/javascripts/ml/model_registry/apps/index_ml_models.vue index e5e093db5ca..3956a1f86e8 100644 --- a/app/assets/javascripts/ml/model_registry/apps/index_ml_models.vue +++ b/app/assets/javascripts/ml/model_registry/apps/index_ml_models.vue @@ -1,6 +1,6 @@ <script> import { isEmpty } from 'lodash'; -import { GlBadge } from '@gitlab/ui'; +import { GlBadge, GlButton } from '@gitlab/ui'; import Pagination from '~/vue_shared/components/incubation/pagination.vue'; import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue'; import TitleArea from '~/vue_shared/components/registry/title_area.vue'; @@ -21,6 +21,7 @@ export default { TitleArea, GlBadge, EmptyState, + GlButton, }, props: { models: { @@ -31,11 +32,20 @@ export default { type: Object, required: true, }, + createModelPath: { + type: String, + required: true, + }, modelCount: { type: Number, required: false, default: 0, }, + canWriteModelRegistry: { + type: Boolean, + required: false, + default: false, + }, }, computed: { hasModels() { @@ -63,6 +73,11 @@ export default { <template #metadata-models-count> <metadata-item icon="machine-learning" :text="$options.i18n.modelsCountLabel(modelCount)" /> </template> + <template #right-actions> + <gl-button v-if="canWriteModelRegistry" :href="createModelPath">{{ + $options.i18n.CREATE_MODEL_LABEL + }}</gl-button> + </template> </title-area> <template v-if="hasModels"> <search-bar :sortable-fields="$options.sortableFields" /> diff --git a/app/assets/javascripts/ml/model_registry/apps/new_ml_model.vue b/app/assets/javascripts/ml/model_registry/apps/new_ml_model.vue new file mode 100644 index 00000000000..618d4cea1a5 --- /dev/null +++ b/app/assets/javascripts/ml/model_registry/apps/new_ml_model.vue @@ -0,0 +1,127 @@ +<script> +import { + GlForm, + GlFormGroup, + GlFormInput, + GlFormTextarea, + GlAlert, + GlButton, + GlLink, + GlSprintf, +} from '@gitlab/ui'; +import TitleArea from '~/vue_shared/components/registry/title_area.vue'; +import { visitUrl } from '~/lib/utils/url_utility'; +import * as Sentry from '~/sentry/sentry_browser_wrapper'; +import { helpPagePath } from '~/helpers/help_page_helper'; +import createModelMutation from '../graphql/mutations/create_model.mutation.graphql'; +import { + NEW_MODEL_LABEL, + ERROR_CREATING_MODEL_LABEL, + CREATE_MODEL_WITH_CLIENT_LABEL, + NAME_LABEL, + DESCRIPTION_LABEL, + CREATE_MODEL_LABEL, +} from '../translations'; + +export default { + name: 'NewMlModel', + components: { + TitleArea, + GlForm, + GlFormInput, + GlFormGroup, + GlFormTextarea, + GlAlert, + GlButton, + GlLink, + GlSprintf, + }, + props: { + projectPath: { + type: String, + required: true, + }, + }, + data() { + return { + errorMessage: '', + modelName: '', + modelDescription: '', + }; + }, + methods: { + async createModel() { + this.errorMessage = ''; + try { + const variables = { + projectPath: this.projectPath, + name: this.modelName, + description: this.modelDescription, + }; + + const { data } = await this.$apollo.mutate({ + mutation: createModelMutation, + variables, + }); + + const [error] = data?.mlModelCreate?.errors || []; + + if (error) { + this.errorMessage = data.mlModelCreate.errors.join(', '); + } else { + visitUrl(data?.mlModelCreate?.model?._links?.showPath); + } + } catch (error) { + Sentry.captureException(error); + this.errorMessage = ERROR_CREATING_MODEL_LABEL; + } + }, + }, + i18n: { + NEW_MODEL_LABEL, + CREATE_MODEL_WITH_CLIENT_LABEL, + NAME_LABEL, + DESCRIPTION_LABEL, + CREATE_MODEL_LABEL, + }, + docHref: helpPagePath('user/project/ml/model_registry/index.md'), +}; +</script> + +<template> + <div> + <title-area :title="$options.i18n.NEW_MODEL_LABEL" /> + + <gl-alert variant="tip" icon="bulb" class="gl-mb-3" :dismissible="false"> + <gl-sprintf :message="$options.i18n.CREATE_MODEL_WITH_CLIENT_LABEL"> + <template #link="{ content }"> + <gl-link :href="$options.docHref" target="_blank">{{ content }}</gl-link> + </template> + </gl-sprintf> + </gl-alert> + + <gl-alert + v-if="errorMessage" + :dismissible="false" + variant="danger" + class="gl-mb-3" + data-testid="new-model-errors" + > + {{ errorMessage }} + </gl-alert> + + <gl-form @submit.prevent="createModel"> + <gl-form-group :label="$options.i18n.NAME_LABEL"> + <gl-form-input v-model="modelName" /> + </gl-form-group> + + <gl-form-group :label="$options.i18n.DESCRIPTION_LABEL" optional> + <gl-form-textarea v-model="modelDescription" /> + </gl-form-group> + + <gl-button type="submit" variant="confirm" class="js-no-auto-disable">{{ + $options.i18n.CREATE_MODEL_LABEL + }}</gl-button> + </gl-form> + </div> +</template> diff --git a/app/assets/javascripts/ml/model_registry/graphql/mutations/create_model.mutation.graphql b/app/assets/javascripts/ml/model_registry/graphql/mutations/create_model.mutation.graphql new file mode 100644 index 00000000000..af801474e80 --- /dev/null +++ b/app/assets/javascripts/ml/model_registry/graphql/mutations/create_model.mutation.graphql @@ -0,0 +1,11 @@ +mutation createModel($projectPath: ID!, $name: String!, $description: String) { + mlModelCreate(input: { projectPath: $projectPath, name: $name, description: $description }) { + model { + id + _links { + showPath + } + } + errors + } +} diff --git a/app/assets/javascripts/ml/model_registry/translations.js b/app/assets/javascripts/ml/model_registry/translations.js index 968ec83434d..006142979e2 100644 --- a/app/assets/javascripts/ml/model_registry/translations.js +++ b/app/assets/javascripts/ml/model_registry/translations.js @@ -32,6 +32,15 @@ export const CI_SECTION_LABEL = s__('MlModelRegistry|CI Info'); export const JOB_LABEL = __('Job'); export const CI_USER_LABEL = s__('MlModelRegistry|Triggered by'); export const CI_MR_LABEL = __('Merge request'); +export const NEW_MODEL_LABEL = s__('MlModelRegistry|New model'); +export const CREATE_MODEL_LABEL = s__('MlModelRegistry|Create model'); +export const ERROR_CREATING_MODEL_LABEL = s__( + 'MlModelRegistry|An error has occurred when saving the model.', +); +export const CREATE_MODEL_WITH_CLIENT_LABEL = s__( + 'MlModelRegistry|Creating models is also possible through the MLflow client. %{linkStart}Follow the documentation to learn more.%{linkEnd}', +); +export const NAME_LABEL = __('Name'); export const makeLoadVersionsErrorMessage = (message) => sprintf(s__('MlModelRegistry|Failed to load model versions with error: %{message}'), { diff --git a/app/assets/javascripts/pages/projects/ml/models/index/index.js b/app/assets/javascripts/pages/projects/ml/models/index/index.js index 3f8ef4910a7..54dcf28164f 100644 --- a/app/assets/javascripts/pages/projects/ml/models/index/index.js +++ b/app/assets/javascripts/pages/projects/ml/models/index/index.js @@ -1,4 +1,4 @@ import { initSimpleApp } from '~/helpers/init_simple_app_helper'; import { IndexMlModels } from '~/ml/model_registry/apps'; -initSimpleApp('#js-index-ml-models', IndexMlModels); +initSimpleApp('#js-index-ml-models', IndexMlModels, { withApolloProvider: true }); diff --git a/app/assets/javascripts/pages/projects/ml/models/new/index.js b/app/assets/javascripts/pages/projects/ml/models/new/index.js new file mode 100644 index 00000000000..8dc5c5aea4e --- /dev/null +++ b/app/assets/javascripts/pages/projects/ml/models/new/index.js @@ -0,0 +1,4 @@ +import { initSimpleApp } from '~/helpers/init_simple_app_helper'; +import { NewMlModel } from '~/ml/model_registry/apps'; + +initSimpleApp('#js-mount-new-ml-model', NewMlModel, { withApolloProvider: true }); |