@mongoosejs/studio 0.0.15 → 0.0.17

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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  const Archetype = require('archetype');
4
4
  const removeSpecifiedPaths = require('../../helpers/removeSpecifiedPaths');
5
- const EJSON = require('ejson');
5
+ const { EJSON } = require('bson')
6
6
 
7
7
  const GetDocumentsParams = new Archetype({
8
8
  model: {
package/frontend/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ const { execSync, exec } = require('child_process');
3
4
  const webpack = require('webpack');
4
5
 
5
6
  module.exports = function(apiUrl, isLambda, options) {
@@ -27,7 +28,13 @@ module.exports = function(apiUrl, isLambda, options) {
27
28
  }
28
29
  console.log('Webpack compiled successfully');
29
30
  });
31
+
32
+ const childProcess = exec('npm run tailwind:watch');
33
+ childProcess.stdout.on('data', data => console.log('[TAILWIND]', data));
34
+ childProcess.stderr.on('data', data => console.log('[TAILWIND]', data));
30
35
  } else {
36
+ execSync('npm run tailwind');
37
+
31
38
  return new Promise((resolve, reject) => {
32
39
  compiler.run((err) => {
33
40
  if (err) {
@@ -8,6 +8,7 @@
8
8
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans"/>
9
9
  <link rel="stylesheet" type="text/css" href="style.css"/>
10
10
  <link rel="stylesheet" href="https://unpkg.com/prismjs@1.29.0/themes/prism.css"/>
11
+ <link rel="stylesheet" href="tw.css">
11
12
  <link rel="stylesheet" href="vanillatoasts/vanillatoasts.css">
12
13
  <script src="https://unpkg.com/vue@3.x"></script>
13
14
  <script src="https://unpkg.com/vue-router@4.0.10"></script>
@@ -24,6 +24,10 @@ button {
24
24
  font-size: 1.1em;
25
25
  }
26
26
 
27
+ input {
28
+ outline: #666 solid 1px;
29
+ }
30
+
27
31
  button.green {
28
32
  background-color: #58D415;
29
33
  }
@@ -7,17 +7,32 @@
7
7
  </div>
8
8
 
9
9
  <div class="right">
10
- <button v-if="!editting" @click="editting = true">
11
- <img src="images/edit.svg" /> Edit
10
+ <button
11
+ v-if="!editting"
12
+ @click="editting = true"
13
+ type="button"
14
+ class="rounded-md bg-puerto-rico-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-puerto-rico-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-puerto-rico-600">
15
+ <img src="images/edit.svg" class="inline" /> Edit
12
16
  </button>
13
- <button v-if="editting" class="grey" @click="editting = false">
17
+ <button
18
+ v-if="editting"
19
+ @click="save"
20
+ type="button"
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">
14
22
  &times; Cancel
15
23
  </button>
16
- <button v-if="editting" class="green" @click="save">
17
- <img src="images/save.svg" /> Save
24
+ <button
25
+ v-if="editting"
26
+ @click="save"
27
+ type="button"
28
+ class="rounded-md bg-green-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600">
29
+ <img src="images/save.svg" class="inline" /> Save
18
30
  </button>
19
- <button class="red" @click="remove">
20
- <img src="images/delete.svg" /> Delete
31
+ <button
32
+ @click="remove"
33
+ type="button"
34
+ class="rounded-md bg-red-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600">
35
+ <img src="images/delete.svg" class="inline" /> Delete
21
36
  </button>
22
37
  </div>
23
38
  </div>
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ const vanillatoasts = require('vanillatoasts');
4
+
3
5
  const app = Vue.createApp({
4
6
  template: '<app-component />'
5
7
  });
@@ -31,7 +33,15 @@ app.component('app-component', {
31
33
  <router-view :key="$route.fullPath" />
32
34
  </div>
33
35
  </div>
34
- `
36
+ `,
37
+ errorCaptured(err) {
38
+ vanillatoasts.create({
39
+ title: `Error: ${err.message}`,
40
+ icon: 'images/failure.jpg',
41
+ timeout: 10000,
42
+ positionClass: 'bottomRight'
43
+ });
44
+ }
35
45
  });
36
46
 
37
47
  const routes = require('./routes');
@@ -18,8 +18,18 @@
18
18
 
19
19
  </div>
20
20
  <div class="buttons">
21
- <button @click="shouldShowExportModal = true">Export</button>
22
- <button @click="shouldShowFieldModal = true">Fields</button>
21
+ <button
22
+ @click="shouldShowExportModal = true"
23
+ type="button"
24
+ class="rounded bg-puerto-rico-600 px-2 py-1 text-sm font-semibold text-white shadow-sm hover:bg-puerto-rico-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-puerto-rico-600">
25
+ Export
26
+ </button>
27
+ <button
28
+ @click="shouldShowFieldModal = true"
29
+ type="button"
30
+ class="rounded bg-puerto-rico-600 px-2 py-1 text-sm font-semibold text-white shadow-sm hover:bg-puerto-rico-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-puerto-rico-600">
31
+ Fields
32
+ </button>
23
33
  </div>
24
34
  </div>
25
35
  </div>
@@ -2,8 +2,14 @@
2
2
 
3
3
  const api = require('../api');
4
4
  const template = require('./models.html');
5
- const EJSON = require('ejson');
6
5
  const mpath = require('mpath');
6
+ const { BSON, EJSON } = require('bson');
7
+
8
+ const ObjectId = new Proxy(BSON.ObjectId, {
9
+ apply (target, thisArg, argumentsList) {
10
+ return new target(...argumentsList);
11
+ }
12
+ });
7
13
 
8
14
  const appendCSS = require('../appendCSS');
9
15
 
@@ -48,6 +54,7 @@ module.exports = app => app.component('models', {
48
54
  if (this.currentModel == null && this.models.length > 0) {
49
55
  this.currentModel = this.models[0];
50
56
  }
57
+
51
58
  this.query = Object.assign({}, this.$route.query); // important that this is here before the if statements
52
59
  if (this.$route.query?.search) {
53
60
  this.searchText = this.$route.query.search;
@@ -64,20 +71,28 @@ module.exports = app => app.component('models', {
64
71
  if (this.currentModel != null) {
65
72
  await this.getDocuments();
66
73
  }
67
-
68
- const hashUrl = window.location.hash.replace(/^#/, '');
69
- if (hashUrl.indexOf('?') !== -1) {
70
- const searchParams = new URLSearchParams(
71
- hashUrl.slice(hashUrl.indexOf('?') + 1)
72
- );
73
- if (searchParams.has('fields')) {
74
- this.filteredPaths = searchParams.get('fields').split(',').map(path => ({ path }));
75
- }
76
- }
74
+ this.applyQueryParams();
77
75
 
78
76
  this.status = 'loaded';
79
77
  },
80
78
  methods: {
79
+ applyQueryParams() {
80
+ const hashUrl = window.location.hash.replace(/^#/, '');
81
+ if (hashUrl.indexOf('?') !== -1) {
82
+ const searchParams = new URLSearchParams(
83
+ hashUrl.slice(hashUrl.indexOf('?') + 1)
84
+ );
85
+ if (searchParams.has('fields')) {
86
+ const filter = searchParams.get('fields').split(',');
87
+ this.filteredPaths = this.filteredPaths.filter(x => filter.includes(x.path))
88
+ }
89
+ if (searchParams.has('search')) {
90
+ this.searchText = searchParams.get('search');
91
+ this.filter = eval(`(${this.searchText})`);
92
+ this.filter = EJSON.stringify(this.filter);
93
+ }
94
+ }
95
+ },
81
96
  async onScroll() {
82
97
  if (this.status === 'loading' || this.loadedAllDocs) {
83
98
  return;
@@ -114,20 +129,31 @@ module.exports = app => app.component('models', {
114
129
  this.query.sort = `{${path}:${num}}`
115
130
  this.$router.push({ query: this.query });
116
131
  }
117
- await this.getDocuments();
132
+ await this.loadMoreDocuments();
118
133
  },
119
134
  async search() {
120
135
  if (this.searchText && Object.keys(this.searchText).length) {
121
136
  this.filter = eval(`(${this.searchText})`);
122
137
  this.filter = EJSON.stringify(this.filter);
123
138
  this.query.search = this.searchText;
124
- this.$router.push({ path: this.$route.path, query: this.query })
125
139
  } else {
126
140
  this.filter = {};
127
141
  delete this.query.search;
128
- this.$router.push({ path: this.$route.path, query: this.query });
129
142
  }
130
- await this.getDocuments();
143
+
144
+ const hashUrl = window.location.hash.replace(/^#/, '');
145
+ if (hashUrl.indexOf('?') === -1) {
146
+ window.history.pushState({}, '', window.location.pathname + '#' + hashUrl + '?search=' + this.query.search);
147
+ } else {
148
+ const searchParams = new URLSearchParams(
149
+ hashUrl.indexOf('?') === -1 ? '' : hashUrl.slice(hashUrl.indexOf('?') + 1)
150
+ );
151
+ const hashUrlWithoutSearchParams = hashUrl.slice(0, hashUrl.indexOf('?'));
152
+
153
+ searchParams.set('search', this.query.search);
154
+ window.history.pushState({}, '', window.location.pathname + '#' + hashUrlWithoutSearchParams + '?' + searchParams);
155
+ }
156
+ await this.loadMoreDocuments();
131
157
  },
132
158
  async getDocuments() {
133
159
  const { docs, schemaPaths, numDocs } = await api.Model.getDocuments({
@@ -159,6 +185,18 @@ module.exports = app => app.component('models', {
159
185
  this.filteredPaths = [...this.schemaPaths];
160
186
  this.selectedPaths = [...this.schemaPaths];
161
187
  },
188
+ async loadMoreDocuments() {
189
+ const { docs } = await api.Model.getDocuments({
190
+ model: this.currentModel,
191
+ filter: this.filter,
192
+ sort: this.sortBy,
193
+ limit
194
+ });
195
+ this.documents = docs;
196
+ if (docs.length < limit) {
197
+ this.loadedAllDocs = true;
198
+ }
199
+ },
162
200
  addOrRemove(path) {
163
201
  const exists = this.selectedPaths.findIndex(x => x.path == path.path);
164
202
  if (exists > 0) { // remove
@@ -180,7 +218,7 @@ module.exports = app => app.component('models', {
180
218
  this.filteredPaths = [...this.selectedPaths];
181
219
  this.shouldShowFieldModal = false;
182
220
  const selectedParams = this.filteredPaths.map(x => x.path).join(',');
183
-
221
+ // sets the query params
184
222
  const hashUrl = window.location.hash.replace(/^#/, '');
185
223
  if (hashUrl.indexOf('?') === -1) {
186
224
  window.history.pushState({}, '', window.location.pathname + '#' + hashUrl + '?fields=' + selectedParams);
@@ -240,4 +278,4 @@ module.exports = app => app.component('models', {
240
278
  this.edittingDoc = null;
241
279
  }
242
280
  }
243
- });
281
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mongoosejs/studio",
3
- "version": "0.0.15",
3
+ "version": "0.0.17",
4
4
  "dependencies": {
5
5
  "archetype": "0.13.0",
6
6
  "csv-stringify": "6.3.0",
@@ -10,6 +10,7 @@
10
10
  "vanillatoasts": "^1.6.0"
11
11
  },
12
12
  "peerDependencies": {
13
+ "bson": "^5.5.1",
13
14
  "express": "4.x",
14
15
  "mongoose": "7.x || 8.0.0-rc0 || 8.x"
15
16
  },
@@ -18,7 +19,12 @@
18
19
  "express": "4.x",
19
20
  "mocha": "10.2.0",
20
21
  "mongoose": "7.x",
22
+ "tailwindcss": "3.4.0",
21
23
  "vue": "3.x",
22
24
  "webpack": "5.75.0"
25
+ },
26
+ "scripts": {
27
+ "tailwind": "tailwindcss -o ./frontend/public/tw.css",
28
+ "tailwind:watch": "tailwindcss -o ./frontend/public/tw.css --watch"
23
29
  }
24
30
  }
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ module.exports = {
4
+ mode: 'jit',
5
+ content: ['./frontend/src/**/*.html', './frontend/src/**/*.js'],
6
+ corePlugins: {
7
+ container: true
8
+ },
9
+ plugins: [],
10
+ theme: {
11
+ extend: {
12
+ colors: {
13
+ 'puerto-rico': {
14
+ '50': '#eefffb',
15
+ '100': '#c6fff3',
16
+ '200': '#8effe8',
17
+ '300': '#4dfbdb',
18
+ '400': '#15d4b7',
19
+ '500': '#00ccb0',
20
+ '600': '#00a491',
21
+ '700': '#038276',
22
+ '800': '#08675f',
23
+ '900': '#0c554e',
24
+ '950': '#003432',
25
+ }
26
+ }
27
+ }
28
+ }
29
+ };