Skip to content
代码片段 群组 项目
未验证 提交 05cdd0ad 编辑于 作者: Alper Akgun's avatar Alper Akgun
浏览文件

Hide "Delete experiment" for model experiment without permission

Changelog: changed
上级 67c701bb
No related branches found
No related tags found
无相关合并请求
显示
59 个添加17 个删除
......@@ -19,7 +19,7 @@ export default {
},
mixins: [timeagoMixin],
props: {
info: {
candidate: {
type: Object,
required: true,
},
......@@ -34,6 +34,9 @@ export default {
statusVariant() {
return this.$options.statusVariants[this.info.status];
},
info() {
return this.candidate.info;
},
},
i18n: {
deleteCandidateConfirmationMessage: s__(
......@@ -87,6 +90,7 @@ export default {
{{ $options.i18n.promoteText }}
</gl-button>
<delete-button
v-if="candidate.canWriteModelExperiments"
:delete-path="info.path"
:delete-confirmation-text="$options.i18n.deleteCandidateConfirmationMessage"
:action-primary-text="$options.i18n.deleteCandidatePrimaryActionLabel"
......
......@@ -14,17 +14,12 @@ export default {
required: true,
},
},
computed: {
info() {
return Object.freeze(this.candidate.info);
},
},
};
</script>
<template>
<div>
<candidate-header :info="info" />
<candidate-header :candidate="candidate" />
<candidate-detail :candidate="candidate" />
</div>
</template>
......@@ -89,6 +89,10 @@ export default {
required: false,
default: '',
},
canWriteModelExperiments: {
type: Boolean,
required: true,
},
},
data() {
return {
......@@ -114,7 +118,7 @@ export default {
return s__('MlExperimentTracking|Experiment created %{timeAgo} by %{author}');
},
showDeleteButton() {
return !this.experiment.model_id;
return !this.experiment.model_id && this.canWriteModelExperiments;
},
},
methods: {
......
......@@ -26,6 +26,7 @@ const initShowExperiment = () => {
pageInfo,
emptyStateSvgPath,
mlflowTrackingUrl,
canWriteModelExperiments,
} = element.dataset;
const props = {
......@@ -36,6 +37,7 @@ const initShowExperiment = () => {
pageInfo: convertObjectPropsToCamelCase(JSON.parse(pageInfo)),
emptyStateSvgPath,
mlflowTrackingUrl,
canWriteModelExperiments: Boolean(canWriteModelExperiments),
};
return new Vue({
......
......@@ -34,6 +34,7 @@ def present
metadata: candidate.metadata,
projectPath: candidate.project.full_path,
can_write_model_registry: current_user&.can?(:write_model_registry, candidate.project),
can_write_model_experiments: current_user&.can?(:write_model_experiments, candidate.project),
markdown_preview_path: project_preview_markdown_path(candidate.project),
model_gid: candidate.experiment.model&.to_global_id.to_s,
latest_version: candidate.experiment.model&.latest_version&.version
......
......@@ -17,4 +17,5 @@
page_info: page_info,
empty_state_svg_path: image_path('illustrations/status/status-new-md.svg'),
mlflow_tracking_url: mlflow_tracking_url(@project),
can_write_model_experiments: current_user&.can?(:write_model_experiments, @project)
} }
......@@ -10,7 +10,7 @@ describe('ml/experiment_tracking/routes/candidates/show/candidate_header.vue', (
let wrapper;
const defaultProps = {
info: newCandidate().info,
candidate: newCandidate(),
};
const createWrapper = (props = {}) => {
......@@ -84,9 +84,12 @@ describe('ml/experiment_tracking/routes/candidates/show/candidate_header.vue', (
testCases.forEach(({ status, variant }) => {
it(`renders correct badge variant for ${status} status`, () => {
wrapper = createWrapper({
info: {
...defaultProps.info,
status,
candidate: {
...defaultProps.candidate,
info: {
...defaultProps.candidate.info,
status,
},
},
});
......@@ -98,10 +101,13 @@ describe('ml/experiment_tracking/routes/candidates/show/candidate_header.vue', (
describe('When author is not provided', () => {
beforeEach(() => {
wrapper = createWrapper({
info: {
...defaultProps.info,
authorName: null,
authorWebUrl: null,
candidate: {
...defaultProps.candidate,
info: {
...defaultProps.candidate.info,
authorName: null,
authorWebUrl: null,
},
},
});
});
......@@ -127,6 +133,21 @@ describe('ml/experiment_tracking/routes/candidates/show/candidate_header.vue', (
});
});
});
describe('When can not write to model experiments', () => {
beforeEach(() => {
wrapper = createWrapper({
candidate: {
...defaultProps.candidate,
canWriteModelExperiments: false,
},
});
});
it('hides the delete button', () => {
const deleteButton = findDeleteButton();
expect(deleteButton.exists()).toBe(false);
});
});
describe('Promote button', () => {
beforeEach(() => {
......
......@@ -20,7 +20,7 @@ describe('MlCandidatesShow', () => {
beforeEach(() => createWrapper());
it('creates the candidate header section', () => {
expect(findCandidateHeader().props('info')).toBe(candidate.info);
expect(findCandidateHeader().props('candidate')).toBe(candidate);
});
it('creates the candidate detail section', () => {
......
......@@ -62,6 +62,7 @@ describe('MlExperimentsShow', () => {
emptyStateSvgPath = 'path',
mountFn = shallowMountExtended,
mlflowTrackingUrl = 'mlflow/tracking/url',
canWriteModelExperiments = true,
} = {}) => {
wrapper = mountFn(MlExperimentsShow, {
propsData: {
......@@ -72,6 +73,7 @@ describe('MlExperimentsShow', () => {
pageInfo,
emptyStateSvgPath,
mlflowTrackingUrl,
canWriteModelExperiments,
},
stubs: { GlTabs, GlBadge, CandidateList, GlSprintf, TimeAgoTooltip },
});
......@@ -129,6 +131,16 @@ describe('MlExperimentsShow', () => {
});
});
describe('Delete with no permission', () => {
beforeEach(() => {
createWrapper({ canWriteModelExperiments: false });
});
it('does not show delete button', () => {
expect(findDeleteButton().exists()).toBe(false);
});
});
describe('With model id', () => {
beforeEach(() => {
createWrapper({ experiment: MOCK_MODEL_EXPERIMENT });
......
......@@ -46,6 +46,7 @@ export const newCandidate = () => ({
},
projectPath: 'some/project',
canWriteModelRegistry: true,
canWriteModelExperiments: true,
markdownPreviewPath: '/markdown-preview',
modelGid: 'gid://gitlab/Ml::Model/1',
latestVersion: '1.0.2',
......
......@@ -86,6 +86,7 @@
metadata: [],
projectPath: project.full_path,
can_write_model_registry: false,
can_write_model_experiments: false,
markdown_preview_path: "/#{project.full_path}/-/preview_markdown",
model_gid: '',
latest_version: nil
......
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册