Commit 9cd9313a authored by Filipa Lacerda's avatar Filipa Lacerda

Merge branch 'design-detail-pagination' into 'master'

Added pagination to design detail view

See merge request gitlab-org/gitlab-ee!10540
parents 8836239a f4b8d48c
......@@ -3,14 +3,20 @@ import { __, sprintf } from '~/locale';
import { GlLoadingIcon } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import Pagination from './pagination.vue';
export default {
components: {
GlLoadingIcon,
Icon,
Pagination,
},
mixins: [timeagoMixin],
props: {
id: {
type: Number,
required: true,
},
isLoading: {
type: Boolean,
required: true,
......@@ -58,5 +64,6 @@ export default {
<small class="text-secondary">{{ updatedText }}</small>
</template>
</div>
<pagination :id="id" class="ml-auto" />
</header>
</template>
<script>
import { s__, sprintf } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import PaginationButton from './pagination_button.vue';
import allDesignsQuery from '../../queries/allDesigns.graphql';
export default {
apollo: {
designs: {
query: allDesignsQuery,
},
},
components: {
Icon,
PaginationButton,
},
props: {
id: {
type: Number,
required: true,
},
},
data() {
return {
designs: [],
};
},
computed: {
designsCount() {
return this.designs.length;
},
currentIndex() {
return this.designs.findIndex(design => design.id === this.id);
},
paginationText() {
return sprintf(s__('DesignManagement|%{current_design} of %{designs_count}'), {
current_design: this.currentIndex + 1,
designs_count: this.designsCount,
});
},
previousDesign() {
if (!this.designsCount) return null;
return this.designs[this.currentIndex - 1];
},
nextDesign() {
if (!this.designsCount) return null;
return this.designs[this.currentIndex + 1];
},
},
};
</script>
<template>
<div v-if="designsCount" class="d-flex align-items-center">
{{ paginationText }}
<div class="btn-group ml-3">
<pagination-button
:design="previousDesign"
:title="s__('DesignManagement|Go to previous design')"
icon-name="angle-left"
class="js-previous-design"
/>
<pagination-button
:design="nextDesign"
:title="s__('DesignManagement|Go to next design')"
icon-name="angle-right"
class="js-next-design"
/>
</div>
</div>
</template>
<script>
import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
Icon,
},
props: {
design: {
type: Object,
required: false,
default: null,
},
title: {
type: String,
required: true,
},
iconName: {
type: String,
required: true,
},
},
computed: {
designLink() {
if (!this.design) return {};
return { name: 'design', params: { id: this.design.id } };
},
},
};
</script>
<template>
<router-link
:to="designLink"
:disabled="!design"
:class="{ disabled: !design }"
:aria-label="title"
class="btn btn-default"
>
<icon :name="iconName" />
</router-link>
</template>
......@@ -48,6 +48,7 @@ export default {
<template>
<div class="design-detail fixed-top w-100 position-bottom-0 d-flex flex-column">
<toolbar
:id="id"
:is-loading="isLoading"
:name="design.name"
:updated-at="design.updatedAt"
......
require 'spec_helper'
describe 'User paginates issue designs', :js do
let(:project) { create(:project_empty_repo, :public) }
let(:issue) { create(:issue, project: project) }
before do
stub_licensed_features(design_management: true)
visit project_issue_path(project, issue)
click_link 'Designs'
wait_for_requests
first('.js-design-list-item').click
end
it 'paginates to next design' do
expect(find('.js-previous-design')[:disabled]).to eq('true')
page.within(find('.js-design-header')) do
expect(page).to have_content('1 of 5')
end
find('.js-next-design').click
expect(find('.js-previous-design')[:disabled]).not_to eq('true')
page.within(find('.js-design-header')) do
expect(page).to have_content('2 of 5')
end
end
end
......@@ -28,6 +28,11 @@ exports[`Design management toolbar component renders design and updated data 1`]
Updated 1 hour ago by Test Name
</small>
</div>
<pagination-stub
class="ml-auto"
id="1"
/>
</header>
`;
......@@ -54,5 +59,10 @@ exports[`Design management toolbar component renders loading icon 1`] = `
size="md"
/>
</div>
<pagination-stub
class="ml-auto"
id="1"
/>
</header>
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Design management pagination button component disables button when no design is passed 1`] = `
<router-link-stub
aria-label="Test title"
class="btn btn-default disabled"
disabled="true"
to="[object Object]"
>
<icon-stub
cssclasses=""
name="angle-right"
size="16"
/>
</router-link-stub>
`;
exports[`Design management pagination button component renders router-link 1`] = `
<router-link-stub
aria-label="Test title"
class="btn btn-default"
to="[object Object]"
>
<icon-stub
cssclasses=""
name="angle-right"
size="16"
/>
</router-link-stub>
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Design management pagination component hides components when designs are empty 1`] = `<!---->`;
exports[`Design management pagination component renders pagination buttons 1`] = `
<div
class="d-flex align-items-center"
>
2 of 2
<div
class="btn-group ml-3"
>
<paginationbutton-stub
class="js-previous-design"
design="[object Object]"
iconname="angle-left"
title="Go to previous design"
/>
<paginationbutton-stub
class="js-next-design"
iconname="angle-right"
title="Go to next design"
/>
</div>
</div>
`;
......@@ -21,6 +21,7 @@ describe('Design management toolbar component', () => {
vm = shallowMount(Toolbar, {
propsData: {
id: 1,
isLoading,
name: 'test.jpg',
updatedAt: updatedAt.toString(),
......
import { shallowMount } from '@vue/test-utils';
import PaginationButton from 'ee/design_management/components/toolbar/pagination_button.vue';
describe('Design management pagination button component', () => {
let vm;
function createComponent(design = null) {
vm = shallowMount(PaginationButton, {
propsData: {
design,
title: 'Test title',
iconName: 'angle-right',
},
stubs: ['router-link'],
});
}
afterEach(() => {
vm.destroy();
});
it('disables button when no design is passed', () => {
createComponent();
expect(vm.element).toMatchSnapshot();
});
it('renders router-link', () => {
createComponent({ id: 2 });
expect(vm.element).toMatchSnapshot();
});
describe('designLink', () => {
it('returns empty link when design is null', () => {
createComponent();
expect(vm.vm.designLink).toEqual({});
});
it('returns design link', () => {
createComponent({ id: 2 });
expect(vm.vm.designLink).toEqual({
name: 'design',
params: { id: 2 },
});
});
});
});
import { shallowMount } from '@vue/test-utils';
import Pagination from 'ee/design_management/components/toolbar/pagination.vue';
describe('Design management pagination component', () => {
let vm;
function createComponent() {
vm = shallowMount(Pagination, {
propsData: {
id: 2,
},
});
}
beforeEach(() => {
createComponent();
});
afterEach(() => {
vm.destroy();
});
it('hides components when designs are empty', () => {
expect(vm.element).toMatchSnapshot();
});
it('renders pagination buttons', () => {
vm.setData({
designs: [{ id: 1 }, { id: 2 }],
});
expect(vm.element).toMatchSnapshot();
});
});
......@@ -5,6 +5,7 @@ exports[`Design management design index page renders design index 1`] = `
class="design-detail fixed-top w-100 position-bottom-0 d-flex flex-column"
>
<toolbar-stub
id="1"
name="test.jpg"
updatedat=""
updatedby="[object Object]"
......@@ -22,6 +23,7 @@ exports[`Design management design index page sets loading state 1`] = `
class="design-detail fixed-top w-100 position-bottom-0 d-flex flex-column"
>
<toolbar-stub
id="1"
isloading="true"
name=""
updatedat=""
......
......@@ -3550,6 +3550,9 @@ msgstr ""
msgid "Description:"
msgstr ""
msgid "DesignManagement|%{current_design} of %{designs_count}"
msgstr ""
msgid "DesignManagement|Could not find design, please try again."
msgstr ""
......@@ -3559,6 +3562,12 @@ msgstr ""
msgid "DesignManagement|Go back to designs"
msgstr ""
msgid "DesignManagement|Go to next design"
msgstr ""
msgid "DesignManagement|Go to previous design"
msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
......
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