@saltcorn/mobile-app 0.7.2-beta.9 → 0.7.2

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.7.2-beta.9",
4
+ "version": "0.7.2",
5
5
  "description": "Apache Cordova application with @saltcorn/markup",
6
6
  "main": "index.js",
7
7
  "scripts": {
package/www/index.html CHANGED
@@ -7,68 +7,110 @@
7
7
  <script src="js/mocks/response.js"></script>
8
8
  <script src="js/mocks/request.js"></script>
9
9
  <script src="npm_packages/jwt-decode.js"></script>
10
- <script src="https://unpkg.com/universal-router/universal-router.min.js"></script>
11
- <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
10
+ <script src="npm_packages/universal-router.min.js"></script>
11
+ <script src="npm_packages/axios.min.js"></script>
12
12
  <script type="module">
13
13
  import { initRoutes } from "./js/routes/init.js";
14
14
  import { renderLoginForm } from "./js/utils/login_form.js";
15
15
  import {
16
- updateDbIfNecessary,
16
+ updateDb,
17
17
  getTableIds,
18
+ dbUpdateNeeded,
19
+ updateScPlugins,
18
20
  } from "./js/utils/table_utils.js";
19
21
  import { readJSON } from "./js/utils/file_helpers.js";
20
22
 
21
23
  const staticPlugins = ["base", "sbadmin2"];
22
24
 
23
- async function addScript(path) {
25
+ async function addScript(scriptObj) {
26
+ let waited = 0;
27
+ const maxWait = 3000;
28
+
29
+ const moduleAvailable = () =>
30
+ window.saltcorn && window.saltcorn[scriptObj.name];
31
+
24
32
  return new Promise((resolve, reject) => {
25
33
  let script = document.createElement("script");
26
34
  document.head.appendChild(script);
35
+
36
+ const waitForModule = () => {
37
+ waited += 100;
38
+ if (waited >= maxWait)
39
+ return reject(`unable to load '${scriptObj.name}'`);
40
+ console.log("waiting for " + scriptObj.name);
41
+ setTimeout(function () {
42
+ if (moduleAvailable()) return resolve();
43
+ else waitForModule();
44
+ }, 100);
45
+ };
46
+
27
47
  script.onload = () => {
28
- resolve();
48
+ if (!scriptObj.name || moduleAvailable()) return resolve();
49
+ waitForModule();
29
50
  };
30
- // TODO reject after some seconds
31
- script.src = path;
51
+ script.src = scriptObj.src;
32
52
  });
33
53
  }
34
54
 
35
55
  async function loadPlugin(plugin) {
36
- return addScript(`js/bundles/${plugin.name}.bundle.js`);
56
+ await addScript({
57
+ src: `js/bundles/${plugin.name}.bundle.js`,
58
+ name: plugin.name,
59
+ });
37
60
  }
38
61
 
39
62
  async function loadPlugins(state) {
40
- let plugins = (await saltcorn.data.models.Plugin.find()).filter(
63
+ const plugins = (await saltcorn.data.models.Plugin.find()).filter(
41
64
  (plugin) => !staticPlugins.includes(plugin.name)
42
65
  );
43
66
  for (const plugin of plugins) {
44
67
  await loadPlugin(plugin);
45
- state.registerPlugin(plugin.name, saltcorn[plugin.name]);
68
+ state.registerPlugin(
69
+ plugin.name,
70
+ saltcorn[plugin.name],
71
+ plugin.configuration
72
+ );
46
73
  }
47
74
  return plugins;
48
75
  }
49
76
 
50
77
  async function addScripts(version_tag) {
51
78
  const scripts = [
52
- `static_assets/${version_tag}/jquery-3.6.0.min.js`,
53
- "js/bundles/common_chunks.bundle.js",
54
- "js/bundles/markup.bundle.js",
55
- "js/bundles/data.bundle.js",
56
- "js/bundles/base_plugin.bundle.js",
57
- "js/bundles/sbadmin2.bundle.js",
79
+ { src: `static_assets/${version_tag}/jquery-3.6.0.min.js` },
80
+ { src: "js/bundles/common_chunks.bundle.js" },
81
+ { src: "js/bundles/markup.bundle.js", name: "markup" },
82
+ { src: "js/bundles/data.bundle.js", name: "data" },
83
+ { src: "js/bundles/base_plugin.bundle.js", name: "base_plugin" },
84
+ { src: "js/bundles/sbadmin2.bundle.js", name: "sbadmin2" },
58
85
  ];
59
86
  for (const script of scripts) {
60
87
  await addScript(script);
61
88
  }
62
89
  }
63
90
 
64
- const addPluginScriptTagsToCfg = (pluginRows) => {
91
+ /*
92
+ A plugin exports headers either as array, as key values object, or
93
+ as a function with a configuration parameter that returns an Array.
94
+ */
95
+ const collectPluginHeaders = (pluginRows) => {
65
96
  window.config.pluginHeaders = [];
66
97
  for (const row of pluginRows) {
67
98
  const pluginHeaders = saltcorn[row.name].headers;
68
99
  if (pluginHeaders) {
69
- for (const header of pluginHeaders) {
70
- window.config.pluginHeaders.push(header);
71
- }
100
+ if (Array.isArray(pluginHeaders))
101
+ for (const header of pluginHeaders) {
102
+ window.config.pluginHeaders.push(header);
103
+ }
104
+ else if (typeof pluginHeaders === "function") {
105
+ const headerResult = pluginHeaders(row.configuration);
106
+ if (Array.isArray(headerResult)) {
107
+ for (const header of headerResult)
108
+ window.config.pluginHeaders.push(header);
109
+ }
110
+ } else
111
+ for (const [key, value] of Object.entries(pluginHeaders)) {
112
+ window.config.pluginHeaders.push(value);
113
+ }
72
114
  }
73
115
  }
74
116
  };
@@ -83,13 +125,24 @@
83
125
  "config",
84
126
  `${cordova.file.applicationDirectory}www`
85
127
  );
128
+ const tablesJSON = await readJSON(
129
+ "tables.json",
130
+ `${cordova.file.applicationDirectory}${"www"}`
131
+ );
86
132
  await addScripts(config.version_tag);
87
133
  await saltcorn.data.db.init();
134
+ const updateNeeded = await dbUpdateNeeded(tablesJSON);
135
+ if (updateNeeded) {
136
+ // update '_sc_plugins' first because of loadPlugins()
137
+ await updateScPlugins(tablesJSON);
138
+ }
88
139
  const state = saltcorn.data.state.getState();
89
140
  state.registerPlugin("base", saltcorn.base_plugin);
90
141
  state.registerPlugin("sbadmin2", saltcorn.sbadmin2);
91
- addPluginScriptTagsToCfg(await loadPlugins(state));
92
- await updateDbIfNecessary();
142
+ collectPluginHeaders(await loadPlugins(state));
143
+ if (updateNeeded) {
144
+ await updateDb(tablesJSON);
145
+ }
93
146
  await state.refresh_tables();
94
147
  await state.refresh_views();
95
148
  await state.refresh_pages();
@@ -1,8 +1,11 @@
1
1
  import { fileExists, readJSON, writeJSON } from "./file_helpers.js";
2
2
 
3
- async function updateScTables(tablesJSON) {
3
+ const historyFile = "update_history";
4
+
5
+ async function updateScTables(tablesJSON, skipScPlugins = true) {
4
6
  saltcorn.data.db.query("PRAGMA foreign_keys = OFF;");
5
7
  for (const { table, rows } of tablesJSON.sc_tables) {
8
+ if (skipScPlugins && table === "_sc_plugins") continue;
6
9
  await saltcorn.data.db.deleteWhere(table);
7
10
  for (const row of rows) {
8
11
  await saltcorn.data.db.insert(table, row);
@@ -11,6 +14,16 @@ async function updateScTables(tablesJSON) {
11
14
  saltcorn.data.db.query("PRAGMA foreign_keys = ON;");
12
15
  }
13
16
 
17
+ export async function updateScPlugins(tablesJSON) {
18
+ const { table, rows } = tablesJSON.sc_tables.find(
19
+ ({ table }) => table === "_sc_plugins"
20
+ );
21
+ await saltcorn.data.db.deleteWhere(table);
22
+ for (const row of rows) {
23
+ await saltcorn.data.db.insert(table, row);
24
+ }
25
+ }
26
+
14
27
  async function handleUserDefinedTables() {
15
28
  const tables = await saltcorn.data.models.Table.find();
16
29
  const existingTables = await saltcorn.data.db.listUserDefinedTables();
@@ -35,23 +48,20 @@ async function tablesUptodate(tables, historyFile) {
35
48
  return tables.created_at.valueOf() < history.updated_at.valueOf();
36
49
  }
37
50
 
38
- export async function updateDbIfNecessary() {
39
- const historyFile = "update_history";
40
- const tablesJSON = await readJSON(
41
- "tables.json",
42
- `${cordova.file.applicationDirectory}${"www"}`
43
- );
44
- if (
51
+ export async function dbUpdateNeeded(tablesJSON) {
52
+ return (
45
53
  !(await fileExists(`${cordova.file.dataDirectory}${historyFile}`)) ||
46
54
  !(await tablesUptodate(tablesJSON, historyFile))
47
- ) {
48
- await updateScTables(tablesJSON);
49
- await saltcorn.data.state.getState().refresh_tables();
50
- await handleUserDefinedTables();
51
- await writeJSON(historyFile, cordova.file.dataDirectory, {
52
- updated_at: new Date(),
53
- });
54
- }
55
+ );
56
+ }
57
+
58
+ export async function updateDb(tablesJSON) {
59
+ await updateScTables(tablesJSON);
60
+ await saltcorn.data.state.getState().refresh_tables();
61
+ await handleUserDefinedTables();
62
+ await writeJSON(historyFile, cordova.file.dataDirectory, {
63
+ updated_at: new Date(),
64
+ });
55
65
  }
56
66
 
57
67
  export async function getTableIds(tableNames) {