@mongoosejs/studio 0.0.32 → 0.0.34
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 +22 -8
- package/frontend/src/api.js +10 -0
- 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
|
@@ -28,6 +28,16 @@ if (typeof config__setAuthorizationHeaderFrom === 'string' && config__setAuthori
|
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
client.interceptors.response.use(
|
|
32
|
+
res => res,
|
|
33
|
+
err => {
|
|
34
|
+
if (typeof err.response.data === 'string') {
|
|
35
|
+
throw new Error(`Error in ${err.config?.method} ${err.config?.url}: ${err.response.data}`);
|
|
36
|
+
}
|
|
37
|
+
throw err;
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
|
|
31
41
|
if (false) {} else {
|
|
32
42
|
exports.Dashboard = {
|
|
33
43
|
createDashboard: function createDashboard(params) {
|
|
@@ -462,6 +472,7 @@ const template = __webpack_require__(/*! ./dashboard.html */ "./frontend/src/das
|
|
|
462
472
|
|
|
463
473
|
module.exports = app => app.component('dashboard', {
|
|
464
474
|
template: template,
|
|
475
|
+
props: ['dashboardId'],
|
|
465
476
|
data: function() {
|
|
466
477
|
return {
|
|
467
478
|
status: 'loading',
|
|
@@ -476,12 +487,12 @@ module.exports = app => app.component('dashboard', {
|
|
|
476
487
|
this.showEditor = !this.showEditor;
|
|
477
488
|
},
|
|
478
489
|
async updateCode(update) {
|
|
479
|
-
this.code = update;
|
|
490
|
+
this.code = update.doc.code;
|
|
491
|
+
this.result = update.result;
|
|
480
492
|
}
|
|
481
493
|
},
|
|
482
494
|
mounted: async function() {
|
|
483
|
-
const
|
|
484
|
-
const { dashboard, result } = await api.Dashboard.getDashboard({ dashboardId: dashboardId, evaluate: true });
|
|
495
|
+
const { dashboard, result } = await api.Dashboard.getDashboard({ dashboardId: this.dashboardId, evaluate: true });
|
|
485
496
|
if (!dashboard) {
|
|
486
497
|
return;
|
|
487
498
|
}
|
|
@@ -521,8 +532,11 @@ module.exports = app => app.component('edit-dashboard', {
|
|
|
521
532
|
this.$emit('close')
|
|
522
533
|
},
|
|
523
534
|
async updateCode() {
|
|
524
|
-
const { doc } = await api.Dashboard.updateDashboard({
|
|
525
|
-
|
|
535
|
+
const { doc, result } = await api.Dashboard.updateDashboard({
|
|
536
|
+
dashboardId: this.dashboardId,
|
|
537
|
+
code: this.editor.getValue()
|
|
538
|
+
});
|
|
539
|
+
this.$emit('update', { doc, result });
|
|
526
540
|
this.editor.setValue(doc.code);
|
|
527
541
|
this.closeEditor();
|
|
528
542
|
}
|
|
@@ -1775,7 +1789,7 @@ module.exports = [
|
|
|
1775
1789
|
component: 'dashboards'
|
|
1776
1790
|
},
|
|
1777
1791
|
{
|
|
1778
|
-
path: '/dashboard',
|
|
1792
|
+
path: '/dashboard/:dashboardId',
|
|
1779
1793
|
name: 'dashboard',
|
|
1780
1794
|
component: 'dashboard'
|
|
1781
1795
|
}
|
|
@@ -2500,7 +2514,7 @@ module.exports = "<div>\n <div v-if=\"Array.isArray(result)\">\n <div v-for=
|
|
|
2500
2514
|
/***/ ((module) => {
|
|
2501
2515
|
|
|
2502
2516
|
"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
|
|
2517
|
+
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
2518
|
|
|
2505
2519
|
/***/ }),
|
|
2506
2520
|
|
|
@@ -2522,7 +2536,7 @@ module.exports = "<div>\n <textarea ref=\"codeEditor\">{{code}}</textarea>\n
|
|
|
2522
2536
|
/***/ ((module) => {
|
|
2523
2537
|
|
|
2524
2538
|
"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
|
|
2539
|
+
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
2540
|
|
|
2527
2541
|
/***/ }),
|
|
2528
2542
|
|
package/frontend/src/api.js
CHANGED
|
@@ -18,6 +18,16 @@ if (typeof config__setAuthorizationHeaderFrom === 'string' && config__setAuthori
|
|
|
18
18
|
});
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
client.interceptors.response.use(
|
|
22
|
+
res => res,
|
|
23
|
+
err => {
|
|
24
|
+
if (typeof err.response.data === 'string') {
|
|
25
|
+
throw new Error(`Error in ${err.config?.method} ${err.config?.url}: ${err.response.data}`);
|
|
26
|
+
}
|
|
27
|
+
throw err;
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
|
|
21
31
|
if (config__isLambda) {
|
|
22
32
|
exports.Dashboard = {
|
|
23
33
|
createDashboard(params) {
|
|
@@ -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