Commit 1bb1ce57 authored by Heinrich Lee Yu's avatar Heinrich Lee Yu

Merge branch '36422-add-nuget-installation-commands' into 'master'

Add Nuget installation instructions to package detail

See merge request gitlab-org/gitlab!24162
parents 4505da2c 32c85a65
---
title: Added NuGet package installation instructions to package details page
merge_request: 24162
author:
type: added
......@@ -12,10 +12,11 @@ import {
import _ from 'underscore';
import Tracking from '~/tracking';
import PackageInformation from './information.vue';
import NpmInstallation from './npm_installation.vue';
import MavenInstallation from './maven_installation.vue';
import ConanInstallation from './conan_installation.vue';
import PackageTitle from './package_title.vue';
import ConanInstallation from './conan_installation.vue';
import MavenInstallation from './maven_installation.vue';
import NpmInstallation from './npm_installation.vue';
import NugetInstallation from './nuget_installation.vue';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import { generatePackageInfo } from '../utils';
......@@ -34,10 +35,11 @@ export default {
GlTable,
GlIcon,
PackageInformation,
NpmInstallation,
MavenInstallation,
ConanInstallation,
PackageTitle,
ConanInstallation,
MavenInstallation,
NpmInstallation,
NugetInstallation,
},
directives: {
GlTooltip: GlTooltipDirective,
......@@ -84,6 +86,14 @@ export default {
type: String,
required: true,
},
nugetPath: {
type: String,
required: true,
},
nugetHelpPath: {
type: String,
required: true,
},
},
computed: {
...mapState(['packageEntity', 'packageFiles']),
......@@ -96,6 +106,9 @@ export default {
isConanPackage() {
return this.packageEntity.package_type === PackageType.CONAN;
},
isNugetPackage() {
return this.packageEntity.package_type === PackageType.NUGET;
},
isValidPackage() {
return Boolean(this.packageEntity.name);
},
......@@ -249,6 +262,13 @@ export default {
:registry-url="conanPath"
:help-url="conanHelpPath"
/>
<nuget-installation
v-else-if="isNugetPackage"
:package-entity="packageEntity"
:registry-url="nugetPath"
:help-url="nugetHelpPath"
/>
</div>
</div>
......
<script>
import { GlTab, GlTabs } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import CodeInstruction from './code_instruction.vue';
import Tracking from '~/tracking';
import { TrackingActions, TrackingLabels } from '../constants';
import { trackInstallationTabChange } from '../utils';
export default {
name: 'NugetInstallation',
components: {
CodeInstruction,
GlTab,
GlTabs,
},
mixins: [
Tracking.mixin({
label: TrackingLabels.NUGET_INSTALLATION,
}),
trackInstallationTabChange,
],
props: {
packageEntity: {
type: Object,
required: true,
},
registryUrl: {
type: String,
required: true,
},
helpUrl: {
type: String,
required: true,
},
},
computed: {
nugetCommand() {
return `nuget install ${this.packageEntity.name} -Source "GitLab"`;
},
setupCommand() {
return `nuget source Add -Name "GitLab" -Source "${this.registryUrl}" -UserName <your_username> -Password <your_token>`;
},
helpText() {
return sprintf(
s__(
`PackageRegistry|For more information on the NuGet registry, %{linkStart}see the documentation%{linkEnd}.`,
),
{
linkStart: `<a href="${this.helpUrl}" target="_blank" rel="noopener noreferer">`,
linkEnd: '</a>',
},
false,
);
},
},
trackingActions: { ...TrackingActions },
};
</script>
<template>
<div class="append-bottom-default">
<gl-tabs @input="trackInstallationTabChange">
<gl-tab :title="s__('PackageRegistry|Installation')" title-item-class="js-installation-tab">
<div class="prepend-left-default append-right-default">
<p class="prepend-top-8 font-weight-bold">{{ s__('PackageRegistry|NuGet Command') }}</p>
<code-instruction
:instruction="nugetCommand"
:copy-text="s__('PackageRegistry|Copy NuGet Command')"
class="js-nuget-command"
:tracking-action="$options.trackingActions.COPY_NUGET_INSTALL_COMMAND"
/>
</div>
</gl-tab>
<gl-tab :title="s__('PackageRegistry|Registry Setup')" title-item-class="js-setup-tab">
<div class="prepend-left-default append-right-default">
<p class="prepend-top-8 font-weight-bold">
{{ s__('PackageRegistry|Add NuGet Source') }}
</p>
<code-instruction
:instruction="setupCommand"
:copy-text="s__('PackageRegistry|Copy NuGet Setup Command')"
class="js-nuget-setup"
:tracking-action="$options.trackingActions.COPY_NUGET_SETUP_COMMAND"
/>
<p v-html="helpText"></p>
</div>
</gl-tab>
</gl-tabs>
</div>
</template>
......@@ -3,6 +3,7 @@ export const TrackingLabels = {
CONAN_INSTALLATION: 'conan_installation',
MAVEN_INSTALLATION: 'maven_installation',
NPM_INSTALLATION: 'npm_installation',
NUGET_INSTALLATION: 'nuget_installation',
};
export const TrackingActions = {
......@@ -21,4 +22,7 @@ export const TrackingActions = {
COPY_YARN_INSTALL_COMMAND: 'copy_yarn_install_command',
COPY_YARN_SETUP_COMMAND: 'copy_yarn_setup_command',
COPY_NUGET_INSTALL_COMMAND: 'copy_nuget_install_command',
COPY_NUGET_SETUP_COMMAND: 'copy_nuget_setup_command',
};
......@@ -32,6 +32,8 @@ export default () => {
mavenHelpPath: dataset.mavenHelpPath,
conanPath: dataset.conanPath,
conanHelpPath: dataset.conanHelpPath,
nugetPath: dataset.nugetPath,
nugetHelpPath: dataset.nugetHelpPath,
};
},
render(createElement) {
......@@ -46,6 +48,8 @@ export default () => {
mavenHelpPath: this.mavenHelpPath,
conanPath: this.conanPath,
conanHelpPath: this.conanHelpPath,
nugetPath: this.nugetPath,
nugetHelpPath: this.nugetHelpPath,
},
});
},
......
export const PackageType = {
CONAN: 'conan',
MAVEN: 'maven',
NPM: 'npm',
CONAN: 'conan',
NUGET: 'nuget',
};
export const TrackingActions = {
......
......@@ -11,17 +11,21 @@ module EE
end
def npm_package_registry_url
::Gitlab::Utils.append_path(::Gitlab.config.gitlab.url, expose_path(api_v4_packages_npm_package_name_path))
expose_url(api_v4_packages_npm_package_name_path)
end
def conan_package_registry_url
::Gitlab::Utils.append_path(::Gitlab.config.gitlab.url, "api/#{::API::API.version}/packages/conan")
expose_url("api/#{::API::API.version}/packages/conan")
end
def nuget_package_registry_url(project_id)
expose_url(api_v4_projects_packages_nuget_index_path(id: project_id, format: '.json'))
end
def package_registry_project_url(project_id, registry_type = :maven)
project_api_path = expose_path(api_v4_projects_path(id: project_id))
package_registry_project_path = "#{project_api_path}/packages/#{registry_type}"
::Gitlab::Utils.append_path(::Gitlab.config.gitlab.url, package_registry_project_path)
expose_url(package_registry_project_path)
end
end
end
......@@ -16,4 +16,6 @@
maven_help_path: help_page_path('user/packages/maven_repository/index'),
conan_path: conan_package_registry_url,
conan_help_path: help_page_path('user/packages/conan_repository/index'),
nuget_path: nuget_package_registry_url(@project.id),
nuget_help_path: help_page_path('user/packages/nuget_repository/index'),
package_file_download_path: download_project_package_file_path(@project, @package_files.first) } }
......@@ -10,7 +10,15 @@ import MavenInstallation from 'ee/packages/details/components/maven_installation
import * as SharedUtils from 'ee/packages/shared/utils';
import { TrackingActions } from 'ee/packages/shared/constants';
import ConanInstallation from 'ee/packages/details/components/conan_installation.vue';
import { conanPackage, mavenPackage, mavenFiles, npmPackage, npmFiles } from '../../mock_data';
import NugetInstallation from 'ee/packages/details/components/nuget_installation.vue';
import {
conanPackage,
mavenPackage,
mavenFiles,
npmPackage,
npmFiles,
nugetPackage,
} from '../../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
......@@ -29,6 +37,8 @@ describe('PackagesApp', () => {
mavenHelpPath: 'foo',
conanPath: 'foo',
conanHelpPath: 'foo',
nugetPath: 'foo',
nugetHelpPath: 'foo',
};
function createComponent(packageEntity = mavenPackage, packageFiles = mavenFiles) {
......@@ -64,6 +74,7 @@ describe('PackagesApp', () => {
const npmInstallation = () => wrapper.find(NpmInstallation);
const mavenInstallation = () => wrapper.find(MavenInstallation);
const conanInstallation = () => wrapper.find(ConanInstallation);
const nugetInstallation = () => wrapper.find(NugetInstallation);
const allFileRows = () => wrapper.findAll('.js-file-row');
const firstFileDownloadLink = () => wrapper.find('.js-file-download');
const deleteButton = () => wrapper.find('.js-delete-button');
......@@ -199,4 +210,12 @@ describe('PackagesApp', () => {
expect(conanInstallation()).toExist();
});
it('renders package installation instructions for nuget packages', () => {
createComponent({
packageEntity: nugetPackage,
});
expect(nugetInstallation()).toExist();
});
});
import { mount } from '@vue/test-utils';
import NugetInstallation from 'ee/packages/details/components/nuget_installation.vue';
import { nugetPackage } from '../../mock_data';
import { registryUrl } from '../mock_data';
import { TrackingActions, TrackingLabels } from 'ee/packages/details/constants';
import Tracking from '~/tracking';
describe('NugetInstallation', () => {
let wrapper;
const defaultProps = {
packageEntity: nugetPackage,
registryUrl,
helpUrl: 'foo',
};
const nugetInstallationCommandStr = `nuget install ${nugetPackage.name} -Source "GitLab"`;
const nugetSetupCommandStr = `nuget source Add -Name "GitLab" -Source "${registryUrl}" -UserName <your_username> -Password <your_token>`;
const installationTab = () => wrapper.find('.js-installation-tab > a');
const setupTab = () => wrapper.find('.js-setup-tab > a');
const nugetInstallationCommand = () => wrapper.find('.js-nuget-command > input');
const nugetSetupCommand = () => wrapper.find('.js-nuget-setup > input');
function createComponent(props = {}) {
const propsData = {
...defaultProps,
...props,
};
wrapper = mount(NugetInstallation, {
propsData,
});
}
beforeEach(() => {
createComponent();
});
afterEach(() => {
if (wrapper) wrapper.destroy();
});
describe('installation commands', () => {
it('renders the correct command', () => {
expect(nugetInstallationCommand().element.value).toBe(nugetInstallationCommandStr);
});
});
describe('setup commands', () => {
it('renders the correct command', () => {
expect(nugetSetupCommand().element.value).toBe(nugetSetupCommandStr);
});
});
describe('tab change tracking', () => {
let eventSpy;
const label = TrackingLabels.NUGET_INSTALLATION;
beforeEach(() => {
eventSpy = jest.spyOn(Tracking, 'event');
});
it('should track when the setup tab is clicked', () => {
setupTab().trigger('click');
return wrapper.vm.$nextTick().then(() => {
expect(eventSpy).toHaveBeenCalledWith(undefined, TrackingActions.REGISTRY_SETUP, {
label,
});
});
});
it('should track when the installation tab is clicked', () => {
setupTab().trigger('click');
return wrapper.vm
.$nextTick()
.then(() => {
installationTab().trigger('click');
return wrapper.vm.$nextTick();
})
.then(() => {
expect(eventSpy).toHaveBeenCalledWith(undefined, TrackingActions.INSTALLATION, {
label,
});
});
});
});
});
......@@ -13207,6 +13207,9 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote"
msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Conan Command"
msgstr ""
......@@ -13225,6 +13228,12 @@ msgstr ""
msgid "PackageRegistry|Copy Maven registry XML"
msgstr ""
msgid "PackageRegistry|Copy NuGet Command"
msgstr ""
msgid "PackageRegistry|Copy NuGet Setup Command"
msgstr ""
msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr ""
......@@ -13252,6 +13261,9 @@ msgstr ""
msgid "PackageRegistry|For more information on the Maven registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
msgid "PackageRegistry|For more information on the NuGet registry, %{linkStart}see the documentation%{linkEnd}."
msgstr ""
msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr ""
......@@ -13267,6 +13279,9 @@ msgstr ""
msgid "PackageRegistry|Maven XML"
msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
msgid "PackageRegistry|Package installation"
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