This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.
osr-discourse-src/app/assets/javascripts/discourse/widgets/hamburger-menu.js.es6
Sam Saffron 79b8c08d45 DEV: give categories-separator class to HR after cateogries
This allows for better styling of the hamburger menu
2019-11-18 17:31:01 +11:00

362 lines
9.4 KiB
JavaScript

import { later } from "@ember/runloop";
import { createWidget, applyDecorators } from "discourse/widgets/widget";
import { h } from "virtual-dom";
import DiscourseURL from "discourse/lib/url";
import { ajax } from "discourse/lib/ajax";
import { userPath } from "discourse/lib/url";
import { NotificationLevels } from "discourse/lib/notification-levels";
const flatten = array => [].concat.apply([], array);
createWidget("priority-faq-link", {
tagName: "a.faq-priority.widget-link",
buildAttributes(attrs) {
return { href: attrs.href };
},
html() {
return [
I18n.t("faq"),
" ",
h("span.badge.badge-notification", I18n.t("new_item"))
];
},
click(e) {
e.preventDefault();
if (this.siteSettings.faq_url === this.attrs.href) {
ajax(userPath("read-faq"), { method: "POST" }).then(() => {
this.currentUser.set("read_faq", true);
DiscourseURL.routeToTag($(e.target).closest("a")[0]);
});
} else {
DiscourseURL.routeToTag($(e.target).closest("a")[0]);
}
}
});
export default createWidget("hamburger-menu", {
tagName: "div.hamburger-panel",
settings: {
showCategories: true,
maxWidth: 320,
showFAQ: true,
showAbout: true
},
adminLinks() {
const { currentUser } = this;
const links = [
{
route: "admin",
className: "admin-link",
icon: "wrench",
label: "admin_title"
}
];
if (currentUser.admin) {
links.push({
href: "/admin/site_settings",
icon: "cog",
label: "admin.site_settings.title",
className: "settings-link"
});
}
return links.map(l => this.attach("link", l));
},
lookupCount(type) {
const tts = this.register.lookup("topic-tracking-state:main");
return tts ? tts.lookupCount(type) : 0;
},
showUserDirectory() {
if (!this.siteSettings.enable_user_directory) return false;
if (this.siteSettings.hide_user_profiles_from_public && !this.currentUser)
return false;
return true;
},
generalLinks() {
const { siteSettings } = this;
const links = [];
links.push({
route: "discovery.latest",
className: "latest-topics-link",
label: "filters.latest.title",
title: "filters.latest.help"
});
if (this.currentUser) {
links.push({
route: "discovery.new",
className: "new-topics-link",
labelCount: "filters.new.title_with_count",
label: "filters.new.title",
title: "filters.new.help",
count: this.lookupCount("new")
});
links.push({
route: "discovery.unread",
className: "unread-topics-link",
labelCount: "filters.unread.title_with_count",
label: "filters.unread.title",
title: "filters.unread.help",
count: this.lookupCount("unread")
});
}
// Staff always see the review link. Non-staff will see it if there are items to review
if (
this.currentUser &&
(this.currentUser.staff || this.currentUser.reviewable_count)
) {
links.push({
route: siteSettings.reviewable_default_topics
? "review.topics"
: "review",
className: "review",
label: "review.title",
badgeCount: "reviewable_count",
badgeClass: "reviewables"
});
}
links.push({
route: "discovery.top",
className: "top-topics-link",
label: "filters.top.title",
title: "filters.top.help"
});
if (siteSettings.enable_badges) {
links.push({
route: "badges",
className: "badge-link",
label: "badges.title"
});
}
if (this.showUserDirectory()) {
links.push({
route: "users",
className: "user-directory-link",
label: "directory.title"
});
}
if (this.siteSettings.enable_group_directory) {
links.push({
route: "groups",
className: "groups-link",
label: "groups.index.title"
});
}
if (this.siteSettings.tagging_enabled) {
links.push({ route: "tags", label: "tagging.tags" });
}
const extraLinks = flatten(
applyDecorators(this, "generalLinks", this.attrs, this.state)
);
return links.concat(extraLinks).map(l => this.attach("link", l));
},
listCategories() {
const maxCategoriesToDisplay = this.siteSettings
.header_dropdown_category_count;
let categories = [];
if (this.currentUser) {
const allCategories = this.site
.get("categories")
.filter(c => c.notification_level !== NotificationLevels.MUTED);
categories = allCategories
.filter(c => c.get("newTopics") > 0 || c.get("unreadTopics") > 0)
.sort((a, b) => {
return (
b.get("newTopics") +
b.get("unreadTopics") -
(a.get("newTopics") + a.get("unreadTopics"))
);
});
const topCategoryIds = this.currentUser.get("top_category_ids") || [];
topCategoryIds.forEach(id => {
const category = allCategories.find(c => c.id === id);
if (category && !categories.includes(category)) {
categories.push(category);
}
});
categories = categories.concat(
allCategories
.filter(c => !categories.includes(c))
.sort((a, b) => b.topic_count - a.topic_count)
);
} else {
categories = this.site
.get("categoriesByCount")
.filter(c => c.notification_level !== NotificationLevels.MUTED);
}
if (!this.siteSettings.allow_uncategorized_topics) {
categories = categories.filter(
c => c.id !== this.site.uncategorized_category_id
);
}
const moreCount = categories.length - maxCategoriesToDisplay;
categories = categories.slice(0, maxCategoriesToDisplay);
return this.attach("hamburger-categories", { categories, moreCount });
},
footerLinks(prioritizeFaq, faqUrl) {
const links = [];
if (this.settings.showAbout) {
links.push({
route: "about",
className: "about-link",
label: "about.simple_title"
});
}
if (this.settings.showFAQ && !prioritizeFaq) {
links.push({ href: faqUrl, className: "faq-link", label: "faq" });
}
const { site } = this;
if (!site.mobileView && !this.capabilities.touch) {
links.push({
href: "",
action: "showKeyboard",
className: "keyboard-shortcuts-link",
label: "keyboard_shortcuts_help.title"
});
}
if (
this.site.mobileView ||
(this.siteSettings.enable_mobile_theme && this.capabilities.touch)
) {
links.push({
action: "toggleMobileView",
className: "mobile-toggle-link",
label: this.site.mobileView ? "desktop_view" : "mobile_view"
});
}
const extraLinks = flatten(
applyDecorators(this, "footerLinks", this.attrs, this.state)
);
return links.concat(extraLinks).map(l => this.attach("link", l));
},
panelContents() {
const { currentUser } = this;
const results = [];
let faqUrl = this.siteSettings.faq_url;
if (!faqUrl || faqUrl.length === 0) {
faqUrl = Discourse.getURL("/faq");
}
const prioritizeFaq =
this.settings.showFAQ && this.currentUser && !this.currentUser.read_faq;
if (prioritizeFaq) {
results.push(
this.attach("menu-links", {
name: "faq-link",
heading: true,
contents: () => {
return this.attach("priority-faq-link", { href: faqUrl });
}
})
);
}
if (currentUser && currentUser.staff) {
results.push(
this.attach("menu-links", {
name: "admin-links",
contents: () => {
const extraLinks = flatten(
applyDecorators(this, "admin-links", this.attrs, this.state)
);
return this.adminLinks().concat(extraLinks);
}
})
);
}
results.push(
this.attach("menu-links", {
name: "general-links",
contents: () => this.generalLinks()
})
);
if (this.settings.showCategories) {
results.push(this.listCategories());
results.push(h("hr.categories-separator"));
}
results.push(
this.attach("menu-links", {
name: "footer-links",
omitRule: true,
contents: () => this.footerLinks(prioritizeFaq, faqUrl)
})
);
return results;
},
html() {
return this.attach("menu-panel", {
contents: () => this.panelContents(),
maxWidth: this.settings.maxWidth
});
},
clickOutsideMobile(e) {
const $centeredElement = $(document.elementFromPoint(e.clientX, e.clientY));
if (
$centeredElement.parents(".panel").length &&
!$centeredElement.hasClass("header-cloak")
) {
this.sendWidgetAction("toggleHamburger");
} else {
const $window = $(window);
const windowWidth = $window.width();
const $panel = $(".menu-panel");
$panel.addClass("animate");
const panelOffsetDirection = this.site.mobileView ? "left" : "right";
$panel.css(panelOffsetDirection, -windowWidth);
const $headerCloak = $(".header-cloak");
$headerCloak.addClass("animate");
$headerCloak.css("opacity", 0);
later(() => this.sendWidgetAction("toggleHamburger"), 200);
}
},
clickOutside(e) {
if (this.site.mobileView) {
this.clickOutsideMobile(e);
} else {
this.sendWidgetAction("toggleHamburger");
}
}
});