Skip to content

Commit

Permalink
feat: Add data panel to display object related data fetched via Cloud…
Browse files Browse the repository at this point in the history
… Function (parse-community#2584)
  • Loading branch information
vardhan0604 authored Oct 6, 2024
1 parent fcfc757 commit 914cc71
Show file tree
Hide file tree
Showing 18 changed files with 872 additions and 75 deletions.
38 changes: 38 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,11 @@
"react-dnd": "10.0.2",
"react-dnd-html5-backend": "10.0.2",
"react-dom": "16.14.0",
"react-draggable": "4.4.6",
"react-helmet": "6.1.0",
"react-json-view": "1.21.3",
"react-popper-tooltip": "4.4.2",
"react-resizable": "3.0.5",
"react-router-dom": "6.4.1",
"regenerator-runtime": "0.13.11"
},
Expand Down
84 changes: 84 additions & 0 deletions src/components/AggregationPanel/AggregationPanel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import LoaderDots from 'components/LoaderDots/LoaderDots.react';
import React, { useEffect, useMemo } from 'react';
import styles from './AggregationPanel.scss';
import {
AudioElement,
ButtonElement,
ImageElement,
KeyValueElement,
TableElement,
TextElement,
VideoElement,
} from './AggregationPanelComponents';

const AggregationPanel = ({
data,
isLoadingCloudFunction,
showAggregatedData,
setErrorAggregatedData,
errorAggregatedData,
showNote,
setSelectedObjectId,
selectedObjectId
}) => {

useEffect(() => {
if (Object.keys(errorAggregatedData).length !== 0) {
setSelectedObjectId(null);
setErrorAggregatedData({});
}
}, [errorAggregatedData, setSelectedObjectId, setErrorAggregatedData]);

const isLoading = useMemo(() =>
selectedObjectId && isLoadingCloudFunction && showAggregatedData,
[selectedObjectId, isLoadingCloudFunction, showAggregatedData]
);

const shouldShowAggregatedData = useMemo(() =>
selectedObjectId && showAggregatedData && Object.keys(data).length !== 0 && Object.keys(errorAggregatedData).length === 0, [selectedObjectId, showAggregatedData, data, errorAggregatedData]
);

return (
<>
{isLoading ? (
<div className={styles.center}>
<LoaderDots />
</div>
) : shouldShowAggregatedData ? (
data.panel.segments.map((segment, index) => (
<div key={index}>
<h2 className={styles.heading}>{segment.title}</h2>
<div className={styles.segmentItems}>
{segment.items.map((item, idx) => {
switch (item.type) {
case 'text':
return <TextElement key={idx} text={item.text} />;
case 'keyValue':
return <KeyValueElement key={idx} item={item} />;
case 'table':
return <TableElement key={idx} columns={item.columns} rows={item.rows} />;
case 'image':
return <ImageElement key={idx} url={item.url} />;
case 'video':
return <VideoElement key={idx} url={item.url} />;
case 'audio':
return <AudioElement key={idx} url={item.url} />;
case 'button':
return <ButtonElement key={idx} item={item} showNote={showNote} />;
default:
return null;
}
})}
</div>
</div>
))
) : (
<div className={styles.loading}>
No object selected.
</div>
)}
</>
);
};

export default AggregationPanel;
99 changes: 99 additions & 0 deletions src/components/AggregationPanel/AggregationPanel.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
@import 'stylesheets/globals.scss';

.heading {
font-size: 14px;
margin-top: 0;
padding: 8px;
padding-left: 10px;
background-color: $blue;
color: $white;
}

.segmentItems {
font-size: 14px;
padding-left: 10px;
padding-right: 10px;
padding-top: 6px;
display: flex;
flex-direction: column;
border-left: 1px solid #e3e3ea;
gap: 10px;
}

.keyValue {
font-size: 14px;
display: flex;
gap: 10px;
}

.video {
width: 100%;
height: 100%;
}

.image {
width: 100%;
height: 100%;
}

.audio {
width: 100%;
}

.segmentItems table,
.segmentItems th,
.segmentItems td {
font-size: 14px;
border: 1px solid #ddd;
}

.segmentItems th,
.segmentItems td {
padding: 4px;
text-align: left;
}

.buttonContainer {
display: flex;
justify-content: center;
align-items: center;
}

.button {
width: auto;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
margin-bottom: 15px;
background-color: $blue;
padding: 3px 13px;
border: none;
color: $white;
line-height: 28px;
outline: 0;
text-decoration: none;
text-align: center;
border-radius: 5px;
font-size: 14px;
&:hover,
&:focus {
background-color: $darkBlue;
}
}

.loading{
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}

.center {
position: absolute;
text-align: center;
top: 50%;
left: 50%;
@include transform(translate(-50%, -50%));
}
97 changes: 97 additions & 0 deletions src/components/AggregationPanel/AggregationPanelComponents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React from 'react';
import styles from './AggregationPanel.scss';

// Text Element Component
export const TextElement = ({ text }) => (
<div className="text-element">
<p>{text}</p>
</div>
);

// Key-Value Element Component
export const KeyValueElement = ({ item }) => (
<div className={styles.keyValue}>
{item.key}:
{item.url ? <a href={item.url} target="_blank">{item.value}</a> : <span>{item.value}</span>}
</div>
);

// Table Element Component
export const TableElement = ({ columns, rows }) => (
<div className="table-element">
<table>
<thead>
<tr>
{columns.map((column, idx) => (
<th key={idx}>{column.name}</th>
))}
</tr>
</thead>
<tbody>
{rows.map((row, idx) => (
<tr key={idx}>
{columns.map((column, colIdx) => (
<td key={colIdx}>{row[column.name]}</td>
))}
</tr>
))}
</tbody>
</table>
</div>
);

// Image Element Component
export const ImageElement = ({ url }) => (
<div className="image-element">
<a href={url} target="_blank" rel="noopener noreferrer">
<img src={url} alt="Image" className={styles.image} />
</a>
</div>
);

// Video Element Component
export const VideoElement = ({ url }) => (
<div className="video-element">
<video controls className={styles.video}>
<source src={url} type="video/mp4" />
Your browser does not support the video tag.
</video>
</div>
);

// Audio Element Component
export const AudioElement = ({ url }) => (
<div className="audio-element">
<audio controls className={styles.audio}>
<source src={url} type="audio/mpeg" />
Your browser does not support the audio element.
</audio>
</div>
);

// Button Element Component
export const ButtonElement = ({ item, showNote }) => {
const handleClick = () => {
fetch(item.action.url, {
method: item.action.method,
headers: item.action.headers,
body: JSON.stringify(item.action.body),
})
.then(response => response.json())
.then(data => {
const formattedData = JSON.stringify(data, null, 2);
showNote(`${formattedData}`,false)
})
.catch(error => {
showNote(`${error}`,true)
});
};

return (
<div className={styles.buttonContainer}>
<button onClick={handleClick} className={styles.button}>
{item.text}
</button>
</div>
);
};
Loading

0 comments on commit 914cc71

Please sign in to comment.