Skip to content

Commit

Permalink
Merge pull request #9071 from inkuzmin/navbar-vue
Browse files Browse the repository at this point in the history
[WIP] Porting Masthead to Vue.js
  • Loading branch information
dannon authored May 19, 2020
2 parents 1ee7a31 + 3964d1a commit 29fdb27
Show file tree
Hide file tree
Showing 13 changed files with 531 additions and 377 deletions.
112 changes: 112 additions & 0 deletions client/galaxy/scripts/components/Masthead/Masthead.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import Masthead from "./Masthead.vue";
import { mount, createLocalVue } from "@vue/test-utils";
import Scratchbook from "layout/scratchbook";

describe("Masthead.vue", () => {
let wrapper;
let localVue;
let scratchbook;
let quotaRendered, quotaEl;

beforeEach(() => {
localVue = createLocalVue();
quotaRendered = false;
quotaEl = null;

const quotaMeter = {
setElement: function (el) {
quotaEl = el;
},
render: function () {
quotaRendered = true;
},
};

const tabs = [
// Main Analysis Tab..
{
id: "analysis",
title: "Analyze",
menu: false,
url: "root",
},
{
id: "shared",
title: "Shared Items",
menu: [{ title: "_menu_title", url: "_menu_url", target: "_menu_target" }],
},
// Hidden tab (pre-Vue framework supported this, not sure it is used
// anywhere?)
{
id: "hiddentab",
title: "Hidden Title",
menu: false,
hidden: true,
},
];
const activeTab = "shared";

// scratchbook assumes this is a Backbone collection - mock that out.
tabs.add = (x) => {
tabs.push(x);
return x;
};
scratchbook = new Scratchbook({
collection: tabs,
});
const frames = scratchbook.getFrames();

wrapper = mount(Masthead, {
propsData: {
quotaMeter,
frames,
tabs,
activeTab,
appRoot: "prefix/",
},
localVue,
attachToDocument: true,
});
});

it("set quota element and renders it", () => {
expect(quotaEl).to.not.equals(null);
expect(quotaRendered).to.equals(true);
});

it("should render simple tab item links", () => {
expect(wrapper.findAll("li.nav-item").length).to.equals(5);
// Ensure specified link title respected.
expect(wrapper.find("#analysis a").text()).to.equals("Analyze");
expect(wrapper.find("#analysis a").attributes("href")).to.equals("prefix/root");
});

it("should render tab items with menus", () => {
// Ensure specified link title respected.
expect(wrapper.find("#shared a").text()).to.equals("Shared Items");
expect(wrapper.find("#shared").classes("dropdown")).to.equals(true);

expect(wrapper.findAll("#shared .dropdown-menu li").length).to.equals(1);
expect(wrapper.find("#shared .dropdown-menu li a").attributes().href).to.equals("prefix/_menu_url");
expect(wrapper.find("#shared .dropdown-menu li a").attributes().target).to.equals("_menu_target");
expect(wrapper.find("#shared .dropdown-menu li a").text()).to.equals("_menu_title");
});

it("should make hidden tabs hidden", () => {
expect(wrapper.find("#analysis").attributes().style).to.not.contain("display: none");
expect(wrapper.find("#hiddentab").attributes().style).to.contain("display: none");
});

it("should highlight the active tab", () => {
expect(wrapper.find("#analysis").classes("active")).to.equals(false);
expect(wrapper.find("#shared").classes("active")).to.equals(true);
});

it("should display scratchbook button", async () => {
expect(wrapper.find("#enable-scratchbook a span").classes("fa-th")).to.equals(true);
expect(scratchbook.active).to.equals(false);
// wrapper.find("#enable-scratchbook a").trigger("click");
// await localVue.nextTick();
// expect(scratchbook.active).to.equals(true);
});
});
116 changes: 116 additions & 0 deletions client/galaxy/scripts/components/Masthead/Masthead.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<template>
<b-navbar
id="masthead"
toggleable="lg"
type="dark"
role="navigation"
aria-label="Main"
class="justify-content-center"
>
<b-navbar-brand :href="brandLink" aria-label="homepage">
<img alt="logo" class="navbar-brand-image" :src="brandImage" />
<span class="navbar-brand-title">{{ brandTitle }}</span>
</b-navbar-brand>

<b-navbar-nav>
<masthead-item
v-for="(tab, idx) in tabs"
:tab="tab"
:activeTab="activeTab"
:key="`tab-${idx}`"
:appRoot="appRoot"
:Galaxy="Galaxy"
v-show="!(tab.hidden === undefined ? false : tab.hidden)"
@updateScratchbookTab="updateScratchbookTab"
>
</masthead-item>
</b-navbar-nav>

<div ref="quota-meter-container" class="quota-meter-container" />
</b-navbar>
</template>

<script>
import { BNavbar, BNavbarBrand, BNavbarNav } from "bootstrap-vue";
import MastheadItem from "./MastheadItem";
import _ from "underscore";
export default {
name: "Masthead",
props: {
brandTitle: {
type: String,
},
brandLink: {
type: String,
},
brandImage: {
type: String,
},
quotaMeter: {
type: Object,
},
activeTab: {
type: String,
},
tabs: {
type: Array,
},
frames: {
type: Object,
},
appRoot: {
type: String,
},
Galaxy: {
type: Object,
},
},
components: {
BNavbar,
BNavbarBrand,
BNavbarNav,
MastheadItem,
},
methods: {
updateScratchbookTab(tab) {
_.each(this.tabs, (tab, i) => {
if (tab.id === "enable-scratchbook") {
tab.active = !tab.active;
this.$set(this.tabs, i, {
...tab,
toggle: tab.active,
show_note: tab.active,
note_cls: tab.active && "fa fa-check",
});
}
});
},
},
mounted() {
this.quotaMeter.setElement(this.$refs["quota-meter-container"]);
this.quotaMeter.render();
const idx = _.findIndex(this.tabs, { id: "show-scratchbook" });
this.frames
.on("add remove", () => {
this.$set(this.tabs, idx, {
...this.tabs[idx],
note: this.frames.length(),
visible: this.frames.length() > 0,
show_note: this.frames.length() > 0,
});
})
.on("show hide", () => {
this.$set(this.tabs, idx, {
...this.tabs[idx],
toggle: this.frames.visible,
icon: (this.frames.visible && "fa-eye") || "fa-eye-slash",
});
});
},
};
</script>

<style scoped></style>
42 changes: 42 additions & 0 deletions client/galaxy/scripts/components/Masthead/MastheadItem.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import MastheadItem from "./MastheadItem.vue";
import { mount, createLocalVue } from "@vue/test-utils";

describe("Masthead.vue", () => {
let wrapper;
let localVue;
let active, menu;

beforeEach(() => {
localVue = createLocalVue();
});

function m() {
const tab = {
id: "mytab",
menu: menu,
};
return mount(MastheadItem, {
propsData: {
tab,
activeTab: active,
},
localVue,
});
}

it("should render active tab with menus", async () => {
active = "mytab";
menu = true;
wrapper = m();
expect(wrapper.vm.active).to.equals(true);
expect(wrapper.vm.menu).to.equals(true);
});

it("should render inactive tabs without menus", async () => {
active = "othertab";
menu = false;
wrapper = m();
expect(wrapper.vm.active).to.equals(false);
expect(wrapper.vm.menu).to.equals(false);
});
});
Loading

0 comments on commit 29fdb27

Please sign in to comment.