mirror of
https://github.com/nasa/openmct.git
synced 2024-12-18 20:57:53 +00:00
Encode urls for css background images (#7906)
* Add new utility to encode urls. Use the encode urls utility to encode all background images in css * need a commit to pull exampleimagery from * skip and fix on otherside --------- Co-authored-by: John Hill <john.c.hill@nasa.gov>
This commit is contained in:
parent
078cd341a5
commit
057a5f997c
BIN
e2e/test-data/rick space roll.jpg
Normal file
BIN
e2e/test-data/rick space roll.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
@ -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
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
@ -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"
|
||||
>
|
||||
<span
|
||||
@ -62,7 +58,7 @@
|
||||
@change="updateStyleValue"
|
||||
/>
|
||||
<ToolbarButton
|
||||
v-if="hasProperty(styleItem.style.imageUrl)"
|
||||
v-if="hasProperty(encodedImageUrl)"
|
||||
class="c-style__toolbar-button--image-url"
|
||||
:options="imageUrlOption"
|
||||
@change="updateStyleValue"
|
||||
@ -93,6 +89,8 @@ import ToolbarButton from '@/ui/toolbar/components/ToolbarButton.vue';
|
||||
import ToolbarColorPicker from '@/ui/toolbar/components/ToolbarColorPicker.vue';
|
||||
import ToolbarToggleButton from '@/ui/toolbar/components/ToolbarToggleButton.vue';
|
||||
|
||||
import { encode_url } from '../../../../utils/encoding';
|
||||
|
||||
export default {
|
||||
name: 'StyleEditor',
|
||||
components: {
|
||||
@ -183,11 +181,14 @@ export default {
|
||||
},
|
||||
property: 'imageUrl',
|
||||
formKeys: ['url'],
|
||||
value: { url: this.styleItem.style.imageUrl },
|
||||
value: { url: this.encodedImageUrl },
|
||||
isEditing: this.isEditing,
|
||||
nonSpecific: this.mixedStyles.indexOf('imageUrl') > -1
|
||||
};
|
||||
},
|
||||
encodedImageUrl() {
|
||||
return encode_url(this.styleItem.style.imageUrl);
|
||||
},
|
||||
isStyleInvisibleOption() {
|
||||
return {
|
||||
value: this.styleItem.style.isStyleInvisible,
|
||||
|
@ -35,6 +35,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { encode_url } from '../../../utils/encoding';
|
||||
import conditionalStylesMixin from '../mixins/objectStyles-mixin.js';
|
||||
import LayoutFrame from './LayoutFrame.vue';
|
||||
|
||||
@ -80,12 +81,12 @@ export default {
|
||||
return this.isEditing || !this.itemStyle?.isStyleInvisible;
|
||||
},
|
||||
style() {
|
||||
let backgroundImage = 'url(' + this.item.url + ')';
|
||||
let backgroundImage = `url('${encode_url(this.item.url)}')`;
|
||||
let border = '1px solid ' + this.item.stroke;
|
||||
|
||||
if (this.itemStyle) {
|
||||
if (this.itemStyle.imageUrl !== undefined) {
|
||||
backgroundImage = 'url(' + this.itemStyle.imageUrl + ')';
|
||||
backgroundImage = `url('${encode_url(this.itemStyle.imageUrl)}')`;
|
||||
}
|
||||
|
||||
border = this.itemStyle.border;
|
||||
|
@ -38,7 +38,7 @@
|
||||
<img
|
||||
ref="img"
|
||||
class="c-thumb__image"
|
||||
:src="`${image.thumbnailUrl || image.url}`"
|
||||
:src="imageSrc"
|
||||
fetchpriority="low"
|
||||
@load="imageLoadCompleted"
|
||||
/>
|
||||
@ -54,6 +54,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { encode_url } from '../../../utils/encoding';
|
||||
|
||||
const THUMB_PADDING = 4;
|
||||
const BORDER_WIDTH = 2;
|
||||
|
||||
@ -96,6 +98,9 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
imageSrc() {
|
||||
return `${encode_url(this.image.thumbnailUrl) || encode_url(this.image.url)}`;
|
||||
},
|
||||
ariaLabel() {
|
||||
return `Image thumbnail from ${this.image.formattedTime}${this.showAnnotationIndicator ? ', has annotations' : ''}`;
|
||||
},
|
||||
|
@ -222,6 +222,7 @@ import { TIME_CONTEXT_EVENTS } from '@/api/time/constants.js';
|
||||
import imageryData from '@/plugins/imagery/mixins/imageryData.js';
|
||||
import { VIEW_LARGE_ACTION_KEY } from '@/plugins/viewLargeAction/viewLargeAction.js';
|
||||
|
||||
import { encode_url } from '../../../utils/encoding';
|
||||
import eventHelpers from '../lib/eventHelpers.js';
|
||||
import AnnotationsCanvas from './AnnotationsCanvas.vue';
|
||||
import Compass from './Compass/CompassComponent.vue';
|
||||
@ -364,7 +365,7 @@ export default {
|
||||
filter: `brightness(${this.filters.brightness}%) contrast(${this.filters.contrast}%)`,
|
||||
backgroundImage: `${
|
||||
this.imageUrl
|
||||
? `url(${this.imageUrl}),
|
||||
? `url(${encode_url(this.imageUrl)}),
|
||||
repeating-linear-gradient(
|
||||
45deg,
|
||||
transparent,
|
||||
@ -789,7 +790,7 @@ export default {
|
||||
},
|
||||
getVisibleLayerStyles(layer) {
|
||||
return {
|
||||
backgroundImage: `url(${layer.source})`,
|
||||
backgroundImage: `url(${encode_url(layer.source)})`,
|
||||
transform: `scale(${this.zoomFactor}) translate(${this.imageTranslateX / 2}px, ${
|
||||
this.imageTranslateY / 2
|
||||
}px)`,
|
||||
|
@ -32,6 +32,7 @@
|
||||
<script>
|
||||
import mount from 'utils/mount';
|
||||
|
||||
import { encode_url } from '../../utils/encoding';
|
||||
import AboutDialog from './AboutDialog.vue';
|
||||
|
||||
export default {
|
||||
@ -39,7 +40,7 @@ export default {
|
||||
mounted() {
|
||||
const branding = this.openmct.branding();
|
||||
if (branding.smallLogoImage) {
|
||||
this.$refs.aboutLogo.style.backgroundImage = `url('${branding.smallLogoImage}')`;
|
||||
this.$refs.aboutLogo.style.backgroundImage = `url('${encode_url(branding.smallLogoImage)}')`;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
25
src/utils/encoding.js
Normal file
25
src/utils/encoding.js
Normal file
@ -0,0 +1,25 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
|
||||
export function encode_url(url) {
|
||||
return url ? encodeURI(url) : url;
|
||||
}
|
Loading…
Reference in New Issue
Block a user