Browse Source

Merge branch 'master' into minor

Michael Bromley 3 years ago
parent
commit
37a9402c54

+ 1 - 1
packages/admin-ui/src/lib/core/src/shared/components/asset-gallery/asset-gallery.component.html

@@ -11,7 +11,7 @@
                 [disabled]="true"
                 [hiddenWhenOff]="true"
             ></vdr-select-toggle>
-            <img [src]="asset | assetPreview: 'thumb'" />
+            <img class="asset-thumb" [src]="asset | assetPreview: 'thumb'" />
         </div>
         <div class="detail">
             <vdr-entity-info

+ 5 - 0
packages/admin-ui/src/lib/core/src/shared/components/asset-gallery/asset-gallery.component.scss

@@ -28,6 +28,11 @@
     position: relative;
 }
 
+
+img.asset-thumb {
+    aspect-ratio: 1;
+}
+
 vdr-select-toggle {
     position: absolute;
     ::ng-deep .toggle {

+ 1 - 1
packages/admin-ui/src/lib/static/styles/global/_overrides.scss

@@ -5,7 +5,7 @@
     background-color: var(--clr-global-app-background);
 }
 
-.content-area img {
+.content-area img, .modal-content img {
     object-fit: cover;
     width: 100%;
     height: 100%;

+ 16 - 1
packages/asset-server-plugin/e2e/asset-server-plugin.e2e-spec.ts

@@ -22,7 +22,7 @@ describe('AssetServerPlugin', () => {
 
     const { server, adminClient, shopClient } = createTestEnvironment(
         mergeConfig(testConfig(), {
-            logger: new DefaultLogger({ level: LogLevel.Info }),
+            // logger: new DefaultLogger({ level: LogLevel.Info }),
             plugins: [
                 AssetServerPlugin.init({
                     assetUploadDir: path.join(__dirname, TEST_ASSET_DIR),
@@ -257,6 +257,21 @@ describe('AssetServerPlugin', () => {
             await testMimeTypeOfAssetWithExt('webp', 'image/webp');
         });
     });
+
+    // https://github.com/vendure-ecommerce/vendure/issues/1563
+    it('falls back to binary preview if image file cannot be processed', async () => {
+        const filesToUpload = [path.join(__dirname, `fixtures/assets/bad-image.jpg`)];
+        const { createAssets }: CreateAssets.Mutation = await adminClient.fileUploadMutation({
+            mutation: CREATE_ASSETS,
+            filePaths: filesToUpload,
+            mapVariables: filePaths => ({
+                input: filePaths.map(p => ({ file: null })),
+            }),
+        });
+
+        expect(createAssets.length).toBe(1);
+        expect(createAssets[0].name).toBe('bad-image.jpg');
+    });
 });
 
 export const CREATE_ASSETS = gql`

+ 1 - 0
packages/asset-server-plugin/e2e/fixtures/assets/bad-image.jpg

@@ -0,0 +1 @@
+this is not an image file! haha.

+ 1 - 1
packages/asset-server-plugin/src/plugin.ts

@@ -256,7 +256,7 @@ export class AssetServerPlugin implements NestModule, OnApplicationBootstrap {
                         res.send(imageBuffer);
                         return;
                     } catch (e) {
-                        Logger.error(e, 'AssetServerPlugin', e.stack);
+                        Logger.error(e, loggerCtx, e.stack);
                         res.status(500).send(e.message);
                         return;
                     }

+ 37 - 21
packages/asset-server-plugin/src/sharp-asset-preview-strategy.ts

@@ -1,8 +1,10 @@
 import { AssetType } from '@vendure/common/lib/generated-types';
-import { AssetPreviewStrategy, getAssetType, RequestContext } from '@vendure/core';
+import { AssetPreviewStrategy, getAssetType, Logger, RequestContext } from '@vendure/core';
 import path from 'path';
 import sharp from 'sharp';
 
+import { loggerCtx } from './constants';
+
 export class SharpAssetPreviewStrategy implements AssetPreviewStrategy {
     constructor(
         private config: {
@@ -16,30 +18,32 @@ export class SharpAssetPreviewStrategy implements AssetPreviewStrategy {
         const { maxWidth, maxHeight } = this.config;
 
         if (assetType === AssetType.IMAGE) {
-            const image = sharp(data);
-            const metadata = await image.metadata();
-            const width = metadata.width || 0;
-            const height = metadata.height || 0;
-            if (maxWidth < width || maxHeight < height) {
-                return image.resize(maxWidth, maxHeight, { fit: 'inside' }).toBuffer();
-            } else {
-                if (mimeType === 'image/svg+xml') {
-                    // Convert the SVG to a raster for the preview
-                    return image.toBuffer();
+            try {
+                const image = sharp(data);
+                const metadata = await image.metadata();
+                const width = metadata.width || 0;
+                const height = metadata.height || 0;
+                if (maxWidth < width || maxHeight < height) {
+                    return image.rotate().resize(maxWidth, maxHeight, { fit: 'inside' }).toBuffer();
                 } else {
-                    return data;
+                    if (mimeType === 'image/svg+xml') {
+                        // Convert the SVG to a raster for the preview
+                        return image.toBuffer();
+                    } else {
+                        return image.rotate().toBuffer();
+                    }
                 }
+            } catch (err: any) {
+                Logger.error(
+                    `An error occurred when generating preview for image with mimeType ${mimeType}: ${
+                        err.message ?? err.toString()
+                    }`,
+                    loggerCtx,
+                );
+                return this.generateBinaryFilePreview(mimeType);
             }
         } else {
-            return sharp(path.join(__dirname, 'file-icon.png'))
-                .resize(800, 800, { fit: 'outside' })
-                .composite([
-                    {
-                        input: this.generateMimeTypeOverlay(mimeType),
-                        gravity: sharp.gravity.center,
-                    },
-                ])
-                .toBuffer();
+            return this.generateBinaryFilePreview(mimeType);
         }
     }
 
@@ -57,4 +61,16 @@ export class SharpAssetPreviewStrategy implements AssetPreviewStrategy {
               <text x="400" y="110"  text-anchor="middle" width="800">${mimeType}</text>
             </svg>`);
     }
+
+    private generateBinaryFilePreview(mimeType: string): Promise<Buffer> {
+        return sharp(path.join(__dirname, 'file-icon.png'))
+            .resize(800, 800, { fit: 'outside' })
+            .composite([
+                {
+                    input: this.generateMimeTypeOverlay(mimeType),
+                    gravity: sharp.gravity.center,
+                },
+            ])
+            .toBuffer();
+    }
 }

+ 1 - 1
packages/core/src/job-queue/subscribable-job.ts

@@ -81,7 +81,7 @@ export class SubscribableJob<T extends JobData<T> = any> extends Job<T> {
                     return strategy.findOne(id);
                 }),
                 filter(notNullOrUndefined),
-                distinctUntilChanged((a, b) => a?.progress === b?.progress || a?.state === b?.state),
+                distinctUntilChanged((a, b) => a?.progress === b?.progress && a?.state === b?.state),
                 takeWhile(
                     job =>
                         job?.state !== JobState.FAILED &&

+ 1 - 1
packages/core/src/plugin/default-search-plugin/indexer/search-index.service.ts

@@ -159,7 +159,7 @@ export class SearchIndexService implements OnApplicationBootstrap {
                     });
                 },
                 error: (err: any) => {
-                    Logger.error(JSON.stringify(err));
+                    Logger.error(err.message || JSON.stringify(err), undefined, err.stack);
                     reject(err);
                 },
             });

+ 3 - 2
packages/core/src/service/helpers/list-query-builder/list-query-builder.ts

@@ -496,8 +496,9 @@ export class ListQueryBuilder implements OnApplicationBootstrap {
             qb.andWhere(
                 new Brackets(qb1 => {
                     qb1.where(`${translationsAlias}.languageCode = :languageCode`, { languageCode });
-
-                    if (languageCode !== this.configService.defaultLanguageCode) {
+                    const defaultLanguageCode =
+                        ctx?.channel.defaultLanguageCode ?? this.configService.defaultLanguageCode;
+                    if (languageCode !== defaultLanguageCode) {
                         // If the current languageCode is not the default, then we create a more
                         // complex WHERE clause to allow us to use the non-default translations and
                         // fall back to the default language if no translation exists.

+ 2 - 1
packages/elasticsearch-plugin/src/indexing/elasticsearch-index.service.ts

@@ -13,6 +13,7 @@ import {
 } from '@vendure/core';
 import { Observable } from 'rxjs';
 
+import { loggerCtx } from '../constants';
 import { UpdateIndexQueueJobData } from '../types';
 
 import { ElasticsearchIndexerController, ReindexMessageResponse } from './indexer.controller';
@@ -161,7 +162,7 @@ export class ElasticsearchIndexService implements OnApplicationBootstrap {
                     });
                 },
                 error: (err: any) => {
-                    Logger.error(JSON.stringify(err));
+                    Logger.error(err.message || JSON.stringify(err), loggerCtx, err.stack);
                     reject(err);
                 },
             });