ohayolibs
Version:
Ohayo is a set of essential modules for ohayojp.
244 lines (218 loc) • 7.14 kB
text/typescript
import { Inject, Injectable } from '@angular/core';
import { OHAYO_I18N_TOKEN, Menu } from '@ohayo/theme';
import { Meta, MetaList, MetaSearchGroup, MetaSearchGroupItem } from '../interfaces';
import { META as ACLMeta } from '../routes/gen/acl/meta';
import { META as AuthMeta } from '../routes/gen/auth/meta';
import { META as CacheMeta } from '../routes/gen/cache/meta';
import { META as ChartMeta } from '../routes/gen/chart/meta';
import { META as CliMeta } from '../routes/gen/cli/meta';
import { META as ComponentsMeta } from '../routes/gen/components/meta';
import { META as DocsMeta } from '../routes/gen/docs/meta';
import { META as FormMeta } from '../routes/gen/form/meta';
import { META as MockMeta } from '../routes/gen/mock/meta';
import { META as ThemeMeta } from '../routes/gen/theme/meta';
import { META as UtilMeta } from '../routes/gen/util/meta';
import { I18NService } from './i18n/service';
const FULLMETAS: Meta[] = [
DocsMeta,
ComponentsMeta,
AuthMeta,
ACLMeta,
CacheMeta,
ChartMeta,
MockMeta,
UtilMeta,
FormMeta,
CliMeta,
ThemeMeta,
] as any;
export class MetaService {
private _platMenus: any[];
private _menus: any[] | null;
private _type: string;
next: any;
prev: any;
constructor( private i18n: I18NService) {
// plat titles
for (const g of FULLMETAS) {
for (const item of g.list!) {
const curTitle = item.meta![i18n.defaultLang].title;
item._t =
typeof curTitle !== 'string'
? Object.values(curTitle!)
.map(v => v)
.join('-')
: curTitle;
}
}
}
private _data: any;
private _isPages = false;
private getCatgory(url: string): Menu | undefined {
const arr = url.split('?')[0].split('/');
if (arr.length <= 2) return;
let categoryName = arr[1].toLowerCase().trim();
let category = FULLMETAS.find(w => w.name === categoryName);
if (~categoryName.indexOf('-')) {
categoryName = categoryName.split('-')[0];
category = FULLMETAS.find(w => w.name === categoryName);
this._isPages = !!category;
} else {
this._isPages = false;
}
return category;
}
private getPageName(url: string): string {
return url.split('?')[0].split('/')[2].toLowerCase().trim();
}
/** `true` 表示需要跳转404 */
set(url: string): boolean {
const category = this.getCatgory(url);
if (!category) return false;
const name = this.getPageName(url);
const data = category.list!.find((w: { name: string }) => w.name === name) || null;
if (!data) return true;
this._data = {
...data.meta![this.i18n.defaultLang],
...data.meta![this.i18n.lang],
i18n: data.i18n,
name: data.name,
module_name: category.module || '',
github: category.github,
list: category.list,
};
// fix title
if (typeof this._data.title === 'object') {
this._data.title = this._data.title[this.i18n.lang] || this._data.title[this.i18n.defaultLang];
}
this.refPage(url);
return false;
}
get item(): any {
return this._data || null;
}
get github(): string {
return this._data.github;
}
get data(): MetaList[] {
return this._data.list;
}
get isPages(): boolean {
return this._isPages;
}
get menus(): any {
return this._menus;
}
get type(): string {
return this._type;
}
clearMenu(): void {
this._menus = null;
}
private getType(url: string): string {
const category = this.getCatgory(url);
return category ? url.split('?')[0].split('/')[1].toLowerCase().split('-')[0] : '';
}
refMenu(url: string): void {
if (!this.menus) {
this.genMenus(url);
return;
}
const curType = this.getType(url);
if (curType && this._type !== curType) {
this.genMenus(url);
return;
}
}
genMenus(url: string): void {
const category = this.getCatgory(url);
if (!category) return;
// todo: support level 2
const group: any[] = category.types!.map((item: any, index: number) => {
return {
index,
title: item[this.i18n.lang] || item[this.i18n.defaultLang],
list: [],
};
});
category.list!.forEach((item: any) => {
const meta = item.meta[this.i18n.lang] || item.meta[this.i18n.defaultLang];
let typeIdx = category.types!.findIndex((w: { [key: string]: string }) => w['zh-CN'] === meta.type || w['en-US'] === meta.type);
if (typeIdx === -1) typeIdx = 0;
let groupItem = group.find(w => w.index === typeIdx);
if (!groupItem) {
groupItem = {
index: typeIdx,
title: category.types![typeIdx][this.i18n.lang] || category.types![typeIdx][this.i18n.defaultLang],
list: [],
};
group.push(groupItem);
}
const entry: any = {
url: (meta.url || item.route || `/${category.name}/${item.name}`) + `/${this.i18n.zone}`,
title: this.i18n.get(meta.title),
subtitle: meta.subtitle,
order: item.order,
hot: typeof meta.hot === 'boolean' ? meta.hot : false,
lib: typeof item.lib === 'boolean' ? item.lib : false,
};
groupItem.list.push(entry);
});
this._platMenus = [];
this._menus = group
.filter((item: any) => Array.isArray(item.list) && item.list.length > 0)
.map((item: any) => {
if (item.list[0].order === -1) {
item.list.sort((a: any, b: any) => a.title.toLowerCase().localeCompare(b.title.toLowerCase()));
} else {
item.list.sort((a: any, b: any) => a.order - b.order);
}
this._platMenus = this._platMenus.concat(item.list);
return item;
})
.filter((item: any) => item.list.length);
}
getPathByUrl(url: string): any {
url = url.split('=')[0].split('?')[0];
let ret: any;
(this._menus || []).forEach((cat: any) => {
if (ret) return;
ret = cat.list.find((i: any) => i.url === url);
});
return ret;
}
private refPage(url: string): void {
this.next = null;
this.prev = null;
if (!this._menus) this.genMenus(url);
const idx = this._platMenus.findIndex(w => w.url === url);
if (idx === -1) return;
if (idx > 0) this.prev = this._platMenus[idx - 1];
if (idx + 1 <= this._platMenus.length) this.next = this._platMenus[idx + 1];
}
search(q: string, childrenMax: number = 5): MetaSearchGroup[] {
const zone = this.i18n.zone;
const res: MetaSearchGroup[] = [];
for (const g of FULLMETAS) {
const type = g.name!.toLowerCase();
const children: MetaSearchGroupItem[] = g
.list!.filter(w => w._t.includes(q))
.map(item => {
return {
title: item._t,
name: item.name,
url: (item.route || `/${type}/${item.name}`) + `/${zone}`,
};
});
if (children != null && children.length) {
res.push({
title: g.name,
type,
children: children.slice(0, childrenMax),
});
}
}
return res;
}
}