@mongoosejs/studio 0.0.34 → 0.0.36
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/deleteDashboard.js +19 -0
- package/backend/actions/Dashboard/index.js +1 -0
- package/backend/actions/Dashboard/updateDashboard.js +18 -2
- package/backend/db/dashboardSchema.js +2 -2
- package/frontend/public/app.js +126 -35
- package/frontend/public/tw.css +123 -21
- package/frontend/src/api.js +3 -0
- package/frontend/src/dashboard/dashboard.html +3 -1
- package/frontend/src/dashboard/dashboard.js +6 -0
- package/frontend/src/dashboard/edit-dashboard/edit-dashboard.html +14 -4
- package/frontend/src/dashboard/edit-dashboard/edit-dashboard.js +9 -4
- package/frontend/src/dashboard-result/dashboard-document/dashboard-document.js +1 -1
- package/frontend/src/dashboards/dashboards.html +19 -1
- package/frontend/src/dashboards/dashboards.js +17 -1
- package/frontend/src/document-details/document-details.css +5 -0
- package/frontend/src/document-details/document-details.html +6 -20
- package/frontend/src/document-details/document-details.js +4 -33
- package/frontend/src/document-details/document-property/document-property.css +23 -0
- package/frontend/src/document-details/document-property/document-property.html +47 -0
- package/frontend/src/document-details/document-property/document-property.js +56 -0
- package/frontend/src/edit-date/edit-date.html +2 -18
- package/frontend/src/edit-date/edit-date.js +7 -6
- package/frontend/src/index.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Archetype = require('archetype');
|
|
4
|
+
const vm = require('vm');
|
|
5
|
+
|
|
6
|
+
const DeleteDashboardParams = new Archetype({
|
|
7
|
+
dashboardId: {
|
|
8
|
+
$type: 'string',
|
|
9
|
+
$required: true
|
|
10
|
+
},
|
|
11
|
+
}).compile('DeleteDashboardParams');
|
|
12
|
+
|
|
13
|
+
module.exports = ({ db }) => async function deleteDashboard(params) {
|
|
14
|
+
const { dashboardId } = new DeleteDashboardParams(params);
|
|
15
|
+
const Dashboard = db.model('__Studio_Dashboard');
|
|
16
|
+
|
|
17
|
+
const result = await Dashboard.deleteOne({ _id: dashboardId }).orFail();
|
|
18
|
+
return { result };
|
|
19
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
exports.createDashboard = require('./createDashboard');
|
|
4
|
+
exports.deleteDashboard = require('./deleteDashboard');
|
|
4
5
|
exports.getDashboard = require('./getDashboard');
|
|
5
6
|
exports.getDashboards = require('./getDashboards');
|
|
6
7
|
exports.updateDashboard = require('./updateDashboard');
|
|
@@ -10,16 +10,32 @@ const UpdateDashboardParams = new Archetype({
|
|
|
10
10
|
code: {
|
|
11
11
|
$type: 'string',
|
|
12
12
|
$required: true
|
|
13
|
+
},
|
|
14
|
+
title: {
|
|
15
|
+
$type: 'string'
|
|
16
|
+
},
|
|
17
|
+
description: {
|
|
18
|
+
$type: 'string'
|
|
13
19
|
}
|
|
14
20
|
}).compile('UpdateDashboardParams');
|
|
15
21
|
|
|
16
22
|
module.exports = ({ db }) => async function updateDashboard(params) {
|
|
17
|
-
const { dashboardId, code } = new UpdateDashboardParams(params);
|
|
23
|
+
const { dashboardId, code, title, description } = new UpdateDashboardParams(params);
|
|
18
24
|
|
|
19
25
|
const Dashboard = db.models[`__Studio_Dashboard`];
|
|
20
26
|
|
|
27
|
+
const updateObj = { code };
|
|
28
|
+
|
|
29
|
+
if (title) {
|
|
30
|
+
updateObj.title = title;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (description) {
|
|
34
|
+
updateObj.description = description;
|
|
35
|
+
}
|
|
36
|
+
|
|
21
37
|
const doc = await Dashboard.
|
|
22
|
-
findByIdAndUpdate(dashboardId,
|
|
38
|
+
findByIdAndUpdate(dashboardId, updateObj, { sanitizeFilter: true, returnDocument: 'after', overwriteImmutable: true });
|
|
23
39
|
|
|
24
40
|
let result = null;
|
|
25
41
|
try {
|
|
@@ -21,9 +21,9 @@ dashboardSchema.methods.evaluate = async function evaluate() {
|
|
|
21
21
|
const context = vm.createContext({ db: this.constructor.db });
|
|
22
22
|
let result = null;
|
|
23
23
|
result = await vm.runInContext(formatFunction(this.code), context);
|
|
24
|
-
if (result.$document?.
|
|
24
|
+
if (result.$document?.constructor?.modelName) {
|
|
25
25
|
let schemaPaths = {};
|
|
26
|
-
const Model = this.constructor.db.model(result.$document?.
|
|
26
|
+
const Model = this.constructor.db.model(result.$document?.constructor?.modelName);
|
|
27
27
|
for (const path of Object.keys(Model.schema.paths)) {
|
|
28
28
|
schemaPaths[path] = {
|
|
29
29
|
instance: Model.schema.paths[path].instance,
|
package/frontend/public/app.js
CHANGED
|
@@ -43,6 +43,9 @@ if (false) {} else {
|
|
|
43
43
|
createDashboard: function createDashboard(params) {
|
|
44
44
|
return client.post('/Dashboard/createDashboard', params).then(res => res.data);
|
|
45
45
|
},
|
|
46
|
+
deleteDashboard: function deleteDashboard(params) {
|
|
47
|
+
return client.post('/Dashboard/deleteDashboard', params).then(res => res.data)
|
|
48
|
+
},
|
|
46
49
|
getDashboard: function getDashboard(params) {
|
|
47
50
|
return client.put('/Dashboard/getDashboard', params).then(res => res.data);
|
|
48
51
|
},
|
|
@@ -367,7 +370,7 @@ module.exports = app => app.component('dashboard-document', {
|
|
|
367
370
|
return null;
|
|
368
371
|
},
|
|
369
372
|
schemaPaths() {
|
|
370
|
-
return Object.keys(this.value.$document
|
|
373
|
+
return Object.keys(this.value.$document?.schemaPaths || {}).sort((k1, k2) => {
|
|
371
374
|
if (k1 === '_id' && k2 !== '_id') {
|
|
372
375
|
return -1;
|
|
373
376
|
}
|
|
@@ -477,6 +480,8 @@ module.exports = app => app.component('dashboard', {
|
|
|
477
480
|
return {
|
|
478
481
|
status: 'loading',
|
|
479
482
|
code: '',
|
|
483
|
+
title: '',
|
|
484
|
+
description: '',
|
|
480
485
|
showEditor: false,
|
|
481
486
|
dashboard: null,
|
|
482
487
|
result: null
|
|
@@ -488,6 +493,8 @@ module.exports = app => app.component('dashboard', {
|
|
|
488
493
|
},
|
|
489
494
|
async updateCode(update) {
|
|
490
495
|
this.code = update.doc.code;
|
|
496
|
+
this.title = update.doc.title;
|
|
497
|
+
this.description = update.doc.description;
|
|
491
498
|
this.result = update.result;
|
|
492
499
|
}
|
|
493
500
|
},
|
|
@@ -498,6 +505,8 @@ module.exports = app => app.component('dashboard', {
|
|
|
498
505
|
}
|
|
499
506
|
this.dashboard = dashboard;
|
|
500
507
|
this.code = this.dashboard.code;
|
|
508
|
+
this.title = this.dashboard.title;
|
|
509
|
+
this.description = this.dashboard.description ?? '';
|
|
501
510
|
this.result = result;
|
|
502
511
|
this.status = 'loaded';
|
|
503
512
|
}
|
|
@@ -520,11 +529,13 @@ const template = __webpack_require__(/*! ./edit-dashboard.html */ "./frontend/sr
|
|
|
520
529
|
|
|
521
530
|
module.exports = app => app.component('edit-dashboard', {
|
|
522
531
|
template: template,
|
|
523
|
-
props: ['dashboardId', 'code'],
|
|
532
|
+
props: ['dashboardId', 'code', 'currentDescription', 'currentTitle'],
|
|
524
533
|
data: function() {
|
|
525
534
|
return {
|
|
526
535
|
status: 'loading',
|
|
527
536
|
editor: null,
|
|
537
|
+
title: '',
|
|
538
|
+
description: ''
|
|
528
539
|
}
|
|
529
540
|
},
|
|
530
541
|
methods: {
|
|
@@ -532,9 +543,12 @@ module.exports = app => app.component('edit-dashboard', {
|
|
|
532
543
|
this.$emit('close')
|
|
533
544
|
},
|
|
534
545
|
async updateCode() {
|
|
546
|
+
console.log('this.title', this.title, 'this.description', this.description)
|
|
535
547
|
const { doc, result } = await api.Dashboard.updateDashboard({
|
|
536
548
|
dashboardId: this.dashboardId,
|
|
537
|
-
code: this.editor.getValue()
|
|
549
|
+
code: this.editor.getValue(),
|
|
550
|
+
title: this.title,
|
|
551
|
+
description: this.description
|
|
538
552
|
});
|
|
539
553
|
this.$emit('update', { doc, result });
|
|
540
554
|
this.editor.setValue(doc.code);
|
|
@@ -560,8 +574,8 @@ module.exports = app => app.component('edit-dashboard', {
|
|
|
560
574
|
|
|
561
575
|
this.editor.focus();
|
|
562
576
|
// this.editor.refresh(); // if anything weird happens on load, this usually fixes it. However, this breaks it in this case.
|
|
563
|
-
|
|
564
|
-
|
|
577
|
+
this.description = this.currentDescription;
|
|
578
|
+
this.title = this.currentTitle;
|
|
565
579
|
}
|
|
566
580
|
});
|
|
567
581
|
|
|
@@ -586,8 +600,24 @@ module.exports = app => app.component('dashboards', {
|
|
|
586
600
|
data: () => ({
|
|
587
601
|
status: 'loading',
|
|
588
602
|
dashboards: [],
|
|
589
|
-
showCreateDashboardModal: false
|
|
603
|
+
showCreateDashboardModal: false,
|
|
604
|
+
showDeleteDashboardModal: null
|
|
590
605
|
}),
|
|
606
|
+
methods: {
|
|
607
|
+
async deleteDashboard(dashboard) {
|
|
608
|
+
if (!dashboard) {
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
await api.Dashboard.deleteDashboard({ dashboardId: dashboard._id });
|
|
612
|
+
const removedDashboard = this.dashboards.findIndex(x => x._id.toString() === dashboard._id.toString());
|
|
613
|
+
this.dashboards.splice(removedDashboard, 1);
|
|
614
|
+
this.showDeleteDashboardModal = null;
|
|
615
|
+
},
|
|
616
|
+
insertNewDashboard(dashboard) {
|
|
617
|
+
this.dashboards.push(dashboard);
|
|
618
|
+
this.showCreateDashboardModal = false;
|
|
619
|
+
}
|
|
620
|
+
},
|
|
591
621
|
async mounted() {
|
|
592
622
|
const { dashboards } = await api.Dashboard.getDashboards();
|
|
593
623
|
this.dashboards = dashboards;
|
|
@@ -676,6 +706,54 @@ appendCSS(__webpack_require__(/*! ./document-details.css */ "./frontend/src/docu
|
|
|
676
706
|
module.exports = app => app.component('document-details', {
|
|
677
707
|
template,
|
|
678
708
|
props: ['document', 'schemaPaths', 'editting', 'changes', 'invalid'],
|
|
709
|
+
computed: {
|
|
710
|
+
virtuals() {
|
|
711
|
+
if (this.schemaPaths == null) {
|
|
712
|
+
return [];
|
|
713
|
+
}
|
|
714
|
+
if (this.document == null) {
|
|
715
|
+
return [];
|
|
716
|
+
}
|
|
717
|
+
const exists = this.schemaPaths.map(x => x.path);
|
|
718
|
+
const docKeys = Object.keys(this.document);
|
|
719
|
+
const result = [];
|
|
720
|
+
for (let i = 0; i < docKeys.length; i++) {
|
|
721
|
+
if (!exists.includes(docKeys[i])) {
|
|
722
|
+
result.push({ name: docKeys[i], value: this.document[docKeys[i]] });
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
return result;
|
|
727
|
+
},
|
|
728
|
+
}
|
|
729
|
+
})
|
|
730
|
+
|
|
731
|
+
/***/ }),
|
|
732
|
+
|
|
733
|
+
/***/ "./frontend/src/document-details/document-property/document-property.js":
|
|
734
|
+
/*!******************************************************************************!*\
|
|
735
|
+
!*** ./frontend/src/document-details/document-property/document-property.js ***!
|
|
736
|
+
\******************************************************************************/
|
|
737
|
+
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
738
|
+
|
|
739
|
+
"use strict";
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
const mpath = __webpack_require__(/*! mpath */ "./node_modules/mpath/index.js");
|
|
743
|
+
const template = __webpack_require__(/*! ./document-property.html */ "./frontend/src/document-details/document-property/document-property.html")
|
|
744
|
+
|
|
745
|
+
const appendCSS = __webpack_require__(/*! ../../appendCSS */ "./frontend/src/appendCSS.js");
|
|
746
|
+
|
|
747
|
+
appendCSS(__webpack_require__(/*! ./document-property.css */ "./frontend/src/document-details/document-property/document-property.css"));
|
|
748
|
+
|
|
749
|
+
module.exports = app => app.component('document-property', {
|
|
750
|
+
template,
|
|
751
|
+
data: function() {
|
|
752
|
+
return {
|
|
753
|
+
dateType: 'picker' // picker, iso
|
|
754
|
+
}
|
|
755
|
+
},
|
|
756
|
+
props: ['document', 'schemaPaths', 'editting', 'changes', 'invalid'],
|
|
679
757
|
methods: {
|
|
680
758
|
getComponentForPath(schemaPath) {
|
|
681
759
|
if (schemaPath.instance === 'Array') {
|
|
@@ -699,30 +777,19 @@ module.exports = app => app.component('document-details', {
|
|
|
699
777
|
return 'edit-default';
|
|
700
778
|
},
|
|
701
779
|
getValueForPath(path) {
|
|
780
|
+
if (this.document == null) {
|
|
781
|
+
return undefined;
|
|
782
|
+
}
|
|
702
783
|
return mpath.get(path, this.document);
|
|
703
784
|
},
|
|
704
785
|
getEditValueForPath({ path }) {
|
|
705
786
|
if (!this.changes) {
|
|
706
787
|
return;
|
|
707
788
|
}
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
},
|
|
711
|
-
computed: {
|
|
712
|
-
virtuals() {
|
|
713
|
-
if (this.schemaPaths == null) {
|
|
714
|
-
return [];
|
|
715
|
-
}
|
|
716
|
-
const exists = this.schemaPaths.map(x => x.path);
|
|
717
|
-
const docKeys = Object.keys(this.document);
|
|
718
|
-
const result = [];
|
|
719
|
-
for (let i = 0; i < docKeys.length; i++) {
|
|
720
|
-
if (!exists.includes(docKeys[i])) {
|
|
721
|
-
result.push({ name: docKeys[i], value: this.document[docKeys[i]] });
|
|
722
|
-
}
|
|
789
|
+
if (!this.document) {
|
|
790
|
+
return;
|
|
723
791
|
}
|
|
724
|
-
|
|
725
|
-
return result;
|
|
792
|
+
return path in this.changes ? this.changes[path] : mpath.get(path, this.document);
|
|
726
793
|
}
|
|
727
794
|
}
|
|
728
795
|
})
|
|
@@ -927,13 +994,11 @@ const template = __webpack_require__(/*! ./edit-date.html */ "./frontend/src/edi
|
|
|
927
994
|
|
|
928
995
|
module.exports = app => app.component('edit-date', {
|
|
929
996
|
template: template,
|
|
930
|
-
props: ['value'],
|
|
997
|
+
props: ['value', 'format'],
|
|
931
998
|
emits: ['input'],
|
|
932
|
-
data:
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
}
|
|
936
|
-
},
|
|
999
|
+
data: () => ({
|
|
1000
|
+
inputType: ''
|
|
1001
|
+
}),
|
|
937
1002
|
computed: {
|
|
938
1003
|
valueAsLocalString() {
|
|
939
1004
|
if (this.value == null) {
|
|
@@ -958,6 +1023,9 @@ module.exports = app => app.component('edit-date', {
|
|
|
958
1023
|
}
|
|
959
1024
|
const date = new Date(this.value);
|
|
960
1025
|
return date.toISOString();
|
|
1026
|
+
},
|
|
1027
|
+
dateSelection() {
|
|
1028
|
+
return this.format;
|
|
961
1029
|
}
|
|
962
1030
|
}
|
|
963
1031
|
});
|
|
@@ -2514,7 +2582,7 @@ module.exports = "<div>\n <div v-if=\"Array.isArray(result)\">\n <div v-for=
|
|
|
2514
2582
|
/***/ ((module) => {
|
|
2515
2583
|
|
|
2516
2584
|
"use strict";
|
|
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\">{{
|
|
2585
|
+
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\">{{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 :currentDescription=\"description\"\n :currentTitle=\"title\"\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>";
|
|
2518
2586
|
|
|
2519
2587
|
/***/ }),
|
|
2520
2588
|
|
|
@@ -2525,7 +2593,7 @@ module.exports = "<div class=\"dashboard px-1\">\n <div v-if=\"dashboard\" clas
|
|
|
2525
2593
|
/***/ ((module) => {
|
|
2526
2594
|
|
|
2527
2595
|
"use strict";
|
|
2528
|
-
module.exports = "<div>\n <textarea ref=\"codeEditor\">{{code}}</textarea>\n <button @click=\"updateCode\"
|
|
2596
|
+
module.exports = "<div class=\"p-4 bg-gray-100 rounded-lg shadow-lg\">\n <div>\n <input v-model=\"title\" class=\"w-full p-2 mb-4 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\" placeholder=\"Title\"/>\n </div>\n <div>\n <textarea v-model=\"description\" class=\"w-full p-2 mb-4 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\" rows=\"4\" placeholder=\"Description\">{{description}}</textarea>\n </div>\n <div>\n <textarea ref=\"codeEditor\" class=\"w-full p-2 mb-4 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500\" rows=\"6\">{{code}}</textarea>\n </div>\n <div class=\"flex space-x-2\">\n <button @click=\"updateCode\" class=\"px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500\">Submit</button>\n <button @click=\"closeEditor\" 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-500\">Cancel</button>\n </div>\n</div>";
|
|
2529
2597
|
|
|
2530
2598
|
/***/ }),
|
|
2531
2599
|
|
|
@@ -2536,7 +2604,7 @@ module.exports = "<div>\n <textarea ref=\"codeEditor\">{{code}}</textarea>\n
|
|
|
2536
2604
|
/***/ ((module) => {
|
|
2537
2605
|
|
|
2538
2606
|
"use strict";
|
|
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>";
|
|
2607
|
+
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 <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-teal-600 hover:text-teal-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>";
|
|
2540
2608
|
|
|
2541
2609
|
/***/ }),
|
|
2542
2610
|
|
|
@@ -2569,7 +2637,7 @@ module.exports = "<div>\n {{value}}\n</div>";
|
|
|
2569
2637
|
/***/ ((module) => {
|
|
2570
2638
|
|
|
2571
2639
|
"use strict";
|
|
2572
|
-
module.exports = ".document-details {\n width: 100%;\n}\n\n.document-details .value {\n padding-top: 10px;\n padding-bottom: 10px;\n}\n\n.document-details .path-key {\n background-color: #f0f0f0;\n margin-bottom: 0.5em;\n}\n\n.document-details .path-type {\n color: rgba(0,0,0,.36);\n font-size: 0.8em;\n}";
|
|
2640
|
+
module.exports = ".document-details {\n width: 100%;\n}\n\n.document-details .value {\n padding-top: 10px;\n padding-bottom: 10px;\n}\n\n.document-details .path-key {\n background-color: #f0f0f0;\n margin-bottom: 0.5em;\n}\n\n.document-details .path-type {\n color: rgba(0,0,0,.36);\n font-size: 0.8em;\n}\n\n.document-details .date-position {\n float: right;\n margin-top: -7px;\n}";
|
|
2573
2641
|
|
|
2574
2642
|
/***/ }),
|
|
2575
2643
|
|
|
@@ -2580,7 +2648,29 @@ module.exports = ".document-details {\n width: 100%;\n}\n\n.document-details .v
|
|
|
2580
2648
|
/***/ ((module) => {
|
|
2581
2649
|
|
|
2582
2650
|
"use strict";
|
|
2583
|
-
module.exports = "<div class=\"document-details\">\n <
|
|
2651
|
+
module.exports = "<div class=\"document-details\">\n <document-property\n :document=\"document\"\n :schemaPaths=\"schemaPaths\"\n :editting=\"editting\"\n :changes=\"changes\"\n :invalid=\"invalid\"></document-property>\n <div v-for=\"path in virtuals\" class=\"mb-2\">\n <div class=\"p-1 mb-1 bg-slate-100\">\n {{path.name}}\n <span class=\"path-type\">\n (virtual)\n </span>\n </div>\n <div v-if=\"path.value == null\" class=\"text-sky-800\">\n {{'' + path.value}}\n </div>\n <div v-else>\n {{path.value}}\n </div>\n </div>\n</div>";
|
|
2652
|
+
|
|
2653
|
+
/***/ }),
|
|
2654
|
+
|
|
2655
|
+
/***/ "./frontend/src/document-details/document-property/document-property.css":
|
|
2656
|
+
/*!*******************************************************************************!*\
|
|
2657
|
+
!*** ./frontend/src/document-details/document-property/document-property.css ***!
|
|
2658
|
+
\*******************************************************************************/
|
|
2659
|
+
/***/ ((module) => {
|
|
2660
|
+
|
|
2661
|
+
"use strict";
|
|
2662
|
+
module.exports = ".document-details {\n width: 100%;\n }\n \n .document-details .value {\n padding-top: 10px;\n padding-bottom: 10px;\n }\n \n .document-details .path-key {\n background-color: #f0f0f0;\n margin-bottom: 0.5em;\n }\n \n .document-details .path-type {\n color: rgba(0,0,0,.36);\n font-size: 0.8em;\n }\n \n .document-details .date-position {\n float: right;\n margin-top: -7px;\n }";
|
|
2663
|
+
|
|
2664
|
+
/***/ }),
|
|
2665
|
+
|
|
2666
|
+
/***/ "./frontend/src/document-details/document-property/document-property.html":
|
|
2667
|
+
/*!********************************************************************************!*\
|
|
2668
|
+
!*** ./frontend/src/document-details/document-property/document-property.html ***!
|
|
2669
|
+
\********************************************************************************/
|
|
2670
|
+
/***/ ((module) => {
|
|
2671
|
+
|
|
2672
|
+
"use strict";
|
|
2673
|
+
module.exports = "<div>\n <div v-for=\"path in schemaPaths\" class=\"value\">\n <div class=\"relative path-key p-1 flex\">\n <div class=\"grow\">\n {{path.path}}\n <span class=\"path-type\">\n ({{(path.instance || 'unknown').toLowerCase()}})\n </span>\n </div>\n <div v-if=\"editting && path.instance === 'Date'\" class=\"flex gap-1.5\">\n <div\n @click=\"dateType = 'picker'\"\n :class=\"dateType === 'picker' ? 'bg-white' : ''\"\n class=\"self-stretch px-2 py-1 rounded-sm justify-center items-center gap-1.5 flex cursor-pointer\">\n <div\n :class=\"dateType === 'picker' ? 'text-sky-600' : 'text-black'\"\n class=\"text-xs font-medium font-['Lato'] capitalize leading-tight\">\n Date Picker\n </div>\n </div>\n <div\n @click=\"dateType = 'iso'\"\n :class=\"dateType === 'iso' ? 'bg-white' : ''\"\n class=\"self-stretch px-2 py-1 rounded-sm justify-center items-center gap-1.5 flex cursor-pointer\">\n <div\n :class=\"dateType === 'iso' ? 'text-sky-600' : 'text-black'\"\n class=\"text-xs font-medium font-['Lato'] capitalize leading-tight\">\n ISO String\n </div>\n </div>\n </div>\n </div>\n <div v-if=\"editting && path.path !== '_id'\" class=\"pl-1\">\n <component\n :is=\"getEditComponentForPath(path)\"\n :value=\"getEditValueForPath(path)\"\n :format=\"dateType\"\n @input=\"changes[path.path] = $event; delete invalid[path.path];\"\n @error=\"invalid[path.path] = $event;\"\n >\n </component>\n </div>\n <div v-else class=\"pl-1\">\n <component :is=\"getComponentForPath(path)\" :value=\"getValueForPath(path.path)\"></component>\n </div>\n </div>\n</div>";
|
|
2584
2674
|
|
|
2585
2675
|
/***/ }),
|
|
2586
2676
|
|
|
@@ -2646,7 +2736,7 @@ module.exports = "<div class=\"edit-array\">\n <textarea\n ref=\"arrayEditor
|
|
|
2646
2736
|
/***/ ((module) => {
|
|
2647
2737
|
|
|
2648
2738
|
"use strict";
|
|
2649
|
-
module.exports = "<div>\n <
|
|
2739
|
+
module.exports = "<div>\n <input v-if=\"dateSelection == 'picker'\" class=\"w-64 h-8 border border-gray-300 outline-0\" type=\"datetime-local\" :value=\"valueAsLocalString\" @input=\"$emit('input', $event.target.value)\">\n <input v-if=\"dateSelection == 'iso'\" type=\"text\" class=\"w-64 h-8 border border-gray-300 outline-0\" :value=\"valueAsISOString\" @input=\"$emit('input', $event.target.value)\">\n</div>";
|
|
2650
2740
|
|
|
2651
2741
|
/***/ }),
|
|
2652
2742
|
|
|
@@ -10571,6 +10661,7 @@ __webpack_require__(/*! ./detail-default/detail-default */ "./frontend/src/detai
|
|
|
10571
10661
|
__webpack_require__(/*! ./document/document */ "./frontend/src/document/document.js")(app);
|
|
10572
10662
|
__webpack_require__(/*! ./document/confirm-changes/confirm-changes */ "./frontend/src/document/confirm-changes/confirm-changes.js")(app);
|
|
10573
10663
|
__webpack_require__(/*! ./document-details/document-details */ "./frontend/src/document-details/document-details.js")(app);
|
|
10664
|
+
__webpack_require__(/*! ./document-details/document-property/document-property */ "./frontend/src/document-details/document-property/document-property.js")(app);
|
|
10574
10665
|
__webpack_require__(/*! ./edit-array/edit-array */ "./frontend/src/edit-array/edit-array.js")(app);
|
|
10575
10666
|
__webpack_require__(/*! ./edit-default/edit-default */ "./frontend/src/edit-default/edit-default.js")(app);
|
|
10576
10667
|
__webpack_require__(/*! ./edit-number/edit-number */ "./frontend/src/edit-number/edit-number.js")(app);
|
package/frontend/public/tw.css
CHANGED
|
@@ -638,10 +638,6 @@ video {
|
|
|
638
638
|
margin-bottom: 1rem;
|
|
639
639
|
}
|
|
640
640
|
|
|
641
|
-
.mb-\[-1px\] {
|
|
642
|
-
margin-bottom: -1px;
|
|
643
|
-
}
|
|
644
|
-
|
|
645
641
|
.ml-3 {
|
|
646
642
|
margin-left: 0.75rem;
|
|
647
643
|
}
|
|
@@ -774,6 +770,10 @@ video {
|
|
|
774
770
|
flex-grow: 1;
|
|
775
771
|
}
|
|
776
772
|
|
|
773
|
+
.cursor-pointer {
|
|
774
|
+
cursor: pointer;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
777
|
.list-disc {
|
|
778
778
|
list-style-type: disc;
|
|
779
779
|
}
|
|
@@ -790,8 +790,16 @@ video {
|
|
|
790
790
|
align-items: center;
|
|
791
791
|
}
|
|
792
792
|
|
|
793
|
-
.justify-
|
|
794
|
-
justify-content:
|
|
793
|
+
.justify-center {
|
|
794
|
+
justify-content: center;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
.gap-1 {
|
|
798
|
+
gap: 0.25rem;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
.gap-1\.5 {
|
|
802
|
+
gap: 0.375rem;
|
|
795
803
|
}
|
|
796
804
|
|
|
797
805
|
.gap-2 {
|
|
@@ -806,6 +814,12 @@ video {
|
|
|
806
814
|
row-gap: 1.75rem;
|
|
807
815
|
}
|
|
808
816
|
|
|
817
|
+
.space-x-2 > :not([hidden]) ~ :not([hidden]) {
|
|
818
|
+
--tw-space-x-reverse: 0;
|
|
819
|
+
margin-right: calc(0.5rem * var(--tw-space-x-reverse));
|
|
820
|
+
margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
|
|
821
|
+
}
|
|
822
|
+
|
|
809
823
|
.space-y-1 > :not([hidden]) ~ :not([hidden]) {
|
|
810
824
|
--tw-space-y-reverse: 0;
|
|
811
825
|
margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));
|
|
@@ -828,6 +842,10 @@ video {
|
|
|
828
842
|
border-color: rgb(209 213 219 / var(--tw-divide-opacity));
|
|
829
843
|
}
|
|
830
844
|
|
|
845
|
+
.self-stretch {
|
|
846
|
+
align-self: stretch;
|
|
847
|
+
}
|
|
848
|
+
|
|
831
849
|
.overflow-auto {
|
|
832
850
|
overflow: auto;
|
|
833
851
|
}
|
|
@@ -854,6 +872,10 @@ video {
|
|
|
854
872
|
border-radius: 0.25rem;
|
|
855
873
|
}
|
|
856
874
|
|
|
875
|
+
.rounded-lg {
|
|
876
|
+
border-radius: 0.5rem;
|
|
877
|
+
}
|
|
878
|
+
|
|
857
879
|
.rounded-md {
|
|
858
880
|
border-radius: 0.375rem;
|
|
859
881
|
}
|
|
@@ -862,6 +884,10 @@ video {
|
|
|
862
884
|
border-radius: 0px;
|
|
863
885
|
}
|
|
864
886
|
|
|
887
|
+
.rounded-sm {
|
|
888
|
+
border-radius: 0.125rem;
|
|
889
|
+
}
|
|
890
|
+
|
|
865
891
|
.rounded-l-md {
|
|
866
892
|
border-top-left-radius: 0.375rem;
|
|
867
893
|
border-bottom-left-radius: 0.375rem;
|
|
@@ -872,14 +898,6 @@ video {
|
|
|
872
898
|
border-bottom-right-radius: 0.375rem;
|
|
873
899
|
}
|
|
874
900
|
|
|
875
|
-
.rounded-tl-md {
|
|
876
|
-
border-top-left-radius: 0.375rem;
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
.rounded-tr-md {
|
|
880
|
-
border-top-right-radius: 0.375rem;
|
|
881
|
-
}
|
|
882
|
-
|
|
883
901
|
.border {
|
|
884
902
|
border-width: 1px;
|
|
885
903
|
}
|
|
@@ -924,11 +942,26 @@ video {
|
|
|
924
942
|
border-color: transparent;
|
|
925
943
|
}
|
|
926
944
|
|
|
945
|
+
.bg-blue-500 {
|
|
946
|
+
--tw-bg-opacity: 1;
|
|
947
|
+
background-color: rgb(59 130 246 / var(--tw-bg-opacity));
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
.bg-gray-100 {
|
|
951
|
+
--tw-bg-opacity: 1;
|
|
952
|
+
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
|
|
953
|
+
}
|
|
954
|
+
|
|
927
955
|
.bg-gray-200 {
|
|
928
956
|
--tw-bg-opacity: 1;
|
|
929
957
|
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
|
|
930
958
|
}
|
|
931
959
|
|
|
960
|
+
.bg-gray-500 {
|
|
961
|
+
--tw-bg-opacity: 1;
|
|
962
|
+
background-color: rgb(107 114 128 / var(--tw-bg-opacity));
|
|
963
|
+
}
|
|
964
|
+
|
|
932
965
|
.bg-green-600 {
|
|
933
966
|
--tw-bg-opacity: 1;
|
|
934
967
|
background-color: rgb(22 163 74 / var(--tw-bg-opacity));
|
|
@@ -939,6 +972,11 @@ video {
|
|
|
939
972
|
background-color: rgb(254 242 242 / var(--tw-bg-opacity));
|
|
940
973
|
}
|
|
941
974
|
|
|
975
|
+
.bg-red-500 {
|
|
976
|
+
--tw-bg-opacity: 1;
|
|
977
|
+
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
|
978
|
+
}
|
|
979
|
+
|
|
942
980
|
.bg-red-600 {
|
|
943
981
|
--tw-bg-opacity: 1;
|
|
944
982
|
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
|
|
@@ -1096,6 +1134,10 @@ video {
|
|
|
1096
1134
|
vertical-align: middle;
|
|
1097
1135
|
}
|
|
1098
1136
|
|
|
1137
|
+
.font-\[\'Lato\'\] {
|
|
1138
|
+
font-family: 'Lato';
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1099
1141
|
.text-base {
|
|
1100
1142
|
font-size: 1rem;
|
|
1101
1143
|
line-height: 1.5rem;
|
|
@@ -1116,6 +1158,11 @@ video {
|
|
|
1116
1158
|
line-height: 1.75rem;
|
|
1117
1159
|
}
|
|
1118
1160
|
|
|
1161
|
+
.text-xs {
|
|
1162
|
+
font-size: 0.75rem;
|
|
1163
|
+
line-height: 1rem;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1119
1166
|
.font-bold {
|
|
1120
1167
|
font-weight: 700;
|
|
1121
1168
|
}
|
|
@@ -1128,10 +1175,18 @@ video {
|
|
|
1128
1175
|
font-weight: 600;
|
|
1129
1176
|
}
|
|
1130
1177
|
|
|
1178
|
+
.capitalize {
|
|
1179
|
+
text-transform: capitalize;
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1131
1182
|
.leading-6 {
|
|
1132
1183
|
line-height: 1.5rem;
|
|
1133
1184
|
}
|
|
1134
1185
|
|
|
1186
|
+
.leading-tight {
|
|
1187
|
+
line-height: 1.25;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1135
1190
|
.text-black {
|
|
1136
1191
|
--tw-text-opacity: 1;
|
|
1137
1192
|
color: rgb(0 0 0 / var(--tw-text-opacity));
|
|
@@ -1152,11 +1207,6 @@ video {
|
|
|
1152
1207
|
color: rgb(55 65 81 / var(--tw-text-opacity));
|
|
1153
1208
|
}
|
|
1154
1209
|
|
|
1155
|
-
.text-gray-800 {
|
|
1156
|
-
--tw-text-opacity: 1;
|
|
1157
|
-
color: rgb(31 41 55 / var(--tw-text-opacity));
|
|
1158
|
-
}
|
|
1159
|
-
|
|
1160
1210
|
.text-gray-900 {
|
|
1161
1211
|
--tw-text-opacity: 1;
|
|
1162
1212
|
color: rgb(17 24 39 / var(--tw-text-opacity));
|
|
@@ -1177,6 +1227,11 @@ video {
|
|
|
1177
1227
|
color: rgb(153 27 27 / var(--tw-text-opacity));
|
|
1178
1228
|
}
|
|
1179
1229
|
|
|
1230
|
+
.text-sky-600 {
|
|
1231
|
+
--tw-text-opacity: 1;
|
|
1232
|
+
color: rgb(2 132 199 / var(--tw-text-opacity));
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1180
1235
|
.text-sky-800 {
|
|
1181
1236
|
--tw-text-opacity: 1;
|
|
1182
1237
|
color: rgb(7 89 133 / var(--tw-text-opacity));
|
|
@@ -1192,6 +1247,12 @@ video {
|
|
|
1192
1247
|
color: rgb(255 255 255 / var(--tw-text-opacity));
|
|
1193
1248
|
}
|
|
1194
1249
|
|
|
1250
|
+
.shadow-lg {
|
|
1251
|
+
--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
1252
|
+
--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
|
|
1253
|
+
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1195
1256
|
.shadow-sm {
|
|
1196
1257
|
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
|
1197
1258
|
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
|
@@ -1272,9 +1333,9 @@ video {
|
|
|
1272
1333
|
border-color: rgb(209 213 219 / var(--tw-border-opacity));
|
|
1273
1334
|
}
|
|
1274
1335
|
|
|
1275
|
-
.hover\:bg-
|
|
1336
|
+
.hover\:bg-blue-600:hover {
|
|
1276
1337
|
--tw-bg-opacity: 1;
|
|
1277
|
-
background-color: rgb(
|
|
1338
|
+
background-color: rgb(37 99 235 / var(--tw-bg-opacity));
|
|
1278
1339
|
}
|
|
1279
1340
|
|
|
1280
1341
|
.hover\:bg-gray-300:hover {
|
|
@@ -1287,6 +1348,11 @@ video {
|
|
|
1287
1348
|
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
|
|
1288
1349
|
}
|
|
1289
1350
|
|
|
1351
|
+
.hover\:bg-gray-600:hover {
|
|
1352
|
+
--tw-bg-opacity: 1;
|
|
1353
|
+
background-color: rgb(75 85 99 / var(--tw-bg-opacity));
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1290
1356
|
.hover\:bg-green-500:hover {
|
|
1291
1357
|
--tw-bg-opacity: 1;
|
|
1292
1358
|
background-color: rgb(34 197 94 / var(--tw-bg-opacity));
|
|
@@ -1297,6 +1363,11 @@ video {
|
|
|
1297
1363
|
background-color: rgb(239 68 68 / var(--tw-bg-opacity));
|
|
1298
1364
|
}
|
|
1299
1365
|
|
|
1366
|
+
.hover\:bg-red-600:hover {
|
|
1367
|
+
--tw-bg-opacity: 1;
|
|
1368
|
+
background-color: rgb(220 38 38 / var(--tw-bg-opacity));
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1300
1371
|
.hover\:bg-slate-500:hover {
|
|
1301
1372
|
--tw-bg-opacity: 1;
|
|
1302
1373
|
background-color: rgb(100 116 139 / var(--tw-bg-opacity));
|
|
@@ -1326,12 +1397,43 @@ video {
|
|
|
1326
1397
|
z-index: 10;
|
|
1327
1398
|
}
|
|
1328
1399
|
|
|
1400
|
+
.focus\:outline-none:focus {
|
|
1401
|
+
outline: 2px solid transparent;
|
|
1402
|
+
outline-offset: 2px;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1329
1405
|
.focus\:ring-0:focus {
|
|
1330
1406
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
|
1331
1407
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
|
1332
1408
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
1333
1409
|
}
|
|
1334
1410
|
|
|
1411
|
+
.focus\:ring-2:focus {
|
|
1412
|
+
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
|
1413
|
+
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
|
1414
|
+
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
.focus\:ring-blue-500:focus {
|
|
1418
|
+
--tw-ring-opacity: 1;
|
|
1419
|
+
--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity));
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
.focus\:ring-gray-500:focus {
|
|
1423
|
+
--tw-ring-opacity: 1;
|
|
1424
|
+
--tw-ring-color: rgb(107 114 128 / var(--tw-ring-opacity));
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
.focus\:ring-gray-600:focus {
|
|
1428
|
+
--tw-ring-opacity: 1;
|
|
1429
|
+
--tw-ring-color: rgb(75 85 99 / var(--tw-ring-opacity));
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
.focus\:ring-red-500:focus {
|
|
1433
|
+
--tw-ring-opacity: 1;
|
|
1434
|
+
--tw-ring-color: rgb(239 68 68 / var(--tw-ring-opacity));
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1335
1437
|
.focus-visible\:outline:focus-visible {
|
|
1336
1438
|
outline-style: solid;
|
|
1337
1439
|
}
|
package/frontend/src/api.js
CHANGED
|
@@ -74,6 +74,9 @@ if (config__isLambda) {
|
|
|
74
74
|
createDashboard: function createDashboard(params) {
|
|
75
75
|
return client.post('/Dashboard/createDashboard', params).then(res => res.data);
|
|
76
76
|
},
|
|
77
|
+
deleteDashboard: function deleteDashboard(params) {
|
|
78
|
+
return client.post('/Dashboard/deleteDashboard', params).then(res => res.data)
|
|
79
|
+
},
|
|
77
80
|
getDashboard: function getDashboard(params) {
|
|
78
81
|
return client.put('/Dashboard/getDashboard', params).then(res => res.data);
|
|
79
82
|
},
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<div class="dashboard px-1">
|
|
2
2
|
<div v-if="dashboard" class="max-w-5xl mx-auto">
|
|
3
3
|
<div class="flex items-center w-full">
|
|
4
|
-
<h2 class="mt-4 mb-4 text-gray-900 font-semibold text-xl grow shrink">{{
|
|
4
|
+
<h2 class="mt-4 mb-4 text-gray-900 font-semibold text-xl grow shrink">{{title}}</h2>
|
|
5
5
|
<div>
|
|
6
6
|
<button
|
|
7
7
|
v-if="!showEditor"
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
<edit-dashboard
|
|
20
20
|
:dashboardId="dashboard._id"
|
|
21
21
|
:code="code"
|
|
22
|
+
:currentDescription="description"
|
|
23
|
+
:currentTitle="title"
|
|
22
24
|
@close="showEditor=false;"
|
|
23
25
|
@update="updateCode"></edit-dashboard>
|
|
24
26
|
</div>
|
|
@@ -10,6 +10,8 @@ module.exports = app => app.component('dashboard', {
|
|
|
10
10
|
return {
|
|
11
11
|
status: 'loading',
|
|
12
12
|
code: '',
|
|
13
|
+
title: '',
|
|
14
|
+
description: '',
|
|
13
15
|
showEditor: false,
|
|
14
16
|
dashboard: null,
|
|
15
17
|
result: null
|
|
@@ -21,6 +23,8 @@ module.exports = app => app.component('dashboard', {
|
|
|
21
23
|
},
|
|
22
24
|
async updateCode(update) {
|
|
23
25
|
this.code = update.doc.code;
|
|
26
|
+
this.title = update.doc.title;
|
|
27
|
+
this.description = update.doc.description;
|
|
24
28
|
this.result = update.result;
|
|
25
29
|
}
|
|
26
30
|
},
|
|
@@ -31,6 +35,8 @@ module.exports = app => app.component('dashboard', {
|
|
|
31
35
|
}
|
|
32
36
|
this.dashboard = dashboard;
|
|
33
37
|
this.code = this.dashboard.code;
|
|
38
|
+
this.title = this.dashboard.title;
|
|
39
|
+
this.description = this.dashboard.description ?? '';
|
|
34
40
|
this.result = result;
|
|
35
41
|
this.status = 'loaded';
|
|
36
42
|
}
|
|
@@ -1,5 +1,15 @@
|
|
|
1
|
-
<div>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
<div class="p-4 bg-gray-100 rounded-lg shadow-lg">
|
|
2
|
+
<div>
|
|
3
|
+
<input v-model="title" class="w-full p-2 mb-4 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Title"/>
|
|
4
|
+
</div>
|
|
5
|
+
<div>
|
|
6
|
+
<textarea v-model="description" class="w-full p-2 mb-4 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" rows="4" placeholder="Description">{{description}}</textarea>
|
|
7
|
+
</div>
|
|
8
|
+
<div>
|
|
9
|
+
<textarea ref="codeEditor" class="w-full p-2 mb-4 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" rows="6">{{code}}</textarea>
|
|
10
|
+
</div>
|
|
11
|
+
<div class="flex space-x-2">
|
|
12
|
+
<button @click="updateCode" class="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500">Submit</button>
|
|
13
|
+
<button @click="closeEditor" 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-500">Cancel</button>
|
|
14
|
+
</div>
|
|
5
15
|
</div>
|
|
@@ -5,11 +5,13 @@ const template = require('./edit-dashboard.html');
|
|
|
5
5
|
|
|
6
6
|
module.exports = app => app.component('edit-dashboard', {
|
|
7
7
|
template: template,
|
|
8
|
-
props: ['dashboardId', 'code'],
|
|
8
|
+
props: ['dashboardId', 'code', 'currentDescription', 'currentTitle'],
|
|
9
9
|
data: function() {
|
|
10
10
|
return {
|
|
11
11
|
status: 'loading',
|
|
12
12
|
editor: null,
|
|
13
|
+
title: '',
|
|
14
|
+
description: ''
|
|
13
15
|
}
|
|
14
16
|
},
|
|
15
17
|
methods: {
|
|
@@ -17,9 +19,12 @@ module.exports = app => app.component('edit-dashboard', {
|
|
|
17
19
|
this.$emit('close')
|
|
18
20
|
},
|
|
19
21
|
async updateCode() {
|
|
22
|
+
console.log('this.title', this.title, 'this.description', this.description)
|
|
20
23
|
const { doc, result } = await api.Dashboard.updateDashboard({
|
|
21
24
|
dashboardId: this.dashboardId,
|
|
22
|
-
code: this.editor.getValue()
|
|
25
|
+
code: this.editor.getValue(),
|
|
26
|
+
title: this.title,
|
|
27
|
+
description: this.description
|
|
23
28
|
});
|
|
24
29
|
this.$emit('update', { doc, result });
|
|
25
30
|
this.editor.setValue(doc.code);
|
|
@@ -45,7 +50,7 @@ module.exports = app => app.component('edit-dashboard', {
|
|
|
45
50
|
|
|
46
51
|
this.editor.focus();
|
|
47
52
|
// this.editor.refresh(); // if anything weird happens on load, this usually fixes it. However, this breaks it in this case.
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
this.description = this.currentDescription;
|
|
54
|
+
this.title = this.currentTitle;
|
|
50
55
|
}
|
|
51
56
|
});
|
|
@@ -15,7 +15,7 @@ module.exports = app => app.component('dashboard-document', {
|
|
|
15
15
|
return null;
|
|
16
16
|
},
|
|
17
17
|
schemaPaths() {
|
|
18
|
-
return Object.keys(this.value.$document
|
|
18
|
+
return Object.keys(this.value.$document?.schemaPaths || {}).sort((k1, k2) => {
|
|
19
19
|
if (k1 === '_id' && k2 !== '_id') {
|
|
20
20
|
return -1;
|
|
21
21
|
}
|
|
@@ -59,6 +59,13 @@
|
|
|
59
59
|
View
|
|
60
60
|
</router-link>
|
|
61
61
|
</td>
|
|
62
|
+
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8">
|
|
63
|
+
<button
|
|
64
|
+
@click="showDeleteDashboardModal=dashboard"
|
|
65
|
+
class="text-teal-600 hover:text-teal-900">
|
|
66
|
+
Delete
|
|
67
|
+
</button>
|
|
68
|
+
</td>
|
|
62
69
|
</tr>
|
|
63
70
|
|
|
64
71
|
<!-- More people... -->
|
|
@@ -73,7 +80,18 @@
|
|
|
73
80
|
<template v-slot:body>
|
|
74
81
|
<div class="modal-exit" @click="showCreateDashboardModal = false;">×</div>
|
|
75
82
|
|
|
76
|
-
<create-dashboard></create-dashboard>
|
|
83
|
+
<create-dashboard @close="insertNewDashboard"></create-dashboard>
|
|
84
|
+
</template>
|
|
85
|
+
</modal>
|
|
86
|
+
|
|
87
|
+
<modal v-if="showDeleteDashboardModal">
|
|
88
|
+
<template v-slot:body>
|
|
89
|
+
<div class="modal-exit" @click="showDeleteDashboardModal = null;">×</div>
|
|
90
|
+
<h2>Are you sure you want to delete this dashboard titled {{showDeleteDashboardModal.title}}?</h2>
|
|
91
|
+
<div class="flex space-x-2">
|
|
92
|
+
<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>
|
|
93
|
+
<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>
|
|
94
|
+
</div>
|
|
77
95
|
</template>
|
|
78
96
|
</modal>
|
|
79
97
|
</div>
|
|
@@ -9,8 +9,24 @@ module.exports = app => app.component('dashboards', {
|
|
|
9
9
|
data: () => ({
|
|
10
10
|
status: 'loading',
|
|
11
11
|
dashboards: [],
|
|
12
|
-
showCreateDashboardModal: false
|
|
12
|
+
showCreateDashboardModal: false,
|
|
13
|
+
showDeleteDashboardModal: null
|
|
13
14
|
}),
|
|
15
|
+
methods: {
|
|
16
|
+
async deleteDashboard(dashboard) {
|
|
17
|
+
if (!dashboard) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
await api.Dashboard.deleteDashboard({ dashboardId: dashboard._id });
|
|
21
|
+
const removedDashboard = this.dashboards.findIndex(x => x._id.toString() === dashboard._id.toString());
|
|
22
|
+
this.dashboards.splice(removedDashboard, 1);
|
|
23
|
+
this.showDeleteDashboardModal = null;
|
|
24
|
+
},
|
|
25
|
+
insertNewDashboard(dashboard) {
|
|
26
|
+
this.dashboards.push(dashboard);
|
|
27
|
+
this.showCreateDashboardModal = false;
|
|
28
|
+
}
|
|
29
|
+
},
|
|
14
30
|
async mounted() {
|
|
15
31
|
const { dashboards } = await api.Dashboard.getDashboards();
|
|
16
32
|
this.dashboards = dashboards;
|
|
@@ -1,24 +1,10 @@
|
|
|
1
1
|
<div class="document-details">
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
</div>
|
|
9
|
-
<div v-if="editting && path.path !== '_id'" class="pl-1">
|
|
10
|
-
<component
|
|
11
|
-
:is="getEditComponentForPath(path)"
|
|
12
|
-
:value="getEditValueForPath(path)"
|
|
13
|
-
@input="changes[path.path] = $event; delete invalid[path.path];"
|
|
14
|
-
@error="invalid[path.path] = $event;"
|
|
15
|
-
>
|
|
16
|
-
</component>
|
|
17
|
-
</div>
|
|
18
|
-
<div v-else class="pl-1">
|
|
19
|
-
<component :is="getComponentForPath(path)" :value="getValueForPath(path.path)"></component>
|
|
20
|
-
</div>
|
|
21
|
-
</div>
|
|
2
|
+
<document-property
|
|
3
|
+
:document="document"
|
|
4
|
+
:schemaPaths="schemaPaths"
|
|
5
|
+
:editting="editting"
|
|
6
|
+
:changes="changes"
|
|
7
|
+
:invalid="invalid"></document-property>
|
|
22
8
|
<div v-for="path in virtuals" class="mb-2">
|
|
23
9
|
<div class="p-1 mb-1 bg-slate-100">
|
|
24
10
|
{{path.name}}
|
|
@@ -10,43 +10,14 @@ appendCSS(require('./document-details.css'));
|
|
|
10
10
|
module.exports = app => app.component('document-details', {
|
|
11
11
|
template,
|
|
12
12
|
props: ['document', 'schemaPaths', 'editting', 'changes', 'invalid'],
|
|
13
|
-
methods: {
|
|
14
|
-
getComponentForPath(schemaPath) {
|
|
15
|
-
if (schemaPath.instance === 'Array') {
|
|
16
|
-
return 'detail-array';
|
|
17
|
-
}
|
|
18
|
-
return 'detail-default';
|
|
19
|
-
},
|
|
20
|
-
getEditComponentForPath(path) {
|
|
21
|
-
if (path.instance == 'Date') {
|
|
22
|
-
return 'edit-date';
|
|
23
|
-
}
|
|
24
|
-
if (path.instance == 'Number') {
|
|
25
|
-
return 'edit-number';
|
|
26
|
-
}
|
|
27
|
-
if (path.instance === 'Array') {
|
|
28
|
-
return 'edit-array';
|
|
29
|
-
}
|
|
30
|
-
if (path.instance === 'Embedded') {
|
|
31
|
-
return 'edit-subdocument';
|
|
32
|
-
}
|
|
33
|
-
return 'edit-default';
|
|
34
|
-
},
|
|
35
|
-
getValueForPath(path) {
|
|
36
|
-
return mpath.get(path, this.document);
|
|
37
|
-
},
|
|
38
|
-
getEditValueForPath({ path }) {
|
|
39
|
-
if (!this.changes) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
return path in this.changes ? this.changes[path] : mpath.get(path, this.document);
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
13
|
computed: {
|
|
46
14
|
virtuals() {
|
|
47
15
|
if (this.schemaPaths == null) {
|
|
48
16
|
return [];
|
|
49
17
|
}
|
|
18
|
+
if (this.document == null) {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
50
21
|
const exists = this.schemaPaths.map(x => x.path);
|
|
51
22
|
const docKeys = Object.keys(this.document);
|
|
52
23
|
const result = [];
|
|
@@ -57,6 +28,6 @@ module.exports = app => app.component('document-details', {
|
|
|
57
28
|
}
|
|
58
29
|
|
|
59
30
|
return result;
|
|
60
|
-
}
|
|
31
|
+
},
|
|
61
32
|
}
|
|
62
33
|
})
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
.document-details {
|
|
2
|
+
width: 100%;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.document-details .value {
|
|
6
|
+
padding-top: 10px;
|
|
7
|
+
padding-bottom: 10px;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.document-details .path-key {
|
|
11
|
+
background-color: #f0f0f0;
|
|
12
|
+
margin-bottom: 0.5em;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.document-details .path-type {
|
|
16
|
+
color: rgba(0,0,0,.36);
|
|
17
|
+
font-size: 0.8em;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.document-details .date-position {
|
|
21
|
+
float: right;
|
|
22
|
+
margin-top: -7px;
|
|
23
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<div>
|
|
2
|
+
<div v-for="path in schemaPaths" class="value">
|
|
3
|
+
<div class="relative path-key p-1 flex">
|
|
4
|
+
<div class="grow">
|
|
5
|
+
{{path.path}}
|
|
6
|
+
<span class="path-type">
|
|
7
|
+
({{(path.instance || 'unknown').toLowerCase()}})
|
|
8
|
+
</span>
|
|
9
|
+
</div>
|
|
10
|
+
<div v-if="editting && path.instance === 'Date'" class="flex gap-1.5">
|
|
11
|
+
<div
|
|
12
|
+
@click="dateType = 'picker'"
|
|
13
|
+
:class="dateType === 'picker' ? 'bg-white' : ''"
|
|
14
|
+
class="self-stretch px-2 py-1 rounded-sm justify-center items-center gap-1.5 flex cursor-pointer">
|
|
15
|
+
<div
|
|
16
|
+
:class="dateType === 'picker' ? 'text-sky-600' : 'text-black'"
|
|
17
|
+
class="text-xs font-medium font-['Lato'] capitalize leading-tight">
|
|
18
|
+
Date Picker
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
<div
|
|
22
|
+
@click="dateType = 'iso'"
|
|
23
|
+
:class="dateType === 'iso' ? 'bg-white' : ''"
|
|
24
|
+
class="self-stretch px-2 py-1 rounded-sm justify-center items-center gap-1.5 flex cursor-pointer">
|
|
25
|
+
<div
|
|
26
|
+
:class="dateType === 'iso' ? 'text-sky-600' : 'text-black'"
|
|
27
|
+
class="text-xs font-medium font-['Lato'] capitalize leading-tight">
|
|
28
|
+
ISO String
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
<div v-if="editting && path.path !== '_id'" class="pl-1">
|
|
34
|
+
<component
|
|
35
|
+
:is="getEditComponentForPath(path)"
|
|
36
|
+
:value="getEditValueForPath(path)"
|
|
37
|
+
:format="dateType"
|
|
38
|
+
@input="changes[path.path] = $event; delete invalid[path.path];"
|
|
39
|
+
@error="invalid[path.path] = $event;"
|
|
40
|
+
>
|
|
41
|
+
</component>
|
|
42
|
+
</div>
|
|
43
|
+
<div v-else class="pl-1">
|
|
44
|
+
<component :is="getComponentForPath(path)" :value="getValueForPath(path.path)"></component>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const mpath = require('mpath');
|
|
4
|
+
const template = require('./document-property.html')
|
|
5
|
+
|
|
6
|
+
const appendCSS = require('../../appendCSS');
|
|
7
|
+
|
|
8
|
+
appendCSS(require('./document-property.css'));
|
|
9
|
+
|
|
10
|
+
module.exports = app => app.component('document-property', {
|
|
11
|
+
template,
|
|
12
|
+
data: function() {
|
|
13
|
+
return {
|
|
14
|
+
dateType: 'picker' // picker, iso
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
props: ['document', 'schemaPaths', 'editting', 'changes', 'invalid'],
|
|
18
|
+
methods: {
|
|
19
|
+
getComponentForPath(schemaPath) {
|
|
20
|
+
if (schemaPath.instance === 'Array') {
|
|
21
|
+
return 'detail-array';
|
|
22
|
+
}
|
|
23
|
+
return 'detail-default';
|
|
24
|
+
},
|
|
25
|
+
getEditComponentForPath(path) {
|
|
26
|
+
if (path.instance == 'Date') {
|
|
27
|
+
return 'edit-date';
|
|
28
|
+
}
|
|
29
|
+
if (path.instance == 'Number') {
|
|
30
|
+
return 'edit-number';
|
|
31
|
+
}
|
|
32
|
+
if (path.instance === 'Array') {
|
|
33
|
+
return 'edit-array';
|
|
34
|
+
}
|
|
35
|
+
if (path.instance === 'Embedded') {
|
|
36
|
+
return 'edit-subdocument';
|
|
37
|
+
}
|
|
38
|
+
return 'edit-default';
|
|
39
|
+
},
|
|
40
|
+
getValueForPath(path) {
|
|
41
|
+
if (this.document == null) {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
return mpath.get(path, this.document);
|
|
45
|
+
},
|
|
46
|
+
getEditValueForPath({ path }) {
|
|
47
|
+
if (!this.changes) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (!this.document) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
return path in this.changes ? this.changes[path] : mpath.get(path, this.document);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
})
|
|
@@ -1,20 +1,4 @@
|
|
|
1
1
|
<div>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
@click="inputType = 'picker'"
|
|
5
|
-
type="button"
|
|
6
|
-
class="relative inline-flex items-center rounded-none p-1 rounded-tl-md text-sm text-gray-800 ring-1 ring-inset ring-gray-300 hover:bg-gray-200 focus:z-10"
|
|
7
|
-
:class="inputType === 'picker' ? 'bg-gray-200' : 'bg-white'">
|
|
8
|
-
Date Picker
|
|
9
|
-
</button>
|
|
10
|
-
<button
|
|
11
|
-
@click="inputType = 'iso'"
|
|
12
|
-
type="button"
|
|
13
|
-
class="relative -ml-px inline-flex items-center p-1 rounded-none rounded-tr-md text-sm text-gray-800 ring-1 ring-inset ring-gray-300 hover:bg-gray-200 focus:z-10"
|
|
14
|
-
:class="inputType === 'iso' ? 'bg-gray-200' : 'bg-white'">
|
|
15
|
-
ISO String Input
|
|
16
|
-
</button>
|
|
17
|
-
</div>
|
|
18
|
-
<input v-if="inputType == 'picker'" class="w-64 h-8 border border-gray-300 outline-0" type="datetime-local" :value="valueAsLocalString" @input="$emit('input', $event.target.value)">
|
|
19
|
-
<input v-if="inputType == 'iso'" type="text" class="w-64 h-8 border border-gray-300 outline-0" :value="valueAsISOString" @input="$emit('input', $event.target.value)">
|
|
2
|
+
<input v-if="dateSelection == 'picker'" class="w-64 h-8 border border-gray-300 outline-0" type="datetime-local" :value="valueAsLocalString" @input="$emit('input', $event.target.value)">
|
|
3
|
+
<input v-if="dateSelection == 'iso'" type="text" class="w-64 h-8 border border-gray-300 outline-0" :value="valueAsISOString" @input="$emit('input', $event.target.value)">
|
|
20
4
|
</div>
|
|
@@ -4,13 +4,11 @@ const template = require('./edit-date.html');
|
|
|
4
4
|
|
|
5
5
|
module.exports = app => app.component('edit-date', {
|
|
6
6
|
template: template,
|
|
7
|
-
props: ['value'],
|
|
7
|
+
props: ['value', 'format'],
|
|
8
8
|
emits: ['input'],
|
|
9
|
-
data:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
},
|
|
9
|
+
data: () => ({
|
|
10
|
+
inputType: ''
|
|
11
|
+
}),
|
|
14
12
|
computed: {
|
|
15
13
|
valueAsLocalString() {
|
|
16
14
|
if (this.value == null) {
|
|
@@ -35,6 +33,9 @@ module.exports = app => app.component('edit-date', {
|
|
|
35
33
|
}
|
|
36
34
|
const date = new Date(this.value);
|
|
37
35
|
return date.toISOString();
|
|
36
|
+
},
|
|
37
|
+
dateSelection() {
|
|
38
|
+
return this.format;
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
});
|
package/frontend/src/index.js
CHANGED
|
@@ -26,6 +26,7 @@ require('./detail-default/detail-default')(app);
|
|
|
26
26
|
require('./document/document')(app);
|
|
27
27
|
require('./document/confirm-changes/confirm-changes')(app);
|
|
28
28
|
require('./document-details/document-details')(app);
|
|
29
|
+
require('./document-details/document-property/document-property')(app);
|
|
29
30
|
require('./edit-array/edit-array')(app);
|
|
30
31
|
require('./edit-default/edit-default')(app);
|
|
31
32
|
require('./edit-number/edit-number')(app);
|