You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

145 lines
6.0 KiB

const Controller = require('libflitter/controller/Controller')
const os = require('os');
const fs = require('fs').promises;
const uuid = require('uuid/v4');
const path = require('path');
/*
* Export Controller
* -------------------------------------------------------------
* Put some description here!
*/
class Export extends Controller {
static get services() {
return [...super.services, 'models', 'app']
}
/*
* Serve the main page.
*/
async json_export(req, res) {
const Page = this.models.get('api:Page')
const Node = this.models.get('api:Node')
const user = req.user
const pages = await Page.find({ OrgUserId: user._id })
const ExportData = {}
for (const page of pages) {
const nodes = await Node.find({ PageId: page.UUID })
const PageData = { ...page }
PageData.Nodes = nodes.map(node => { return { ...node } })
ExportData[page.Name] = PageData
}
return res.api(ExportData)
}
async markdown_export(req, res) {
const Page = this.models.get('api:Page')
const Node = this.models.get('api:Node')
const user = req.user
const page0 = await user.get_root_page() //topmost page
const temp_dir = path.resolve(os.tmpdir(), uuid())
await fs.mkdir(temp_dir)
await this._markdown_recurse(page0, temp_dir)
/* Archive directory */
const exec = require('child_process').exec;
console.log('zip -9jpr ' + path.resolve(temp_dir, '../archive.zip') + ' ' + path.resolve(temp_dir) + '/')
exec('cd ' + path.resolve(temp_dir) + '; zip -r archive.zip *', (error) => {
if (error) {
console.error(`exec error: ${error}`);
return res.error(500);
return;
}
return res.sendFile(`${path.resolve(temp_dir, 'archive.zip')}`)
})
}
async _markdown_recurse(root, temp_dir) { //recursive function for creating directory and generating markdown pages
const fs = require('fs').promises
const Page = this.models.get('api:Page')
const child = await Page.find({ UUID: { $in: root.ChildPageIds } })
for (const page of child) {
const markdown = await this._generate_markdown(page)
await fs.writeFile(path.resolve(temp_dir, page.Name.replace(/\s/g, '_')) + '.md', markdown)
if (page.ChildPageIds && page.ChildPageIds.length) {
const sub_temp_dir = path.resolve(temp_dir, page.Name.replace(/\s/g, '_'))
// console.log(sub_temp_dir)
await fs.mkdir(sub_temp_dir)
await this._markdown_recurse(page, sub_temp_dir)
}
}
}
async _generate_markdown(page) { //generate mark down
const Node = this.models.get('api:Node')
const nodes = await Node.find({ PageId: page.UUID })
return nodes.map(x => {
if (x.Type === 'click_link') {
return '[' + x.Value.Value + ']' + '(' + x.Value.Value + ')'
}
return x.Value.Value
}).join('\n')
}
async html_export(req, res) {
const Page = this.models.get('api:Page')
const Node = this.models.get('api:Node')
const user = req.user
const pages = await Page.find({ OrgUserId: user._id })
const mapping = {} //keeps track of html file UUID and file name
const page0 = await user.get_root_page() //topmost page
for (const page of pages) {
const html_name = page.Name.replace(/\s/g, '_') + '.html'
mapping[page.UUID] = html_name
}
console.log(page0)
const sidebar_html = await this._generate_sidebar(mapping, page0) //generates the sidebar contents
const temp_dir = path.resolve(os.tmpdir(), uuid()) //make temporary directory
await fs.mkdir(temp_dir)
/* Generates html files from template */
for (const page of pages) {
const fs = require('fs').promises
const contents = (await fs.readFile(path.resolve(this.app.directories.assets, 'export-template.html'))).toString('utf8')
console.log(page)
//console.log({contents})
const content_html = await this._generate_html(page)
//console.log({content_html, sidebar_html})
const page_html = contents.replace('%%SIDEBAR%%', sidebar_html).replace('%%CONTENTS%%', content_html)
await fs.writeFile(path.resolve(temp_dir, mapping[page.UUID]), page_html)
}
/* Archive directory */
const exec = require('child_process').exec;
exec('zip -r ' + path.resolve(temp_dir, 'archive.zip') + ' ' + path.resolve(temp_dir), (error) => {
if (error) {
console.error(`exec error: ${error}`);
return res.error(500);
return;
}
return res.sendFile(`${path.resolve(temp_dir, 'archive.zip')}`)
})
}
async _generate_sidebar(mapping, upper_node) { //generate sidebar from mapping array and upper_node
const Page = this.models.get('api:Page')
console.log(upper_node)
console.log(upper_node.ChildPageIds == 'undefined')
if (upper_node.ChildPageIds == 'undefined') {
return '<a class="nav-link" href="' + mapping[upper_node.UUID] + '">' + upper_node.Name + '</a>'
} else {
let base = '<nav class="nav nav-pills flex-column">'
for (const childrenId of upper_node.ChildPageIds) {
base += (await this._generate_sidebar(await Page.findOne({ UUID: childrenId })))
}
console.log({ base })
return base
}
}
async _generate_html(page) { //generate html page from page and node data
const Node = this.models.get('api:Node')
const nodes = await Node.find({ PageId: page.UUID })
return nodes.map(x => { return x.to_html() }).join('\n')
}
}
module.exports = exports = Export