@saltcorn/mobile-app 1.5.0-beta.14 → 1.5.0-beta.15
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/package.json +1 -1
- package/src/helpers/auth.js +2 -2
- package/src/helpers/offline_mode.js +45 -8
- package/src/init.js +3 -3
- package/www/js/iframe_view_utils.js +12 -13
package/package.json
CHANGED
package/src/helpers/auth.js
CHANGED
|
@@ -69,7 +69,7 @@ const initialSync = async (config) => {
|
|
|
69
69
|
const alerts = [];
|
|
70
70
|
const { offlineUser, hasOfflineData } = (await getLastOfflineSession()) || {};
|
|
71
71
|
if (!offlineUser || offlineUser === config.user.email) {
|
|
72
|
-
await sync();
|
|
72
|
+
await sync(false, alerts);
|
|
73
73
|
} else {
|
|
74
74
|
if (hasOfflineData)
|
|
75
75
|
alerts.push({
|
|
@@ -78,7 +78,7 @@ const initialSync = async (config) => {
|
|
|
78
78
|
});
|
|
79
79
|
else {
|
|
80
80
|
await deleteOfflineData(true);
|
|
81
|
-
await sync();
|
|
81
|
+
await sync(false, alerts);
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
return alerts;
|
|
@@ -318,6 +318,27 @@ const handleUniqueConflicts = async (uniqueConflicts, translatedIds) => {
|
|
|
318
318
|
}
|
|
319
319
|
};
|
|
320
320
|
|
|
321
|
+
const handleUpdateConflicts = async (dataConflicts, alerts) => {
|
|
322
|
+
let hasConflicts = false;
|
|
323
|
+
for (const [tblName, updates] of Object.entries(dataConflicts)) {
|
|
324
|
+
const table = saltcorn.data.models.Table.findOne({ name: tblName });
|
|
325
|
+
const pkName = table.pk_name || "id";
|
|
326
|
+
for (const update of updates) {
|
|
327
|
+
const { [pkName]: _sc_pkValue, ...rest } = update;
|
|
328
|
+
await table.updateRow(rest, _sc_pkValue);
|
|
329
|
+
hasConflicts = true;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
if (hasConflicts) {
|
|
333
|
+
alerts.push({
|
|
334
|
+
type: "info",
|
|
335
|
+
msg:
|
|
336
|
+
"Some of your changes could not be applied because the data has changed on the server. " +
|
|
337
|
+
"Your local data has been updated accordingly.",
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
|
|
321
342
|
const updateSyncInfos = async (
|
|
322
343
|
offlineChanges,
|
|
323
344
|
allTranslations,
|
|
@@ -357,7 +378,7 @@ const updateSyncInfos = async (
|
|
|
357
378
|
}
|
|
358
379
|
};
|
|
359
380
|
|
|
360
|
-
const syncOfflineData = async (synchedTables, syncTimestamp) => {
|
|
381
|
+
const syncOfflineData = async (synchedTables, syncTimestamp, alerts) => {
|
|
361
382
|
const offlineChanges = await loadOfflineChanges(synchedTables);
|
|
362
383
|
if (Object.keys(offlineChanges).length === 0) return null;
|
|
363
384
|
const uploadResp = await apiCall({
|
|
@@ -365,7 +386,8 @@ const syncOfflineData = async (synchedTables, syncTimestamp) => {
|
|
|
365
386
|
path: "/sync/offline_changes",
|
|
366
387
|
body: {
|
|
367
388
|
changes: offlineChanges,
|
|
368
|
-
|
|
389
|
+
oldSyncTimestamp: await getLocalSyncTimestamp(),
|
|
390
|
+
newSyncTimestamp: syncTimestamp,
|
|
369
391
|
},
|
|
370
392
|
});
|
|
371
393
|
const { syncDir } = uploadResp.data;
|
|
@@ -377,10 +399,12 @@ const syncOfflineData = async (synchedTables, syncTimestamp) => {
|
|
|
377
399
|
path: `/sync/upload_finished?dir_name=${encodeURIComponent(syncDir)}`,
|
|
378
400
|
});
|
|
379
401
|
pollCount++;
|
|
380
|
-
const { finished, translatedIds, uniqueConflicts, error } =
|
|
402
|
+
const { finished, translatedIds, uniqueConflicts, dataConflicts, error } =
|
|
403
|
+
pollResp.data;
|
|
381
404
|
if (finished) {
|
|
382
405
|
if (error) throw new Error(error.message);
|
|
383
406
|
else {
|
|
407
|
+
await handleUpdateConflicts(dataConflicts, alerts);
|
|
384
408
|
await handleUniqueConflicts(uniqueConflicts, translatedIds);
|
|
385
409
|
await handleTranslatedIds(uniqueConflicts, translatedIds);
|
|
386
410
|
await updateSyncInfos(offlineChanges, translatedIds, syncTimestamp);
|
|
@@ -425,7 +449,7 @@ const checkCleanSync = async (uploadStarted, uploadStartTime, userName) => {
|
|
|
425
449
|
return false;
|
|
426
450
|
};
|
|
427
451
|
|
|
428
|
-
const
|
|
452
|
+
const getServerTime = async () => {
|
|
429
453
|
const resp = await apiCall({
|
|
430
454
|
method: "GET",
|
|
431
455
|
path: `/sync/sync_timestamp`,
|
|
@@ -433,6 +457,16 @@ const getSyncTimestamp = async () => {
|
|
|
433
457
|
return resp.data.syncTimestamp;
|
|
434
458
|
};
|
|
435
459
|
|
|
460
|
+
const setLocalSyncTimestamp = async (syncTimestamp) => {
|
|
461
|
+
const state = saltcorn.data.state.getState();
|
|
462
|
+
await state.setConfig("mobile_sync_timestamp", syncTimestamp);
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
const getLocalSyncTimestamp = async () => {
|
|
466
|
+
const state = saltcorn.data.state.getState();
|
|
467
|
+
return await state.getConfig("mobile_sync_timestamp");
|
|
468
|
+
};
|
|
469
|
+
|
|
436
470
|
const setSpinnerText = () => {
|
|
437
471
|
const iframeWindow = $("#content-iframe")[0].contentWindow;
|
|
438
472
|
if (iframeWindow) {
|
|
@@ -451,7 +485,7 @@ export async function isSyncInProgress() {
|
|
|
451
485
|
return syncInProgress;
|
|
452
486
|
}
|
|
453
487
|
|
|
454
|
-
export async function sync(background = false) {
|
|
488
|
+
export async function sync(background = false, alerts = []) {
|
|
455
489
|
if (syncInProgress)
|
|
456
490
|
throw new Error("A synchronization is already in progress.");
|
|
457
491
|
|
|
@@ -472,7 +506,7 @@ export async function sync(background = false) {
|
|
|
472
506
|
uploadStartTime,
|
|
473
507
|
user.email
|
|
474
508
|
);
|
|
475
|
-
const syncTimestamp = await
|
|
509
|
+
const syncTimestamp = await getServerTime();
|
|
476
510
|
await setUploadStarted(true, syncTimestamp);
|
|
477
511
|
let lock = null;
|
|
478
512
|
if (!background) {
|
|
@@ -492,8 +526,9 @@ export async function sync(background = false) {
|
|
|
492
526
|
if (cleanSync) await clearLocalData(true);
|
|
493
527
|
const { synchedTables, syncInfos } = await prepare();
|
|
494
528
|
await syncRemoteDeletes(syncInfos, syncTimestamp);
|
|
495
|
-
syncDir = await syncOfflineData(synchedTables, syncTimestamp);
|
|
529
|
+
syncDir = await syncOfflineData(synchedTables, syncTimestamp, alerts);
|
|
496
530
|
await syncRemoteData(syncInfos, syncTimestamp);
|
|
531
|
+
await setLocalSyncTimestamp(syncTimestamp);
|
|
497
532
|
if (!background) await endOfflineMode(true);
|
|
498
533
|
await setUploadStarted(false);
|
|
499
534
|
await saltcorn.data.db.query("COMMIT");
|
|
@@ -663,8 +698,10 @@ export function addPushSyncHandler() {
|
|
|
663
698
|
const state = saltcorn.data.state.getState();
|
|
664
699
|
state.mobile_push_handler["push_sync"] = async (notification) => {
|
|
665
700
|
console.log("Push sync received:", notification);
|
|
701
|
+
const alerts = [];
|
|
666
702
|
try {
|
|
667
|
-
await sync(true);
|
|
703
|
+
await sync(true, alerts);
|
|
704
|
+
if (alerts.length > 0) showAlerts(alerts);
|
|
668
705
|
} catch (error) {
|
|
669
706
|
console.log("Error during push sync:", error);
|
|
670
707
|
}
|
package/src/init.js
CHANGED
|
@@ -472,7 +472,7 @@ export async function init(mobileConfig) {
|
|
|
472
472
|
}
|
|
473
473
|
} else if (offlineUser) {
|
|
474
474
|
if (offlineUser === mobileConfig.user.email) {
|
|
475
|
-
await sync();
|
|
475
|
+
await sync(false, alerts);
|
|
476
476
|
alerts.push({
|
|
477
477
|
type: "info",
|
|
478
478
|
msg: "Synchronized your offline data.",
|
|
@@ -483,7 +483,7 @@ export async function init(mobileConfig) {
|
|
|
483
483
|
msg: `'${offlineUser}' has not yet uploaded offline data.`,
|
|
484
484
|
});
|
|
485
485
|
} else {
|
|
486
|
-
await sync();
|
|
486
|
+
await sync(false, alerts);
|
|
487
487
|
alerts.push({
|
|
488
488
|
type: "info",
|
|
489
489
|
msg: "Synchronized your offline data.",
|
|
@@ -555,7 +555,7 @@ export async function init(mobileConfig) {
|
|
|
555
555
|
"Please go online and reload, the public login is not yet supported."
|
|
556
556
|
);
|
|
557
557
|
await publicLogin(getEntryPoint(100, state, state.mobileConfig));
|
|
558
|
-
|
|
558
|
+
} else {
|
|
559
559
|
// open login page
|
|
560
560
|
await showLogin(alerts);
|
|
561
561
|
}
|
|
@@ -892,15 +892,15 @@ async function callSync() {
|
|
|
892
892
|
} else {
|
|
893
893
|
const wasOffline = mobileConfig.isOfflineMode;
|
|
894
894
|
showLoadSpinner();
|
|
895
|
-
|
|
895
|
+
const alerts = [];
|
|
896
|
+
await parent.saltcorn.mobileApp.offlineMode.sync(false, alerts);
|
|
896
897
|
parent.saltcorn.mobileApp.common.clearAlerts();
|
|
897
898
|
if (!wasOffline) {
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
]);
|
|
899
|
+
alerts.push({
|
|
900
|
+
type: "info",
|
|
901
|
+
msg: "Synchronized your offline data.",
|
|
902
|
+
});
|
|
903
|
+
parent.saltcorn.mobileApp.common.showAlerts(alerts);
|
|
904
904
|
} else {
|
|
905
905
|
setNetworSwitcherOn();
|
|
906
906
|
parent.saltcorn.mobileApp.navigation.clearHistory();
|
|
@@ -908,12 +908,11 @@ async function callSync() {
|
|
|
908
908
|
parent.saltcorn.mobileApp.navigation.addRoute({
|
|
909
909
|
route: "get/sync/sync_settings",
|
|
910
910
|
});
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
]);
|
|
911
|
+
alerts.push({
|
|
912
|
+
type: "info",
|
|
913
|
+
msg: "Synchronized your offline data, you are online again.",
|
|
914
|
+
});
|
|
915
|
+
parent.saltcorn.mobileApp.common.showAlerts(alerts);
|
|
917
916
|
parent.saltcorn.mobileApp.common.clearTopAlerts();
|
|
918
917
|
}
|
|
919
918
|
}
|