Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add data aggregation panel #2495

Open
3 tasks done
mtrezza opened this issue Jul 18, 2023 · 6 comments · May be fixed by #2584
Open
3 tasks done

Add data aggregation panel #2495

mtrezza opened this issue Jul 18, 2023 · 6 comments · May be fixed by #2584
Labels
bounty:$250 Bounty applies for fixing this issue (Parse Bounty Program)

Comments

@mtrezza
Copy link
Member

mtrezza commented Jul 18, 2023

New Feature / Enhancement Checklist

Current Limitation

An object may have related information stored in other classes, for example a user and its related purchase history and its related payment transactions. This related information needs to be researched manually by going into the respective classes. With each navigation, only the information in the current class is visible, there is no aggregated view of all information at once, e.g. purchase history and payment transactions.

Feature / Enhancement Description

Add a slide-in panel that displays aggregated information related to the selected object in the data browser table.

The process should be:

  1. User opens the side-panel
  2. User selects a row in the data browser table by clicking any field
  3. The selected object is sent incl. all its fields to a Parse Server Cloud Function
  4. The response is displayed in the info panel

Example Use Case

Dashboard options could look like this:

"apps": [
  {
    "infoPanel": [
      {
        "title": "User Details",
        "classes": ["_User"],
        "cloudCodeFunction": "getUserDetails",
      }
    ]
  }
]

The response of the Cloud Function could be:

{
  "panel": {
    // Nest response in `segments` property to be able to extend the response object
    // in the future if needed; the `segments` property is an ordered array so that 
    // it can display segments in a given order
    "segments": [
      {
        // The segment title
        "title": "Purchases",
        // The items within the segment; as ordered array to display items in a given
        // order; items here are only
        "items": [
          {
            // A plain text field
            "type": "text",
            "text": "This user has a high churn risk!"
          },
          {
            // A key-value style
            "type": "keyValue",
            "key": "Lifetime purchase value",
            "value": "$10k"
          },
          {
            // A key-value style with a linked URL
            "type": "keyValue",
            "key": "Last purchase ID",
            "value": "012345",
            "url": "https://example.com/purchaseDetails?purchaseId=012345"
          },
          {
            // A table
            "type": "table",
            "columns": [
              {
                "name": "Name",
                "type": "string"
              },
              {
                "name": "Age",
                "type": "number"
              }
            ],
            "rows": [
              {
                "Name": "Alice",
                "Age": 30
              },
              {
                "Name": "Bob",
                "Age": 40
              }
            ]
          },
          {
            // An image
            "type": "image",
            "url": "https://example.com/images?purchaseId=012345"
          },
          {
            // A video
            "type": "video",
            "url": "https://example.com/video.mp4"
          },
          {
            // An audio
            "type": "audio",
            "url": "https://example.com/audio.mp3"
          }
          {
            // A button
            "type": "button",
            "text": "Click me!",
            "action": {
              "url": "https://api.example.com/click",
              "method": "POST",
              "headers": {
                "Content-Type": "application/json"
              },
              "body": {
                "key": "value"
              }
            }
          }
        ]
      }
    ]
  }
}

The panel could look like this:

image

  • The panel size should be resizable by the dashboard user do adapt it depending on available screen space and displayed info; some form of control like a drag handle would be needed for that, not visible in the screenshot.
  • When being resized, text should wrap and images should resize.
  • Sliding the panel in completely, so that it doesn't appear should disable loading the info unnecessarily.
  • The panel should have an "X" (close) button in the top right corner, to close it easily.
  • The panel should not cover any space other than the data browser itself.
  • The panel needs a loading indicator; this also prevents mistaking panel data from the previous object as the current object.
  • Panel loading is an async operation, when switching quickly between objects, it must be ensured that only the current panel data is shown and any previous request is cancelled and its result discarded.

Alternatives / Workarounds

  • Research manually by navigating to each class
  • User Dashboard Script to display information in a pop-up message

Future extensions

  • Add buttons to execute scripts on the user, like the existing scripts feature in the context menu.
@parse-github-assistant
Copy link

parse-github-assistant bot commented Jul 18, 2023

Thanks for opening this issue!

  • 🎉 We are excited about your ideas for improvement!

@mtrezza mtrezza changed the title Add info panel Add data aggregation panel Jul 18, 2023
@mtrezza mtrezza added the bounty:$100 Bounty applies for fixing this issue (Parse Bounty Program) label Jul 18, 2023
@mtrezza
Copy link
Member Author

mtrezza commented May 4, 2024

@Bhavyajain21 this may be interesting for you

@vardhan0604
Copy link
Contributor

@mtrezza
From my understanding, the process involves:

  • The dashboard reads the configuration to know which Cloud Function to call based on the selected class.
  • The side panel makes an API call to the Cloud Function specified in the config.
  • The response from the Cloud Function is displayed in the side panel.

can you define how the response from the Cloud Function should look? This will ensure consistency and make it easier to render the information in the panel.

Thank you!

@mtrezza
Copy link
Member Author

mtrezza commented Jul 10, 2024

I have updated the JSON response structure in the description above. The panel would structurally look like this (albeit in the style of the screenshot above, so it fits the dashboard style), where each element is a row:

image

For reference the HTML code of the render above as an example:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Panel Example</title>
<style>
    body {
        font-family: Arial, sans-serif;
    }
    .panel {
        width: 300px;
        border: 1px solid #ccc;
        padding: 15px;
        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
        margin: 0 auto;
    }
    .panel h2 {
        font-size: 18px;
        margin-bottom: 15px;
    }
    .panel table {
        width: 100%;
        border-collapse: collapse;
        margin-bottom: 15px;
    }
    .panel table, .panel th, .panel td {
        border: 1px solid #ddd;
    }
    .panel th, .panel td {
        padding: 8px;
        text-align: left;
    }
    .panel button {
        display: block;
        width: 100%;
        padding: 10px;
        background-color: #007BFF;
        color: #fff;
        border: none;
        cursor: pointer;
        margin-bottom: 15px;
    }
    .panel button:hover {
        background-color: #0056b3;
    }
    .panel img, .panel video, .panel audio {
        width: 100%;
        margin-bottom: 15px;
    }
    .key-value {
        margin-bottom: 15px;
    }
    .key-value a {
        color: #007BFF;
        text-decoration: none;
    }
</style>
</head>
<body>

<div class="panel">
    <h2>Purchases</h2>
    
    <!-- Text Element -->
    <div class="text-element">
        <p>This user has a high churn risk!</p>
    </div>
    
    <!-- Key-Value Element -->
    <div class="key-value">
        <strong>Lifetime purchase value:</strong> $10k
    </div>
    
    <!-- Key-Value with Link Element -->
    <div class="key-value">
        <strong>Last purchase ID:</strong> 
        <a href="https://example.com/purchaseDetails?purchaseId=012345">012345</a>
    </div>

    <!-- Table Element -->
    <div class="table-element">
        <table>
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Age</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td>Alice</td>
                    <td>30</td>
                </tr>
                <tr>
                    <td>Bob</td>
                    <td>40</td>
                </tr>
            </tbody>
        </table>
    </div>

    <!-- Image Element -->
    <div class="image-element">
        <img src="https://example.com/images?purchaseId=012345" alt="Image">
    </div>

    <!-- Video Element -->
    <div class="video-element">
        <video controls>
            <source src="https://example.com/video.mp4" type="video/mp4">
            Your browser does not support the video tag.
        </video>
    </div>

    <!-- Audio Element -->
    <div class="audio-element">
        <audio controls>
            <source src="https://example.com/audio.mp3" type="audio/mpeg">
            Your browser does not support the audio element.
        </audio>
    </div>

    <!-- Button Element -->
    <div class="button-element">
        <button onclick="handleButtonClick()">Click me!</button>
    </div>
</div>

<script>
function handleButtonClick() {
    fetch('https://api.example.com/click', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({ key: 'value' })
    })
    .then(response => response.json())
    // Instead of console logging, the response would need to displayed like other messages, there's a pop-up method for this, see for example the "script" feature of dashboard
    .then(data => console.log(data))
    .catch(error => console.error('Error:', error));
}
</script>

</body>
</html>

@mtrezza mtrezza added bounty:$250 Bounty applies for fixing this issue (Parse Bounty Program) and removed bounty:$100 Bounty applies for fixing this issue (Parse Bounty Program) labels Jul 10, 2024
@mtrezza
Copy link
Member Author

mtrezza commented Jul 10, 2024

Bounty increased due to scope increase of the feature and its high value for the usability of the dashboard.

@vardhan0604
Copy link
Contributor

I have updated the JSON response structure in the description above. The panel would structurally look like this (albeit in the style of the screenshot above, so it fits the dashboard style), where each element is a row:

I have checked the JSON response , I will get started with this feature asap

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bounty:$250 Bounty applies for fixing this issue (Parse Bounty Program)
Projects
None yet
2 participants