소스 검색

Refs #7 mass add/remove tags

isundil 1 년 전
부모
커밋
fea4cd1476
4개의 변경된 파일89개의 추가작업 그리고 45개의 파일을 삭제
  1. 10 3
      model/mediaService.js
  2. 40 18
      router/api.js
  3. 38 23
      static/public/js/medias.js
  4. 1 1
      static/public/js/uiMediaFullpage.js

+ 10 - 3
model/mediaService.js

@@ -129,7 +129,7 @@ function reduceReqToMediaStruct(acc, i) {
     return acc;
 }
 
-module.exports.fetchOne = async function(app, md5sum, accessList) {
+module.exports.fetchMultiple = async function(app, md5sums, accessList) {
     let result = ((await app.databaseHelper.runSql(`
         select mediaFile.path, mediaFile.md5sum, mediaFile.date, mediaFile.fixedSum,
         mediaMeta.key as metaKey, mediaMeta.value as metaValue,
@@ -137,9 +137,16 @@ module.exports.fetchOne = async function(app, md5sum, accessList) {
         from mediaFile
         left join mediaMeta on mediaMeta.md5sum=mediaFile.fixedSum
         left join mediaTag on mediaTag.md5sum=mediaFile.fixedSum
-        where mediaFile.fixedSum=?`, md5sum)) || []).reduce(reduceReqToMediaStruct, {})[md5sum] || null;
+        where mediaFile.fixedSum in (` +md5sums.map(x => '?').join(',')+`)`, md5sums)) || []).reduce(reduceReqToMediaStruct, {}) || null;
     accessList = await buildAccessList(app, accessList);
-    return result?.HaveAccess(accessList) ? result : null;
+    for (let key in result)
+        if (!result[key].HaveAccess(accessList))
+            delete result[key];
+    return result;
+}
+
+module.exports.fetchOne = async function(app, md5sum, accessList) {
+    return (await module.exports.fetchMultiple(app, [md5sum], accessList))[md5sum] || null;
 }
 
 function fetchAccessSubQuery(args, access) {

+ 40 - 18
router/api.js

@@ -44,32 +44,54 @@ module.exports = { register: app => {
         const result = Security.removeFromSession(req, req.params.id);
         app.routerUtils.jsonResponse(res, result);
     });
-    app.router.del("/api/media/:id/tag/:tag", async (req, res) => {
+    app.router.post("/api/media/:id/tag/del/:tag", async (req, res) => {
         app.routerUtils.onApiRequest(req, res);
         if (!req.params.id ||!req.params.tag)
             return app.routerUtils.onBadRequest(res);
-        let data = await MediaService.fetchOne(app, req.params.id, req.sessionObj?.accessList);
-        if (!data || data.accessType !== ACCESS_GRANT.write)
-            return app.routerUtils.onPageNotFound(res);
-        await app.databaseHelper.remove(MediaFileTagModel, { md5sum: data.fixedSum, tag: decodeURIComponent(req.params.tag), fromMeta: 0 });
-        app.routerUtils.jsonResponse(res, MediaToJson(await MediaService.fetchOne(app, req.params.id, req.sessionObj?.accessList)));
+        let checksum = [ req.params.id ];
+        if (req.params.id === "list") {
+            if (!req.body?.['list[]'])
+                return app.routerUtils.onBadRequest(res);
+            checksum = req.body['list[]'];
+        }
+
+        let data = await MediaService.fetchMultiple(app, checksum, req.sessionObj?.accessList);
+        data = Object.keys(data).map(x => data[x]).filter(x => x.ACCESS_TYPE != ACCESS_GRANT.write);
+
+        await app.databaseHelper.remove(MediaFileTagModel, { md5sum: data.map(x => x.fixedSum), tag: decodeURIComponent(req.params.tag), fromMeta: 0 });
+        const allMedias = await MediaService.fetchMultiple(app, checksum, req.sessionObj?.accessList);
+        app.routerUtils.jsonResponse(res, Object.keys(allMedias).map(x => allMedias[x]).map(x => MediaToJson(x)));
     });
     app.router.put("/api/media/:id/tag", async (req, res) => {
         app.routerUtils.onApiRequest(req, res);
-        if (!req.params.id ||!req.body?.tag)
+        const requestedTag = req.body?.tag;
+        if (!req.params.id ||!requestedTag)
             return app.routerUtils.onBadRequest(res);
-        let data = await MediaService.fetchOne(app, req.params.id, req.sessionObj?.accessList);
-        if (!data || data.accessType !== ACCESS_GRANT.write)
-            return app.routerUtils.onPageNotFound(res);
-        const requestedTag = req.body.tag;
-        for (let existingTag of [...data.tags, ...data.fixedTags]) {
-            if (existingTag === requestedTag || existingTag.startsWith(`${requestedTag}/`)) {
-                return app.routerUtils.jsonResponse(res, data);
-            }
+
+        let checksum = [ req.params.id ];
+        if (req.params.id === "list") {
+            if (!req.body?.['list[]'])
+                return app.routerUtils.onBadRequest(res);
+            checksum = req.body['list[]'];
         }
-        let tag = new MediaFileTagModel(data.fixedSum, requestedTag, false);
-        await app.databaseHelper.insertOne(tag);
-        app.routerUtils.jsonResponse(res, MediaToJson(await MediaService.fetchOne(app, req.params.id, req.sessionObj?.accessList)));
+
+        let data = await MediaService.fetchMultiple(app, checksum, req.sessionObj?.accessList);
+        data = Object.keys(data)
+            .map(x => data[x])
+            .filter(x => {
+                if (x.ACCESS_TYPE != ACCESS_GRANT.write)
+                    return true;
+                for (let existingTag of [...x.tags, ...x.fixedTags]) {
+                    if (existingTag === requestedTag || existingTag.startsWith(`${requestedTag}/`)) {
+                        return true;
+                    }
+                }
+            });
+
+        let tag = data.map(x => new MediaFileTagModel(x.fixedSum, requestedTag, false));
+        await app.databaseHelper.insertMultipleSameTable(tag);
+        const allMedias = await MediaService.fetchMultiple(app, checksum, req.sessionObj?.accessList);
+        app.routerUtils.jsonResponse(res, Object.keys(allMedias).map(x => allMedias[x]).map(x => MediaToJson(x)));
     });
     app.router.patch("/api/media/:id/meta/:key", async (req, res) => {
         app.routerUtils.onApiRequest(req, res);

+ 38 - 23
static/public/js/medias.js

@@ -226,8 +226,8 @@ class MediaStorage extends EventTarget
                     url: `/api/media/${encodeURIComponent(md5sum)}/meta/${encodeURIComponent(key)}`,
                     type: "PATCH",
                     data: { value },
-                    success: (media) => {
-                        let meta = media.meta[key] || { type: 'string', value: value, canWrite: true };
+                    success: (queryResult) => {
+                        let meta = queryResult.meta[key] || { type: 'string', value: value, canWrite: true };
                         meta.value = value;
                         this.#pushMeta(key, meta);
                         media.meta[key] = meta;
@@ -241,21 +241,29 @@ class MediaStorage extends EventTarget
     }
 
     removeTag(md5sum, tagName) {
-        // FIXME md5sum may be array
+        let md5arr = undefined;
+        if (Array.isArray(md5sum)) {
+            md5arr = md5sum;
+            md5sum = "list";
+        }
         return LoadingTasks.push(() => {
             return new Promise(ok => {
-                let media = this.medias.find(x => x.fixedSum === md5sum);
-                if (!media || !media.writeAccess)
+                let mediaCount = (md5arr || [ md5sum ]).map(checksum => this.medias.find(x => x.fixedSum === checksum)).filter(x => x.writeAccess).length;
+                if (mediaCount != (md5arr || [ md5sum ]).length)
                     return ok(false);
                 $.ajax({
-                    url: `/api/media/${encodeURIComponent(md5sum)}/tag/${encodeURIComponent(tagName)}`,
-                    type: "DELETE",
-                    success: data => {
-                        media.setTags(data.fixedTags, data.tags);
-                        for (let i of data.tags)
-                            this.#pushTag(i, true);
-                        for (let i of data.fixedTags)
-                            this.#pushTag(i, true);
+                    url: `/api/media/${encodeURIComponent(md5sum)}/tag/del/${encodeURIComponent(tagName)}`,
+                    type: "POST",
+                    data: { list: md5arr || [0] },
+                    success: allData => {
+                        allData.forEach(data => {
+                            let media = this.medias.find(x => x.fixedSum === data.fixedSum);
+                            media.setTags(data.fixedTags, data.tags);
+                            for (let i of data.tags)
+                                this.#pushTag(i, true);
+                            for (let i of data.fixedTags)
+                                this.#pushTag(i, true);
+                        });
                         ok(true);
                     },
                     error: err => ok(false),
@@ -265,22 +273,29 @@ class MediaStorage extends EventTarget
     }
 
     addTag(md5sum, tagName) {
-        // FIXME md5sum may be array
+        let md5arr = undefined;
+        if (Array.isArray(md5sum)) {
+            md5arr = md5sum;
+            md5sum = "list";
+        }
         return LoadingTasks.push(() => {
             return new Promise(ok => {
-                let media = this.medias.find(x => x.fixedSum === md5sum);
-                if (!media || !media.writeAccess)
+                let mediaCount = (md5arr || [ md5sum ]).map(checksum => this.medias.find(x => x.fixedSum === checksum)).filter(x => x.writeAccess).length;
+                if (mediaCount != (md5arr || [ md5sum ]).length)
                     return ok(false);
                 $.ajax({
                     url: `/api/media/${encodeURIComponent(md5sum)}/tag`,
                     type: "PUT",
-                    data: { tag: tagName },
-                    success: data => {
-                        media.setTags(data.fixedTags, data.tags);
-                        for (let i of data.tags)
-                            this.#pushTag(i, true);
-                        for (let i of data.fixedTags)
-                            this.#pushTag(i, true);
+                    data: { tag: tagName, list: md5arr },
+                    success: allData => {
+                        allData.forEach(data => {
+                            let media = this.medias.find(x => x.fixedSum === data.fixedSum);
+                            media.setTags(data.fixedTags, data.tags);
+                            for (let i of data.tags)
+                                this.#pushTag(i, true);
+                            for (let i of data.fixedTags)
+                                this.#pushTag(i, true);
+                        });
                         ok(true);
                     },
                     error: err => ok(false),

+ 1 - 1
static/public/js/uiMediaFullpage.js

@@ -159,7 +159,7 @@ $(() => {
                 btItem.href = '#';
                 btItem.addEventListener('click', async e => {
                     e.preventDefault();
-                    await MediaStorage.Instance.removeTag(fullPageMediaDisplayed?.fixedSum || fullPageMediaDisplayed, i);
+                    await MediaStorage.Instance.removeTag(fullPageMediaDisplayed?.fixedSum || fullPageMediaList, i);
                     reloadCurrentMedia();
                 });
                 uiItem.appendChild(btItem);