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

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

Design management detail

See merge request gitlab-org/gitlab-ee!10299
parents 2bcf1ea6 1e055d69
<script>
import { __, sprintf } from '~/locale';
import { GlLoadingIcon } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
export default {
components: {
GlLoadingIcon,
Icon,
},
mixins: [timeagoMixin],
props: {
isLoading: {
type: Boolean,
required: true,
},
name: {
type: String,
required: false,
default: '',
},
updatedAt: {
type: String,
required: false,
default: '',
},
updatedBy: {
type: Object,
required: false,
default: () => ({}),
},
},
computed: {
updatedText() {
return sprintf(__('Updated %{updated_at} by %{updated_by}'), {
updated_at: this.timeFormated(this.updatedAt),
updated_by: this.updatedBy.name,
});
},
},
};
</script>
<template>
<header class="d-flex w-100 p-2 bg-white align-items-center js-design-header">
<router-link
:to="{ name: 'designs' }"
:aria-label="s__('DesignManagement|Go back to designs')"
class="mr-3 text-plain"
>
<icon :size="18" name="close" />
</router-link>
<div>
<gl-loading-icon v-if="isLoading" size="md" class="mt-2 mb-2" />
<template v-else>
<h2 class="m-0">{{ name }}</h2>
<small class="text-secondary">{{ updatedText }}</small>
</template>
</div>
</header>
</template>
......@@ -12,20 +12,31 @@ const createMockDesign = id => ({
name: 'test.jpg',
commentsCount: 2,
updatedAt: new Date().toString(),
updatedBy: {
name: 'Test Name',
__typename: 'Author',
},
__typename: 'Design',
});
const defaultClient = createDefaultClient({
defaults: {
designs: [
const designsStore = [
createMockDesign(_.uniqueId()),
createMockDesign(_.uniqueId()),
createMockDesign(_.uniqueId()),
createMockDesign(_.uniqueId()),
createMockDesign(_.uniqueId()),
],
];
const defaultClient = createDefaultClient({
defaults: {
designs: designsStore,
},
resolvers: {
Query: {
design(ctx, { id }) {
return designsStore.find(design => design.id === id);
},
},
Mutation: {
uploadDesign(ctx, { name }, { cache }) {
const designs = name.map(n => ({
......
<script>
import Toolbar from '../../components/toolbar/index.vue';
import getDesignQuery from '../../queries/getDesign.graphql';
export default {
components: {
Toolbar,
},
props: {
id: {
type: Number,
required: true,
},
},
data() {
return {
design: {},
};
},
apollo: {
design: {
query: getDesignQuery,
variables() {
return {
id: this.id,
};
},
},
},
computed: {
isLoading() {
return this.$apollo.queries.design.loading;
},
},
};
</script>
<template>
<div>
Design detail for {{ id }}
<router-link to="/designs">All designs</router-link>
<div class="design-detail fixed-top w-100 h-100">
<toolbar
:is-loading="isLoading"
:name="design.name"
:updated-at="design.updatedAt"
:updated-by="design.updatedBy"
/>
</div>
</template>
......@@ -89,5 +89,6 @@ export default {
<design-list v-else-if="designs.length" :designs="designs" />
<div v-else>{{ __('No designs found.') }}</div>
</div>
<router-view />
</div>
</template>
query getDesign($id: ID!) {
design(id: $id) @client {
image
name
updatedAt
updatedBy {
name
}
}
}
......@@ -24,10 +24,10 @@ const router = new VueRouter({
meta: {
el: 'designs',
},
},
children: [
{
name: 'design',
path: '/designs/:id',
path: ':id',
component: DesignDetail,
meta: {
el: 'designs',
......@@ -35,6 +35,8 @@ const router = new VueRouter({
props: ({ params: { id } }) => ({ id: parseInt(id, 10) }),
},
],
},
],
});
router.beforeEach(({ meta: { el } }, from, next) => {
......
.design-detail {
background-color: rgba($black, 0.9);
.with-performance-bar & {
top: 35px;
}
h2 {
font-size: 14px;
line-height: 1;
}
}
require 'spec_helper'
describe 'User views issue designs', :js do
let(:project) { create(:project_empty_repo, :public) }
let(:issue) { create(:issue, project: project) }
before do
visit project_issue_path(project, issue)
click_link 'Designs'
wait_for_requests
end
it 'opens design detail' do
first('.js-design-list-item').click
page.within(find('.js-design-header')) do
expect(page).to have_content('test.jpg')
expect(page).to have_content('Test Name')
end
end
end
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Design management toolbar component renders design and updated data 1`] = `
<header
class="d-flex w-100 p-2 bg-white align-items-center js-design-header"
>
<a
aria-label="Go back to designs"
class="mr-3 text-plain"
>
<icon-stub
cssclasses=""
name="close"
size="18"
/>
</a>
<div>
<h2
class="m-0"
>
test.jpg
</h2>
<small
class="text-secondary"
>
Updated 1 hour ago by Test Name
</small>
</div>
</header>
`;
exports[`Design management toolbar component renders loading icon 1`] = `
<header
class="d-flex w-100 p-2 bg-white align-items-center js-design-header"
>
<a
aria-label="Go back to designs"
class="mr-3 text-plain"
>
<icon-stub
cssclasses=""
name="close"
size="18"
/>
</a>
<div>
<glloadingicon-stub
class="mt-2 mb-2"
color="orange"
label="Loading"
size="md"
/>
</div>
</header>
`;
import { shallowMount } from '@vue/test-utils';
import Toolbar from 'ee/design_management/components/toolbar/index.vue';
const RouterLinkStub = {
props: {
to: {
type: Object,
},
},
render(createElement) {
return createElement('a', {}, this.$slots.default);
},
};
describe('Design management toolbar component', () => {
let vm;
function createComponent(isLoading = false) {
const updatedAt = new Date();
updatedAt.setHours(updatedAt.getHours() - 1);
vm = shallowMount(Toolbar, {
propsData: {
isLoading,
name: 'test.jpg',
updatedAt: updatedAt.toString(),
updatedBy: {
name: 'Test Name',
},
},
stubs: {
'router-link': RouterLinkStub,
},
});
}
it('renders loading icon', () => {
createComponent(true);
expect(vm.element).toMatchSnapshot();
});
it('renders design and updated data', () => {
createComponent();
expect(vm.element).toMatchSnapshot();
});
it('links back to designs list', () => {
createComponent();
const link = vm.find('a');
expect(link.props('to')).toEqual({
name: 'designs',
});
});
});
......@@ -11,6 +11,8 @@ exports[`Design management index page designs renders designs list 1`] = `
designs="design"
/>
</div>
<router-view-stub />
</div>
`;
......@@ -25,6 +27,8 @@ exports[`Design management index page designs renders empty text 1`] = `
No designs found.
</div>
</div>
<router-view-stub />
</div>
`;
......@@ -43,6 +47,8 @@ exports[`Design management index page designs renders error 1`] = `
</div>
</div>
<router-view-stub />
</div>
`;
......@@ -59,5 +65,7 @@ exports[`Design management index page designs renders loading icon 1`] = `
size="md"
/>
</div>
<router-view-stub />
</div>
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Design management design index page sets loading state 1`] = `
<div
class="design-detail fixed-top w-100 h-100"
>
<toolbar-stub
isloading="true"
name=""
updatedat=""
updatedby="[object Object]"
/>
</div>
`;
exports[`Design management design index page sets loading state 2`] = `
<div
class="design-detail fixed-top w-100 h-100"
>
<toolbar-stub
name="test.jpg"
updatedat="01-01-2019"
updatedby="[object Object]"
/>
</div>
`;
import { shallowMount } from '@vue/test-utils';
import DesignIndex from 'ee/design_management/pages/design/index.vue';
describe('Design management design index page', () => {
let vm;
function createComponent(loading = false) {
const $apollo = {
queries: {
design: {
loading,
},
},
};
vm = shallowMount(DesignIndex, {
propsData: { id: 1 },
mocks: { $apollo },
});
}
it('sets loading state', () => {
createComponent(true);
expect(vm.element).toMatchSnapshot();
});
it('sets loading state', () => {
createComponent();
vm.setData({
design: {
name: 'test.jpg',
updatedAt: '01-01-2019',
updatedBy: {
name: 'test',
},
},
});
expect(vm.element).toMatchSnapshot();
});
});
......@@ -18,6 +18,7 @@ describe('Design management index page', () => {
vm = shallowMount(Index, {
mocks: { $apollo },
stubs: ['router-view'],
});
}
......
......@@ -17,12 +17,14 @@ describe('Design management router', () => {
localVue.use(VueRouter);
window.gon = { sprite_icons: '' };
vm = mount(App, {
localVue,
router,
mocks: {
$apollo: {
queries: { designs: { loading: true } },
queries: { designs: { loading: true }, design: { loading: true } },
},
},
});
......
......@@ -3520,6 +3520,9 @@ msgstr ""
msgid "DesignManagement|Error uploading a new design. Please try again"
msgstr ""
msgid "DesignManagement|Go back to designs"
msgstr ""
msgid "DesignManagement|Upload designs"
msgstr ""
......@@ -11363,6 +11366,9 @@ msgstr ""
msgid "Updated"
msgstr ""
msgid "Updated %{updated_at} by %{updated_by}"
msgstr ""
msgid "Updating"
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