@saltcorn/server 0.6.3-beta.3 → 0.6.4-beta.3
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/app.js +3 -1
- package/auth/resetpw.js +7 -7
- package/auth/routes.js +1 -1
- package/locales/en.json +870 -860
- package/package.json +17 -14
- package/public/gridedit.js +162 -221
- package/public/saltcorn.js +137 -12
- package/public/tabulator.min.js +3 -0
- package/public/tabulator_bootstrap4.min.css +2 -0
- package/restart_watcher.js +1 -1
- package/routes/admin.js +9 -3
- package/routes/api.js +10 -5
- package/routes/fields.js +31 -2
- package/routes/files.js +2 -1
- package/routes/homepage.js +1 -1
- package/routes/list.js +169 -87
- package/routes/packs.js +1 -1
- package/routes/pageedit.js +7 -4
- package/routes/plugins.js +1 -1
- package/routes/scapi.js +1 -1
- package/routes/tables.js +3 -1
- package/routes/tenant.js +19 -9
- package/routes/view.js +2 -0
- package/routes/viewedit.js +1 -1
- package/serve.js +38 -27
- package/wrapper.js +5 -2
package/package.json
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/server",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4-beta.3",
|
|
4
4
|
"description": "Server app for Saltcorn, open-source no-code platform",
|
|
5
5
|
"homepage": "https://saltcorn.com",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@saltcorn/base-plugin": "0.6.
|
|
10
|
-
"@saltcorn/builder": "0.6.
|
|
11
|
-
"@saltcorn/data": "0.6.
|
|
12
|
-
"
|
|
13
|
-
"@saltcorn/markup": "0.6.
|
|
14
|
-
"@saltcorn/sbadmin2": "0.6.
|
|
9
|
+
"@saltcorn/base-plugin": "0.6.4-beta.3",
|
|
10
|
+
"@saltcorn/builder": "0.6.4-beta.3",
|
|
11
|
+
"@saltcorn/data": "0.6.4-beta.3",
|
|
12
|
+
"@saltcorn/admin-models": "0.6.4-beta.3",
|
|
13
|
+
"@saltcorn/markup": "0.6.4-beta.3",
|
|
14
|
+
"@saltcorn/sbadmin2": "0.6.4-beta.3",
|
|
15
15
|
"@socket.io/cluster-adapter": "^0.1.0",
|
|
16
16
|
"@socket.io/sticky": "^1.0.1",
|
|
17
|
+
"aws-sdk": "^2.1037.0",
|
|
17
18
|
"connect-flash": "^0.1.1",
|
|
18
19
|
"connect-pg-simple": "^6.1.0",
|
|
19
20
|
"connect-sqlite3": "^0.9.11",
|
|
21
|
+
"content-disposition": "^0.5.3",
|
|
20
22
|
"contractis": "^0.1.0",
|
|
21
23
|
"cookie-parser": "^1.4.4",
|
|
22
24
|
"cookie-session": "^1.4.0",
|
|
@@ -28,10 +30,13 @@
|
|
|
28
30
|
"express-rate-limit": "^5.1.3",
|
|
29
31
|
"express-session": "^1.17.1",
|
|
30
32
|
"greenlock": "^4.0.4",
|
|
33
|
+
"greenlock-express": "^4.0.3",
|
|
31
34
|
"helmet": "^3.23.3",
|
|
32
35
|
"i18n": "^0.13.2",
|
|
33
36
|
"live-plugin-manager": "^0.16.0",
|
|
34
37
|
"moment": "^2.27.0",
|
|
38
|
+
"multer": "^1.4.3",
|
|
39
|
+
"multer-s3": "^2.10.0",
|
|
35
40
|
"node-fetch": "2.6.2",
|
|
36
41
|
"node-watch": "^0.7.2",
|
|
37
42
|
"notp": "2.0.3",
|
|
@@ -43,13 +48,9 @@
|
|
|
43
48
|
"pluralize": "^8.0.0",
|
|
44
49
|
"qrcode": "1.5.0",
|
|
45
50
|
"socket.io": "4.2.0",
|
|
46
|
-
"tmp-promise": "^3.0.2",
|
|
47
51
|
"thirty-two": "1.0.2",
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"aws-sdk": "^2.1037.0",
|
|
51
|
-
"uuid": "^8.2.0",
|
|
52
|
-
"content-disposition": "^0.5.3"
|
|
52
|
+
"tmp-promise": "^3.0.2",
|
|
53
|
+
"uuid": "^8.2.0"
|
|
53
54
|
},
|
|
54
55
|
"optionalDependencies": {
|
|
55
56
|
"sd-notify": "^2.8.0"
|
|
@@ -81,7 +82,9 @@
|
|
|
81
82
|
"@saltcorn/data/(.*)": "@saltcorn/data/dist/$1",
|
|
82
83
|
"@saltcorn/types/(.*)": "@saltcorn/types/dist/$1",
|
|
83
84
|
"@saltcorn/markup$": "@saltcorn/markup/dist",
|
|
84
|
-
"@saltcorn/markup/(.*)": "@saltcorn/markup/dist/$1"
|
|
85
|
+
"@saltcorn/markup/(.*)": "@saltcorn/markup/dist/$1",
|
|
86
|
+
"@saltcorn/server/(.*)": "@saltcorn/server/dist/$1",
|
|
87
|
+
"@saltcorn/admin-models/(.*)": "@saltcorn/admin-models/dist/$1"
|
|
85
88
|
}
|
|
86
89
|
},
|
|
87
90
|
"publishConfig": {
|
package/public/gridedit.js
CHANGED
|
@@ -1,228 +1,169 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
function showHideCol(nm, e) {
|
|
2
|
+
if (e && e.checked) window.tabulator_table.showColumn(nm);
|
|
3
|
+
else window.tabulator_table.hideColumn(nm);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function lookupIntToString(cell, formatterParams, onRendered) {
|
|
7
|
+
const val = `${cell.getValue()}`;
|
|
8
|
+
const res = formatterParams.values[val];
|
|
9
|
+
return res;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function flatpickerEditor(cell, onRendered, success, cancel) {
|
|
13
|
+
var input = $("<input type='text'/>");
|
|
14
|
+
|
|
15
|
+
input.flatpickr({
|
|
16
|
+
enableTime: true,
|
|
17
|
+
dateFormat: "Y-m-d H:i",
|
|
18
|
+
time_24hr: true,
|
|
19
|
+
locale: "en", // global variable with locale 'en', 'fr', ...
|
|
20
|
+
defaultDate: cell.getValue(),
|
|
21
|
+
onClose: function (selectedDates, dateStr, instance) {
|
|
22
|
+
evt = window.event;
|
|
23
|
+
var isEscape = false;
|
|
24
|
+
if ("key" in evt) {
|
|
25
|
+
isEscape = evt.key === "Escape" || evt.key === "Esc";
|
|
26
|
+
} else {
|
|
27
|
+
isEscape = evt.keyCode === 27;
|
|
28
|
+
}
|
|
29
|
+
if (isEscape) {
|
|
30
|
+
// user hit escape
|
|
31
|
+
cancel();
|
|
32
|
+
} else {
|
|
33
|
+
success(dateStr);
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
input.css({
|
|
39
|
+
border: "1px",
|
|
40
|
+
background: "transparent",
|
|
41
|
+
padding: "4px",
|
|
42
|
+
width: "100%",
|
|
43
|
+
"box-sizing": "border-box",
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
input.val(cell.getValue());
|
|
47
|
+
|
|
48
|
+
var inputBlur = function (e) {
|
|
49
|
+
if (e.target !== input[0]) {
|
|
50
|
+
if ($(e.target).closest(".flatpicker-input").length === 0) {
|
|
51
|
+
$(document).off("mousedown", inputBlur);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
17
54
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
55
|
+
|
|
56
|
+
$(document).on("mousedown", inputBlur);
|
|
57
|
+
|
|
58
|
+
onRendered(function () {
|
|
59
|
+
input.focus();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return input[0];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function isoDateTimeFormatter(cell, formatterParams, onRendered) {
|
|
66
|
+
const val = cell.getValue();
|
|
67
|
+
if (!val) return "";
|
|
68
|
+
|
|
69
|
+
return new Date(val).toLocaleString(window.detected_locale || "en");
|
|
70
|
+
}
|
|
71
|
+
function colorFormatter(cell, formatterParams, onRendered) {
|
|
72
|
+
const val = cell.getValue();
|
|
73
|
+
if (!val) return "";
|
|
74
|
+
|
|
75
|
+
return $(
|
|
76
|
+
`<div style="height: 15px; width: 30px; background-color: ${val}"></div>`
|
|
77
|
+
)[0];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function jsonFormatter(cell, formatterParams, onRendered) {
|
|
81
|
+
const val = cell.getValue();
|
|
82
|
+
if (val === null) return "";
|
|
83
|
+
return JSON.stringify(val, null, 1);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function versionsFormatter(cell, formatterParams, onRendered) {
|
|
87
|
+
const value = cell.getValue();
|
|
88
|
+
const row = cell.getRow().getData();
|
|
89
|
+
return $(`<a href="/list/_versions/${window.tabulator_table_name}/${row.id}">
|
|
90
|
+
${value || 0} <i class="fa-sm fas fa-list"></i></a>`)[0];
|
|
91
|
+
}
|
|
92
|
+
function colorEditor(cell, onRendered, success, cancel) {
|
|
93
|
+
const editor = document.createElement("input");
|
|
94
|
+
|
|
95
|
+
editor.setAttribute("type", "color");
|
|
96
|
+
editor.value = cell.getValue();
|
|
97
|
+
//when the value has been set, trigger the cell to update
|
|
98
|
+
function successFunc() {
|
|
99
|
+
const val = editor.value;
|
|
100
|
+
success(val);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
editor.addEventListener("change", successFunc);
|
|
104
|
+
editor.addEventListener("blur", successFunc);
|
|
105
|
+
|
|
106
|
+
//return the editor element
|
|
107
|
+
return editor;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function jsonEditor(cell, onRendered, success, cancel) {
|
|
111
|
+
const editor = document.createElement("textarea");
|
|
112
|
+
|
|
113
|
+
editor.value = JSON.stringify(cell.getValue());
|
|
114
|
+
//when the value has been set, trigger the cell to update
|
|
115
|
+
function successFunc() {
|
|
116
|
+
const val = editor.value;
|
|
117
|
+
try {
|
|
118
|
+
success(JSON.parse(val));
|
|
119
|
+
} catch (e) {
|
|
120
|
+
if (e) tabulator_show_error(e.message);
|
|
121
|
+
cancel();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
editor.addEventListener("change", successFunc);
|
|
126
|
+
editor.addEventListener("blur", successFunc);
|
|
127
|
+
|
|
128
|
+
//return the editor element
|
|
129
|
+
return editor;
|
|
130
|
+
}
|
|
131
|
+
function add_tabulator_row() {
|
|
132
|
+
window.tabulator_table.addRow({}, true);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function delete_tabulator_row(e, cell) {
|
|
136
|
+
const row = cell.getRow().getData();
|
|
137
|
+
if (!row.id) {
|
|
138
|
+
cell.getRow().delete();
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
$.ajax({
|
|
142
|
+
type: "DELETE",
|
|
143
|
+
url: `/api/${window.tabulator_table_name}/${row.id}`,
|
|
144
|
+
data: row, // to process primary keys different from id
|
|
145
|
+
headers: {
|
|
146
|
+
"CSRF-Token": _sc_globalCsrf,
|
|
147
|
+
},
|
|
148
|
+
success: () => cell.getRow().delete(),
|
|
149
|
+
error: tabulator_error_handler,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function tabulator_error_handler(request) {
|
|
154
|
+
let errtxt =
|
|
155
|
+
request.responseJSON && request.responseJSON.error
|
|
156
|
+
? request.responseJSON.error
|
|
157
|
+
: request.responseText;
|
|
158
|
+
if (errtxt) {
|
|
159
|
+
tabulator_show_error(errtxt);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function tabulator_show_error(errtxt) {
|
|
163
|
+
$("#jsGridNotify").html(`<div class="alert alert-danger" role="alert">
|
|
25
164
|
${errtxt}
|
|
26
165
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
|
27
166
|
<span aria-hidden="true">×</span>
|
|
28
167
|
</button>
|
|
29
168
|
</div>`);
|
|
30
|
-
if (prom) prom.reject(errtxt);
|
|
31
|
-
};
|
|
32
|
-
};
|
|
33
|
-
return {
|
|
34
|
-
// load of data
|
|
35
|
-
loadData: function (filter) {
|
|
36
|
-
var data = $.Deferred();
|
|
37
|
-
$.ajax({
|
|
38
|
-
type: "GET",
|
|
39
|
-
url: url + (vc ? "?versioncount=on" : ""),
|
|
40
|
-
data: filter,
|
|
41
|
-
error: errorHandler(data),
|
|
42
|
-
}).done(function (resp) {
|
|
43
|
-
data.resolve(resp.success);
|
|
44
|
-
});
|
|
45
|
-
return data.promise();
|
|
46
|
-
},
|
|
47
|
-
// insert row
|
|
48
|
-
insertItem: function (item) {
|
|
49
|
-
var data = $.Deferred();
|
|
50
|
-
$.ajax({
|
|
51
|
-
type: "POST",
|
|
52
|
-
url: url,
|
|
53
|
-
data: item,
|
|
54
|
-
headers: {
|
|
55
|
-
"CSRF-Token": _sc_globalCsrf,
|
|
56
|
-
},
|
|
57
|
-
error: errorHandler(data),
|
|
58
|
-
}).done(function (resp) {
|
|
59
|
-
item._versions = 1;
|
|
60
|
-
if (resp.success) {
|
|
61
|
-
item.id = resp.success;
|
|
62
|
-
data.resolve(fixKeys(item));
|
|
63
|
-
} else {
|
|
64
|
-
data.resolve();
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
return data.promise();
|
|
68
|
-
},
|
|
69
|
-
// update row
|
|
70
|
-
updateItem: function (item) {
|
|
71
|
-
var data = $.Deferred();
|
|
72
|
-
$.ajax({
|
|
73
|
-
type: "POST",
|
|
74
|
-
url: url + item.id,
|
|
75
|
-
data: item,
|
|
76
|
-
headers: {
|
|
77
|
-
"CSRF-Token": _sc_globalCsrf,
|
|
78
|
-
},
|
|
79
|
-
error: errorHandler(data),
|
|
80
|
-
}).done(function (resp) {
|
|
81
|
-
if (item._versions) item._versions = +item._versions + 1;
|
|
82
|
-
data.resolve(fixKeys(item));
|
|
83
|
-
});
|
|
84
|
-
return data.promise();
|
|
85
|
-
},
|
|
86
|
-
// delete row
|
|
87
|
-
deleteItem: function (item) {
|
|
88
|
-
return $.ajax({
|
|
89
|
-
type: "DELETE",
|
|
90
|
-
url: url + item.id,
|
|
91
|
-
data: item, // to process primary keys different from id
|
|
92
|
-
headers: {
|
|
93
|
-
"CSRF-Token": _sc_globalCsrf,
|
|
94
|
-
},
|
|
95
|
-
error: errorHandler(),
|
|
96
|
-
});
|
|
97
|
-
},
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
function DecimalField(config) {
|
|
101
|
-
jsGrid.fields.number.call(this, config);
|
|
102
169
|
}
|
|
103
|
-
DecimalField.prototype = new jsGrid.fields.number({
|
|
104
|
-
filterValue: function () {
|
|
105
|
-
return this.filterControl.val()
|
|
106
|
-
? parseFloat(this.filterControl.val() || 0, 10)
|
|
107
|
-
: undefined;
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
insertValue: function () {
|
|
111
|
-
return this.insertControl.val()
|
|
112
|
-
? parseFloat(this.insertControl.val() || 0, 10)
|
|
113
|
-
: undefined;
|
|
114
|
-
},
|
|
115
|
-
|
|
116
|
-
editValue: function () {
|
|
117
|
-
return this.editControl.val()
|
|
118
|
-
? parseFloat(this.editControl.val() || 0, 10)
|
|
119
|
-
: undefined;
|
|
120
|
-
},
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
jsGrid.fields.decimal = jsGrid.DecimalField = DecimalField;
|
|
124
|
-
|
|
125
|
-
var ColorField = function (config) {
|
|
126
|
-
jsGrid.Field.call(this, config);
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
ColorField.prototype = new jsGrid.Field({
|
|
130
|
-
itemTemplate: function (value) {
|
|
131
|
-
return $("<div>").css({
|
|
132
|
-
display: "inline-block",
|
|
133
|
-
background: value,
|
|
134
|
-
width: "50px",
|
|
135
|
-
height: "20px",
|
|
136
|
-
});
|
|
137
|
-
},
|
|
138
|
-
|
|
139
|
-
insertTemplate: function (value) {
|
|
140
|
-
var insertPicker = (this._insertPicker = $("<input>").attr(
|
|
141
|
-
"type",
|
|
142
|
-
"color"
|
|
143
|
-
));
|
|
144
|
-
|
|
145
|
-
return insertPicker;
|
|
146
|
-
},
|
|
147
|
-
|
|
148
|
-
editTemplate: function (value) {
|
|
149
|
-
var editPicker = (this._editPicker = $("<input>")
|
|
150
|
-
.attr("type", "color")
|
|
151
|
-
.val(value));
|
|
152
|
-
|
|
153
|
-
return editPicker;
|
|
154
|
-
},
|
|
155
|
-
|
|
156
|
-
insertValue: function () {
|
|
157
|
-
return this._insertPicker.val();
|
|
158
|
-
},
|
|
159
|
-
|
|
160
|
-
editValue: function () {
|
|
161
|
-
return this._editPicker.val();
|
|
162
|
-
},
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
jsGrid.fields.color = ColorField;
|
|
166
|
-
|
|
167
|
-
var DateField = function (config) {
|
|
168
|
-
jsGrid.Field.call(this, config);
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
DateField.prototype = new jsGrid.Field({
|
|
172
|
-
itemTemplate: function (value) {
|
|
173
|
-
var v = typeof value === "string" && value !== "" ? new Date(value) : value;
|
|
174
|
-
return v && v.toLocaleString ? v.toLocaleString() : v;
|
|
175
|
-
},
|
|
176
|
-
|
|
177
|
-
insertTemplate: function (value) {
|
|
178
|
-
var insertPicker = (this._insertPicker = $("<input>").attr("type", "text"));
|
|
179
|
-
setTimeout(function () {
|
|
180
|
-
flatpickr(insertPicker, {
|
|
181
|
-
enableTime: true,
|
|
182
|
-
dateFormat: "Z",
|
|
183
|
-
altInput: true,
|
|
184
|
-
altFormat: "Y-m-d h:i K",
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
return insertPicker;
|
|
188
|
-
},
|
|
189
|
-
|
|
190
|
-
editTemplate: function (value) {
|
|
191
|
-
var editPicker = (this._editPicker = $("<input>")
|
|
192
|
-
.attr("type", "text")
|
|
193
|
-
.val(value));
|
|
194
|
-
setTimeout(function () {
|
|
195
|
-
flatpickr(editPicker, {
|
|
196
|
-
enableTime: true,
|
|
197
|
-
dateFormat: "Z",
|
|
198
|
-
altInput: true,
|
|
199
|
-
altFormat: "Y-m-d h:i K",
|
|
200
|
-
});
|
|
201
|
-
});
|
|
202
|
-
return editPicker;
|
|
203
|
-
},
|
|
204
|
-
|
|
205
|
-
insertValue: function () {
|
|
206
|
-
return this._insertPicker.val();
|
|
207
|
-
},
|
|
208
|
-
|
|
209
|
-
editValue: function () {
|
|
210
|
-
return this._editPicker.val();
|
|
211
|
-
},
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
jsGrid.fields.date = DateField;
|
|
215
|
-
|
|
216
|
-
var HtmlField = function (config) {
|
|
217
|
-
jsGrid.Field.call(this, config);
|
|
218
|
-
};
|
|
219
|
-
HtmlField.prototype = new jsGrid.Field({
|
|
220
|
-
align: "left",
|
|
221
|
-
itemTemplate: function (value, item) {
|
|
222
|
-
if (value) {
|
|
223
|
-
//return +value+1;
|
|
224
|
-
return value;
|
|
225
|
-
} else return "";
|
|
226
|
-
},
|
|
227
|
-
});
|
|
228
|
-
jsGrid.fields.html = HtmlField;
|
package/public/saltcorn.js
CHANGED
|
@@ -30,7 +30,10 @@ function add_repeater(nm) {
|
|
|
30
30
|
function apply_showif() {
|
|
31
31
|
$("[data-show-if]").each(function (ix, element) {
|
|
32
32
|
var e = $(element);
|
|
33
|
-
var to_show = new Function(
|
|
33
|
+
var to_show = new Function(
|
|
34
|
+
"e",
|
|
35
|
+
"return " + decodeURIComponent(e.attr("data-show-if"))
|
|
36
|
+
);
|
|
34
37
|
if (to_show(e))
|
|
35
38
|
e.show()
|
|
36
39
|
.find("input, textarea, button, select")
|
|
@@ -174,6 +177,14 @@ function rep_down(e) {
|
|
|
174
177
|
apply_form_subset_record(theform, vals1);
|
|
175
178
|
}
|
|
176
179
|
}
|
|
180
|
+
|
|
181
|
+
function reload_on_init() {
|
|
182
|
+
localStorage.setItem("reload_on_init", true);
|
|
183
|
+
}
|
|
184
|
+
if (localStorage.getItem("reload_on_init")) {
|
|
185
|
+
localStorage.removeItem("reload_on_init");
|
|
186
|
+
location.reload();
|
|
187
|
+
}
|
|
177
188
|
function initialize_page() {
|
|
178
189
|
$("form").change(apply_showif);
|
|
179
190
|
apply_showif();
|
|
@@ -225,13 +236,15 @@ function initialize_page() {
|
|
|
225
236
|
});
|
|
226
237
|
if (codes.length > 0)
|
|
227
238
|
enable_codemirror(() => {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
239
|
+
setTimeout(() => {
|
|
240
|
+
codes.forEach((el) => {
|
|
241
|
+
//console.log($(el).attr("mode"), el);
|
|
242
|
+
CodeMirror.fromTextArea(el, {
|
|
243
|
+
lineNumbers: true,
|
|
244
|
+
mode: $(el).attr("mode"),
|
|
245
|
+
});
|
|
233
246
|
});
|
|
234
|
-
});
|
|
247
|
+
}, 100);
|
|
235
248
|
});
|
|
236
249
|
const locale =
|
|
237
250
|
navigator.userLanguage ||
|
|
@@ -242,6 +255,7 @@ function initialize_page() {
|
|
|
242
255
|
navigator.browserLanguage ||
|
|
243
256
|
navigator.systemLanguage ||
|
|
244
257
|
"en";
|
|
258
|
+
window.detected_locale = locale;
|
|
245
259
|
const parse = (s) => JSON.parse(decodeURIComponent(s));
|
|
246
260
|
$("time[locale-time-options]").each(function () {
|
|
247
261
|
var el = $(this);
|
|
@@ -261,6 +275,7 @@ function initialize_page() {
|
|
|
261
275
|
const options = parse(el.attr("locale-date-options"));
|
|
262
276
|
el.text(date.toLocaleDateString(locale, options));
|
|
263
277
|
});
|
|
278
|
+
$('a[data-toggle="tab"]').historyTabs();
|
|
264
279
|
}
|
|
265
280
|
|
|
266
281
|
$(initialize_page);
|
|
@@ -479,7 +494,7 @@ function press_store_button(clicked) {
|
|
|
479
494
|
|
|
480
495
|
function ajax_modal(url, opts = {}) {
|
|
481
496
|
if ($("#scmodal").length === 0) {
|
|
482
|
-
$("body").append(`<div id="scmodal", class="modal"
|
|
497
|
+
$("body").append(`<div id="scmodal", class="modal">
|
|
483
498
|
<div class="modal-dialog">
|
|
484
499
|
<div class="modal-content">
|
|
485
500
|
<div class="modal-header">
|
|
@@ -503,6 +518,7 @@ function ajax_modal(url, opts = {}) {
|
|
|
503
518
|
if (title) $("#scmodal .modal-title").html(decodeURIComponent(title));
|
|
504
519
|
$("#scmodal .modal-body").html(res);
|
|
505
520
|
$("#scmodal").modal();
|
|
521
|
+
initialize_page();
|
|
506
522
|
(opts.onOpen || function () {})(res);
|
|
507
523
|
$("#scmodal").on("hidden.bs.modal", function (e) {
|
|
508
524
|
(opts.onClose || function () {})(res);
|
|
@@ -510,6 +526,36 @@ function ajax_modal(url, opts = {}) {
|
|
|
510
526
|
},
|
|
511
527
|
});
|
|
512
528
|
}
|
|
529
|
+
|
|
530
|
+
function saveAndContinue(e, k) {
|
|
531
|
+
var form = $(e).closest("form");
|
|
532
|
+
var url = form.attr("action");
|
|
533
|
+
var form_data = form.serialize();
|
|
534
|
+
$.ajax(url, {
|
|
535
|
+
type: "POST",
|
|
536
|
+
headers: {
|
|
537
|
+
"CSRF-Token": _sc_globalCsrf,
|
|
538
|
+
},
|
|
539
|
+
data: form_data,
|
|
540
|
+
success: function (res) {
|
|
541
|
+
if (res.id && form.find("input[name=id")) {
|
|
542
|
+
form.append(
|
|
543
|
+
`<input type="hidden" class="form-control " name="id" value="${res.id}">`
|
|
544
|
+
);
|
|
545
|
+
}
|
|
546
|
+
},
|
|
547
|
+
error: function (request) {
|
|
548
|
+
$("#page-inner-content").html(request.responseText);
|
|
549
|
+
initialize_page();
|
|
550
|
+
},
|
|
551
|
+
complete: function () {
|
|
552
|
+
if (k) k();
|
|
553
|
+
},
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
return false;
|
|
557
|
+
}
|
|
558
|
+
|
|
513
559
|
function ajaxSubmitForm(e) {
|
|
514
560
|
var form = $(e).closest("form");
|
|
515
561
|
var url = form.attr("action");
|
|
@@ -574,7 +620,41 @@ function ajax_post_btn(e, reload_on_done, reload_delay) {
|
|
|
574
620
|
|
|
575
621
|
return false;
|
|
576
622
|
}
|
|
577
|
-
|
|
623
|
+
function make_unique_field(
|
|
624
|
+
id,
|
|
625
|
+
table_id,
|
|
626
|
+
field_name,
|
|
627
|
+
value,
|
|
628
|
+
space,
|
|
629
|
+
start,
|
|
630
|
+
always_append
|
|
631
|
+
) {
|
|
632
|
+
if (!value) return;
|
|
633
|
+
$.ajax(
|
|
634
|
+
`/api/${table_id}?approximate=true&${encodeURIComponent(
|
|
635
|
+
field_name
|
|
636
|
+
)}=${encodeURIComponent(value)}&fields=${encodeURIComponent(field_name)}`,
|
|
637
|
+
{
|
|
638
|
+
type: "GET",
|
|
639
|
+
success: function (res) {
|
|
640
|
+
if (res.success) {
|
|
641
|
+
const vals = res.success
|
|
642
|
+
.map((o) => o[field_name])
|
|
643
|
+
.filter((s) => s.startsWith(value));
|
|
644
|
+
if (vals.includes(value) || always_append) {
|
|
645
|
+
for (let i = start || 0; i < vals.length + (start || 0) + 2; i++) {
|
|
646
|
+
const newname = `${value}${space ? " " : ""}${i}`;
|
|
647
|
+
if (!vals.includes(newname)) {
|
|
648
|
+
$("#" + id).val(newname);
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
},
|
|
655
|
+
}
|
|
656
|
+
);
|
|
657
|
+
}
|
|
578
658
|
function test_formula(tablename, stored) {
|
|
579
659
|
var formula = $("input[name=expression]").val();
|
|
580
660
|
ajax_post(`/field/test-formula`, {
|
|
@@ -640,6 +720,51 @@ function room_older(viewname, room_id, btn) {
|
|
|
640
720
|
}
|
|
641
721
|
);
|
|
642
722
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
723
|
+
|
|
724
|
+
/*
|
|
725
|
+
https://github.com/jeffdavidgreen/bootstrap-html5-history-tabs/blob/master/bootstrap-history-tabs.js
|
|
726
|
+
Copyright (c) 2015 Jeff Green
|
|
727
|
+
*/
|
|
728
|
+
|
|
729
|
+
+(function ($) {
|
|
730
|
+
"use strict";
|
|
731
|
+
$.fn.historyTabs = function () {
|
|
732
|
+
var that = this;
|
|
733
|
+
window.addEventListener("popstate", function (event) {
|
|
734
|
+
if (event.state) {
|
|
735
|
+
$(that)
|
|
736
|
+
.filter('[href="' + event.state.url + '"]')
|
|
737
|
+
.tab("show");
|
|
738
|
+
}
|
|
739
|
+
});
|
|
740
|
+
return this.each(function (index, element) {
|
|
741
|
+
$(element).on("show.bs.tab", function () {
|
|
742
|
+
var stateObject = { url: $(this).attr("href") };
|
|
743
|
+
|
|
744
|
+
if (window.location.hash && stateObject.url !== window.location.hash) {
|
|
745
|
+
window.history.pushState(
|
|
746
|
+
stateObject,
|
|
747
|
+
document.title,
|
|
748
|
+
window.location.pathname +
|
|
749
|
+
window.location.search +
|
|
750
|
+
$(this).attr("href")
|
|
751
|
+
);
|
|
752
|
+
} else {
|
|
753
|
+
window.history.replaceState(
|
|
754
|
+
stateObject,
|
|
755
|
+
document.title,
|
|
756
|
+
window.location.pathname +
|
|
757
|
+
window.location.search +
|
|
758
|
+
$(this).attr("href")
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
if (!window.location.hash && $(element).is(".active")) {
|
|
763
|
+
// Shows the first element if there are no query parameters.
|
|
764
|
+
$(element).tab("show");
|
|
765
|
+
} else if ($(this).attr("href") === window.location.hash) {
|
|
766
|
+
$(element).tab("show");
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
};
|
|
770
|
+
})(jQuery);
|