@saltcorn/mobile-app 1.1.0-beta.8 → 1.1.0
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/.babelrc +3 -0
- package/build_scripts/modify_android_manifest.js +47 -0
- package/build_scripts/modify_gradle_cfg.js +21 -0
- package/package.json +21 -12
- package/src/.eslintrc +21 -0
- package/src/helpers/api.js +43 -0
- package/src/helpers/auth.js +191 -0
- package/src/helpers/common.js +189 -0
- package/{www/js/utils/table_utils.js → src/helpers/db_schema.js} +18 -40
- package/src/helpers/file_system.js +102 -0
- package/{www/js/utils/global_utils.js → src/helpers/navigation.js} +189 -332
- package/src/helpers/offline_mode.js +645 -0
- package/src/index.js +20 -0
- package/src/init.js +424 -0
- package/src/routing/index.js +98 -0
- package/{www/js → src/routing}/mocks/request.js +5 -5
- package/{www/js → src/routing}/mocks/response.js +1 -1
- package/{www/js → src/routing}/routes/api.js +10 -15
- package/{www/js → src/routing}/routes/auth.js +12 -6
- package/{www/js → src/routing}/routes/delete.js +9 -6
- package/{www/js → src/routing}/routes/edit.js +9 -6
- package/src/routing/routes/error.js +6 -0
- package/{www/js → src/routing}/routes/fields.js +7 -2
- package/{www/js → src/routing}/routes/page.js +15 -10
- package/{www/js → src/routing}/routes/sync.js +17 -8
- package/{www/js → src/routing}/routes/view.js +20 -15
- package/{www/js/routes/common.js → src/routing/utils.js} +18 -13
- package/unsecure-default-key.jks +0 -0
- package/webpack.config.js +31 -0
- package/www/data/encoded_site_logo.js +1 -0
- package/www/index.html +23 -493
- package/www/js/{utils/iframe_view_utils.js → iframe_view_utils.js} +193 -274
- package/config.xml +0 -27
- package/res/icon/android/icon.png +0 -0
- package/res/screen/android/splash-icon.png +0 -0
- package/res/screen/ios/Default@2x~universal~anyany.png +0 -0
- package/www/js/routes/error.js +0 -5
- package/www/js/routes/init.js +0 -76
- package/www/js/utils/file_helpers.js +0 -108
- package/www/js/utils/offline_mode_helper.js +0 -625
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*eslint-env browser*/
|
|
2
|
-
/*global $, KTDrawer, submitWithEmptyAction, is_paging_param, bootstrap, common_done, unique_field_from_rows, inline_submit_success*/
|
|
2
|
+
/*global $, KTDrawer, submitWithEmptyAction, is_paging_param, bootstrap, common_done, unique_field_from_rows, inline_submit_success, get_current_state_url, initialize_page */
|
|
3
3
|
|
|
4
4
|
function combineFormAndQuery(form, query) {
|
|
5
5
|
let paramsList = [];
|
|
@@ -28,19 +28,32 @@ async function execLink(url, linkSrc) {
|
|
|
28
28
|
try {
|
|
29
29
|
if (document.getElementById("scspinner")) return;
|
|
30
30
|
showLoadSpinner();
|
|
31
|
-
if (url.startsWith("
|
|
31
|
+
if (url.startsWith("#")) {
|
|
32
|
+
const anchor = url.substring(1);
|
|
33
|
+
parent.saltcorn.mobileApp.navigation.setAnchor(anchor);
|
|
34
|
+
} else if (url.startsWith("javascript:")) eval(url.substring(11));
|
|
32
35
|
else {
|
|
33
|
-
const { path, query } =
|
|
34
|
-
|
|
36
|
+
const { path, query } =
|
|
37
|
+
parent.saltcorn.mobileApp.navigation.splitPathQuery(url);
|
|
38
|
+
const safePath = path.startsWith("http")
|
|
39
|
+
? new URL(path).pathname
|
|
40
|
+
: path;
|
|
41
|
+
await parent.saltcorn.mobileApp.navigation.handleRoute(
|
|
42
|
+
`get${safePath}`,
|
|
43
|
+
query
|
|
44
|
+
);
|
|
35
45
|
}
|
|
46
|
+
} catch (error) {
|
|
47
|
+
parent.saltcorn.mobileApp.common.errorAlert(error);
|
|
36
48
|
} finally {
|
|
37
49
|
removeLoadSpinner();
|
|
38
50
|
}
|
|
39
51
|
}
|
|
40
52
|
|
|
41
53
|
async function runUrl(url, method = "get") {
|
|
42
|
-
const { path, query } =
|
|
43
|
-
|
|
54
|
+
const { path, query } =
|
|
55
|
+
parent.saltcorn.mobileApp.navigation.splitPathQuery(url);
|
|
56
|
+
const page = await parent.saltcorn.mobileApp.navigation.router.resolve({
|
|
44
57
|
pathname: `${method}${path}`,
|
|
45
58
|
query: query,
|
|
46
59
|
});
|
|
@@ -84,17 +97,23 @@ async function formSubmit(e, urlSuffix, viewname, noSubmitCb, matchingState) {
|
|
|
84
97
|
const tokens = entry[1].split("/");
|
|
85
98
|
const fileName = tokens[tokens.length - 1];
|
|
86
99
|
const directory = tokens.splice(0, tokens.length - 1).join("/");
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
100
|
+
const { buffer, file } =
|
|
101
|
+
await parent.saltcorn.mobileApp.fileSystem.readBinaryCordova(
|
|
102
|
+
fileName,
|
|
103
|
+
directory
|
|
104
|
+
);
|
|
105
|
+
files[entry[0]] = {
|
|
106
|
+
blob: new Blob([buffer], { type: file.type }),
|
|
107
|
+
fileObj: file,
|
|
108
|
+
};
|
|
90
109
|
} else if (!matchingState) urlParams.append(entry[0], entry[1]);
|
|
91
110
|
else data[entry[0]] = entry[1];
|
|
92
111
|
}
|
|
93
112
|
}
|
|
94
113
|
const queryStr = !matchingState
|
|
95
114
|
? urlParams.toString()
|
|
96
|
-
: parent.currentQuery() || "";
|
|
97
|
-
await parent.handleRoute(
|
|
115
|
+
: parent.saltcorn.mobileApp.navigation.currentQuery() || "";
|
|
116
|
+
await parent.saltcorn.mobileApp.navigation.handleRoute(
|
|
98
117
|
`post${urlSuffix}${viewname}`,
|
|
99
118
|
queryStr,
|
|
100
119
|
files,
|
|
@@ -116,13 +135,13 @@ async function inline_local_submit(e, opts1) {
|
|
|
116
135
|
urlParams.append(entry[0], entry[1]);
|
|
117
136
|
}
|
|
118
137
|
const url = form.attr("action");
|
|
119
|
-
await parent.router.resolve({
|
|
138
|
+
await parent.saltcorn.mobileApp.navigation.router.resolve({
|
|
120
139
|
pathname: `post${url}`,
|
|
121
140
|
query: urlParams.toString(),
|
|
122
141
|
});
|
|
123
142
|
inline_submit_success(e, form, opts);
|
|
124
143
|
} catch (error) {
|
|
125
|
-
parent.showAlerts([
|
|
144
|
+
parent.saltcorn.mobileApp.common.showAlerts([
|
|
126
145
|
{
|
|
127
146
|
type: "error",
|
|
128
147
|
msg: error.message ? error.message : "An error occured.",
|
|
@@ -145,7 +164,7 @@ async function saveAndContinue(e, action, k) {
|
|
|
145
164
|
const form = $(e).closest("form");
|
|
146
165
|
submitWithEmptyAction(form[0]);
|
|
147
166
|
const queryStr = new URLSearchParams(new FormData(form[0])).toString();
|
|
148
|
-
const res = await parent.router.resolve({
|
|
167
|
+
const res = await parent.saltcorn.mobileApp.navigation.router.resolve({
|
|
149
168
|
pathname: `post${action}`,
|
|
150
169
|
query: queryStr,
|
|
151
170
|
xhr: true,
|
|
@@ -162,95 +181,16 @@ async function saveAndContinue(e, action, k) {
|
|
|
162
181
|
}
|
|
163
182
|
}
|
|
164
183
|
|
|
165
|
-
async function loginRequest({ email, password, isSignup, isPublic }) {
|
|
166
|
-
const opts = isPublic
|
|
167
|
-
? {
|
|
168
|
-
method: "GET",
|
|
169
|
-
path: "/auth/login-with/jwt",
|
|
170
|
-
}
|
|
171
|
-
: isSignup
|
|
172
|
-
? {
|
|
173
|
-
method: "POST",
|
|
174
|
-
path: "/auth/signup",
|
|
175
|
-
body: {
|
|
176
|
-
email,
|
|
177
|
-
password,
|
|
178
|
-
},
|
|
179
|
-
}
|
|
180
|
-
: {
|
|
181
|
-
method: "GET",
|
|
182
|
-
path: "/auth/login-with/jwt",
|
|
183
|
-
params: {
|
|
184
|
-
email,
|
|
185
|
-
password,
|
|
186
|
-
},
|
|
187
|
-
};
|
|
188
|
-
const response = await parent.apiCall(opts);
|
|
189
|
-
return response.data;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
184
|
async function login(e, entryPoint, isSignup) {
|
|
193
185
|
try {
|
|
194
186
|
showLoadSpinner();
|
|
195
187
|
const formData = new FormData(e);
|
|
196
|
-
|
|
188
|
+
await parent.saltcorn.mobileApp.auth.login({
|
|
197
189
|
email: formData.get("email"),
|
|
198
190
|
password: formData.get("password"),
|
|
199
191
|
isSignup,
|
|
192
|
+
entryPoint,
|
|
200
193
|
});
|
|
201
|
-
if (typeof loginResult === "string") {
|
|
202
|
-
// use it as a token
|
|
203
|
-
const decodedJwt = parent.jwt_decode(loginResult);
|
|
204
|
-
const state = parent.saltcorn.data.state.getState();
|
|
205
|
-
const config = state.mobileConfig;
|
|
206
|
-
config.role_id = decodedJwt.user.role_id ? decodedJwt.user.role_id : 100;
|
|
207
|
-
config.user_name = decodedJwt.user.email;
|
|
208
|
-
config.user_id = decodedJwt.user.id;
|
|
209
|
-
config.language = decodedJwt.user.language;
|
|
210
|
-
config.user = decodedJwt.user;
|
|
211
|
-
config.isPublicUser = false;
|
|
212
|
-
config.isOfflineMode = false;
|
|
213
|
-
await parent.insertUser(config.user);
|
|
214
|
-
await parent.setJwt(loginResult);
|
|
215
|
-
config.jwt = loginResult;
|
|
216
|
-
await parent.i18next.changeLanguage(config.language);
|
|
217
|
-
const alerts = [];
|
|
218
|
-
if (config.allowOfflineMode) {
|
|
219
|
-
const { offlineUser, hasOfflineData } =
|
|
220
|
-
(await parent.offlineHelper.getLastOfflineSession()) || {};
|
|
221
|
-
if (!offlineUser || offlineUser === config.user_name) {
|
|
222
|
-
await parent.offlineHelper.sync();
|
|
223
|
-
} else {
|
|
224
|
-
if (hasOfflineData)
|
|
225
|
-
alerts.push({
|
|
226
|
-
type: "warning",
|
|
227
|
-
msg: `'${offlineUser}' has not yet uploaded offline data.`,
|
|
228
|
-
});
|
|
229
|
-
else {
|
|
230
|
-
await deleteOfflineData(true);
|
|
231
|
-
await parent.offlineHelper.sync();
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
alerts.push({
|
|
236
|
-
type: "success",
|
|
237
|
-
msg: parent.i18next.t("Welcome, %s!", {
|
|
238
|
-
postProcess: "sprintf",
|
|
239
|
-
sprintf: [config.user_name],
|
|
240
|
-
}),
|
|
241
|
-
});
|
|
242
|
-
parent.addRoute({ route: entryPoint, query: undefined });
|
|
243
|
-
const page = await parent.router.resolve({
|
|
244
|
-
pathname: entryPoint,
|
|
245
|
-
fullWrap: true,
|
|
246
|
-
alerts,
|
|
247
|
-
});
|
|
248
|
-
if (page.content) await parent.replaceIframe(page.content, page.isFile);
|
|
249
|
-
} else if (loginResult?.alerts) {
|
|
250
|
-
parent.showAlerts(loginResult?.alerts);
|
|
251
|
-
} else {
|
|
252
|
-
throw new Error("The login failed.");
|
|
253
|
-
}
|
|
254
194
|
} finally {
|
|
255
195
|
removeLoadSpinner();
|
|
256
196
|
}
|
|
@@ -259,77 +199,16 @@ async function login(e, entryPoint, isSignup) {
|
|
|
259
199
|
async function publicLogin(entryPoint) {
|
|
260
200
|
try {
|
|
261
201
|
showLoadSpinner();
|
|
262
|
-
|
|
263
|
-
if (typeof loginResult === "string") {
|
|
264
|
-
const config = parent.saltcorn.data.state.getState().mobileConfig;
|
|
265
|
-
config.user = {
|
|
266
|
-
role_id: 100,
|
|
267
|
-
user_name: "public",
|
|
268
|
-
language: "en",
|
|
269
|
-
};
|
|
270
|
-
// TODO remove these, use 'user' everywhere
|
|
271
|
-
config.role_id = 100;
|
|
272
|
-
config.user_name = "public";
|
|
273
|
-
config.language = "en";
|
|
274
|
-
|
|
275
|
-
config.isPublicUser = true;
|
|
276
|
-
await parent.setJwt(loginResult);
|
|
277
|
-
config.jwt = loginResult;
|
|
278
|
-
parent.i18next.changeLanguage(config.language);
|
|
279
|
-
parent.addRoute({ route: entryPoint, query: undefined });
|
|
280
|
-
const page = await parent.router.resolve({
|
|
281
|
-
pathname: entryPoint,
|
|
282
|
-
fullWrap: true,
|
|
283
|
-
alerts: [
|
|
284
|
-
{
|
|
285
|
-
type: "success",
|
|
286
|
-
msg: parent.i18next.t("Welcome to %s!", {
|
|
287
|
-
postProcess: "sprintf",
|
|
288
|
-
sprintf: [
|
|
289
|
-
parent.saltcorn.data.state.getState().getConfig("site_name") ||
|
|
290
|
-
"Saltcorn",
|
|
291
|
-
],
|
|
292
|
-
}),
|
|
293
|
-
},
|
|
294
|
-
],
|
|
295
|
-
});
|
|
296
|
-
if (page.content) await parent.replaceIframe(page.content, page.isFile);
|
|
297
|
-
} else if (loginResult?.alerts) {
|
|
298
|
-
parent.showAlerts(loginResult?.alerts);
|
|
299
|
-
} else {
|
|
300
|
-
throw new Error("The login failed.");
|
|
301
|
-
}
|
|
302
|
-
} catch (error) {
|
|
303
|
-
console.log(error);
|
|
304
|
-
parent.showAlerts([
|
|
305
|
-
{
|
|
306
|
-
type: "error",
|
|
307
|
-
msg: error.message ? error.message : "An error occured.",
|
|
308
|
-
},
|
|
309
|
-
]);
|
|
310
|
-
throw error;
|
|
202
|
+
await parent.saltcorn.mobileApp.auth.publicLogin(entryPoint);
|
|
311
203
|
} finally {
|
|
312
204
|
removeLoadSpinner();
|
|
313
205
|
}
|
|
314
206
|
}
|
|
315
207
|
|
|
316
208
|
async function logout() {
|
|
317
|
-
const config = parent.saltcorn.data.state.getState().mobileConfig;
|
|
318
209
|
try {
|
|
319
210
|
showLoadSpinner();
|
|
320
|
-
|
|
321
|
-
pathname: "get/auth/logout",
|
|
322
|
-
entryView: config.entry_point,
|
|
323
|
-
versionTag: config.version_tag,
|
|
324
|
-
});
|
|
325
|
-
await parent.replaceIframe(page.content);
|
|
326
|
-
} catch (error) {
|
|
327
|
-
parent.showAlerts([
|
|
328
|
-
{
|
|
329
|
-
type: "error",
|
|
330
|
-
msg: error.message ? error.message : "An error occured.",
|
|
331
|
-
},
|
|
332
|
-
]);
|
|
211
|
+
await parent.saltcorn.mobileApp.auth.logout();
|
|
333
212
|
} finally {
|
|
334
213
|
removeLoadSpinner();
|
|
335
214
|
}
|
|
@@ -339,7 +218,7 @@ async function signupFormSubmit(e, entryView) {
|
|
|
339
218
|
try {
|
|
340
219
|
await login(e, entryView, true);
|
|
341
220
|
} catch (error) {
|
|
342
|
-
parent.errorAlert(error);
|
|
221
|
+
parent.saltcorn.mobileApp.common.errorAlert(error);
|
|
343
222
|
}
|
|
344
223
|
}
|
|
345
224
|
|
|
@@ -353,7 +232,7 @@ async function loginFormSubmit(e, entryView) {
|
|
|
353
232
|
}
|
|
354
233
|
await login(e, safeEntryView, false);
|
|
355
234
|
} catch (error) {
|
|
356
|
-
parent.errorAlert(error);
|
|
235
|
+
parent.saltcorn.mobileApp.common.errorAlert(error);
|
|
357
236
|
}
|
|
358
237
|
}
|
|
359
238
|
|
|
@@ -363,8 +242,9 @@ async function local_post_btn(e) {
|
|
|
363
242
|
const form = $(e).closest("form");
|
|
364
243
|
const url = form.attr("action");
|
|
365
244
|
const method = form.attr("method");
|
|
366
|
-
const { path, query } =
|
|
367
|
-
|
|
245
|
+
const { path, query } =
|
|
246
|
+
parent.saltcorn.mobileApp.navigation.splitPathQuery(url);
|
|
247
|
+
await parent.saltcorn.mobileApp.navigation.handleRoute(
|
|
368
248
|
`${method}${path}`,
|
|
369
249
|
combineFormAndQuery(form, query)
|
|
370
250
|
);
|
|
@@ -382,7 +262,7 @@ async function stateFormSubmit(e, path) {
|
|
|
382
262
|
try {
|
|
383
263
|
showLoadSpinner();
|
|
384
264
|
const formQuery = new URLSearchParams(new FormData(e)).toString();
|
|
385
|
-
await parent.handleRoute(path, formQuery);
|
|
265
|
+
await parent.saltcorn.mobileApp.navigation.handleRoute(path, formQuery);
|
|
386
266
|
} finally {
|
|
387
267
|
removeLoadSpinner();
|
|
388
268
|
}
|
|
@@ -428,11 +308,14 @@ function invalidate_pagings(currentQuery) {
|
|
|
428
308
|
return newQuery;
|
|
429
309
|
}
|
|
430
310
|
|
|
431
|
-
async function set_state_fields(kvs,
|
|
311
|
+
async function set_state_fields(kvs, disablePjax, e) {
|
|
432
312
|
try {
|
|
433
313
|
showLoadSpinner();
|
|
314
|
+
let newhref = get_current_state_url(e);
|
|
434
315
|
let queryParams = [];
|
|
435
|
-
|
|
316
|
+
const { path, query } =
|
|
317
|
+
parent.saltcorn.mobileApp.navigation.splitPathQuery(newhref);
|
|
318
|
+
let currentQuery = query || {};
|
|
436
319
|
if (Object.keys(kvs).some((k) => !is_paging_param(k))) {
|
|
437
320
|
currentQuery = invalidate_pagings(currentQuery);
|
|
438
321
|
}
|
|
@@ -446,17 +329,65 @@ async function set_state_fields(kvs, href) {
|
|
|
446
329
|
for (const [k, v] of new URLSearchParams(currentQuery).entries()) {
|
|
447
330
|
queryParams.push(`${k}=${v}`);
|
|
448
331
|
}
|
|
449
|
-
|
|
332
|
+
const queryStr = queryParams.join("&");
|
|
333
|
+
if (disablePjax)
|
|
334
|
+
await parent.saltcorn.mobileApp.navigation.handleRoute(path, queryStr);
|
|
335
|
+
else await pjax_to(path, queryStr, e);
|
|
450
336
|
} finally {
|
|
451
337
|
removeLoadSpinner();
|
|
452
338
|
}
|
|
453
339
|
}
|
|
454
340
|
|
|
341
|
+
async function pjax_to(href, query, e) {
|
|
342
|
+
const safeHref = href.startsWith("get") ? href.substring(3) : href;
|
|
343
|
+
const path = `${safeHref}?${query}`;
|
|
344
|
+
let $modal = $("#scmodal");
|
|
345
|
+
const inModal = $modal.length && $modal.hasClass("show");
|
|
346
|
+
const localizer = e ? $(e).closest("[data-sc-local-state]") : [];
|
|
347
|
+
let $dest = localizer.length
|
|
348
|
+
? localizer
|
|
349
|
+
: inModal
|
|
350
|
+
? $("#scmodal .modal-body")
|
|
351
|
+
: $("#page-inner-content");
|
|
352
|
+
if (!$dest.length)
|
|
353
|
+
await parent.saltcorn.mobileApp.navigation.handleRoute(safeHref, query);
|
|
354
|
+
else
|
|
355
|
+
try {
|
|
356
|
+
const headers = {
|
|
357
|
+
pjaxpageload: "true",
|
|
358
|
+
};
|
|
359
|
+
if (localizer.length) headers.localizedstate = "true";
|
|
360
|
+
const result = await parent.saltcorn.mobileApp.api.apiCall({
|
|
361
|
+
path: path,
|
|
362
|
+
method: "GET",
|
|
363
|
+
additionalHeaders: headers,
|
|
364
|
+
});
|
|
365
|
+
if (!inModal && !localizer.length) {
|
|
366
|
+
// not sure for mobile
|
|
367
|
+
// window.history.pushState({ url: href }, "", href);
|
|
368
|
+
}
|
|
369
|
+
if (inModal && !localizer.length)
|
|
370
|
+
$(".sc-modal-linkout").attr("href", path);
|
|
371
|
+
$dest.html(result.data);
|
|
372
|
+
if (localizer.length) localizer.attr("data-sc-local-state", path);
|
|
373
|
+
initialize_page();
|
|
374
|
+
} catch (error) {
|
|
375
|
+
parent.saltcorn.mobileApp.common.errorAlert(error);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
455
379
|
async function set_state_field(key, value) {
|
|
456
380
|
try {
|
|
457
381
|
showLoadSpinner();
|
|
458
|
-
const query = updateQueryStringParameter(
|
|
459
|
-
|
|
382
|
+
const query = updateQueryStringParameter(
|
|
383
|
+
parent.saltcorn.mobileApp.navigation.currentQuery(),
|
|
384
|
+
key,
|
|
385
|
+
value
|
|
386
|
+
);
|
|
387
|
+
await parent.saltcorn.mobileApp.navigation.handleRoute(
|
|
388
|
+
parent.saltcorn.mobileApp.navigation.currentLocation(),
|
|
389
|
+
query
|
|
390
|
+
);
|
|
460
391
|
} finally {
|
|
461
392
|
removeLoadSpinner();
|
|
462
393
|
}
|
|
@@ -465,32 +396,37 @@ async function set_state_field(key, value) {
|
|
|
465
396
|
async function unset_state_field(key) {
|
|
466
397
|
try {
|
|
467
398
|
showLoadSpinner();
|
|
468
|
-
const href = parent.currentLocation();
|
|
469
|
-
const query = removeQueryStringParameter(
|
|
470
|
-
|
|
399
|
+
const href = parent.saltcorn.mobileApp.navigation.currentLocation();
|
|
400
|
+
const query = removeQueryStringParameter(
|
|
401
|
+
parent.saltcorn.mobileApp.navigation.currentLocation(),
|
|
402
|
+
key
|
|
403
|
+
);
|
|
404
|
+
await parent.saltcorn.mobileApp.navigation.handleRoute(href, query);
|
|
471
405
|
} finally {
|
|
472
406
|
removeLoadSpinner();
|
|
473
407
|
}
|
|
474
408
|
}
|
|
475
409
|
|
|
476
|
-
async function sortby(k, desc, viewIdentifier) {
|
|
410
|
+
async function sortby(k, desc, viewIdentifier, e) {
|
|
477
411
|
await set_state_fields(
|
|
478
412
|
{
|
|
479
413
|
[`_${viewIdentifier}_sortby`]: k,
|
|
480
414
|
[`_${viewIdentifier}_sortdesc`]: desc ? "on" : { unset: true },
|
|
481
415
|
},
|
|
482
|
-
|
|
416
|
+
false,
|
|
417
|
+
e
|
|
483
418
|
);
|
|
484
419
|
}
|
|
485
420
|
|
|
486
|
-
async function gopage(n, pagesize, viewIdentifier, extra) {
|
|
421
|
+
async function gopage(n, pagesize, viewIdentifier, extra, e) {
|
|
487
422
|
await set_state_fields(
|
|
488
423
|
{
|
|
489
424
|
...extra,
|
|
490
425
|
[`_${viewIdentifier}_page`]: n,
|
|
491
426
|
[`_${viewIdentifier}_pagesize`]: pagesize,
|
|
492
427
|
},
|
|
493
|
-
|
|
428
|
+
false,
|
|
429
|
+
e
|
|
494
430
|
);
|
|
495
431
|
}
|
|
496
432
|
|
|
@@ -529,18 +465,19 @@ async function mobile_modal(url, opts = {}) {
|
|
|
529
465
|
if (opts.submitReload === false) $("#scmodal").addClass("no-submit-reload");
|
|
530
466
|
else $("#scmodal").removeClass("no-submit-reload");
|
|
531
467
|
try {
|
|
532
|
-
const { path, query } =
|
|
468
|
+
const { path, query } =
|
|
469
|
+
parent.saltcorn.mobileApp.navigation.splitPathQuery(url);
|
|
533
470
|
const mobileConfig = parent.saltcorn.data.state.getState().mobileConfig;
|
|
534
471
|
if (
|
|
535
472
|
mobileConfig.networkState === "none" &&
|
|
536
473
|
mobileConfig.allowOfflineMode &&
|
|
537
474
|
!mobileConfig.isOfflineMode
|
|
538
475
|
) {
|
|
539
|
-
await parent.
|
|
540
|
-
parent.clearHistory();
|
|
541
|
-
await parent.gotoEntryView();
|
|
476
|
+
await parent.saltcorn.mobileApp.offlineMode.startOfflineMode();
|
|
477
|
+
parent.saltcorn.mobileApp.navigation.clearHistory();
|
|
478
|
+
await parent.saltcorn.mobileApp.navigation.gotoEntryView();
|
|
542
479
|
} else {
|
|
543
|
-
const page = await parent.router.resolve({
|
|
480
|
+
const page = await parent.saltcorn.mobileApp.navigation.router.resolve({
|
|
544
481
|
pathname: `get${path}`,
|
|
545
482
|
query: query,
|
|
546
483
|
alerts: [],
|
|
@@ -553,7 +490,7 @@ async function mobile_modal(url, opts = {}) {
|
|
|
553
490
|
// onOpen onClose initialize_page?
|
|
554
491
|
}
|
|
555
492
|
} catch (error) {
|
|
556
|
-
parent.showAlerts([
|
|
493
|
+
parent.saltcorn.mobileApp.common.showAlerts([
|
|
557
494
|
{
|
|
558
495
|
type: "error",
|
|
559
496
|
msg: error.message ? error.message : "An error occured.",
|
|
@@ -569,14 +506,15 @@ function closeModal() {
|
|
|
569
506
|
async function local_post(url, args) {
|
|
570
507
|
try {
|
|
571
508
|
showLoadSpinner();
|
|
572
|
-
const result = await parent.router.resolve({
|
|
509
|
+
const result = await parent.saltcorn.mobileApp.navigation.router.resolve({
|
|
573
510
|
pathname: `post${url}`,
|
|
574
511
|
data: args,
|
|
575
512
|
});
|
|
576
|
-
if (result.redirect)
|
|
513
|
+
if (result.redirect)
|
|
514
|
+
await parent.saltcorn.mobileApp.navigation.handleRoute(result.redirect);
|
|
577
515
|
else await common_done(result, "", false);
|
|
578
516
|
} catch (error) {
|
|
579
|
-
parent.errorAlert(error);
|
|
517
|
+
parent.saltcorn.mobileApp.common.errorAlert(error);
|
|
580
518
|
} finally {
|
|
581
519
|
removeLoadSpinner();
|
|
582
520
|
}
|
|
@@ -585,17 +523,18 @@ async function local_post(url, args) {
|
|
|
585
523
|
async function local_post_json(url, data, cb) {
|
|
586
524
|
try {
|
|
587
525
|
showLoadSpinner();
|
|
588
|
-
const result = await parent.router.resolve({
|
|
526
|
+
const result = await parent.saltcorn.mobileApp.navigation.router.resolve({
|
|
589
527
|
pathname: `post${url}`,
|
|
590
528
|
data: data,
|
|
591
|
-
query: parent.currentQuery(),
|
|
529
|
+
query: parent.saltcorn.mobileApp.navigation.currentQuery(),
|
|
592
530
|
});
|
|
593
531
|
if (result.server_eval) await evalServerCode(url);
|
|
594
|
-
if (result.redirect)
|
|
532
|
+
if (result.redirect)
|
|
533
|
+
await parent.saltcorn.mobileApp.navigation.handleRoute(result.redirect);
|
|
595
534
|
else await common_done(result, "", false);
|
|
596
535
|
if (cb?.success) cb.success(result);
|
|
597
536
|
} catch (error) {
|
|
598
|
-
parent.errorAlert(error);
|
|
537
|
+
parent.saltcorn.mobileApp.common.errorAlert(error);
|
|
599
538
|
if (cb?.error) cb.error(error);
|
|
600
539
|
} finally {
|
|
601
540
|
removeLoadSpinner();
|
|
@@ -603,7 +542,7 @@ async function local_post_json(url, data, cb) {
|
|
|
603
542
|
}
|
|
604
543
|
|
|
605
544
|
async function evalServerCode(url) {
|
|
606
|
-
await parent.apiCall({
|
|
545
|
+
await parent.saltcorn.mobileApp.api.apiCall({
|
|
607
546
|
method: "POST",
|
|
608
547
|
path: url,
|
|
609
548
|
});
|
|
@@ -626,7 +565,7 @@ async function make_unique_field(
|
|
|
626
565
|
)}=${encodeURIComponent(value)}&fields=${encodeURIComponent(field_name)}`;
|
|
627
566
|
try {
|
|
628
567
|
// TODO ch support local tables
|
|
629
|
-
const response = await parent.apiCall({
|
|
568
|
+
const response = await parent.saltcorn.mobileApp.api.apiCall({
|
|
630
569
|
method: "GET",
|
|
631
570
|
path,
|
|
632
571
|
});
|
|
@@ -643,7 +582,7 @@ async function make_unique_field(
|
|
|
643
582
|
);
|
|
644
583
|
}
|
|
645
584
|
} catch (error) {
|
|
646
|
-
parent.showAlerts([
|
|
585
|
+
parent.saltcorn.mobileApp.common.showAlerts([
|
|
647
586
|
{
|
|
648
587
|
type: "error",
|
|
649
588
|
msg: "unable to 'make_unique_field'",
|
|
@@ -688,11 +627,14 @@ async function select_id(id) {
|
|
|
688
627
|
try {
|
|
689
628
|
showLoadSpinner();
|
|
690
629
|
const newQuery = updateQueryStringParameter(
|
|
691
|
-
parent.currentQuery(),
|
|
630
|
+
parent.saltcorn.mobileApp.navigation.currentQuery(),
|
|
692
631
|
"id",
|
|
693
632
|
id
|
|
694
633
|
);
|
|
695
|
-
await parent.handleRoute(
|
|
634
|
+
await parent.handleRoute(
|
|
635
|
+
parent.saltcorn.mobileApp.navigation.currentLocation(),
|
|
636
|
+
newQuery
|
|
637
|
+
);
|
|
696
638
|
} finally {
|
|
697
639
|
removeLoadSpinner();
|
|
698
640
|
}
|
|
@@ -703,9 +645,16 @@ async function check_state_field(that) {
|
|
|
703
645
|
showLoadSpinner();
|
|
704
646
|
const name = that.name;
|
|
705
647
|
const newQuery = that.checked
|
|
706
|
-
? updateQueryStringParameter(
|
|
648
|
+
? updateQueryStringParameter(
|
|
649
|
+
parent.saltcorn.mobileApp.navigation.currentQuery(),
|
|
650
|
+
name,
|
|
651
|
+
that.value
|
|
652
|
+
)
|
|
707
653
|
: removeQueryStringParameter(name);
|
|
708
|
-
await parent.handleRoute(
|
|
654
|
+
await parent.saltcorn.mobileApp.navigation.handleRoute(
|
|
655
|
+
parent.saltcorn.mobileApp.navigation.currentLocation(),
|
|
656
|
+
newQuery
|
|
657
|
+
);
|
|
709
658
|
} finally {
|
|
710
659
|
removeLoadSpinner();
|
|
711
660
|
}
|
|
@@ -714,7 +663,10 @@ async function check_state_field(that) {
|
|
|
714
663
|
async function clear_state() {
|
|
715
664
|
try {
|
|
716
665
|
showLoadSpinner();
|
|
717
|
-
await parent.handleRoute(
|
|
666
|
+
await parent.saltcorn.mobileApp.navigation.handleRoute(
|
|
667
|
+
parent.saltcorn.mobileApp.navigation.currentLocation(),
|
|
668
|
+
undefined
|
|
669
|
+
);
|
|
718
670
|
} finally {
|
|
719
671
|
removeLoadSpinner();
|
|
720
672
|
}
|
|
@@ -728,7 +680,7 @@ async function view_post(viewnameOrElem, route, data, onDone, sendState) {
|
|
|
728
680
|
.closest("[data-sc-embed-viewname]")
|
|
729
681
|
.attr("data-sc-embed-viewname");
|
|
730
682
|
const buildQuery = () => {
|
|
731
|
-
const query = parent.currentQuery();
|
|
683
|
+
const query = parent.saltcorn.mobileApp.navigation.currentQuery();
|
|
732
684
|
return query ? `?${query}` : "";
|
|
733
685
|
};
|
|
734
686
|
const mobileConfig = parent.saltcorn.data.state.getState().mobileConfig;
|
|
@@ -741,13 +693,13 @@ async function view_post(viewnameOrElem, route, data, onDone, sendState) {
|
|
|
741
693
|
mobileConfig.isOfflineMode ||
|
|
742
694
|
(view?.table_id && mobileConfig.localTableIds.indexOf(view.table_id) >= 0)
|
|
743
695
|
) {
|
|
744
|
-
respData = await parent.router.resolve({
|
|
696
|
+
respData = await parent.saltcorn.mobileApp.navigation.router.resolve({
|
|
745
697
|
pathname: `post/view/${viewname}/${route}`,
|
|
746
698
|
data,
|
|
747
699
|
query,
|
|
748
700
|
});
|
|
749
701
|
} else {
|
|
750
|
-
const response = await parent.apiCall({
|
|
702
|
+
const response = await parent.saltcorn.mobileApp.api.apiCall({
|
|
751
703
|
method: "POST",
|
|
752
704
|
path: "/view/" + viewname + "/" + route + query,
|
|
753
705
|
body: data,
|
|
@@ -760,7 +712,7 @@ async function view_post(viewnameOrElem, route, data, onDone, sendState) {
|
|
|
760
712
|
if (onDone) await onDone(respData);
|
|
761
713
|
await common_done(respData, viewname, false);
|
|
762
714
|
} catch (error) {
|
|
763
|
-
parent.errorAlert(error);
|
|
715
|
+
parent.saltcorn.mobileApp.common.errorAlert(error);
|
|
764
716
|
} finally {
|
|
765
717
|
removeLoadSpinner();
|
|
766
718
|
}
|
|
@@ -783,37 +735,41 @@ async function switchNetworkMode() {
|
|
|
783
735
|
const state = parent.saltcorn.data.state.getState();
|
|
784
736
|
const { isOfflineMode, networkState } = state.mobileConfig;
|
|
785
737
|
if (!isOfflineMode) {
|
|
786
|
-
await parent.
|
|
787
|
-
parent.clearHistory();
|
|
788
|
-
parent.addRoute({ route: "/" });
|
|
789
|
-
parent.addRoute({
|
|
790
|
-
|
|
738
|
+
await parent.saltcorn.mobileApp.offlineMode.startOfflineMode();
|
|
739
|
+
parent.saltcorn.mobileApp.navigation.clearHistory();
|
|
740
|
+
parent.saltcorn.mobileApp.navigation.addRoute({ route: "/" });
|
|
741
|
+
parent.saltcorn.mobileApp.navigation.addRoute({
|
|
742
|
+
route: "get/sync/sync_settings",
|
|
743
|
+
});
|
|
744
|
+
parent.saltcorn.mobileApp.common.showAlerts(
|
|
791
745
|
[
|
|
792
746
|
{
|
|
793
747
|
type: "info",
|
|
794
|
-
msg: parent.
|
|
748
|
+
msg: parent.saltcorn.mobileApp.offlineMode.getOfflineMsg(),
|
|
795
749
|
},
|
|
796
750
|
],
|
|
797
751
|
false
|
|
798
752
|
);
|
|
799
|
-
parent.clearAlerts();
|
|
753
|
+
parent.saltcorn.mobileApp.common.clearAlerts();
|
|
800
754
|
} else {
|
|
801
755
|
if (networkState === "none")
|
|
802
756
|
throw new Error("No internet connection is available.");
|
|
803
|
-
await parent.
|
|
804
|
-
parent.clearHistory();
|
|
805
|
-
parent.addRoute({ route: "/" });
|
|
806
|
-
parent.addRoute({
|
|
807
|
-
|
|
757
|
+
await parent.saltcorn.mobileApp.offlineMode.endOfflineMode();
|
|
758
|
+
parent.saltcorn.mobileApp.navigation.clearHistory();
|
|
759
|
+
parent.saltcorn.mobileApp.navigation.addRoute({ route: "/" });
|
|
760
|
+
parent.saltcorn.mobileApp.navigation.addRoute({
|
|
761
|
+
route: "get/sync/sync_settings",
|
|
762
|
+
});
|
|
763
|
+
parent.saltcorn.mobileApp.common.showAlerts([
|
|
808
764
|
{
|
|
809
765
|
type: "info",
|
|
810
766
|
msg: "You are online again.",
|
|
811
767
|
},
|
|
812
768
|
]);
|
|
813
|
-
parent.clearTopAlerts();
|
|
769
|
+
parent.saltcorn.mobileApp.common.clearTopAlerts();
|
|
814
770
|
}
|
|
815
771
|
} catch (error) {
|
|
816
|
-
parent.showAlerts([
|
|
772
|
+
parent.saltcorn.mobileApp.common.showAlerts([
|
|
817
773
|
{
|
|
818
774
|
type: "error",
|
|
819
775
|
msg: `Unable to change the network mode: ${
|
|
@@ -833,7 +789,7 @@ async function callSync() {
|
|
|
833
789
|
try {
|
|
834
790
|
const mobileConfig = parent.saltcorn.data.state.getState().mobileConfig;
|
|
835
791
|
if (mobileConfig.networkState === "none") {
|
|
836
|
-
parent.showAlerts([
|
|
792
|
+
parent.saltcorn.mobileApp.common.showAlerts([
|
|
837
793
|
{
|
|
838
794
|
type: "error",
|
|
839
795
|
msg: "You don't have an internet connection.",
|
|
@@ -842,10 +798,10 @@ async function callSync() {
|
|
|
842
798
|
} else {
|
|
843
799
|
const wasOffline = mobileConfig.isOfflineMode;
|
|
844
800
|
showLoadSpinner();
|
|
845
|
-
await parent.
|
|
846
|
-
parent.clearAlerts();
|
|
801
|
+
await parent.saltcorn.mobileApp.offlineMode.sync();
|
|
802
|
+
parent.saltcorn.mobileApp.common.clearAlerts();
|
|
847
803
|
if (!wasOffline) {
|
|
848
|
-
parent.showAlerts([
|
|
804
|
+
parent.saltcorn.mobileApp.common.showAlerts([
|
|
849
805
|
{
|
|
850
806
|
type: "info",
|
|
851
807
|
msg: "Synchronized your offline data.",
|
|
@@ -853,38 +809,41 @@ async function callSync() {
|
|
|
853
809
|
]);
|
|
854
810
|
} else {
|
|
855
811
|
setNetworSwitcherOn();
|
|
856
|
-
parent.clearHistory();
|
|
857
|
-
parent.addRoute({ route: "/" });
|
|
858
|
-
parent.addRoute({
|
|
859
|
-
|
|
812
|
+
parent.saltcorn.mobileApp.navigation.clearHistory();
|
|
813
|
+
parent.saltcorn.mobileApp.navigation.addRoute({ route: "/" });
|
|
814
|
+
parent.saltcorn.mobileApp.navigation.addRoute({
|
|
815
|
+
route: "get/sync/sync_settings",
|
|
816
|
+
});
|
|
817
|
+
parent.saltcorn.mobileApp.common.showAlerts([
|
|
860
818
|
{
|
|
861
819
|
type: "info",
|
|
862
820
|
msg: "Synchronized your offline data, you are online again.",
|
|
863
821
|
},
|
|
864
822
|
]);
|
|
865
|
-
parent.clearTopAlerts();
|
|
823
|
+
parent.saltcorn.mobileApp.common.clearTopAlerts();
|
|
866
824
|
}
|
|
867
825
|
}
|
|
868
826
|
} catch (error) {
|
|
869
827
|
console.log(error);
|
|
870
|
-
parent.errorAlert(error);
|
|
828
|
+
parent.saltcorn.mobileApp.common.errorAlert(error);
|
|
871
829
|
} finally {
|
|
872
830
|
removeLoadSpinner();
|
|
873
831
|
}
|
|
874
832
|
}
|
|
875
833
|
|
|
876
834
|
async function deleteOfflineDataClicked() {
|
|
877
|
-
const lastOfflineSession =
|
|
878
|
-
|
|
835
|
+
const lastOfflineSession =
|
|
836
|
+
await parent.saltcorn.mobileApp.offlineMode.getLastOfflineSession();
|
|
837
|
+
const { user } = parent.saltcorn.data.state.getState().mobileConfig;
|
|
879
838
|
if (!lastOfflineSession?.offlineUser) {
|
|
880
|
-
parent.showAlerts([
|
|
839
|
+
parent.saltcorn.mobileApp.common.showAlerts([
|
|
881
840
|
{
|
|
882
841
|
type: "error",
|
|
883
842
|
msg: "You don't have any offline data.",
|
|
884
843
|
},
|
|
885
844
|
]);
|
|
886
|
-
} else if (lastOfflineSession.offlineUser !==
|
|
887
|
-
parent.showAlerts([
|
|
845
|
+
} else if (lastOfflineSession.offlineUser !== user.email) {
|
|
846
|
+
parent.saltcorn.mobileApp.common.showAlerts([
|
|
888
847
|
{
|
|
889
848
|
type: "error",
|
|
890
849
|
msg: `The offline data is owned by '${lastOfflineSession.offlineUser}'.`,
|
|
@@ -895,30 +854,8 @@ async function deleteOfflineDataClicked() {
|
|
|
895
854
|
}
|
|
896
855
|
}
|
|
897
856
|
|
|
898
|
-
async function deleteOfflineData(noFeedback) {
|
|
899
|
-
const mobileConfig = parent.saltcorn.data.state.getState().mobileConfig;
|
|
900
|
-
try {
|
|
901
|
-
mobileConfig.inLoadState = true;
|
|
902
|
-
if (!noFeedback) showLoadSpinner();
|
|
903
|
-
await parent.offlineHelper.clearLocalData(false);
|
|
904
|
-
await parent.offlineHelper.setHasOfflineData(false);
|
|
905
|
-
if (!noFeedback)
|
|
906
|
-
parent.showAlerts([
|
|
907
|
-
{
|
|
908
|
-
type: "info",
|
|
909
|
-
msg: "Deleted your offline data.",
|
|
910
|
-
},
|
|
911
|
-
]);
|
|
912
|
-
} catch (error) {
|
|
913
|
-
parent.errorAlert(error);
|
|
914
|
-
} finally {
|
|
915
|
-
mobileConfig.inLoadState = false;
|
|
916
|
-
if (!noFeedback) removeLoadSpinner();
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
|
|
920
857
|
function showLoadSpinner() {
|
|
921
|
-
if (!parent.isHtmlFile()) {
|
|
858
|
+
if (!parent.saltcorn.mobileApp.navigation.isHtmlFile()) {
|
|
922
859
|
const spinner = $("#scspinner");
|
|
923
860
|
if (spinner.length === 0) {
|
|
924
861
|
$("body").append(`
|
|
@@ -961,7 +898,7 @@ function showLoadSpinner() {
|
|
|
961
898
|
}
|
|
962
899
|
|
|
963
900
|
function removeLoadSpinner() {
|
|
964
|
-
if (!parent.isHtmlFile()) {
|
|
901
|
+
if (!parent.saltcorn.mobileApp.navigation.isHtmlFile()) {
|
|
965
902
|
const spinner = $("#scspinner");
|
|
966
903
|
if (spinner.length > 0) {
|
|
967
904
|
const count = parseInt(spinner.attr("spinner-count")) - 1;
|
|
@@ -977,29 +914,11 @@ function removeLoadSpinner() {
|
|
|
977
914
|
* @param {*} fieldName
|
|
978
915
|
*/
|
|
979
916
|
async function getPicture(fieldName) {
|
|
980
|
-
const cameraOptions = {
|
|
981
|
-
quality: 50,
|
|
982
|
-
encodingType: parent.Camera.EncodingType.JPEG,
|
|
983
|
-
destinationType: parent.Camera.DestinationType.FILE_URI,
|
|
984
|
-
};
|
|
985
|
-
const getPictureWithPromise = () => {
|
|
986
|
-
return new Promise((resolve, reject) => {
|
|
987
|
-
parent.navigator.camera.getPicture(
|
|
988
|
-
(imageDate) => {
|
|
989
|
-
return resolve(imageDate);
|
|
990
|
-
},
|
|
991
|
-
(message) => {
|
|
992
|
-
return reject(message);
|
|
993
|
-
},
|
|
994
|
-
cameraOptions
|
|
995
|
-
);
|
|
996
|
-
});
|
|
997
|
-
};
|
|
998
917
|
try {
|
|
999
918
|
const form = $(`#cptbtn${fieldName}`).closest("form");
|
|
1000
919
|
const onsubmit = form.attr("onsubmit");
|
|
1001
920
|
form.attr("onsubmit", "javascript:void(0)");
|
|
1002
|
-
const fileURI = await
|
|
921
|
+
const fileURI = await parent.saltcorn.mobileApp.common.takePhoto("uri");
|
|
1003
922
|
form.attr("onsubmit", onsubmit);
|
|
1004
923
|
const inputId = `input${fieldName}`;
|
|
1005
924
|
form.find(`#${inputId}`).remove();
|
|
@@ -1009,7 +928,7 @@ async function getPicture(fieldName) {
|
|
|
1009
928
|
const tokens = fileURI.split("/");
|
|
1010
929
|
$(`#cpt-file-name-${fieldName}`).text(tokens[tokens.length - 1]);
|
|
1011
930
|
} catch (error) {
|
|
1012
|
-
parent.errorAlert(error);
|
|
931
|
+
parent.saltcorn.mobileApp.common.errorAlert(error);
|
|
1013
932
|
}
|
|
1014
933
|
}
|
|
1015
934
|
|
|
@@ -1024,7 +943,7 @@ async function updateMatchingRows(e, viewname) {
|
|
|
1024
943
|
true
|
|
1025
944
|
);
|
|
1026
945
|
} catch (error) {
|
|
1027
|
-
parent.errorAlert(error);
|
|
946
|
+
parent.saltcorn.mobileApp.common.errorAlert(error);
|
|
1028
947
|
}
|
|
1029
948
|
}
|
|
1030
949
|
|