Commit 41e0294d authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 7ff73cc4 578ab1bb
......@@ -85,7 +85,11 @@ export default {
role="button"
@click="openFileInEditor"
>
<span class="multi-file-commit-list-file-path d-flex align-items-center">
<span
class="multi-file-commit-list-file-path d-flex align-items-center"
data-qa-selector="file_to_commit_content"
:data-qa-file-name="file.name"
>
<file-icon :file-name="file.name" class="gl-mr-3" />
<template v-if="file.prevName && file.prevName !== file.name">
{{ file.prevName }} &#x2192;
......
......@@ -58,8 +58,9 @@ export default {
<new-entry-button
:label="__('New file')"
:show-label="false"
class="d-flex border-0 p-0 mr-3 qa-new-file"
class="d-flex border-0 p-0 mr-3"
icon="doc-new"
data-qa-selector="new_file_button"
@click="createNewFile()"
/>
<upload
......@@ -73,6 +74,7 @@ export default {
:show-label="false"
class="d-flex border-0 p-0"
icon="folder-new"
data-qa-selector="new_directory_button"
@click="createNewFolder()"
/>
</div>
......
......@@ -90,6 +90,12 @@ export default {
<svg v-else-if="!folder" :key="spriteHref" :class="[iconSizeClass, cssClasses]">
<use v-bind="{ 'xlink:href': spriteHref }" />
</svg>
<gl-icon v-else :name="folderIconName" :size="size" class="folder-icon" />
<gl-icon
v-else
:name="folderIconName"
:size="size"
class="folder-icon"
data-qa-selector="folder_icon_content"
/>
</span>
</template>
......@@ -5,7 +5,7 @@
.col-sm-2.col-form-label
= f.label :projects_limit
.col-sm-10
= f.number_field :projects_limit, min: 0, max: Gitlab::Database::MAX_INT_VALUE, class: 'form-control'
= f.number_field :projects_limit, min: 0, max: Gitlab::Database::MAX_INT_VALUE, class: 'form-control gl-form-input'
.form-group.row
.col-sm-2.col-form-label.gl-pt-0
......
......@@ -4,4 +4,4 @@
.col-sm-2.col-form-label
= f.label :note, s_('AdminNote|Note')
.col-sm-10
= f.text_area :note, class: 'form-control'
= f.text_area :note, class: 'form-control gl-form-input gl-form-textarea'
......@@ -8,19 +8,19 @@
.col-sm-2.col-form-label
= f.label :name
.col-sm-10
= f.text_field :name, required: true, autocomplete: 'off', class: 'form-control'
= f.text_field :name, required: true, autocomplete: 'off', class: 'form-control gl-form-input'
%span.help-inline * required
.form-group.row
.col-sm-2.col-form-label
= f.label :username
.col-sm-10
= f.text_field :username, required: true, autocomplete: 'off', autocorrect: 'off', autocapitalize: 'off', spellcheck: false, class: 'form-control'
= f.text_field :username, required: true, autocomplete: 'off', autocorrect: 'off', autocapitalize: 'off', spellcheck: false, class: 'form-control gl-form-input'
%span.help-inline * required
.form-group.row
.col-sm-2.col-form-label
= f.label :email
.col-sm-10
= f.text_field :email, required: true, autocomplete: 'off', class: 'form-control'
= f.text_field :email, required: true, autocomplete: 'off', class: 'form-control gl-form-input'
%span.help-inline * required
- if @user.new_record?
......@@ -41,12 +41,12 @@
.col-sm-2.col-form-label
= f.label :password
.col-sm-10
= f.password_field :password, disabled: f.object.force_random_password, class: 'form-control'
= f.password_field :password, disabled: f.object.force_random_password, class: 'form-control gl-form-input'
.form-group.row
.col-sm-2.col-form-label
= f.label :password_confirmation
.col-sm-10
= f.password_field :password_confirmation, disabled: f.object.force_random_password, class: 'form-control'
= f.password_field :password_confirmation, disabled: f.object.force_random_password, class: 'form-control gl-form-input'
= render partial: 'access_levels', locals: { f: f }
......@@ -66,22 +66,22 @@
.col-sm-2.col-form-label
= f.label :skype
.col-sm-10
= f.text_field :skype, class: 'form-control'
= f.text_field :skype, class: 'form-control gl-form-input'
.form-group.row
.col-sm-2.col-form-label
= f.label :linkedin
.col-sm-10
= f.text_field :linkedin, class: 'form-control'
= f.text_field :linkedin, class: 'form-control gl-form-input'
.form-group.row
.col-sm-2.col-form-label
= f.label :twitter
.col-sm-10
= f.text_field :twitter, class: 'form-control'
= f.text_field :twitter, class: 'form-control gl-form-input'
.form-group.row
.col-sm-2.col-form-label
= f.label :website_url
.col-sm-10
= f.text_field :website_url, class: 'form-control'
= f.text_field :website_url, class: 'form-control gl-form-input'
= render 'admin/users/admin_notes', f: f
......
---
title: Add tooltips to requirement import and export buttons
merge_request: 52582
author: Kev @KevSlashNull
type: fixed
---
title: Apply new GitLab UI for inputs in admin/users directory
merge_request: 52290
author: Yogi (@yo)
type: other
......@@ -10,7 +10,6 @@ import {
GlLink,
} from '@gitlab/ui';
import { s__ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import DependencyLicenseLinks from './dependency_license_links.vue';
import DependencyVulnerabilities from './dependency_vulnerabilities.vue';
import DependencyLocation from './dependency_location.vue';
......@@ -45,7 +44,6 @@ export default {
GlPopover,
GlLink,
},
mixins: [glFeatureFlagsMixin()],
props: {
dependencies: {
type: Array,
......@@ -115,25 +113,23 @@ export default {
>
<template #head(location)="data">
{{ data.label }}
<template v-if="glFeatures.pathToVulnerableDependency">
<gl-icon id="location-info" name="information" class="gl-text-blue-600" />
<gl-popover
target="location-info"
triggers="hover focus"
placement="top"
:title="s__('Dependencies|Location and dependency path')"
>
{{ $options.i18n.tooltipText }}
<div class="gl-mt-4">
<gl-link
:href="$options.DEPENDENCY_PATH_LINK"
target="_blank"
class="font-size-inherit"
>{{ $options.i18n.tooltipMoreText }}</gl-link
>
</div>
</gl-popover>
</template>
<gl-icon id="location-info" name="information" class="gl-text-blue-600" />
<gl-popover
target="location-info"
triggers="hover focus"
placement="top"
:title="s__('Dependencies|Location and dependency path')"
>
{{ $options.i18n.tooltipText }}
<div class="gl-mt-4">
<gl-link
:href="$options.DEPENDENCY_PATH_LINK"
target="_blank"
class="font-size-inherit"
>{{ $options.i18n.tooltipMoreText }}</gl-link
>
</div>
</gl-popover>
</template>
<!-- toggleDetails and detailsShowing are scoped slot props provided by
......
......@@ -2,7 +2,6 @@
import { GlIcon, GlLink, GlPopover, GlIntersperse } from '@gitlab/ui';
import { n__ } from '~/locale';
import DependencyPathViewer from './dependency_path_viewer.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export const VISIBLE_DEPENDENCY_COUNT = 2;
......@@ -15,7 +14,6 @@ export default {
GlPopover,
GlIntersperse,
},
mixins: [glFeatureFlagsMixin()],
props: {
location: {
type: Object,
......@@ -27,10 +25,10 @@ export default {
return this.location.ancestors || [];
},
hasAncestors() {
return this.glFeatures.pathToVulnerableDependency && this.ancestors.length > 0;
return this.ancestors.length > 0;
},
isTopLevelDependency() {
return this.glFeatures.pathToVulnerableDependency && this.location.top_level;
return this.location.top_level;
},
visibleDependencies() {
return this.ancestors.slice(0, VISIBLE_DEPENDENCY_COUNT);
......@@ -39,7 +37,7 @@ export default {
return Math.max(0, this.ancestors.length - VISIBLE_DEPENDENCY_COUNT);
},
showMoreLink() {
return this.glFeatures.pathToVulnerableDependency && this.remainingDependenciesCount > 0;
return this.remainingDependenciesCount > 0;
},
nMoreMessage() {
return n__('Dependencies|%d more', 'Dependencies|%d more', this.remainingDependenciesCount);
......
<script>
import { GlBadge, GlButton, GlButtonGroup, GlTabs, GlTab } from '@gitlab/ui';
import { GlBadge, GlButton, GlButtonGroup, GlTabs, GlTab, GlTooltipDirective } from '@gitlab/ui';
import { FilterState } from '../constants';
export default {
directives: {
GlTooltip: GlTooltipDirective,
},
FilterState,
components: {
GlBadge,
......@@ -89,6 +92,8 @@ export default {
<gl-button-group>
<gl-button
v-if="showUploadCsv"
v-gl-tooltip
:title="__('Export as CSV')"
category="secondary"
:disabled="showCreateForm"
icon="export"
......@@ -96,6 +101,8 @@ export default {
/>
<gl-button
v-if="showUploadCsv"
v-gl-tooltip
:title="__('Import requirements')"
category="secondary"
class="js-import-requirements qa-import-requirements-button"
:disabled="showCreateForm"
......
......@@ -4,10 +4,6 @@ module Projects
class DependenciesController < Projects::ApplicationController
before_action :authorize_read_dependency_list!
before_action do
push_frontend_feature_flag(:path_to_vulnerable_dependency, project, default_enabled: true)
end
feature_category :dependency_scanning
def index
......
---
name: path_to_vulnerable_dependency
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40627
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/241739
milestone: '13.4'
type: development
group: group::composition analysis
default_enabled: true
......@@ -59,7 +59,6 @@ module Gitlab
path: file_path
}
return base_location if Feature.disabled?(:path_to_vulnerable_dependency, project, default_enabled: true)
return base_location unless dependency['iid']
base_location.merge({
......
......@@ -95,9 +95,11 @@ describe('DependenciesTable component', () => {
it('renders the table header', () => {
const expectedLabels = DependenciesTable.fields.map(({ label }) => label);
const headerCells = wrapper.findAll('thead th').wrappers;
const headerCells = wrapper.findAll('thead th');
expect(headerCells.map((cell) => cell.text())).toEqual(expectedLabels);
expectedLabels.forEach((expectedLabel, i) => {
expect(headerCells.at(i).text()).toContain(expectedLabel);
});
});
it('does not render any rows', () => {
......
......@@ -12,11 +12,6 @@ describe('Dependency Location component', () => {
wrapper = shallowMount(DependencyLocation, {
propsData: { ...propsData },
stubs: { GlLink, DependencyPathViewer, GlIntersperse },
provide: {
glFeatures: {
pathToVulnerableDependency: true,
},
},
...options,
});
};
......@@ -87,23 +82,4 @@ describe('Dependency Location component', () => {
expect(findPopover().exists()).toBe(false);
});
});
describe('with feature flag off', () => {
it.each`
name | location | path
${'no path'} | ${Paths.noPath} | ${'package.json'}
${'top level path'} | ${Paths.topLevelPath} | ${'package.json'}
${'short path'} | ${Paths.shortPath} | ${'package.json'}
${'long path'} | ${Paths.longPath} | ${'package.json'}
`('do not show dependency path for $name', ({ location, path }) => {
createComponent({
propsData: {
location,
},
provide: { glFeatures: { pathToVulnerableDependency: false } },
});
expect(wrapper.text()).toBe(path);
});
});
});
......@@ -67,19 +67,6 @@ RSpec.describe Gitlab::Ci::Parsers::Security::Formatters::DependencyList do
end
end
context 'when feature flag for dependency path is off' do
let(:dependency) { parsed_report['dependency_files'][0]['dependencies'][0] }
let(:location) { data[:location] }
before do
stub_feature_flags(path_to_vulnerable_dependency: false)
end
it { expect(location[:top_level]).to be_nil }
it { expect(location[:ancestors]).to be_nil }
it { expect(location[:path]).to eq('file.path') }
end
context 'with vulnerable dependency' do
let(:data) { formatter.format(dependency, package_manager, file_path, parsed_report['vulnerabilities'].first) }
let(:dependency) { parsed_report['dependency_files'][0]['dependencies'][1] }
......
......@@ -18,7 +18,8 @@ module QA
end
view 'app/assets/javascripts/ide/components/ide_tree.vue' do
element :new_file
element :new_file_button
element :new_directory_button
end
view 'app/assets/javascripts/ide/components/ide_tree_list.vue' do
......@@ -83,6 +84,10 @@ module QA
element :changed_file_icon_content
end
view 'app/assets/javascripts/vue_shared/components/file_icon.vue' do
element :folder_icon_content
end
view 'app/assets/javascripts/vue_shared/components/content_viewer/content_viewer.vue' do
element :preview_container
end
......@@ -99,12 +104,20 @@ module QA
element :file_upload_field
end
view 'app/assets/javascripts/ide/components/commit_sidebar/list_item.vue' do
element :file_to_commit_content
end
def has_file?(file_name)
within_element(:file_list) do
has_text?(file_name)
has_element?(:file_name_content, file_name: file_name)
end
end
def has_file_to_commit?(file_name)
has_element?(:file_to_commit_content, file_name: file_name)
end
def has_project_path?(project_path)
has_element?(:project_path_content, project_path: project_path)
end
......@@ -115,6 +128,12 @@ module QA
end
end
def has_folder_icon?(file_name)
within_element(:file_row_container, file_name: file_name) do
has_element?(:folder_icon_content)
end
end
def has_download_button?(file_name)
click_element(:file_row_container, file_name: file_name)
within_element(:preview_container) do
......@@ -141,7 +160,7 @@ module QA
end
def create_new_file_from_template(file_name, template)
click_element(:new_file, Page::Component::WebIDE::Modal::CreateNewFile)
click_element(:new_file_button, Page::Component::WebIDE::Modal::CreateNewFile)
within_element(:template_list) do
click_on file_name
......@@ -234,7 +253,7 @@ module QA
end
def add_file(file_name, file_text)
click_element(:new_file, Page::Component::WebIDE::Modal::CreateNewFile)
click_element(:new_file_button, Page::Component::WebIDE::Modal::CreateNewFile)
fill_element(:file_name_field, file_name)
click_button('Create file')
wait_until(reload: false) { has_file?(file_name) }
......@@ -243,6 +262,13 @@ module QA
end
end
def add_directory(directory_name)
click_element(:new_directory_button, Page::Component::WebIDE::Modal::CreateNewFile)
fill_element(:file_name_field, directory_name)
click_button('Create directory')
wait_until(reload: false) { has_file?(directory_name) }
end
def rename_file(file_name, new_file_name)
click_element(:file_name_content, file_name: file_name)
click_element(:dropdown_button)
......@@ -273,6 +299,10 @@ module QA
click_element(:dropdown_button)
click_element(:delete_button)
end
def switch_to_commit_tab
click_element(:commit_mode_tab)
end
end
end
end
......
# frozen_string_literal: true
module QA
RSpec.describe 'Create' do
describe 'Add a directory in Web IDE' do
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'add-directory-project'
project.initialize_with_readme = true
end
end
before do
Flow::Login.sign_in
project.visit!
end
context 'when a directory with the same name already exists' do
let(:directory_name) { 'first_directory' }
before do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.add_files([
{
file_path: 'first_directory/test_file.txt',
content: "Test file content"
}
])
end
project.visit!
Page::Project::Show.perform(&:open_web_ide!)
end
it 'throws an error' do
Page::Project::WebIDE::Edit.perform do |ide|
ide.add_directory(directory_name)
end
expect(page).to have_content('The name "first_directory" is already taken in this directory.')
end
end
context 'when user adds a new empty directory' do
let(:directory_name) { 'new_empty_directory' }
before do
Page::Project::Show.perform(&:open_web_ide!)
end
it 'shows in the tree view but cannot be committed' do
Page::Project::WebIDE::Edit.perform do |ide|
ide.add_directory(directory_name)
expect(ide).to have_file(directory_name)
expect(ide).to have_folder_icon(directory_name)
expect(ide).not_to have_file_addition_icon(directory_name)
ide.switch_to_commit_tab
expect(ide).not_to have_file_to_commit(directory_name)
end
end
end
end
end
end
......@@ -22,7 +22,7 @@ module QA
context 'when a file with the same name already exists' do
let(:file_name) { 'README.md' }
it 'throws an error' do
it 'throws an error', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1136' do
Page::Project::WebIDE::Edit.perform do |ide|
ide.upload_file(file_path)
end
......@@ -34,7 +34,7 @@ module QA
context 'when the file is a text file' do
let(:file_name) { 'text_file.txt' }
it 'shows the Edit tab with the text' do
it 'shows the Edit tab with the text', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1138' do
Page::Project::WebIDE::Edit.perform do |ide|
ide.upload_file(file_path)
......@@ -52,7 +52,7 @@ module QA
context 'when the file is binary' do
let(:file_name) { 'logo_sample.svg' }
it 'shows a Download button' do
it 'shows a Download button', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1137' do
Page::Project::WebIDE::Edit.perform do |ide|
ide.upload_file(file_path)
......@@ -70,7 +70,7 @@ module QA
context 'when the file is an image' do
let(:file_name) { 'dk.png' }
it 'shows an image viewer' do
it 'shows an image viewer', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1139' do
Page::Project::WebIDE::Edit.perform do |ide|
ide.upload_file(file_path)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment