@saltcorn/server 1.3.0-beta.12 → 1.3.0-beta.14
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/CHANGELOG.md +10 -0
- package/docs/classes/_saltcorn_common_code.Relation.html +10 -10
- package/docs/classes/_saltcorn_common_code.RelationsFinder.html +5 -5
- package/docs/classes/_saltcorn_data.models.Crash.html +17 -17
- package/docs/classes/_saltcorn_data.models.EventLog-1.html +19 -19
- package/docs/classes/_saltcorn_data.models.Field.html +74 -74
- package/docs/classes/_saltcorn_data.models.FieldRepeat.html +16 -16
- package/docs/classes/_saltcorn_data.models.File-1.html +48 -48
- package/docs/classes/_saltcorn_data.models.Form-1.html +39 -39
- package/docs/classes/_saltcorn_data.models.Library.html +13 -13
- package/docs/classes/_saltcorn_data.models.Page.html +24 -24
- package/docs/classes/_saltcorn_data.models.PageGroup-1.html +25 -25
- package/docs/classes/_saltcorn_data.models.Plugin.html +25 -25
- package/docs/classes/_saltcorn_data.models.Role.html +9 -9
- package/docs/classes/_saltcorn_data.models.Table-1.html +92 -92
- package/docs/classes/_saltcorn_data.models.TableConstraint.html +14 -14
- package/docs/classes/_saltcorn_data.models.Trigger.html +36 -36
- package/docs/classes/_saltcorn_data.models.User.html +48 -48
- package/docs/classes/_saltcorn_data.models.View-1.html +54 -54
- package/docs/classes/_saltcorn_data.models.Workflow.html +17 -17
- package/docs/classes/_saltcorn_data.models.WorkflowRun.html +35 -35
- package/docs/classes/_saltcorn_data.models.WorkflowStep.html +25 -25
- package/docs/classes/_saltcorn_data.models.WorkflowTrace.html +18 -18
- package/docs/classes/_saltcorn_mobile_builder.MobileBuilder.html +36 -36
- package/docs/enums/_saltcorn_common_code.RelationType.html +7 -7
- package/docs/enums/_saltcorn_common_code.ViewDisplayType.html +4 -4
- package/docs/functions/_saltcorn_admin_models.backup.create_backup.html +1 -1
- package/docs/functions/_saltcorn_admin_models.backup.create_csv_from_rows.html +1 -1
- package/docs/functions/_saltcorn_admin_models.backup.restore.html +1 -1
- package/docs/functions/_saltcorn_admin_models.pack.add_to_menu.html +1 -1
- package/docs/functions/_saltcorn_admin_models.pack.can_install_pack.html +1 -1
- package/docs/functions/_saltcorn_admin_models.pack.fetch_available_packs.html +1 -1
- package/docs/functions/_saltcorn_admin_models.pack.fetch_pack_by_name.html +1 -1
- package/docs/functions/_saltcorn_admin_models.pack.install_pack.html +1 -1
- package/docs/functions/_saltcorn_admin_models.pack.library_pack.html +1 -1
- package/docs/functions/_saltcorn_admin_models.pack.model_instance_pack.html +1 -1
- package/docs/functions/_saltcorn_admin_models.pack.model_pack.html +1 -1
- package/docs/functions/_saltcorn_admin_models.pack.page_group_pack.html +1 -1
- package/docs/functions/_saltcorn_admin_models.pack.page_pack.html +1 -1
- package/docs/functions/_saltcorn_admin_models.pack.plugin_pack.html +1 -1
- package/docs/functions/_saltcorn_admin_models.pack.role_pack.html +1 -1
- package/docs/functions/_saltcorn_admin_models.pack.table_pack.html +1 -1
- package/docs/functions/_saltcorn_admin_models.pack.trigger_pack.html +1 -1
- package/docs/functions/_saltcorn_admin_models.pack.uninstall_pack.html +1 -1
- package/docs/functions/_saltcorn_admin_models.pack.view_pack.html +1 -1
- package/docs/functions/_saltcorn_admin_models.tenant.copy_tenant_template.html +1 -1
- package/docs/functions/_saltcorn_admin_models.tenant.create_tenant.html +1 -1
- package/docs/functions/_saltcorn_admin_models.tenant.deleteTenant.html +1 -1
- package/docs/functions/_saltcorn_admin_models.tenant.domain_sanitize.html +1 -1
- package/docs/functions/_saltcorn_admin_models.tenant.eachTenant.html +1 -1
- package/docs/functions/_saltcorn_admin_models.tenant.getAllTenantRows.html +1 -1
- package/docs/functions/_saltcorn_admin_models.tenant.getAllTenants.html +1 -1
- package/docs/functions/_saltcorn_admin_models.tenant.insertTenant.html +1 -1
- package/docs/functions/_saltcorn_admin_models.tenant.switchToTenant.html +1 -1
- package/docs/functions/_saltcorn_common_code.buildTableCaches.html +1 -1
- package/docs/functions/_saltcorn_common_code.parseLegacyRelation.html +1 -1
- package/docs/functions/_saltcorn_common_code.parseRelationPath.html +1 -1
- package/docs/functions/_saltcorn_data.models.config.check_email_mask.html +1 -1
- package/docs/functions/_saltcorn_data.models.config.deleteConfig.html +1 -1
- package/docs/functions/_saltcorn_data.models.config.getAllConfig.html +1 -1
- package/docs/functions/_saltcorn_data.models.config.getConfig.html +1 -1
- package/docs/functions/_saltcorn_data.models.config.get_base_url.html +1 -1
- package/docs/functions/_saltcorn_data.models.config.get_latest_npm_version.html +1 -1
- package/docs/functions/_saltcorn_data.models.config.remove_from_menu.html +1 -1
- package/docs/functions/_saltcorn_data.models.config.save_menu_items.html +1 -1
- package/docs/functions/_saltcorn_data.models.config.setConfig.html +1 -1
- package/docs/functions/_saltcorn_data.models.discovery.discover_tables.html +1 -1
- package/docs/functions/_saltcorn_data.models.discovery.discoverable_tables.html +1 -1
- package/docs/functions/_saltcorn_data.models.discovery.findType.html +1 -1
- package/docs/functions/_saltcorn_data.models.discovery.get_existing_views.html +1 -1
- package/docs/functions/_saltcorn_data.models.discovery.implement_discovery.html +1 -1
- package/docs/functions/_saltcorn_data.models.email.getMailTransport.html +1 -1
- package/docs/functions/_saltcorn_data.models.email.send_verification_email.html +1 -1
- package/docs/functions/_saltcorn_data.models.email.viewToEmailHtml.html +1 -1
- package/docs/functions/_saltcorn_data.models.expression.apply_calculated_fields.html +1 -1
- package/docs/functions/_saltcorn_data.models.expression.apply_calculated_fields_stored.html +1 -1
- package/docs/functions/_saltcorn_data.models.expression.eval_expression.html +1 -1
- package/docs/functions/_saltcorn_data.models.expression.expressionValidator.html +1 -1
- package/docs/functions/_saltcorn_data.models.expression.get_async_expression_function.html +1 -1
- package/docs/functions/_saltcorn_data.models.expression.get_expression_function.html +1 -1
- package/docs/functions/_saltcorn_data.models.expression.jsexprToWhere.html +1 -1
- package/docs/functions/_saltcorn_data.models.expression.recalculate_for_stored.html +1 -1
- package/docs/functions/_saltcorn_data.models.expression.transform_for_async.html +1 -1
- package/docs/functions/_saltcorn_data.models.layout.eachView.html +1 -1
- package/docs/functions/_saltcorn_data.models.layout.getStringsForI18n.html +1 -1
- package/docs/functions/_saltcorn_data.models.layout.getViews.html +1 -1
- package/docs/functions/_saltcorn_data.models.layout.translateLayout.html +1 -1
- package/docs/functions/_saltcorn_data.models.layout.traverse.html +1 -1
- package/docs/functions/_saltcorn_data.models.layout.traverseSync.html +1 -1
- package/docs/functions/_saltcorn_data.models.random.all_views.html +1 -1
- package/docs/functions/_saltcorn_data.models.random.fill_table_row.html +1 -1
- package/docs/functions/_saltcorn_data.models.random.initial_view.html +1 -1
- package/docs/functions/_saltcorn_data.models.random.random_table.html +1 -1
- package/docs/functions/_saltcorn_db_common.buildInsertBulkSql.html +1 -1
- package/docs/functions/_saltcorn_db_common.buildInsertSql.html +1 -1
- package/docs/functions/_saltcorn_db_common.doCount.html +1 -1
- package/docs/functions/_saltcorn_db_common.doDeleteWhere.html +1 -1
- package/docs/functions/_saltcorn_db_common.doListScTables.html +1 -1
- package/docs/functions/_saltcorn_db_common.doListTables.html +1 -1
- package/docs/functions/_saltcorn_db_common.doListUserDefinedTables.html +1 -1
- package/docs/functions/_saltcorn_db_common.do_add_index.html +1 -1
- package/docs/functions/_saltcorn_db_common.do_drop_index.html +1 -1
- package/docs/functions/_saltcorn_db_common.ftsFieldsSqlExpr.html +1 -1
- package/docs/functions/_saltcorn_db_common.mkSelectOptions.html +1 -1
- package/docs/functions/_saltcorn_db_common.mkVal.html +1 -1
- package/docs/functions/_saltcorn_db_common.mkWhere.html +1 -1
- package/docs/functions/_saltcorn_db_common.multi_tenant.enable_multi_tenant.html +1 -1
- package/docs/functions/_saltcorn_db_common.multi_tenant.getRequestContext.html +1 -1
- package/docs/functions/_saltcorn_db_common.multi_tenant.getTenantSchema.html +1 -1
- package/docs/functions/_saltcorn_db_common.multi_tenant.init.html +1 -1
- package/docs/functions/_saltcorn_db_common.multi_tenant.is_it_multi_tenant.html +1 -1
- package/docs/functions/_saltcorn_db_common.multi_tenant.runWithTenant.html +1 -1
- package/docs/functions/_saltcorn_db_common.orderByIsObject.html +1 -1
- package/docs/functions/_saltcorn_db_common.orderByIsOperator.html +1 -1
- package/docs/functions/_saltcorn_db_common.prefixFieldsInWhere.html +1 -1
- package/docs/functions/_saltcorn_db_common.reprAsJson.html +1 -1
- package/docs/functions/_saltcorn_db_common.slugify.html +1 -1
- package/docs/functions/_saltcorn_db_common.sqlBinOp.html +1 -1
- package/docs/functions/_saltcorn_db_common.sqlFun.html +1 -1
- package/docs/functions/_saltcorn_db_common.sqlsanitize.html +1 -1
- package/docs/functions/_saltcorn_db_common.sqlsanitizeAllowDots.html +1 -1
- package/docs/functions/_saltcorn_db_common.subSelectWhere.html +1 -1
- package/docs/functions/_saltcorn_db_common.tryCatchInTransaction.html +1 -1
- package/docs/functions/_saltcorn_db_common.withTransaction.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.androidFeatures.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.androidPermissions.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.buildTablesFile.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copyPrepopulatedDb.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copyServerFiles.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copyShareExtFiles.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copySiteLogo.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.copyTranslationFiles.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.createSqliteDb.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.decodeProvisioningProfile.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.extractDomain.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.generateAndroidVersionCode.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyAndroidManifest.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyConfigXml.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyGradleConfig.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyInfoPlist.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.modifyXcodeProjectFile.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepAppIcon.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareAppIcon.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareBuildDir.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareExportOptionsPlist.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareSplashIcon.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.prepareSplashPage.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writeCapacitorConfig.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writeCfgFile.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writeDataExtractionRules.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writeNetworkSecurityConfig.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writePodfile.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.common_build_utils.writePrivacyInfo.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.package_bundle_utils.bundleMobileAppCode.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.package_bundle_utils.bundlePackagesAndPlugins.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.package_bundle_utils.copyMobileAppDirs.html +1 -1
- package/docs/functions/_saltcorn_mobile_builder.package_bundle_utils.copyPublicDirs.html +1 -1
- package/docs/functions/_saltcorn_sqlite.add_index.html +1 -1
- package/docs/functions/_saltcorn_sqlite.add_unique_constraint.html +1 -1
- package/docs/functions/_saltcorn_sqlite.begin.html +1 -1
- package/docs/functions/_saltcorn_sqlite.changeConnection.html +1 -1
- package/docs/functions/_saltcorn_sqlite.close.html +1 -1
- package/docs/functions/_saltcorn_sqlite.commit.html +1 -1
- package/docs/functions/_saltcorn_sqlite.count.html +1 -1
- package/docs/functions/_saltcorn_sqlite.deleteWhere.html +1 -1
- package/docs/functions/_saltcorn_sqlite.dropTable.html +1 -1
- package/docs/functions/_saltcorn_sqlite.dropTables.html +1 -1
- package/docs/functions/_saltcorn_sqlite.drop_index.html +1 -1
- package/docs/functions/_saltcorn_sqlite.drop_reset_schema.html +1 -1
- package/docs/functions/_saltcorn_sqlite.drop_unique_constraint.html +1 -1
- package/docs/functions/_saltcorn_sqlite.getVersion.html +1 -1
- package/docs/functions/_saltcorn_sqlite.get_db_filepath.html +1 -1
- package/docs/functions/_saltcorn_sqlite.get_sql_logging.html +1 -1
- package/docs/functions/_saltcorn_sqlite.init.html +1 -1
- package/docs/functions/_saltcorn_sqlite.insert.html +1 -1
- package/docs/functions/_saltcorn_sqlite.listScTables.html +1 -1
- package/docs/functions/_saltcorn_sqlite.listTables.html +1 -1
- package/docs/functions/_saltcorn_sqlite.listUserDefinedTables.html +1 -1
- package/docs/functions/_saltcorn_sqlite.query.html +1 -1
- package/docs/functions/_saltcorn_sqlite.rollback.html +1 -1
- package/docs/functions/_saltcorn_sqlite.select.html +1 -1
- package/docs/functions/_saltcorn_sqlite.selectMaybeOne.html +1 -1
- package/docs/functions/_saltcorn_sqlite.selectOne.html +1 -1
- package/docs/functions/_saltcorn_sqlite.set_sql_logging.html +1 -1
- package/docs/functions/_saltcorn_sqlite.sql_log.html +1 -1
- package/docs/functions/_saltcorn_sqlite.update.html +1 -1
- package/docs/functions/_saltcorn_sqlite.updateWhere.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.add_index.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.add_unique_constraint.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.count.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.deleteWhere.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.drop_index.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.drop_reset_schema.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.drop_unique_constraint.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.init.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.insert.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.insertRows.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.listScTables.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.listTables.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.listUserDefinedTables.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.query.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.select.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.selectMaybeOne.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.selectOne.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.setConnectionObject.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.tableExists.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.time.html +1 -1
- package/docs/functions/_saltcorn_sqlite_mobile.update.html +1 -1
- package/docs/functions/_saltcorn_types.ModelAbstracts.abstract_field.instanceOfField.html +1 -1
- package/docs/functions/_saltcorn_types.ModelAbstracts.abstract_page.instanceOfPage.html +1 -1
- package/docs/functions/_saltcorn_types.ModelAbstracts.abstract_view.instanceOfView.html +1 -1
- package/docs/functions/_saltcorn_types.Types.base_types.instanceOWithHtmlFile.html +1 -1
- package/docs/functions/_saltcorn_types.Types.common_types.instanceOfErrorMsg.html +1 -1
- package/docs/functions/_saltcorn_types.Types.common_types.instanceOfSuccessMsg.html +1 -1
- package/docs/functions/_saltcorn_types.Types.common_types.instanceOfType.html +1 -1
- package/docs/functions/_saltcorn_types.generators.generateBool.html +1 -1
- package/docs/functions/_saltcorn_types.generators.generateString.html +1 -1
- package/docs/functions/_saltcorn_types.generators.num_between.html +1 -1
- package/docs/functions/_saltcorn_types.generators.oneOf.html +1 -1
- package/docs/interfaces/_saltcorn_mobile_builder.common_build_utils.ScCapacitorConfig.html +10 -10
- package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_field.AbstractField.html +15 -15
- package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_field.AbstractFieldRepeat.html +3 -3
- package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_form.AbstractForm.html +27 -27
- package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_page.AbstractPage.html +7 -7
- package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_role.AbstractRole.html +3 -3
- package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_table.AbstractTable.html +11 -11
- package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_trigger.AbstractTrigger.html +16 -16
- package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_view.AbstractView.html +10 -10
- package/docs/interfaces/_saltcorn_types.ModelAbstracts.abstract_workflow.AbstractWorkflow.html +13 -13
- package/docs/modules/_saltcorn_admin_models.backup.html +1 -1
- package/docs/modules/_saltcorn_admin_models.html +1 -1
- package/docs/modules/_saltcorn_admin_models.pack.html +1 -1
- package/docs/modules/_saltcorn_admin_models.tenant.html +1 -1
- package/docs/modules/_saltcorn_common_code.html +1 -1
- package/docs/modules/_saltcorn_data.html +3 -3
- package/docs/modules/_saltcorn_data.models.EventLog.html +2 -2
- package/docs/modules/_saltcorn_data.models.File.html +2 -2
- package/docs/modules/_saltcorn_data.models.Form.html +2 -2
- package/docs/modules/_saltcorn_data.models.PageGroup.html +2 -2
- package/docs/modules/_saltcorn_data.models.Table.html +2 -2
- package/docs/modules/_saltcorn_data.models.View.html +2 -2
- package/docs/modules/_saltcorn_data.models.config.html +1 -1
- package/docs/modules/_saltcorn_data.models.discovery.html +1 -1
- package/docs/modules/_saltcorn_data.models.email.html +1 -1
- package/docs/modules/_saltcorn_data.models.expression.html +1 -1
- package/docs/modules/_saltcorn_data.models.html +1 -1
- package/docs/modules/_saltcorn_data.models.layout.html +1 -1
- package/docs/modules/_saltcorn_data.models.random.html +1 -1
- package/docs/modules/_saltcorn_data.models.scheduler.html +1 -1
- package/docs/modules/_saltcorn_data.plugin_helper.html +1 -1
- package/docs/modules/_saltcorn_data.utils.html +1 -1
- package/docs/modules/_saltcorn_db_common.html +2 -2
- package/docs/modules/_saltcorn_db_common.multi_tenant.html +1 -1
- package/docs/modules/_saltcorn_markup.html +7 -7
- package/docs/modules/_saltcorn_mobile_builder.common_build_utils.html +1 -1
- package/docs/modules/_saltcorn_mobile_builder.html +1 -1
- package/docs/modules/_saltcorn_mobile_builder.package_bundle_utils.html +1 -1
- package/docs/modules/_saltcorn_sqlite.html +1 -1
- package/docs/modules/_saltcorn_sqlite_mobile.html +1 -1
- package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_field.html +1 -1
- package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_form.html +1 -1
- package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_library.html +1 -1
- package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_page.html +1 -1
- package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_plugin.html +1 -1
- package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_role.html +1 -1
- package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_table.html +1 -1
- package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_trigger.html +1 -1
- package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_view.html +1 -1
- package/docs/modules/_saltcorn_types.ModelAbstracts.abstract_workflow.html +1 -1
- package/docs/modules/_saltcorn_types.ModelAbstracts.html +1 -1
- package/docs/modules/_saltcorn_types.Types.base_types.html +1 -1
- package/docs/modules/_saltcorn_types.Types.common_types.html +1 -1
- package/docs/modules/_saltcorn_types.Types.html +1 -1
- package/docs/modules/_saltcorn_types.generators.html +1 -1
- package/docs/modules/_saltcorn_types.html +1 -1
- package/docs/types/_saltcorn_data.models.EventLog.EventLogCfg.html +1 -1
- package/docs/types/_saltcorn_data.models.File.FileCfg.html +1 -1
- package/docs/types/_saltcorn_data.models.Form.AdditionalButton.html +1 -1
- package/docs/types/_saltcorn_data.models.Form.FormCfg.html +1 -1
- package/docs/types/_saltcorn_data.models.PageGroup.ScreenInfoParams.html +1 -1
- package/docs/types/_saltcorn_data.models.Table.ChildRelations.html +1 -1
- package/docs/types/_saltcorn_data.models.Table.ParentRelations.html +1 -1
- package/docs/types/_saltcorn_data.models.Table.RelationData.html +1 -1
- package/docs/types/_saltcorn_data.models.View.FindViewsPred.html +1 -1
- package/docs/types/_saltcorn_db_common.AggregationOptions.html +1 -1
- package/docs/types/_saltcorn_db_common.CoordOpts.html +1 -1
- package/docs/types/_saltcorn_db_common.DatabaseClient.html +1 -1
- package/docs/types/_saltcorn_db_common.JoinField.html +1 -1
- package/docs/types/_saltcorn_db_common.JoinFields.html +1 -1
- package/docs/types/_saltcorn_db_common.JoinOptions.html +1 -1
- package/docs/types/_saltcorn_db_common.JsonPath.html +1 -1
- package/docs/types/_saltcorn_db_common.JsonPathElem.html +1 -1
- package/docs/types/_saltcorn_db_common.Operator.html +1 -1
- package/docs/types/_saltcorn_db_common.PartialSome.html +1 -1
- package/docs/types/_saltcorn_db_common.PrimaryKeyValue.html +1 -1
- package/docs/types/_saltcorn_db_common.Row.html +1 -1
- package/docs/types/_saltcorn_db_common.SelectOptions.html +1 -1
- package/docs/types/_saltcorn_db_common.SqlAndValues.html +1 -1
- package/docs/types/_saltcorn_db_common.StrongRow.html +1 -1
- package/docs/types/_saltcorn_db_common.SubselectOptions.html +1 -1
- package/docs/types/_saltcorn_db_common.Value.html +1 -1
- package/docs/types/_saltcorn_db_common.Where.html +1 -1
- package/docs/types/_saltcorn_mobile_builder.IosCfg.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_field.FieldCfg.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_field.InputType.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_form.AdditionalButton.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_library.LibraryCfg.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_library.LibraryPack.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_page.PageCfg.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_page.PagePack.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_plugin.PluginCfg.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_plugin.PluginPack.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_role.RoleCfg.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_role.RolePack.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_table.TableCfg.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_table.TablePack.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_trigger.TriggerCfg.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_trigger.TriggerPack.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_view.ViewCfg.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_view.ViewPack.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_workflow.ConfigWorkflowStep.html +1 -1
- package/docs/types/_saltcorn_types.ModelAbstracts.abstract_workflow.RunResult.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.Action.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.AuthenticationMethod.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.CalcJoinfield.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.CapacitorPlugin.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.CodePagePack.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.Column.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.ConnectObjType.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.ConnectedObjects.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.CopilotSkill.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.ErrorObj.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.FieldLike.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.FieldView.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.Header.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.JoinFieldOption.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.Layout.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.MobileConfig.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.ModelPattern.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.Pack.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.Plugin.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.PluginFunction.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.PluginLayout.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.PluginRoute.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.PluginSourceType.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.PluginType.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.PluginWrap.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.PluginWrapArg.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.RelationOption.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.Req.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.Res.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.ResultType.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.RouteAction.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.RunExtra.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.SlugStepType.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.StepResType.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.SubField.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.TableProvider.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.TableQuery.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.Tablely.html +1 -1
- package/docs/types/_saltcorn_types.Types.base_types.ViewTemplate.html +1 -1
- package/docs/types/_saltcorn_types.Types.common_types.ErrorMessage.html +1 -1
- package/docs/types/_saltcorn_types.Types.common_types.GenObj.html +1 -1
- package/docs/types/_saltcorn_types.Types.common_types.ReqRes.html +1 -1
- package/docs/types/_saltcorn_types.Types.common_types.ResultMessage.html +1 -1
- package/docs/types/_saltcorn_types.Types.common_types.SuccessMessage.html +1 -1
- package/docs/types/_saltcorn_types.Types.common_types.Type.html +1 -1
- package/docs/variables/_saltcorn_data.db.html +1 -1
- package/docs/variables/_saltcorn_data.migrations.html +1 -1
- package/docs/variables/_saltcorn_data.models.config.available_languages.html +1 -1
- package/docs/variables/_saltcorn_data.models.config.configTypes.html +1 -1
- package/docs/variables/_saltcorn_data.models.scheduler.runScheduler.html +1 -1
- package/docs/variables/_saltcorn_data.plugin_helper.run_action_column.html +1 -1
- package/docs/variables/_saltcorn_data.utils.NotAuthorized.html +1 -1
- package/docs/variables/_saltcorn_data.utils.sleep.html +1 -1
- package/docs/variables/_saltcorn_db_common.multi_tenant.tenantNamespace.html +1 -1
- package/locales/en.json +5 -1
- package/package.json +10 -10
- package/public/saltcorn-common.js +114 -0
- package/public/saltcorn.js +14 -3
- package/public/serviceworker.js +11 -0
- package/routes/admin.js +56 -1
- package/routes/fields.js +10 -0
- package/routes/notifications.js +141 -4
- package/routes/search.js +23 -2
- package/routes/tables.js +1 -0
- package/serve.js +29 -6
- package/tests/plugin_install.test.js +1 -1
- package/wrapper.js +18 -0
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
<h1>Variable NotAuthorized</h1></div>
|
|
20
20
|
<div class="tsd-signature"><span class="tsd-kind-variable">Not<wbr/>Authorized</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">any</span></div><aside class="tsd-sources">
|
|
21
21
|
<ul>
|
|
22
|
-
<li>Defined in <a href="https://github.com/saltcorn/saltcorn/blob/
|
|
22
|
+
<li>Defined in <a href="https://github.com/saltcorn/saltcorn/blob/a072fcff0e/packages/saltcorn-data/index.ts#L20">saltcorn-data/index.ts:20</a></li></ul></aside></div>
|
|
23
23
|
<div class="col-sidebar">
|
|
24
24
|
<div class="page-menu">
|
|
25
25
|
<div class="tsd-navigation settings">
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
<h1>Variable sleep</h1></div>
|
|
20
20
|
<div class="tsd-signature"><span class="tsd-kind-variable">sleep</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">any</span></div><aside class="tsd-sources">
|
|
21
21
|
<ul>
|
|
22
|
-
<li>Defined in <a href="https://github.com/saltcorn/saltcorn/blob/
|
|
22
|
+
<li>Defined in <a href="https://github.com/saltcorn/saltcorn/blob/a072fcff0e/packages/saltcorn-data/index.ts#L20">saltcorn-data/index.ts:20</a></li></ul></aside></div>
|
|
23
23
|
<div class="col-sidebar">
|
|
24
24
|
<div class="page-menu">
|
|
25
25
|
<div class="tsd-navigation settings">
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
<h1>Variable tenantNamespace<code class="tsd-tag ts-flagConst">Const</code> </h1></div>
|
|
20
20
|
<div class="tsd-signature"><span class="tsd-kind-variable">tenant<wbr/>Namespace</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type ">AsyncLocalStorage</span><span class="tsd-signature-symbol"><</span><span class="tsd-signature-type ">RequestContext</span><span class="tsd-signature-symbol">></span><span class="tsd-signature-symbol"> = ...</span></div><aside class="tsd-sources">
|
|
21
21
|
<ul>
|
|
22
|
-
<li>Defined in <a href="https://github.com/saltcorn/saltcorn/blob/
|
|
22
|
+
<li>Defined in <a href="https://github.com/saltcorn/saltcorn/blob/a072fcff0e/packages/db-common/multi-tenant.ts#L17">db-common/multi-tenant.ts:17</a></li></ul></aside></div>
|
|
23
23
|
<div class="col-sidebar">
|
|
24
24
|
<div class="page-menu">
|
|
25
25
|
<div class="tsd-navigation settings">
|
package/locales/en.json
CHANGED
|
@@ -1619,5 +1619,9 @@
|
|
|
1619
1619
|
"Decimal places": "Decimal places",
|
|
1620
1620
|
"%s view - %s": "%s view - %s",
|
|
1621
1621
|
"Password to encrypt the backup file. Leave empty for no encryption": "Password to encrypt the backup file. Leave empty for no encryption",
|
|
1622
|
-
"Show full error to user on crash, enable editing field type": "Show full error to user on crash, enable editing field type"
|
|
1622
|
+
"Show full error to user on crash, enable editing field type": "Show full error to user on crash, enable editing field type",
|
|
1623
|
+
"Shown to the user if foreign key constraint is violated": "Shown to the user if foreign key constraint is violated",
|
|
1624
|
+
"Button Style": "Button Style",
|
|
1625
|
+
"Disable full-text search": "Disable full-text search",
|
|
1626
|
+
"Use LIKE instead of tsvector. Use to match against phrase in the middle of a word.": "Use LIKE instead of tsvector. Use to match against phrase in the middle of a word."
|
|
1623
1627
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/server",
|
|
3
|
-
"version": "1.3.0-beta.
|
|
3
|
+
"version": "1.3.0-beta.14",
|
|
4
4
|
"description": "Server app for Saltcorn, open-source no-code platform",
|
|
5
5
|
"homepage": "https://saltcorn.com",
|
|
6
6
|
"main": "index.js",
|
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@aws-sdk/client-s3": "^3.735.0",
|
|
10
10
|
"@dr.pogodin/csurf": "1.15.0",
|
|
11
|
-
"@saltcorn/admin-models": "1.3.0-beta.
|
|
12
|
-
"@saltcorn/base-plugin": "1.3.0-beta.
|
|
13
|
-
"@saltcorn/builder": "1.3.0-beta.
|
|
14
|
-
"@saltcorn/data": "1.3.0-beta.
|
|
15
|
-
"@saltcorn/filemanager": "1.3.0-beta.
|
|
16
|
-
"@saltcorn/markup": "1.3.0-beta.
|
|
17
|
-
"@saltcorn/plugins-loader": "1.3.0-beta.
|
|
18
|
-
"@saltcorn/sbadmin2": "1.3.0-beta.
|
|
11
|
+
"@saltcorn/admin-models": "1.3.0-beta.14",
|
|
12
|
+
"@saltcorn/base-plugin": "1.3.0-beta.14",
|
|
13
|
+
"@saltcorn/builder": "1.3.0-beta.14",
|
|
14
|
+
"@saltcorn/data": "1.3.0-beta.14",
|
|
15
|
+
"@saltcorn/filemanager": "1.3.0-beta.14",
|
|
16
|
+
"@saltcorn/markup": "1.3.0-beta.14",
|
|
17
|
+
"@saltcorn/plugins-loader": "1.3.0-beta.14",
|
|
18
|
+
"@saltcorn/sbadmin2": "1.3.0-beta.14",
|
|
19
19
|
"@socket.io/cluster-adapter": "^0.2.1",
|
|
20
20
|
"@socket.io/sticky": "^1.0.1",
|
|
21
21
|
"adm-zip": "0.5.16",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
},
|
|
73
73
|
"repository": "github:saltcorn/saltcorn",
|
|
74
74
|
"devDependencies": {
|
|
75
|
-
"jest": "
|
|
75
|
+
"jest": "29.7.0",
|
|
76
76
|
"jest-environment-jsdom": "29.7.0",
|
|
77
77
|
"supertest": "7.0.0"
|
|
78
78
|
},
|
|
@@ -2428,3 +2428,117 @@ const observer = new IntersectionObserver(
|
|
|
2428
2428
|
document.querySelectorAll("[data-animate]").forEach((element) => {
|
|
2429
2429
|
observer.observe(element);
|
|
2430
2430
|
});
|
|
2431
|
+
|
|
2432
|
+
function isPWA() {
|
|
2433
|
+
if (!window.matchMedia) return false;
|
|
2434
|
+
const isStandaloneDisplay = window.matchMedia(
|
|
2435
|
+
"(display-mode: standalone)"
|
|
2436
|
+
).matches;
|
|
2437
|
+
const isStandaloneNavigator = window.navigator.standalone === true; // iOS Safari
|
|
2438
|
+
const isTrustedDisplayMode = ["fullscreen", "standalone", "minimal-ui"].some(
|
|
2439
|
+
(mode) => window.matchMedia(`(display-mode: ${mode})`).matches
|
|
2440
|
+
);
|
|
2441
|
+
return isStandaloneDisplay || isStandaloneNavigator || isTrustedDisplayMode;
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2444
|
+
const subscribeHelper = (config, swReg) => {
|
|
2445
|
+
if (!config.vapidPublicKey) throw new Error("VAPID public key is missing");
|
|
2446
|
+
|
|
2447
|
+
function urlBase64ToUint8Array(base64String) {
|
|
2448
|
+
const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
|
|
2449
|
+
const base64 = (base64String + padding)
|
|
2450
|
+
.replace(/\-/g, "+")
|
|
2451
|
+
.replace(/_/g, "/");
|
|
2452
|
+
|
|
2453
|
+
const rawData = atob(base64);
|
|
2454
|
+
const outputArray = new Uint8Array(rawData.length);
|
|
2455
|
+
|
|
2456
|
+
for (let i = 0; i < rawData.length; ++i) {
|
|
2457
|
+
outputArray[i] = rawData.charCodeAt(i);
|
|
2458
|
+
}
|
|
2459
|
+
return outputArray;
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
const subscribe = async () => {
|
|
2463
|
+
const subscription = await swReg.pushManager.subscribe({
|
|
2464
|
+
userVisibleOnly: true,
|
|
2465
|
+
applicationServerKey: urlBase64ToUint8Array(config.vapidPublicKey),
|
|
2466
|
+
});
|
|
2467
|
+
return subscription;
|
|
2468
|
+
};
|
|
2469
|
+
|
|
2470
|
+
const uploadSubscription = async (subscription) => {
|
|
2471
|
+
const response = await fetch("/notifications/subscribe", {
|
|
2472
|
+
method: "POST",
|
|
2473
|
+
body: JSON.stringify(subscription),
|
|
2474
|
+
headers: {
|
|
2475
|
+
"Content-Type": "application/json",
|
|
2476
|
+
"CSRF-Token": _sc_globalCsrf,
|
|
2477
|
+
},
|
|
2478
|
+
});
|
|
2479
|
+
if (response.status === 200) {
|
|
2480
|
+
const data = await response.json();
|
|
2481
|
+
console.log("Subscription uploaded successfully:", data);
|
|
2482
|
+
} else console.error("Failed to upload subscription:", response.statusText);
|
|
2483
|
+
};
|
|
2484
|
+
|
|
2485
|
+
const removeSubscription = async (subscription) => {
|
|
2486
|
+
const response = await fetch("/notifications/remove-subscription", {
|
|
2487
|
+
method: "POST",
|
|
2488
|
+
body: JSON.stringify(subscription),
|
|
2489
|
+
headers: {
|
|
2490
|
+
"Content-Type": "application/json",
|
|
2491
|
+
"CSRF-Token": _sc_globalCsrf,
|
|
2492
|
+
},
|
|
2493
|
+
});
|
|
2494
|
+
if (response.status === 200) {
|
|
2495
|
+
console.log("Subscription removed successfully");
|
|
2496
|
+
} else {
|
|
2497
|
+
console.error("Failed to remove subscription:", response.statusText);
|
|
2498
|
+
}
|
|
2499
|
+
};
|
|
2500
|
+
|
|
2501
|
+
return {
|
|
2502
|
+
handle: async () => {
|
|
2503
|
+
const enabled = config?.enabled && config.userEnabled;
|
|
2504
|
+
let currentSub = await swReg.pushManager.getSubscription();
|
|
2505
|
+
if (!enabled) {
|
|
2506
|
+
if (currentSub) {
|
|
2507
|
+
await currentSub.unsubscribe();
|
|
2508
|
+
await removeSubscription(currentSub);
|
|
2509
|
+
}
|
|
2510
|
+
} else {
|
|
2511
|
+
if (
|
|
2512
|
+
currentSub &&
|
|
2513
|
+
!config.endpoints.find((endpoint) => endpoint === currentSub.endpoint)
|
|
2514
|
+
) {
|
|
2515
|
+
console.log(
|
|
2516
|
+
"Current subscription does not exist server-side, renewing..."
|
|
2517
|
+
);
|
|
2518
|
+
await currentSub.unsubscribe();
|
|
2519
|
+
currentSub = null;
|
|
2520
|
+
}
|
|
2521
|
+
|
|
2522
|
+
if (!currentSub) {
|
|
2523
|
+
const permission = await Notification.requestPermission();
|
|
2524
|
+
if (permission !== "granted")
|
|
2525
|
+
throw new Error(`Push permission denied ${permission}`);
|
|
2526
|
+
const newSub = await subscribe();
|
|
2527
|
+
await uploadSubscription(newSub);
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
},
|
|
2531
|
+
};
|
|
2532
|
+
};
|
|
2533
|
+
|
|
2534
|
+
async function initPushNotify() {
|
|
2535
|
+
try {
|
|
2536
|
+
const webPushConfig = window.push_notify_cfg;
|
|
2537
|
+
if (webPushConfig) {
|
|
2538
|
+
const swReg = await navigator.serviceWorker.ready;
|
|
2539
|
+
await subscribeHelper(webPushConfig, swReg).handle();
|
|
2540
|
+
}
|
|
2541
|
+
} catch (error) {
|
|
2542
|
+
console.error("Push notification initialization failed:", error);
|
|
2543
|
+
}
|
|
2544
|
+
}
|
package/public/saltcorn.js
CHANGED
|
@@ -158,14 +158,16 @@ function invalidate_pagings(href) {
|
|
|
158
158
|
|
|
159
159
|
function set_state_fields(kvs, disable_pjax, e) {
|
|
160
160
|
let newhref = get_current_state_url(e);
|
|
161
|
+
const oldhref = newhref;
|
|
161
162
|
if (Object.keys(kvs).some((k) => !is_paging_param(k))) {
|
|
162
163
|
newhref = invalidate_pagings(newhref);
|
|
163
164
|
}
|
|
164
165
|
Object.entries(kvs).forEach((kv) => {
|
|
165
|
-
if (kv[1]
|
|
166
|
+
if (kv[1]?.unset && kv[1]?.unset === true)
|
|
166
167
|
newhref = removeQueryStringParameter(newhref, kv[0]);
|
|
167
168
|
else newhref = updateQueryStringParameter(newhref, kv[0], kv[1]);
|
|
168
169
|
});
|
|
170
|
+
if (newhref === oldhref) return;
|
|
169
171
|
if (disable_pjax) href_to(newhref.replace("&&", "&").replace("?&", "?"));
|
|
170
172
|
else pjax_to(newhref.replace("&&", "&").replace("?&", "?"), e);
|
|
171
173
|
}
|
|
@@ -1241,6 +1243,15 @@ window.addEventListener("beforeinstallprompt", (e) => {
|
|
|
1241
1243
|
defferedPrompt = e;
|
|
1242
1244
|
});
|
|
1243
1245
|
|
|
1246
|
+
window.addEventListener("appinstalled", async (event) => {
|
|
1247
|
+
console.log("App was installed.", event);
|
|
1248
|
+
await initPushNotify();
|
|
1249
|
+
});
|
|
1250
|
+
|
|
1251
|
+
document.addEventListener("DOMContentLoaded", async () => {
|
|
1252
|
+
await initPushNotify();
|
|
1253
|
+
});
|
|
1254
|
+
|
|
1244
1255
|
function isAndroidMobile() {
|
|
1245
1256
|
const ua = navigator.userAgent || navigator.vendor || window.opera;
|
|
1246
1257
|
return /android/i.test(ua) && /mobile/i.test(ua);
|
|
@@ -1439,14 +1450,14 @@ function cfu_translate(that) {
|
|
|
1439
1450
|
l = function (a, b) {
|
|
1440
1451
|
d = setTimeout(function () {
|
|
1441
1452
|
d = !1;
|
|
1442
|
-
if (h || c) e.apply(a, b), c && (j = +new Date());
|
|
1453
|
+
if (h || c) (e.apply(a, b), c && (j = +new Date()));
|
|
1443
1454
|
i && g.apply(a, b);
|
|
1444
1455
|
}, f);
|
|
1445
1456
|
},
|
|
1446
1457
|
k = function () {
|
|
1447
1458
|
if (!d || a) {
|
|
1448
1459
|
if (!d && !h && (!c || +new Date() - j > f))
|
|
1449
|
-
e.apply(this, arguments), c && (j = +new Date());
|
|
1460
|
+
(e.apply(this, arguments), c && (j = +new Date()));
|
|
1450
1461
|
(a || !c) && clearTimeout(d);
|
|
1451
1462
|
l(this, arguments);
|
|
1452
1463
|
}
|
package/public/serviceworker.js
CHANGED
|
@@ -3,3 +3,14 @@
|
|
|
3
3
|
self.addEventListener("fetch", function () {
|
|
4
4
|
return;
|
|
5
5
|
});
|
|
6
|
+
|
|
7
|
+
self.addEventListener("push", function (event) {
|
|
8
|
+
const data = event.data.json();
|
|
9
|
+
event.waitUntil(
|
|
10
|
+
self.registration.showNotification(data.title, {
|
|
11
|
+
body: data.body,
|
|
12
|
+
icon: data.icon,
|
|
13
|
+
badge: data.badge,
|
|
14
|
+
})
|
|
15
|
+
);
|
|
16
|
+
});
|
package/routes/admin.js
CHANGED
|
@@ -4501,6 +4501,28 @@ admin_config_route({
|
|
|
4501
4501
|
name: "pwa_icons",
|
|
4502
4502
|
showIf: { pwa_enabled: true },
|
|
4503
4503
|
},
|
|
4504
|
+
{ section_header: "Push Notifications" },
|
|
4505
|
+
"enable_push_notify",
|
|
4506
|
+
{
|
|
4507
|
+
name: "vapid_public_key",
|
|
4508
|
+
showIf: { enable_push_notify: true },
|
|
4509
|
+
},
|
|
4510
|
+
{
|
|
4511
|
+
name: "vapid_private_key",
|
|
4512
|
+
showIf: { enable_push_notify: true },
|
|
4513
|
+
},
|
|
4514
|
+
{
|
|
4515
|
+
name: "vapid_email",
|
|
4516
|
+
showIf: { enable_push_notify: true },
|
|
4517
|
+
},
|
|
4518
|
+
{
|
|
4519
|
+
name: "push_notification_icon",
|
|
4520
|
+
showIf: { enable_push_notify: true },
|
|
4521
|
+
},
|
|
4522
|
+
{
|
|
4523
|
+
name: "push_notification_badge",
|
|
4524
|
+
showIf: { enable_push_notify: true },
|
|
4525
|
+
},
|
|
4504
4526
|
],
|
|
4505
4527
|
response(form, req, res) {
|
|
4506
4528
|
send_admin_page({
|
|
@@ -4511,7 +4533,40 @@ admin_config_route({
|
|
|
4511
4533
|
type: "card",
|
|
4512
4534
|
title: req.__("Notification settings"),
|
|
4513
4535
|
titleAjaxIndicator: true,
|
|
4514
|
-
contents: [
|
|
4536
|
+
contents: [
|
|
4537
|
+
renderForm(form, req.csrfToken()) +
|
|
4538
|
+
button(
|
|
4539
|
+
{
|
|
4540
|
+
id: "generate-vapid-keys-btn",
|
|
4541
|
+
class: "btn btn-primary d-none",
|
|
4542
|
+
onclick:
|
|
4543
|
+
"if (confirm('Are you sure? The old keys will be lost, and existing subscriptions will be deleted.')) ajax_post_btn('/notifications/generate-vapid-keys', true)",
|
|
4544
|
+
},
|
|
4545
|
+
"Generate VAPID keys"
|
|
4546
|
+
) +
|
|
4547
|
+
script(
|
|
4548
|
+
domReady(`
|
|
4549
|
+
const fn = () => {
|
|
4550
|
+
const pushEnabled = document.getElementById("inputenable_push_notify");
|
|
4551
|
+
const generateBtn = document.getElementById("generate-vapid-keys-btn");
|
|
4552
|
+
if (pushEnabled && pushEnabled.checked) {
|
|
4553
|
+
generateBtn.classList.remove("d-none");
|
|
4554
|
+
generateBtn.classList.add("d-inline");
|
|
4555
|
+
}
|
|
4556
|
+
else {
|
|
4557
|
+
generateBtn.classList.remove("d-inline");
|
|
4558
|
+
generateBtn.classList.add("d-none");
|
|
4559
|
+
}
|
|
4560
|
+
};
|
|
4561
|
+
setTimeout(fn, 0);
|
|
4562
|
+
const mainForm = document.querySelector("form[action='/admin/notifications']");
|
|
4563
|
+
if (mainForm) {
|
|
4564
|
+
mainForm.addEventListener("change", (e) => {
|
|
4565
|
+
fn();
|
|
4566
|
+
});
|
|
4567
|
+
}`)
|
|
4568
|
+
),
|
|
4569
|
+
],
|
|
4515
4570
|
},
|
|
4516
4571
|
});
|
|
4517
4572
|
},
|
package/routes/fields.js
CHANGED
|
@@ -251,6 +251,7 @@ const fieldFlow = (req) =>
|
|
|
251
251
|
attributes.include_fts = context.include_fts;
|
|
252
252
|
attributes.on_delete_cascade = context.on_delete_cascade;
|
|
253
253
|
attributes.on_delete = context.on_delete;
|
|
254
|
+
attributes.fkey_error_msg = context.fkey_error_msg;
|
|
254
255
|
attributes.unique_error_msg = context.unique_error_msg;
|
|
255
256
|
if (context.protected) attributes.min_role_write = context.min_role_write;
|
|
256
257
|
else attributes.min_role_write = undefined;
|
|
@@ -723,6 +724,15 @@ const fieldFlow = (req) =>
|
|
|
723
724
|
"If the parent row is deleted, do this to the child rows."
|
|
724
725
|
),
|
|
725
726
|
}),
|
|
727
|
+
new Field({
|
|
728
|
+
name: "fkey_error_msg",
|
|
729
|
+
label: req.__("Error message"),
|
|
730
|
+
type: "String",
|
|
731
|
+
sublabel: req.__(
|
|
732
|
+
"Shown to the user if foreign key constraint is violated"
|
|
733
|
+
),
|
|
734
|
+
showIf: { on_delete: "Fail" },
|
|
735
|
+
}),
|
|
726
736
|
],
|
|
727
737
|
});
|
|
728
738
|
},
|
package/routes/notifications.js
CHANGED
|
@@ -32,14 +32,23 @@ router.use(
|
|
|
32
32
|
})
|
|
33
33
|
);
|
|
34
34
|
|
|
35
|
-
const notificationSettingsForm = () =>
|
|
36
|
-
|
|
35
|
+
const notificationSettingsForm = () => {
|
|
36
|
+
const fields = [{ name: "notify_email", label: "Email", type: "Bool" }];
|
|
37
|
+
if (getState().getConfig("enable_push_notify", false))
|
|
38
|
+
fields.push({
|
|
39
|
+
name: "notify_push",
|
|
40
|
+
label: "Push",
|
|
41
|
+
type: "Bool",
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return new Form({
|
|
37
45
|
action: `/notifications/settings`,
|
|
38
46
|
noSubmitButton: true,
|
|
39
47
|
onChange: `saveAndContinue(this)`,
|
|
40
48
|
labelCols: 4,
|
|
41
|
-
fields
|
|
49
|
+
fields,
|
|
42
50
|
});
|
|
51
|
+
};
|
|
43
52
|
|
|
44
53
|
router.get(
|
|
45
54
|
"/",
|
|
@@ -67,7 +76,10 @@ router.get(
|
|
|
67
76
|
|
|
68
77
|
const form = notificationSettingsForm();
|
|
69
78
|
const user = await User.findOne({ id: req.user?.id });
|
|
70
|
-
form.values = {
|
|
79
|
+
form.values = {
|
|
80
|
+
notify_email: user?._attributes?.notify_email,
|
|
81
|
+
notify_push: user?._attributes?.notify_push,
|
|
82
|
+
};
|
|
71
83
|
const notifyCards = nots.length
|
|
72
84
|
? nots.map((not) => ({
|
|
73
85
|
type: "card",
|
|
@@ -185,6 +197,16 @@ router.post(
|
|
|
185
197
|
form.validate(req.body || {});
|
|
186
198
|
const _attributes = { ...user._attributes, ...form.values };
|
|
187
199
|
await user.update({ _attributes });
|
|
200
|
+
const pushEnabled = !!_attributes.notify_push;
|
|
201
|
+
const allSubs = getState().getConfig("push_notification_subscriptions", {});
|
|
202
|
+
const newSubs = { ...allSubs };
|
|
203
|
+
if (!pushEnabled && newSubs[req.user.id]) {
|
|
204
|
+
delete newSubs[req.user.id];
|
|
205
|
+
await getState().setConfig("push_notification_subscriptions", newSubs);
|
|
206
|
+
} else if (pushEnabled && !newSubs[req.user.id]) {
|
|
207
|
+
newSubs[req.user.id] = [];
|
|
208
|
+
await getState().setConfig("push_notification_subscriptions", newSubs);
|
|
209
|
+
}
|
|
188
210
|
res.json({ success: "ok" });
|
|
189
211
|
})
|
|
190
212
|
);
|
|
@@ -248,6 +270,121 @@ router.post(
|
|
|
248
270
|
})
|
|
249
271
|
);
|
|
250
272
|
|
|
273
|
+
router.post(
|
|
274
|
+
"/subscribe",
|
|
275
|
+
loggedIn,
|
|
276
|
+
error_catcher(async (req, res) => {
|
|
277
|
+
const enabled = getState().getConfig("enable_push_notify", false);
|
|
278
|
+
if (!enabled) {
|
|
279
|
+
res.status(403).json({
|
|
280
|
+
error: req.__("Notifications are not enabled on this server"),
|
|
281
|
+
});
|
|
282
|
+
} else {
|
|
283
|
+
const user = req.user;
|
|
284
|
+
const allSubs = getState().getConfig(
|
|
285
|
+
"push_notification_subscriptions",
|
|
286
|
+
{}
|
|
287
|
+
);
|
|
288
|
+
const userSubs = allSubs[user.id] || [];
|
|
289
|
+
const existingSub = userSubs.find(
|
|
290
|
+
(s) =>
|
|
291
|
+
s.endpoint === req.body.endpoint &&
|
|
292
|
+
s.keys.p256dh === req.body.keys.p256dh &&
|
|
293
|
+
s.keys.auth === req.body.keys.auth
|
|
294
|
+
);
|
|
295
|
+
if (existingSub) {
|
|
296
|
+
res.json({
|
|
297
|
+
success: "ok",
|
|
298
|
+
message: req.__("Subscribed to notifications"),
|
|
299
|
+
});
|
|
300
|
+
} else {
|
|
301
|
+
userSubs.push({
|
|
302
|
+
endpoint: req.body.endpoint,
|
|
303
|
+
keys: {
|
|
304
|
+
auth: req.body.keys.auth,
|
|
305
|
+
p256dh: req.body.keys.p256dh,
|
|
306
|
+
},
|
|
307
|
+
});
|
|
308
|
+
await getState().setConfig("push_notification_subscriptions", {
|
|
309
|
+
...allSubs,
|
|
310
|
+
[user.id]: userSubs,
|
|
311
|
+
});
|
|
312
|
+
res.json({
|
|
313
|
+
success: "ok",
|
|
314
|
+
message: req.__("Subscribed to notifications"),
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
})
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
router.post(
|
|
322
|
+
"/remove-subscription",
|
|
323
|
+
loggedIn,
|
|
324
|
+
error_catcher(async (req, res) => {
|
|
325
|
+
const enabled = getState().getConfig("enable_push_notify", false);
|
|
326
|
+
if (!enabled) {
|
|
327
|
+
res.status(403).json({
|
|
328
|
+
error: req.__("Notifications are not enabled on this server"),
|
|
329
|
+
});
|
|
330
|
+
} else {
|
|
331
|
+
const { subscription } = req.body;
|
|
332
|
+
const user = req.user;
|
|
333
|
+
const oldSubs = getState().getConfig(
|
|
334
|
+
"push_notification_subscriptions",
|
|
335
|
+
{}
|
|
336
|
+
);
|
|
337
|
+
let userSubs = oldSubs[user.id];
|
|
338
|
+
if (userSubs) {
|
|
339
|
+
userSubs = userSubs.filter(
|
|
340
|
+
(s) =>
|
|
341
|
+
s.endpoint !== subscription.endpoint ||
|
|
342
|
+
s.keys.p256dh !== subscription.keys.p256dh ||
|
|
343
|
+
s.keys.auth !== subscription.keys.auth
|
|
344
|
+
);
|
|
345
|
+
await getState().setConfig("push_notification_subscriptions", {
|
|
346
|
+
...oldSubs,
|
|
347
|
+
[user.id]: userSubs,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
res.json({
|
|
351
|
+
success: "ok",
|
|
352
|
+
message: req.__("Unsubscribed from notifications"),
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
})
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
router.post(
|
|
359
|
+
"/generate-vapid-keys",
|
|
360
|
+
isAdmin,
|
|
361
|
+
error_catcher(async (req, res) => {
|
|
362
|
+
const enabled = getState().getConfig("enable_push_notify", false);
|
|
363
|
+
if (!enabled) {
|
|
364
|
+
res.status(403).json({
|
|
365
|
+
error: req.__("Notifications are not enabled on this server"),
|
|
366
|
+
});
|
|
367
|
+
} else {
|
|
368
|
+
const webPush = require("web-push");
|
|
369
|
+
const vapidKeys = webPush.generateVAPIDKeys();
|
|
370
|
+
await getState().setConfig("vapid_public_key", vapidKeys.publicKey);
|
|
371
|
+
await getState().setConfig("vapid_private_key", vapidKeys.privateKey);
|
|
372
|
+
const allSubs = getState().setConfig(
|
|
373
|
+
"push_notification_subscriptions",
|
|
374
|
+
{}
|
|
375
|
+
);
|
|
376
|
+
const newSubs = {};
|
|
377
|
+
for (const k of Object.keys(allSubs)) {
|
|
378
|
+
newSubs[k] = [];
|
|
379
|
+
}
|
|
380
|
+
await getState().setConfig("push_notification_subscriptions", newSubs);
|
|
381
|
+
res.json({
|
|
382
|
+
success: "ok",
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
})
|
|
386
|
+
);
|
|
387
|
+
|
|
251
388
|
router.get(
|
|
252
389
|
"/manifest.json{:opt_cache_bust}",
|
|
253
390
|
error_catcher(async (req, res) => {
|
package/routes/search.js
CHANGED
|
@@ -71,6 +71,14 @@ const searchConfigForm = (tables, views, req) => {
|
|
|
71
71
|
input_type: "select",
|
|
72
72
|
options: ["Cards", "Tabs"],
|
|
73
73
|
});
|
|
74
|
+
fields.push({
|
|
75
|
+
name: "search_disable_fts",
|
|
76
|
+
label: req.__("Disable full-text search"),
|
|
77
|
+
type: "Bool",
|
|
78
|
+
sublabel: req.__(
|
|
79
|
+
"Use LIKE instead of tsvector. Use to match against phrase in the middle of a word."
|
|
80
|
+
),
|
|
81
|
+
});
|
|
74
82
|
const blurb1 = req.__(
|
|
75
83
|
`Choose views for <a href="/search">search results</a> for each table.<br/>Set to blank to omit table from global search.`
|
|
76
84
|
);
|
|
@@ -112,6 +120,10 @@ router.get(
|
|
|
112
120
|
"search_results_decoration",
|
|
113
121
|
"Cards"
|
|
114
122
|
);
|
|
123
|
+
form.values.search_disable_fts = getState().getConfig(
|
|
124
|
+
"search_disable_fts",
|
|
125
|
+
true
|
|
126
|
+
);
|
|
115
127
|
send_infoarch_page({
|
|
116
128
|
res,
|
|
117
129
|
req,
|
|
@@ -154,6 +166,10 @@ router.post(
|
|
|
154
166
|
"search_results_decoration",
|
|
155
167
|
result.success.search_results_decoration || "Cards"
|
|
156
168
|
);
|
|
169
|
+
await getState().setConfig(
|
|
170
|
+
"search_disable_fts",
|
|
171
|
+
result.success.search_disable_fts || false
|
|
172
|
+
);
|
|
157
173
|
await getState().setConfig("search_use_websearch", +dbversion >= 11.0);
|
|
158
174
|
delete result.success.search_table_description;
|
|
159
175
|
delete result.success.search_results_decoration;
|
|
@@ -235,7 +251,9 @@ const runSearch = async ({ q, _page, table }, req, res) => {
|
|
|
235
251
|
viewName === "search_table_description" ||
|
|
236
252
|
tableName === "search_table_description" ||
|
|
237
253
|
viewName === "search_results_decoration" ||
|
|
238
|
-
tableName === "search_results_decoration"
|
|
254
|
+
tableName === "search_results_decoration" ||
|
|
255
|
+
viewName === "search_disable_fts" ||
|
|
256
|
+
tableName === "search_disable_fts"
|
|
239
257
|
)
|
|
240
258
|
continue;
|
|
241
259
|
tablesConfigured += 1;
|
|
@@ -367,7 +385,10 @@ router.get(
|
|
|
367
385
|
"/",
|
|
368
386
|
error_catcher(async (req, res, next) => {
|
|
369
387
|
const state = getState();
|
|
370
|
-
const maintenanceModeEnabled = state.getConfig(
|
|
388
|
+
const maintenanceModeEnabled = state.getConfig(
|
|
389
|
+
"maintenance_mode_enabled",
|
|
390
|
+
false
|
|
391
|
+
);
|
|
371
392
|
|
|
372
393
|
if (maintenanceModeEnabled && (!req.user || req.user.role_id > 1)) {
|
|
373
394
|
res.status(503).send("Page Unavailable: in maintenance mode");
|
package/routes/tables.js
CHANGED
package/serve.js
CHANGED
|
@@ -111,7 +111,8 @@ const ensurePluginsFolder = async () => {
|
|
|
111
111
|
const pluginDir = path.join(
|
|
112
112
|
rootFolder,
|
|
113
113
|
plugin.source === "git" ? "git_plugins" : "plugins_folder",
|
|
114
|
-
...tokens
|
|
114
|
+
...tokens,
|
|
115
|
+
plugin.version || "unknownversion"
|
|
115
116
|
);
|
|
116
117
|
allPluginFolders.add(pluginDir);
|
|
117
118
|
}
|
|
@@ -142,6 +143,29 @@ const ensurePluginsFolder = async () => {
|
|
|
142
143
|
}
|
|
143
144
|
};
|
|
144
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Users with push_notify enabled store subscription in push_notification_subscriptions
|
|
148
|
+
* This function ensures that enabled users at least have an empty array
|
|
149
|
+
* and disabled users have no entry
|
|
150
|
+
*/
|
|
151
|
+
const ensureNotificationSubscriptions = async () => {
|
|
152
|
+
const allSubs = await getConfig("push_notification_subscriptions", {});
|
|
153
|
+
let changed = false;
|
|
154
|
+
for (const user of await User.find()) {
|
|
155
|
+
const enabled = user._attributes?.notify_push || false;
|
|
156
|
+
if (enabled && !allSubs[user.id]) {
|
|
157
|
+
allSubs[user.id] = [];
|
|
158
|
+
changed = true;
|
|
159
|
+
} else if (!enabled && allSubs[user.id]) {
|
|
160
|
+
delete allSubs[user.id];
|
|
161
|
+
changed = true;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (changed) {
|
|
165
|
+
await setConfig("push_notification_subscriptions", { ...allSubs });
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
|
|
145
169
|
// helpful https://gist.github.com/jpoehls/2232358
|
|
146
170
|
/**
|
|
147
171
|
* @param {object} opts
|
|
@@ -194,7 +218,6 @@ const initMaster = async ({ disableMigrate }, useClusterAdaptor = true) => {
|
|
|
194
218
|
/**
|
|
195
219
|
* @param {object} opts
|
|
196
220
|
* @param {object} opts.tenant
|
|
197
|
-
* @param {...*} opts.msg
|
|
198
221
|
* @returns {void}
|
|
199
222
|
*/
|
|
200
223
|
const workerDispatchMsg = ({ tenant, ...msg }) => {
|
|
@@ -302,6 +325,7 @@ module.exports =
|
|
|
302
325
|
ensureJwtSecret();
|
|
303
326
|
await ensureEnginesCache();
|
|
304
327
|
await ensurePluginsFolder();
|
|
328
|
+
await ensureNotificationSubscriptions();
|
|
305
329
|
}
|
|
306
330
|
process.on("unhandledRejection", (reason, p) => {
|
|
307
331
|
console.error(reason, "Unhandled Rejection at Promise");
|
|
@@ -594,10 +618,9 @@ const setupSocket = (subdomainOffset, pruneSessionInterval, ...servers) => {
|
|
|
594
618
|
"joined_real_time_socket_ids"
|
|
595
619
|
);
|
|
596
620
|
socketIds.push(socket.id);
|
|
597
|
-
await getState().setConfig(
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
);
|
|
621
|
+
await getState().setConfig("joined_real_time_socket_ids", [
|
|
622
|
+
...socketIds,
|
|
623
|
+
]);
|
|
601
624
|
if (typeof callback === "function") callback({ status: "ok" });
|
|
602
625
|
} catch (err) {
|
|
603
626
|
getState().log(1, `Socket join_collab_room: ${err.stack}`);
|