Skip to content

Commit 6a6b1f0

Browse files
authored
feat: Add support for Image type in View table to display images (#2952)
1 parent 9b48d21 commit 6a6b1f0

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ Parse Dashboard is a standalone dashboard for managing your [Parse Server](https
8585
- [View Table](#view-table)
8686
- [Pointer](#pointer)
8787
- [Link](#link)
88+
- [Image](#image)
8889
- [Contributing](#contributing)
8990

9091
# Getting Started
@@ -1362,6 +1363,25 @@ In the example above, the query string will be escaped and added to the url, res
13621363
> [!Note]
13631364
> For security reasons, the link `<a>` tag contains the `rel="noreferrer"` attribute, which prevents the target website to know the referring website which in this case is the Parse Dashboard URL. That attribute is widely supported across modern browsers, but if in doubt check your browser's compatibility.
13641365
1366+
#### Image
1367+
1368+
Images are rendered directly in the output table with an `<img>` tag. The content mode is always "scale to fit", meaning that if the image file is 100x50px and the specified dimensions are 50x50px, it would display as 50x25px, since it's scaled maintaining aspect ratio.
1369+
1370+
Example:
1371+
1372+
```json
1373+
{
1374+
"__type": "Image",
1375+
"url": "https://example.com/image.png",
1376+
"width": "50",
1377+
"height": "50",
1378+
"alt": "Image"
1379+
}
1380+
```
1381+
1382+
> [!Warning]
1383+
> The URL will be directly invoked by the browser when trying to display the image. For security reasons, make sure you either control the full URL, including the image file name, or sanitize the URL before returning it to the dashboard. URLs containing `javascript:` or `<script` will be blocked automatically and replaced with a placeholder.
1384+
13651385
# Contributing
13661386

13671387
We really want Parse to be yours, to see it grow and thrive in the open source community. Please see the [Contributing to Parse Dashboard guide](CONTRIBUTING.md).

src/dashboard/Data/Views/Views.react.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,8 @@ class Views extends TableView {
251251
type = 'GeoPoint';
252252
} else if (val.__type === 'Link') {
253253
type = 'Link';
254+
} else if (val.__type === 'Image') {
255+
type = 'Image';
254256
} else {
255257
type = 'Object';
256258
}
@@ -379,6 +381,8 @@ class Views extends TableView {
379381
type = 'GeoPoint';
380382
} else if (value.__type === 'Link') {
381383
type = 'Link';
384+
} else if (value.__type === 'Image') {
385+
type = 'Image';
382386
} else {
383387
type = 'Object';
384388
}
@@ -428,6 +432,41 @@ class Views extends TableView {
428432
{text}
429433
</a>
430434
);
435+
} else if (type === 'Image') {
436+
// Sanitize URL
437+
let url = value.url;
438+
if (
439+
!url ||
440+
url.match(/javascript/i) ||
441+
url.match(/<script/i)
442+
) {
443+
url = '#';
444+
}
445+
446+
// Parse dimensions, ensuring they are positive numbers
447+
const width = value.width && parseInt(value.width, 10) > 0 ? parseInt(value.width, 10) : null;
448+
const height = value.height && parseInt(value.height, 10) > 0 ? parseInt(value.height, 10) : null;
449+
450+
// Create style object for scale-to-fit behavior
451+
const imgStyle = {
452+
maxWidth: width ? `${width}px` : '100%',
453+
maxHeight: height ? `${height}px` : '100%',
454+
objectFit: 'contain', // This ensures scale-to-fit behavior maintaining aspect ratio
455+
display: 'block'
456+
};
457+
458+
content = (
459+
<img
460+
src={url}
461+
alt={value.alt || 'Image'}
462+
style={imgStyle}
463+
onError={(e) => {
464+
if (e.target && e.target.style) {
465+
e.target.style.display = 'none';
466+
}
467+
}}
468+
/>
469+
);
431470
} else if (value === undefined) {
432471
content = '';
433472
} else {

0 commit comments

Comments
 (0)