-
Notifications
You must be signed in to change notification settings - Fork 89
Expand file tree
/
Copy pathpagesFlatArray.ts
More file actions
186 lines (154 loc) · 4.51 KB
/
Copy pathpagesFlatArray.ts
File metadata and controls
186 lines (154 loc) · 4.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
import Page from './page.js';
import PageOrder from './pageOrder.js';
import NodeCache from 'node-cache';
import { EntityId } from '../database/types.js';
import { isEqualIds } from '../database/index.js';
// Create cache for flat array
const cache = new NodeCache({ stdTTL: 120 });
const cacheKey = 'pagesFlatArray';
/**
* Element for pagesFlatArray
*/
export interface PagesFlatArrayData {
/**
* Page id
*/
id: EntityId;
/**
* Page parent id
*/
parentId?: EntityId;
/**
* id of parent with parent id '0'
*/
rootId: string;
/**
* Page level in sidebar view
*/
level: number;
/**
* Page title
*/
title: string;
/**
* Page uri
*/
uri?: string;
}
/**
* @class PagesFlatArray model - flat array of pages, which are ordered like in sidebar
*/
class PagesFlatArray {
/**
* Returns pages flat array
*
* @param nestingLimit - max `level` to keep (level 0 = root pages, 1 = their children, …).
* Pass **null** to return the full tree order (needed for prev/next links past depth 2).
* @returns {Promise<Array<PagesFlatArrayData>>}
*/
public static async get(nestingLimit: number | null = 2): Promise<Array<PagesFlatArrayData>> {
// Get flat array from cache
let arr = cache.get(cacheKey) as Array<PagesFlatArrayData>;
// Check is flat array consists in cache
if (!arr) {
arr = await this.regenerate();
}
if (!nestingLimit) {
return arr;
}
return arr.filter( (item) => item.level < nestingLimit );
}
/**
* Generates new flat array, saves it to cache, returns it
* Calls, when there is no pages flat array data in cache or when page or pageOrder data updates
*
* @returns {Promise<Array<PagesFlatArrayData>>}
*/
public static async regenerate(): Promise<Array<PagesFlatArrayData>> {
const pages = await Page.getAll();
const pagesOrders = await PageOrder.getAll();
let arr = new Array<PagesFlatArrayData>();
// Get root order
const rootOrder = pagesOrders.find( order => order.page == '0' );
// Check is root order is not empty
if (!rootOrder) {
return [];
}
for (const pageId of rootOrder.order) {
arr = arr.concat(this.getChildrenFlatArray(pageId, 0, pages,
pagesOrders));
}
// Save generated flat array to cache
cache.set(cacheKey, arr);
return arr;
}
/**
* Returns previous page
*
* @param pageId - page id
* @returns {Promise<PagesFlatArrayData | undefined>}
*/
public static async getPageBefore(pageId: EntityId): Promise<PagesFlatArrayData | undefined> {
/** `null` = no level cap; default (2) would drop pages at level ≥2 from the chain */
const arr = await this.get(null);
const pageIndex = arr.findIndex((item) => isEqualIds(item.id, pageId));
// Check if index is not the first
if (pageIndex && pageIndex > 0) {
// Return previous element from array
return arr[pageIndex - 1];
} else {
return;
}
}
/**
* Returns next page
*
* @param pageId - page id
* @returns {Promise<PagesFlatArrayData | undefined>}
*/
public static async getPageAfter(pageId: EntityId): Promise<PagesFlatArrayData | undefined> {
const arr = await this.get(null);
const pageIndex = arr.findIndex( (item) => isEqualIds(item.id, pageId));
// Check if index is not the last
if (pageIndex < arr.length -1) {
// Return next element from array
return arr[pageIndex + 1];
} else {
return;
}
}
/**
* Returns child pages array
*
* @param pageId - parent page id
* @param level - page level in sidebar
* @param pages - all pages
* @param orders - all page orders
* @returns {Promise<Array<PagesFlatArrayData>>}
*/
private static getChildrenFlatArray(pageId: EntityId, level: number,
pages: Array<Page>, orders: Array<PageOrder>): Array<PagesFlatArrayData> {
let arr: Array<PagesFlatArrayData> = new Array<PagesFlatArrayData>();
const page = pages.find(item => isEqualIds(item._id, pageId));
// Add element to child array
if (page) {
arr.push( {
id: page._id!,
level: level,
parentId: page._parent,
rootId: '0',
title: page.title!,
uri: page.uri,
} );
}
const order = orders.find(item => isEqualIds(item.page, pageId));
if (order) {
for (const childPageId of order.order) {
arr = arr.concat(this.getChildrenFlatArray(childPageId, level + 1,
pages, orders));
}
}
return arr;
}
}
export default PagesFlatArray;