Commit 04797778 authored by Filipa Lacerda's avatar Filipa Lacerda

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

Creates design component for design management

Closes #9667

See merge request gitlab-org/gitlab-ee!9691
parents 07814e73 7cf2e6e5
<script>
import Design from './item.vue';
export default {
components: {
Design,
},
props: {
designs: {
type: Array,
required: true,
},
},
};
</script>
<template>
<ol class="list-unstyled row">
<li v-for="design in designs" :key="design.id" class="col-md-6 col-lg-4">
<design
:comments-count="design.commentsCount"
:image="design.image"
:name="design.name"
:updated-at="design.updatedAt"
/>
</li>
</ol>
</template>
<script>
import Icon from '~/vue_shared/components/icon.vue';
import Timeago from '~/vue_shared/components/time_ago_tooltip.vue';
import { n__ } from '~/locale';
export default {
components: {
Icon,
Timeago,
},
props: {
commentsCount: {
type: Number,
required: true,
},
image: {
type: String,
required: true,
},
name: {
type: String,
required: true,
},
updatedAt: {
type: String,
required: true,
},
},
computed: {
commentsLabel() {
return n__('%d comment', '%d comments', this.commentsCount);
},
},
};
</script>
<template>
<div class="card js-design-list-item">
<div class="card-body p-0">
<img :src="image" :alt="name" class="block ml-auto mr-auto design-img" height="230" />
</div>
<div class="card-footer d-flex">
<div class="d-flex flex-column">
<span class="bold">{{ name }}</span>
<span>{{ __('Updated') }} <timeago :time="updatedAt" tooltip-placement="bottom"/></span>
</div>
<div class="ml-auto d-flex align-items-center text-secondary">
<icon name="comments" />
<span :aria-label="commentsLabel" class="ml-1">
{{ commentsCount }}
</span>
</div>
</div>
</div>
</template>
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import _ from 'underscore';
import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo);
const createMockDesign = id => ({
id,
image: 'http://via.placeholder.com/300',
name: 'test.jpg',
commentsCount: 2,
updatedAt: new Date().toString(),
__typename: 'Design',
});
export default new VueApollo({
defaultClient: createDefaultClient(),
defaultClient: createDefaultClient({
defaults: {
designs: [
createMockDesign(_.uniqueId()),
createMockDesign(_.uniqueId()),
createMockDesign(_.uniqueId()),
createMockDesign(_.uniqueId()),
createMockDesign(_.uniqueId()),
],
},
}),
});
<script>
import { GlLoadingIcon } from '@gitlab/ui';
import DesignList from '../components/list/index.vue';
import allDesignsQuery from '../queries/allDesigns.graphql';
export default {
components: {
GlLoadingIcon,
DesignList,
},
apollo: {
designs: {
query: allDesignsQuery,
error() {
this.error = true;
},
},
},
data() {
return {
designs: [],
error: false,
};
},
computed: {
isLoading() {
return this.$apollo.queries.designs.loading;
},
},
};
</script>
<template>
<div>
Home
<router-link to="/designs/1">Design</router-link>
<div class="mt-4">
<gl-loading-icon v-if="isLoading" :size="2" />
<div v-else-if="error" class="alert alert-danger">
{{ __('An error occured while loading designs. Please try again.') }}
</div>
<design-list v-else-if="designs.length" :designs="designs" />
<div v-else>{{ __('No designs found.') }}</div>
</div>
</div>
</template>
query allDesigns {
designs @client {
id
image
name
updatedAt
commentsCount
}
}
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 'fetches list of designs' do
expect(page).to have_selector('.js-design-list-item', count: 5)
end
end
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Design management list component renders list 1`] = `
<ol
class="list-unstyled row"
>
<li
class="col-md-6 col-lg-4"
>
<design-stub
commentscount="2"
image="test"
name="test"
updatedat="01-01-2019"
/>
</li>
<li
class="col-md-6 col-lg-4"
>
<design-stub
commentscount="2"
image="test"
name="test"
updatedat="01-01-2019"
/>
</li>
</ol>
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Design management list item component renders item with multiple comments 1`] = `
<div
class="card js-design-list-item"
id="1"
>
<div
class="card-body p-0"
>
<img
alt="test"
class="block ml-auto mr-auto design-img"
height="230"
src="http://via.placeholder.com/300"
/>
</div>
<div
class="card-footer d-flex"
>
<div
class="d-flex flex-column"
>
<span
class="bold"
>
test
</span>
<span>
Updated
<timeago-stub
cssclass=""
time="01-01-2019"
tooltipplacement="bottom"
/>
</span>
</div>
<div
class="ml-auto d-flex align-items-center text-secondary"
>
<icon-stub
cssclasses=""
name="comments"
size="16"
/>
<span
aria-label="2 comments"
class="ml-1"
>
2
</span>
</div>
</div>
</div>
`;
exports[`Design management list item component renders item with single comment 1`] = `
<div
class="card js-design-list-item"
id="1"
>
<div
class="card-body p-0"
>
<img
alt="test"
class="block ml-auto mr-auto design-img"
height="230"
src="http://via.placeholder.com/300"
/>
</div>
<div
class="card-footer d-flex"
>
<div
class="d-flex flex-column"
>
<span
class="bold"
>
test
</span>
<span>
Updated
<timeago-stub
cssclass=""
time="01-01-2019"
tooltipplacement="bottom"
/>
</span>
</div>
<div
class="ml-auto d-flex align-items-center text-secondary"
>
<icon-stub
cssclasses=""
name="comments"
size="16"
/>
<span
aria-label="1 comment"
class="ml-1"
>
1
</span>
</div>
</div>
</div>
`;
import { shallowMount } from '@vue/test-utils';
import List from 'ee/design_management/components/list/index.vue';
const createMockDesign = id => ({
id,
name: 'test',
image: 'test',
commentsCount: 2,
updatedAt: '01-01-2019',
});
describe('Design management list component', () => {
let vm;
function createComponent() {
vm = shallowMount(List, {
propsData: {
designs: [createMockDesign(1), createMockDesign(2)],
},
});
}
afterEach(() => {
vm.destroy();
});
it('renders list', () => {
createComponent();
expect(vm.element).toMatchSnapshot();
});
});
import { shallowMount } from '@vue/test-utils';
import Item from 'ee/design_management/components/list/item.vue';
describe('Design management list item component', () => {
let vm;
function createComponent(commentsCount) {
vm = shallowMount(Item, {
propsData: {
id: 1,
name: 'test',
image: 'http://via.placeholder.com/300',
commentsCount,
updatedAt: '01-01-2019',
},
});
}
afterEach(() => {
vm.destroy();
});
it('renders item with single comment', () => {
createComponent(1);
expect(vm.element).toMatchSnapshot();
});
it('renders item with multiple comments', () => {
createComponent(2);
expect(vm.element).toMatchSnapshot();
});
});
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Design management index page designs renders designs list 1`] = `
<div>
<div
class="mt-4"
>
<designlist-stub
designs="design"
/>
</div>
</div>
`;
exports[`Design management index page designs renders empty text 1`] = `
<div>
<div
class="mt-4"
>
<div>
No designs found.
</div>
</div>
</div>
`;
exports[`Design management index page designs renders error 1`] = `
<div>
<div
class="mt-4"
>
<div
class="alert alert-danger"
>
An error occured while loading designs. Please try again.
</div>
</div>
</div>
`;
exports[`Design management index page designs renders loading icon 1`] = `
<div>
<div
class="mt-4"
>
<glloadingicon-stub
label="Loading"
size="2"
/>
</div>
</div>
`;
import { shallowMount } from '@vue/test-utils';
import Index from 'ee/design_management/pages/index.vue';
describe('Design management index page', () => {
let vm;
function createComponent(loading = false) {
const $apollo = {
queries: {
designs: {
loading,
},
},
};
vm = shallowMount(Index, {
mocks: { $apollo },
});
}
describe('designs', () => {
it('renders loading icon', () => {
createComponent(true);
expect(vm.element).toMatchSnapshot();
});
it('renders error', () => {
createComponent();
vm.setData({ error: true });
expect(vm.element).toMatchSnapshot();
});
it('renders empty text', () => {
createComponent();
expect(vm.element).toMatchSnapshot();
});
it('renders designs list', () => {
createComponent();
vm.setData({ designs: ['design'] });
expect(vm.element).toMatchSnapshot();
});
});
});
......@@ -4,6 +4,7 @@ import App from 'ee/design_management/components/app.vue';
import Designs from 'ee/design_management/pages/index.vue';
import DesignDetail from 'ee/design_management/pages/design/index.vue';
import router from 'ee/design_management/router';
import '~/commons/bootstrap';
describe('Design management router', () => {
let vm;
......@@ -13,7 +14,15 @@ describe('Design management router', () => {
localVue.use(VueRouter);
vm = mount(App, { localVue, router });
vm = mount(App, {
localVue,
router,
mocks: {
$apollo: {
queries: { designs: { loading: true } },
},
},
});
}
beforeEach(() => {
......
......@@ -44,6 +44,11 @@ msgstr ""
msgid "\"%{query}\" in projects"
msgstr ""
msgid "%d comment"
msgid_plural "%d comments"
msgstr[0] ""
msgstr[1] ""
msgid "%d commit"
msgid_plural "%d commits"
msgstr[0] ""
......@@ -791,6 +796,9 @@ msgstr ""
msgid "An error has occurred"
msgstr ""
msgid "An error occured while loading designs. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion."
msgstr ""
......@@ -6554,6 +6562,9 @@ msgstr ""
msgid "No credit card required."
msgstr ""
msgid "No designs found."
msgstr ""
msgid "No details available"
msgstr ""
......@@ -10527,6 +10538,9 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updated"
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