Commit 422bd337 authored by Nick Kipling's avatar Nick Kipling

Add NuGet metadata to the package details ui

Adds project and licence url to package details information
Updates information to support ordering and links
Updated tests
parent 98b59f13
<script> <script>
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { GlLink } from '@gitlab/ui';
export default { export default {
name: 'PackageInformation', name: 'PackageInformation',
components: { components: {
ClipboardButton, ClipboardButton,
GlLink,
}, },
props: { props: {
heading: { heading: {
...@@ -37,7 +39,12 @@ export default { ...@@ -37,7 +39,12 @@ export default {
<li v-for="(item, index) in information" :key="index"> <li v-for="(item, index) in information" :key="index">
<span class="text-secondary">{{ item.label }}</span> <span class="text-secondary">{{ item.label }}</span>
<div class="pull-right"> <div class="pull-right">
<span>{{ item.value }}</span> <gl-link v-if="item.type === 'link'" :href="item.value" target="_blank">
{{ item.value }}
</gl-link>
<span v-else>{{ item.value }}</span>
<clipboard-button <clipboard-button
v-if="showCopy" v-if="showCopy"
:text="item.value" :text="item.value"
......
...@@ -2,6 +2,7 @@ import { __ } from '~/locale'; ...@@ -2,6 +2,7 @@ import { __ } from '~/locale';
import { formatDate } from '~/lib/utils/datetime_utility'; import { formatDate } from '~/lib/utils/datetime_utility';
import { TrackingActions } from './constants'; import { TrackingActions } from './constants';
import { PackageType } from '../shared/constants'; import { PackageType } from '../shared/constants';
import { orderBy } from 'lodash';
export const trackInstallationTabChange = { export const trackInstallationTabChange = {
methods: { methods: {
...@@ -30,29 +31,61 @@ export function generatePackageInfo(packageEntity = {}) { ...@@ -30,29 +31,61 @@ export function generatePackageInfo(packageEntity = {}) {
if (packageEntity.package_type === PackageType.CONAN) { if (packageEntity.package_type === PackageType.CONAN) {
information.push({ information.push({
order: 1,
label: __('Recipe'), label: __('Recipe'),
value: generateConanRecipe(packageEntity), value: generateConanRecipe(packageEntity),
}); });
} else { } else {
information.push({ information.push({
order: 1,
label: __('Name'), label: __('Name'),
value: packageEntity.name || '', value: packageEntity.name || '',
}); });
} }
return [ if (packageEntity.package_type === PackageType.NUGET) {
...information, const {
{ nuget_metadatum: { project_url: projectUrl, license_url: licenseUrl } = {},
label: __('Version'), } = packageEntity;
value: packageEntity.version || '',
}, if (projectUrl) {
{ information.push({
label: __('Created on'), order: 3,
value: formatDate(packageEntity.created_at), label: __('Project URL'),
}, value: projectUrl,
{ type: 'link',
label: __('Updated at'), });
value: formatDate(packageEntity.updated_at), }
},
]; if (licenseUrl) {
information.push({
order: 4,
label: __('License URL'),
value: licenseUrl,
type: 'link',
});
}
}
return orderBy(
[
...information,
{
order: 2,
label: __('Version'),
value: packageEntity.version || '',
},
{
order: 5,
label: __('Created on'),
value: formatDate(packageEntity.created_at),
},
{
order: 6,
label: __('Updated at'),
value: formatDate(packageEntity.updated_at),
},
],
['order'],
);
} }
---
title: Adds NuGet project and license URL to the package details page
merge_request: 33268
author:
type: added
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import PackageInformation from 'ee/packages/details/components/information.vue'; import PackageInformation from 'ee/packages/details/components/information.vue';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import { GlLink } from '@gitlab/ui';
describe('PackageInformation', () => { describe('PackageInformation', () => {
let wrapper; let wrapper;
const defaultProps = { const gitlabLink = 'https://gitlab.com';
information: [ const testInformation = [
{ {
label: 'Information one', label: 'Information one',
value: 'Information value one', value: 'Information value one',
}, },
{ {
label: 'Information two', label: 'Information two',
value: 'Information value two', value: 'Information value two',
}, },
{ {
label: 'Information three', label: 'Information three',
value: 'Information value three', value: 'Information value three',
}, },
], ];
};
function createComponent(props = {}) { function createComponent(props = {}) {
const propsData = { const propsData = {
...defaultProps, information: testInformation,
...props, ...props,
}; };
...@@ -40,6 +40,7 @@ describe('PackageInformation', () => { ...@@ -40,6 +40,7 @@ describe('PackageInformation', () => {
informationSelector() informationSelector()
.at(index) .at(index)
.text(); .text();
const informationLink = () => wrapper.find(GlLink);
afterEach(() => { afterEach(() => {
if (wrapper) wrapper.destroy(); if (wrapper) wrapper.destroy();
...@@ -66,10 +67,28 @@ describe('PackageInformation', () => { ...@@ -66,10 +67,28 @@ describe('PackageInformation', () => {
it('renders the supplied information', () => { it('renders the supplied information', () => {
createComponent(); createComponent();
expect(informationSelector()).toHaveLength(3); expect(informationSelector()).toHaveLength(testInformation.length);
expect(informationRowText(0)).toContain('one'); expect(informationRowText(0)).toContain(testInformation[0].value);
expect(informationRowText(1)).toContain('two'); expect(informationRowText(1)).toContain(testInformation[1].value);
expect(informationRowText(2)).toContain('three'); expect(informationRowText(2)).toContain(testInformation[2].value);
});
it('renders a link when the information is of type link', () => {
createComponent({
information: [
{
label: 'Information link',
value: gitlabLink,
type: 'link',
},
],
});
const link = informationLink();
expect(link.exists()).toBe(true);
expect(link.text()).toBe(gitlabLink);
expect(link.attributes('href')).toBe(gitlabLink);
}); });
describe('copy button', () => { describe('copy button', () => {
...@@ -82,10 +101,10 @@ describe('PackageInformation', () => { ...@@ -82,10 +101,10 @@ describe('PackageInformation', () => {
it('does render when the prop is set and has correct text set', () => { it('does render when the prop is set and has correct text set', () => {
createComponent({ showCopy: true }); createComponent({ showCopy: true });
expect(copyButton()).toHaveLength(3); expect(copyButton()).toHaveLength(testInformation.length);
expect(copyButton().at(0).vm.text).toBe(defaultProps.information[0].value); expect(copyButton().at(0).vm.text).toBe(testInformation[0].value);
expect(copyButton().at(1).vm.text).toBe(defaultProps.information[1].value); expect(copyButton().at(1).vm.text).toBe(testInformation[1].value);
expect(copyButton().at(2).vm.text).toBe(defaultProps.information[2].value); expect(copyButton().at(2).vm.text).toBe(testInformation[2].value);
}); });
}); });
}); });
import { formatDate } from '~/lib/utils/datetime_utility'; import { formatDate } from '~/lib/utils/datetime_utility';
import { orderBy } from 'lodash';
export const registryUrl = 'foo/registry'; export const registryUrl = 'foo/registry';
...@@ -43,18 +44,21 @@ export const generateMavenSetupXml = () => `<repositories> ...@@ -43,18 +44,21 @@ export const generateMavenSetupXml = () => `<repositories>
</snapshotRepository> </snapshotRepository>
</distributionManagement>`; </distributionManagement>`;
export const generateCommonPackageInformation = packageEntity => [ const generateCommonPackageInformation = packageEntity => [
{ {
label: 'Version', label: 'Version',
value: packageEntity.version, value: packageEntity.version,
order: 2,
}, },
{ {
label: 'Created on', label: 'Created on',
value: formatDate(packageEntity.created_at), value: formatDate(packageEntity.created_at),
order: 5,
}, },
{ {
label: 'Updated at', label: 'Updated at',
value: formatDate(packageEntity.updated_at), value: formatDate(packageEntity.updated_at),
order: 6,
}, },
]; ];
...@@ -62,6 +66,7 @@ export const generateStandardPackageInformation = packageEntity => [ ...@@ -62,6 +66,7 @@ export const generateStandardPackageInformation = packageEntity => [
{ {
label: 'Name', label: 'Name',
value: packageEntity.name, value: packageEntity.name,
order: 1,
}, },
...generateCommonPackageInformation(packageEntity), ...generateCommonPackageInformation(packageEntity),
]; ];
...@@ -70,10 +75,36 @@ export const generateConanInformation = conanPackage => [ ...@@ -70,10 +75,36 @@ export const generateConanInformation = conanPackage => [
{ {
label: 'Recipe', label: 'Recipe',
value: conanPackage.recipe, value: conanPackage.recipe,
order: 1,
}, },
...generateCommonPackageInformation(conanPackage), ...generateCommonPackageInformation(conanPackage),
]; ];
export const generateNugetInformation = nugetPackage =>
orderBy(
[
...generateCommonPackageInformation(nugetPackage),
{
label: 'Name',
value: nugetPackage.name,
order: 1,
},
{
label: 'Project URL',
value: nugetPackage.nuget_metadatum.project_url,
order: 3,
type: 'link',
},
{
label: 'License URL',
value: nugetPackage.nuget_metadatum.license_url,
order: 4,
type: 'link',
},
],
['order'],
);
export const pypiSetupCommandStr = `[gitlab] export const pypiSetupCommandStr = `[gitlab]
repository = foo repository = foo
username = __token__ username = __token__
......
import { generateConanRecipe, generatePackageInfo } from 'ee/packages/details/utils'; import { generateConanRecipe, generatePackageInfo } from 'ee/packages/details/utils';
import { conanPackage, mavenPackage, npmPackage } from '../mock_data'; import { conanPackage, mavenPackage, npmPackage, nugetPackage } from '../mock_data';
import { generateConanInformation, generateStandardPackageInformation } from './mock_data'; import {
generateConanInformation,
generateStandardPackageInformation,
generateNugetInformation,
} from './mock_data';
describe('Package detail utils', () => { describe('Package detail utils', () => {
describe('generating information', () => { describe('generating information', () => {
...@@ -53,5 +57,15 @@ describe('Package detail utils', () => { ...@@ -53,5 +57,15 @@ describe('Package detail utils', () => {
expect(info).toEqual(mavenInformation); expect(info).toEqual(mavenInformation);
}); });
}); });
describe('nuget packages', () => {
const nugetInformation = generateNugetInformation(nugetPackage);
it('correctly generates the nuget information', () => {
const info = generatePackageInfo(nugetPackage);
expect(info).toEqual(nugetInformation);
});
});
}); });
}); });
...@@ -120,6 +120,8 @@ export const nugetPackage = { ...@@ -120,6 +120,8 @@ export const nugetPackage = {
dependency_links: Object.values(dependencyLinks), dependency_links: Object.values(dependencyLinks),
nuget_metadatum: { nuget_metadatum: {
icon_url: 'fake-icon', icon_url: 'fake-icon',
project_url: 'project-foo-url',
license_url: 'license-foo-url',
}, },
}; };
......
...@@ -12970,6 +12970,9 @@ msgstr "" ...@@ -12970,6 +12970,9 @@ msgstr ""
msgid "License History" msgid "License History"
msgstr "" msgstr ""
msgid "License URL"
msgstr ""
msgid "License-Check" msgid "License-Check"
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