diff --git a/.circleci/config.yml b/.circleci/config.yml index 3998a1c9189..15769661326 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ orbs: executors: pw-focal-development: docker: - - image: mcr.microsoft.com/playwright:v1.47.2-focal + - image: mcr.microsoft.com/playwright:v1.48.1-focal environment: NODE_ENV: development # Needed to ensure 'dist' folder created and devDependencies installed PERCY_POSTINSTALL_BROWSER: 'true' # Needed to store the percy browser in cache deps @@ -198,7 +198,7 @@ jobs: steps: - build_and_install: node-version: lts/hydrogen - - run: npx playwright@1.47.2 install #Necessary for bare ubuntu machine + - run: npx playwright@1.48.1 install #Necessary for bare ubuntu machine - run: | export $(cat src/plugins/persistence/couch/.env.ci | xargs) docker compose -f src/plugins/persistence/couch/couchdb-compose.yaml up --detach @@ -286,8 +286,8 @@ workflows: overall-circleci-commit-status: #These jobs run on every commit jobs: - lint: - name: node20-lint - node-version: lts/iron + name: node22-lint + node-version: '22' - unit-test: name: node18-chrome node-version: lts/hydrogen @@ -304,8 +304,8 @@ workflows: the-nightly: #These jobs do not run on PRs, but against master at night jobs: - unit-test: - name: node20-chrome-nightly - node-version: lts/iron + name: node22-chrome-nightly + node-version: '22' - unit-test: name: node18-chrome node-version: lts/hydrogen diff --git a/.github/workflows/e2e-couchdb.yml b/.github/workflows/e2e-couchdb.yml index 20036629477..edab4e9fb46 100644 --- a/.github/workflows/e2e-couchdb.yml +++ b/.github/workflows/e2e-couchdb.yml @@ -37,7 +37,7 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - run: npx playwright@1.47.2 install + - run: npx playwright@1.48.1 install - name: Start CouchDB Docker Container and Init with Setup Scripts run: | diff --git a/.github/workflows/e2e-flakefinder.yml b/.github/workflows/e2e-flakefinder.yml index c06edea6531..09c912f4240 100644 --- a/.github/workflows/e2e-flakefinder.yml +++ b/.github/workflows/e2e-flakefinder.yml @@ -30,7 +30,7 @@ jobs: restore-keys: | ${{ runner.os }}-node- - - run: npx playwright@1.47.2 install + - run: npx playwright@1.48.1 install - run: npm ci --no-audit --progress=false - name: Run E2E Tests (Repeated 10 Times) diff --git a/.github/workflows/e2e-perf.yml b/.github/workflows/e2e-perf.yml index 2553336f117..36285589b12 100644 --- a/.github/workflows/e2e-perf.yml +++ b/.github/workflows/e2e-perf.yml @@ -28,7 +28,7 @@ jobs: restore-keys: | ${{ runner.os }}-node- - - run: npx playwright@1.47.2 install + - run: npx playwright@1.48.1 install - run: npm ci --no-audit --progress=false - run: npm run test:perf:localhost - run: npm run test:perf:contract diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 045dfedb183..00000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,116 +0,0 @@ -# GitHub Actions Workflow for Automated Releases - -name: Automated Release Workflow - -on: - schedule: - # Nightly builds at 6 PM PST every day - - cron: '0 2 * * *' - release: - types: - - created - - published - -jobs: - nightly-build: - if: github.event_name == 'schedule' - runs-on: ubuntu-latest - name: Nightly Build and Release - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Set Up Node.js - uses: actions/setup-node@v4 - with: - node-version: 'lts/iron' # Specify your Node.js version - registry-url: 'https://registry.npmjs.org/' - - - name: Install Dependencies - run: npm ci - - - name: Bump Version for Nightly - id: bump_version - run: | - PACKAGE_VERSION=$(node -p "require('./package.json').version") - DATE=$(date +%Y%m%d) - NIGHTLY_VERSION=$(echo $PACKAGE_VERSION | awk -F. -v OFS=. '{$NF+=1; print}')-nightly-$DATE - echo "NIGHTLY_VERSION=${NIGHTLY_VERSION}" >> $GITHUB_ENV - - - name: Update package.json - run: | - npm version $NIGHTLY_VERSION --no-git-tag-version - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git add package.json - git commit -m "chore: bump version to $NIGHTLY_VERSION for nightly build" - - - name: Push Changes - uses: ad-m/github-push-action@v0.6.0 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - branch: ${{ github.ref }} - - - name: Build Project - run: npm run build:prod - - - name: Publish Nightly to NPM - run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc - npm publish --access public --tag nightly - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - prerelease-build: - if: github.event.release.prerelease == true - runs-on: ubuntu-latest - name: Pre-release (Beta) Build and Publish - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Set Up Node.js - uses: actions/setup-node@v4 - with: - node-version: '16' # Specify your Node.js version - registry-url: 'https://registry.npmjs.org/' - - - name: Install Dependencies - run: npm ci - - - name: Build Project - run: npm run build:prod - - - name: Publish Beta to NPM - run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc - npm publish --access public --tag beta - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - - stable-release-build: - if: github.event.release.prerelease == false - runs-on: ubuntu-latest - name: Stable Release Build and Publish - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Set Up Node.js - uses: actions/setup-node@v4 - with: - node-version: '16' # Specify your Node.js version - registry-url: 'https://registry.npmjs.org/' - - - name: Install Dependencies - run: npm ci - - - name: Build Project - run: npm run build:prod - - - name: Publish to NPM - run: | - echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" > ~/.npmrc - npm publish --access public - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} \ No newline at end of file diff --git a/e2e/helper/planningUtils.js b/e2e/helper/planningUtils.js index 43988532f30..2e1d8a8a700 100644 --- a/e2e/helper/planningUtils.js +++ b/e2e/helper/planningUtils.js @@ -129,6 +129,7 @@ export async function setBoundsToSpanAllActivities(page, planJson, planObjectUrl */ export function getEarliestStartTime(planJson) { const activities = Object.values(planJson).flat(); + return Math.min(...activities.map((activity) => activity.start)); } @@ -139,6 +140,7 @@ export function getEarliestStartTime(planJson) { */ export function getLatestEndTime(planJson) { const activities = Object.values(planJson).flat(); + return Math.max(...activities.map((activity) => activity.end)); } @@ -151,6 +153,7 @@ export function getFirstActivity(planJson) { const groups = Object.keys(planJson); const firstGroupKey = groups[0]; const firstGroupItems = planJson[firstGroupKey]; + return firstGroupItems[0]; } diff --git a/e2e/package.json b/e2e/package.json index 61000a86d0b..f9436276aa6 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -16,7 +16,7 @@ "devDependencies": { "@percy/cli": "1.27.4", "@percy/playwright": "1.0.4", - "@playwright/test": "1.47.2", + "@playwright/test": "1.48.1", "@axe-core/playwright": "4.8.5" }, "author": { diff --git a/e2e/test-data/rick space roll.jpg b/e2e/test-data/rick space roll.jpg new file mode 100644 index 00000000000..98340f6304b Binary files /dev/null and b/e2e/test-data/rick space roll.jpg differ diff --git a/e2e/tests/functional/plugins/imagery/exampleImagery.e2e.spec.js b/e2e/tests/functional/plugins/imagery/exampleImagery.e2e.spec.js index d5d218bc05c..cd90c76c234 100644 --- a/e2e/tests/functional/plugins/imagery/exampleImagery.e2e.spec.js +++ b/e2e/tests/functional/plugins/imagery/exampleImagery.e2e.spec.js @@ -96,9 +96,6 @@ test.describe('Example Imagery Object', () => { expect(newPage.url()).toContain('.jpg'); }); - // this requires CORS to be enabled in some fashion - test.fixme('Can right click on image and save it as a file', async ({ page }) => {}); - test('Can adjust image brightness/contrast by dragging the sliders', async ({ page, browserName diff --git a/e2e/tests/functional/plugins/imagery/exampleImageryFile.e2e.spec.js b/e2e/tests/functional/plugins/imagery/exampleImageryFile.e2e.spec.js new file mode 100644 index 00000000000..a030e43f788 --- /dev/null +++ b/e2e/tests/functional/plugins/imagery/exampleImageryFile.e2e.spec.js @@ -0,0 +1,93 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2024, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +/* + * This test suite verifies modifying the image location of the example imagery object. + */ + +import { createDomainObjectWithDefaults } from '../../../../appActions.js'; +import { expect, test } from '../../../../pluginFixtures.js'; + +test.describe('Example Imagery Object Custom Images', () => { + let exampleImagery; + test.beforeEach(async ({ page }) => { + //Go to baseURL + await page.goto('./', { waitUntil: 'domcontentloaded' }); + + // Create a default 'Example Imagery' object + exampleImagery = await createDomainObjectWithDefaults(page, { + name: 'Example Imagery', + type: 'Example Imagery' + }); + + // Verify that the created object is focused + await expect(page.locator('.l-browse-bar__object-name')).toContainText(exampleImagery.name); + await page.getByLabel('Focused Image Element').hover({ trial: true }); + + // Wait for image thumbnail auto-scroll to complete + await expect(page.getByLabel('Image Thumbnail from').last()).toBeInViewport(); + }); + // this requires CORS to be enabled in some fashion + test.fixme('Can right click on image and save it as a file', async ({ page }) => {}); + test('Can provide a custom image location for the example imagery object', async ({ page }) => { + // Modify Example Imagery to create a really stable image which will never let us down + await page.getByRole('button', { name: 'More actions' }).click(); + await page.getByRole('menuitem', { name: 'Edit Properties...' }).click(); + await page + .locator('#imageLocation-textarea') + .fill( + 'https://raw.githubusercontent.com/nasa/openmct/554f77c42fec81cf0f63e62b278012cb08d82af9/e2e/test-data/rick.jpg,https://raw.githubusercontent.com/nasa/openmct/554f77c42fec81cf0f63e62b278012cb08d82af9/e2e/test-data/rick.jpg' + ); + await page.getByRole('button', { name: 'Save' }).click(); + await page.reload({ waitUntil: 'domcontentloaded' }); + + // Wait for the thumbnails to finish their scroll animation + // (Wait until the rightmost thumbnail is in view) + await expect(page.getByLabel('Image Thumbnail from').last()).toBeInViewport(); + + await expect(page.getByLabel('Image Wrapper')).toBeVisible(); + }); + test.fixme('Can provide a custom image with spaces in name', async ({ page }) => { + test.info().annotations.push({ + type: 'issue', + description: 'https://github.com/nasa/openmct/issues/7903' + }); + await page.goto(exampleImagery.url, { waitUntil: 'domcontentloaded' }); + + // Modify Example Imagery to create a really stable image which will never let us down + await page.getByRole('button', { name: 'More actions' }).click(); + await page.getByRole('menuitem', { name: 'Edit Properties...' }).click(); + await page + .locator('#imageLocation-textarea') + .fill( + 'https://raw.githubusercontent.com/nasa/openmct/d8c64f183400afb70137221fc1a035e091bea912/e2e/test-data/rick%20space%20roll.jpg' + ); + await page.getByRole('button', { name: 'Save' }).click(); + await page.reload({ waitUntil: 'domcontentloaded' }); + + // Wait for the thumbnails to finish their scroll animation + // (Wait until the rightmost thumbnail is in view) + await expect(page.getByLabel('Image Thumbnail from').last()).toBeInViewport(); + + await expect(page.getByLabel('Image Wrapper')).toBeVisible(); + }); +}); diff --git a/e2e/tests/visual-a11y/planning-gantt.visual.spec.js b/e2e/tests/visual-a11y/planning-gantt.visual.spec.js index f41cfa23fd3..7af9942404c 100644 --- a/e2e/tests/visual-a11y/planning-gantt.visual.spec.js +++ b/e2e/tests/visual-a11y/planning-gantt.visual.spec.js @@ -26,14 +26,25 @@ import fs from 'fs'; import { createDomainObjectWithDefaults, createPlanFromJSON } from '../../appActions.js'; import { scanForA11yViolations, test } from '../../avpFixtures.js'; import { VISUAL_FIXED_URL } from '../../constants.js'; -import { setBoundsToSpanAllActivities, setDraftStatusForPlan } from '../../helper/planningUtils.js'; +import { + getFirstActivity, + setBoundsToSpanAllActivities, + setDraftStatusForPlan +} from '../../helper/planningUtils.js'; const examplePlanSmall2 = JSON.parse( fs.readFileSync(new URL('../../test-data/examplePlans/ExamplePlan_Small2.json', import.meta.url)) ); +const FIRST_ACTIVITY_SMALL_2 = getFirstActivity(examplePlanSmall2); + test.describe('Visual - Gantt Chart @a11y', () => { test.beforeEach(async ({ page }) => { + // Set the clock to the end of the first activity in the plan + // This is so we can see the "now" line in the plan view + await page.clock.install({ time: FIRST_ACTIVITY_SMALL_2.end + 10000 }); + await page.clock.resume(); + await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' }); }); test('Gantt Chart View', async ({ page, theme }) => { diff --git a/e2e/tests/visual-a11y/planning-timestrip.visual.spec.js b/e2e/tests/visual-a11y/planning-timestrip.visual.spec.js index f0a6c9a90ca..2ea1e254782 100644 --- a/e2e/tests/visual-a11y/planning-timestrip.visual.spec.js +++ b/e2e/tests/visual-a11y/planning-timestrip.visual.spec.js @@ -27,14 +27,21 @@ import { createDomainObjectWithDefaults, createPlanFromJSON } from '../../appAct import { scanForA11yViolations, test } from '../../avpFixtures.js'; import { waitForAnimations } from '../../baseFixtures.js'; import { VISUAL_FIXED_URL } from '../../constants.js'; -import { setBoundsToSpanAllActivities } from '../../helper/planningUtils.js'; +import { getFirstActivity, setBoundsToSpanAllActivities } from '../../helper/planningUtils.js'; const examplePlanSmall2 = JSON.parse( fs.readFileSync(new URL('../../test-data/examplePlans/ExamplePlan_Small2.json', import.meta.url)) ); +const FIRST_ACTIVITY_SMALL_2 = getFirstActivity(examplePlanSmall2); + test.describe('Visual - Time Strip @a11y', () => { test.beforeEach(async ({ page }) => { + // Set the clock to the end of the first activity in the plan + // This is so we can see the "now" line in the plan view + await page.clock.install({ time: FIRST_ACTIVITY_SMALL_2.end + 10000 }); + await page.clock.resume(); + await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' }); }); test('Time Strip View', async ({ page, theme }) => { diff --git a/e2e/tests/visual-a11y/planning-view.visual.spec.js b/e2e/tests/visual-a11y/planning-view.visual.spec.js index 7ca1200c03d..6386f0cca4c 100644 --- a/e2e/tests/visual-a11y/planning-view.visual.spec.js +++ b/e2e/tests/visual-a11y/planning-view.visual.spec.js @@ -42,6 +42,7 @@ const examplePlanSmall2 = JSON.parse( ); const FIRST_ACTIVITY_SMALL_1 = getFirstActivity(examplePlanSmall1); +const FIRST_ACTIVITY_SMALL_2 = getFirstActivity(examplePlanSmall2); test.describe('Visual - Timelist progress bar @clock @a11y', () => { test.beforeEach(async ({ page }) => { @@ -59,6 +60,11 @@ test.describe('Visual - Timelist progress bar @clock @a11y', () => { test.describe('Visual - Plan View @a11y', () => { test.beforeEach(async ({ page }) => { + // Set the clock to the end of the first activity in the plan + // This is so we can see the "now" line in the plan view + await page.clock.install({ time: FIRST_ACTIVITY_SMALL_2.end + 10000 }); + await page.clock.resume(); + await page.goto(VISUAL_FIXED_URL, { waitUntil: 'domcontentloaded' }); }); diff --git a/package-lock.json b/package-lock.json index d6cda9c5837..ab90e82caab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -94,7 +94,7 @@ "webpack-merge": "5.10.0" }, "engines": { - "node": ">=18.14.2 <22" + "node": ">=18.14.2 <23" } }, "e2e": { @@ -105,7 +105,7 @@ "@axe-core/playwright": "4.8.5", "@percy/cli": "1.27.4", "@percy/playwright": "1.0.4", - "@playwright/test": "1.47.2" + "@playwright/test": "1.48.1" } }, "e2e/node_modules/@percy/cli": { @@ -1561,13 +1561,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.47.2", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.47.2.tgz", - "integrity": "sha512-jTXRsoSPONAs8Za9QEQdyjFn+0ZQFjCiIztAIF6bi1HqhBzG9Ma7g1WotyiGqFSBRZjIEqMdT8RUlbk1QVhzCQ==", + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.1.tgz", + "integrity": "sha512-s9RtWoxkOLmRJdw3oFvhFbs9OJS0BzrLUc8Hf6l2UdCNd1rqeEyD4BhCJkvzeEoD1FsK4mirsWwGerhVmYKtZg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.47.2" + "playwright": "1.48.1" }, "bin": { "playwright": "cli.js" @@ -8830,13 +8830,13 @@ } }, "node_modules/playwright": { - "version": "1.47.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.47.2.tgz", - "integrity": "sha512-nx1cLMmQWqmA3UsnjaaokyoUpdVaaDhJhMoxX2qj3McpjnsqFHs516QAKYhqHAgOP+oCFTEOCOAaD1RgD/RQfA==", + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.48.1.tgz", + "integrity": "sha512-j8CiHW/V6HxmbntOfyB4+T/uk08tBy6ph0MpBXwuoofkSnLmlfdYNNkFTYD6ofzzlSqLA1fwH4vwvVFvJgLN0w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.47.2" + "playwright-core": "1.48.1" }, "bin": { "playwright": "cli.js" @@ -8849,9 +8849,9 @@ } }, "node_modules/playwright-core": { - "version": "1.47.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.47.2.tgz", - "integrity": "sha512-3JvMfF+9LJfe16l7AbSmU555PaTl2tPyQsVInqm3id16pdDfvZ8TTZ/pyzmkbDrZTQefyzU7AIHlZqQnxpqHVQ==", + "version": "1.48.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.48.1.tgz", + "integrity": "sha512-Yw/t4VAFX/bBr1OzwCuOMZkY1Cnb4z/doAFSwf4huqAGWmf9eMNjmK7NiOljCdLmxeRYcGPPmcDgU0zOlzP0YA==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index ee9e9e4074e..be1e65a21bd 100644 --- a/package.json +++ b/package.json @@ -140,7 +140,7 @@ "url": "git+https://github.com/nasa/openmct.git" }, "engines": { - "node": ">=18.14.2 <22" + "node": ">=18.14.2 <23" }, "browserslist": [ "Firefox ESR", diff --git a/src/plugins/charts/bar/BarGraphView.vue b/src/plugins/charts/bar/BarGraphView.vue index 0bc90e3ebb9..07c24932d63 100644 --- a/src/plugins/charts/bar/BarGraphView.vue +++ b/src/plugins/charts/bar/BarGraphView.vue @@ -332,7 +332,11 @@ export default { this.domainObject.configuration.axes.xKey === undefined || this.domainObject.configuration.axes.yKey === undefined ) { - return; + const { xKey, yKey } = this.identifyAxesKeys(axisMetadata); + this.openmct.objects.mutate(this.domainObject, 'configuration.axes', { + xKey, + yKey + }); } let xValues = []; @@ -431,6 +435,30 @@ export default { subscribeToAll() { const telemetryObjects = Object.values(this.telemetryObjects); telemetryObjects.forEach(this.subscribeToObject); + }, + identifyAxesKeys(metadata) { + const { xAxisMetadata, yAxisMetadata } = metadata; + + let xKey; + let yKey; + + // If xAxisMetadata contains array values, use the first one for xKey + const arrayValues = xAxisMetadata.filter((metaDatum) => metaDatum.isArrayValue); + const nonArrayValues = xAxisMetadata.filter((metaDatum) => !metaDatum.isArrayValue); + + if (arrayValues.length > 0) { + xKey = arrayValues[0].key; + yKey = arrayValues.length > 1 ? arrayValues[1].key : yAxisMetadata.key; + } else if (nonArrayValues.length > 0) { + xKey = nonArrayValues[0].key; + yKey = 'none'; + } else { + // Fallback if no valid xKey or yKey is found + xKey = 'none'; + yKey = 'none'; + } + + return { xKey, yKey }; } } }; diff --git a/src/plugins/comps/components/CompsView.vue b/src/plugins/comps/components/CompsView.vue index 273a7e50981..5e5cf886487 100644 --- a/src/plugins/comps/components/CompsView.vue +++ b/src/plugins/comps/components/CompsView.vue @@ -209,9 +209,20 @@ const props = defineProps({ }); onBeforeMount(async () => { + let maxSampleSize = 20; + if (parameters.value) { + maxSampleSize = + parameters.value.reduce((max, param) => { + if (param.accumulateValues) { + return Math.max(max, param.sampleSize); + } + return max; + }, 0) + 20; + } + const telemetryOptions = { strategy: 'minmax', - size: 20, + size: maxSampleSize }; // TODO: we should dynamically set size to the largest comp input window outputTelemetryCollection = openmct.telemetry.requestCollection(domainObject, telemetryOptions); diff --git a/src/plugins/condition/components/inspector/StyleEditor.vue b/src/plugins/condition/components/inspector/StyleEditor.vue index 512c75cc03d..076e16889e3 100644 --- a/src/plugins/condition/components/inspector/StyleEditor.vue +++ b/src/plugins/condition/components/inspector/StyleEditor.vue @@ -28,11 +28,7 @@ { 'is-style-invisible': styleItem.style && styleItem.style.isStyleInvisible }, { 'c-style-thumb--mixed': mixedStyles.indexOf('backgroundColor') > -1 } ]" - :style="[ - styleItem.style.imageUrl - ? { backgroundImage: 'url(' + styleItem.style.imageUrl + ')' } - : itemStyle - ]" + :style="[encodedImageUrl ? { backgroundImage: 'url(' + encodedImageUrl + ')' } : itemStyle]" class="c-style-thumb" > -1 }; }, + encodedImageUrl() { + return encode_url(this.styleItem.style.imageUrl); + }, isStyleInvisibleOption() { return { value: this.styleItem.style.isStyleInvisible, diff --git a/src/plugins/displayLayout/components/ImageView.vue b/src/plugins/displayLayout/components/ImageView.vue index b22b8d87aac..d653f3afcfc 100644 --- a/src/plugins/displayLayout/components/ImageView.vue +++ b/src/plugins/displayLayout/components/ImageView.vue @@ -35,6 +35,7 @@