Commit 33eb4b49 authored by Paul Slaughter's avatar Paul Slaughter

Merge branch 'ph/vueFileCorrectlyShowElements' into 'master'

Show and hide correct elements on file tree navigation

See merge request gitlab-org/gitlab!19481
parents 36f4701f 74fb4a1a
...@@ -16,7 +16,6 @@ export default function setupVueRepositoryList() { ...@@ -16,7 +16,6 @@ export default function setupVueRepositoryList() {
const { dataset } = el; const { dataset } = el;
const { projectPath, projectShortPath, ref, fullName } = dataset; const { projectPath, projectShortPath, ref, fullName } = dataset;
const router = createRouter(projectPath, ref); const router = createRouter(projectPath, ref);
const hideOnRootEls = document.querySelectorAll('.js-hide-on-root');
apolloProvider.clients.defaultClient.cache.writeData({ apolloProvider.clients.defaultClient.cache.writeData({
data: { data: {
...@@ -28,20 +27,7 @@ export default function setupVueRepositoryList() { ...@@ -28,20 +27,7 @@ export default function setupVueRepositoryList() {
}); });
router.afterEach(({ params: { pathMatch } }) => { router.afterEach(({ params: { pathMatch } }) => {
const isRoot = pathMatch === undefined || pathMatch === '/';
setTitle(pathMatch, ref, fullName); setTitle(pathMatch, ref, fullName);
if (!isRoot) {
document
.querySelectorAll('.js-keep-hidden-on-navigation')
.forEach(elem => elem.classList.add('hidden'));
}
document
.querySelectorAll('.js-hide-on-navigation')
.forEach(elem => elem.classList.toggle('hidden', !isRoot));
hideOnRootEls.forEach(elem => elem.classList.toggle('hidden', isRoot));
}); });
const breadcrumbEl = document.getElementById('js-repo-breadcrumb'); const breadcrumbEl = document.getElementById('js-repo-breadcrumb');
......
<script> <script>
import TreeContent from '../components/tree_content.vue'; import TreePage from './tree.vue';
import { updateElementsVisibility } from '../utils/dom';
export default { export default {
components: { components: {
TreeContent, TreePage,
},
mounted() {
this.updateProjectElements(true);
},
beforeDestroy() {
this.updateProjectElements(false);
},
methods: {
updateProjectElements(isShow) {
updateElementsVisibility('.js-show-on-project-root', isShow);
},
}, },
}; };
</script> </script>
<template> <template>
<tree-content /> <tree-page path="/" />
</template> </template>
<script> <script>
import TreeContent from '../components/tree_content.vue'; import TreeContent from '../components/tree_content.vue';
import { updateElementsVisibility } from '../utils/dom';
export default { export default {
components: { components: {
...@@ -12,6 +13,23 @@ export default { ...@@ -12,6 +13,23 @@ export default {
default: '/', default: '/',
}, },
}, },
computed: {
isRoot() {
return this.path === '/';
},
},
watch: {
isRoot: {
immediate: true,
handler: 'updateElements',
},
},
methods: {
updateElements(isRoot) {
updateElementsVisibility('.js-show-on-root', isRoot);
updateElementsVisibility('.js-hide-on-root', !isRoot);
},
},
}; };
</script> </script>
......
// eslint-disable-next-line import/prefer-default-export
export const updateElementsVisibility = (selector, isVisible) => {
document.querySelectorAll(selector).forEach(elem => elem.classList.toggle('hidden', !isVisible));
};
const DEFAULT_TITLE = '· GitLab';
// eslint-disable-next-line import/prefer-default-export // eslint-disable-next-line import/prefer-default-export
export const setTitle = (pathMatch, ref, project) => { export const setTitle = (pathMatch, ref, project) => {
if (!pathMatch) return; if (!pathMatch) {
document.title = `${project} ${DEFAULT_TITLE}`;
return;
}
const path = pathMatch.replace(/^\//, ''); const path = pathMatch.replace(/^\//, '');
const isEmpty = path === ''; const isEmpty = path === '';
/* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */ /* eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings */
document.title = `${isEmpty ? 'Files' : path} · ${ref} · ${project}`; document.title = `${isEmpty ? 'Files' : path} · ${ref} · ${project} ${DEFAULT_TITLE}`;
}; };
...@@ -4,7 +4,7 @@ module RepositoryLanguagesHelper ...@@ -4,7 +4,7 @@ module RepositoryLanguagesHelper
def repository_languages_bar(languages) def repository_languages_bar(languages)
return if languages.none? return if languages.none?
content_tag :div, class: 'progress repository-languages-bar' do content_tag :div, class: 'progress repository-languages-bar js-show-on-project-root' do
safe_join(languages.map { |lang| language_progress(lang) }) safe_join(languages.map { |lang| language_progress(lang) })
end end
end end
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
= render 'shared/commit_well', commit: commit, ref: ref, project: project = render 'shared/commit_well', commit: commit, ref: ref, project: project
- if is_project_overview - if is_project_overview
.project-buttons.append-bottom-default{ class: ("js-keep-hidden-on-navigation" if vue_file_list_enabled?) } .project-buttons.append-bottom-default{ class: ("js-show-on-project-root" if vue_file_list_enabled?) }
= render 'stat_anchor_list', anchors: @project.statistics_buttons(show_auto_devops_callout: show_auto_devops_callout) = render 'stat_anchor_list', anchors: @project.statistics_buttons(show_auto_devops_callout: show_auto_devops_callout)
- if vue_file_list_enabled? - if vue_file_list_enabled?
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
- max_project_topic_length = 15 - max_project_topic_length = 15
- emails_disabled = @project.emails_disabled? - emails_disabled = @project.emails_disabled?
.project-home-panel{ class: [("empty-project" if empty_repo), ("js-keep-hidden-on-navigation" if vue_file_list_enabled?)] } .project-home-panel{ class: [("empty-project" if empty_repo), ("js-show-on-project-root" if vue_file_list_enabled?)] }
.row.append-bottom-8 .row.append-bottom-8
.home-panel-title-row.col-md-12.col-lg-6.d-flex .home-panel-title-row.col-md-12.col-lg-6.d-flex
.avatar-container.rect-avatar.s64.home-panel-avatar.append-right-default.float-none .avatar-container.rect-avatar.s64.home-panel-avatar.append-right-default.float-none
......
- if readme.rich_viewer - if readme.rich_viewer
%article.file-holder.readme-holder{ id: 'readme', class: [("limited-width-container" unless fluid_layout), ("js-hide-on-navigation" if vue_file_list_enabled?)] } %article.file-holder.readme-holder{ id: 'readme', class: [("limited-width-container" unless fluid_layout), ("js-show-on-root" if vue_file_list_enabled?)] }
.js-file-title.file-title .js-file-title.file-title
= blob_icon readme.mode, readme.name = blob_icon readme.mode, readme.name
= link_to project_blob_path(@project, tree_join(@ref, readme.path)) do = link_to project_blob_path(@project, tree_join(@ref, readme.path)) do
......
import { shallowMount } from '@vue/test-utils';
import IndexPage from '~/repository/pages/index.vue';
import TreePage from '~/repository/pages/tree.vue';
import { updateElementsVisibility } from '~/repository/utils/dom';
jest.mock('~/repository/utils/dom');
describe('Repository index page component', () => {
let wrapper;
function factory() {
wrapper = shallowMount(IndexPage);
}
afterEach(() => {
wrapper.destroy();
updateElementsVisibility.mockClear();
});
it('calls updateElementsVisibility on mounted', () => {
factory();
expect(updateElementsVisibility).toHaveBeenCalledWith('.js-show-on-project-root', true);
});
it('calls updateElementsVisibility after destroy', () => {
factory();
wrapper.destroy();
expect(updateElementsVisibility.mock.calls.pop()).toEqual(['.js-show-on-project-root', false]);
});
it('renders TreePage', () => {
factory();
const child = wrapper.find(TreePage);
expect(child.exists()).toBe(true);
expect(child.props()).toEqual({ path: '/' });
});
});
import { shallowMount } from '@vue/test-utils';
import TreePage from '~/repository/pages/tree.vue';
import { updateElementsVisibility } from '~/repository/utils/dom';
jest.mock('~/repository/utils/dom');
describe('Repository tree page component', () => {
let wrapper;
function factory(path) {
wrapper = shallowMount(TreePage, { propsData: { path } });
}
afterEach(() => {
wrapper.destroy();
updateElementsVisibility.mockClear();
});
describe('when root path', () => {
beforeEach(() => {
factory('/');
});
it('shows root elements', () => {
expect(updateElementsVisibility.mock.calls).toEqual([
['.js-show-on-root', true],
['.js-hide-on-root', false],
]);
});
describe('when changed', () => {
beforeEach(() => {
updateElementsVisibility.mockClear();
wrapper.setProps({ path: '/test' });
});
it('hides root elements', () => {
expect(updateElementsVisibility.mock.calls).toEqual([
['.js-show-on-root', false],
['.js-hide-on-root', true],
]);
});
});
});
describe('when non-root path', () => {
beforeEach(() => {
factory('/test');
});
it('hides root elements', () => {
expect(updateElementsVisibility.mock.calls).toEqual([
['.js-show-on-root', false],
['.js-hide-on-root', true],
]);
});
});
});
import { setHTMLFixture } from '../../helpers/fixtures';
import { updateElementsVisibility } from '~/repository/utils/dom';
describe('updateElementsVisibility', () => {
it('adds hidden class', () => {
setHTMLFixture('<div class="js-test"></div>');
updateElementsVisibility('.js-test', false);
expect(document.querySelector('.js-test').classList).toContain('hidden');
});
it('removes hidden class', () => {
setHTMLFixture('<div class="hidden js-test"></div>');
updateElementsVisibility('.js-test', true);
expect(document.querySelector('.js-test').classList).not.toContain('hidden');
});
});
...@@ -8,8 +8,8 @@ describe('setTitle', () => { ...@@ -8,8 +8,8 @@ describe('setTitle', () => {
${'app/assets'} | ${'app/assets'} ${'app/assets'} | ${'app/assets'}
${'app/assets/javascripts'} | ${'app/assets/javascripts'} ${'app/assets/javascripts'} | ${'app/assets/javascripts'}
`('sets document title as $title for $path', ({ path, title }) => { `('sets document title as $title for $path', ({ path, title }) => {
setTitle(path, 'master', 'GitLab'); setTitle(path, 'master', 'GitLab Org / GitLab');
expect(document.title).toEqual(`${title} · master · GitLab`); expect(document.title).toEqual(`${title} · master · GitLab Org / GitLab · GitLab`);
}); });
}); });
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