Commit ffe1ee15 authored by Phil Hughes's avatar Phil Hughes

Refactor tree controls into Vue

This is part of the ongoing repository tree refactor
into Vue. The tree control buttons need to react
to the router changes.
parent 84241607
<script>
import { GlLink } from '@gitlab/ui';
export default {
components: {
GlLink,
},
props: {
currentPath: {
type: String,
required: false,
default: null,
},
links: {
type: Array,
required: true,
},
},
computed: {
normalizedLinks() {
return this.links.map(link => ({
text: link.text,
path: `${link.path}?path=${this.currentPath}`,
}));
},
},
};
</script>
<template>
<section class="border-top pt-1 mt-1">
<h5 class="m-0 dropdown-bold-header">{{ __('Download this directory') }}</h5>
<div class="dropdown-menu-content">
<div class="btn-group ml-0 w-100">
<gl-link
v-for="(link, index) in normalizedLinks"
:key="index"
:href="link.path"
:class="{ 'btn-primary': index === 0 }"
class="btn btn-xs"
>
{{ link.text }}
</gl-link>
</div>
</div>
</section>
</template>
<script>
import { GlLink } from '@gitlab/ui';
export default {
components: {
GlLink,
},
props: {
path: {
type: String,
required: true,
},
text: {
type: String,
required: true,
},
cssClass: {
type: String,
required: false,
default: null,
},
},
};
</script>
<template>
<gl-link :href="path" :class="cssClass" class="btn">{{ text }}</gl-link>
</template>
......@@ -3,9 +3,13 @@ import createRouter from './router';
import App from './components/app.vue';
import Breadcrumbs from './components/breadcrumbs.vue';
import LastCommit from './components/last_commit.vue';
import TreeActionLink from './components/tree_action_link.vue';
import DirectoryDownloadLinks from './components/directory_download_links.vue';
import apolloProvider from './graphql';
import { setTitle } from './utils/title';
import { parseBoolean } from '../lib/utils/common_utils';
import { webIDEUrl } from '../lib/utils/url_utility';
import { __ } from '../locale';
export default function setupVueRepositoryList() {
const el = document.getElementById('js-tree-list');
......@@ -91,6 +95,66 @@ export default function setupVueRepositoryList() {
},
});
const treeHistoryLinkEl = document.getElementById('js-tree-history-link');
const { historyLink } = treeHistoryLinkEl.dataset;
// eslint-disable-next-line no-new
new Vue({
el: treeHistoryLinkEl,
router,
render(h) {
return h(TreeActionLink, {
props: {
path: historyLink + (this.$route.params.pathMatch || '/'),
text: __('History'),
},
});
},
});
const webIdeLinkEl = document.getElementById('js-tree-web-ide-link');
if (webIdeLinkEl) {
// eslint-disable-next-line no-new
new Vue({
el: webIdeLinkEl,
router,
render(h) {
return h(TreeActionLink, {
props: {
path: webIDEUrl(`/${projectPath}/edit/${ref}/-${this.$route.params.pathMatch || '/'}`),
text: __('Web IDE'),
cssClass: 'qa-web-ide-button',
},
});
},
});
}
const directoryDownloadLinks = document.getElementById('js-directory-downloads');
if (directoryDownloadLinks) {
// eslint-disable-next-line no-new
new Vue({
el: directoryDownloadLinks,
router,
render(h) {
const currentPath = this.$route.params.pathMatch || '/';
if (currentPath !== '/') {
return h(DirectoryDownloadLinks, {
props: {
currentPath: currentPath.replace(/^\//, ''),
links: JSON.parse(directoryDownloadLinks.dataset.links),
},
});
}
return null;
},
});
}
// eslint-disable-next-line no-new
new Vue({
el,
......
......@@ -195,6 +195,17 @@ module TreeHelper
full_name: project.name_with_namespace
}
end
def directory_download_links(project, ref, archive_prefix)
formats = ['zip', 'tar.gz', 'tar.bz2', 'tar']
formats.map do |fmt|
{
text: fmt,
path: project_archive_path(project, id: tree_join(ref, archive_prefix), format: fmt)
}
end
end
end
TreeHelper.prepend_if_ee('::EE::TreeHelper')
......@@ -12,11 +12,14 @@
%h5.m-0.dropdown-bold-header= _('Download source code')
.dropdown-menu-content
= render 'projects/buttons/download_links', project: project, ref: ref, archive_prefix: archive_prefix, path: nil
- if directory? && Feature.enabled?(:git_archive_path, default_enabled: true)
%section.border-top.pt-1.mt-1
%h5.m-0.dropdown-bold-header= _('Download this directory')
.dropdown-menu-content
= render 'projects/buttons/download_links', project: project, ref: ref, archive_prefix: archive_prefix, path: @path
- if Feature.enabled?(:git_archive_path, default_enabled: true)
- if vue_file_list_enabled?
#js-directory-downloads{ data: { links: directory_download_links(project, ref, archive_prefix).to_json } }
- elsif directory?
%section.border-top.pt-1.mt-1
%h5.m-0.dropdown-bold-header= _('Download this directory')
.dropdown-menu-content
= render 'projects/buttons/download_links', project: project, ref: ref, archive_prefix: archive_prefix, path: @path
- if pipeline && pipeline.latest_builds_with_artifacts.any?
%section.border-top.pt-1.mt-1
%h5.m-0.dropdown-bold-header= _('Download artifacts')
......
......@@ -77,15 +77,21 @@
.tree-controls
= render_if_exists 'projects/tree/lock_link'
= link_to s_('Commits|History'), project_commits_path(@project, @id), class: 'btn'
- if vue_file_list_enabled?
#js-tree-history-link.d-inline-block{ data: { history_link: project_commits_path(@project, @ref) } }
- else
= link_to s_('Commits|History'), project_commits_path(@project, @id), class: 'btn'
= render 'projects/find_file_link'
- if can_create_mr_from_fork
= succeed " " do
- if can_collaborate || current_user&.already_forked?(@project)
= link_to ide_edit_path(@project, @ref, @path), class: 'btn btn-default qa-web-ide-button' do
= _('Web IDE')
- if vue_file_list_enabled?
#js-tree-web-ide-link.d-inline-block
- else
= link_to ide_edit_path(@project, @ref, @path), class: 'btn btn-default qa-web-ide-button' do
= _('Web IDE')
- else
= link_to '#modal-confirm-fork', class: 'btn btn-default qa-web-ide-button', data: { target: '#modal-confirm-fork', toggle: 'modal'} do
= _('Web IDE')
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Repository directory download links component renders downloads links for path app 1`] = `
<section
class="border-top pt-1 mt-1"
>
<h5
class="m-0 dropdown-bold-header"
>
Download this directory
</h5>
<div
class="dropdown-menu-content"
>
<div
class="btn-group ml-0 w-100"
>
<gllink-stub
class="btn btn-xs btn-primary"
href="http://test.com/?path=app"
>
zip
</gllink-stub>
<gllink-stub
class="btn btn-xs"
href="http://test.com/?path=app"
>
tar
</gllink-stub>
</div>
</div>
</section>
`;
exports[`Repository directory download links component renders downloads links for path app/assets 1`] = `
<section
class="border-top pt-1 mt-1"
>
<h5
class="m-0 dropdown-bold-header"
>
Download this directory
</h5>
<div
class="dropdown-menu-content"
>
<div
class="btn-group ml-0 w-100"
>
<gllink-stub
class="btn btn-xs btn-primary"
href="http://test.com/?path=app/assets"
>
zip
</gllink-stub>
<gllink-stub
class="btn btn-xs"
href="http://test.com/?path=app/assets"
>
tar
</gllink-stub>
</div>
</div>
</section>
`;
import { shallowMount } from '@vue/test-utils';
import DirectoryDownloadLinks from '~/repository/components/directory_download_links.vue';
let vm;
function factory(currentPath) {
vm = shallowMount(DirectoryDownloadLinks, {
propsData: {
currentPath,
links: [{ text: 'zip', path: 'http://test.com/' }, { text: 'tar', path: 'http://test.com/' }],
},
});
}
describe('Repository directory download links component', () => {
afterEach(() => {
vm.destroy();
});
it.each`
path
${'app'}
${'app/assets'}
`('renders downloads links for path $path', ({ path }) => {
factory(path);
expect(vm.element).toMatchSnapshot();
});
});
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