Unverified Commit 0605f654 authored by NGPixel's avatar NGPixel

feat: file manager thumbnail preview

parent 5c1b9b66
...@@ -10,8 +10,7 @@ ...@@ -10,8 +10,7 @@
"dev": "nodemon server", "dev": "nodemon server",
"legacy:dev": "NODE_OPTIONS=--openssl-legacy-provider node dev", "legacy:dev": "NODE_OPTIONS=--openssl-legacy-provider node dev",
"legacy:build": "NODE_OPTIONS=--openssl-legacy-provider webpack --profile --config dev/webpack/webpack.prod.js", "legacy:build": "NODE_OPTIONS=--openssl-legacy-provider webpack --profile --config dev/webpack/webpack.prod.js",
"test": "eslint --format codeframe --ext .js,.vue . && pug-lint server/views && jest", "test": "eslint --format codeframe --ext .js,.vue . && pug-lint server/views && jest"
"cypress:open": "cypress open"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
......
...@@ -5,8 +5,6 @@ const _ = require('lodash') ...@@ -5,8 +5,6 @@ const _ = require('lodash')
const CleanCSS = require('clean-css') const CleanCSS = require('clean-css')
const moment = require('moment') const moment = require('moment')
const path = require('path') const path = require('path')
const tmplCreateRegex = /^[0-9]+(,[0-9]+)?$/
const siteAssetsPath = path.resolve(WIKI.ROOTPATH, WIKI.config.dataPath, 'assets') const siteAssetsPath = path.resolve(WIKI.ROOTPATH, WIKI.config.dataPath, 'assets')
/** /**
...@@ -78,30 +76,35 @@ router.get('/_site/:siteId?/:resource', async (req, res, next) => { ...@@ -78,30 +76,35 @@ router.get('/_site/:siteId?/:resource', async (req, res, next) => {
/** /**
* Asset Thumbnails / Download * Asset Thumbnails / Download
*/ */
router.get('/_asset/:siteId/:mode/*', async (req, res, next) => { router.get('/_thumb/:id.png', async (req, res, next) => {
const site = req.params.siteId ? WIKI.sites[req.params.siteId] : await WIKI.db.sites.getSiteByHostname({ hostname: req.hostname }) const thumb = await WIKI.db.assets.getThumbnail({
if (!site) { id: req.params.id
return res.status(404).send('Site Not Found') })
}
const filePath = req.params[0]
console.info(filePath)
switch (req.params.mode) {
case 'thumb': {
try {
} catch (err) { if (thumb) {
// TODO: Check permissions
switch (thumb.previewState) {
case 'pending': {
res.send('PENDING')
break
}
case 'ready': {
res.set('Content-Type', 'image/png')
res.send(thumb.preview)
break
}
case 'failed': {
res.status(500).send('Thumbnail Preview Failed').end()
break
}
default: {
return res.status(500).send('Invalid Thumbnail Preview State')
} }
break
}
case 'download': {
break
}
default: {
return res.status(404).send('Invalid Site Resource')
} }
} else {
return res.sendStatus(404)
} }
return res.send('BOB').end()
}) })
/** /**
......
...@@ -10,6 +10,9 @@ module.exports = { ...@@ -10,6 +10,9 @@ module.exports = {
minimumNodeRequired: '18.0.0' minimumNodeRequired: '18.0.0'
}, },
init () { init () {
fs.ensureDir(path.resolve(WIKI.ROOTPATH, WIKI.config.dataPath, 'assets'))
fs.ensureDir(path.resolve(WIKI.ROOTPATH, WIKI.config.dataPath, 'uploads'))
// Clear content cache // Clear content cache
fs.emptyDir(path.resolve(WIKI.ROOTPATH, WIKI.config.dataPath, 'cache')) fs.emptyDir(path.resolve(WIKI.ROOTPATH, WIKI.config.dataPath, 'cache'))
......
...@@ -258,7 +258,7 @@ module.exports = { ...@@ -258,7 +258,7 @@ module.exports = {
const asset = assetRaw[0] const asset = assetRaw[0]
// Add to tree // Add to tree
const treeAsset = await WIKI.db.tree.addAsset({ await WIKI.db.tree.addAsset({
id: asset.id, id: asset.id,
parentPath: folder.folderPath ? `${folder.folderPath}.${folder.fileName}` : folder.fileName, parentPath: folder.folderPath ? `${folder.folderPath}.${folder.fileName}` : folder.fileName,
fileName: formattedFilename, fileName: formattedFilename,
...@@ -309,13 +309,7 @@ module.exports = { ...@@ -309,13 +309,7 @@ module.exports = {
WIKI.logger.warn('Cannot generate asset thumbnail because the Sharp extension is not installed.') WIKI.logger.warn('Cannot generate asset thumbnail because the Sharp extension is not installed.')
} else { } else {
WIKI.logger.debug(`Generating thumbnail of asset ${sanitizedFilename}...`) WIKI.logger.debug(`Generating thumbnail of asset ${sanitizedFilename}...`)
const previewDestFolder = path.resolve( const previewDestPath = path.resolve(WIKI.ROOTPATH, WIKI.config.dataPath, `uploads/${tempFileId}-thumb.png`)
WIKI.ROOTPATH,
WIKI.config.dataPath,
'assets'
)
const previewDestPath = path.join(previewDestFolder, `asset-thumb-${treeAsset.hash}.png`)
await fs.ensureDir(previewDestFolder)
// -> Resize // -> Resize
await WIKI.extensions.ext.sharp.resize({ await WIKI.extensions.ext.sharp.resize({
format: 'png', format: 'png',
...@@ -332,6 +326,9 @@ module.exports = { ...@@ -332,6 +326,9 @@ module.exports = {
preview: await fs.readFile(previewDestPath), preview: await fs.readFile(previewDestPath),
previewState: 'ready' previewState: 'ready'
}) })
// -> Delete
await fs.remove(previewDestPath)
} }
} }
......
...@@ -3,6 +3,7 @@ const moment = require('moment') ...@@ -3,6 +3,7 @@ const moment = require('moment')
const path = require('path') const path = require('path')
const fs = require('fs-extra') const fs = require('fs-extra')
const _ = require('lodash') const _ = require('lodash')
const commonHelper = require('../helpers/common')
/** /**
* Users model * Users model
...@@ -160,7 +161,19 @@ module.exports = class Asset extends Model { ...@@ -160,7 +161,19 @@ module.exports = class Asset extends Model {
} }
} }
static async getAsset(assetPath, res) { static async getThumbnail ({ id, path, locale, siteId }) {
return WIKI.db.tree.query()
.select('tree.*', 'assets.preview', 'assets.previewState')
.innerJoin('assets', 'tree.id', 'assets.id')
.where(id ? { 'tree.id': id } : {
'tree.hash': commonHelper.generateHash(path),
'tree.localeCode': locale,
'tree.siteId': siteId
})
.first()
}
static async getAsset({ path, locale, siteId }, res) {
try { try {
const fileInfo = '' // assetHelper.getPathInfo(assetPath) const fileInfo = '' // assetHelper.getPathInfo(assetPath)
const fileHash = '' // assetHelper.generateHash(assetPath) const fileHash = '' // assetHelper.generateHash(assetPath)
......
...@@ -51,7 +51,8 @@ module.exports = { ...@@ -51,7 +51,8 @@ module.exports = {
width = null, width = null,
height = null, height = null,
fit = 'cover', fit = 'cover',
background = { r: 0, g: 0, b: 0, alpha: 0 } background = { r: 0, g: 0, b: 0, alpha: 0 },
kernel = 'lanczos3'
}) { }) {
this.load() this.load()
...@@ -75,7 +76,8 @@ module.exports = { ...@@ -75,7 +76,8 @@ module.exports = {
width, width,
height, height,
fit, fit,
background background,
kernel
}).toFormat(format) }).toFormat(format)
return pipeline([inputStream, transformer, outputStream]) return pipeline([inputStream, transformer, outputStream])
......
...@@ -44,7 +44,7 @@ html(lang=siteConfig.lang) ...@@ -44,7 +44,7 @@ html(lang=siteConfig.lang)
link( link(
type='text/css' type='text/css'
rel='stylesheet' rel='stylesheet'
href='/_assets-legacy/css/app.36b4c9522aa279325701.css' href='/_assets-legacy/css/app.c05740c020721e44657c.css'
) )
...@@ -54,14 +54,14 @@ html(lang=siteConfig.lang) ...@@ -54,14 +54,14 @@ html(lang=siteConfig.lang)
script( script(
type='text/javascript' type='text/javascript'
src='/_assets-legacy/js/runtime.js?1671237890' src='/_assets-legacy/js/runtime.js?1674373130'
) )
script( script(
type='text/javascript' type='text/javascript'
src='/_assets-legacy/js/app.js?1671237890' src='/_assets-legacy/js/app.js?1674373130'
) )
......
...@@ -102,11 +102,12 @@ module.exports = configure(function (/* ctx */) { ...@@ -102,11 +102,12 @@ module.exports = configure(function (/* ctx */) {
devServer: { devServer: {
// https: true // https: true
open: false, // opens browser window automatically open: false, // opens browser window automatically
port: 5001, port: 3001,
proxy: { proxy: {
'/_graphql': 'http://localhost:5000/_graphql', '/_graphql': 'http://127.0.0.1:3000/_graphql',
'/_site': 'http://localhost:5000', '/_site': 'http://127.0.0.1:3000',
'/_user': 'http://localhost:5000' '/_thumb': 'http://127.0.0.1:3000',
'/_user': 'http://127.0.0.1:3000'
} }
}, },
......
...@@ -68,7 +68,7 @@ q-layout.fileman(view='hHh lpR lFr', container) ...@@ -68,7 +68,7 @@ q-layout.fileman(view='hHh lpR lFr', container)
.q-pa-md .q-pa-md
template(v-if='currentFileDetails') template(v-if='currentFileDetails')
q-img.rounded-borders.q-mb-md( q-img.rounded-borders.q-mb-md(
src='/_assets/illustrations/fileman-page.svg' :src='currentFileDetails.thumbnail'
width='100%' width='100%'
fit='cover' fit='cover'
:ratio='16/10' :ratio='16/10'
...@@ -450,8 +450,10 @@ const currentFileDetails = computed(() => { ...@@ -450,8 +450,10 @@ const currentFileDetails = computed(() => {
value: item.title value: item.title
} }
] ]
let thumbnail = ''
switch (item.type) { switch (item.type) {
case 'page': { case 'page': {
thumbnail = '/_assets/illustrations/fileman-page.svg'
items.push({ items.push({
label: t('fileman.detailsPageType'), label: t('fileman.detailsPageType'),
value: t(`fileman.${item.pageType}PageType`) value: t(`fileman.${item.pageType}PageType`)
...@@ -471,6 +473,7 @@ const currentFileDetails = computed(() => { ...@@ -471,6 +473,7 @@ const currentFileDetails = computed(() => {
break break
} }
case 'asset': { case 'asset': {
thumbnail = `/_thumb/${item.id}.png`
items.push({ items.push({
label: t('fileman.detailsAssetType'), label: t('fileman.detailsAssetType'),
value: fileTypes[item.fileExt] ? t(`fileman.${item.fileExt}FileType`) : t('fileman.unknownFileType', { type: item.fileExt.toUpperCase() }) value: fileTypes[item.fileExt] ? t(`fileman.${item.fileExt}FileType`) : t('fileman.unknownFileType', { type: item.fileExt.toUpperCase() })
...@@ -483,7 +486,7 @@ const currentFileDetails = computed(() => { ...@@ -483,7 +486,7 @@ const currentFileDetails = computed(() => {
} }
} }
return { return {
thumbnail: '', thumbnail,
items items
} }
} else { } else {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment