parse-dashboard 7.3.0-alpha.4 → 7.3.0-alpha.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Parse-Dashboard/CLI/mfa.js +4 -1
- package/Parse-Dashboard/app.js +7 -5
- package/Parse-Dashboard/public/bundles/dashboard.bundle.js +1 -1
- package/Parse-Dashboard/public/bundles/login.bundle.js +1 -1
- package/Parse-Dashboard/public/bundles/sprites.svg +12 -0
- package/Parse-Dashboard/public/sw.js +46 -0
- package/README.md +213 -21
- package/package.json +10 -10
|
@@ -321,6 +321,18 @@
|
|
|
321
321
|
<symbol id="rtos" viewBox="0 0 32 29">
|
|
322
322
|
<path d="M22.2507228,5.13932004 C22.2507228,6.01438998 21.5190958,6.72381712 20.6164538,6.72381712 C19.7140006,6.72381712 18.9825623,6.01438998 18.9825623,5.13932004 C18.9825623,4.26425009 19.7140006,3.55482295 20.6164538,3.55482295 C21.5190958,3.55482295 22.2507228,4.26425009 22.2507228,5.13932004 L22.2507228,5.13932004 Z M29.9027937,6.91471817 C27.7237684,5.63423515 24.8185901,5.6982959 23.3659066,6.14653818 L22.7058189,9.53974499 L24.8846555,9.53974499 L24.2904445,12.6130141 L22.1114192,12.6130141 L21.18707,17.286887 C20.7908664,19.2076115 21.8473464,18.82343 22.6397535,18.82343 L22.3096154,20.616033 C16.4990699,23.1131213 15.3765246,19.2716723 15.7066628,17.5429469 L16.6312007,12.6130141 L13.7258336,12.6130141 L14.3200446,9.53974499 L17.2254117,9.53974499 L17.9517535,5.89029514 C15.3765246,5.05805439 15.5747208,4.92993287 15.5747208,2.94514757 L15.5747208,0 L7.84941158,0 L7.84941158,11.6526518 L0.0580370154,11.6526518 C-0.272101176,12.8690741 0.850444177,14.7897986 2.30293896,15.1739801 C3.75562251,15.5581616 4.74603708,18.56737 5.27418268,19.2076115 C5.80251704,19.847853 7.12306981,20.6800938 8.44362257,20.5521553 C9.89630611,18.7593692 10.0943135,18.5033092 10.7545899,18.7593692 C11.1507935,18.82343 11.9432006,19.0154292 12.5374116,18.9515515 C16.3010625,28.6832957 21.1210046,29.899718 24.0263717,28.4911135 C19.8665172,21.5125176 29.176452,18.82343 31.1574699,18.1191277 C31.7516809,16.2624639 31.8177463,13.8294363 31.6195501,12.4208318 C29.3746481,11.332531 29.7047863,8.64344348 29.9027937,6.91471817 L29.9027937,6.91471817 Z M16.648944,17.6611848 L20.1483333,17.6611848 L22.1952278,7.35307679 L18.6297731,7.35307679 L16.648944,17.6611848 L16.648944,17.6611848 Z"/>
|
|
323
323
|
</symbol>
|
|
324
|
+
<symbol id="script-solid" viewBox="0 0 100 100">
|
|
325
|
+
<defs/>
|
|
326
|
+
<path class="st0" d="M50,0C22.4,0,0,22.4,0,50s22.4,50,50,50,50-22.4,50-50S77.6,0,50,0ZM45,32.8h-1.5c-1.4,0-2.4.2-3.1.7-.7.5-1.2,1.2-1.4,2.3-.2.6-.2,2.1-.3,4.6,0,2.5-.3,4.5-.9,5.9-.4,1.1-1.1,2-1.9,2.6-.6.5-1.6,1-3,1.5,1.5.6,2.5,1.2,3.2,1.8.7.6,1.3,1.6,1.8,2.8.5,1.3.8,3.3.8,6.1s.2,4.1.5,4.9c.3.8.8,1.3,1.5,1.6.7.3,2.1.5,4.3.5v9h-4.1c-4.2,0-7.3-.4-9-1.2-1.8-.8-3.1-1.9-3.8-3.5-.8-1.5-1.1-3.8-1.1-6.8s0-1.3,0-2c0-.4,0-.8,0-1.3,0-2.2-.2-3.7-.7-4.6-.5-.9-1.1-1.6-2-2-.9-.4-2.1-.6-3.7-.7v-9.6c1.7,0,2.9-.2,3.8-.7s1.5-1.1,1.9-2c.4-.9.7-2.5.7-4.7v-.9c0-.4,0-.9,0-1.3,0-3.3.3-5.7,1-7.1.6-1.5,1.5-2.6,2.7-3.4.8-.6,2-1,3.5-1.3,1.9-.4,4.1-.6,6.6-.6h4.4v9.1ZM78.5,55.2c-1.6,0-2.9.3-3.7.7-.9.4-1.5,1.1-2,2-.5.9-.7,2.4-.7,4.6s0,.8,0,1.3c0,.7,0,1.3,0,2,0,3-.4,5.3-1.1,6.8-.8,1.5-2,2.7-3.8,3.5-1.8.8-4.8,1.2-9,1.2h-4.1v-9c2.1,0,3.6-.2,4.3-.5.7-.3,1.2-.9,1.5-1.6.3-.8.5-2.4.5-4.9s.2-4.8.8-6.1c.5-1.3,1.1-2.2,1.8-2.8.7-.6,1.8-1.2,3.2-1.8-1.4-.5-2.4-1-3-1.5-.8-.7-1.4-1.5-1.9-2.6-.6-1.4-.9-3.4-.9-5.9,0-2.5-.1-4-.3-4.6-.3-1-.8-1.8-1.4-2.3-.7-.5-1.7-.7-3.1-.7h-1.5v-9.1h4.4c2.5,0,4.7.2,6.6.6,1.5.3,2.6.7,3.5,1.3,1.1.8,2,1.9,2.7,3.4.6,1.5,1,3.8,1,7.1s0,.9,0,1.3v.9c0,2.2.2,3.7.7,4.7.4.9,1.1,1.6,1.9,2s2.1.7,3.8.7v9.6Z"/>
|
|
327
|
+
</symbol>
|
|
328
|
+
<symbol id="script" viewBox="0 0 100 100">
|
|
329
|
+
<defs/>
|
|
330
|
+
<path d="M50,100C22.4,100,0,77.6,0,50S22.4,0,50,0s50,22.4,50,50-22.4,50-50,50ZM50,8.1c-23.1,0-41.9,18.8-41.9,41.9s18.8,41.9,41.9,41.9,41.9-18.8,41.9-41.9S73.1,8.1,50,8.1Z"/>
|
|
331
|
+
<g>
|
|
332
|
+
<path class="st0" d="M45,23.6v9.1h-1.5c-1.4,0-2.4.2-3.1.7-.7.5-1.2,1.2-1.4,2.3-.2.6-.2,2.1-.3,4.6,0,2.5-.3,4.5-.9,5.9-.4,1.1-1.1,2-1.9,2.6-.6.5-1.6,1-3,1.5,1.5.6,2.5,1.2,3.2,1.8.7.6,1.3,1.6,1.8,2.8.5,1.3.8,3.3.8,6.1s.2,4.1.5,4.9c.3.8.8,1.3,1.5,1.6.7.3,2.1.5,4.3.5v9h-4.1c-4.2,0-7.3-.4-9-1.2-1.8-.8-3.1-1.9-3.8-3.5-.8-1.5-1.1-3.8-1.1-6.8s0-1.3,0-2c0-.4,0-.8,0-1.3,0-2.2-.2-3.7-.7-4.6-.5-.9-1.1-1.6-2-2-.9-.4-2.1-.6-3.7-.7v-9.6c1.7,0,2.9-.2,3.8-.7s1.5-1.1,1.9-2c.4-.9.7-2.5.7-4.7v-.9c0-.4,0-.9,0-1.3,0-3.3.3-5.7,1-7.1.6-1.5,1.5-2.6,2.7-3.4.8-.6,2-1,3.5-1.3,1.9-.4,4.1-.6,6.6-.6h4.4Z"/>
|
|
333
|
+
<path class="st0" d="M58.4,23.6c2.5,0,4.7.2,6.6.6,1.5.3,2.6.7,3.5,1.3,1.1.8,2,1.9,2.7,3.4.6,1.5,1,3.8,1,7.1s0,.9,0,1.3v.9c0,2.2.2,3.7.7,4.7.4.9,1.1,1.6,1.9,2s2.1.7,3.8.7v9.6c-1.6,0-2.9.3-3.7.7-.9.4-1.5,1.1-2,2-.5.9-.7,2.4-.7,4.6s0,.8,0,1.3c0,.7,0,1.3,0,2,0,3-.4,5.3-1.1,6.8-.8,1.5-2,2.7-3.8,3.5-1.8.8-4.8,1.2-9,1.2h-4.1v-9c2.1,0,3.6-.2,4.3-.5.7-.3,1.2-.9,1.5-1.6.3-.8.5-2.4.5-4.9s.2-4.8.8-6.1c.5-1.3,1.1-2.2,1.8-2.8.7-.6,1.8-1.2,3.2-1.8-1.4-.5-2.4-1-3-1.5-.8-.7-1.4-1.5-1.9-2.6-.6-1.4-.9-3.4-.9-5.9,0-2.5-.1-4-.3-4.6-.3-1-.8-1.8-1.4-2.3-.7-.5-1.7-.7-3.1-.7h-1.5v-9.1h4.4Z"/>
|
|
334
|
+
</g>
|
|
335
|
+
</symbol>
|
|
324
336
|
<symbol id="search-outline" viewBox="0 0 100 100">
|
|
325
337
|
<path d="M59.038.217c-21.828 0-39.586 17.758-39.586 39.586 0 8.93 2.975 17.175 7.98 23.806L3.472 87.57c-2.794 2.795-2.794 7.324 0 10.118 2.794 2.794 7.323 2.794 10.117 0l24.39-24.39c6.1 3.85 13.32 6.09 21.06 6.09 21.824 0 39.582-17.758 39.582-39.586S80.862.217 59.038.217zm0 69.142C42.74 69.36 29.48 56.1 29.48 39.8s13.26-29.555 29.56-29.555 29.557 13.26 29.557 29.557S75.335 69.36 59.037 69.36z"/>
|
|
326
338
|
</symbol>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const CACHE_NAME = 'dashboard-cache-v1';
|
|
2
|
+
|
|
3
|
+
self.addEventListener('install', () => {
|
|
4
|
+
self.skipWaiting();
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
self.addEventListener('activate', event => {
|
|
8
|
+
event.waitUntil(
|
|
9
|
+
Promise.all([
|
|
10
|
+
self.clients.claim(),
|
|
11
|
+
caches.keys().then(cacheNames => {
|
|
12
|
+
return Promise.all(
|
|
13
|
+
cacheNames.map(cacheName => {
|
|
14
|
+
if (cacheName !== CACHE_NAME) {
|
|
15
|
+
return caches.delete(cacheName);
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
);
|
|
19
|
+
})
|
|
20
|
+
])
|
|
21
|
+
);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
self.addEventListener('fetch', event => {
|
|
25
|
+
const req = event.request;
|
|
26
|
+
if (req.destination === 'script' || req.destination === 'style' || req.url.includes('/bundles/')) {
|
|
27
|
+
event.respondWith(
|
|
28
|
+
caches.match(req).then(cached => {
|
|
29
|
+
return (
|
|
30
|
+
cached ||
|
|
31
|
+
fetch(req).then(resp => {
|
|
32
|
+
const resClone = resp.clone();
|
|
33
|
+
caches.open(CACHE_NAME).then(cache => cache.put(req, resClone));
|
|
34
|
+
return resp;
|
|
35
|
+
})
|
|
36
|
+
);
|
|
37
|
+
})
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
self.addEventListener('message', event => {
|
|
43
|
+
if (event.data === 'unregister') {
|
|
44
|
+
self.registration.unregister();
|
|
45
|
+
}
|
|
46
|
+
});
|
package/README.md
CHANGED
|
@@ -43,6 +43,7 @@ Parse Dashboard is a standalone dashboard for managing your [Parse Server](https
|
|
|
43
43
|
- [Custom order in the filter popup](#custom-order-in-the-filter-popup)
|
|
44
44
|
- [Persistent Filters](#persistent-filters)
|
|
45
45
|
- [Scripts](#scripts)
|
|
46
|
+
- [Resource Cache](#resource-cache)
|
|
46
47
|
- [Running as Express Middleware](#running-as-express-middleware)
|
|
47
48
|
- [Deploying Parse Dashboard](#deploying-parse-dashboard)
|
|
48
49
|
- [Preparing for Deployment](#preparing-for-deployment)
|
|
@@ -61,20 +62,30 @@ Parse Dashboard is a standalone dashboard for managing your [Parse Server](https
|
|
|
61
62
|
- [Data Browser](#data-browser)
|
|
62
63
|
- [Filters](#filters)
|
|
63
64
|
- [Info Panel](#info-panel)
|
|
64
|
-
- [
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
65
|
+
- [Response](#response)
|
|
66
|
+
- [Segments](#segments)
|
|
67
|
+
- [Text Item](#text-item)
|
|
68
|
+
- [Key-Value Item](#key-value-item)
|
|
69
|
+
- [Table Item](#table-item)
|
|
70
|
+
- [Image Item](#image-item)
|
|
71
|
+
- [Video Item](#video-item)
|
|
72
|
+
- [Audio Item](#audio-item)
|
|
73
|
+
- [Button Item](#button-item)
|
|
74
|
+
- [Panel Item](#panel-item)
|
|
75
|
+
- [Prefetching](#prefetching)
|
|
73
76
|
- [Freeze Columns](#freeze-columns)
|
|
74
77
|
- [Browse as User](#browse-as-user)
|
|
75
78
|
- [Change Pointer Key](#change-pointer-key)
|
|
76
79
|
- [Limitations](#limitations)
|
|
77
80
|
- [CSV Export](#csv-export)
|
|
81
|
+
- [Views](#views)
|
|
82
|
+
- [Data Sources](#data-sources)
|
|
83
|
+
- [Aggregation Pipeline](#aggregation-pipeline)
|
|
84
|
+
- [Cloud Function](#cloud-function)
|
|
85
|
+
- [View Table](#view-table)
|
|
86
|
+
- [Pointer](#pointer)
|
|
87
|
+
- [Link](#link)
|
|
88
|
+
- [Image](#image)
|
|
78
89
|
- [Contributing](#contributing)
|
|
79
90
|
|
|
80
91
|
# Getting Started
|
|
@@ -139,6 +150,8 @@ Parse Dashboard is continuously tested with the most recent releases of Node.js
|
|
|
139
150
|
| `infoPanel[*].title` | String | no | - | `User Details` | The panel title. |
|
|
140
151
|
| `infoPanel[*].classes` | Array<String> | no | - | `["_User"]` | The classes for which the info panel should be displayed. |
|
|
141
152
|
| `infoPanel[*].cloudCodeFunction` | String | no | - | `getUserDetails` | The Cloud Code Function which received the selected object in the data browser and returns the response to be displayed in the info panel. |
|
|
153
|
+
| `infoPanel[*].prefetchObjects` | Number | yes | `0` | `2` | Number of next rows to prefetch when browsing sequential rows. For example, `2` means the next 2 rows will be fetched in advance. |
|
|
154
|
+
| `infoPanel[*].prefetchStale` | Number | yes | `0` | `10` | Duration in seconds after which prefetched data is discarded as stale. |
|
|
142
155
|
| `apps.scripts` | Array<Object> | yes | `[]` | `[{ ... }, { ... }]` | The scripts that can be executed for that app. |
|
|
143
156
|
| `apps.scripts.title` | String | no | - | `'Delete User'` | The title that will be displayed in the data browser context menu and the script run confirmation dialog. |
|
|
144
157
|
| `apps.scripts.classes` | Array<String> | no | - | `['_User']` | The classes of Parse Objects for which the scripts can be executed. |
|
|
@@ -444,7 +457,6 @@ You can also specify custom fields with the `scrips` option:
|
|
|
444
457
|
|
|
445
458
|
```
|
|
446
459
|
|
|
447
|
-
|
|
448
460
|
Next, define the Cloud Function in Parse Server that will be called. The object that has been selected in the data browser will be made available as a request parameter:
|
|
449
461
|
|
|
450
462
|
```js
|
|
@@ -505,6 +517,37 @@ Parse.Cloud.define('deleteAccount', async (req) => {
|
|
|
505
517
|
|
|
506
518
|
</details>
|
|
507
519
|
|
|
520
|
+
### Resource Cache
|
|
521
|
+
|
|
522
|
+
Parse Dashboard can cache its resources such as bundles in the browser, so that opening the dashboard in another tab does not reload the dashboard resources from the server but from the local browser cache. Caching only starts after login in the dashboard.
|
|
523
|
+
|
|
524
|
+
| Parameter | Type | Optional | Default | Example | Description |
|
|
525
|
+
|-----------------------|---------|----------|---------|---------|-----------------------------------------------------------------------------------------------------------------------------------------|
|
|
526
|
+
| `enableResourceCache` | Boolean | yes | `false` | `true` | Enables caching of dashboard resources in the browser for faster dashboard loading in additional browser tabs. |
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
Example configuration:
|
|
530
|
+
|
|
531
|
+
```javascript
|
|
532
|
+
const dashboard = new ParseDashboard({
|
|
533
|
+
enableResourceCache: true,
|
|
534
|
+
apps: [
|
|
535
|
+
{
|
|
536
|
+
serverURL: 'http://localhost:1337/parse',
|
|
537
|
+
appId: 'myAppId',
|
|
538
|
+
masterKey: 'myMasterKey',
|
|
539
|
+
appName: 'MyApp'
|
|
540
|
+
}
|
|
541
|
+
]
|
|
542
|
+
});
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
> [!Warning]
|
|
546
|
+
> This feature can make it more difficult to push dashboard updates to users. Enabling the resource cache will start a browser service worker that caches dashboard resources locally only once. As long as the service worker is running, it will prevent loading any dashboard updates from the server, even if the user reloads the browser tab. The service worker is automatically stopped, once the last dashboard browser tab is closed. On the opening of the first dashboard browser tab, a new service worker is started and the dashboard resources are loaded from the server.
|
|
547
|
+
|
|
548
|
+
> [!Note]
|
|
549
|
+
> For developers: during dashboard development, the resource cache should be disabled to ensure reloading the dashboard tab in the browser loads the new dashboard bundle with any changes you made in the source code. You can inspect the service worker in the developer tools of most browsers. For example in Google Chrome, go to *Developer Tools > Application tab > Service workers* to see whether the dashboard service worker is currently running and to debug it.
|
|
550
|
+
|
|
508
551
|
# Running as Express Middleware
|
|
509
552
|
|
|
510
553
|
Instead of starting Parse Dashboard with the CLI, you can also run it as an [express](https://github.com/expressjs/express) middleware.
|
|
@@ -872,7 +915,9 @@ The following example dashboard configuration shows an info panel for the `_User
|
|
|
872
915
|
{
|
|
873
916
|
"title": "User Details",
|
|
874
917
|
"classes": ["_User"],
|
|
875
|
-
"cloudCodeFunction": "getUserDetails"
|
|
918
|
+
"cloudCodeFunction": "getUserDetails",
|
|
919
|
+
"prefetchObjects": 2,
|
|
920
|
+
"prefetchStale": 10
|
|
876
921
|
}
|
|
877
922
|
]
|
|
878
923
|
}
|
|
@@ -881,7 +926,9 @@ The following example dashboard configuration shows an info panel for the `_User
|
|
|
881
926
|
|
|
882
927
|
The Cloud Code Function receives the selected object in the payload and returns a response that can include various items.
|
|
883
928
|
|
|
884
|
-
####
|
|
929
|
+
#### Response
|
|
930
|
+
|
|
931
|
+
##### Segments
|
|
885
932
|
|
|
886
933
|
The info panel can contain multiple segments to display different groups of information.
|
|
887
934
|
|
|
@@ -917,7 +964,7 @@ Example:
|
|
|
917
964
|
|
|
918
965
|
The items array can include various types of content such as text, key-value pairs, tables, images, videos, audios, and buttons. Each type offers a different way to display information within the info panel, allowing for a customizable and rich user experience. Below is a detailed explanation of each type.
|
|
919
966
|
|
|
920
|
-
|
|
967
|
+
##### Text Item
|
|
921
968
|
|
|
922
969
|
A simple text field.
|
|
923
970
|
|
|
@@ -937,7 +984,7 @@ Example:
|
|
|
937
984
|
}
|
|
938
985
|
```
|
|
939
986
|
|
|
940
|
-
|
|
987
|
+
##### Key-Value Item
|
|
941
988
|
|
|
942
989
|
A text item that consists of a key and a value. The value can optionally be linked to a URL.
|
|
943
990
|
|
|
@@ -948,6 +995,7 @@ A text item that consists of a key and a value. The value can optionally be link
|
|
|
948
995
|
| `value` | String | - | No | The value text to display. |
|
|
949
996
|
| `url` | String | `undefined` | Yes | The URL that will be opened in a new browser tab when clicking on the value text. It can be set to an absolute URL or a relative URL in which case the base URL is `<PROTOCOL>://<HOST>/<MOUNT_PATH>/`. |
|
|
950
997
|
| `isRelativeUrl` | Boolean | `false` | Yes | Set this to `true` when linking to another dashboard page, in which case the base URL for the relative URL will be `<PROTOCOL>://<HOST>/<MOUNT_PATH>/apps/<APP_NAME>/`. |
|
|
998
|
+
| `values` | Array | - | Yes | Additional values to display after `value`. Each item is an object with `value`, optional `url` and `isRelativeUrl`. |
|
|
951
999
|
| `style` | Object | - | Yes | The CSS style definition. |
|
|
952
1000
|
|
|
953
1001
|
Examples:
|
|
@@ -980,6 +1028,17 @@ Examples:
|
|
|
980
1028
|
}
|
|
981
1029
|
```
|
|
982
1030
|
|
|
1031
|
+
```json
|
|
1032
|
+
{
|
|
1033
|
+
"type": "keyValue",
|
|
1034
|
+
"key": "Purchase Value",
|
|
1035
|
+
"value": "123",
|
|
1036
|
+
"url": "browser/Purchase",
|
|
1037
|
+
"isRelativeUrl": true,
|
|
1038
|
+
"values": [{ "value": "456" }]
|
|
1039
|
+
}
|
|
1040
|
+
```
|
|
1041
|
+
|
|
983
1042
|
To navigate to a specific object using a relative URL, the query parameters must be URL encoded:
|
|
984
1043
|
|
|
985
1044
|
```js
|
|
@@ -996,7 +1055,7 @@ const item = {
|
|
|
996
1055
|
}
|
|
997
1056
|
```
|
|
998
1057
|
|
|
999
|
-
|
|
1058
|
+
##### Table Item
|
|
1000
1059
|
|
|
1001
1060
|
A table with columns and rows to display data in a structured format.
|
|
1002
1061
|
|
|
@@ -1038,7 +1097,7 @@ Example:
|
|
|
1038
1097
|
}
|
|
1039
1098
|
```
|
|
1040
1099
|
|
|
1041
|
-
|
|
1100
|
+
##### Image Item
|
|
1042
1101
|
|
|
1043
1102
|
An image to be displayed in the panel.
|
|
1044
1103
|
|
|
@@ -1058,7 +1117,7 @@ Example:
|
|
|
1058
1117
|
}
|
|
1059
1118
|
```
|
|
1060
1119
|
|
|
1061
|
-
|
|
1120
|
+
##### Video Item
|
|
1062
1121
|
|
|
1063
1122
|
A video to be displayed in the panel.
|
|
1064
1123
|
|
|
@@ -1078,7 +1137,7 @@ Example:
|
|
|
1078
1137
|
}
|
|
1079
1138
|
```
|
|
1080
1139
|
|
|
1081
|
-
|
|
1140
|
+
##### Audio Item
|
|
1082
1141
|
|
|
1083
1142
|
An audio file to be played in the panel.
|
|
1084
1143
|
|
|
@@ -1098,7 +1157,7 @@ Example:
|
|
|
1098
1157
|
}
|
|
1099
1158
|
```
|
|
1100
1159
|
|
|
1101
|
-
|
|
1160
|
+
##### Button Item
|
|
1102
1161
|
|
|
1103
1162
|
A button that triggers an action when clicked.
|
|
1104
1163
|
|
|
@@ -1133,7 +1192,7 @@ Example:
|
|
|
1133
1192
|
}
|
|
1134
1193
|
```
|
|
1135
1194
|
|
|
1136
|
-
|
|
1195
|
+
##### Panel Item
|
|
1137
1196
|
|
|
1138
1197
|
A sub-panel whose data is loaded on-demand by expanding the item.
|
|
1139
1198
|
|
|
@@ -1155,6 +1214,17 @@ Example:
|
|
|
1155
1214
|
}
|
|
1156
1215
|
```
|
|
1157
1216
|
|
|
1217
|
+
#### Prefetching
|
|
1218
|
+
|
|
1219
|
+
To reduce the time for info panel data to appear, data can be prefetched.
|
|
1220
|
+
|
|
1221
|
+
| Parameter | Type | Optional | Default | Example | Description |
|
|
1222
|
+
|--------------------------------|--------|----------|---------|---------|-----------------------------------------------------------------------------------------------------------------------------------|
|
|
1223
|
+
| `infoPanel[*].prefetchObjects` | Number | yes | `0` | `2` | Number of next rows to prefetch when browsing sequential rows. For example, `2` means the next 2 rows will be fetched in advance. |
|
|
1224
|
+
| `infoPanel[*].prefetchStale` | Number | yes | `0` | `10` | Duration in seconds after which prefetched data is discarded as stale. |
|
|
1225
|
+
|
|
1226
|
+
Prefetching is particularly useful when navigating through lists of objects. To optimize performance and avoid unnecessary data loading, prefetching is triggered only after the user has moved through 3 consecutive rows using the keyboard down-arrow key or by mouse click.
|
|
1227
|
+
|
|
1158
1228
|
### Freeze Columns
|
|
1159
1229
|
|
|
1160
1230
|
▶️ *Core > Browser > Freeze column*
|
|
@@ -1190,6 +1260,128 @@ This feature will take either selected rows or all rows of an individual class a
|
|
|
1190
1260
|
|
|
1191
1261
|
> ⚠️ There is currently a 10,000 row limit when exporting all data. If more than 10,000 rows are present in the class, the CSV file will only contain 10,000 rows.
|
|
1192
1262
|
|
|
1263
|
+
## Views
|
|
1264
|
+
|
|
1265
|
+
▶️ *Core > Views*
|
|
1266
|
+
|
|
1267
|
+
Views are saved queries that display data in a table format. Saved views appear in the sidebar, where you can select, edit, or delete them. Optionally you can enable the object counter to show in the sidebar how many items match the view.
|
|
1268
|
+
|
|
1269
|
+
> [!Caution]
|
|
1270
|
+
> Values are generally rendered without sanitization in the resulting data table. If rendered values come from user input or untrusted data, make sure to remove potentially dangerous HTML or JavaScript, to prevent an attacker from injecting malicious code, to exploit vulnerabilities like Cross-Site Scripting (XSS).
|
|
1271
|
+
|
|
1272
|
+
### Data Sources
|
|
1273
|
+
|
|
1274
|
+
Views can pull their data from the following data sources.
|
|
1275
|
+
|
|
1276
|
+
#### Aggregation Pipeline
|
|
1277
|
+
|
|
1278
|
+
Display aggregated data from your classes using a MongoDB aggregation pipeline. Create a view by selecting a class and defining an aggregation pipeline.
|
|
1279
|
+
|
|
1280
|
+
#### Cloud Function
|
|
1281
|
+
|
|
1282
|
+
Display data returned by a Parse Cloud Function. Create a view specifying a Cloud Function that returns an array of objects. Cloud Functions enable custom business logic, computed fields, and complex data transformations.
|
|
1283
|
+
|
|
1284
|
+
Cloud Function views can prompt users for text input and/or file upload when opened. Enable "Require text input" or "Require file upload" checkboxes when creating the view. The user provided data will then be available in the Cloud Function as parameters.
|
|
1285
|
+
|
|
1286
|
+
Cloud Function example:
|
|
1287
|
+
|
|
1288
|
+
```js
|
|
1289
|
+
Parse.Cloud.define("myViewFunction", request => {
|
|
1290
|
+
const text = request.params.text;
|
|
1291
|
+
const fileData = request.params.fileData;
|
|
1292
|
+
return processDataWithTextAndFile(text, fileData);
|
|
1293
|
+
});
|
|
1294
|
+
```
|
|
1295
|
+
|
|
1296
|
+
> [!Note]
|
|
1297
|
+
> Text and file data are ephemeral and only available to the Cloud Function during that request. Files are base64 encoded, increasing the data during transfer by ~33%.
|
|
1298
|
+
|
|
1299
|
+
### View Table
|
|
1300
|
+
|
|
1301
|
+
When designing the aggregation pipeline, consider that some values are rendered specially in the output table.
|
|
1302
|
+
|
|
1303
|
+
#### Pointer
|
|
1304
|
+
|
|
1305
|
+
Parse Object pointers are automatically displayed as links to the target object.
|
|
1306
|
+
|
|
1307
|
+
Example:
|
|
1308
|
+
|
|
1309
|
+
```json
|
|
1310
|
+
{ "__type": "Pointer", "className": "_User", "objectId": "xWMyZ4YEGZ" }
|
|
1311
|
+
```
|
|
1312
|
+
|
|
1313
|
+
#### Link
|
|
1314
|
+
|
|
1315
|
+
Links are rendered as hyperlinks that open in a new browser tab.
|
|
1316
|
+
|
|
1317
|
+
Example:
|
|
1318
|
+
|
|
1319
|
+
```json
|
|
1320
|
+
{
|
|
1321
|
+
"__type": "Link",
|
|
1322
|
+
"url": "https://example.com",
|
|
1323
|
+
"text": "Link"
|
|
1324
|
+
}
|
|
1325
|
+
```
|
|
1326
|
+
|
|
1327
|
+
Set `isRelativeUrl: true` when linking to another dashboard page, in which case the base URL for the relative URL will be `<PROTOCOL>://<HOST>/<MOUNT_PATH>/apps/<APP_NAME>/`. The key `isRelativeUrl` is optional and `false` by default.
|
|
1328
|
+
|
|
1329
|
+
Example:
|
|
1330
|
+
|
|
1331
|
+
```json
|
|
1332
|
+
{
|
|
1333
|
+
"__type": "Link",
|
|
1334
|
+
"url": "browser/_Installation",
|
|
1335
|
+
"isRelativeUrl": true,
|
|
1336
|
+
"text": "Link"
|
|
1337
|
+
}
|
|
1338
|
+
```
|
|
1339
|
+
|
|
1340
|
+
A query part of the URL can be easily added using the `urlQuery` key which will automatically escape the query string.
|
|
1341
|
+
|
|
1342
|
+
Example:
|
|
1343
|
+
|
|
1344
|
+
```json
|
|
1345
|
+
{
|
|
1346
|
+
"__type": "Link",
|
|
1347
|
+
"url": "browser/_Installation",
|
|
1348
|
+
"urlQuery": "filters=[{\"field\":\"objectId\",\"constraint\":\"eq\",\"compareTo\":\"xWMyZ4YEGZ\",\"class\":\"_Installation\"}]",
|
|
1349
|
+
"isRelativeUrl": true,
|
|
1350
|
+
"text": "Link"
|
|
1351
|
+
}
|
|
1352
|
+
```
|
|
1353
|
+
|
|
1354
|
+
In the example above, the query string will be escaped and added to the url, resulting in the complete URL:
|
|
1355
|
+
|
|
1356
|
+
```js
|
|
1357
|
+
"browser/_Installation?filters=%5B%7B%22field%22%3A%22objectId%22%2C%22constraint%22%3A%22eq%22%2C%22compareTo%22%3A%22xWMyZ4YEGZ%22%2C%22class%22%3A%22_Installation%22%7D%5D"
|
|
1358
|
+
```
|
|
1359
|
+
|
|
1360
|
+
> [!Tip]
|
|
1361
|
+
> For guidance on how to create the URL query for a dashboard data browser filter, open the data browser and set the filter. Then copy the browser URL and unescape it. The query constraints in `?filters=[...]` will give you an idea of the constraint syntax.
|
|
1362
|
+
|
|
1363
|
+
> [!Note]
|
|
1364
|
+
> 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.
|
|
1365
|
+
|
|
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
|
+
|
|
1193
1385
|
# Contributing
|
|
1194
1386
|
|
|
1195
1387
|
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).
|
|
@@ -1200,4 +1392,4 @@ As of April 5, 2017, Parse, LLC has transferred this code to the parse-community
|
|
|
1200
1392
|
|
|
1201
1393
|
[license-svg]: https://img.shields.io/badge/license-BSD-lightgrey.svg
|
|
1202
1394
|
[license-link]: LICENSE
|
|
1203
|
-
[open-collective-link]: https://opencollective.com/parse-server
|
|
1395
|
+
[open-collective-link]: https://opencollective.com/parse-server
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "parse-dashboard",
|
|
3
|
-
"version": "7.3.0-alpha.
|
|
3
|
+
"version": "7.3.0-alpha.41",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/parse-community/parse-dashboard"
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"body-parser": "2.2.0",
|
|
42
42
|
"commander": "13.1.0",
|
|
43
43
|
"connect-flash": "0.1.1",
|
|
44
|
-
"cookie-session": "2.1.
|
|
44
|
+
"cookie-session": "2.1.1",
|
|
45
45
|
"copy-to-clipboard": "3.3.3",
|
|
46
46
|
"core-js": "3.42.0",
|
|
47
47
|
"csurf": "1.11.0",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"fast-deep-equal": "3.1.3",
|
|
50
50
|
"graphiql": "2.0.8",
|
|
51
51
|
"graphql": "16.11.0",
|
|
52
|
-
"immutable": "5.1.
|
|
52
|
+
"immutable": "5.1.3",
|
|
53
53
|
"immutable-devtools": "0.1.5",
|
|
54
54
|
"inquirer": "12.6.3",
|
|
55
55
|
"js-beautify": "1.15.4",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"react-dnd": "10.0.2",
|
|
67
67
|
"react-dnd-html5-backend": "16.0.1",
|
|
68
68
|
"react-dom": "16.14.0",
|
|
69
|
-
"react-draggable": "4.
|
|
69
|
+
"react-draggable": "4.5.0",
|
|
70
70
|
"react-helmet": "6.1.0",
|
|
71
71
|
"react-json-view": "1.21.3",
|
|
72
72
|
"react-popper-tooltip": "4.4.2",
|
|
@@ -79,10 +79,10 @@
|
|
|
79
79
|
"@babel/core": "7.27.4",
|
|
80
80
|
"@babel/eslint-parser": "7.28.0",
|
|
81
81
|
"@babel/plugin-proposal-decorators": "7.27.1",
|
|
82
|
-
"@babel/plugin-transform-runtime": "7.
|
|
82
|
+
"@babel/plugin-transform-runtime": "7.28.0",
|
|
83
83
|
"@babel/preset-env": "7.27.2",
|
|
84
84
|
"@babel/preset-react": "7.27.1",
|
|
85
|
-
"@eslint/compat": "1.
|
|
85
|
+
"@eslint/compat": "1.3.1",
|
|
86
86
|
"@saithodev/semantic-release-backmerge": "4.0.1",
|
|
87
87
|
"@semantic-release/changelog": "6.0.3",
|
|
88
88
|
"@semantic-release/commit-analyzer": "13.0.1",
|
|
@@ -106,13 +106,13 @@
|
|
|
106
106
|
"marked": "15.0.12",
|
|
107
107
|
"null-loader": "4.0.1",
|
|
108
108
|
"prettier": "3.5.3",
|
|
109
|
-
"puppeteer": "24.
|
|
109
|
+
"puppeteer": "24.12.1",
|
|
110
110
|
"react-test-renderer": "16.13.1",
|
|
111
111
|
"request": "2.88.2",
|
|
112
|
-
"request-promise": "4.2.
|
|
113
|
-
"sass": "1.89.
|
|
112
|
+
"request-promise": "4.2.6",
|
|
113
|
+
"sass": "1.89.2",
|
|
114
114
|
"sass-loader": "13.2.0",
|
|
115
|
-
"semantic-release": "24.2.
|
|
115
|
+
"semantic-release": "24.2.7",
|
|
116
116
|
"semver": "7.7.2",
|
|
117
117
|
"style-loader": "3.3.1",
|
|
118
118
|
"svg-prep": "1.0.4",
|