@saltcorn/mobile-app 0.8.6-beta.4 → 0.8.6-beta.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@saltcorn/mobile-app",
3
3
  "displayName": "Saltcorn mobile app",
4
- "version": "0.8.6-beta.4",
4
+ "version": "0.8.6-beta.6",
5
5
  "description": "Apache Cordova application with @saltcorn/markup",
6
6
  "main": "index.js",
7
7
  "scripts": {
package/www/index.html CHANGED
@@ -18,6 +18,7 @@
18
18
  <script src="js/routes/auth.js"></script>
19
19
  <script src="js/routes/delete.js"></script>
20
20
  <script src="js/routes/edit.js"></script>
21
+ <script src="js/routes/api.js"></script>
21
22
  <script src="js/routes/error.js"></script>
22
23
  <script src="js/routes/page.js"></script>
23
24
  <script src="js/routes/view.js"></script>
@@ -180,7 +181,7 @@
180
181
  const onResume = async () => {
181
182
  const state = saltcorn.data.state.getState();
182
183
  const mobileConfig = state.mobileConfig;
183
- if (mobileConfig.allowOfflineMode) {
184
+ if (mobileConfig?.allowOfflineMode) {
184
185
  mobileConfig.networkState = navigator.connection.type;
185
186
  if (
186
187
  mobileConfig.networkState === "none" &&
@@ -0,0 +1,39 @@
1
+ /*global saltcorn, apiCall*/
2
+
3
+ // post/api/:tableName/:id
4
+ const updateTableRow = async (context) => {
5
+ const { tableName, id } = context.params;
6
+ const mobileConfig = saltcorn.data.state.getState().mobileConfig;
7
+ const user = {
8
+ id: mobileConfig.user_id,
9
+ role_id: mobileConfig.role_id || 100,
10
+ };
11
+ const table = saltcorn.data.models.Table.findOne({ name: tableName });
12
+ if (!table) throw new Error(`The table '${tableName}' does not exist.`);
13
+ if (
14
+ mobileConfig.isOfflineMode ||
15
+ mobileConfig.localTableIds.indexOf(table.id) >= 0
16
+ ) {
17
+ const row = {};
18
+ for (const [k, v] of new URLSearchParams(context.query).entries()) {
19
+ row[k] = v;
20
+ }
21
+ const errors = await saltcorn.data.web_mobile_commons.prepare_update_row(
22
+ table,
23
+ row,
24
+ id
25
+ );
26
+ if (errors.length > 0) throw new Error(errors.join(", "));
27
+ const ins_res = await table.tryUpdateRow(row, id, user);
28
+ if (ins_res.error)
29
+ throw new Error(`Update ${table.name} error: ${ins_res.error}`);
30
+ return { ins_res };
31
+ } else {
32
+ const response = await apiCall({
33
+ method: "POST",
34
+ path: `/api/${tableName}/${id}`,
35
+ body: context.query,
36
+ });
37
+ return response.data;
38
+ }
39
+ };
@@ -64,13 +64,13 @@ const getMenu = (req) => {
64
64
  const authItems = mobileCfg.isPublicUser
65
65
  ? [
66
66
  {
67
- link: "javascript:execLink('/auth/login')",
67
+ link: "javascript:execNavbarLink('/auth/login')",
68
68
  label: req.__("Login"),
69
69
  },
70
70
  ...(allowSignup
71
71
  ? [
72
72
  {
73
- link: "javascript:execLink('/auth/signup')",
73
+ link: "javascript:execNavbarLink('/auth/signup')",
74
74
  label: req.__("Sign up"),
75
75
  },
76
76
  ]
@@ -107,7 +107,7 @@ const getMenu = (req) => {
107
107
  section: "Network",
108
108
  items: [
109
109
  {
110
- link: "javascript:execLink('/sync/sync_settings')",
110
+ link: "javascript:execNavbarLink('/sync/sync_settings')",
111
111
  icon: "fas fa-sync",
112
112
  label: "Network",
113
113
  },
@@ -9,14 +9,11 @@ const deleteRows = async (context) => {
9
9
  if (isOfflineMode || localTableIds.indexOf(table.id) >= 0) {
10
10
  if (role_id <= table.min_role_write) {
11
11
  await table.deleteRows({ id });
12
- }
12
+ // TODO 'table.is_owner' check?
13
+ } else throw new Error(i18next.t("Not authorized"));
13
14
  if (isOfflineMode && !(await offlineHelper.hasOfflineRows())) {
14
15
  await offlineHelper.setOfflineSession(null);
15
16
  }
16
- // TODO 'table.is_owner' check?
17
- else {
18
- throw new Error(i18next.t("Not authorized"));
19
- }
20
17
  } else {
21
18
  await apiCall({ method: "POST", path: `/delete/${name}/${id}` });
22
19
  }
@@ -1,4 +1,4 @@
1
- /*global postView, postViewRoute, getView, postToggleField, deleteRows, postPageAction, getPage, getLoginView, logoutAction, getSignupView, getErrorView, window, getSyncSettingsView, getAskDeleteOfflineData, getAskUploadNotEnded */
1
+ /*global postView, postViewRoute, getView, postToggleField, deleteRows, postPageAction, getPage, getLoginView, logoutAction, getSignupView, getErrorView, window, getSyncSettingsView, getAskDeleteOfflineData, getAskUploadNotEnded, updateTableRow */
2
2
  // TODO module namespacese
3
3
 
4
4
  const initRoutes = async () => {
@@ -15,6 +15,10 @@ const initRoutes = async () => {
15
15
  path: "get/view/:viewname",
16
16
  action: getView,
17
17
  },
18
+ {
19
+ path: "post/api/:tableName/:id",
20
+ action: updateTableRow,
21
+ },
18
22
  {
19
23
  path: "post/edit/toggle/:name/:id/:field_name",
20
24
  action: postToggleField,
@@ -209,11 +209,17 @@ async function handleRoute(route, query, files) {
209
209
  : [],
210
210
  });
211
211
  if (page.redirect) {
212
- if (page.redirect.startsWith("http://localhost")) {
212
+ if (
213
+ page.redirect.startsWith("http://localhost") ||
214
+ page.redirect === "undefined"
215
+ ) {
213
216
  await gotoEntryView();
214
217
  } else {
215
218
  const { path, query } = splitPathQuery(page.redirect);
216
- await handleRoute(path, query);
219
+ await handleRoute(
220
+ path.startsWith("/") && path.length > 1 ? `get${path}` : path,
221
+ query
222
+ );
217
223
  }
218
224
  } else if (page.content) {
219
225
  if (!page.replaceIframe) await replaceIframeInnerContent(page.content);
@@ -1,5 +1,5 @@
1
1
  /*eslint-env browser*/
2
- /*global $, submitWithEmptyAction, is_paging_param, bootstrap, common_done, unique_field_from_rows*/
2
+ /*global $, submitWithEmptyAction, is_paging_param, bootstrap, common_done, unique_field_from_rows, inline_submit_success*/
3
3
 
4
4
  function combineFormAndQuery(form, query) {
5
5
  let paramsList = [];
@@ -24,6 +24,11 @@ async function execLink(url) {
24
24
  await parent.handleRoute(`get${path}`, query);
25
25
  }
26
26
 
27
+ async function execNavbarLink(url) {
28
+ $(".navbar-toggler").click();
29
+ execLink(url);
30
+ }
31
+
27
32
  /**
28
33
  *
29
34
  * @param {*} e
@@ -42,6 +47,31 @@ async function formSubmit(e, urlSuffix, viewname) {
42
47
  await parent.handleRoute(`post${urlSuffix}${viewname}`, queryStr, files);
43
48
  }
44
49
 
50
+ async function inline_local_submit(e, opts1) {
51
+ try {
52
+ e.preventDefault();
53
+ const opts = JSON.parse(decodeURIComponent(opts1 || "") || "{}");
54
+ const form = $(e.target).closest("form");
55
+ const urlParams = new URLSearchParams();
56
+ for (const entry of new FormData(form[0]).entries()) {
57
+ urlParams.append(entry[0], entry[1]);
58
+ }
59
+ const url = form.attr("action");
60
+ await parent.router.resolve({
61
+ pathname: `post${url}`,
62
+ query: urlParams.toString(),
63
+ });
64
+ inline_submit_success(e, form, opts);
65
+ } catch (error) {
66
+ parent.showAlerts([
67
+ {
68
+ type: "error",
69
+ msg: error.message ? error.message : "An error occured.",
70
+ },
71
+ ]);
72
+ }
73
+ }
74
+
45
75
  async function saveAndContinue(e, action, k) {
46
76
  const form = $(e).closest("form");
47
77
  submitWithEmptyAction(form[0]);
@@ -105,6 +135,12 @@ async function login(e, entryPoint, isSignup) {
105
135
  config.language = decodedJwt.user.language;
106
136
  config.isPublicUser = false;
107
137
  config.isOfflineMode = false;
138
+ await parent.insertUser({
139
+ id: config.user_id,
140
+ email: config.user_name,
141
+ role_id: config.role_id,
142
+ language: config.language,
143
+ });
108
144
  await parent.setJwt(loginResult);
109
145
  config.jwt = loginResult;
110
146
  await parent.i18next.changeLanguage(config.language);
@@ -114,3 +114,11 @@ async function setJwt(jwt) {
114
114
  await removeJwt();
115
115
  await saltcorn.data.db.insert(jwtTableName, { jwt: jwt });
116
116
  }
117
+
118
+ async function insertUser({ id, email, role_id, language }) {
119
+ await saltcorn.data.db.insert(
120
+ "users",
121
+ { id, email, role_id, language },
122
+ { ignoreExisting: true }
123
+ );
124
+ }