فهرست منبع

feat: asset add/rename/remove + dump action for git and disk modules

NGPixel 5 سال پیش
والد
کامیت
d987058336

+ 4 - 4
client/components/common/nav-header.vue

@@ -91,7 +91,7 @@
           //- LANGUAGES
 
           template(v-if='mode === `view` && locales.length > 0')
-            v-menu(offset-y, bottom, nudge-bottom='30', transition='slide-y-transition')
+            v-menu(offset-y, bottom, transition='slide-y-transition')
               template(v-slot:activator='{ on: menu }')
                 v-tooltip(bottom)
                   template(v-slot:activator='{ on: tooltip }')
@@ -101,14 +101,14 @@
               v-list(nav)
                 template(v-for='(lc, idx) of locales')
                   v-list-item(@click='changeLocale(lc)')
-                    v-list-item-action: v-chip(:color='lc.code === locale ? `blue` : `grey`', small, label, dark) {{lc.code.toUpperCase()}}
+                    v-list-item-action(style='min-width:auto;'): v-chip(:color='lc.code === locale ? `blue` : `grey`', small, label, dark) {{lc.code.toUpperCase()}}
                     v-list-item-title {{lc.name}}
             v-divider(vertical)
 
           //- PAGE ACTIONS
 
           template(v-if='isAuthenticated && path && mode !== `edit`')
-            v-menu(offset-y, bottom, nudge-bottom='30', transition='slide-y-transition')
+            v-menu(offset-y, bottom, transition='slide-y-transition')
               template(v-slot:activator='{ on: menu }')
                 v-tooltip(bottom)
                   template(v-slot:activator='{ on: tooltip }')
@@ -152,7 +152,7 @@
 
           //- ACCOUNT
 
-          v-menu(v-if='isAuthenticated', offset-y, bottom, nudge-bottom='30', min-width='300', transition='slide-y-transition')
+          v-menu(v-if='isAuthenticated', offset-y, bottom, min-width='300', transition='slide-y-transition')
             template(v-slot:activator='{ on: menu }')
               v-tooltip(bottom)
                 template(v-slot:activator='{ on: tooltip }')

+ 1 - 1
server/controllers/upload.js

@@ -90,7 +90,7 @@ router.post('/u', multer({
     ...fileMeta,
     folderId: folderId,
     assetPath,
-    userId: req.user.id
+    user: req.user
   })
   res.send('ok')
 })

+ 13 - 4
server/graph/resolvers/asset.js

@@ -123,8 +123,11 @@ module.exports = {
             event: 'renamed',
             asset: {
               ...asset,
-              sourcePath: assetSourcePath,
-              destinationPath: assetTargetPath
+              path: assetSourcePath,
+              destinationPath: assetTargetPath,
+              moveAuthorId: context.req.user.id,
+              moveAuthorName: context.req.user.name,
+              moveAuthorEmail: context.req.user.email
             }
           })
 
@@ -146,7 +149,7 @@ module.exports = {
         const asset = await WIKI.models.assets.query().findById(args.id)
         if (asset) {
           // Check permissions
-          const assetPath = asset.getAssetPath()
+          const assetPath = await asset.getAssetPath()
           if (!WIKI.auth.checkAccess(context.req.user, ['manage:assets'], { path: assetPath })) {
             throw new WIKI.Error.AssetDeleteForbidden()
           }
@@ -158,7 +161,13 @@ module.exports = {
           // Delete from Storage
           await WIKI.models.storage.assetEvent({
             event: 'deleted',
-            asset
+            asset: {
+              ...asset,
+              path: assetPath,
+              authorId: context.req.user.id,
+              authorName: context.req.user.name,
+              authorEmail: context.req.user.email
+            }
           })
 
           return {

+ 19 - 1
server/models/assetFolders.js

@@ -39,7 +39,7 @@ module.exports = class AssetFolder extends Model {
    *
    * @param {Number} folderId Id of the folder
    */
-  static async getHierarchy(folderId) {
+  static async getHierarchy (folderId) {
     const hier = await WIKI.models.knex.withRecursive('ancestors', qb => {
       qb.select('id', 'name', 'slug', 'parentId').from('assetFolders').where('id', folderId).union(sqb => {
         sqb.select('a.id', 'a.name', 'a.slug', 'a.parentId').from('assetFolders AS a').join('ancestors', 'ancestors.parentId', 'a.id')
@@ -48,4 +48,22 @@ module.exports = class AssetFolder extends Model {
     // The ancestors are from children to grandparents, must reverse for correct path order.
     return _.reverse(hier)
   }
+
+  /**
+   * Get full folder paths
+   */
+  static async getAllPaths () {
+    const all = await WIKI.models.assetFolders.query()
+    let folders = {}
+    all.forEach(fld => {
+      _.set(folders, fld.id, fld.slug)
+      let parentId = fld.parentId
+      while (parentId !== null || parentId > 0) {
+        const parent = _.find(all, ['id', parentId])
+        _.set(folders, fld.id, `${parent.slug}/${_.get(folders, fld.id)}`)
+        parentId = parent.parentId
+      }
+    })
+    return folders
+  }
 }

+ 19 - 12
server/models/assets.js

@@ -96,7 +96,7 @@ module.exports = class Asset extends Model {
       mime: opts.mimetype,
       fileSize: opts.size,
       folderId: opts.folderId,
-      authorId: opts.userId
+      authorId: opts.user.id
     }
 
     // Save asset data
@@ -119,20 +119,27 @@ module.exports = class Asset extends Model {
           data: fileBuffer
         })
       }
+
+      // Move temp upload to cache
+      await fs.move(opts.path, path.join(process.cwd(), `data/cache/${fileHash}.dat`), { overwrite: true })
+
+      // Add to Storage
+      if (!opts.skipStorage) {
+        await WIKI.models.storage.assetEvent({
+          event: 'uploaded',
+          asset: {
+            ...asset,
+            path: await asset.getAssetPath(),
+            data: fileBuffer,
+            authorId: opts.user.id,
+            authorName: opts.user.name,
+            authorEmail: opts.user.email
+          }
+        })
+      }
     } catch (err) {
       WIKI.logger.warn(err)
     }
-
-    // Move temp upload to cache
-    await fs.move(opts.path, path.join(process.cwd(), `data/cache/${fileHash}.dat`), { overwrite: true })
-
-    // Add to Storage
-    if (!opts.skipStorage) {
-      await WIKI.models.storage.assetEvent({
-        event: 'uploaded',
-        asset
-      })
-    }
   }
 
   static async getAsset(assetPath, res) {

+ 47 - 1
server/modules/storage/disk/storage.js

@@ -88,12 +88,41 @@ module.exports = {
 
     await fs.move(path.join(this.config.path, sourceFilePath), path.join(this.config.path, destinationFilePath), { overwrite: true })
   },
+  /**
+   * ASSET UPLOAD
+   *
+   * @param {Object} asset Asset to upload
+   */
+  async assetUploaded (asset) {
+    WIKI.logger.info(`(STORAGE/DISK) Creating new file ${asset.path}...`)
+    await fs.outputFile(path.join(this.config.path, asset.path), asset.data)
+  },
+  /**
+   * ASSET DELETE
+   *
+   * @param {Object} asset Asset to delete
+   */
+  async assetDeleted (asset) {
+    WIKI.logger.info(`(STORAGE/DISK) Deleting file ${asset.path}...`)
+    await fs.remove(path.join(this.config.path, asset.path))
+  },
+  /**
+   * ASSET RENAME
+   *
+   * @param {Object} asset Asset to rename
+   */
+  async assetRenamed (asset) {
+    WIKI.logger.info(`(STORAGE/DISK) Renaming file from ${asset.path} to ${asset.destinationPath}...`)
+    await fs.move(path.join(this.config.path, asset.path), path.join(this.config.path, asset.destinationPath), { overwrite: true })
+  },
 
   /**
    * HANDLERS
    */
   async dump() {
     WIKI.logger.info(`(STORAGE/DISK) Dumping all content to disk...`)
+
+    // -> Pages
     await pipeline(
       WIKI.models.knex.column('path', 'localeCode', 'title', 'description', 'contentType', 'content', 'isPublished', 'updatedAt').select().from('pages').where({
         isPrivate: false
@@ -105,13 +134,30 @@ module.exports = {
           if (WIKI.config.lang.code !== page.localeCode) {
             fileName = `${page.localeCode}/${fileName}`
           }
-          WIKI.logger.info(`(STORAGE/DISK) Dumping ${fileName}...`)
+          WIKI.logger.info(`(STORAGE/DISK) Dumping page ${fileName}...`)
           const filePath = path.join(this.config.path, fileName)
           await fs.outputFile(filePath, pageHelper.injectPageMetadata(page), 'utf8')
           cb()
         }
       })
     )
+
+    // -> Assets
+    const assetFolders = await WIKI.models.assetFolders.getAllPaths()
+
+    await pipeline(
+      WIKI.models.knex.column('filename', 'folderId', 'data').select().from('assets').join('assetData', 'assets.id', '=', 'assetData.id').stream(),
+      new stream.Transform({
+        objectMode: true,
+        transform: async (asset, enc, cb) => {
+          const filename = (asset.folderId && asset.folderId > 0) ? `${_.get(assetFolders, asset.folderId)}/${asset.filename}` : asset.filename
+          WIKI.logger.info(`(STORAGE/DISK) Dumping asset ${filename}...`)
+          await fs.outputFile(path.join(this.config.path, filename), asset.data)
+          cb()
+        }
+      })
+    )
+
     WIKI.logger.info('(STORAGE/DISK) All content was dumped to disk successfully.')
   },
   async backup() {

+ 25 - 7
server/modules/storage/git/storage.js

@@ -283,7 +283,7 @@ module.exports = {
     }
 
     await this.git.mv(`./${sourceFilePath}`, `./${destinationFilePath}`)
-    await this.git.commit(`docs: rename ${page.path} to ${page.destinationPath}`, destinationFilePath, {
+    await this.git.commit(`docs: rename ${page.path} to ${page.destinationPath}`, [sourceFilePath, destinationFilePath], {
       '--author': `"${page.moveAuthorName} <${page.moveAuthorEmail}>"`
     })
   },
@@ -295,7 +295,7 @@ module.exports = {
   async assetUploaded (asset) {
     WIKI.logger.info(`(STORAGE/GIT) Committing new file ${asset.path}...`)
     const filePath = path.join(this.repoPath, asset.path)
-    await fs.outputFile(filePath, asset, 'utf8')
+    await fs.outputFile(filePath, asset.data, 'utf8')
 
     await this.git.add(`./${asset.path}`)
     await this.git.commit(`docs: upload ${asset.path}`, asset.path, {
@@ -321,11 +321,11 @@ module.exports = {
    * @param {Object} asset Asset to upload
    */
   async assetRenamed (asset) {
-    WIKI.logger.info(`(STORAGE/GIT) Committing file move from ${asset.sourcePath} to ${asset.destinationPath}...`)
+    WIKI.logger.info(`(STORAGE/GIT) Committing file move from ${asset.path} to ${asset.destinationPath}...`)
 
-    await this.git.mv(`./${asset.sourcePath}`, `./${asset.destinationPath}`)
-    await this.git.commit(`docs: rename ${asset.sourcePath} to ${asset.destinationPath}`, asset.destinationPath, {
-      '--author': `"${asset.authorName} <${asset.authorEmail}>"`
+    await this.git.mv(`./${asset.path}`, `./${asset.destinationPath}`)
+    await this.git.commit(`docs: rename ${asset.path} to ${asset.destinationPath}`, [asset.path, asset.destinationPath], {
+      '--author': `"${asset.moveAuthorName} <${asset.moveAuthorEmail}>"`
     })
   },
   /**
@@ -364,6 +364,7 @@ module.exports = {
   async syncUntracked() {
     WIKI.logger.info(`(STORAGE/GIT) Adding all untracked content...`)
 
+    // -> Pages
     await pipeline(
       WIKI.models.knex.column('path', 'localeCode', 'title', 'description', 'contentType', 'content', 'isPublished', 'updatedAt').select().from('pages').where({
         isPrivate: false
@@ -375,7 +376,7 @@ module.exports = {
           if (WIKI.config.lang.namespacing && WIKI.config.lang.code !== page.localeCode) {
             fileName = `${page.localeCode}/${fileName}`
           }
-          WIKI.logger.info(`(STORAGE/GIT) Adding ${fileName}...`)
+          WIKI.logger.info(`(STORAGE/GIT) Adding page ${fileName}...`)
           const filePath = path.join(this.repoPath, fileName)
           await fs.outputFile(filePath, pageHelper.injectPageMetadata(page), 'utf8')
           await this.git.add(`./${fileName}`)
@@ -383,6 +384,23 @@ module.exports = {
         }
       })
     )
+
+    // -> Assets
+    const assetFolders = await WIKI.models.assetFolders.getAllPaths()
+
+    await pipeline(
+      WIKI.models.knex.column('filename', 'folderId', 'data').select().from('assets').join('assetData', 'assets.id', '=', 'assetData.id').stream(),
+      new stream.Transform({
+        objectMode: true,
+        transform: async (asset, enc, cb) => {
+          const filename = (asset.folderId && asset.folderId > 0) ? `${_.get(assetFolders, asset.folderId)}/${asset.filename}` : asset.filename
+          WIKI.logger.info(`(STORAGE/GIT) Adding asset ${filename}...`)
+          await fs.outputFile(path.join(this.repoPath, filename), asset.data)
+          await this.git.add(`./${filename}`)
+          cb()
+        }
+      })
+    )
     await this.git.commit(`docs: add all untracked content`)
     WIKI.logger.info('(STORAGE/GIT) All content is now tracked.')
   }