Commit 74fb4a1a authored by Phil Hughes's avatar Phil Hughes

Show and hide correct elements on file tree navigation

This correctly hides or shows elements based on the path in the
Vue file listing refactor
parent 16eec80d
......@@ -16,7 +16,6 @@ export default function setupVueRepositoryList() {
const { dataset } = el;
const { projectPath, projectShortPath, ref, fullName } = dataset;
const router = createRouter(projectPath, ref);
const hideOnRootEls = document.querySelectorAll('.js-hide-on-root');
apolloProvider.clients.defaultClient.cache.writeData({
data: {
......@@ -28,20 +27,7 @@ export default function setupVueRepositoryList() {
});
router.afterEach(({ params: { pathMatch } }) => {
const isRoot = pathMatch === undefined || pathMatch === '/';
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');
......
<script>
import TreeContent from '../components/tree_content.vue';
import TreePage from './tree.vue';
import { updateElementsVisibility } from '../utils/dom';
export default {
components: {
TreeContent,
TreePage,
},
mounted() {
this.updateProjectElements(true);
},
beforeDestroy() {
this.updateProjectElements(false);
},
methods: {
updateProjectElements(isShow) {
updateElementsVisibility('.js-show-on-project-root', isShow);
},
},
};
</script>
<template>
<tree-content />
<tree-page path="/" />
</template>
<script>
import TreeContent from '../components/tree_content.vue';
import { updateElementsVisibility } from '../utils/dom';
export default {
components: {
......@@ -12,6 +13,23 @@ export 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>
......
// 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
export const setTitle = (pathMatch, ref, project) => {
if (!pathMatch) return;
if (!pathMatch) {
document.title = `${project} ${DEFAULT_TITLE}`;
return;
}
const path = pathMatch.replace(/^\//, '');
const isEmpty = path === '';
/* 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
def repository_languages_bar(languages)
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) })
end
end
......
......@@ -15,7 +15,7 @@
= render 'shared/commit_well', commit: commit, ref: ref, project: project
- 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)
- if vue_file_list_enabled?
......
......@@ -3,7 +3,7 @@
- max_project_topic_length = 15
- 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
.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
......
- 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
= blob_icon readme.mode, readme.name
= 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', () => {
${'app/assets'} | ${'app/assets'}
${'app/assets/javascripts'} | ${'app/assets/javascripts'}
`('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