Commit 2a32e31c authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch '215355-pin-filters' into 'master'

Create sticky section in security dashboard layout

See merge request gitlab-org/gitlab!33651
parents 65024ab3 ec969158
...@@ -52,7 +52,7 @@ export default { ...@@ -52,7 +52,7 @@ export default {
<template> <template>
<security-dashboard-layout> <security-dashboard-layout>
<template #header> <template #sticky>
<filters :projects="projects" @filterChange="handleFilterChange" /> <filters :projects="projects" @filterChange="handleFilterChange" />
</template> </template>
<group-security-vulnerabilities <group-security-vulnerabilities
......
...@@ -118,6 +118,8 @@ export default { ...@@ -118,6 +118,8 @@ export default {
>{{ toggleButtonProps.text }}</gl-button >{{ toggleButtonProps.text }}</gl-button
> >
</header> </header>
</template>
<template #sticky>
<filters <filters
v-if="shouldShowDashboard" v-if="shouldShowDashboard"
:projects="graphqlProjectList" :projects="graphqlProjectList"
......
...@@ -112,6 +112,8 @@ export default { ...@@ -112,6 +112,8 @@ export default {
<csv-export-button :vulnerabilities-export-endpoint="vulnerabilitiesExportEndpoint" /> <csv-export-button :vulnerabilities-export-endpoint="vulnerabilitiesExportEndpoint" />
</div> </div>
<vulnerabilities-count-list :project-full-path="projectFullPath" /> <vulnerabilities-count-list :project-full-path="projectFullPath" />
</template>
<template #sticky>
<filters @filterChange="handleFilterChange" /> <filters @filterChange="handleFilterChange" />
</template> </template>
<project-vulnerabilities-app <project-vulnerabilities-app
......
...@@ -4,6 +4,9 @@ export default { ...@@ -4,6 +4,9 @@ export default {
hasHeaderSlot() { hasHeaderSlot() {
return Boolean(this.$slots.header); return Boolean(this.$slots.header);
}, },
hasStickySlot() {
return Boolean(this.$slots.sticky);
},
hasAsideSlot() { hasAsideSlot() {
return Boolean(this.$slots.aside); return Boolean(this.$slots.aside);
}, },
...@@ -17,6 +20,14 @@ export default { ...@@ -17,6 +20,14 @@ export default {
<slot name="header"></slot> <slot name="header"></slot>
</header> </header>
<section
v-if="hasStickySlot"
data-testid="sticky-section"
class="position-sticky gl-z-index-2 security_dashboard_filters"
>
<slot name="sticky"></slot>
</section>
<div class="row mt-4"> <div class="row mt-4">
<article class="col" :class="{ 'col-xl-7': hasAsideSlot }"> <article class="col" :class="{ 'col-xl-7': hasAsideSlot }">
<slot></slot> <slot></slot>
......
...@@ -23,3 +23,10 @@ ...@@ -23,3 +23,10 @@
} }
} }
.security_dashboard_filters {
top: $header-height;
.with-performance-bar & {
top: $header-height + $performance-bar-height;
}
}
---
title: Create sticky section in security dashboard layout
merge_request: 33651
author:
type: added
...@@ -4,6 +4,7 @@ import SecurityDashboardLayout from 'ee/security_dashboard/components/security_d ...@@ -4,6 +4,7 @@ import SecurityDashboardLayout from 'ee/security_dashboard/components/security_d
describe('Security Dashboard Layout component', () => { describe('Security Dashboard Layout component', () => {
let wrapper; let wrapper;
const SMALLER_SECTION_CLASS = 'col-xl-7'; const SMALLER_SECTION_CLASS = 'col-xl-7';
const STICKY_SECTION_SELECTOR = '[data-testid="sticky-section"]';
const DummyComponent = { const DummyComponent = {
name: 'dummy-component', name: 'dummy-component',
...@@ -17,6 +18,7 @@ describe('Security Dashboard Layout component', () => { ...@@ -17,6 +18,7 @@ describe('Security Dashboard Layout component', () => {
const findArticle = () => wrapper.find('article'); const findArticle = () => wrapper.find('article');
const findHeader = () => wrapper.find('header'); const findHeader = () => wrapper.find('header');
const findAside = () => wrapper.find('aside'); const findAside = () => wrapper.find('aside');
const findStickySection = () => wrapper.find(STICKY_SECTION_SELECTOR);
afterEach(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
...@@ -34,6 +36,7 @@ describe('Security Dashboard Layout component', () => { ...@@ -34,6 +36,7 @@ describe('Security Dashboard Layout component', () => {
${'article'} | ${true} ${'article'} | ${true}
${'header'} | ${false} ${'header'} | ${false}
${'aside'} | ${false} ${'aside'} | ${false}
${STICKY_SECTION_SELECTOR} | ${false}
`('should find that $element exists is $exists', ({ element, exists }) => { `('should find that $element exists is $exists', ({ element, exists }) => {
expect(wrapper.find(element).exists()).toBe(exists); expect(wrapper.find(element).exists()).toBe(exists);
}); });
...@@ -64,6 +67,7 @@ describe('Security Dashboard Layout component', () => { ...@@ -64,6 +67,7 @@ describe('Security Dashboard Layout component', () => {
${'article'} | ${true} ${'article'} | ${true}
${'header'} | ${true} ${'header'} | ${true}
${'aside'} | ${false} ${'aside'} | ${false}
${STICKY_SECTION_SELECTOR} | ${false}
`('should find that $element exists is $exists', ({ element, exists }) => { `('should find that $element exists is $exists', ({ element, exists }) => {
expect(wrapper.find(element).exists()).toBe(exists); expect(wrapper.find(element).exists()).toBe(exists);
}); });
...@@ -80,6 +84,36 @@ describe('Security Dashboard Layout component', () => { ...@@ -80,6 +84,36 @@ describe('Security Dashboard Layout component', () => {
expect(header.find(DummyComponent).exists()).toBe(true); expect(header.find(DummyComponent).exists()).toBe(true);
}); });
}); });
describe('with the sticky section and main slots', () => {
beforeEach(() => {
createWrapper({
default: DummyComponent,
sticky: DummyComponent,
});
});
it.each`
element | exists
${'article'} | ${true}
${'header'} | ${false}
${'aside'} | ${false}
${STICKY_SECTION_SELECTOR} | ${true}
`('should find that $element exists is $exists', ({ element, exists }) => {
expect(wrapper.find(element).exists()).toBe(exists);
});
it('should render the dummy component in the main section', () => {
const article = findArticle();
expect(article.find(DummyComponent).exists()).toBe(true);
});
it('should render the dummy component in the sticky section', () => {
const section = findStickySection();
expect(section.find(DummyComponent).exists()).toBe(true);
});
});
describe('with the aside and main slots', () => { describe('with the aside and main slots', () => {
beforeEach(() => { beforeEach(() => {
...@@ -94,6 +128,7 @@ describe('Security Dashboard Layout component', () => { ...@@ -94,6 +128,7 @@ describe('Security Dashboard Layout component', () => {
${'article'} | ${true} ${'article'} | ${true}
${'header'} | ${false} ${'header'} | ${false}
${'aside'} | ${true} ${'aside'} | ${true}
${STICKY_SECTION_SELECTOR} | ${false}
`('should find that $element exists is $exists', ({ element, exists }) => { `('should find that $element exists is $exists', ({ element, exists }) => {
expect(wrapper.find(element).exists()).toBe(exists); expect(wrapper.find(element).exists()).toBe(exists);
}); });
......
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