Commit 7cf2e6e5 authored by Phil Hughes's avatar Phil Hughes

Creates design component for design management

Creates a list and design item components for design management.

Closes https://gitlab.com/gitlab-org/gitlab-ee/issues/9667
parent 02c75cfd
<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 Vue from 'vue';
import VueApollo from 'vue-apollo'; import VueApollo from 'vue-apollo';
import _ from 'underscore';
import createDefaultClient from '~/lib/graphql'; import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo); 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({ 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> <template>
<div> <div>
Home <div class="mt-4">
<router-link to="/designs/1">Design</router-link> <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> </div>
</template> </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'; ...@@ -4,6 +4,7 @@ import App from 'ee/design_management/components/app.vue';
import Designs from 'ee/design_management/pages/index.vue'; import Designs from 'ee/design_management/pages/index.vue';
import DesignDetail from 'ee/design_management/pages/design/index.vue'; import DesignDetail from 'ee/design_management/pages/design/index.vue';
import router from 'ee/design_management/router'; import router from 'ee/design_management/router';
import '~/commons/bootstrap';
describe('Design management router', () => { describe('Design management router', () => {
let vm; let vm;
...@@ -13,7 +14,15 @@ describe('Design management router', () => { ...@@ -13,7 +14,15 @@ describe('Design management router', () => {
localVue.use(VueRouter); localVue.use(VueRouter);
vm = mount(App, { localVue, router }); vm = mount(App, {
localVue,
router,
mocks: {
$apollo: {
queries: { designs: { loading: true } },
},
},
});
} }
beforeEach(() => { beforeEach(() => {
......
...@@ -44,6 +44,11 @@ msgstr "" ...@@ -44,6 +44,11 @@ msgstr ""
msgid "\"%{query}\" in projects" msgid "\"%{query}\" in projects"
msgstr "" msgstr ""
msgid "%d comment"
msgid_plural "%d comments"
msgstr[0] ""
msgstr[1] ""
msgid "%d commit" msgid "%d commit"
msgid_plural "%d commits" msgid_plural "%d commits"
msgstr[0] "" msgstr[0] ""
...@@ -770,6 +775,9 @@ msgstr "" ...@@ -770,6 +775,9 @@ msgstr ""
msgid "An error has occurred" msgid "An error has occurred"
msgstr "" msgstr ""
msgid "An error occured while loading designs. Please try again."
msgstr ""
msgid "An error occurred adding a draft to the discussion." msgid "An error occurred adding a draft to the discussion."
msgstr "" msgstr ""
...@@ -6551,6 +6559,9 @@ msgstr "" ...@@ -6551,6 +6559,9 @@ msgstr ""
msgid "No credit card required." msgid "No credit card required."
msgstr "" msgstr ""
msgid "No designs found."
msgstr ""
msgid "No details available" msgid "No details available"
msgstr "" msgstr ""
...@@ -10524,6 +10535,9 @@ msgstr "" ...@@ -10524,6 +10535,9 @@ msgstr ""
msgid "Update your group name, description, avatar, and visibility." msgid "Update your group name, description, avatar, and visibility."
msgstr "" msgstr ""
msgid "Updated"
msgstr ""
msgid "Updating" msgid "Updating"
msgstr "" 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