@mongoosejs/studio 0.0.116 → 0.0.117
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 +16 -7
- package/backend/db/dashboardSchema.js +1 -1
- package/frontend/public/app.js +12 -7
- package/frontend/public/tw.css +33 -18
- package/frontend/src/dashboard/dashboard.html +2 -1
- package/frontend/src/dashboard/dashboard.js +7 -4
- package/frontend/src/dashboard/edit-dashboard/edit-dashboard.js +2 -0
- package/frontend/src/dashboards/dashboards.html +108 -86
- package/package.json +1 -1
|
@@ -41,14 +41,23 @@ module.exports = ({ db }) => async function getDashboard(params) {
|
|
|
41
41
|
return { dashboard, error: { message: error.message } };
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
try {
|
|
45
|
+
const { dashboardResult } = await startExec.then(({ dashboardResult }) => {
|
|
46
|
+
if (!dashboardResult) {
|
|
47
|
+
return {};
|
|
48
|
+
}
|
|
49
|
+
return completeDashboardEvaluate(
|
|
50
|
+
dashboardResult._id,
|
|
51
|
+
$workspaceId,
|
|
52
|
+
authorization,
|
|
53
|
+
result
|
|
54
|
+
);
|
|
55
|
+
});
|
|
50
56
|
|
|
51
|
-
|
|
57
|
+
return { dashboard, dashboardResult };
|
|
58
|
+
} catch (error) {
|
|
59
|
+
return { dashboard, error: { message: error.message } };
|
|
60
|
+
}
|
|
52
61
|
} else {
|
|
53
62
|
const { dashboardResults } = await getDashboardResults(dashboardId, $workspaceId, authorization);
|
|
54
63
|
return { dashboard, dashboardResults };
|
|
@@ -18,7 +18,7 @@ const dashboardSchema = new mongoose.Schema({
|
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
dashboardSchema.methods.evaluate = async function evaluate() {
|
|
21
|
-
const context = vm.createContext({ db: this.constructor.db, setTimeout });
|
|
21
|
+
const context = vm.createContext({ db: this.constructor.db, setTimeout, ObjectId: mongoose.Types.ObjectId });
|
|
22
22
|
let result = null;
|
|
23
23
|
result = await vm.runInContext(formatFunction(this.code), context);
|
|
24
24
|
if (result.$document?.constructor?.modelName) {
|
package/frontend/public/app.js
CHANGED
|
@@ -1209,16 +1209,19 @@ module.exports = app => app.component('dashboard', {
|
|
|
1209
1209
|
},
|
|
1210
1210
|
async evaluateDashboard() {
|
|
1211
1211
|
this.status = 'evaluating';
|
|
1212
|
+
this.errorMessage = null;
|
|
1212
1213
|
try {
|
|
1213
1214
|
const { dashboard, dashboardResult, error } = await api.Dashboard.getDashboard({ dashboardId: this.dashboardId, evaluate: true });
|
|
1214
1215
|
this.dashboard = dashboard;
|
|
1215
|
-
if (error) {
|
|
1216
|
-
this.errorMessage = error.message;
|
|
1217
|
-
}
|
|
1218
1216
|
this.code = this.dashboard.code;
|
|
1219
1217
|
this.title = this.dashboard.title;
|
|
1220
1218
|
this.description = this.dashboard.description ?? '';
|
|
1221
|
-
|
|
1219
|
+
if (dashboardResult) {
|
|
1220
|
+
this.dashboardResults.unshift(dashboardResult);
|
|
1221
|
+
}
|
|
1222
|
+
if (error) {
|
|
1223
|
+
this.errorMessage = error.message;
|
|
1224
|
+
}
|
|
1222
1225
|
} finally {
|
|
1223
1226
|
this.status = 'loaded';
|
|
1224
1227
|
}
|
|
@@ -1265,6 +1268,7 @@ const template = __webpack_require__(/*! ./edit-dashboard.html */ "./frontend/sr
|
|
|
1265
1268
|
module.exports = app => app.component('edit-dashboard', {
|
|
1266
1269
|
template: template,
|
|
1267
1270
|
props: ['dashboardId', 'code', 'currentDescription', 'currentTitle'],
|
|
1271
|
+
emits: ['close', 'clearError'],
|
|
1268
1272
|
data: function() {
|
|
1269
1273
|
return {
|
|
1270
1274
|
status: 'loaded',
|
|
@@ -1278,6 +1282,7 @@ module.exports = app => app.component('edit-dashboard', {
|
|
|
1278
1282
|
this.$emit('close');
|
|
1279
1283
|
},
|
|
1280
1284
|
async updateCode() {
|
|
1285
|
+
this.$emit('clearError');
|
|
1281
1286
|
this.status = 'loading';
|
|
1282
1287
|
try {
|
|
1283
1288
|
const { doc, result, error } = await api.Dashboard.updateDashboard({
|
|
@@ -4362,7 +4367,7 @@ module.exports = "<div class=\"py-2\">\n <div v-if=\"header\" class=\"border-b
|
|
|
4362
4367
|
/***/ ((module) => {
|
|
4363
4368
|
|
|
4364
4369
|
"use strict";
|
|
4365
|
-
module.exports = "<div class=\"dashboard px-1\">\n <div v-if=\"status === 'loading'\" class=\"max-w-5xl mx-auto text-center\">\n <img src=\"images/loader.gif\" class=\"inline mt-10\">\n </div>\n <div v-if=\"dashboard && status !== 'loading'\" class=\"max-w-5xl mx-auto\">\n <div class=\"flex items-center w-full\" v-if=\"!showEditor\">\n <h2 class=\"mt-4 mb-4 text-gray-900 font-semibold text-xl grow shrink\">{{title}}</h2>\n <div class=\"flex gap-2\">\n <button\n @click=\"showEditor = true\"\n type=\"button\"\n :disabled=\"status === 'evaluating'\"\n class=\"flex items-center rounded-md bg-ultramarine-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600 disabled:cursor-not-allowed disabled:bg-gray-600\">\n <img src=\"images/edit.svg\" class=\"inline h-[1.25em] mr-1\" /> Edit\n </button>\n\n <async-button\n @click=\"evaluateDashboard\"\n type=\"button\"\n :disabled=\"status === 'evaluating'\"\n class=\"flex items-center rounded-md bg-ultramarine-600 px-4 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600 disabled:cursor-not-allowed disabled:bg-gray-600\"\n >\n <svg class=\"inline h-[1.25em] mr-1\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\" fill=\"currentColor\"><path d=\"m670-140 160-100-160-100v200ZM240-600h480v-80H240v80ZM720-40q-83 0-141.5-58.5T520-240q0-83 58.5-141.5T720-440q83 0 141.5 58.5T920-240q0 83-58.5 141.5T720-40ZM120-80v-680q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v267q-19-9-39-15t-41-9v-243H200v562h243q5 31 15.5 59T486-86l-6 6-60-60-60 60-60-60-60 60-60-60-60 60Zm120-200h203q3-21 9-41t15-39H240v80Zm0-160h284q38-37 88.5-58.5T720-520H240v80Zm-40 242v-562 562Z\"/></svg>\n Evaluate\n </async-button>\n </div>\n </div>\n <div v-if=\"!showEditor\" class=\"mt-4 mb-4\">\n <div v-if=\"dashboardResults.length === 0\">\n <div class=\"flex flex-col items-center justify-center py-8\">\n <p class=\"text-gray-700 text-base mb-4\">This dashboard hasn't been evaluated yet.</p>\n <async-button\n @click=\"evaluateDashboard\"\n type=\"button\"\n :disabled=\"status === 'evaluating'\"\n class=\"rounded-md bg-ultramarine-600 px-4 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600 disabled:cursor-not-allowed disabled:bg-gray-600\"\n >\n Evaluate Dashboard\n </async-button>\n </div>\n </div>\n <div v-else>\n <div class=\"relative\">\n <dashboard-result\n :key=\"dashboardResult.finishedEvaluatingAt\"\n :result=\"dashboardResult.result\"\n :finishedEvaluatingAt=\"dashboardResult.finishedEvaluatingAt\"\n @fullscreen=\"showDetailModal = true\"\n class=\"h-[40vh]\"\n >\n </dashboard-result>\n </div>\n </div>\n </div>\n <div v-if=\"showEditor\" class=\"mt-4\">\n <edit-dashboard\n :dashboardId=\"dashboard._id\"\n :code=\"code\"\n :currentDescription=\"description\"\n :currentTitle=\"title\"\n @close=\"showEditor=false;\"\n @update=\"updateCode\"></edit-dashboard>\n </div>\n <div v-if=\"errorMessage\" class=\"rounded-md bg-red-50 p-4 mt-4\">\n <div class=\"flex\">\n <div class=\"flex-shrink-0\">\n <svg class=\"h-5 w-5 text-red-400\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\" data-slot=\"icon\">\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 1 0 0-16 8 8 0 0 0 0 16ZM8.28 7.22a.75.75 0 0 0-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 1 0 1.06 1.06L10 11.06l1.72 1.72a.75.75 0 1 0 1.06-1.06L11.06 10l1.72-1.72a.75.75 0 0 0-1.06-1.06L10 8.94 8.28 7.22Z\" clip-rule=\"evenodd\" />\n </svg>\n </div>\n <div class=\"ml-3\">\n <h3 class=\"text-sm font-medium text-red-800\">{{errorMessage}}</h3>\n </div>\n </div>\n </div>\n\n </div>\n <div v-if=\"!dashboard && status !== 'loading'\">\n No dashboard with the given id could be found.\n </div>\n</div>\n\n<modal\n v-if=\"showDetailModal\"\n containerClass=\"!h-[90vh] !w-[90vw]\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Dashboard Details\"\n>\n <template #body>\n <div class=\"absolute font-mono right-1 top-1 cursor-pointer text-xl\" @click=\"showDetailModal = false;\" role=\"button\" aria-label=\"Close modal\">×</div>\n <div class=\"h-full overflow-auto\">\n <dashboard-result\n v-if=\"dashboardResult\"\n :result=\"dashboardResult.result\"\n :finishedEvaluatingAt=\"dashboardResult.finishedEvaluatingAt\"\n :fullscreen=\"true\"\n :responsive=\"true\">\n </dashboard-result>\n </div>\n </template>\n</modal>\n";
|
|
4370
|
+
module.exports = "<div class=\"dashboard px-1\">\n <div v-if=\"status === 'loading'\" class=\"max-w-5xl mx-auto text-center\">\n <img src=\"images/loader.gif\" class=\"inline mt-10\">\n </div>\n <div v-if=\"dashboard && status !== 'loading'\" class=\"max-w-5xl mx-auto\">\n <div class=\"flex items-center w-full\" v-if=\"!showEditor\">\n <h2 class=\"mt-4 mb-4 text-gray-900 font-semibold text-xl grow shrink\">{{title}}</h2>\n <div class=\"flex gap-2\">\n <button\n @click=\"showEditor = true\"\n type=\"button\"\n :disabled=\"status === 'evaluating'\"\n class=\"flex items-center rounded-md bg-ultramarine-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600 disabled:cursor-not-allowed disabled:bg-gray-600\">\n <img src=\"images/edit.svg\" class=\"inline h-[1.25em] mr-1\" /> Edit\n </button>\n\n <async-button\n @click=\"evaluateDashboard\"\n type=\"button\"\n :disabled=\"status === 'evaluating'\"\n class=\"flex items-center rounded-md bg-ultramarine-600 px-4 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600 disabled:cursor-not-allowed disabled:bg-gray-600\"\n >\n <svg class=\"inline h-[1.25em] mr-1\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 -960 960 960\" fill=\"currentColor\"><path d=\"m670-140 160-100-160-100v200ZM240-600h480v-80H240v80ZM720-40q-83 0-141.5-58.5T520-240q0-83 58.5-141.5T720-440q83 0 141.5 58.5T920-240q0 83-58.5 141.5T720-40ZM120-80v-680q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v267q-19-9-39-15t-41-9v-243H200v562h243q5 31 15.5 59T486-86l-6 6-60-60-60 60-60-60-60 60-60-60-60 60Zm120-200h203q3-21 9-41t15-39H240v80Zm0-160h284q38-37 88.5-58.5T720-520H240v80Zm-40 242v-562 562Z\"/></svg>\n Evaluate\n </async-button>\n </div>\n </div>\n <div v-if=\"!showEditor\" class=\"mt-4 mb-4\">\n <div v-if=\"dashboardResults.length === 0\">\n <div class=\"flex flex-col items-center justify-center py-8\">\n <p class=\"text-gray-700 text-base mb-4\">This dashboard hasn't been evaluated yet.</p>\n <async-button\n @click=\"evaluateDashboard\"\n type=\"button\"\n :disabled=\"status === 'evaluating'\"\n class=\"rounded-md bg-ultramarine-600 px-4 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600 disabled:cursor-not-allowed disabled:bg-gray-600\"\n >\n Evaluate Dashboard\n </async-button>\n </div>\n </div>\n <div v-else>\n <div class=\"relative\">\n <dashboard-result\n :key=\"dashboardResult.finishedEvaluatingAt\"\n :result=\"dashboardResult.result\"\n :finishedEvaluatingAt=\"dashboardResult.finishedEvaluatingAt\"\n @fullscreen=\"showDetailModal = true\"\n class=\"h-[40vh]\"\n >\n </dashboard-result>\n </div>\n </div>\n </div>\n <div v-if=\"showEditor\" class=\"mt-4\">\n <edit-dashboard\n :dashboardId=\"dashboard._id\"\n :code=\"code\"\n :currentDescription=\"description\"\n :currentTitle=\"title\"\n @close=\"showEditor=false;\"\n @update=\"updateCode\"\n @clearError=\"errorMessage = null\"></edit-dashboard>\n </div>\n <div v-if=\"errorMessage\" class=\"rounded-md bg-red-50 p-4 mt-4\">\n <div class=\"flex\">\n <div class=\"flex-shrink-0\">\n <svg class=\"h-5 w-5 text-red-400\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden=\"true\" data-slot=\"icon\">\n <path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 1 0 0-16 8 8 0 0 0 0 16ZM8.28 7.22a.75.75 0 0 0-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 1 0 1.06 1.06L10 11.06l1.72 1.72a.75.75 0 1 0 1.06-1.06L11.06 10l1.72-1.72a.75.75 0 0 0-1.06-1.06L10 8.94 8.28 7.22Z\" clip-rule=\"evenodd\" />\n </svg>\n </div>\n <div class=\"ml-3\">\n <h3 class=\"text-sm font-medium text-red-800\">{{errorMessage}}</h3>\n </div>\n </div>\n </div>\n\n </div>\n <div v-if=\"!dashboard && status !== 'loading'\">\n No dashboard with the given id could be found.\n </div>\n</div>\n\n<modal\n v-if=\"showDetailModal\"\n containerClass=\"!h-[90vh] !w-[90vw]\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Dashboard Details\"\n>\n <template #body>\n <div class=\"absolute font-mono right-1 top-1 cursor-pointer text-xl\" @click=\"showDetailModal = false;\" role=\"button\" aria-label=\"Close modal\">×</div>\n <div class=\"h-full overflow-auto\">\n <dashboard-result\n v-if=\"dashboardResult\"\n :result=\"dashboardResult.result\"\n :finishedEvaluatingAt=\"dashboardResult.finishedEvaluatingAt\"\n :fullscreen=\"true\"\n :responsive=\"true\">\n </dashboard-result>\n </div>\n </template>\n</modal>\n";
|
|
4366
4371
|
|
|
4367
4372
|
/***/ }),
|
|
4368
4373
|
|
|
@@ -4384,7 +4389,7 @@ module.exports = "<div class=\"p-4 bg-gray-100 rounded-lg shadow-lg\">\n <div
|
|
|
4384
4389
|
/***/ ((module) => {
|
|
4385
4390
|
|
|
4386
4391
|
"use strict";
|
|
4387
|
-
module.exports = "<div class=\"dashboards max-w-5xl mx-auto mt-8\">\n <div v-if=\"status === 'loaded' && dashboards.length === 0\">\n
|
|
4392
|
+
module.exports = "<div class=\"dashboards max-w-5xl mx-auto mt-8\">\n <div v-if=\"status === 'loading'\" class=\"text-center mt-4\">\n <svg\n class=\"inline w-8 h-8 animate-spin text-ultramarine-600\"\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <circle\n class=\"opacity-25\"\n cx=\"12\"\n cy=\"12\"\n r=\"10\"\n stroke=\"currentColor\"\n stroke-width=\"4\"\n ></circle>\n <path\n class=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z\"\n ></path>\n </svg>\n </div>\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-ultramarine-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-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 <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-ultramarine-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-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-ultramarine-600 hover:text-ultramarine-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-ultramarine-600 hover:text-ultramarine-900\">\n View\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 <button\n @click=\"showDeleteDashboardModal=dashboard\"\n class=\"text-ultramarine-600 hover:text-ultramarine-900\">\n Delete\n </button>\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 @close=\"insertNewDashboard\"></create-dashboard>\n </template>\n </modal>\n\n <modal v-if=\"showDeleteDashboardModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"showDeleteDashboardModal = null;\">×</div>\n <h2>Are you sure you want to delete this dashboard titled {{showDeleteDashboardModal.title}}?</h2>\n <div class=\"flex space-x-2\">\n <button class=\"px-4 py-2 bg-red-500 text-white rounded-md hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500\" @click=\"deleteDashboard(showDeleteDashboardModal)\">Yes, delete</button>\n <button class=\"px-4 py-2 bg-gray-500 text-white rounded-md hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-600\" @click=\"showDeleteDashboardModal=null;\">Cancel</button>\n </div>\n </template>\n </modal>\n </div>\n</div>";
|
|
4388
4393
|
|
|
4389
4394
|
/***/ }),
|
|
4390
4395
|
|
|
@@ -14876,7 +14881,7 @@ var bson = /*#__PURE__*/Object.freeze({
|
|
|
14876
14881
|
/***/ ((module) => {
|
|
14877
14882
|
|
|
14878
14883
|
"use strict";
|
|
14879
|
-
module.exports = /*#__PURE__*/JSON.parse('{"name":"@mongoosejs/studio","version":"0.0.
|
|
14884
|
+
module.exports = /*#__PURE__*/JSON.parse('{"name":"@mongoosejs/studio","version":"0.0.117","description":"A sleek, powerful MongoDB UI with built-in dashboarding and auth, seamlessly integrated with your Express, Vercel, or Netlify app.","homepage":"https://studio.mongoosejs.io/","repository":{"type":"git","url":"https://github.com/mongoosejs/studio"},"dependencies":{"archetype":"0.13.1","csv-stringify":"6.3.0","ejson":"^2.2.3","extrovert":"0.0.26","marked":"15.0.12","node-inspect-extracted":"3.x","tailwindcss":"3.4.0","vanillatoasts":"^1.6.0","vue":"3.x","webpack":"5.x"},"peerDependencies":{"bson":"^5.5.1 || 6.x","express":"4.x","mongoose":"7.x || 8.x"},"devDependencies":{"@masteringjs/eslint-config":"0.1.1","axios":"1.2.2","dedent":"^1.6.0","eslint":"9.30.0","express":"4.x","mocha":"10.2.0","mongoose":"8.x"},"scripts":{"lint":"eslint .","tailwind":"tailwindcss -o ./frontend/public/tw.css","tailwind:watch":"tailwindcss -o ./frontend/public/tw.css --watch","test":"mocha test/*.test.js"}}');
|
|
14880
14885
|
|
|
14881
14886
|
/***/ })
|
|
14882
14887
|
|
package/frontend/public/tw.css
CHANGED
|
@@ -642,10 +642,6 @@ video {
|
|
|
642
642
|
top: 90%;
|
|
643
643
|
}
|
|
644
644
|
|
|
645
|
-
.bottom-0 {
|
|
646
|
-
bottom: 0px;
|
|
647
|
-
}
|
|
648
|
-
|
|
649
645
|
.isolate {
|
|
650
646
|
isolation: isolate;
|
|
651
647
|
}
|
|
@@ -982,6 +978,10 @@ video {
|
|
|
982
978
|
max-width: 64rem;
|
|
983
979
|
}
|
|
984
980
|
|
|
981
|
+
.max-w-\[calc\(100vw-3rem\)\] {
|
|
982
|
+
max-width: calc(100vw - 3rem);
|
|
983
|
+
}
|
|
984
|
+
|
|
985
985
|
.max-w-\[calc\(100vw-4rem\)\] {
|
|
986
986
|
max-width: calc(100vw - 4rem);
|
|
987
987
|
}
|
|
@@ -990,10 +990,6 @@ video {
|
|
|
990
990
|
max-width: 20rem;
|
|
991
991
|
}
|
|
992
992
|
|
|
993
|
-
.max-w-\[calc\(100vw-3rem\)\] {
|
|
994
|
-
max-width: calc(100vw - 3rem);
|
|
995
|
-
}
|
|
996
|
-
|
|
997
993
|
.flex-1 {
|
|
998
994
|
flex: 1 1 0%;
|
|
999
995
|
}
|
|
@@ -1044,6 +1040,16 @@ video {
|
|
|
1044
1040
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
|
1045
1041
|
}
|
|
1046
1042
|
|
|
1043
|
+
@keyframes spin {
|
|
1044
|
+
to {
|
|
1045
|
+
transform: rotate(360deg);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
.animate-spin {
|
|
1050
|
+
animation: spin 1s linear infinite;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1047
1053
|
.cursor-not-allowed {
|
|
1048
1054
|
cursor: not-allowed;
|
|
1049
1055
|
}
|
|
@@ -1800,6 +1806,11 @@ video {
|
|
|
1800
1806
|
color: rgb(255 255 255 / var(--tw-text-opacity));
|
|
1801
1807
|
}
|
|
1802
1808
|
|
|
1809
|
+
.text-ultramarine-600 {
|
|
1810
|
+
--tw-text-opacity: 1;
|
|
1811
|
+
color: rgb(24 35 255 / var(--tw-text-opacity));
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1803
1814
|
.accent-sky-600 {
|
|
1804
1815
|
accent-color: #0284c7;
|
|
1805
1816
|
}
|
|
@@ -1808,6 +1819,14 @@ video {
|
|
|
1808
1819
|
opacity: 0.5;
|
|
1809
1820
|
}
|
|
1810
1821
|
|
|
1822
|
+
.opacity-25 {
|
|
1823
|
+
opacity: 0.25;
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
.opacity-75 {
|
|
1827
|
+
opacity: 0.75;
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1811
1830
|
.shadow {
|
|
1812
1831
|
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
|
1813
1832
|
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
|
@@ -2085,9 +2104,9 @@ video {
|
|
|
2085
2104
|
color: rgb(10 87 87 / var(--tw-text-opacity));
|
|
2086
2105
|
}
|
|
2087
2106
|
|
|
2088
|
-
.hover\:text-
|
|
2107
|
+
.hover\:text-ultramarine-900:hover {
|
|
2089
2108
|
--tw-text-opacity: 1;
|
|
2090
|
-
color: rgb(
|
|
2109
|
+
color: rgb(6 14 172 / var(--tw-text-opacity));
|
|
2091
2110
|
}
|
|
2092
2111
|
|
|
2093
2112
|
.focus\:z-10:focus {
|
|
@@ -2367,10 +2386,6 @@ video {
|
|
|
2367
2386
|
.md\:hidden {
|
|
2368
2387
|
display: none;
|
|
2369
2388
|
}
|
|
2370
|
-
|
|
2371
|
-
.md\:p-3 {
|
|
2372
|
-
padding: 0.75rem;
|
|
2373
|
-
}
|
|
2374
2389
|
}
|
|
2375
2390
|
|
|
2376
2391
|
@media (min-width: 1024px) {
|
|
@@ -2391,14 +2406,14 @@ video {
|
|
|
2391
2406
|
width: 16rem;
|
|
2392
2407
|
}
|
|
2393
2408
|
|
|
2394
|
-
.lg\:max-w-\[calc\(100vw-20rem\)\] {
|
|
2395
|
-
max-width: calc(100vw - 20rem);
|
|
2396
|
-
}
|
|
2397
|
-
|
|
2398
2409
|
.lg\:max-w-\[calc\(100vw-15rem\)\] {
|
|
2399
2410
|
max-width: calc(100vw - 15rem);
|
|
2400
2411
|
}
|
|
2401
2412
|
|
|
2413
|
+
.lg\:max-w-\[calc\(100vw-20rem\)\] {
|
|
2414
|
+
max-width: calc(100vw - 20rem);
|
|
2415
|
+
}
|
|
2416
|
+
|
|
2402
2417
|
.lg\:px-8 {
|
|
2403
2418
|
padding-left: 2rem;
|
|
2404
2419
|
padding-right: 2rem;
|
|
@@ -59,7 +59,8 @@
|
|
|
59
59
|
:currentDescription="description"
|
|
60
60
|
:currentTitle="title"
|
|
61
61
|
@close="showEditor=false;"
|
|
62
|
-
@update="updateCode"
|
|
62
|
+
@update="updateCode"
|
|
63
|
+
@clearError="errorMessage = null"></edit-dashboard>
|
|
63
64
|
</div>
|
|
64
65
|
<div v-if="errorMessage" class="rounded-md bg-red-50 p-4 mt-4">
|
|
65
66
|
<div class="flex">
|
|
@@ -35,16 +35,19 @@ module.exports = app => app.component('dashboard', {
|
|
|
35
35
|
},
|
|
36
36
|
async evaluateDashboard() {
|
|
37
37
|
this.status = 'evaluating';
|
|
38
|
+
this.errorMessage = null;
|
|
38
39
|
try {
|
|
39
40
|
const { dashboard, dashboardResult, error } = await api.Dashboard.getDashboard({ dashboardId: this.dashboardId, evaluate: true });
|
|
40
41
|
this.dashboard = dashboard;
|
|
41
|
-
if (error) {
|
|
42
|
-
this.errorMessage = error.message;
|
|
43
|
-
}
|
|
44
42
|
this.code = this.dashboard.code;
|
|
45
43
|
this.title = this.dashboard.title;
|
|
46
44
|
this.description = this.dashboard.description ?? '';
|
|
47
|
-
|
|
45
|
+
if (dashboardResult) {
|
|
46
|
+
this.dashboardResults.unshift(dashboardResult);
|
|
47
|
+
}
|
|
48
|
+
if (error) {
|
|
49
|
+
this.errorMessage = error.message;
|
|
50
|
+
}
|
|
48
51
|
} finally {
|
|
49
52
|
this.status = 'loaded';
|
|
50
53
|
}
|
|
@@ -6,6 +6,7 @@ const template = require('./edit-dashboard.html');
|
|
|
6
6
|
module.exports = app => app.component('edit-dashboard', {
|
|
7
7
|
template: template,
|
|
8
8
|
props: ['dashboardId', 'code', 'currentDescription', 'currentTitle'],
|
|
9
|
+
emits: ['close', 'clearError'],
|
|
9
10
|
data: function() {
|
|
10
11
|
return {
|
|
11
12
|
status: 'loaded',
|
|
@@ -19,6 +20,7 @@ module.exports = app => app.component('edit-dashboard', {
|
|
|
19
20
|
this.$emit('close');
|
|
20
21
|
},
|
|
21
22
|
async updateCode() {
|
|
23
|
+
this.$emit('clearError');
|
|
22
24
|
this.status = 'loading';
|
|
23
25
|
try {
|
|
24
26
|
const { doc, result, error } = await api.Dashboard.updateDashboard({
|
|
@@ -1,97 +1,119 @@
|
|
|
1
1
|
<div class="dashboards max-w-5xl mx-auto mt-8">
|
|
2
|
-
<div v-if="status === '
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
<div v-if="status === 'loading'" class="text-center mt-4">
|
|
3
|
+
<svg
|
|
4
|
+
class="inline w-8 h-8 animate-spin text-ultramarine-600"
|
|
5
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
6
|
+
fill="none"
|
|
7
|
+
viewBox="0 0 24 24"
|
|
8
|
+
>
|
|
9
|
+
<circle
|
|
10
|
+
class="opacity-25"
|
|
11
|
+
cx="12"
|
|
12
|
+
cy="12"
|
|
13
|
+
r="10"
|
|
14
|
+
stroke="currentColor"
|
|
15
|
+
stroke-width="4"
|
|
16
|
+
></circle>
|
|
17
|
+
<path
|
|
18
|
+
class="opacity-75"
|
|
19
|
+
fill="currentColor"
|
|
20
|
+
d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"
|
|
21
|
+
></path>
|
|
22
|
+
</svg>
|
|
23
|
+
</div>
|
|
24
|
+
<div v-if="status === 'loaded' && dashboards.length === 0">
|
|
25
|
+
<div class="text-center">
|
|
26
|
+
<h3 class="mt-2 text-sm font-semibold text-gray-900">No dashboards yet</h3>
|
|
27
|
+
<p class="mt-1 text-sm text-gray-500">Get started by creating a new dashboard.</p>
|
|
28
|
+
<div class="mt-6">
|
|
29
|
+
<button type="button" class="inline-flex items-center rounded-md bg-ultramarine-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600">
|
|
30
|
+
<svg class="-ml-0.5 mr-1.5 h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
|
31
|
+
<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" />
|
|
32
|
+
</svg>
|
|
33
|
+
New Dashboard
|
|
34
|
+
</button>
|
|
35
|
+
</div>
|
|
13
36
|
</div>
|
|
14
37
|
</div>
|
|
15
|
-
</div>
|
|
16
|
-
|
|
17
38
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
39
|
+
<div class="px-4 sm:px-6 lg:px-8">
|
|
40
|
+
<div class="sm:flex sm:items-center">
|
|
41
|
+
<div class="sm:flex-auto">
|
|
42
|
+
<h1 class="text-base font-semibold leading-6 text-gray-900">Dashboards</h1>
|
|
43
|
+
</div>
|
|
44
|
+
<div class="mt-4 sm:ml-16 sm:mt-0 sm:flex-none">
|
|
45
|
+
<button
|
|
46
|
+
type="button"
|
|
47
|
+
@click="showCreateDashboardModal = true"
|
|
48
|
+
class="block rounded-md bg-ultramarine-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600">Create New Dashboard</button>
|
|
49
|
+
</div>
|
|
28
50
|
</div>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
</
|
|
42
|
-
</
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
</
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
</
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
</
|
|
68
|
-
</
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
</
|
|
73
|
-
</
|
|
51
|
+
<div class="mt-8 flow-root">
|
|
52
|
+
<div class="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
|
53
|
+
<div class="inline-block min-w-full py-2 align-middle">
|
|
54
|
+
<table class="min-w-full divide-y divide-gray-300">
|
|
55
|
+
<thead>
|
|
56
|
+
<tr>
|
|
57
|
+
<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>
|
|
58
|
+
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 w-[50%]">Description</th>
|
|
59
|
+
<th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-6 lg:pr-8">
|
|
60
|
+
</th>
|
|
61
|
+
<th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-6 lg:pr-8">
|
|
62
|
+
</th>
|
|
63
|
+
</tr>
|
|
64
|
+
</thead>
|
|
65
|
+
<tbody class="divide-y divide-gray-200 bg-white">
|
|
66
|
+
<tr v-for="dashboard in dashboards">
|
|
67
|
+
<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>
|
|
68
|
+
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500 truncate w-[50%]">{{dashboard.description}}</td>
|
|
69
|
+
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8">
|
|
70
|
+
<router-link
|
|
71
|
+
:to="'/dashboard/' + dashboard._id + '?edit=true'"
|
|
72
|
+
class="text-ultramarine-600 hover:text-ultramarine-900">
|
|
73
|
+
Edit
|
|
74
|
+
</router-link>
|
|
75
|
+
</td>
|
|
76
|
+
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8">
|
|
77
|
+
<router-link
|
|
78
|
+
:to="'/dashboard/' + dashboard._id"
|
|
79
|
+
class="text-ultramarine-600 hover:text-ultramarine-900">
|
|
80
|
+
View
|
|
81
|
+
</router-link>
|
|
82
|
+
</td>
|
|
83
|
+
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8">
|
|
84
|
+
<button
|
|
85
|
+
@click="showDeleteDashboardModal=dashboard"
|
|
86
|
+
class="text-ultramarine-600 hover:text-ultramarine-900">
|
|
87
|
+
Delete
|
|
88
|
+
</button>
|
|
89
|
+
</td>
|
|
90
|
+
</tr>
|
|
91
|
+
|
|
92
|
+
<!-- More people... -->
|
|
93
|
+
</tbody>
|
|
94
|
+
</table>
|
|
95
|
+
</div>
|
|
74
96
|
</div>
|
|
75
97
|
</div>
|
|
76
98
|
</div>
|
|
77
|
-
</div>
|
|
78
99
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
<create-dashboard @close="insertNewDashboard"></create-dashboard>
|
|
84
|
-
</template>
|
|
85
|
-
</modal>
|
|
100
|
+
<modal v-if="showCreateDashboardModal">
|
|
101
|
+
<template v-slot:body>
|
|
102
|
+
<div class="modal-exit" @click="showCreateDashboardModal = false;">×</div>
|
|
86
103
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
<
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
104
|
+
<create-dashboard @close="insertNewDashboard"></create-dashboard>
|
|
105
|
+
</template>
|
|
106
|
+
</modal>
|
|
107
|
+
|
|
108
|
+
<modal v-if="showDeleteDashboardModal">
|
|
109
|
+
<template v-slot:body>
|
|
110
|
+
<div class="modal-exit" @click="showDeleteDashboardModal = null;">×</div>
|
|
111
|
+
<h2>Are you sure you want to delete this dashboard titled {{showDeleteDashboardModal.title}}?</h2>
|
|
112
|
+
<div class="flex space-x-2">
|
|
113
|
+
<button class="px-4 py-2 bg-red-500 text-white rounded-md hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500" @click="deleteDashboard(showDeleteDashboardModal)">Yes, delete</button>
|
|
114
|
+
<button class="px-4 py-2 bg-gray-500 text-white rounded-md hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-600" @click="showDeleteDashboardModal=null;">Cancel</button>
|
|
115
|
+
</div>
|
|
116
|
+
</template>
|
|
117
|
+
</modal>
|
|
118
|
+
</div>
|
|
97
119
|
</div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mongoosejs/studio",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.117",
|
|
4
4
|
"description": "A sleek, powerful MongoDB UI with built-in dashboarding and auth, seamlessly integrated with your Express, Vercel, or Netlify app.",
|
|
5
5
|
"homepage": "https://studio.mongoosejs.io/",
|
|
6
6
|
"repository": {
|