quar 1.2.1 → 1.2.2
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/index.js +3 -1
- package/package.json +3 -2
- package/public/scripts/insertTab.js +53 -1
- package/public/scripts/main.js +12 -0
- package/public/styles/insertTab.css +19 -2
- package/server.js +1 -0
- package/utils/loadModels.js +2 -0
- package/views/pages/index.zare +2 -2
package/index.js
CHANGED
|
@@ -51,9 +51,11 @@ try {
|
|
|
51
51
|
(async () => {
|
|
52
52
|
|
|
53
53
|
await mongoose.connect(`${args.uri || "mongodb://localhost:27017/"}${args.db}`)
|
|
54
|
+
console.log( chalk.blue.bold('[INFO]'), chalk.gray("Quar: Database connection established"))
|
|
55
|
+
|
|
54
56
|
app.listen(app.get('port'), () => {
|
|
55
57
|
const url = `http://127.0.0.1:${app.get('port')}`;
|
|
56
|
-
console.log(chalk.green.bold('[SUCCESS]') + ` Server is running on ${chalk.underline(url)}`);
|
|
58
|
+
console.log(chalk.green.bold('[SUCCESS]') + chalk.gray(` Server is running on ${chalk.underline(url)}`));
|
|
57
59
|
open(url);
|
|
58
60
|
});
|
|
59
61
|
})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quar",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "This will load all Mongoose models from the folder and start a local web UI to Create, view, update, and delete documents.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
"quar": "./index.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"start": "node index.js"
|
|
11
|
+
"start": "node index.js",
|
|
12
|
+
"dev": "node .\\index.js --model .\\models\\ --db shopDB"
|
|
12
13
|
},
|
|
13
14
|
"author": "@IsmailBinMujeeb (IsmailBinMujeeb@gmail.com)",
|
|
14
15
|
"license": "MIT",
|
|
@@ -25,6 +25,18 @@ async function toggleInsertTab() {
|
|
|
25
25
|
const formData = new FormData(e.target);
|
|
26
26
|
const data = Object.fromEntries(formData.entries());
|
|
27
27
|
|
|
28
|
+
const checkboxes = e.target.querySelectorAll('input[type="checkbox"]');
|
|
29
|
+
checkboxes.forEach(cb => {
|
|
30
|
+
data[cb.name] = cb.checked;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const textareas = e.target.querySelectorAll('textarea');
|
|
34
|
+
textareas.forEach(async tarea => {
|
|
35
|
+
|
|
36
|
+
data[tarea.name] = JSON.parse(tarea.value)
|
|
37
|
+
|
|
38
|
+
})
|
|
39
|
+
|
|
28
40
|
const res = await fetch(`/insert/${modelName}`, {
|
|
29
41
|
method: 'POST',
|
|
30
42
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -40,8 +52,12 @@ async function toggleInsertTab() {
|
|
|
40
52
|
loadDocuments();
|
|
41
53
|
});
|
|
42
54
|
|
|
55
|
+
|
|
43
56
|
for (const key in schema) {
|
|
57
|
+
|
|
58
|
+
if (/\.\$\*$/.test(key)) continue;
|
|
44
59
|
const field = schema[key];
|
|
60
|
+
let inputType = null;
|
|
45
61
|
|
|
46
62
|
const label = document.createElement('label');
|
|
47
63
|
label.innerHTML = `${key}:`;
|
|
@@ -73,8 +89,44 @@ async function toggleInsertTab() {
|
|
|
73
89
|
continue;
|
|
74
90
|
}
|
|
75
91
|
|
|
92
|
+
if (field.type === 'String') inputType = 'text';
|
|
93
|
+
else if (field.type === 'Number') inputType = 'number';
|
|
94
|
+
else if (field.type === 'Boolean') inputType = 'checkbox';
|
|
95
|
+
else if (field.type === 'Date') inputType = 'date';
|
|
96
|
+
else if (field.type === 'Array' || field.type === "Map" || field.type === "Object" || field.type == "Mixed" || field.type === "Buffer") {
|
|
97
|
+
const input = document.createElement('textarea');
|
|
98
|
+
|
|
99
|
+
input.placeholder = field.type;
|
|
100
|
+
input.id = key;
|
|
101
|
+
input.name = key;
|
|
102
|
+
input.className = 'input';
|
|
103
|
+
field.type === "Array" ? input.textContent = "[ ]" : input.textContent = "{ }";
|
|
104
|
+
input.required = isRequired(field.require);
|
|
105
|
+
if (field.default !== undefined) input.value = field.default;
|
|
106
|
+
|
|
107
|
+
form.append(label, input);
|
|
108
|
+
continue;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
if (field.enum) {
|
|
112
|
+
const select = document.createElement('select');
|
|
113
|
+
select.id = key;
|
|
114
|
+
select.name = key;
|
|
115
|
+
select.className = 'input';
|
|
116
|
+
|
|
117
|
+
field.enum.forEach(id => {
|
|
118
|
+
const option = document.createElement('option');
|
|
119
|
+
option.value = id;
|
|
120
|
+
option.innerText = id;
|
|
121
|
+
select.appendChild(option);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
form.append(label, select);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
|
|
76
128
|
const input = document.createElement('input');
|
|
77
|
-
input.type =
|
|
129
|
+
input.type = inputType || 'text';
|
|
78
130
|
input.placeholder = field.type;
|
|
79
131
|
input.id = key;
|
|
80
132
|
input.name = key;
|
package/public/scripts/main.js
CHANGED
|
@@ -35,6 +35,8 @@ async function activateTab(modelName) {
|
|
|
35
35
|
|
|
36
36
|
content.dataset.modelName = modelName;
|
|
37
37
|
document.getElementById("page-value").innerText = 1;
|
|
38
|
+
document.querySelectorAll(".operations .btn")?.forEach( btn => btn.disabled = false )
|
|
39
|
+
document.querySelector(".operations select").disabled = false;
|
|
38
40
|
|
|
39
41
|
const insertTab = document.querySelector('.insert-tab');
|
|
40
42
|
insertTab.classList.remove('active');
|
|
@@ -62,9 +64,18 @@ function closeTab(event, modelName) {
|
|
|
62
64
|
const keys = Object.keys(openTabs);
|
|
63
65
|
const modelName = keys[keys.length - 1] || null;
|
|
64
66
|
if (modelName) activateTab(modelName);
|
|
67
|
+
else disableAllOptions();
|
|
65
68
|
}
|
|
66
69
|
}
|
|
67
70
|
|
|
71
|
+
function disableAllOptions() {
|
|
72
|
+
content.dataset.modelName = '';
|
|
73
|
+
|
|
74
|
+
document.querySelectorAll(".operations .btn")?.forEach( btn => btn.disabled = true );
|
|
75
|
+
document.getElementById("document-count").innerText = 0;
|
|
76
|
+
document.querySelector(".operations select").disabled = true;
|
|
77
|
+
}
|
|
78
|
+
|
|
68
79
|
async function loadDocuments() {
|
|
69
80
|
|
|
70
81
|
content.innerHTML = "";
|
|
@@ -267,6 +278,7 @@ async function deleteDoc(modelName, id) {
|
|
|
267
278
|
openModel(modelName);
|
|
268
279
|
const data = await res.json();
|
|
269
280
|
document.getElementById(`${modelName}-doc-count`).innerText = data.count || 0;
|
|
281
|
+
loadDocuments()
|
|
270
282
|
} else {
|
|
271
283
|
showModal('error', 'Delete Failed', await res.json().error || 'Delete failed, please try again.');
|
|
272
284
|
}
|
|
@@ -31,7 +31,9 @@
|
|
|
31
31
|
color: var(--text-color);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
#insert-form input,
|
|
34
|
+
#insert-form input,
|
|
35
|
+
select,
|
|
36
|
+
textarea {
|
|
35
37
|
width: 100%;
|
|
36
38
|
padding: 10px;
|
|
37
39
|
border: 1px solid var(--muted-color);
|
|
@@ -40,6 +42,21 @@
|
|
|
40
42
|
color: var(--text-color);
|
|
41
43
|
}
|
|
42
44
|
|
|
45
|
+
#insert-form textarea {
|
|
46
|
+
resize: vertical;
|
|
47
|
+
min-height: fit-content;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
#insert-form input[type="checkbox"] {
|
|
51
|
+
width: 16px;
|
|
52
|
+
height: 16px;
|
|
53
|
+
accent-color: var(--green-color);
|
|
54
|
+
background-color: var(--bg-color);
|
|
55
|
+
border: 1px solid var(--muted-color);
|
|
56
|
+
border-radius: 10px;
|
|
57
|
+
cursor: pointer;
|
|
58
|
+
}
|
|
59
|
+
|
|
43
60
|
#insert-form .btn {
|
|
44
61
|
background: transparent;
|
|
45
62
|
color: var(--text-color);
|
|
@@ -54,4 +71,4 @@
|
|
|
54
71
|
background: var(--blue-color);
|
|
55
72
|
color: var(--bg-color);
|
|
56
73
|
}
|
|
57
|
-
}
|
|
74
|
+
}
|
package/server.js
CHANGED
package/utils/loadModels.js
CHANGED
package/views/pages/index.zare
CHANGED
|
@@ -37,12 +37,12 @@ serve (
|
|
|
37
37
|
<div class="text">Count</div>
|
|
38
38
|
<div class="count-div" id="document-count">0</div>
|
|
39
39
|
</div>
|
|
40
|
-
<button class="btn" id="previous-page" onclick="gotoPreviousPage()">Previous</button>
|
|
40
|
+
<button class="btn" id="previous-page" onclick="gotoPreviousPage()" disabled>Previous</button>
|
|
41
41
|
<div class="page-wrapper" id="page" data-page="1">
|
|
42
42
|
<div class="text">Page</div>
|
|
43
43
|
<div class="page-div" id="page-value">1</div>
|
|
44
44
|
</div>
|
|
45
|
-
<button class="btn" id="next-page" onclick="gotoNextPage()">Next</button>
|
|
45
|
+
<button class="btn" id="next-page" onclick="gotoNextPage()" disabled>Next</button>
|
|
46
46
|
<button class="btn" onclick="toggleInsertTab()">Add Record</button>
|
|
47
47
|
<button class="btn" onclick="deleteAllDocs()">🗑</button>
|
|
48
48
|
</div>
|