@saltcorn/server 1.1.4-beta.1 → 1.1.4-beta.10

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.
Files changed (409) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/auth/resetpw.js +1 -1
  3. package/auth/roleadmin.js +1 -4
  4. package/auth/routes.js +33 -1
  5. package/docs/assets/search.js +1 -1
  6. package/docs/classes/_saltcorn_common_code.Relation.html +8 -8
  7. package/docs/classes/_saltcorn_common_code.RelationsFinder.html +5 -5
  8. package/docs/classes/_saltcorn_data.models.Crash-1.html +18 -18
  9. package/docs/classes/_saltcorn_data.models.EventLog-1.html +19 -19
  10. package/docs/classes/_saltcorn_data.models.Field.html +71 -71
  11. package/docs/classes/_saltcorn_data.models.FieldRepeat-1.html +17 -17
  12. package/docs/classes/_saltcorn_data.models.File-1.html +48 -48
  13. package/docs/classes/_saltcorn_data.models.Form-1.html +38 -38
  14. package/docs/classes/_saltcorn_data.models.Library.html +13 -13
  15. package/docs/classes/_saltcorn_data.models.Page.html +24 -24
  16. package/docs/classes/_saltcorn_data.models.PageGroup-1.html +25 -25
  17. package/docs/classes/_saltcorn_data.models.Plugin.html +25 -25
  18. package/docs/classes/_saltcorn_data.models.Role.html +9 -9
  19. package/docs/classes/_saltcorn_data.models.Table-1.html +107 -92
  20. package/docs/classes/_saltcorn_data.models.TableConstraint-1.html +14 -14
  21. package/docs/classes/_saltcorn_data.models.Trigger.html +36 -36
  22. package/docs/classes/_saltcorn_data.models.User-1.html +50 -50
  23. package/docs/classes/_saltcorn_data.models.View-1.html +52 -52
  24. package/docs/classes/_saltcorn_data.models.Workflow-1.html +17 -17
  25. package/docs/classes/_saltcorn_data.models.WorkflowRun.html +35 -35
  26. package/docs/classes/_saltcorn_data.models.WorkflowStep.html +25 -25
  27. package/docs/classes/_saltcorn_data.models.WorkflowTrace.html +18 -18
  28. package/docs/classes/_saltcorn_mobile_builder.MobileBuilder.html +36 -36
  29. package/docs/enums/_saltcorn_common_code.RelationType.html +7 -7
  30. package/docs/enums/_saltcorn_common_code.ViewDisplayType.html +4 -4
  31. package/docs/functions/_saltcorn_admin_models.backup.create_backup.html +1 -1
  32. package/docs/functions/_saltcorn_admin_models.backup.create_csv_from_rows.html +1 -1
  33. package/docs/functions/_saltcorn_admin_models.backup.restore.html +1 -1
  34. package/docs/functions/_saltcorn_admin_models.pack.add_to_menu.html +1 -1
  35. package/docs/functions/_saltcorn_admin_models.pack.can_install_pack.html +1 -1
  36. package/docs/functions/_saltcorn_admin_models.pack.fetch_available_packs.html +1 -1
  37. package/docs/functions/_saltcorn_admin_models.pack.fetch_pack_by_name.html +1 -1
  38. package/docs/functions/_saltcorn_admin_models.pack.install_pack.html +1 -1
  39. package/docs/functions/_saltcorn_admin_models.pack.library_pack.html +1 -1
  40. package/docs/functions/_saltcorn_admin_models.pack.model_instance_pack.html +1 -1
  41. package/docs/functions/_saltcorn_admin_models.pack.model_pack.html +1 -1
  42. package/docs/functions/_saltcorn_admin_models.pack.page_group_pack.html +1 -1
  43. package/docs/functions/_saltcorn_admin_models.pack.page_pack.html +1 -1
  44. package/docs/functions/_saltcorn_admin_models.pack.plugin_pack.html +1 -1
  45. package/docs/functions/_saltcorn_admin_models.pack.role_pack.html +1 -1
  46. package/docs/functions/_saltcorn_admin_models.pack.table_pack.html +1 -1
  47. package/docs/functions/_saltcorn_admin_models.pack.trigger_pack.html +1 -1
  48. package/docs/functions/_saltcorn_admin_models.pack.uninstall_pack.html +1 -1
  49. package/docs/functions/_saltcorn_admin_models.pack.view_pack.html +1 -1
  50. package/docs/functions/_saltcorn_admin_models.tenant.copy_tenant_template.html +1 -1
  51. package/docs/functions/_saltcorn_admin_models.tenant.create_tenant.html +1 -1
  52. package/docs/functions/_saltcorn_admin_models.tenant.deleteTenant.html +1 -1
  53. package/docs/functions/_saltcorn_admin_models.tenant.domain_sanitize.html +1 -1
  54. package/docs/functions/_saltcorn_admin_models.tenant.eachTenant.html +1 -1
  55. package/docs/functions/_saltcorn_admin_models.tenant.getAllTenantRows.html +1 -1
  56. package/docs/functions/_saltcorn_admin_models.tenant.getAllTenants.html +1 -1
  57. package/docs/functions/_saltcorn_admin_models.tenant.insertTenant.html +1 -1
  58. package/docs/functions/_saltcorn_admin_models.tenant.switchToTenant.html +1 -1
  59. package/docs/functions/_saltcorn_common_code.buildTableCaches.html +1 -1
  60. package/docs/functions/_saltcorn_common_code.parseLegacyRelation.html +1 -1
  61. package/docs/functions/_saltcorn_common_code.parseRelationPath.html +1 -1
  62. package/docs/functions/_saltcorn_data.models.config.check_email_mask.html +1 -1
  63. package/docs/functions/_saltcorn_data.models.config.deleteConfig.html +1 -1
  64. package/docs/functions/_saltcorn_data.models.config.getAllConfig.html +1 -1
  65. package/docs/functions/_saltcorn_data.models.config.getConfig.html +1 -1
  66. package/docs/functions/_saltcorn_data.models.config.get_base_url.html +1 -1
  67. package/docs/functions/_saltcorn_data.models.config.get_latest_npm_version.html +1 -1
  68. package/docs/functions/_saltcorn_data.models.config.remove_from_menu.html +1 -1
  69. package/docs/functions/_saltcorn_data.models.config.save_menu_items.html +1 -1
  70. package/docs/functions/_saltcorn_data.models.config.setConfig.html +1 -1
  71. package/docs/functions/_saltcorn_data.models.discovery.discover_tables.html +1 -1
  72. package/docs/functions/_saltcorn_data.models.discovery.discoverable_tables.html +1 -1
  73. package/docs/functions/_saltcorn_data.models.discovery.findType.html +3 -3
  74. package/docs/functions/_saltcorn_data.models.discovery.get_existing_views.html +1 -1
  75. package/docs/functions/_saltcorn_data.models.discovery.implement_discovery.html +1 -1
  76. package/docs/functions/_saltcorn_data.models.email.getMailTransport.html +3 -3
  77. package/docs/functions/_saltcorn_data.models.email.send_verification_email.html +1 -1
  78. package/docs/functions/_saltcorn_data.models.email.viewToEmailHtml.html +1 -1
  79. package/docs/functions/_saltcorn_data.models.expression.apply_calculated_fields.html +1 -1
  80. package/docs/functions/_saltcorn_data.models.expression.apply_calculated_fields_stored.html +1 -1
  81. package/docs/functions/_saltcorn_data.models.expression.eval_expression.html +1 -1
  82. package/docs/functions/_saltcorn_data.models.expression.expressionValidator.html +1 -1
  83. package/docs/functions/_saltcorn_data.models.expression.get_async_expression_function.html +1 -1
  84. package/docs/functions/_saltcorn_data.models.expression.get_expression_function.html +1 -1
  85. package/docs/functions/_saltcorn_data.models.expression.jsexprToWhere.html +1 -1
  86. package/docs/functions/_saltcorn_data.models.expression.recalculate_for_stored.html +1 -1
  87. package/docs/functions/_saltcorn_data.models.expression.transform_for_async.html +1 -1
  88. package/docs/functions/_saltcorn_data.models.layout.eachView.html +1 -1
  89. package/docs/functions/_saltcorn_data.models.layout.getStringsForI18n.html +1 -1
  90. package/docs/functions/_saltcorn_data.models.layout.getViews.html +1 -1
  91. package/docs/functions/_saltcorn_data.models.layout.translateLayout.html +1 -1
  92. package/docs/functions/_saltcorn_data.models.layout.traverse.html +1 -1
  93. package/docs/functions/_saltcorn_data.models.layout.traverseSync.html +1 -1
  94. package/docs/functions/_saltcorn_data.models.random.all_views.html +1 -1
  95. package/docs/functions/_saltcorn_data.models.random.fill_table_row.html +1 -1
  96. package/docs/functions/_saltcorn_data.models.random.initial_view.html +1 -1
  97. package/docs/functions/_saltcorn_data.models.random.random_table.html +1 -1
  98. package/docs/functions/_saltcorn_db_common.buildInsertBulkSql.html +1 -1
  99. package/docs/functions/_saltcorn_db_common.buildInsertSql.html +1 -1
  100. package/docs/functions/_saltcorn_db_common.doCount.html +1 -1
  101. package/docs/functions/_saltcorn_db_common.doDeleteWhere.html +1 -1
  102. package/docs/functions/_saltcorn_db_common.doListScTables.html +1 -1
  103. package/docs/functions/_saltcorn_db_common.doListTables.html +1 -1
  104. package/docs/functions/_saltcorn_db_common.doListUserDefinedTables.html +1 -1
  105. package/docs/functions/_saltcorn_db_common.do_add_index.html +1 -1
  106. package/docs/functions/_saltcorn_db_common.do_drop_index.html +1 -1
  107. package/docs/functions/_saltcorn_db_common.ftsFieldsSqlExpr.html +1 -1
  108. package/docs/functions/_saltcorn_db_common.mkSelectOptions.html +1 -1
  109. package/docs/functions/_saltcorn_db_common.mkVal.html +1 -1
  110. package/docs/functions/_saltcorn_db_common.mkWhere.html +1 -1
  111. package/docs/functions/_saltcorn_db_common.multi_tenant.enable_multi_tenant.html +1 -1
  112. package/docs/functions/_saltcorn_db_common.multi_tenant.getRequestContext.html +1 -1
  113. package/docs/functions/_saltcorn_db_common.multi_tenant.getTenantSchema.html +1 -1
  114. package/docs/functions/_saltcorn_db_common.multi_tenant.init.html +1 -1
  115. package/docs/functions/_saltcorn_db_common.multi_tenant.is_it_multi_tenant.html +1 -1
  116. package/docs/functions/_saltcorn_db_common.multi_tenant.runWithTenant.html +1 -1
  117. package/docs/functions/_saltcorn_db_common.orderByIsObject.html +1 -1
  118. package/docs/functions/_saltcorn_db_common.orderByIsOperator.html +1 -1
  119. package/docs/functions/_saltcorn_db_common.prefixFieldsInWhere.html +1 -1
  120. package/docs/functions/_saltcorn_db_common.reprAsJson.html +1 -1
  121. package/docs/functions/_saltcorn_db_common.sqlBinOp.html +1 -1
  122. package/docs/functions/_saltcorn_db_common.sqlFun.html +1 -1
  123. package/docs/functions/_saltcorn_db_common.sqlsanitize.html +1 -1
  124. package/docs/functions/_saltcorn_db_common.sqlsanitizeAllowDots.html +1 -1
  125. package/docs/functions/_saltcorn_db_common.subSelectWhere.html +1 -1
  126. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.androidFeatures.html +1 -1
  127. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.androidPermissions.html +1 -1
  128. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.buildTablesFile.html +1 -1
  129. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copyPrepopulatedDb.html +1 -1
  130. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copyServerFiles.html +1 -1
  131. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copyShareExtFiles.html +1 -1
  132. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copySiteLogo.html +1 -1
  133. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copyTranslationFiles.html +1 -1
  134. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.createSqliteDb.html +1 -1
  135. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.decodeProvisioningProfile.html +1 -1
  136. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.extractDomain.html +1 -1
  137. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.generateAndroidVersionCode.html +1 -1
  138. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyAndroidManifest.html +1 -1
  139. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyConfigXml.html +1 -1
  140. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyGradleConfig.html +1 -1
  141. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyInfoPlist.html +1 -1
  142. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyXcodeProjectFile.html +1 -1
  143. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepAppIcon.html +1 -1
  144. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareAppIcon.html +1 -1
  145. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareBuildDir.html +1 -1
  146. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareExportOptionsPlist.html +1 -1
  147. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareSplashIcon.html +1 -1
  148. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareSplashPage.html +1 -1
  149. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writeCapacitorConfig.html +1 -1
  150. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writeCfgFile.html +1 -1
  151. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writeDataExtractionRules.html +1 -1
  152. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writeNetworkSecurityConfig.html +1 -1
  153. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writePodfile.html +1 -1
  154. package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writePrivacyInfo.html +1 -1
  155. package/docs/functions/_saltcorn_mobile_builder.package_bundle_utils.bundleMobileAppCode.html +1 -1
  156. package/docs/functions/_saltcorn_mobile_builder.package_bundle_utils.bundlePackagesAndPlugins.html +1 -1
  157. package/docs/functions/_saltcorn_mobile_builder.package_bundle_utils.copyMobileAppDirs.html +1 -1
  158. package/docs/functions/_saltcorn_mobile_builder.package_bundle_utils.copyPublicDirs.html +1 -1
  159. package/docs/functions/_saltcorn_sqlite.add_index.html +2 -1
  160. package/docs/functions/_saltcorn_sqlite.add_unique_constraint.html +2 -1
  161. package/docs/functions/_saltcorn_sqlite.begin.html +2 -1
  162. package/docs/functions/_saltcorn_sqlite.changeConnection.html +2 -1
  163. package/docs/functions/_saltcorn_sqlite.close.html +2 -1
  164. package/docs/functions/_saltcorn_sqlite.commit.html +2 -1
  165. package/docs/functions/_saltcorn_sqlite.count.html +2 -1
  166. package/docs/functions/_saltcorn_sqlite.deleteWhere.html +2 -1
  167. package/docs/functions/_saltcorn_sqlite.dropTable.html +2 -1
  168. package/docs/functions/_saltcorn_sqlite.dropTables.html +2 -1
  169. package/docs/functions/_saltcorn_sqlite.drop_index.html +2 -1
  170. package/docs/functions/_saltcorn_sqlite.drop_reset_schema.html +2 -1
  171. package/docs/functions/_saltcorn_sqlite.drop_unique_constraint.html +2 -1
  172. package/docs/functions/_saltcorn_sqlite.getVersion.html +2 -1
  173. package/docs/functions/_saltcorn_sqlite.get_db_filepath.html +2 -1
  174. package/docs/functions/_saltcorn_sqlite.get_sql_logging.html +2 -1
  175. package/docs/functions/_saltcorn_sqlite.init.html +2 -1
  176. package/docs/functions/_saltcorn_sqlite.insert.html +2 -1
  177. package/docs/functions/_saltcorn_sqlite.listScTables.html +2 -1
  178. package/docs/functions/_saltcorn_sqlite.listTables.html +2 -1
  179. package/docs/functions/_saltcorn_sqlite.listUserDefinedTables.html +2 -1
  180. package/docs/functions/_saltcorn_sqlite.query.html +2 -1
  181. package/docs/functions/_saltcorn_sqlite.rollback.html +2 -1
  182. package/docs/functions/_saltcorn_sqlite.select.html +2 -1
  183. package/docs/functions/_saltcorn_sqlite.selectMaybeOne.html +2 -1
  184. package/docs/functions/_saltcorn_sqlite.selectOne.html +2 -1
  185. package/docs/functions/_saltcorn_sqlite.set_sql_logging.html +2 -1
  186. package/docs/functions/_saltcorn_sqlite.slugify.html +2 -1
  187. package/docs/functions/_saltcorn_sqlite.sql_log.html +2 -1
  188. package/docs/functions/_saltcorn_sqlite.tryCatchInTransaction.html +97 -0
  189. package/docs/functions/_saltcorn_sqlite.update.html +2 -1
  190. package/docs/functions/_saltcorn_sqlite.updateWhere.html +2 -1
  191. package/docs/functions/_saltcorn_sqlite.withTransaction.html +2 -1
  192. package/docs/functions/_saltcorn_sqlite_mobile.add_index.html +1 -1
  193. package/docs/functions/_saltcorn_sqlite_mobile.add_unique_constraint.html +1 -1
  194. package/docs/functions/_saltcorn_sqlite_mobile.count.html +1 -1
  195. package/docs/functions/_saltcorn_sqlite_mobile.deleteWhere.html +1 -1
  196. package/docs/functions/_saltcorn_sqlite_mobile.drop_index.html +1 -1
  197. package/docs/functions/_saltcorn_sqlite_mobile.drop_reset_schema.html +1 -1
  198. package/docs/functions/_saltcorn_sqlite_mobile.drop_unique_constraint.html +1 -1
  199. package/docs/functions/_saltcorn_sqlite_mobile.init.html +1 -1
  200. package/docs/functions/_saltcorn_sqlite_mobile.insert.html +1 -1
  201. package/docs/functions/_saltcorn_sqlite_mobile.insertRows.html +1 -1
  202. package/docs/functions/_saltcorn_sqlite_mobile.listScTables.html +1 -1
  203. package/docs/functions/_saltcorn_sqlite_mobile.listTables.html +1 -1
  204. package/docs/functions/_saltcorn_sqlite_mobile.listUserDefinedTables.html +1 -1
  205. package/docs/functions/_saltcorn_sqlite_mobile.query.html +1 -1
  206. package/docs/functions/_saltcorn_sqlite_mobile.select.html +1 -1
  207. package/docs/functions/_saltcorn_sqlite_mobile.selectMaybeOne.html +1 -1
  208. package/docs/functions/_saltcorn_sqlite_mobile.selectOne.html +1 -1
  209. package/docs/functions/_saltcorn_sqlite_mobile.setConnectionObject.html +1 -1
  210. package/docs/functions/_saltcorn_sqlite_mobile.tableExists.html +1 -1
  211. package/docs/functions/_saltcorn_sqlite_mobile.time.html +1 -1
  212. package/docs/functions/_saltcorn_sqlite_mobile.update.html +1 -1
  213. package/docs/functions/_saltcorn_types.ModelAbstracts.abstract_field.instanceOfField.html +1 -1
  214. package/docs/functions/_saltcorn_types.ModelAbstracts.abstract_page.instanceOfPage.html +1 -1
  215. package/docs/functions/_saltcorn_types.ModelAbstracts.abstract_view.instanceOfView.html +1 -1
  216. package/docs/functions/_saltcorn_types.Types.base_types.instanceOWithHtmlFile.html +1 -1
  217. package/docs/functions/_saltcorn_types.Types.common_types.instanceOfErrorMsg.html +1 -1
  218. package/docs/functions/_saltcorn_types.Types.common_types.instanceOfSuccessMsg.html +1 -1
  219. package/docs/functions/_saltcorn_types.Types.common_types.instanceOfType.html +1 -1
  220. package/docs/functions/_saltcorn_types.generators.generateBool.html +1 -1
  221. package/docs/functions/_saltcorn_types.generators.generateString.html +1 -1
  222. package/docs/functions/_saltcorn_types.generators.num_between.html +1 -1
  223. package/docs/functions/_saltcorn_types.generators.oneOf.html +1 -1
  224. package/docs/interfaces/_saltcorn_mobile_builder.common_build_utils.ScCapacitorConfig.html +10 -10
  225. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_field.AbstractField.html +14 -14
  226. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_field.AbstractFieldRepeat.html +3 -3
  227. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_form.AbstractForm.html +26 -26
  228. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_page.AbstractPage.html +7 -7
  229. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_role.AbstractRole.html +3 -3
  230. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_table.AbstractTable.html +7 -7
  231. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_trigger.AbstractTrigger.html +16 -16
  232. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_view.AbstractView.html +10 -10
  233. package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_workflow.AbstractWorkflow.html +13 -13
  234. package/docs/modules/_saltcorn_admin_models.backup.html +1 -1
  235. package/docs/modules/_saltcorn_admin_models.html +1 -1
  236. package/docs/modules/_saltcorn_admin_models.pack.html +1 -1
  237. package/docs/modules/_saltcorn_admin_models.tenant.html +1 -1
  238. package/docs/modules/_saltcorn_common_code.html +1 -1
  239. package/docs/modules/_saltcorn_data.html +3 -3
  240. package/docs/modules/_saltcorn_data.models.Crash.html +2 -2
  241. package/docs/modules/_saltcorn_data.models.EventLog.html +2 -2
  242. package/docs/modules/_saltcorn_data.models.FieldRepeat.html +2 -2
  243. package/docs/modules/_saltcorn_data.models.File.html +2 -2
  244. package/docs/modules/_saltcorn_data.models.Form.html +2 -2
  245. package/docs/modules/_saltcorn_data.models.PageGroup.html +2 -2
  246. package/docs/modules/_saltcorn_data.models.Table.html +2 -2
  247. package/docs/modules/_saltcorn_data.models.TableConstraint.html +2 -2
  248. package/docs/modules/_saltcorn_data.models.User.html +2 -2
  249. package/docs/modules/_saltcorn_data.models.View.html +2 -2
  250. package/docs/modules/_saltcorn_data.models.Workflow.html +2 -2
  251. package/docs/modules/_saltcorn_data.models.config.html +1 -1
  252. package/docs/modules/_saltcorn_data.models.discovery.html +1 -1
  253. package/docs/modules/_saltcorn_data.models.email.html +1 -1
  254. package/docs/modules/_saltcorn_data.models.expression.html +1 -1
  255. package/docs/modules/_saltcorn_data.models.html +1 -1
  256. package/docs/modules/_saltcorn_data.models.layout.html +1 -1
  257. package/docs/modules/_saltcorn_data.models.random.html +1 -1
  258. package/docs/modules/_saltcorn_data.models.scheduler.html +1 -1
  259. package/docs/modules/_saltcorn_data.plugin_helper.html +1 -1
  260. package/docs/modules/_saltcorn_data.utils.html +1 -1
  261. package/docs/modules/_saltcorn_db_common.html +2 -2
  262. package/docs/modules/_saltcorn_db_common.multi_tenant.html +1 -1
  263. package/docs/modules/_saltcorn_markup.html +2 -2
  264. package/docs/modules/_saltcorn_mobile_builder.common_build_utils.html +1 -1
  265. package/docs/modules/_saltcorn_mobile_builder.html +1 -1
  266. package/docs/modules/_saltcorn_mobile_builder.package_bundle_utils.html +1 -1
  267. package/docs/modules/_saltcorn_sqlite.html +3 -1
  268. package/docs/modules/_saltcorn_sqlite_mobile.html +1 -1
  269. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_field.html +1 -1
  270. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_form.html +1 -1
  271. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_library.html +1 -1
  272. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_page.html +1 -1
  273. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_plugin.html +1 -1
  274. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_role.html +1 -1
  275. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_table.html +1 -1
  276. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_trigger.html +1 -1
  277. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_view.html +1 -1
  278. package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_workflow.html +1 -1
  279. package/docs/modules/_saltcorn_types.ModelAbstracts.html +1 -1
  280. package/docs/modules/_saltcorn_types.Types.base_types.html +1 -1
  281. package/docs/modules/_saltcorn_types.Types.common_types.html +1 -1
  282. package/docs/modules/_saltcorn_types.Types.html +1 -1
  283. package/docs/modules/_saltcorn_types.generators.html +1 -1
  284. package/docs/modules/_saltcorn_types.html +1 -1
  285. package/docs/types/_saltcorn_data.models.Crash.CrashCfg.html +1 -1
  286. package/docs/types/_saltcorn_data.models.EventLog.EventLogCfg.html +1 -1
  287. package/docs/types/_saltcorn_data.models.FieldRepeat.FieldRepeatCfg.html +1 -1
  288. package/docs/types/_saltcorn_data.models.File.FileCfg.html +1 -1
  289. package/docs/types/_saltcorn_data.models.Form.AdditionalButton.html +1 -1
  290. package/docs/types/_saltcorn_data.models.Form.FormCfg.html +1 -1
  291. package/docs/types/_saltcorn_data.models.PageGroup.ScreenInfoParams.html +1 -1
  292. package/docs/types/_saltcorn_data.models.Table.ChildRelations.html +1 -1
  293. package/docs/types/_saltcorn_data.models.Table.ParentRelations.html +1 -1
  294. package/docs/types/_saltcorn_data.models.Table.RelationData.html +1 -1
  295. package/docs/types/_saltcorn_data.models.TableConstraint.TableConstraintCfg.html +1 -1
  296. package/docs/types/_saltcorn_data.models.User.UserCfg.html +1 -1
  297. package/docs/types/_saltcorn_data.models.View.FindViewsPred.html +1 -1
  298. package/docs/types/_saltcorn_data.models.Workflow.WorkflowCfg.html +1 -1
  299. package/docs/types/_saltcorn_db_common.AggregationOptions.html +1 -1
  300. package/docs/types/_saltcorn_db_common.CoordOpts.html +1 -1
  301. package/docs/types/_saltcorn_db_common.DatabaseClient.html +1 -1
  302. package/docs/types/_saltcorn_db_common.JoinField.html +1 -1
  303. package/docs/types/_saltcorn_db_common.JoinFields.html +1 -1
  304. package/docs/types/_saltcorn_db_common.JoinOptions.html +1 -1
  305. package/docs/types/_saltcorn_db_common.JsonPath.html +1 -1
  306. package/docs/types/_saltcorn_db_common.JsonPathElem.html +1 -1
  307. package/docs/types/_saltcorn_db_common.Operator.html +1 -1
  308. package/docs/types/_saltcorn_db_common.PrimaryKeyValue.html +1 -1
  309. package/docs/types/_saltcorn_db_common.Row.html +1 -1
  310. package/docs/types/_saltcorn_db_common.SelectOptions.html +1 -1
  311. package/docs/types/_saltcorn_db_common.SqlAndValues.html +1 -1
  312. package/docs/types/_saltcorn_db_common.SubselectOptions.html +1 -1
  313. package/docs/types/_saltcorn_db_common.Value.html +1 -1
  314. package/docs/types/_saltcorn_db_common.Where.html +1 -1
  315. package/docs/types/_saltcorn_mobile_builder.IosCfg.html +1 -1
  316. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_field.FieldCfg.html +1 -1
  317. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_field.InputType.html +1 -1
  318. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_form.AdditionalButton.html +1 -1
  319. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_library.LibraryCfg.html +1 -1
  320. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_library.LibraryPack.html +1 -1
  321. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_page.PageCfg.html +1 -1
  322. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_page.PagePack.html +1 -1
  323. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_plugin.PluginCfg.html +1 -1
  324. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_plugin.PluginPack.html +1 -1
  325. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_role.RoleCfg.html +1 -1
  326. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_role.RolePack.html +1 -1
  327. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_table.TableCfg.html +1 -1
  328. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_table.TablePack.html +1 -1
  329. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_trigger.TriggerCfg.html +1 -1
  330. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_trigger.TriggerPack.html +1 -1
  331. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_view.ViewCfg.html +1 -1
  332. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_view.ViewPack.html +1 -1
  333. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_workflow.ConfigWorkflowStep.html +1 -1
  334. package/docs/types/_saltcorn_types.ModelAbstracts.abstract_workflow.RunResult.html +1 -1
  335. package/docs/types/_saltcorn_types.Types.base_types.Action.html +1 -1
  336. package/docs/types/_saltcorn_types.Types.base_types.AuthenticationMethod.html +1 -1
  337. package/docs/types/_saltcorn_types.Types.base_types.CapacitorPlugin.html +1 -1
  338. package/docs/types/_saltcorn_types.Types.base_types.CodePagePack.html +1 -1
  339. package/docs/types/_saltcorn_types.Types.base_types.Column.html +1 -1
  340. package/docs/types/_saltcorn_types.Types.base_types.ConnectedObjects.html +1 -1
  341. package/docs/types/_saltcorn_types.Types.base_types.CopilotSkill.html +1 -1
  342. package/docs/types/_saltcorn_types.Types.base_types.FieldLike.html +1 -1
  343. package/docs/types/_saltcorn_types.Types.base_types.FieldView.html +1 -1
  344. package/docs/types/_saltcorn_types.Types.base_types.Header.html +1 -1
  345. package/docs/types/_saltcorn_types.Types.base_types.JoinFieldOption.html +1 -1
  346. package/docs/types/_saltcorn_types.Types.base_types.Layout.html +1 -1
  347. package/docs/types/_saltcorn_types.Types.base_types.MobileConfig.html +1 -1
  348. package/docs/types/_saltcorn_types.Types.base_types.ModelPattern.html +1 -1
  349. package/docs/types/_saltcorn_types.Types.base_types.Pack.html +1 -1
  350. package/docs/types/_saltcorn_types.Types.base_types.Plugin.html +1 -1
  351. package/docs/types/_saltcorn_types.Types.base_types.PluginFunction.html +5 -5
  352. package/docs/types/_saltcorn_types.Types.base_types.PluginLayout.html +1 -1
  353. package/docs/types/_saltcorn_types.Types.base_types.PluginRoute.html +1 -1
  354. package/docs/types/_saltcorn_types.Types.base_types.PluginSourceType.html +1 -1
  355. package/docs/types/_saltcorn_types.Types.base_types.PluginType.html +1 -1
  356. package/docs/types/_saltcorn_types.Types.base_types.PluginWrap.html +1 -1
  357. package/docs/types/_saltcorn_types.Types.base_types.PluginWrapArg.html +1 -1
  358. package/docs/types/_saltcorn_types.Types.base_types.RelationOption.html +1 -1
  359. package/docs/types/_saltcorn_types.Types.base_types.Req.html +1 -1
  360. package/docs/types/_saltcorn_types.Types.base_types.Res.html +1 -1
  361. package/docs/types/_saltcorn_types.Types.base_types.RouteAction.html +1 -1
  362. package/docs/types/_saltcorn_types.Types.base_types.RunExtra.html +1 -1
  363. package/docs/types/_saltcorn_types.Types.base_types.TableProvider.html +5 -5
  364. package/docs/types/_saltcorn_types.Types.base_types.TableQuery.html +1 -1
  365. package/docs/types/_saltcorn_types.Types.base_types.Tablely.html +1 -1
  366. package/docs/types/_saltcorn_types.Types.base_types.ViewTemplate.html +1 -1
  367. package/docs/types/_saltcorn_types.Types.common_types.ErrorMessage.html +1 -1
  368. package/docs/types/_saltcorn_types.Types.common_types.GenObj.html +1 -1
  369. package/docs/types/_saltcorn_types.Types.common_types.ReqRes.html +1 -1
  370. package/docs/types/_saltcorn_types.Types.common_types.ResultMessage.html +1 -1
  371. package/docs/types/_saltcorn_types.Types.common_types.SuccessMessage.html +1 -1
  372. package/docs/types/_saltcorn_types.Types.common_types.Type.html +17 -4
  373. package/docs/variables/_saltcorn_data.db.html +1 -1
  374. package/docs/variables/_saltcorn_data.migrations.html +1 -1
  375. package/docs/variables/_saltcorn_data.models.config.available_languages.html +1 -1
  376. package/docs/variables/_saltcorn_data.models.config.configTypes.html +1 -1
  377. package/docs/variables/_saltcorn_data.models.scheduler.runScheduler.html +1 -1
  378. package/docs/variables/_saltcorn_data.plugin_helper.run_action_column.html +1 -1
  379. package/docs/variables/_saltcorn_data.utils.NotAuthorized.html +1 -1
  380. package/docs/variables/_saltcorn_data.utils.sleep.html +1 -1
  381. package/docs/variables/_saltcorn_db_common.multi_tenant.tenantNamespace.html +1 -1
  382. package/load_plugins.js +1 -1
  383. package/locales/da.json +862 -860
  384. package/locales/de.json +20 -2
  385. package/locales/en.json +10 -1
  386. package/locales/es.json +20 -2
  387. package/locales/fr.json +21 -3
  388. package/locales/pl.json +19 -9
  389. package/locales/pt.json +20 -2
  390. package/markup/admin.js +28 -0
  391. package/markup/expression_blurb.js +4 -2
  392. package/package.json +10 -9
  393. package/public/saltcorn-common.js +32 -7
  394. package/public/saltcorn.css +11 -1
  395. package/public/saltcorn.js +1 -0
  396. package/public/tabulator.min.js +2 -2
  397. package/public/tabulator_bootstrap4.min.css +1 -1
  398. package/public/tabulator_bootstrap5.min.css +2 -1
  399. package/routes/actions.js +28 -5
  400. package/routes/admin.js +115 -31
  401. package/routes/api.js +27 -15
  402. package/routes/common_lists.js +18 -7
  403. package/routes/infoarch.js +159 -8
  404. package/routes/list.js +47 -11
  405. package/routes/tables.js +15 -2
  406. package/routes/tag_entries.js +6 -1
  407. package/routes/view.js +10 -3
  408. package/serve.js +5 -1
  409. package/wrapper.js +8 -5
package/routes/admin.js CHANGED
@@ -15,6 +15,8 @@ const {
15
15
  tenant_letsencrypt_name,
16
16
  isAdminOrHasConfigMinRole,
17
17
  checkEditPermission,
18
+ addOnDoneRedirect,
19
+ is_relative_url,
18
20
  } = require("./utils.js");
19
21
  const Table = require("@saltcorn/data/models/table");
20
22
  const Plugin = require("@saltcorn/data/models/plugin");
@@ -95,7 +97,10 @@ const {
95
97
  const packagejson = require("../package.json");
96
98
  const Form = require("@saltcorn/data/models/form");
97
99
  const { get_latest_npm_version } = require("@saltcorn/data/models/config");
98
- const { getMailTransport } = require("@saltcorn/data/models/email");
100
+ const {
101
+ getMailTransport,
102
+ getOauth2Client,
103
+ } = require("@saltcorn/data/models/email");
99
104
  const {
100
105
  getBaseDomain,
101
106
  hostname_matches_baseurl,
@@ -214,8 +219,22 @@ admin_config_route({
214
219
  flash: "Email settings updated",
215
220
  field_names: [
216
221
  "smtp_host",
217
- "smtp_username",
218
- "smtp_password",
222
+ "smtp_auth_method",
223
+ { name: "smtp_username", showIf: { smtp_auth_method: "password" } },
224
+ { name: "smtp_password", showIf: { smtp_auth_method: "password" } },
225
+ {
226
+ name: "smtp_api_option",
227
+ showIf: {
228
+ smtp_host: "outlook.office365.com",
229
+ smtp_auth_method: "oauth2",
230
+ },
231
+ },
232
+ { name: "smtp_authorize_url", showIf: { smtp_auth_method: "oauth2" } },
233
+ { name: "smtp_token_url", showIf: { smtp_auth_method: "oauth2" } },
234
+ { name: "smtp_redirect_uri", showIf: { smtp_auth_method: "oauth2" } },
235
+ { name: "smtp_client_id", showIf: { smtp_auth_method: "oauth2" } },
236
+ { name: "smtp_client_secret", showIf: { smtp_auth_method: "oauth2" } },
237
+ { name: "smtp_outh_scopes", showIf: { smtp_auth_method: "oauth2" } },
219
238
  "smtp_port",
220
239
  "smtp_secure",
221
240
  "smtp_allow_self_signed",
@@ -241,6 +260,40 @@ admin_config_route({
241
260
  },
242
261
  req.__("Send test email")
243
262
  ),
263
+ a(
264
+ {
265
+ id: "authenticate_oauth",
266
+ href: "/admin/authorize-mail-oauth",
267
+ class: "btn btn-primary ms-2",
268
+ onclick: "spin_action_link(this)",
269
+ },
270
+ req.__("Authorize")
271
+ ),
272
+ script(`
273
+ function authMethodChange(method) {
274
+ const btn = document.getElementById("authenticate_oauth");
275
+ if (method === "oauth2") {
276
+ btn.classList.remove("d-none");
277
+ btn.classList.add("d-inline");
278
+ // get
279
+ }
280
+ else {
281
+ btn.classList.add("d-none");
282
+ btn.classList.remove("d-inline");
283
+ }
284
+
285
+ }
286
+ ${domReady(`
287
+ const authMethod = document.getElementById('inputsmtp_auth_method');
288
+ if (authMethod) {
289
+ const authMethodValue = authMethod.value;
290
+ authMethodChange(authMethodValue);
291
+ authMethod.addEventListener('change', (e) => {
292
+ const authMethod = e.target.value;
293
+ authMethodChange(authMethod);
294
+ });
295
+ }`)}
296
+ `),
244
297
  ],
245
298
  },
246
299
  });
@@ -264,7 +317,7 @@ router.get(
264
317
  html: req.__("Hello from Saltcorn"),
265
318
  };
266
319
  try {
267
- const sendres = await getMailTransport().sendMail(email);
320
+ const sendres = await (await getMailTransport()).sendMail(email);
268
321
  getState().log(6, sendres);
269
322
  req.flash(
270
323
  "success",
@@ -279,6 +332,27 @@ router.get(
279
332
  })
280
333
  );
281
334
 
335
+ /**
336
+ * do the redirect to the oauth2 provider
337
+ */
338
+ router.get(
339
+ "/authorize-mail-oauth",
340
+ isAdmin,
341
+ error_catcher(async (req, res) => {
342
+ const client = getOauth2Client();
343
+ const smtpRedirectUri = getState().getConfig("smtp_redirect_uri");
344
+ const scopes = getState().getConfig("smtp_outh_scopes");
345
+ const scopeArray = scopes.split(" ").map((s) => s.trim());
346
+
347
+ // Mail.Send SMTP.Send profile openid email https://outlook.office365.com/IMAP.AccessAsUser.All
348
+ const authorizeUrl = client.authorizeURL({
349
+ redirect_uri: smtpRedirectUri,
350
+ scope: scopeArray,
351
+ });
352
+ res.redirect(authorizeUrl);
353
+ })
354
+ );
355
+
282
356
  /**
283
357
  * @name get/send-test-email
284
358
  * @function
@@ -435,7 +509,10 @@ router.get(
435
509
  req.csrfToken(),
436
510
  {
437
511
  btnClass: "btn-outline-primary",
438
- spinner: true,
512
+ klass: "backupadminbtn",
513
+ //TODO not sure how to tell when backup done
514
+ onClick:
515
+ "spin_action_link($('.backupadminbtn'));setTimeout(()=> reset_spinners($('.backupadminbtn')), 3000)",
439
516
  }
440
517
  )
441
518
  ),
@@ -723,7 +800,10 @@ router.get(
723
800
  label: req.__("Restore"),
724
801
  key: (r) =>
725
802
  post_btn(
726
- `/admin/snapshot-restore/${type}/${name}/${r.id}`,
803
+ addOnDoneRedirect(
804
+ `/admin/snapshot-restore/${type}/${name}/${r.id}`,
805
+ req
806
+ ),
727
807
  req.__("Restore"),
728
808
  req.csrfToken()
729
809
  ),
@@ -762,13 +842,16 @@ router.post(
762
842
  }
763
843
  await getState().refresh();
764
844
  res.redirect(
765
- type == "codepage"
845
+ req.query.on_done_redirect &&
846
+ is_relative_url("/" + req.query.on_done_redirect)
847
+ ? `/${req.query.on_done_redirect}`
848
+ : type == "codepage"
766
849
  ? `/admin/edit-codepage/${name}`
767
850
  : type === "trigger"
768
- ? `/actions`
769
- : /^[a-z]+$/g.test(type)
770
- ? `/${type}edit`
771
- : "/"
851
+ ? `/actions`
852
+ : /^[a-z]+$/g.test(type)
853
+ ? `/${type}edit`
854
+ : "/"
772
855
  );
773
856
  })
774
857
  );
@@ -1269,20 +1352,20 @@ router.get(
1269
1352
  }
1270
1353
  )
1271
1354
  : isRoot && is_latest
1272
- ? span(
1273
- { class: "badge bg-primary ms-2" },
1274
- req.__("Latest")
1275
- ) +
1276
- post_btn(
1277
- "/admin/check-for-upgrade",
1278
- req.__("Check updates"),
1279
- req.csrfToken(),
1280
- {
1281
- btnClass: "btn-primary btn-sm px-1 py-0",
1282
- formClass: "d-inline",
1283
- }
1284
- )
1285
- : "",
1355
+ ? span(
1356
+ { class: "badge bg-primary ms-2" },
1357
+ req.__("Latest")
1358
+ ) +
1359
+ post_btn(
1360
+ "/admin/check-for-upgrade",
1361
+ req.__("Check updates"),
1362
+ req.csrfToken(),
1363
+ {
1364
+ btnClass: "btn-primary btn-sm px-1 py-0",
1365
+ formClass: "d-inline",
1366
+ }
1367
+ )
1368
+ : "",
1286
1369
  isRoot &&
1287
1370
  !git_commit &&
1288
1371
  a(
@@ -2051,8 +2134,9 @@ router.get(
2051
2134
  const filename = `${moment(start).format("YYYYMMDDHHmm")}.html`;
2052
2135
  await File.new_folder("configuration_checks");
2053
2136
  const go = async () => {
2054
- const { passes, errors, pass, warnings } =
2055
- await runConfigurationCheck(req);
2137
+ const { passes, errors, pass, warnings } = await runConfigurationCheck(
2138
+ req
2139
+ );
2056
2140
  const end = new Date();
2057
2141
  const secs = Math.round((end.getTime() - start.getTime()) / 1000);
2058
2142
 
@@ -3329,8 +3413,8 @@ router.get(
3329
3413
  mode === "prepare"
3330
3414
  ? "_prepare_step"
3331
3415
  : mode === "finish"
3332
- ? "_finish_step"
3333
- : "";
3416
+ ? "_finish_step"
3417
+ : "";
3334
3418
  res.json({
3335
3419
  finished: await checkFiles(out_dir_name, [
3336
3420
  `logs${stepDesc}.txt`,
@@ -3405,8 +3489,8 @@ router.get(
3405
3489
  mode === "prepare"
3406
3490
  ? "_prepare_step"
3407
3491
  : mode === "finish"
3408
- ? "_finish_step"
3409
- : "";
3492
+ ? "_finish_step"
3493
+ : "";
3410
3494
  const resultMsg = files.find(
3411
3495
  (file) => file.filename === `logs${stepDesc}.txt`
3412
3496
  )
package/routes/api.js CHANGED
@@ -407,23 +407,35 @@ router.get(
407
407
  target: field?.attributes?.summary_field,
408
408
  };
409
409
  });
410
- rows = await table.getJoinedRows({
411
- where: qstate,
412
- joinFields,
413
- limit: use_limit,
414
- offset: use_offset,
415
- orderDesc:
416
- (sortDesc && sortDesc !== "false") || tabulator_dir == "desc",
417
- orderBy: orderByField?.name || undefined,
418
- forPublic: !(req.user || user),
419
- forUser: req.user || user,
420
- });
410
+ try {
411
+ rows = await table.getJoinedRows({
412
+ where: qstate,
413
+ joinFields,
414
+ limit: use_limit,
415
+ offset: use_offset,
416
+ orderDesc:
417
+ (sortDesc && sortDesc !== "false") || tabulator_dir == "desc",
418
+ orderBy: orderByField?.name || undefined,
419
+ forPublic: !(req.user || user),
420
+ forUser: req.user || user,
421
+ });
422
+ } catch (e) {
423
+ console.error(e);
424
+ res.json({ error: "API error" });
425
+ return;
426
+ }
421
427
  }
422
428
  if (tabulator_pagination_format) {
423
- res.json({
424
- last_page: Math.ceil((await table.countRows()) / +tabulator_size),
425
- data: rows.map(limitFields(fields)),
426
- });
429
+ const count = await table.countRows();
430
+ if (count === null)
431
+ res.json({
432
+ data: rows.map(limitFields(fields)),
433
+ });
434
+ else
435
+ res.json({
436
+ last_page: Math.ceil(count / +tabulator_size),
437
+ data: rows.map(limitFields(fields)),
438
+ });
427
439
  } else res.json({ success: rows.map(limitFields(fields)) });
428
440
  } else {
429
441
  getState().log(3, `API get ${table.name} not authorized`);
@@ -205,7 +205,7 @@ const view_dropdown = (view, req, on_done_redirect_str = "") =>
205
205
  a(
206
206
  {
207
207
  class: "dropdown-item",
208
- href: `javascript:ajax_modal('/admin/snapshot-restore/view/${view.name}')`,
208
+ href: `javascript:ajax_modal('/admin/snapshot-restore/view/${view.name}${on_done_redirect_str}')`,
209
209
  },
210
210
  '<i class="fas fa-undo-alt"></i>&nbsp;' + req.__("Restore")
211
211
  ),
@@ -284,7 +284,7 @@ const tagsDropdown = (tags, altHeader, req) =>
284
284
  {
285
285
  class: "dropdown-item",
286
286
  // TODO check url why view for page, what do we need for page group
287
- href: `tag`,
287
+ href: `/tag`,
288
288
  },
289
289
  req.__("Manage tags...")
290
290
  )
@@ -391,7 +391,7 @@ const viewsList = async (
391
391
  filterOnTag ? `Tag:${filterOnTag.name}` : undefined,
392
392
  req
393
393
  ),
394
- key: (r) => tagBadges(r),
394
+ key: (r) => (r.id ? tagBadges(r) : ""),
395
395
  },
396
396
  ]),
397
397
  {
@@ -674,12 +674,12 @@ const trigger_dropdown = (trigger, req, on_done_redirect_str = "") =>
674
674
  a(
675
675
  {
676
676
  class: "dropdown-item",
677
- href: `javascript:ajax_modal('/admin/snapshot-restore/trigger/${trigger.name}')`,
677
+ href: `javascript:ajax_modal('/admin/snapshot-restore/trigger/${trigger.name}${on_done_redirect_str}')`,
678
678
  },
679
679
  '<i class="fas fa-undo-alt"></i>&nbsp;' + req.__("Restore")
680
680
  ),
681
681
  post_dropdown_item(
682
- `/actions/clone/${trigger.id}`,
682
+ `/actions/clone/${trigger.id}${on_done_redirect_str}`,
683
683
  '<i class="far fa-copy"></i>&nbsp;' + req.__("Duplicate"),
684
684
  req
685
685
  ),
@@ -734,11 +734,22 @@ const getTriggerList = async (
734
734
  { label: req.__("Name"), key: "name" },
735
735
  {
736
736
  label: req.__("Test run"),
737
- key: (r) => link(`/actions/testrun/${r.id}`, req.__("Test run")),
737
+ key: (r) =>
738
+ link(
739
+ `/actions/testrun/${r.id}${on_done_redirect_str}`,
740
+ req.__("Test run"),
741
+ {
742
+ onclick: `press_store_button(this)`,
743
+ }
744
+ ),
738
745
  },
739
746
  {
740
747
  label: req.__("Configure"),
741
- key: (r) => link(`/actions/configure/${r.id}`, req.__("Configure")),
748
+ key: (r) =>
749
+ link(
750
+ `/actions/configure/${r.id}${on_done_redirect_str}`,
751
+ req.__("Configure")
752
+ ),
742
753
  },
743
754
  ...(tagId
744
755
  ? []
@@ -16,12 +16,16 @@ const {
16
16
  send_admin_page,
17
17
  config_fields_form,
18
18
  save_config_from_form,
19
+ upload_language_pack,
19
20
  } = require("../markup/admin.js");
20
21
  const { getState } = require("@saltcorn/data/db/state");
21
22
  const { div, a, i, text, button } = require("@saltcorn/markup/tags");
22
23
  const { mkTable, renderForm, post_delete_btn } = require("@saltcorn/markup");
23
24
  const Form = require("@saltcorn/data/models/form");
24
25
  const Snapshot = require("@saltcorn/admin-models/models/snapshot");
26
+ const { stringify } = require("csv-stringify");
27
+ const csvtojson = require("csvtojson");
28
+ const { hasLLM, translate } = require("@saltcorn/data/translate");
25
29
 
26
30
  /**
27
31
  * @type {object}
@@ -175,6 +179,17 @@ router.get(
175
179
  })
176
180
  : "",
177
181
  },
182
+ {
183
+ label: req.__("Language CSV"),
184
+ key: (r) =>
185
+ a(
186
+ {
187
+ href: `/site-structure/localizer/download-pack/${r.locale}`,
188
+ },
189
+ i({ class: "fas fa-download me-2" }),
190
+ req.__("Download")
191
+ ),
192
+ },
178
193
  {
179
194
  label: req.__("Delete"),
180
195
  key: (r) =>
@@ -187,13 +202,17 @@ router.get(
187
202
  ],
188
203
  Object.values(cfgLangs)
189
204
  ),
190
- a(
191
- {
192
- href: "/site-structure/localizer/add-lang",
193
- class: "btn btn-primary mt-1",
194
- },
195
- i({ class: "fas fa-plus-square me-1" }),
196
- req.__("Add language")
205
+ div(
206
+ { class: "d-flex mt-1" },
207
+ a(
208
+ {
209
+ href: "/site-structure/localizer/add-lang",
210
+ class: "btn btn-primary me-2",
211
+ },
212
+ i({ class: "fas fa-plus-square me-1" }),
213
+ req.__("Add language")
214
+ ),
215
+ upload_language_pack(req)
197
216
  )
198
217
  ),
199
218
  },
@@ -201,6 +220,75 @@ router.get(
201
220
  })
202
221
  );
203
222
 
223
+ router.get(
224
+ "/localizer/download-pack/:lang",
225
+ isAdmin,
226
+ error_catcher(async (req, res) => {
227
+ const { lang } = req.params;
228
+ if (lang === "__proto__" || lang === "constructor") {
229
+ res.redirect(`/`);
230
+ return;
231
+ }
232
+ const cfgLangs = getState().getConfig("localizer_languages");
233
+
234
+ if (!cfgLangs[lang]) {
235
+ req.flash("error", req.__("Language not found"));
236
+ return res.redirect(`/site-structure/localizer`);
237
+ }
238
+ const default_lang =
239
+ Object.values(cfgLangs).find((lobj) => lobj.is_default)?.locale ||
240
+ getState().getConfig("default_locale", "en");
241
+
242
+ const cfgStrings = getState().getConfig("localizer_strings", {});
243
+ const translation = cfgStrings[lang] || {};
244
+ const strings = getState()
245
+ .getStringsForI18n()
246
+ .map((s) => ({ [default_lang]: s, [lang]: translation[s] || s }));
247
+ res.type("text/csv");
248
+ res.setHeader("Content-Disposition", `attachment; filename="${lang}.csv"`);
249
+ res.setHeader("Cache-Control", "no-cache");
250
+ res.setHeader("Pragma", "no-cache");
251
+ stringify(strings, {
252
+ header: true,
253
+ columns: [default_lang, lang],
254
+ quoted: true,
255
+ }).pipe(res);
256
+ })
257
+ );
258
+
259
+ router.post(
260
+ "/localizer/upload-language-pack",
261
+ isAdmin,
262
+ setTenant, // TODO why is this needed?????
263
+ error_catcher(async (req, res) => {
264
+ if (req.files?.file?.tempFilePath) {
265
+ const cfgLangs = getState().getConfig("localizer_languages");
266
+ const default_lang =
267
+ Object.values(cfgLangs).find((lobj) => lobj.is_default)?.locale ||
268
+ getState().getConfig("default_locale", "en");
269
+ const cfgStrings = getState().getConfigCopy("localizer_strings");
270
+
271
+ try {
272
+ const rows = await csvtojson().fromFile(req.files?.file?.tempFilePath);
273
+ const langs = Object.keys(rows[0]).filter((k) => k !== default_lang);
274
+ for (const lang of langs)
275
+ for (const row of rows) {
276
+ const defstring = row[default_lang];
277
+ if (cfgStrings[lang]) cfgStrings[lang][defstring] = row[lang];
278
+ else cfgStrings[lang] = { [defstring]: row[lang] };
279
+ }
280
+ await getState().setConfig("localizer_strings", cfgStrings);
281
+
282
+ req.flash("success", `Updated languages: ${langs.join(", ")}`);
283
+ } catch (e) {
284
+ console.error(e);
285
+ req.flash("error", e.message);
286
+ }
287
+ }
288
+ res.redirect(`/site-structure/localizer`);
289
+ })
290
+ );
291
+
204
292
  /**
205
293
  * @name get/localizer/add-lang
206
294
  * @function
@@ -253,7 +341,21 @@ router.get(
253
341
  above: [
254
342
  {
255
343
  type: "card",
256
- contents: [renderForm(form, req.csrfToken())],
344
+ contents: [
345
+ renderForm(form, req.csrfToken()),
346
+ hasLLM() &&
347
+ renderForm(
348
+ new Form({
349
+ fields: [],
350
+ action: `/site-structure/localizer/translate-llm/${lang}`,
351
+ submitLabel: req.__("Translate with LLM"),
352
+ onSubmit: "press_store_button(this)",
353
+
354
+ submitButtonClass: "btn-secondary",
355
+ }),
356
+ req.csrfToken()
357
+ ),
358
+ ],
257
359
  },
258
360
  !is_default && {
259
361
  type: "card",
@@ -288,6 +390,55 @@ router.get(
288
390
  })
289
391
  );
290
392
 
393
+ router.post(
394
+ "/localizer/translate-llm/:lang/",
395
+ isAdmin,
396
+ error_catcher(async (req, res) => {
397
+ const { lang, defstring } = req.params;
398
+ if (
399
+ lang === "__proto__" ||
400
+ defstring === "__proto__" ||
401
+ lang === "constructor"
402
+ ) {
403
+ res.redirect(`/`);
404
+ return;
405
+ }
406
+ const cfgLangs = getState().getConfig("localizer_languages");
407
+
408
+ if (!cfgLangs[lang]) {
409
+ req.flash("error", req.__("Language not found"));
410
+ return res.redirect(`/site-structure/localizer`);
411
+ }
412
+ const default_lang =
413
+ Object.values(cfgLangs).find((lobj) => lobj.is_default)?.locale ||
414
+ getState().getConfig("default_locale", "en");
415
+ let count = 0;
416
+ for (const defstring of getState().getStringsForI18n()) {
417
+ const cfgStrings = getState().getConfigCopy("localizer_strings", {});
418
+ if (
419
+ cfgStrings[lang][defstring] &&
420
+ cfgStrings[lang][defstring] !== defstring
421
+ )
422
+ continue;
423
+ if (count >= 20) break;
424
+ count += 1;
425
+ const translated = await translate(defstring, lang, default_lang);
426
+ if (cfgStrings[lang]) cfgStrings[lang][defstring] = translated;
427
+ else cfgStrings[lang] = { [defstring]: translated };
428
+ await getState().setConfig("localizer_strings", cfgStrings);
429
+ }
430
+ if (count == 20)
431
+ req.flash(
432
+ "success",
433
+ req.__(
434
+ `Translated %s strings. Click 'Translate with LLM' again to continue`, count
435
+ )
436
+ );
437
+ else req.flash("success", req.__(`Finished translating %s strings.`, count));
438
+ res.redirect(`/site-structure/localizer/edit/${lang}`);
439
+ })
440
+ );
441
+
291
442
  /**
292
443
  * @name post/localizer/save-string/:lang/:defstring
293
444
  * @function
package/routes/list.js CHANGED
@@ -19,6 +19,7 @@ const {
19
19
  i,
20
20
  text,
21
21
  button,
22
+ a,
22
23
  input,
23
24
  label,
24
25
  form,
@@ -31,6 +32,7 @@ const {
31
32
  } = require("./utils");
32
33
  const moment = require("moment");
33
34
  const { getState } = require("@saltcorn/data/db/state");
35
+ const { comparingCaseInsensitive } = require("@saltcorn/data/utils");
34
36
 
35
37
  /**
36
38
  * @type {object}
@@ -127,19 +129,26 @@ router.post(
127
129
  const typeToGridType = (t, field) => {
128
130
  const jsgField = { field: field.name, title: field.label, editor: true };
129
131
  if (t.name === "String" && field.attributes && field.attributes.options) {
130
- jsgField.editor = "select";
132
+ jsgField.editor = "list";
131
133
 
132
134
  const values = field.attributes.options.split(",").map((o) => o.trim());
133
135
  if (!field.required) values.unshift("");
134
136
 
135
137
  jsgField.editorParams = { values };
136
138
  } else if (t === "Key" || t === "File") {
137
- jsgField.editor = "select";
138
- const values = {};
139
-
140
- field.options.forEach(({ label, value }) => (values[value] = label));
139
+ jsgField.editor = "list";
140
+ const values = [];
141
+ const valuesObj = {};
142
+ field.options
143
+ .sort(comparingCaseInsensitive("label"))
144
+ .forEach(({ label, value }) => {
145
+ //en space. tabulator workaround
146
+ const l = label === "" ? "\u2002" : label;
147
+ values.push({ label: l, value });
148
+ valuesObj[value] = l;
149
+ });
141
150
  jsgField.editorParams = { values };
142
- jsgField.formatterParams = { values };
151
+ jsgField.formatterParams = { values: valuesObj };
143
152
  jsgField.formatter = "__lookupIntToString";
144
153
  } else if (t.name === "Float" || t.name === "Integer") {
145
154
  jsgField.editor = "number";
@@ -373,6 +382,21 @@ router.get(
373
382
  },
374
383
  form(
375
384
  { class: "px-2" },
385
+ a(
386
+ {
387
+ onclick: `event.stopPropagation();allnonecols(true,this)`,
388
+ href: "javascript:;",
389
+ },
390
+ "All"
391
+ ),
392
+ " | ",
393
+ a(
394
+ {
395
+ onclick: `event.stopPropagation();allnonecols(false,this)`,
396
+ href: "javascript:;",
397
+ },
398
+ "None"
399
+ ),
376
400
  fields.map((f) =>
377
401
  div(
378
402
  { class: "form-check" },
@@ -403,7 +427,7 @@ router.get(
403
427
  if(typeof v === "string" && v.startsWith("__"))
404
428
  col[k] = window[v.substring(2)];
405
429
  })
406
- })
430
+ })
407
431
  window.tabulator_table_primary_key = "${table.pk_name}";
408
432
  window.tabulator_table = new Tabulator("#jsGrid", {
409
433
  ajaxURL:"/api/${encodeURIComponent(
@@ -411,22 +435,34 @@ router.get(
411
435
  )}?tabulator_pagination_format=true${
412
436
  table.versioned ? "&versioncount=on" : ""
413
437
  }",
414
- layout:"fitColumns",
438
+ layout:"fitData",
415
439
  columns,
416
440
  height:"100%",
417
441
  pagination:true,
418
442
  paginationMode:"remote",
419
443
  paginationSize:20,
420
- clipboard:true,
421
- persistence:true,
422
- persistenceID:"table_tab_${table.name}",
444
+ clipboard:true,
423
445
  movableColumns: true,
424
446
  ajaxContentType:"json",
425
447
  sortMode:"remote",
448
+ resizableColumnGuide:true,
449
+ columnDefaults:{
450
+ resizable:true,
451
+ maxWidth:500
452
+ },
426
453
  initialSort:[
427
454
  {column:"${table.pk_name}", dir:"asc"},
428
455
  ],
429
456
  });
457
+ window.allnonecols= (do_show, e) =>{
458
+ columns.forEach(col=>{
459
+ if(col.frozen && !do_show) return;
460
+ if (do_show) window.tabulator_table.showColumn(col.field);
461
+ else window.tabulator_table.hideColumn(col.field);
462
+ $(e).closest("form").find("input").prop("checked", do_show)
463
+ })
464
+ }
465
+
430
466
  window.tabulator_table.on("cellEdited", function(cell){
431
467
  const row = cell.getRow().getData()
432
468
  const fieldName = cell.getColumn().getField()