parse-dashboard 8.5.0-alpha.6 → 8.5.0
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/public/bundles/221.bundle.js +1 -1
- package/Parse-Dashboard/public/bundles/448.bundle.js +1 -1
- package/Parse-Dashboard/public/bundles/584.bundle.js +1 -1
- package/Parse-Dashboard/public/bundles/75.bundle.js +1 -1
- package/Parse-Dashboard/public/bundles/dashboard.bundle.js +1 -1
- package/Parse-Dashboard/public/bundles/login.bundle.js +1 -1
- package/README.md +190 -105
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -51,7 +51,6 @@ Parse Dashboard is a standalone dashboard for managing your [Parse Server](https
|
|
|
51
51
|
- [Custom order in the filter popup](#custom-order-in-the-filter-popup)
|
|
52
52
|
- [Persistent Filters](#persistent-filters)
|
|
53
53
|
- [Keyboard Shortcuts](#keyboard-shortcuts)
|
|
54
|
-
- [Scripts](#scripts)
|
|
55
54
|
- [Resource Cache](#resource-cache)
|
|
56
55
|
- [Running as Express Middleware](#running-as-express-middleware)
|
|
57
56
|
- [Browser Control API (Development Only)](#browser-control-api-development-only)
|
|
@@ -88,6 +87,11 @@ Parse Dashboard is a standalone dashboard for managing your [Parse Server](https
|
|
|
88
87
|
- [Panel Item](#panel-item)
|
|
89
88
|
- [Auto-Scroll](#auto-scroll)
|
|
90
89
|
- [Prefetching](#prefetching)
|
|
90
|
+
- [Scripts](#scripts)
|
|
91
|
+
- [Script Response Form](#script-response-form)
|
|
92
|
+
- [Response Fields](#response-fields)
|
|
93
|
+
- [Form Elements](#form-elements)
|
|
94
|
+
- [Drop-Down](#drop-down)
|
|
91
95
|
- [Graph](#graph)
|
|
92
96
|
- [Calculated Values](#calculated-values)
|
|
93
97
|
- [Formula Operator](#formula-operator)
|
|
@@ -550,110 +554,6 @@ Configure custom keyboard shortcuts for dashboard actions in **App Settings > Ke
|
|
|
550
554
|
|
|
551
555
|
Delete a shortcut key to disable the shortcut.
|
|
552
556
|
|
|
553
|
-
### Scripts
|
|
554
|
-
|
|
555
|
-
You can specify scripts to execute Cloud Functions with the `scripts` option:
|
|
556
|
-
|
|
557
|
-
```json
|
|
558
|
-
"apps": [
|
|
559
|
-
{
|
|
560
|
-
"scripts": [
|
|
561
|
-
{
|
|
562
|
-
"title": "Delete Account",
|
|
563
|
-
"classes": ["_User"],
|
|
564
|
-
"cloudCodeFunction": "deleteAccount",
|
|
565
|
-
"showConfirmationDialog": true,
|
|
566
|
-
"confirmationDialogStyle": "critical"
|
|
567
|
-
}
|
|
568
|
-
]
|
|
569
|
-
}
|
|
570
|
-
]
|
|
571
|
-
```
|
|
572
|
-
|
|
573
|
-
You can also specify custom fields with the `scrips` option:
|
|
574
|
-
|
|
575
|
-
```json
|
|
576
|
-
"apps": [
|
|
577
|
-
{
|
|
578
|
-
"scripts": [
|
|
579
|
-
{
|
|
580
|
-
"title": "Delete account",
|
|
581
|
-
"classes": [
|
|
582
|
-
{
|
|
583
|
-
"name": "_User",
|
|
584
|
-
"fields": [
|
|
585
|
-
{ "name": "createdAt", "validator": "value => value > new Date(\"2025\")" }
|
|
586
|
-
]
|
|
587
|
-
}
|
|
588
|
-
],
|
|
589
|
-
"cloudCodeFunction": "deleteAccount"
|
|
590
|
-
}
|
|
591
|
-
]
|
|
592
|
-
}
|
|
593
|
-
]
|
|
594
|
-
|
|
595
|
-
```
|
|
596
|
-
|
|
597
|
-
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:
|
|
598
|
-
|
|
599
|
-
```js
|
|
600
|
-
Parse.Cloud.define('deleteAccount', async (req) => {
|
|
601
|
-
req.params.object.set('deleted', true);
|
|
602
|
-
await req.params.object.save(null, {useMasterKey: true});
|
|
603
|
-
}, {
|
|
604
|
-
requireMaster: true
|
|
605
|
-
});
|
|
606
|
-
```
|
|
607
|
-
|
|
608
|
-
The field which the script was invoked on can be accessed by `selectedField`:
|
|
609
|
-
|
|
610
|
-
```js
|
|
611
|
-
Parse.Cloud.define('deleteAccount', async (req) => {
|
|
612
|
-
if (req.params.selectedField !== 'objectId') {
|
|
613
|
-
throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Deleting accounts is only available on the objectId field.');
|
|
614
|
-
}
|
|
615
|
-
req.params.object.set('deleted', true);
|
|
616
|
-
await req.params.object.save(null, {useMasterKey: true});
|
|
617
|
-
}, {
|
|
618
|
-
requireMaster: true
|
|
619
|
-
});
|
|
620
|
-
```
|
|
621
|
-
|
|
622
|
-
⚠️ Depending on your Parse Server version you may need to set the Parse Server option `encodeParseObjectInCloudFunction` to `true` so that the selected object in the data browser is made available in the Cloud Function as an instance of `Parse.Object`. If the option is not set, is set to `false`, or you are using an older version of Parse Server, the object is made available as a plain JavaScript object and needs to be converted from a JSON object to a `Parse.Object` instance with `req.params.object = Parse.Object.fromJSON(req.params.object);`, before you can call any `Parse.Object` properties and methods on it.
|
|
623
|
-
|
|
624
|
-
For older versions of Parse Server:
|
|
625
|
-
|
|
626
|
-
<details>
|
|
627
|
-
<summary>Parse Server >=4.4.0 <6.2.0</summary>
|
|
628
|
-
|
|
629
|
-
```js
|
|
630
|
-
Parse.Cloud.define('deleteAccount', async (req) => {
|
|
631
|
-
req.params.object = Parse.Object.fromJSON(req.params.object);
|
|
632
|
-
req.params.object.set('deleted', true);
|
|
633
|
-
await req.params.object.save(null, {useMasterKey: true});
|
|
634
|
-
}, {
|
|
635
|
-
requireMaster: true
|
|
636
|
-
});
|
|
637
|
-
```
|
|
638
|
-
|
|
639
|
-
</details>
|
|
640
|
-
|
|
641
|
-
<details>
|
|
642
|
-
<summary>Parse Server >=2.1.4 <4.4.0</summary>
|
|
643
|
-
|
|
644
|
-
```js
|
|
645
|
-
Parse.Cloud.define('deleteAccount', async (req) => {
|
|
646
|
-
if (!req.master || !req.params.object) {
|
|
647
|
-
throw 'Unauthorized';
|
|
648
|
-
}
|
|
649
|
-
req.params.object = Parse.Object.fromJSON(req.params.object);
|
|
650
|
-
req.params.object.set('deleted', true);
|
|
651
|
-
await req.params.object.save(null, {useMasterKey: true});
|
|
652
|
-
});
|
|
653
|
-
```
|
|
654
|
-
|
|
655
|
-
</details>
|
|
656
|
-
|
|
657
557
|
### Resource Cache
|
|
658
558
|
|
|
659
559
|
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.
|
|
@@ -1480,6 +1380,191 @@ Prefetching is particularly useful when navigating through lists of objects. To
|
|
|
1480
1380
|
|
|
1481
1381
|
When `prefetchObjects` is enabled, media content (images, videos, and audio) in the info panel can also be prefetched to improve loading performance. By default, all media types are prefetched, but you can selectively disable prefetching for specific media types using the `prefetchImage`, `prefetchVideo`, and `prefetchAudio` options.
|
|
1482
1382
|
|
|
1383
|
+
### Scripts
|
|
1384
|
+
|
|
1385
|
+
You can specify scripts to execute Cloud Functions with the `scripts` option:
|
|
1386
|
+
|
|
1387
|
+
```json
|
|
1388
|
+
"apps": [
|
|
1389
|
+
{
|
|
1390
|
+
"scripts": [
|
|
1391
|
+
{
|
|
1392
|
+
"title": "Delete Account",
|
|
1393
|
+
"classes": ["_User"],
|
|
1394
|
+
"cloudCodeFunction": "deleteAccount",
|
|
1395
|
+
"showConfirmationDialog": true,
|
|
1396
|
+
"confirmationDialogStyle": "critical"
|
|
1397
|
+
}
|
|
1398
|
+
]
|
|
1399
|
+
}
|
|
1400
|
+
]
|
|
1401
|
+
```
|
|
1402
|
+
|
|
1403
|
+
You can also specify custom fields with the `scripts` option:
|
|
1404
|
+
|
|
1405
|
+
```json
|
|
1406
|
+
"apps": [
|
|
1407
|
+
{
|
|
1408
|
+
"scripts": [
|
|
1409
|
+
{
|
|
1410
|
+
"title": "Delete account",
|
|
1411
|
+
"classes": [
|
|
1412
|
+
{
|
|
1413
|
+
"name": "_User",
|
|
1414
|
+
"fields": [
|
|
1415
|
+
{ "name": "createdAt", "validator": "value => value > new Date(\"2025\")" }
|
|
1416
|
+
]
|
|
1417
|
+
}
|
|
1418
|
+
],
|
|
1419
|
+
"cloudCodeFunction": "deleteAccount"
|
|
1420
|
+
}
|
|
1421
|
+
]
|
|
1422
|
+
}
|
|
1423
|
+
]
|
|
1424
|
+
|
|
1425
|
+
```
|
|
1426
|
+
|
|
1427
|
+
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:
|
|
1428
|
+
|
|
1429
|
+
```js
|
|
1430
|
+
Parse.Cloud.define('deleteAccount', async (req) => {
|
|
1431
|
+
req.params.object.set('deleted', true);
|
|
1432
|
+
await req.params.object.save(null, {useMasterKey: true});
|
|
1433
|
+
}, {
|
|
1434
|
+
requireMaster: true
|
|
1435
|
+
});
|
|
1436
|
+
```
|
|
1437
|
+
|
|
1438
|
+
The field which the script was invoked on can be accessed by `selectedField`:
|
|
1439
|
+
|
|
1440
|
+
```js
|
|
1441
|
+
Parse.Cloud.define('deleteAccount', async (req) => {
|
|
1442
|
+
if (req.params.selectedField !== 'objectId') {
|
|
1443
|
+
throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Deleting accounts is only available on the objectId field.');
|
|
1444
|
+
}
|
|
1445
|
+
req.params.object.set('deleted', true);
|
|
1446
|
+
await req.params.object.save(null, {useMasterKey: true});
|
|
1447
|
+
}, {
|
|
1448
|
+
requireMaster: true
|
|
1449
|
+
});
|
|
1450
|
+
```
|
|
1451
|
+
|
|
1452
|
+
⚠️ Depending on your Parse Server version you may need to set the Parse Server option `encodeParseObjectInCloudFunction` to `true` so that the selected object in the data browser is made available in the Cloud Function as an instance of `Parse.Object`. If the option is not set, is set to `false`, or you are using an older version of Parse Server, the object is made available as a plain JavaScript object and needs to be converted from a JSON object to a `Parse.Object` instance with `req.params.object = Parse.Object.fromJSON(req.params.object);`, before you can call any `Parse.Object` properties and methods on it.
|
|
1453
|
+
|
|
1454
|
+
For older versions of Parse Server:
|
|
1455
|
+
|
|
1456
|
+
<details>
|
|
1457
|
+
<summary>Parse Server >=4.4.0 <6.2.0</summary>
|
|
1458
|
+
|
|
1459
|
+
```js
|
|
1460
|
+
Parse.Cloud.define('deleteAccount', async (req) => {
|
|
1461
|
+
req.params.object = Parse.Object.fromJSON(req.params.object);
|
|
1462
|
+
req.params.object.set('deleted', true);
|
|
1463
|
+
await req.params.object.save(null, {useMasterKey: true});
|
|
1464
|
+
}, {
|
|
1465
|
+
requireMaster: true
|
|
1466
|
+
});
|
|
1467
|
+
```
|
|
1468
|
+
|
|
1469
|
+
</details>
|
|
1470
|
+
|
|
1471
|
+
<details>
|
|
1472
|
+
<summary>Parse Server >=2.1.4 <4.4.0</summary>
|
|
1473
|
+
|
|
1474
|
+
```js
|
|
1475
|
+
Parse.Cloud.define('deleteAccount', async (req) => {
|
|
1476
|
+
if (!req.master || !req.params.object) {
|
|
1477
|
+
throw 'Unauthorized';
|
|
1478
|
+
}
|
|
1479
|
+
req.params.object = Parse.Object.fromJSON(req.params.object);
|
|
1480
|
+
req.params.object.set('deleted', true);
|
|
1481
|
+
await req.params.object.save(null, {useMasterKey: true});
|
|
1482
|
+
});
|
|
1483
|
+
```
|
|
1484
|
+
|
|
1485
|
+
</details>
|
|
1486
|
+
|
|
1487
|
+
#### Script Response Form
|
|
1488
|
+
|
|
1489
|
+
A Cloud Function invoked by a script can return a structured response that shows a modal dialog with form elements. When the user submits the form, the values are sent to a callback Cloud Function specified in the response.
|
|
1490
|
+
|
|
1491
|
+
Return a `ScriptResponse` from the Cloud Function:
|
|
1492
|
+
|
|
1493
|
+
```js
|
|
1494
|
+
Parse.Cloud.define('assignRole', async (req) => {
|
|
1495
|
+
return {
|
|
1496
|
+
__type: 'ScriptResponse',
|
|
1497
|
+
payload: {
|
|
1498
|
+
requestId: '123-456-789'
|
|
1499
|
+
},
|
|
1500
|
+
form: {
|
|
1501
|
+
title: 'Assign Role',
|
|
1502
|
+
icon: 'gears',
|
|
1503
|
+
cloudCodeFunction: 'assignRoleCallback',
|
|
1504
|
+
elements: [
|
|
1505
|
+
{
|
|
1506
|
+
element: 'dropDown',
|
|
1507
|
+
name: 'role',
|
|
1508
|
+
label: 'Role',
|
|
1509
|
+
items: [
|
|
1510
|
+
{ title: 'Admin', value: 'admin' },
|
|
1511
|
+
{ title: 'User', value: 'user' }
|
|
1512
|
+
]
|
|
1513
|
+
}
|
|
1514
|
+
]
|
|
1515
|
+
}
|
|
1516
|
+
};
|
|
1517
|
+
}, {
|
|
1518
|
+
requireMaster: true
|
|
1519
|
+
});
|
|
1520
|
+
```
|
|
1521
|
+
|
|
1522
|
+
Then define the callback Cloud Function that receives the form data:
|
|
1523
|
+
|
|
1524
|
+
```js
|
|
1525
|
+
Parse.Cloud.define('assignRoleCallback', async (req) => {
|
|
1526
|
+
const { object, payload, formData } = req.params;
|
|
1527
|
+
const role = formData.role;
|
|
1528
|
+
object.set('role', role);
|
|
1529
|
+
await object.save(null, { useMasterKey: true });
|
|
1530
|
+
return `Assigned role "${role}" to ${object.id} (request ${payload.requestId}).`;
|
|
1531
|
+
}, {
|
|
1532
|
+
requireMaster: true
|
|
1533
|
+
});
|
|
1534
|
+
```
|
|
1535
|
+
|
|
1536
|
+
> [!NOTE]
|
|
1537
|
+
> When executing a script on multiple selected rows, the Cloud Function is called for the first object. If the response is a `ScriptResponse`, the modal is shown once. On submission, the callback Cloud Function is called for all selected objects.
|
|
1538
|
+
|
|
1539
|
+
##### Response Fields
|
|
1540
|
+
|
|
1541
|
+
| Field | Type | Optional | Default | Description |
|
|
1542
|
+
|---|---|---|---|---|
|
|
1543
|
+
| `__type` | `String` | No | - | Must be `"ScriptResponse"` to indicate a structured response. |
|
|
1544
|
+
| `payload` | `Object` | Yes | - | Pass-through data forwarded to the callback Cloud Function. |
|
|
1545
|
+
| `form.title` | `String` | Yes | `"Script"` | The modal title. |
|
|
1546
|
+
| `form.icon` | `String` | Yes | `"gears"` | The modal icon. |
|
|
1547
|
+
| `form.cloudCodeFunction` | `String` | Yes | Script `cloudCodeFunction` | The callback Cloud Function to invoke on form submission. |
|
|
1548
|
+
| `form.elements` | `Array` | No | - | The form elements to display in the modal. |
|
|
1549
|
+
|
|
1550
|
+
##### Form Elements
|
|
1551
|
+
|
|
1552
|
+
| Parameter | Value | Optional | Description |
|
|
1553
|
+
|-----------|--------|----------|----------------------------------|
|
|
1554
|
+
| `elements` | `Array` | No | The form elements. Elements are rendered in the order they are defined. |
|
|
1555
|
+
|
|
1556
|
+
###### Drop-Down
|
|
1557
|
+
|
|
1558
|
+
A drop-down to select a single item from a list.
|
|
1559
|
+
|
|
1560
|
+
| Parameter | Value | Optional | Description |
|
|
1561
|
+
|-----------|--------|----------|----------------------------------|
|
|
1562
|
+
| `element` | `String` | No | Must be `"dropDown"`. |
|
|
1563
|
+
| `label` | `String` | No | The display label shown next to the dropdown. |
|
|
1564
|
+
| `items` | `Array` | No | The selectable options. |
|
|
1565
|
+
| `items[].title` | `String` | No | The display text of the option. |
|
|
1566
|
+
| `items[].value` | `String` | No | The value of the option. |
|
|
1567
|
+
|
|
1483
1568
|
### Graph
|
|
1484
1569
|
|
|
1485
1570
|
▶️ *Core > Browser > Graph*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "parse-dashboard",
|
|
3
|
-
"version": "8.5.0
|
|
3
|
+
"version": "8.5.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/parse-community/parse-dashboard"
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@actions/core": "2.0.1",
|
|
86
86
|
"@babel/core": "7.29.0",
|
|
87
|
-
"@babel/eslint-parser": "7.28.
|
|
87
|
+
"@babel/eslint-parser": "7.28.6",
|
|
88
88
|
"@babel/plugin-proposal-decorators": "7.29.0",
|
|
89
89
|
"@babel/plugin-transform-runtime": "7.29.0",
|
|
90
90
|
"@babel/preset-env": "7.29.0",
|
|
@@ -101,11 +101,11 @@
|
|
|
101
101
|
"all-node-versions": "13.0.1",
|
|
102
102
|
"babel-loader": "10.0.0",
|
|
103
103
|
"css-loader": "6.7.3",
|
|
104
|
-
"eslint": "9.39.
|
|
104
|
+
"eslint": "9.39.2",
|
|
105
105
|
"eslint-plugin-jest": "29.5.0",
|
|
106
106
|
"eslint-plugin-react": "7.37.5",
|
|
107
107
|
"get-port": "7.1.0",
|
|
108
|
-
"globals": "
|
|
108
|
+
"globals": "17.3.0",
|
|
109
109
|
"http-server": "14.1.1",
|
|
110
110
|
"husky": "9.1.7",
|
|
111
111
|
"jest": "30.0.4",
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
"null-loader": "4.0.1",
|
|
117
117
|
"parse-server": "9.2.0",
|
|
118
118
|
"prettier": "3.8.1",
|
|
119
|
-
"puppeteer": "24.
|
|
119
|
+
"puppeteer": "24.37.2",
|
|
120
120
|
"react-test-renderer": "16.13.1",
|
|
121
121
|
"request": "2.88.2",
|
|
122
122
|
"request-promise": "4.2.6",
|
|
@@ -127,9 +127,9 @@
|
|
|
127
127
|
"style-loader": "3.3.1",
|
|
128
128
|
"svg-prep": "1.0.4",
|
|
129
129
|
"typescript": "5.9.3",
|
|
130
|
-
"webpack": "5.
|
|
130
|
+
"webpack": "5.105.1",
|
|
131
131
|
"webpack-cli": "6.0.1",
|
|
132
|
-
"ws": "8.
|
|
132
|
+
"ws": "8.19.0",
|
|
133
133
|
"yaml": "2.8.2"
|
|
134
134
|
},
|
|
135
135
|
"scripts": {
|