@mongoosejs/studio 0.0.21 → 0.0.23
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 +18 -0
- package/backend/actions/Dashboard/getDashboards.js +10 -0
- package/backend/actions/Dashboard/index.js +5 -0
- package/backend/actions/Dashboard/updateDashboard.js +25 -0
- package/backend/actions/Model/createDocument.js +28 -0
- package/backend/actions/Model/getDocuments.js +2 -1
- package/backend/actions/Model/index.js +1 -0
- package/backend/actions/Model/listModels.js +3 -1
- package/backend/actions/Model/updateDocument.js +1 -1
- package/backend/actions/index.js +1 -0
- package/backend/db/dashboardSchema.js +16 -0
- package/backend/index.js +9 -1
- package/frontend/public/app.js +1172 -473
- package/frontend/public/images/json.svg +2 -0
- package/frontend/public/images/table.svg +1 -0
- package/frontend/public/index.html +3 -0
- package/frontend/public/tw.css +298 -18
- package/frontend/src/api.js +28 -0
- package/frontend/src/create-document/create-document.css +0 -0
- package/frontend/src/create-document/create-document.html +25 -0
- package/frontend/src/create-document/create-document.js +61 -0
- package/frontend/src/dashboard/dashboard.html +17 -0
- package/frontend/src/dashboard/dashboard.js +36 -0
- package/frontend/src/dashboard/edit-dashboard/edit-dashboard.html +5 -0
- package/frontend/src/dashboard/edit-dashboard/edit-dashboard.js +48 -0
- package/frontend/src/dashboards/dashboards.html +5 -0
- package/frontend/src/dashboards/dashboards.js +20 -0
- package/frontend/src/document/document.html +5 -4
- package/frontend/src/document/document.js +7 -1
- package/frontend/src/edit-array/edit-array.html +1 -7
- package/frontend/src/edit-array/edit-array.js +27 -9
- package/frontend/src/edit-date/edit-date.html +18 -1
- package/frontend/src/edit-date/edit-date.js +12 -0
- package/frontend/src/edit-default/edit-default.html +1 -1
- package/frontend/src/index.js +5 -0
- package/frontend/src/list-json/list-json.css +3 -0
- package/frontend/src/list-json/list-json.html +4 -0
- package/frontend/src/list-json/list-json.js +40 -0
- package/frontend/src/models/models.css +2 -8
- package/frontend/src/models/models.html +42 -10
- package/frontend/src/models/models.js +22 -1
- package/frontend/src/navbar/navbar.css +9 -0
- package/frontend/src/navbar/navbar.html +11 -3
- package/frontend/src/navbar/navbar.js +6 -1
- package/frontend/src/routes.js +10 -0
- package/mongoosejs-studio-0.0.16.tgz +0 -0
- package/package.json +2 -2
- package/tailwind.config.js +27 -1
- package/frontend/dist/app.js +0 -160
- package/frontend/dist/tw.css +0 -595
- package/logs/COUNT_20230524-154120-151469/operation.log +0 -8
- package/logs/COUNT_20230524-154408-077670/operation.log +0 -22
- package/logs/COUNT_20230524-154414-431706/operation.log +0 -8
- package/logs/COUNT_20230524-155000-297076/operation.log +0 -8
- package/logs/LOAD_20230524-155832-351763/checkpoint.csv +0 -1
- package/logs/LOAD_20230524-155832-351763/operation.log +0 -23
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const api = require('../../api');
|
|
4
|
+
const template = require('./edit-dashboard.html');
|
|
5
|
+
|
|
6
|
+
module.exports = app => app.component('edit-dashboard', {
|
|
7
|
+
template: template,
|
|
8
|
+
props: ['dashboardId', 'code'],
|
|
9
|
+
data: function() {
|
|
10
|
+
return {
|
|
11
|
+
status: 'loading',
|
|
12
|
+
editor: null,
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
methods: {
|
|
16
|
+
closeEditor() {
|
|
17
|
+
this.$emit('close')
|
|
18
|
+
},
|
|
19
|
+
async updateCode() {
|
|
20
|
+
const { doc } = await api.Dashboard.updateDashboard({ dashboardId: this.dashboardId, code: this.editor.getValue() });
|
|
21
|
+
this.$emit('update', doc.code);
|
|
22
|
+
this.editor.setValue(doc.code);
|
|
23
|
+
this.closeEditor();
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
mounted: async function() {
|
|
27
|
+
this.editor = CodeMirror.fromTextArea(this.$refs.codeEditor, {
|
|
28
|
+
mode: 'javascript',
|
|
29
|
+
lineNumbers: true,
|
|
30
|
+
indentUnit: 4,
|
|
31
|
+
smartIndent: true,
|
|
32
|
+
tabsize: 4,
|
|
33
|
+
indentWithTabs: true,
|
|
34
|
+
cursorBlinkRate: 300,
|
|
35
|
+
lineWrapping: true,
|
|
36
|
+
showCursorWhenSelecting: true,
|
|
37
|
+
});
|
|
38
|
+
// this.editor.setValue(this.code);
|
|
39
|
+
// this.editor.setSize(300, 300); // Ensure the editor has a fixed height
|
|
40
|
+
|
|
41
|
+
// this.editor.setCursor(this.editor.lineCount() - 1, this.editor.getLine(this.editor.lineCount() - 1).length);
|
|
42
|
+
|
|
43
|
+
this.editor.focus();
|
|
44
|
+
// this.editor.refresh(); // if anything weird happens on load, this usually fixes it. However, this breaks it in this case.
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
}
|
|
48
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const api = require('../api');
|
|
4
|
+
const template = require('./dashboards.html');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
module.exports = app => app.component('dashboards', {
|
|
8
|
+
template: template,
|
|
9
|
+
data: () => ({
|
|
10
|
+
dashboards: [],
|
|
11
|
+
}),
|
|
12
|
+
async mounted() {
|
|
13
|
+
const { dashboards } = await api.Dashboard.getDashboards();
|
|
14
|
+
this.dashboards = dashboards;
|
|
15
|
+
if (!this.$route.query.dashboardId) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
this.status = 'loaded';
|
|
19
|
+
},
|
|
20
|
+
});
|
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
v-if="!editting"
|
|
12
12
|
@click="editting = true"
|
|
13
13
|
type="button"
|
|
14
|
-
class="rounded-md bg-
|
|
14
|
+
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">
|
|
15
15
|
<img src="images/edit.svg" class="inline" /> Edit
|
|
16
16
|
</button>
|
|
17
17
|
<button
|
|
18
18
|
v-if="editting"
|
|
19
|
-
@click="
|
|
19
|
+
@click="editting = false"
|
|
20
20
|
type="button"
|
|
21
21
|
class="rounded-md bg-slate-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-slate-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-slate-600">
|
|
22
22
|
× Cancel
|
|
@@ -42,13 +42,14 @@
|
|
|
42
42
|
{{path.path}}
|
|
43
43
|
<span class="path-type">
|
|
44
44
|
({{(path.instance || 'unknown').toLowerCase()}})
|
|
45
|
-
</span>
|
|
45
|
+
</span>
|
|
46
46
|
</div>
|
|
47
47
|
<div v-if="editting && path.path !== '_id'">
|
|
48
48
|
<component
|
|
49
49
|
:is="getEditComponentForPath(path)"
|
|
50
50
|
:value="getEditValueForPath(path)"
|
|
51
|
-
@input="changes[path.path] = $event;"
|
|
51
|
+
@input="changes[path.path] = $event; delete invalid[path.path];"
|
|
52
|
+
@error="invalid[path.path] = $event;"
|
|
52
53
|
>
|
|
53
54
|
</component>
|
|
54
55
|
</div>
|
|
@@ -17,11 +17,14 @@ module.exports = app => app.component('document', {
|
|
|
17
17
|
status: 'init',
|
|
18
18
|
document: null,
|
|
19
19
|
changes: {},
|
|
20
|
+
invalid: {},
|
|
20
21
|
editting: false,
|
|
21
|
-
virtuals: []
|
|
22
|
+
virtuals: [],
|
|
22
23
|
}),
|
|
23
24
|
async mounted() {
|
|
25
|
+
window.pageState = this;
|
|
24
26
|
const { doc, schemaPaths } = await api.Model.getDocument({ model: this.model, documentId: this.documentId });
|
|
27
|
+
window.doc = doc;
|
|
25
28
|
this.document = doc;
|
|
26
29
|
this.schemaPaths = await Object.keys(schemaPaths).sort((k1, k2) => {
|
|
27
30
|
if (k1 === '_id' && k2 !== '_id') {
|
|
@@ -74,6 +77,9 @@ module.exports = app => app.component('document', {
|
|
|
74
77
|
this.editting = false;
|
|
75
78
|
},
|
|
76
79
|
async save() {
|
|
80
|
+
if (Object.keys(this.invalid).length > 0) {
|
|
81
|
+
throw new Error('Invalid paths: ' + Object.keys(this.invalid).join(', '));
|
|
82
|
+
}
|
|
77
83
|
const { doc } = await api.Model.updateDocument({
|
|
78
84
|
model: this.model,
|
|
79
85
|
_id: this.document._id,
|
|
@@ -1,9 +1,3 @@
|
|
|
1
1
|
<div class="edit-array">
|
|
2
|
-
<
|
|
3
|
-
<input type="text" :value="el" @input="currentValue[i] = $event.target.value; onUpdate()">
|
|
4
|
-
<span style="cursor: pointer; color: #880000; font-weight: bold;" @click="removeValue(i)">×</span>
|
|
5
|
-
</div>
|
|
6
|
-
<div>
|
|
7
|
-
<button @click="currentValue.push(''); onUpdate();">Add</button>
|
|
8
|
-
</div>
|
|
2
|
+
<textarea ref="arrayEditor" v-model="currentValue" class="w-full border border-gray-300 p-1 h-[300px]"></textarea>
|
|
9
3
|
</div>
|
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
const template = require('./edit-array.html');
|
|
4
4
|
|
|
5
|
+
const { BSON, EJSON } = require('bson');
|
|
6
|
+
|
|
7
|
+
const ObjectId = new Proxy(BSON.ObjectId, {
|
|
8
|
+
apply (target, thisArg, argumentsList) {
|
|
9
|
+
return new target(...argumentsList);
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
|
|
5
13
|
const appendCSS = require('../appendCSS');
|
|
6
14
|
appendCSS(require('./edit-array.css'));
|
|
7
15
|
|
|
@@ -10,16 +18,26 @@ module.exports = app => app.component('edit-array', {
|
|
|
10
18
|
props: ['value'],
|
|
11
19
|
data: () => ({ currentValue: null }),
|
|
12
20
|
mounted() {
|
|
13
|
-
this.currentValue = this.value;
|
|
21
|
+
this.currentValue = JSON.stringify(this.value, null, ' ').trim();
|
|
22
|
+
this.$refs.arrayEditor.value = this.currentValue;
|
|
23
|
+
this.editor = CodeMirror.fromTextArea(this.$refs.arrayEditor, {
|
|
24
|
+
mode: 'javascript',
|
|
25
|
+
lineNumbers: true
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
watch: {
|
|
29
|
+
currentValue() {
|
|
30
|
+
try {
|
|
31
|
+
this.$emit('input', eval(this.currentValue));
|
|
32
|
+
} catch (err) {
|
|
33
|
+
this.$emit('error', err);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
14
36
|
},
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
this
|
|
18
|
-
},
|
|
19
|
-
removeValue(i) {
|
|
20
|
-
this.currentValue.splice(i, 1);
|
|
21
|
-
this.$emit('input', this.currentValue);
|
|
37
|
+
beforeDestroy() {
|
|
38
|
+
if (this.editor) {
|
|
39
|
+
this.editor.toTextArea();
|
|
22
40
|
}
|
|
23
41
|
},
|
|
24
|
-
emits: ['input']
|
|
42
|
+
emits: ['input', 'error']
|
|
25
43
|
});
|
|
@@ -1,3 +1,20 @@
|
|
|
1
1
|
<div>
|
|
2
|
-
<
|
|
2
|
+
<div class="flex mb-[-1px] w-64 justify-end">
|
|
3
|
+
<button
|
|
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)">
|
|
3
20
|
</div>
|
|
@@ -6,6 +6,11 @@ module.exports = app => app.component('edit-date', {
|
|
|
6
6
|
template: template,
|
|
7
7
|
props: ['value'],
|
|
8
8
|
emits: ['input'],
|
|
9
|
+
data: function() {
|
|
10
|
+
return {
|
|
11
|
+
inputType: 'picker' // picker, iso
|
|
12
|
+
}
|
|
13
|
+
},
|
|
9
14
|
computed: {
|
|
10
15
|
valueAsLocalString() {
|
|
11
16
|
if (this.value == null) {
|
|
@@ -23,6 +28,13 @@ module.exports = app => app.component('edit-date', {
|
|
|
23
28
|
':',
|
|
24
29
|
date.getMinutes().toString().padStart(2, '0')
|
|
25
30
|
].join('');
|
|
31
|
+
},
|
|
32
|
+
valueAsISOString() {
|
|
33
|
+
if (this.value == null) {
|
|
34
|
+
return this.value;
|
|
35
|
+
}
|
|
36
|
+
const date = new Date(this.value);
|
|
37
|
+
return date.toISOString();
|
|
26
38
|
}
|
|
27
39
|
}
|
|
28
40
|
});
|
package/frontend/src/index.js
CHANGED
|
@@ -8,6 +8,10 @@ const app = Vue.createApp({
|
|
|
8
8
|
|
|
9
9
|
require('./async-button/async-button')(app);
|
|
10
10
|
require('./charts/charts')(app);
|
|
11
|
+
require('./create-document/create-document')(app);
|
|
12
|
+
require('./dashboards/dashboards')(app);
|
|
13
|
+
require('./dashboard/dashboard')(app);
|
|
14
|
+
require('./dashboard/edit-dashboard/edit-dashboard')(app)
|
|
11
15
|
require('./detail-array/detail-array')(app);
|
|
12
16
|
require('./detail-default/detail-default')(app);
|
|
13
17
|
require('./document/document')(app);
|
|
@@ -18,6 +22,7 @@ require('./edit-date/edit-date')(app);
|
|
|
18
22
|
require('./export-query-results/export-query-results')(app);
|
|
19
23
|
require('./list-array/list-array')(app);
|
|
20
24
|
require('./list-default/list-default')(app);
|
|
25
|
+
require('./list-json/list-json')(app)
|
|
21
26
|
require('./list-mixed/list-mixed')(app);
|
|
22
27
|
require('./list-string/list-string')(app);
|
|
23
28
|
require('./list-subdocument/list-subdocument')(app);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const api = require('../api');
|
|
4
|
+
const template = require('./list-json.html');
|
|
5
|
+
|
|
6
|
+
const vanillatoast = require('vanillatoasts');
|
|
7
|
+
|
|
8
|
+
require('../appendCSS')(require('./list-json.css'));
|
|
9
|
+
|
|
10
|
+
module.exports = app => app.component('list-json', {
|
|
11
|
+
template: template,
|
|
12
|
+
props: ['value'],
|
|
13
|
+
computed: {
|
|
14
|
+
shortenValue() {
|
|
15
|
+
return JSON.stringify(this.value, null, 4);
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
methods: {
|
|
19
|
+
copyText(value) {
|
|
20
|
+
const storage = document.createElement('textarea');
|
|
21
|
+
storage.value = JSON.stringify(value);
|
|
22
|
+
const elem = this.$refs.JSONCode;
|
|
23
|
+
elem.appendChild(storage);
|
|
24
|
+
storage.select();
|
|
25
|
+
storage.setSelectionRange(0, 99999);
|
|
26
|
+
document.execCommand('copy');
|
|
27
|
+
elem.removeChild(storage);
|
|
28
|
+
vanillatoast.create({
|
|
29
|
+
title: 'Text copied!',
|
|
30
|
+
type: 'success',
|
|
31
|
+
timeout: 3000,
|
|
32
|
+
icon: 'images/success.png',
|
|
33
|
+
positionClass: 'bottomRight'
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
mounted: function() {
|
|
38
|
+
Prism.highlightElement(this.$refs.JSONCode);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
@@ -27,10 +27,6 @@
|
|
|
27
27
|
max-height: calc(100vh - 56px);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
.models .documents .documents-container {
|
|
31
|
-
margin-top: 60px;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
30
|
.models .documents table {
|
|
35
31
|
/* max-width: -moz-fit-content;
|
|
36
32
|
max-width: fit-content; */
|
|
@@ -84,8 +80,6 @@
|
|
|
84
80
|
}
|
|
85
81
|
|
|
86
82
|
.models textarea {
|
|
87
|
-
width: 100%;
|
|
88
|
-
height: 600px;
|
|
89
83
|
font-size: 1.2em;
|
|
90
84
|
}
|
|
91
85
|
|
|
@@ -97,12 +91,12 @@
|
|
|
97
91
|
.models .documents-menu {
|
|
98
92
|
display: flex;
|
|
99
93
|
margin: 0.25em;
|
|
100
|
-
position: fixed;
|
|
101
94
|
width: calc(100vw - 220px);
|
|
102
95
|
}
|
|
103
96
|
|
|
104
97
|
.models .documents-menu .search-input {
|
|
105
98
|
flex-grow: 1;
|
|
99
|
+
align-items: center;
|
|
106
100
|
}
|
|
107
101
|
|
|
108
102
|
.models .search-input input {
|
|
@@ -130,5 +124,5 @@
|
|
|
130
124
|
.models .documents .buttons {
|
|
131
125
|
display: inline-flex;
|
|
132
126
|
justify-content: space-around;
|
|
133
|
-
align-items:
|
|
127
|
+
align-items: center;
|
|
134
128
|
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<router-link
|
|
13
13
|
:to="'/model/' + model"
|
|
14
14
|
class="block rounded-md py-2 pr-2 pl-2 text-sm font-semibold text-gray-700"
|
|
15
|
-
:class="model === currentModel ? 'bg-
|
|
15
|
+
:class="model === currentModel ? 'bg-teal-100 font-bold' : 'hover:bg-teal-100'">
|
|
16
16
|
{{model}}
|
|
17
17
|
</router-link>
|
|
18
18
|
</li>
|
|
@@ -26,33 +26,53 @@
|
|
|
26
26
|
<div class="documents" ref="documentsList">
|
|
27
27
|
<div>
|
|
28
28
|
<div class="documents-menu">
|
|
29
|
-
<div class="
|
|
30
|
-
<form @submit.prevent="search">
|
|
31
|
-
<input class="
|
|
29
|
+
<div class="flex flex-row items-center w-full gap-2">
|
|
30
|
+
<form @submit.prevent="search" class="flex-grow m-0">
|
|
31
|
+
<input class="w-full rounded-md p-1 outline-gray-300 text-lg" type="text" placeholder="Filter or text" v-model="searchText" />
|
|
32
32
|
</form>
|
|
33
|
-
|
|
34
|
-
<div class="buttons">
|
|
35
|
-
<div class="mr-2">
|
|
33
|
+
<div>
|
|
36
34
|
<span v-if="status === 'loading'">Loading ...</span>
|
|
37
35
|
<span v-if="status === 'loaded'">{{numDocuments === 1 ? numDocuments+ ' document' : numDocuments + ' documents'}}</span>
|
|
38
36
|
</div>
|
|
39
37
|
<button
|
|
40
38
|
@click="shouldShowExportModal = true"
|
|
41
39
|
type="button"
|
|
42
|
-
class="
|
|
40
|
+
class="rounded bg-teal-600 px-2 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">
|
|
43
41
|
Export
|
|
44
42
|
</button>
|
|
43
|
+
<button
|
|
44
|
+
@click="shouldShowCreateModal = true;"
|
|
45
|
+
type="button"
|
|
46
|
+
class="rounded bg-teal-600 px-2 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">
|
|
47
|
+
Create
|
|
48
|
+
</button>
|
|
45
49
|
<button
|
|
46
50
|
@click="shouldShowFieldModal = true"
|
|
47
51
|
type="button"
|
|
48
|
-
class="rounded bg-
|
|
52
|
+
class="rounded bg-teal-600 px-2 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">
|
|
49
53
|
Fields
|
|
50
54
|
</button>
|
|
55
|
+
<span class="isolate inline-flex rounded-md shadow-sm">
|
|
56
|
+
<button
|
|
57
|
+
@click="outputType = 'table'"
|
|
58
|
+
type="button"
|
|
59
|
+
class="relative inline-flex items-center rounded-none rounded-l-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10"
|
|
60
|
+
:class="outputType === 'table' ? 'bg-gray-200' : 'bg-white'">
|
|
61
|
+
<img class="h-5 w-5" src="images/table.svg">
|
|
62
|
+
</button>
|
|
63
|
+
<button
|
|
64
|
+
@click="outputType = 'json'"
|
|
65
|
+
type="button"
|
|
66
|
+
class="relative -ml-px inline-flex items-center rounded-none rounded-r-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10"
|
|
67
|
+
:class="outputType === 'json' ? 'bg-gray-200' : 'bg-white'">
|
|
68
|
+
<img class="h-5 w-5" src="images/json.svg">
|
|
69
|
+
</button>
|
|
70
|
+
</span>
|
|
51
71
|
</div>
|
|
52
72
|
</div>
|
|
53
73
|
</div>
|
|
54
74
|
<div class="documents-container">
|
|
55
|
-
<table>
|
|
75
|
+
<table v-if="outputType === 'table'">
|
|
56
76
|
<thead>
|
|
57
77
|
<th v-for="path in filteredPaths">
|
|
58
78
|
{{path.path}}
|
|
@@ -75,6 +95,12 @@
|
|
|
75
95
|
</tr>
|
|
76
96
|
</tbody>
|
|
77
97
|
</table>
|
|
98
|
+
<div v-if="outputType === 'json'">
|
|
99
|
+
<div v-for="document in documents" @click="$router.push('/model/' + currentModel + '/document/' + document._id)" :key="document._id">
|
|
100
|
+
<list-json :value="filterDocument(document)">
|
|
101
|
+
</list-json>
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
78
104
|
<div v-if="status === 'loading'" class="loader">
|
|
79
105
|
<img src="images/loader.gif">
|
|
80
106
|
</div>
|
|
@@ -105,5 +131,11 @@
|
|
|
105
131
|
</div>
|
|
106
132
|
</template>
|
|
107
133
|
</modal>
|
|
134
|
+
<modal v-if="shouldShowCreateModal">
|
|
135
|
+
<template v-slot:body>
|
|
136
|
+
<div class="modal-exit" @click="shouldShowCreateModal = false;">×</div>
|
|
137
|
+
<create-document :currentModel="currentModel" :paths="schemaPaths" @close="closeCreationModal"></create-document>
|
|
138
|
+
</template>
|
|
139
|
+
</modal>
|
|
108
140
|
</div>
|
|
109
141
|
</div>
|
|
@@ -5,6 +5,8 @@ const template = require('./models.html');
|
|
|
5
5
|
const mpath = require('mpath');
|
|
6
6
|
const { BSON, EJSON } = require('bson');
|
|
7
7
|
|
|
8
|
+
|
|
9
|
+
|
|
8
10
|
const ObjectId = new Proxy(BSON.ObjectId, {
|
|
9
11
|
apply (target, thisArg, argumentsList) {
|
|
10
12
|
return new target(...argumentsList);
|
|
@@ -13,6 +15,7 @@ const ObjectId = new Proxy(BSON.ObjectId, {
|
|
|
13
15
|
|
|
14
16
|
const appendCSS = require('../appendCSS');
|
|
15
17
|
|
|
18
|
+
|
|
16
19
|
appendCSS(require('./models.css'));
|
|
17
20
|
|
|
18
21
|
const limit = 50;
|
|
@@ -35,12 +38,14 @@ module.exports = app => app.component('models', {
|
|
|
35
38
|
filter: null,
|
|
36
39
|
searchText: '',
|
|
37
40
|
shouldShowExportModal: false,
|
|
41
|
+
shouldShowCreateModal: false,
|
|
38
42
|
shouldShowFieldModal: false,
|
|
39
43
|
shouldExport: {},
|
|
40
44
|
sortBy: {},
|
|
41
45
|
query: {},
|
|
42
46
|
scrollHeight: 0,
|
|
43
|
-
interval: null
|
|
47
|
+
interval: null,
|
|
48
|
+
outputType: 'table' // json, table
|
|
44
49
|
}),
|
|
45
50
|
created() {
|
|
46
51
|
this.currentModel = this.model;
|
|
@@ -77,9 +82,25 @@ module.exports = app => app.component('models', {
|
|
|
77
82
|
this.filteredPaths = this.filteredPaths.filter(x => filter.includes(x.path))
|
|
78
83
|
}
|
|
79
84
|
|
|
85
|
+
|
|
80
86
|
this.status = 'loaded';
|
|
81
87
|
},
|
|
82
88
|
methods: {
|
|
89
|
+
async closeCreationModal() {
|
|
90
|
+
this.shouldShowCreateModal = false;
|
|
91
|
+
await this.getDocuments();
|
|
92
|
+
},
|
|
93
|
+
initializeDocumentData() {
|
|
94
|
+
this.shouldShowCreateModal = true;
|
|
95
|
+
},
|
|
96
|
+
filterDocument(doc) {
|
|
97
|
+
const filteredDoc = {};
|
|
98
|
+
console.log(doc, this.filteredPaths)
|
|
99
|
+
for (let i = 0; i < this.filteredPaths.length; i++) {
|
|
100
|
+
filteredDoc[this.filteredPaths[i].path] = doc[this.filteredPaths[i].path];
|
|
101
|
+
}
|
|
102
|
+
return filteredDoc;
|
|
103
|
+
},
|
|
83
104
|
async onScroll() {
|
|
84
105
|
if (this.status === 'loading' || this.loadedAllDocs) {
|
|
85
106
|
return;
|
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
background-color: #eee;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
+
.active {
|
|
7
|
+
text-decoration: underline;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.spacing {
|
|
11
|
+
margin-right: 10px;
|
|
12
|
+
}
|
|
13
|
+
|
|
6
14
|
.navbar .nav-left {
|
|
7
15
|
float: left;
|
|
8
16
|
line-height: 54px;
|
|
@@ -30,6 +38,7 @@
|
|
|
30
38
|
float: right;
|
|
31
39
|
display: flex;
|
|
32
40
|
flex-direction: row;
|
|
41
|
+
justify-content: space-between;
|
|
33
42
|
font-size: 16px;
|
|
34
43
|
line-height: 54px;
|
|
35
44
|
padding-right: 20px;
|
|
@@ -4,9 +4,17 @@
|
|
|
4
4
|
<img src="images/logo.svg" alt="Mongoose Studio Logo" />
|
|
5
5
|
</router-link>
|
|
6
6
|
</div>
|
|
7
|
-
<div class="nav-right">
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
<div class="nav-right h-full">
|
|
8
|
+
<div class="sm:ml-6 sm:flex sm:space-x-8 h-full">
|
|
9
|
+
<a
|
|
10
|
+
href="#/"
|
|
11
|
+
class="inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium"
|
|
12
|
+
:class="routeName === 'root' ? 'text-gray-900 border-teal-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'">Documents</a>
|
|
13
|
+
<a
|
|
14
|
+
href="#/dashboards"
|
|
15
|
+
class="inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium"
|
|
16
|
+
:class="routeName === 'dashboards' ? 'text-gray-900 border-teal-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'">Dashboards</a>
|
|
17
|
+
</div>
|
|
10
18
|
</div>
|
|
11
19
|
<div style="clear: both"></div>
|
|
12
20
|
</div>
|
package/frontend/src/routes.js
CHANGED
|
@@ -20,5 +20,15 @@ module.exports = [
|
|
|
20
20
|
path: '/model/:model/document/:documentId',
|
|
21
21
|
name: 'document',
|
|
22
22
|
component: 'document'
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
path: '/dashboards',
|
|
26
|
+
name: 'dashboards',
|
|
27
|
+
component: 'dashboards'
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
path: '/dashboard',
|
|
31
|
+
name: 'dashboard',
|
|
32
|
+
component: 'dashboard'
|
|
23
33
|
}
|
|
24
34
|
];
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mongoosejs/studio",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.23",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"archetype": "0.13.0",
|
|
6
6
|
"csv-stringify": "6.3.0",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"axios": "1.2.2",
|
|
19
19
|
"express": "4.x",
|
|
20
20
|
"mocha": "10.2.0",
|
|
21
|
-
"mongoose": "
|
|
21
|
+
"mongoose": "8.x",
|
|
22
22
|
"tailwindcss": "3.4.0",
|
|
23
23
|
"vue": "3.x",
|
|
24
24
|
"webpack": "5.75.0"
|
package/tailwind.config.js
CHANGED
|
@@ -22,7 +22,33 @@ module.exports = {
|
|
|
22
22
|
'800': '#08675f',
|
|
23
23
|
'900': '#0c554e',
|
|
24
24
|
'950': '#003432',
|
|
25
|
-
}
|
|
25
|
+
},
|
|
26
|
+
'teal': {
|
|
27
|
+
'50': '#eefffc',
|
|
28
|
+
'100': '#c5fffa',
|
|
29
|
+
'200': '#8bfff5',
|
|
30
|
+
'300': '#4afef0',
|
|
31
|
+
'400': '#15ece2',
|
|
32
|
+
'500': '#00d0c9',
|
|
33
|
+
'600': '#00a8a5',
|
|
34
|
+
'700': '#008888',
|
|
35
|
+
'800': '#066769',
|
|
36
|
+
'900': '#0a5757',
|
|
37
|
+
'950': '#003235',
|
|
38
|
+
},
|
|
39
|
+
'navy-blue': {
|
|
40
|
+
'50': '#f1f4ff',
|
|
41
|
+
'100': '#e5e8ff',
|
|
42
|
+
'200': '#ced5ff',
|
|
43
|
+
'300': '#a7b1ff',
|
|
44
|
+
'400': '#767fff',
|
|
45
|
+
'500': '#3f42ff',
|
|
46
|
+
'600': '#2118ff',
|
|
47
|
+
'700': '#1007fa',
|
|
48
|
+
'800': '#0d05d2',
|
|
49
|
+
'900': '#0c06ac',
|
|
50
|
+
'950': '#000088',
|
|
51
|
+
},
|
|
26
52
|
}
|
|
27
53
|
}
|
|
28
54
|
}
|