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 { ...@@ -12,10 +12,11 @@ import {
import _ from 'underscore'; import _ from 'underscore';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import PackageInformation from './information.vue'; 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 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 { numberToHumanSize } from '~/lib/utils/number_utils';
import timeagoMixin from '~/vue_shared/mixins/timeago'; import timeagoMixin from '~/vue_shared/mixins/timeago';
import { generatePackageInfo } from '../utils'; import { generatePackageInfo } from '../utils';
...@@ -34,10 +35,11 @@ export default { ...@@ -34,10 +35,11 @@ export default {
GlTable, GlTable,
GlIcon, GlIcon,
PackageInformation, PackageInformation,
NpmInstallation,
MavenInstallation,
ConanInstallation,
PackageTitle, PackageTitle,
ConanInstallation,
MavenInstallation,
NpmInstallation,
NugetInstallation,
}, },
directives: { directives: {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
...@@ -84,6 +86,14 @@ export default { ...@@ -84,6 +86,14 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
nugetPath: {
type: String,
required: true,
},
nugetHelpPath: {
type: String,
required: true,
},
}, },
computed: { computed: {
...mapState(['packageEntity', 'packageFiles']), ...mapState(['packageEntity', 'packageFiles']),
...@@ -96,6 +106,9 @@ export default { ...@@ -96,6 +106,9 @@ export default {
isConanPackage() { isConanPackage() {
return this.packageEntity.package_type === PackageType.CONAN; return this.packageEntity.package_type === PackageType.CONAN;
}, },
isNugetPackage() {
return this.packageEntity.package_type === PackageType.NUGET;
},
isValidPackage() { isValidPackage() {
return Boolean(this.packageEntity.name); return Boolean(this.packageEntity.name);
}, },
...@@ -249,6 +262,13 @@ export default { ...@@ -249,6 +262,13 @@ export default {
:registry-url="conanPath" :registry-url="conanPath"
:help-url="conanHelpPath" :help-url="conanHelpPath"
/> />
<nuget-installation
v-else-if="isNugetPackage"
:package-entity="packageEntity"
:registry-url="nugetPath"
:help-url="nugetHelpPath"
/>
</div> </div>
</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 = { ...@@ -3,6 +3,7 @@ export const TrackingLabels = {
CONAN_INSTALLATION: 'conan_installation', CONAN_INSTALLATION: 'conan_installation',
MAVEN_INSTALLATION: 'maven_installation', MAVEN_INSTALLATION: 'maven_installation',
NPM_INSTALLATION: 'npm_installation', NPM_INSTALLATION: 'npm_installation',
NUGET_INSTALLATION: 'nuget_installation',
}; };
export const TrackingActions = { export const TrackingActions = {
...@@ -21,4 +22,7 @@ export const TrackingActions = { ...@@ -21,4 +22,7 @@ export const TrackingActions = {
COPY_YARN_INSTALL_COMMAND: 'copy_yarn_install_command', COPY_YARN_INSTALL_COMMAND: 'copy_yarn_install_command',
COPY_YARN_SETUP_COMMAND: 'copy_yarn_setup_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 () => { ...@@ -32,6 +32,8 @@ export default () => {
mavenHelpPath: dataset.mavenHelpPath, mavenHelpPath: dataset.mavenHelpPath,
conanPath: dataset.conanPath, conanPath: dataset.conanPath,
conanHelpPath: dataset.conanHelpPath, conanHelpPath: dataset.conanHelpPath,
nugetPath: dataset.nugetPath,
nugetHelpPath: dataset.nugetHelpPath,
}; };
}, },
render(createElement) { render(createElement) {
...@@ -46,6 +48,8 @@ export default () => { ...@@ -46,6 +48,8 @@ export default () => {
mavenHelpPath: this.mavenHelpPath, mavenHelpPath: this.mavenHelpPath,
conanPath: this.conanPath, conanPath: this.conanPath,
conanHelpPath: this.conanHelpPath, conanHelpPath: this.conanHelpPath,
nugetPath: this.nugetPath,
nugetHelpPath: this.nugetHelpPath,
}, },
}); });
}, },
......
export const PackageType = { export const PackageType = {
CONAN: 'conan',
MAVEN: 'maven', MAVEN: 'maven',
NPM: 'npm', NPM: 'npm',
CONAN: 'conan', NUGET: 'nuget',
}; };
export const TrackingActions = { export const TrackingActions = {
......
...@@ -11,17 +11,21 @@ module EE ...@@ -11,17 +11,21 @@ module EE
end end
def npm_package_registry_url 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 end
def conan_package_registry_url 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 end
def package_registry_project_url(project_id, registry_type = :maven) def package_registry_project_url(project_id, registry_type = :maven)
project_api_path = expose_path(api_v4_projects_path(id: project_id)) project_api_path = expose_path(api_v4_projects_path(id: project_id))
package_registry_project_path = "#{project_api_path}/packages/#{registry_type}" 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 end
end end
...@@ -16,4 +16,6 @@ ...@@ -16,4 +16,6 @@
maven_help_path: help_page_path('user/packages/maven_repository/index'), maven_help_path: help_page_path('user/packages/maven_repository/index'),
conan_path: conan_package_registry_url, conan_path: conan_package_registry_url,
conan_help_path: help_page_path('user/packages/conan_repository/index'), 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) } } 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 ...@@ -10,7 +10,15 @@ import MavenInstallation from 'ee/packages/details/components/maven_installation
import * as SharedUtils from 'ee/packages/shared/utils'; import * as SharedUtils from 'ee/packages/shared/utils';
import { TrackingActions } from 'ee/packages/shared/constants'; import { TrackingActions } from 'ee/packages/shared/constants';
import ConanInstallation from 'ee/packages/details/components/conan_installation.vue'; 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(); const localVue = createLocalVue();
localVue.use(Vuex); localVue.use(Vuex);
...@@ -29,6 +37,8 @@ describe('PackagesApp', () => { ...@@ -29,6 +37,8 @@ describe('PackagesApp', () => {
mavenHelpPath: 'foo', mavenHelpPath: 'foo',
conanPath: 'foo', conanPath: 'foo',
conanHelpPath: 'foo', conanHelpPath: 'foo',
nugetPath: 'foo',
nugetHelpPath: 'foo',
}; };
function createComponent(packageEntity = mavenPackage, packageFiles = mavenFiles) { function createComponent(packageEntity = mavenPackage, packageFiles = mavenFiles) {
...@@ -64,6 +74,7 @@ describe('PackagesApp', () => { ...@@ -64,6 +74,7 @@ describe('PackagesApp', () => {
const npmInstallation = () => wrapper.find(NpmInstallation); const npmInstallation = () => wrapper.find(NpmInstallation);
const mavenInstallation = () => wrapper.find(MavenInstallation); const mavenInstallation = () => wrapper.find(MavenInstallation);
const conanInstallation = () => wrapper.find(ConanInstallation); const conanInstallation = () => wrapper.find(ConanInstallation);
const nugetInstallation = () => wrapper.find(NugetInstallation);
const allFileRows = () => wrapper.findAll('.js-file-row'); const allFileRows = () => wrapper.findAll('.js-file-row');
const firstFileDownloadLink = () => wrapper.find('.js-file-download'); const firstFileDownloadLink = () => wrapper.find('.js-file-download');
const deleteButton = () => wrapper.find('.js-delete-button'); const deleteButton = () => wrapper.find('.js-delete-button');
...@@ -199,4 +210,12 @@ describe('PackagesApp', () => { ...@@ -199,4 +210,12 @@ describe('PackagesApp', () => {
expect(conanInstallation()).toExist(); 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 "" ...@@ -13207,6 +13207,9 @@ msgstr ""
msgid "PackageRegistry|Add Conan Remote" msgid "PackageRegistry|Add Conan Remote"
msgstr "" msgstr ""
msgid "PackageRegistry|Add NuGet Source"
msgstr ""
msgid "PackageRegistry|Conan Command" msgid "PackageRegistry|Conan Command"
msgstr "" msgstr ""
...@@ -13225,6 +13228,12 @@ msgstr "" ...@@ -13225,6 +13228,12 @@ msgstr ""
msgid "PackageRegistry|Copy Maven registry XML" msgid "PackageRegistry|Copy Maven registry XML"
msgstr "" 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." msgid "PackageRegistry|Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
msgstr "" msgstr ""
...@@ -13252,6 +13261,9 @@ msgstr "" ...@@ -13252,6 +13261,9 @@ msgstr ""
msgid "PackageRegistry|For more information on the Maven registry, %{linkStart}see the documentation%{linkEnd}." msgid "PackageRegistry|For more information on the Maven registry, %{linkStart}see the documentation%{linkEnd}."
msgstr "" 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." msgid "PackageRegistry|If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
msgstr "" msgstr ""
...@@ -13267,6 +13279,9 @@ msgstr "" ...@@ -13267,6 +13279,9 @@ msgstr ""
msgid "PackageRegistry|Maven XML" msgid "PackageRegistry|Maven XML"
msgstr "" msgstr ""
msgid "PackageRegistry|NuGet Command"
msgstr ""
msgid "PackageRegistry|Package installation" msgid "PackageRegistry|Package installation"
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