diff options
-rw-r--r-- | app/assets/javascripts/releases/components/release_block.vue | 145 | ||||
-rw-r--r-- | changelogs/unreleased/41766-vue-component.yml | 5 | ||||
-rw-r--r-- | locale/gitlab.pot | 9 | ||||
-rw-r--r-- | spec/javascripts/releases/components/release_block_spec.js | 148 |
4 files changed, 307 insertions, 0 deletions
diff --git a/app/assets/javascripts/releases/components/release_block.vue b/app/assets/javascripts/releases/components/release_block.vue new file mode 100644 index 00000000000..bd65a225d8f --- /dev/null +++ b/app/assets/javascripts/releases/components/release_block.vue @@ -0,0 +1,145 @@ +<script> +import { GlTooltipDirective, GlLink } from '@gitlab/ui'; +import Icon from '~/vue_shared/components/icon.vue'; +import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue'; +import timeagoMixin from '~/vue_shared/mixins/timeago'; +import { sprintf } from '../../locale'; + +export default { + name: 'ReleaseBlock', + components: { + GlLink, + Icon, + UserAvatarLink, + }, + directives: { + GlTooltip: GlTooltipDirective, + }, + mixins: [timeagoMixin], + props: { + name: { + type: String, + required: true, + }, + tag: { + type: String, + required: true, + }, + commit: { + type: Object, + required: true, + }, + description: { + type: String, + required: false, + default: '', + }, + author: { + type: Object, + required: true, + }, + createdAt: { + type: String, + required: false, + default: '', + }, + assetsCount: { + type: Number, + required: false, + default: 0, + }, + sources: { + type: Array, + required: false, + default: () => [], + }, + links: { + type: Array, + required: false, + default: () => [], + }, + }, + computed: { + releasedTimeAgo() { + return sprintf('released %{time}', { + time: this.timeFormated(this.createdAt), + }); + }, + userImageAltDescription() { + return this.author && this.author.username + ? sprintf("%{username}'s avatar", { username: this.author.username }) + : null; + }, + }, +}; +</script> +<template> + <div class="card"> + <div class="card-body"> + <h2 class="card-title mt-0">{{ name }}</h2> + + <div class="card-subtitle d-flex flex-wrap text-secondary"> + <div class="append-right-8"> + <icon name="commit" class="align-middle" /> + <span v-gl-tooltip.bottom :title="commit.title">{{ commit.short_id }}</span> + </div> + + <div class="append-right-8"> + <icon name="tag" class="align-middle" /> + <span v-gl-tooltip.bottom :title="__('Tag')">{{ tag }}</span> + </div> + + <div class="append-right-4"> + • + <span v-gl-tooltip.bottom :title="tooltipTitle(createdAt)">{{ releasedTimeAgo }}</span> + </div> + + <div class="d-flex"> + by + <user-avatar-link + class="prepend-left-4" + :link-href="author.path" + :img-src="author.avatar_url" + :img-alt="userImageAltDescription" + :tooltip-text="author.username" + /> + </div> + </div> + + <div class="card-text prepend-top-default"> + <b> + {{ __('Assets') }} <span class="js-assets-count badge badge-pill">{{ assetsCount }}</span> + </b> + + <ul class="pl-0 mb-0 prepend-top-8 list-unstyled js-assets-list"> + <li v-for="link in links" :key="link.name" class="append-bottom-8"> + <gl-link v-gl-tooltip.bottom :title="__('Download asset')" :href="link.url"> + <icon name="package" class="align-middle append-right-4" /> {{ link.name }} + </gl-link> + </li> + </ul> + + <div class="dropdown"> + <button + type="button" + class="btn btn-link" + data-toggle="dropdown" + aria-haspopup="true" + aria-expanded="false" + > + <icon name="doc-code" class="align-top append-right-4" /> {{ __('Source code') }} + <icon name="arrow-down" /> + </button> + + <div class="js-sources-dropdown dropdown-menu"> + <li v-for="asset in sources" :key="asset.url"> + <gl-link :href="asset.url">{{ __('Download') }} {{ asset.format }}</gl-link> + </li> + </div> + </div> + </div> + + <div class="card-text prepend-top-default"><div v-html="description"></div></div> + </div> + </div> +</template> diff --git a/changelogs/unreleased/41766-vue-component.yml b/changelogs/unreleased/41766-vue-component.yml new file mode 100644 index 00000000000..12343c8ce84 --- /dev/null +++ b/changelogs/unreleased/41766-vue-component.yml @@ -0,0 +1,5 @@ +--- +title: Creates component for release block +merge_request: 23697 +author: +type: added diff --git a/locale/gitlab.pot b/locale/gitlab.pot index b85eb6bdc88..e47f1433b8a 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -711,6 +711,9 @@ msgstr "" msgid "Ask your group maintainer to set up a group Runner." msgstr "" +msgid "Assets" +msgstr "" + msgid "Assign custom color like #FF0000" msgstr "" @@ -2587,6 +2590,9 @@ msgstr "" msgid "Download" msgstr "" +msgid "Download asset" +msgstr "" + msgid "Download tar" msgstr "" @@ -6377,6 +6383,9 @@ msgstr "" msgid "System metrics (Kubernetes)" msgstr "" +msgid "Tag" +msgstr "" + msgid "Tags" msgstr "" diff --git a/spec/javascripts/releases/components/release_block_spec.js b/spec/javascripts/releases/components/release_block_spec.js new file mode 100644 index 00000000000..c0cd15b7507 --- /dev/null +++ b/spec/javascripts/releases/components/release_block_spec.js @@ -0,0 +1,148 @@ +import Vue from 'vue'; +import component from '~/releases/components/release_block.vue'; +import timeagoMixin from '~/vue_shared/mixins/timeago'; + +import mountComponent from '../../helpers/vue_mount_component_helper'; + +describe('Release block', () => { + const Component = Vue.extend(component); + + const release = { + name: 'Bionic Beaver', + tag_name: '18.04', + description: '## changelog\n\n* line 1\n* line2', + description_html: '<div><h2>changelog</h2><ul><li>line1</li<li>line 2</li></ul></div>', + author_name: 'Release bot', + author_email: 'release-bot@example.com', + created_at: '2012-05-28T05:00:00-07:00', + commit: { + id: '2695effb5807a22ff3d138d593fd856244e155e7', + short_id: '2695effb', + title: 'Initial commit', + created_at: '2017-07-26T11:08:53.000+02:00', + parent_ids: ['2a4b78934375d7f53875269ffd4f45fd83a84ebe'], + message: 'Initial commit', + author_name: 'John Smith', + author_email: 'john@example.com', + authored_date: '2012-05-28T04:42:42-07:00', + committer_name: 'Jack Smith', + committer_email: 'jack@example.com', + committed_date: '2012-05-28T04:42:42-07:00', + }, + assets: { + count: 6, + sources: [ + { + format: 'zip', + url: 'https://gitlab.com/gitlab-org/gitlab-ce/-/archive/v11.3.12/gitlab-ce-v11.3.12.zip', + }, + { + format: 'tar.gz', + url: + 'https://gitlab.com/gitlab-org/gitlab-ce/-/archive/v11.3.12/gitlab-ce-v11.3.12.tar.gz', + }, + { + format: 'tar.bz2', + url: + 'https://gitlab.com/gitlab-org/gitlab-ce/-/archive/v11.3.12/gitlab-ce-v11.3.12.tar.bz2', + }, + { + format: 'tar', + url: 'https://gitlab.com/gitlab-org/gitlab-ce/-/archive/v11.3.12/gitlab-ce-v11.3.12.tar', + }, + ], + links: [ + { + name: 'release-18.04.dmg', + url: 'https://my-external-hosting.example.com/scrambled-url/', + external: true, + }, + { + name: 'binary-linux-amd64', + url: + 'https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/artifacts/v11.6.0-rc4/download?job=rspec-mysql+41%2F50', + external: false, + }, + ], + }, + }; + + const props = { + name: release.name, + tag: release.tag_name, + commit: release.commit, + description: release.description_html, + author: { + avatar_url: 'uploads/-/system/user/avatar/johndoe/avatar.png', + id: 482476, + name: 'John Doe', + path: '/johndoe', + state: 'active', + status_tooltip_html: null, + username: 'johndoe', + web_url: 'https://gitlab.com/johndoe', + }, + createdAt: release.created_at, + assetsCount: release.assets.count, + sources: release.assets.sources, + links: release.assets.links, + }; + + let vm; + + beforeEach(() => { + vm = mountComponent(Component, props); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('renders release name', () => { + expect(vm.$el.textContent).toContain(release.name); + }); + + it('renders commit sha', () => { + expect(vm.$el.textContent).toContain(release.commit.short_id); + }); + + it('renders tag name', () => { + expect(vm.$el.textContent).toContain(release.tag_name); + }); + + it('renders release date', () => { + expect(vm.$el.textContent).toContain(timeagoMixin.methods.timeFormated(release.created_at)); + }); + + it('renders number of assets provided', () => { + expect(vm.$el.querySelector('.js-assets-count').textContent).toContain(release.assets.count); + }); + + it('renders dropdown with the sources', () => { + expect(vm.$el.querySelectorAll('.js-sources-dropdown li').length).toEqual( + release.assets.sources.length, + ); + + expect(vm.$el.querySelector('.js-sources-dropdown li a').getAttribute('href')).toEqual( + release.assets.sources[0].url, + ); + + expect(vm.$el.querySelector('.js-sources-dropdown li a').textContent).toContain( + release.assets.sources[0].format, + ); + }); + + it('renders list with the links provided', () => { + expect(vm.$el.querySelectorAll('.js-assets-list li').length).toEqual( + release.assets.links.length, + ); + + expect(vm.$el.querySelector('.js-assets-list li a').getAttribute('href')).toEqual( + release.assets.links[0].url, + ); + + expect(vm.$el.querySelector('.js-assets-list li a').textContent).toContain( + release.assets.links[0].name, + ); + }); +}); |