@saltcorn/mobile-app 1.3.1-beta.9 → 1.4.0-beta.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@saltcorn/mobile-app",
3
3
  "displayName": "Saltcorn mobile app",
4
- "version": "1.3.1-beta.9",
4
+ "version": "1.4.0-beta.0",
5
5
  "description": "Saltcorn mobile app for Android and iOS",
6
6
  "main": "index.js",
7
7
  "scripts": {
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "universal-router": "9.2.1",
21
- "axios": "^1.7.7",
21
+ "axios": "^0.29.0",
22
22
  "jwt-decode": "4.0.0",
23
23
  "i18next": "24.2.2",
24
24
  "i18next-sprintf-postprocessor": "0.2.2",
@@ -19,27 +19,27 @@ async function loginRequest({ email, password, isSignup, isPublic }) {
19
19
  path: "/auth/login-with/jwt",
20
20
  }
21
21
  : isSignup
22
- ? {
23
- method: "POST",
24
- path: "/auth/signup",
25
- body: {
26
- email,
27
- password,
28
- },
29
- }
30
- : {
31
- method: "GET",
32
- path: "/auth/login-with/jwt",
33
- params: {
34
- email,
35
- password,
36
- },
37
- };
22
+ ? {
23
+ method: "POST",
24
+ path: "/auth/signup",
25
+ body: {
26
+ email,
27
+ password,
28
+ },
29
+ }
30
+ : {
31
+ method: "GET",
32
+ path: "/auth/login-with/jwt",
33
+ params: {
34
+ email,
35
+ password,
36
+ },
37
+ };
38
38
  const response = await apiCall(opts);
39
39
  return response.data;
40
40
  }
41
41
 
42
- export async function login({ email, password, entryPoint, isSignup }) {
42
+ export async function login({ email, password, isSignup }) {
43
43
  const loginResult = await loginRequest({
44
44
  email,
45
45
  password,
@@ -48,7 +48,8 @@ export async function login({ email, password, entryPoint, isSignup }) {
48
48
  if (typeof loginResult === "string") {
49
49
  // use it as a token
50
50
  const decodedJwt = jwtDecode(loginResult);
51
- const config = saltcorn.data.state.getState().mobileConfig;
51
+ const state = saltcorn.data.state.getState();
52
+ const config = state.mobileConfig;
52
53
  config.user = decodedJwt.user;
53
54
  config.isPublicUser = false;
54
55
  config.isOfflineMode = false;
@@ -86,6 +87,16 @@ export async function login({ email, password, entryPoint, isSignup }) {
86
87
  sprintf: [config.user.email],
87
88
  }),
88
89
  });
90
+
91
+ let entryPoint = null;
92
+ if (config.entryPointType === "byrole") {
93
+ const homepageByRole = state.getConfig("home_page_by_role", {})[
94
+ config.user.role_id
95
+ ];
96
+ if (homepageByRole) entryPoint = `get/page/${homepageByRole}`;
97
+ else throw new Error("No homepage defined for this role.");
98
+ } else entryPoint = config.entry_point;
99
+
89
100
  addRoute({ route: entryPoint, query: undefined });
90
101
  const page = await router.resolve({
91
102
  pathname: entryPoint,
@@ -224,8 +224,8 @@ const loadOfflineChanges = async (synchedTbls) => {
224
224
  from "${saltcorn.data.db.sqlsanitize(
225
225
  synchedTbl
226
226
  )}_sync_info" as info_tbl left join "${saltcorn.data.db.sqlsanitize(
227
- synchedTbl
228
- )}" as data_tbl
227
+ synchedTbl
228
+ )}" as data_tbl
229
229
  on info_tbl.ref = data_tbl."${saltcorn.data.db.sqlsanitize(pkName)}"
230
230
  where info_tbl.modified_local = true`
231
231
  );
@@ -562,7 +562,7 @@ export async function clearLocalData(inTransaction) {
562
562
  const { synchedTables } = saltcorn.data.state.getState().mobileConfig;
563
563
  for (const tblName of synchedTables) {
564
564
  const table = saltcorn.data.models.Table.findOne({ name: tblName });
565
- await table.deleteRows();
565
+ await table.deleteRows({});
566
566
  await saltcorn.data.db.deleteWhere(`${table.name}_sync_info`, {});
567
567
  }
568
568
  if (!inTransaction) await saltcorn.data.db.query("COMMIT");
package/src/init.js CHANGED
@@ -30,6 +30,7 @@ import i18nextSprintfPostProcessor from "i18next-sprintf-postprocessor";
30
30
  import { jwtDecode } from "jwt-decode";
31
31
 
32
32
  import { Network } from "@capacitor/network";
33
+ import { App } from "@capacitor/app";
33
34
 
34
35
  import { defineCustomElements } from "jeep-sqlite/loader";
35
36
 
@@ -59,7 +60,7 @@ async function addScript(scriptObj) {
59
60
  if (!scriptObj.name || moduleAvailable()) return resolve();
60
61
  waitForModule();
61
62
  };
62
- script.src = scriptObj.src;
63
+ script.src = scriptObj.src || scriptObj.script;
63
64
  });
64
65
  }
65
66
 
@@ -117,27 +118,33 @@ const prepareHeader = (header) => {
117
118
  /*
118
119
  A plugin exports headers either as array, as key values object, or
119
120
  as a function with a configuration parameter that returns an Array.
121
+
122
+ If mobile_top_scope is set, the script is added to the index.html <head>
123
+ otherwise it will be added to the iframe headers
120
124
  */
121
- const collectPluginHeaders = (pluginRows) => {
125
+ const handlePluginHeaders = async (plugins) => {
122
126
  const config = saltcorn.data.state.getState().mobileConfig;
123
127
  config.pluginHeaders = [];
124
- for (const row of pluginRows) {
125
- const pluginHeaders = saltcorn[row.name].headers;
128
+
129
+ const handler = async (header) => {
130
+ if (header.mobile_top_scope) await addScript(prepareHeader(header));
131
+ else config.pluginHeaders.push(prepareHeader(header));
132
+ };
133
+
134
+ for (const plugin of plugins) {
135
+ const pluginHeaders = saltcorn[plugin.name].headers;
126
136
  if (pluginHeaders) {
127
- if (Array.isArray(pluginHeaders))
128
- for (const header of pluginHeaders) {
129
- config.pluginHeaders.push(prepareHeader(header));
130
- }
131
- else if (typeof pluginHeaders === "function") {
132
- const headerResult = pluginHeaders(row.configuration || {});
137
+ if (Array.isArray(pluginHeaders)) {
138
+ for (const header of pluginHeaders) await handler(header);
139
+ } else if (typeof pluginHeaders === "function") {
140
+ const headerResult = pluginHeaders(plugin.configuration || {});
133
141
  if (Array.isArray(headerResult)) {
134
- for (const header of headerResult)
135
- config.pluginHeaders.push(prepareHeader(header));
136
- }
137
- } else
138
- for (const value of Object.values(pluginHeaders)) {
139
- config.pluginHeaders.push(prepareHeader(value));
142
+ for (const header of headerResult) await handler(header);
140
143
  }
144
+ } else {
145
+ for (const header of Object.values(pluginHeaders))
146
+ await handler(header);
147
+ }
141
148
  }
142
149
  }
143
150
  };
@@ -357,6 +364,11 @@ export async function init(mobileConfig) {
357
364
  document.body.appendChild(jeepSqlite);
358
365
  await jeepSqlite.componentOnReady();
359
366
  }
367
+
368
+ App.addListener("backButton", async ({ canGoBack }) => {
369
+ await saltcorn.mobileApp.navigation.goBack(1, true);
370
+ });
371
+
360
372
  const lastLocation = takeLastLocation();
361
373
  document.addEventListener("resume", onResume, false);
362
374
  await addScripts(mobileConfig.version_tag);
@@ -373,7 +385,7 @@ export async function init(mobileConfig) {
373
385
  state.mobileConfig.user = {};
374
386
  state.registerPlugin("base", saltcorn.base_plugin);
375
387
  state.registerPlugin("sbadmin2", saltcorn.sbadmin2);
376
- collectPluginHeaders(await loadPlugins(state));
388
+ await handlePluginHeaders(await loadPlugins(state));
377
389
  if (updateNeeded) {
378
390
  await updateDb(tablesJSON);
379
391
  }
@@ -148,7 +148,6 @@ export const getView = async (context) => {
148
148
  const { viewname } = context.params;
149
149
  const view = saltcorn.data.models.View.findOne({ name: viewname });
150
150
  if (!view) throw new Error(req.__("No such view: %s", viewname));
151
- const res = new MobileResponse();
152
151
  if (
153
152
  state.mobileConfig.user.role_id > view.min_role &&
154
153
  !(await view.authorise_get({ query, req, ...view }))
@@ -158,45 +157,53 @@ export const getView = async (context) => {
158
157
  req.__("Not authorized") + additionalInfos
159
158
  );
160
159
  }
161
- state.queriesCache = {};
162
160
  let contents0 = null;
163
- try {
164
- contents0 = await view.run_possibly_on_page(
165
- query,
166
- req,
167
- res,
168
- view.isRemoteTable()
169
- );
170
- } finally {
171
- state.queriesCache = null;
161
+ if (!view.renderLocally()) {
162
+ const response = await apiCall({
163
+ method: "GET",
164
+ path: `/view/${encodeURIComponent(viewname)}${context.query ? `?${context.query}` : ""}`,
165
+ });
166
+ const data = response.data;
167
+ contents0 = data;
168
+ } else {
169
+ const res = new MobileResponse();
170
+ state.queriesCache = {};
171
+ try {
172
+ contents0 = await view.run_possibly_on_page(
173
+ query,
174
+ req,
175
+ res,
176
+ view.isRemoteTable()
177
+ );
178
+ } finally {
179
+ state.queriesCache = null;
180
+ }
181
+ const wrapped = res.getWrapHtml();
182
+ if (wrapped)
183
+ return await wrapContents(
184
+ wrapped,
185
+ res.getWrapViewName() || "viewname",
186
+ context,
187
+ req
188
+ );
172
189
  }
173
- const wrapped = res.getWrapHtml();
174
- if (wrapped)
175
- return await wrapContents(
176
- wrapped,
177
- res.getWrapViewName() || "viewname",
178
- context,
179
- req
180
- );
181
- else {
182
- const contents =
183
- typeof contents0 === "string"
184
- ? saltcorn.markup.div(
185
- {
186
- class: "d-inline",
187
- "data-sc-embed-viewname": view.name,
188
- "data-sc-view-source": `/view/${context.params.viewname}${
189
- context.query
190
- ? context.query.startsWith("?")
191
- ? context.query
192
- : `?${context.query}`
193
- : ""
194
- }`,
195
- },
196
- contents0
197
- )
198
- : contents0;
190
+ const contents =
191
+ typeof contents0 === "string"
192
+ ? saltcorn.markup.div(
193
+ {
194
+ class: "d-inline",
195
+ "data-sc-embed-viewname": view.name,
196
+ "data-sc-view-source": `/view/${context.params.viewname}${
197
+ context.query
198
+ ? context.query.startsWith("?")
199
+ ? context.query
200
+ : `?${context.query}`
201
+ : ""
202
+ }`,
203
+ },
204
+ contents0
205
+ )
206
+ : contents0;
199
207
 
200
- return await wrapContents(contents, viewname, context, req);
201
- }
208
+ return await wrapContents(contents, viewname, context, req);
202
209
  };
package/www/index.html CHANGED
@@ -20,9 +20,6 @@
20
20
  document.addEventListener("deviceready", () => {
21
21
  saltcorn.mobileApp.init(_sc_mobile_config);
22
22
  });
23
- document.addEventListener("backbutton", async () => {
24
- await saltcorn.mobileApp.navigation.goBack(1, true);
25
- });
26
23
  } else {
27
24
  saltcorn.mobileApp.init(_sc_mobile_config);
28
25
  }