let expiryTabBuffer = 1800000;
// Create variables
let localStorageTabPrefix = "tab-menu-data";
let categoriesTabPrefix = "tab-menu-category";
let sectionsTabPrefix = "tab-menu-section";
let articleTabPrefix = "tab-menu-article";
let currentTabItemClass = "current-item";
let currentTabItemParentClass = "current-item-parent";
let mainTabParent = null;
// Fetch data from url
async function fetchDataFromUrl(url, dataField){
let returnData = {};
let response = await fetch(url);
let responseJson = await response.json();
responseJson[dataField].map(dataSingle=>{
returnData[dataSingle.id] = dataSingle;
});
if (responseJson.next_page) {
let nextPage = await fetchDataFromUrl(responseJson.next_page,dataField);
return {...returnData,...nextPage};
} else {
return returnData;
}
}
// Setting all retrieved data from URL
async function setRequiredData(locale = 'en-us'){
let categoriesPromise = fetchDataFromUrl(`/api/v2/help_center/${locale}/categories`,'categories');
let sectionsPromise = fetchDataFromUrl(`/api/v2/help_center/${locale}/sections`,'sections');
// let articlesPromise = fetchDataFromUrl(`/api/v2/help_center/${locale}/articles`,'articles');
let [categories,sections] = await Promise.all([categoriesPromise,sectionsPromise]).catch(err=>{
console.error("Error occured in fetching data",err);
});
let subSections = {};
let subSubSections = {};
let subSubSubSections = {};
let subSubSubSubSections = {};
for (let [key, value] of Object.entries(sections)) {
if(value.parent_section_id){
subSections[value.id] = value;
delete sections[key];
}
}
for (let [key, value] of Object.entries(subSections)) {
if(value.parent_section_id && subSections[value.parent_section_id]){
subSubSections[value.id] = value;
delete subSections[key];
}
}
for (let [key, value] of Object.entries(subSubSections)) {
if(value.parent_section_id && subSubSections[value.parent_section_id]){
subSubSubSections[value.id] = value;
delete subSubSections[key];
}
}
for (let [key, value] of Object.entries(subSubSubSections)) {
if(value.parent_section_id && subSubSubSections[value.parent_section_id]){
subSubSubSubSections[value.id] = value;
delete subSubSubSections[key];
}
}
let now = new Date();
let storageData = {
categories,
sections,
subSections,
subSubSections,
subSubSubSections,
subSubSubSubSections,
expiry : now.getTime() + expiryTabBuffer
}
localStorage.setItem(`${localStorageTabPrefix}-${locale}`, JSON.stringify(storageData));
return storageData;
}
// Function for getting URL data and return its type and ID
function fetchCurrentUrlData(){
let returnData = {
type : null,
id : null
};
let pathArray = window.location.pathname.split("/");
pathArray = pathArray.slice(3);
if(pathArray[0] && pathArray[1]){
// Get current page ID to mark the active element
let currentId = document.getElementById('current-id')
if (currentId) {
currentId = currentId.dataset.id
} else {
currentId = parseInt(pathArray[1].replace(/(^\d+)/i,'$1'))
}
returnData.type = pathArray[0];
returnData.id = currentId;
}
return returnData;
}
// Function for getting breadcrumb data and return its type and ID
function fetchCurrentBreadcrumbData() {
let breadcrumb = document.querySelector('.sub-nav ol.breadcrumbs')
if (breadcrumb) {
let returnData = {}
let pathElement = breadcrumb.querySelector('li:last-child')
let pathUrl = pathElement.querySelector('a').href
let pathArray = pathUrl.split("/");
pathArray = pathArray.slice(5)
if (pathArray[0] && pathArray[1]) {
let pathType = pathArray[0]
switch (pathType) {
case "categories":
pathType = "category"
break;
case "sections":
pathType = "section"
}
returnData.type = pathType;
returnData.id = parseInt(pathArray[1].replace(/(^\d+)/i,'$1'))
}
return returnData;
}
}
function setRequiredLi(urlData, locale) {
let prefix = null;
// set prefix from URL
if(urlData.type == 'categories'){
prefix = categoriesTabPrefix;
} else if(urlData.type == 'sections'){
prefix = sectionsTabPrefix;
} else if (urlData.type == 'articles'){
prefix = articleTabPrefix;
}
if(prefix){
let currentItem = document.getElementById(`${prefix}-link-${urlData.id}`);
// Check if current item are fetched from API or not
if(currentItem){
// If present, add current-item class to element
currentItem.classList.add(currentTabItemClass);
let currentItemParent;
while(currentItemParent = currentItem.parentNode.closest("li")){
currentItem = currentItemParent
currentItem.classList.add(currentTabItemParentClass);
}
}
if (prefix == articleTabPrefix || prefix == sectionsTabPrefix) {
let breadcrumbData = fetchCurrentBreadcrumbData()
// Get current sidebar parent list from breadcrumb
let currentSidebar = document.getElementById(`menu-tab-${breadcrumbData.type}-link-${breadcrumbData.id}`)
if (currentSidebar) {
let currentSidebarParent;
while (currentSidebarParent = currentSidebar.parentNode.closest("li")) {
currentSidebar = currentSidebarParent
// Fetch article if current item or article parent not present
if (!currentItem) {
if (!currentSidebar.classList.contains('tab-menu-category')) {
fetchTabArticleOnClick(currentSidebar, locale)
}
} else if (currentSidebar.querySelector('.tab-menu-article') == null) {
if (!currentSidebar.classList.contains('tab-menu-category')) {
fetchTabArticleOnClick(currentSidebar, locale)
}
}
currentSidebar.querySelector("a").click()
currentSidebar.classList.add(currentTabItemParentClass)
}
}
}
}
}
function fetchMenuTabData(key) {
const itemStr = localStorage.getItem(key)
// if the item doesn't exist, return null
if (!itemStr) {
return null
}
const item = JSON.parse(itemStr)
const now = new Date()
// compare the expiry time of the item with the current time
if (now.getTime() > item.expiry) {
// If the item is expired, delete the item from storage
// and return null
localStorage.removeItem(key)
return null
}
return item
}
function createTabHeader(parent, prefix, data){
let parentNode = document.getElementById(parent);
if(parentNode){
let parentUl = parentNode.getElementsByTagName("ul")[0];
if(!parentUl){
parentUl = document.createElement("ul");
if((prefix == sectionsTabPrefix) && data.parent_section_id){
parentUl.className = `${articleTabPrefix}-header`;
} else {
parentUl.className = `${prefix}-header`;
}
parentNode.appendChild(parentUl);
}
let elementLi = document.createElement("li");
elementLi.className = `${prefix}-header-wrapper`;
parentUl.appendChild(elementLi);
let elementLink = document.createElement("a");
elementLink.className = `${prefix}-header-link`;
let elementSpan = document.createElement('span')
if (prefix == categoriesTabPrefix) {
elementLink.dataset.target = `#${categoriesTabPrefix}-${data.id}`;
elementLink.dataset.toggle = 'tab'
elementSpan.innerHTML = data.name
elementLink.appendChild(elementSpan)
} else if (prefix == sectionsTabPrefix) {
elementLink.dataset.target = `#${sectionsTabPrefix}-${data.id}`;
elementLink.dataset.toggle = 'tab'
elementSpan.innerHTML = data.name
elementLink.appendChild(elementSpan)
} else if (prefix == articleTabPrefix) {
elementLink.href = data.html_url;
elementLink.innerHTML = data.name;
} else {
elementLink.dataset.target = `#${data.id}`;
}
elementLi.appendChild(elementLink);
}
}
function createDummyTabHeader(parent, prefix, data, isCollapsible){
let parentNode = document.getElementById(parent);
// console.log(prefix)
if(parentNode){
let parentDiv = parentNode.getElementsByTagName("div")[0];
if(!parentDiv){
parentDiv = document.createElement("div");
if((prefix == sectionsTabPrefix) && data.parent_section_id){
parentDiv.className = `${articleTabPrefix}-content`;
} else {
parentDiv.className = `${prefix}-content`;
}
if (data.parent_section_id) {
parentDiv.id = `${prefix}-collapse-${data.parent_section_id}`;
if (isCollapsible) {
parentDiv.classList.add('collapse')
}
} else if (prefix == articleTabPrefix) {
parentDiv.id = `${sectionsTabPrefix}-collapse-${data.section_id}`
if (isCollapsible) {
parentDiv.classList.add('collapse')
}
} else {
// parentDiv.id = `${articleTabPrefix}-collapse-${data.section_id}`;
}
parentNode.appendChild(parentDiv);
}
// Create div tag inside parentDiv
let elementDiv = document.createElement("div");
elementDiv.id = `${prefix}-${data.id}`;
elementDiv.className = prefix;
// Create anchor tag inside elementDiv
let elementLink = document.createElement("a");
elementLink.id = `${prefix}-link-${data.id}`;
elementLink.dataset.id = data.id;
elementLink.className = `${prefix}-content-link`;
let elementSpan = document.createElement('span')
let elementArrow = document.createElement('i')
elementArrow.className = 'fa fa-angle-down'
if (prefix == categoriesTabPrefix) {
elementSpan.innerHTML = data.name
elementLink.appendChild(elementSpan)
} else if (prefix == sectionsTabPrefix) {
elementLink.dataset.target = `#${sectionsTabPrefix}-collapse-${data.id}`
elementLink.dataset.toggle = 'collapse'
elementLink.ariaExpanded = false;
elementSpan.innerHTML = data.name
elementLink.appendChild(elementSpan)
elementLink.appendChild(elementArrow)
elementDiv.appendChild(elementLink);
} else if (prefix == articleTabPrefix) {
elementLink.href = data.html_url;
elementLink.innerHTML = data.name;
if (data.user_type == "staff") {
let svgElement = ``
elementLink.innerHTML = `${data.name} ${svgElement}`
}
if (data.promoted == true) {
let svgPromotedElement = ``
elementLink.innerHTML = `${svgPromotedElement} ${data.name}`
}
if ((data.promoted == true) && ( data.user_type == "staff")) {
let svgElement = ``
let svgPromotedElement = ``
elementLink.innerHTML = `${svgPromotedElement} ${data.name} ${svgElement}`
}
elementDiv.appendChild(elementLink);
}
else {
elementLink.dataset.target = `#${data.id}`;
}
parentDiv.appendChild(elementDiv);
}
}
async function fetchUserSegment(id) {
let userSegment = await fetch(`/api/v2/help_center/user_segments/${id}`)
let response = await userSegment.json()
return response.user_segment
}
// Helper function to create article element on section click
function createTabArticleElement(parent, data) {
// console.log(data)
let prefix = "tab-menu-article"
let currentItem = fetchCurrentUrlData()
let currentId = currentItem.id
let parentNode = document.getElementById(parent)
let parentDiv = parentNode.getElementsByTagName("div")[0];
if(!parentDiv){
parentDiv = document.createElement("div");
}
parentDiv.className = `${prefix}-content collapse in`;
parentDiv.id = `${sectionsTabPrefix}-collapse-${data.section_id}`
parentNode.appendChild(parentDiv);
let elementDiv = document.createElement("div");
elementDiv.id = `${prefix}-${data.id}`;
elementDiv.className = prefix;
if (data.id == currentId) {
elementDiv.classList.add(currentTabItemParentClass)
}
parentDiv.appendChild(elementDiv);
// Create anchor tag inside elementDiv
let elementLink = document.createElement("a");
elementLink.id = `${prefix}-link-${data.id}`;
elementLink.dataset.id = `${prefix}-${data.id}`;
elementLink.className = `${prefix}-content-link`;
if (data.id == currentId) {
elementLink.classList.add(currentTabItemClass)
}
elementLink.href = data.html_url;
elementLink.innerHTML = data.name;
if (data.user_type == "staff") {
let svgElement = ``
elementLink.innerHTML = `${data.name} ${svgElement}`
}
if (data.promoted == true) {
let svgPromotedElement = ``
elementLink.innerHTML = `${svgPromotedElement} ${data.name}`
}
if ((data.promoted == true) && ( data.user_type == "staff")) {
let svgElement = ``
let svgPromotedElement = ``
elementLink.innerHTML = `${svgPromotedElement} ${data.name} ${svgElement}`
}
elementLink.dataset.target = `#${data.id}`;
elementLink.ariaExpanded = false;
elementDiv.appendChild(elementLink);
}
// Function for fetching article on section click
async function fetchTabArticleOnClick(element, locale) {
let sectionElement = $(element)
let sectionId =
$(element)
.find('a')
.attr('data-id')
let parent = $(element).attr('id')
let url = `/api/v2/help_center/${locale}/sections/${sectionId}/articles?per_page=100`
let articleData = await fetchDataFromUrl(url, 'articles')
let [articlesPromise] = await Promise.all([articleData])
.then($(sectionElement).removeClass('is-loading'))
.catch(err=>{
console.error("Error occured in fetching data",err);
});
if (Object.keys(articlesPromise).length != 0) {
$(element).find('a').eq(0).attr('aria-expanded', true)
for (let [key, value] of Object.entries(articlesPromise)) {
if (HelpCenter.user.role !== 'end_user') {
if (value.user_segment_id !== null) {
let userSegmentId = value.user_segment_id
let userSegment = await fetchUserSegment(userSegmentId)
if (userSegment.user_type == 'staff') {
value.user_type = "staff"
}
}
}
createTabArticleElement(parent, value)
}
}
// Get old localstorage data
let oldStorage = fetchMenuTabData(`${localStorageTabPrefix}-${locale}`)
// Assign new promise with old data to new array
let articles = Object.assign(articlesPromise, oldStorage["articles"])
let storageData = {
...oldStorage,
articles
}
localStorage.setItem(`${localStorageTabPrefix}-${locale}`, JSON.stringify(storageData))
}
async function createMenuTab(sidebar, locale = "en-us") {
let menuTree = document.getElementById(sidebar);
if(menuTree){
let MenuTabData = fetchMenuTabData(`${localStorageTabPrefix}-${locale}`);
if(!MenuTabData){
MenuTabData = await setRequiredData(locale);
}
let categoriesLength = Object.keys(MenuTabData.categories).length
if (categoriesLength >= 1) {
for (let [key, value] of Object.entries(MenuTabData.categories)) { // Fetch categories data using category classname
createTabHeader(sidebar,categoriesTabPrefix,value);
}
for (let [key, value] of Object.entries(MenuTabData.categories)) { // Fetch categories data using category classname for dummy
createDummyTabHeader(sidebar,categoriesTabPrefix,value);
}
for (let [key, value] of Object.entries(MenuTabData.sections)) {
createDummyTabHeader(`${categoriesTabPrefix}-${value.category_id}`, sectionsTabPrefix, value, true);
}
for (let [key, value] of Object.entries(MenuTabData.subSections)) {
createDummyTabHeader(`${sectionsTabPrefix}-${value.parent_section_id}`,sectionsTabPrefix,value, true);
}
for (let [key, value] of Object.entries(MenuTabData.subSubSections)) {
createDummyTabHeader(`${sectionsTabPrefix}-${value.parent_section_id}`,sectionsTabPrefix,value, true);
}
for (let [key, value] of Object.entries(MenuTabData.subSubSubSections)) {
createDummyTabHeader(`${sectionsTabPrefix}-${value.parent_section_id}`,sectionsTabPrefix,value, true);
}
for (let [key, value] of Object.entries(MenuTabData.subSubSubSubSections)) {
createDummyTabHeader(`${sectionsTabPrefix}-${value.parent_section_id}`,sectionsTabPrefix,value, true);
}
}
if (MenuTabData.articles) {
for (let [key, value] of Object.entries(MenuTabData.articles)) {
createDummyTabHeader(`${sectionsTabPrefix}-${value.section_id}`,articleTabPrefix,value, true);
}
}
// Get current page data from URL in case no breadcrumb present (eg: homepage)
let urlData = fetchCurrentUrlData();
// Then set the active list based on urlData
if(urlData.type){
setRequiredLi(urlData, locale);
}
let element = document.getElementsByClassName('tab-menu-section')
for (i = 0; i < element.length; i++) {
if ($(element[i]).attr('aria-expanded', 'false')) {
if (!$(element[i]).hasClass('current-item-parent')) {
if ($(element[i]).find('.tab-menu-article').eq(0).length == 0) {
element[i].addEventListener('click', function(e) {
fetchTabArticleOnClick(this, locale)
}, {once: true})
}
}
} else { return null }
}
// console.log(MenuTabData)
}
}