@mongoosejs/studio 0.0.32 → 0.0.33
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/backend/actions/Dashboard/getDashboard.js +2 -20
- package/backend/actions/Dashboard/updateDashboard.js +26 -19
- package/backend/db/dashboardSchema.js +27 -1
- package/frontend/public/app.js +12 -8
- package/frontend/src/dashboard/dashboard.html +5 -1
- package/frontend/src/dashboard/dashboard.js +4 -3
- package/frontend/src/dashboard/edit-dashboard/edit-dashboard.js +5 -2
- package/frontend/src/dashboards/dashboards.html +2 -2
- package/frontend/src/routes.js +1 -1
- package/package.json +1 -1
|
@@ -19,23 +19,9 @@ module.exports = ({ db }) => async function getDashboard(params) {
|
|
|
19
19
|
|
|
20
20
|
const dashboard = await Dashboard.findOne({ _id: dashboardId });
|
|
21
21
|
if (evaluate) {
|
|
22
|
-
const context = vm.createContext({ db });
|
|
23
22
|
let result = null;
|
|
24
23
|
try {
|
|
25
|
-
result = await
|
|
26
|
-
if (result.$document?.model) {
|
|
27
|
-
let schemaPaths = {};
|
|
28
|
-
const Model = Dashboard.db.model(result.$document?.model);
|
|
29
|
-
for (const path of Object.keys(Model.schema.paths)) {
|
|
30
|
-
schemaPaths[path] = {
|
|
31
|
-
instance: Model.schema.paths[path].instance,
|
|
32
|
-
path,
|
|
33
|
-
ref: Model.schema.paths[path].options?.ref,
|
|
34
|
-
required: Model.schema.paths[path].options?.required
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
result.$document.schemaPaths = schemaPaths;
|
|
38
|
-
}
|
|
24
|
+
result = await dashboard.evaluate();
|
|
39
25
|
} catch (error) {
|
|
40
26
|
return { dashboard, error: { message: error.message } };
|
|
41
27
|
}
|
|
@@ -44,8 +30,4 @@ module.exports = ({ db }) => async function getDashboard(params) {
|
|
|
44
30
|
}
|
|
45
31
|
|
|
46
32
|
return { dashboard };
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
const formatFunction = code => `(async function() {
|
|
50
|
-
${code}
|
|
51
|
-
})();`
|
|
33
|
+
};
|
|
@@ -3,23 +3,30 @@
|
|
|
3
3
|
const Archetype = require('archetype');
|
|
4
4
|
|
|
5
5
|
const UpdateDashboardParams = new Archetype({
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
6
|
+
dashboardId: {
|
|
7
|
+
$type: 'string',
|
|
8
|
+
$required: true
|
|
9
|
+
},
|
|
10
|
+
code: {
|
|
11
|
+
$type: 'string',
|
|
12
|
+
$required: true
|
|
13
|
+
}
|
|
14
|
+
}).compile('UpdateDashboardParams');
|
|
15
|
+
|
|
16
|
+
module.exports = ({ db }) => async function updateDashboard(params) {
|
|
17
|
+
const { dashboardId, code } = new UpdateDashboardParams(params);
|
|
18
|
+
|
|
19
|
+
const Dashboard = db.models[`__Studio_Dashboard`];
|
|
20
|
+
|
|
21
|
+
const doc = await Dashboard.
|
|
22
|
+
findByIdAndUpdate(dashboardId, { code }, { sanitizeFilter: true, returnDocument: 'after', overwriteImmutable: true });
|
|
18
23
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
let result = null;
|
|
25
|
+
try {
|
|
26
|
+
result = await doc.evaluate();
|
|
27
|
+
} catch (error) {
|
|
28
|
+
return { doc, error: { message: error.message } };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return { doc, result };
|
|
32
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const mongoose = require('mongoose');
|
|
4
|
+
const vm = require('vm');
|
|
4
5
|
|
|
5
6
|
const dashboardSchema = new mongoose.Schema({
|
|
6
7
|
title: {
|
|
@@ -16,4 +17,29 @@ const dashboardSchema = new mongoose.Schema({
|
|
|
16
17
|
}
|
|
17
18
|
});
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
dashboardSchema.methods.evaluate = async function evaluate() {
|
|
21
|
+
const context = vm.createContext({ db: this.constructor.db });
|
|
22
|
+
let result = null;
|
|
23
|
+
result = await vm.runInContext(formatFunction(this.code), context);
|
|
24
|
+
if (result.$document?.model) {
|
|
25
|
+
let schemaPaths = {};
|
|
26
|
+
const Model = this.constructor.db.model(result.$document?.model);
|
|
27
|
+
for (const path of Object.keys(Model.schema.paths)) {
|
|
28
|
+
schemaPaths[path] = {
|
|
29
|
+
instance: Model.schema.paths[path].instance,
|
|
30
|
+
path,
|
|
31
|
+
ref: Model.schema.paths[path].options?.ref,
|
|
32
|
+
required: Model.schema.paths[path].options?.required
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
result.$document.schemaPaths = schemaPaths;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
module.exports = dashboardSchema;
|
|
42
|
+
|
|
43
|
+
const formatFunction = code => `(async function() {
|
|
44
|
+
${code}
|
|
45
|
+
})();`
|
package/frontend/public/app.js
CHANGED
|
@@ -462,6 +462,7 @@ const template = __webpack_require__(/*! ./dashboard.html */ "./frontend/src/das
|
|
|
462
462
|
|
|
463
463
|
module.exports = app => app.component('dashboard', {
|
|
464
464
|
template: template,
|
|
465
|
+
props: ['dashboardId'],
|
|
465
466
|
data: function() {
|
|
466
467
|
return {
|
|
467
468
|
status: 'loading',
|
|
@@ -476,12 +477,12 @@ module.exports = app => app.component('dashboard', {
|
|
|
476
477
|
this.showEditor = !this.showEditor;
|
|
477
478
|
},
|
|
478
479
|
async updateCode(update) {
|
|
479
|
-
this.code = update;
|
|
480
|
+
this.code = update.doc.code;
|
|
481
|
+
this.result = update.result;
|
|
480
482
|
}
|
|
481
483
|
},
|
|
482
484
|
mounted: async function() {
|
|
483
|
-
const
|
|
484
|
-
const { dashboard, result } = await api.Dashboard.getDashboard({ dashboardId: dashboardId, evaluate: true });
|
|
485
|
+
const { dashboard, result } = await api.Dashboard.getDashboard({ dashboardId: this.dashboardId, evaluate: true });
|
|
485
486
|
if (!dashboard) {
|
|
486
487
|
return;
|
|
487
488
|
}
|
|
@@ -521,8 +522,11 @@ module.exports = app => app.component('edit-dashboard', {
|
|
|
521
522
|
this.$emit('close')
|
|
522
523
|
},
|
|
523
524
|
async updateCode() {
|
|
524
|
-
const { doc } = await api.Dashboard.updateDashboard({
|
|
525
|
-
|
|
525
|
+
const { doc, result } = await api.Dashboard.updateDashboard({
|
|
526
|
+
dashboardId: this.dashboardId,
|
|
527
|
+
code: this.editor.getValue()
|
|
528
|
+
});
|
|
529
|
+
this.$emit('update', { doc, result });
|
|
526
530
|
this.editor.setValue(doc.code);
|
|
527
531
|
this.closeEditor();
|
|
528
532
|
}
|
|
@@ -1775,7 +1779,7 @@ module.exports = [
|
|
|
1775
1779
|
component: 'dashboards'
|
|
1776
1780
|
},
|
|
1777
1781
|
{
|
|
1778
|
-
path: '/dashboard',
|
|
1782
|
+
path: '/dashboard/:dashboardId',
|
|
1779
1783
|
name: 'dashboard',
|
|
1780
1784
|
component: 'dashboard'
|
|
1781
1785
|
}
|
|
@@ -2500,7 +2504,7 @@ module.exports = "<div>\n <div v-if=\"Array.isArray(result)\">\n <div v-for=
|
|
|
2500
2504
|
/***/ ((module) => {
|
|
2501
2505
|
|
|
2502
2506
|
"use strict";
|
|
2503
|
-
module.exports = "<div class=\"dashboard px-1\">\n <div v-if=\"dashboard\" class=\"max-w-5xl mx-auto\">\n <div class=\"flex items-center w-full\">\n <h2 class=\"mt-4 mb-4 text-gray-900 font-semibold text-xl grow shrink\">{{dashboard.title}}</h2>\n <div>\n <button\n v-if=\"!showEditor\"\n @click=\"showEditor = true\"\n type=\"button\"\n class=\"rounded-md bg-teal-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">\n <img src=\"images/edit.svg\" class=\"inline h-[1em]\" /> Edit\n </button>\n </div>\n </div>\n <div v-if=\"!showEditor\" class=\"mt-4 mb-4\">\n <dashboard-result :result=\"result\"></dashboard-result>\n </div>\n <div v-if=\"showEditor\">\n <edit-dashboard
|
|
2507
|
+
module.exports = "<div class=\"dashboard px-1\">\n <div v-if=\"dashboard\" class=\"max-w-5xl mx-auto\">\n <div class=\"flex items-center w-full\">\n <h2 class=\"mt-4 mb-4 text-gray-900 font-semibold text-xl grow shrink\">{{dashboard.title}}</h2>\n <div>\n <button\n v-if=\"!showEditor\"\n @click=\"showEditor = true\"\n type=\"button\"\n class=\"rounded-md bg-teal-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">\n <img src=\"images/edit.svg\" class=\"inline h-[1em]\" /> Edit\n </button>\n </div>\n </div>\n <div v-if=\"!showEditor\" class=\"mt-4 mb-4\">\n <dashboard-result :result=\"result\"></dashboard-result>\n </div>\n <div v-if=\"showEditor\">\n <edit-dashboard\n :dashboardId=\"dashboard._id\"\n :code=\"code\"\n @close=\"showEditor=false;\"\n @update=\"updateCode\"></edit-dashboard>\n </div>\n \n </div>\n <div v-if=\"!dashboard && status === 'loaded'\">\n No dashboard with the given id could be found.\n </div>\n</div>";
|
|
2504
2508
|
|
|
2505
2509
|
/***/ }),
|
|
2506
2510
|
|
|
@@ -2522,7 +2526,7 @@ module.exports = "<div>\n <textarea ref=\"codeEditor\">{{code}}</textarea>\n
|
|
|
2522
2526
|
/***/ ((module) => {
|
|
2523
2527
|
|
|
2524
2528
|
"use strict";
|
|
2525
|
-
module.exports = "<div class=\"dashboards max-w-5xl mx-auto mt-8\">\n <div v-if=\"status === 'loaded' && dashboards.length === 0\">\n <div class=\"text-center\">\n <h3 class=\"mt-2 text-sm font-semibold text-gray-900\">No dashboards yet</h3>\n <p class=\"mt-1 text-sm text-gray-500\">Get started by creating a new dashboard.</p>\n <div class=\"mt-6\">\n <button type=\"button\" class=\"inline-flex items-center rounded-md bg-teal-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z\" />\n </svg>\n New Dashboard\n </button>\n </div>\n </div>\n </div>\n\n\n <div class=\"px-4 sm:px-6 lg:px-8\">\n <div class=\"sm:flex sm:items-center\">\n <div class=\"sm:flex-auto\">\n <h1 class=\"text-base font-semibold leading-6 text-gray-900\">Dashboards</h1>\n </div>\n <div class=\"mt-4 sm:ml-16 sm:mt-0 sm:flex-none\">\n <button\n type=\"button\"\n @click=\"showCreateDashboardModal = true\"\n class=\"block rounded-md bg-teal-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">Create New Dashboard</button>\n </div>\n </div>\n <div class=\"mt-8 flow-root\">\n <div class=\"-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8\">\n <div class=\"inline-block min-w-full py-2 align-middle\">\n <table class=\"min-w-full divide-y divide-gray-300\">\n <thead>\n <tr>\n <th scope=\"col\" class=\"py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6 lg:pl-8\">Title</th>\n <th scope=\"col\" class=\"px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-[50%]\">Description</th>\n <th scope=\"col\" class=\"relative py-3.5 pl-3 pr-4 sm:pr-6 lg:pr-8\">\n </th>\n <th scope=\"col\" class=\"relative py-3.5 pl-3 pr-4 sm:pr-6 lg:pr-8\">\n </th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-gray-200 bg-white\">\n <tr v-for=\"dashboard in dashboards\">\n <td class=\"whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6 lg:pl-8\">{{dashboard.title}}</td>\n <td class=\"whitespace-nowrap px-3 py-4 text-sm text-gray-500 truncate w-[50%]\">{{dashboard.description}}</td>\n <td class=\"relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8\">\n <router-link\n :to=\"'dashboard
|
|
2529
|
+
module.exports = "<div class=\"dashboards max-w-5xl mx-auto mt-8\">\n <div v-if=\"status === 'loaded' && dashboards.length === 0\">\n <div class=\"text-center\">\n <h3 class=\"mt-2 text-sm font-semibold text-gray-900\">No dashboards yet</h3>\n <p class=\"mt-1 text-sm text-gray-500\">Get started by creating a new dashboard.</p>\n <div class=\"mt-6\">\n <button type=\"button\" class=\"inline-flex items-center rounded-md bg-teal-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">\n <svg class=\"-ml-0.5 mr-1.5 h-5 w-5\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\">\n <path d=\"M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z\" />\n </svg>\n New Dashboard\n </button>\n </div>\n </div>\n </div>\n\n\n <div class=\"px-4 sm:px-6 lg:px-8\">\n <div class=\"sm:flex sm:items-center\">\n <div class=\"sm:flex-auto\">\n <h1 class=\"text-base font-semibold leading-6 text-gray-900\">Dashboards</h1>\n </div>\n <div class=\"mt-4 sm:ml-16 sm:mt-0 sm:flex-none\">\n <button\n type=\"button\"\n @click=\"showCreateDashboardModal = true\"\n class=\"block rounded-md bg-teal-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-teal-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600\">Create New Dashboard</button>\n </div>\n </div>\n <div class=\"mt-8 flow-root\">\n <div class=\"-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8\">\n <div class=\"inline-block min-w-full py-2 align-middle\">\n <table class=\"min-w-full divide-y divide-gray-300\">\n <thead>\n <tr>\n <th scope=\"col\" class=\"py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6 lg:pl-8\">Title</th>\n <th scope=\"col\" class=\"px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-[50%]\">Description</th>\n <th scope=\"col\" class=\"relative py-3.5 pl-3 pr-4 sm:pr-6 lg:pr-8\">\n </th>\n <th scope=\"col\" class=\"relative py-3.5 pl-3 pr-4 sm:pr-6 lg:pr-8\">\n </th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-gray-200 bg-white\">\n <tr v-for=\"dashboard in dashboards\">\n <td class=\"whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6 lg:pl-8\">{{dashboard.title}}</td>\n <td class=\"whitespace-nowrap px-3 py-4 text-sm text-gray-500 truncate w-[50%]\">{{dashboard.description}}</td>\n <td class=\"relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8\">\n <router-link\n :to=\"'/dashboard/' + dashboard._id + '?edit=true'\"\n class=\"text-teal-600 hover:text-teal-900\">\n Edit\n </router-link>\n </td>\n <td class=\"relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8\">\n <router-link\n :to=\"'/dashboard/' + dashboard._id\"\n class=\"text-teal-600 hover:text-teal-900\">\n View\n </router-link>\n </td>\n </tr>\n \n <!-- More people... -->\n </tbody>\n </table>\n </div>\n </div>\n </div>\n </div>\n\n <modal v-if=\"showCreateDashboardModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"showCreateDashboardModal = false;\">×</div>\n \n <create-dashboard></create-dashboard>\n </template>\n </modal>\n</div>";
|
|
2526
2530
|
|
|
2527
2531
|
/***/ }),
|
|
2528
2532
|
|
|
@@ -16,7 +16,11 @@
|
|
|
16
16
|
<dashboard-result :result="result"></dashboard-result>
|
|
17
17
|
</div>
|
|
18
18
|
<div v-if="showEditor">
|
|
19
|
-
<edit-dashboard
|
|
19
|
+
<edit-dashboard
|
|
20
|
+
:dashboardId="dashboard._id"
|
|
21
|
+
:code="code"
|
|
22
|
+
@close="showEditor=false;"
|
|
23
|
+
@update="updateCode"></edit-dashboard>
|
|
20
24
|
</div>
|
|
21
25
|
|
|
22
26
|
</div>
|
|
@@ -5,6 +5,7 @@ const template = require('./dashboard.html');
|
|
|
5
5
|
|
|
6
6
|
module.exports = app => app.component('dashboard', {
|
|
7
7
|
template: template,
|
|
8
|
+
props: ['dashboardId'],
|
|
8
9
|
data: function() {
|
|
9
10
|
return {
|
|
10
11
|
status: 'loading',
|
|
@@ -19,12 +20,12 @@ module.exports = app => app.component('dashboard', {
|
|
|
19
20
|
this.showEditor = !this.showEditor;
|
|
20
21
|
},
|
|
21
22
|
async updateCode(update) {
|
|
22
|
-
this.code = update;
|
|
23
|
+
this.code = update.doc.code;
|
|
24
|
+
this.result = update.result;
|
|
23
25
|
}
|
|
24
26
|
},
|
|
25
27
|
mounted: async function() {
|
|
26
|
-
const
|
|
27
|
-
const { dashboard, result } = await api.Dashboard.getDashboard({ dashboardId: dashboardId, evaluate: true });
|
|
28
|
+
const { dashboard, result } = await api.Dashboard.getDashboard({ dashboardId: this.dashboardId, evaluate: true });
|
|
28
29
|
if (!dashboard) {
|
|
29
30
|
return;
|
|
30
31
|
}
|
|
@@ -17,8 +17,11 @@ module.exports = app => app.component('edit-dashboard', {
|
|
|
17
17
|
this.$emit('close')
|
|
18
18
|
},
|
|
19
19
|
async updateCode() {
|
|
20
|
-
const { doc } = await api.Dashboard.updateDashboard({
|
|
21
|
-
|
|
20
|
+
const { doc, result } = await api.Dashboard.updateDashboard({
|
|
21
|
+
dashboardId: this.dashboardId,
|
|
22
|
+
code: this.editor.getValue()
|
|
23
|
+
});
|
|
24
|
+
this.$emit('update', { doc, result });
|
|
22
25
|
this.editor.setValue(doc.code);
|
|
23
26
|
this.closeEditor();
|
|
24
27
|
}
|
|
@@ -47,14 +47,14 @@
|
|
|
47
47
|
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500 truncate w-[50%]">{{dashboard.description}}</td>
|
|
48
48
|
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8">
|
|
49
49
|
<router-link
|
|
50
|
-
:to="'dashboard
|
|
50
|
+
:to="'/dashboard/' + dashboard._id + '?edit=true'"
|
|
51
51
|
class="text-teal-600 hover:text-teal-900">
|
|
52
52
|
Edit
|
|
53
53
|
</router-link>
|
|
54
54
|
</td>
|
|
55
55
|
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8">
|
|
56
56
|
<router-link
|
|
57
|
-
:to="'dashboard
|
|
57
|
+
:to="'/dashboard/' + dashboard._id"
|
|
58
58
|
class="text-teal-600 hover:text-teal-900">
|
|
59
59
|
View
|
|
60
60
|
</router-link>
|
package/frontend/src/routes.js
CHANGED