@saltcorn/mobile-builder 1.6.0-rc.1 → 1.6.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,113 @@
1
+ /*
2
+ * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
3
+ * This devtool is neither made for production nor for readable output files.
4
+ * It uses "eval()" calls to create a separate source file in the browser devtools.
5
+ * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
6
+ * or disable the default devtool with "devtool: false".
7
+ * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
8
+ */
9
+ (function webpackUniversalModuleDefinition(root, factory) {
10
+ if(typeof exports === 'object' && typeof module === 'object')
11
+ module.exports = factory();
12
+ else if(typeof define === 'function' && define.amd)
13
+ define([], factory);
14
+ else if(typeof exports === 'object')
15
+ exports["saltcorn"] = factory();
16
+ else
17
+ root["saltcorn"] = root["saltcorn"] || {}, root["saltcorn"]["tabulator"] = factory();
18
+ })(self, () => {
19
+ return (self["webpackChunksaltcorn"] = self["webpackChunksaltcorn"] || []).push([["tabulator"],{
20
+
21
+ /***/ "../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/common.js"
22
+ /*!***************************************************************************************************!*\
23
+ !*** ../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/common.js ***!
24
+ \***************************************************************************************************/
25
+ (module, __unused_webpack_exports, __webpack_require__) {
26
+
27
+ eval("{const crypto = __webpack_require__(/*! crypto */ \"../../node_modules/crypto-browserify/index.js\");\nconst db = __webpack_require__(/*! @saltcorn/data/db */ \"../saltcorn-data/dist/db/index.js\");\nconst { getState, features } = __webpack_require__(/*! @saltcorn/data/db/state */ \"../saltcorn-data/dist/db/state.js\");\nconst { eval_expression } = __webpack_require__(/*! @saltcorn/data/models/expression */ \"../saltcorn-data/dist/models/expression.js\");\nconst { interpolate } = __webpack_require__(/*! @saltcorn/data/utils */ \"../saltcorn-data/dist/utils.js\");\nconst { post_btn, localeDate, localeDateTime } = __webpack_require__(/*! @saltcorn/markup */ \"../saltcorn-markup/dist/index.js\");\nconst {\n text,\n div,\n h5,\n style,\n a,\n script,\n pre,\n domReady,\n button,\n i,\n form,\n input,\n label,\n text_attr,\n select,\n option,\n link,\n} = __webpack_require__(/*! @saltcorn/markup/tags */ \"../saltcorn-markup/dist/tags.js\");\nconst User = __webpack_require__(/*! @saltcorn/data/models/user */ \"../saltcorn-data/dist/models/user.js\");\nconst Table = __webpack_require__(/*! @saltcorn/data/models/table */ \"../saltcorn-data/dist/models/table.js\");\n\nconst {\n action_url,\n view_linker,\n parse_view_select,\n action_link,\n make_link,\n splitUniques,\n} = __webpack_require__(/*! @saltcorn/data/base-plugin/viewtemplates/viewable_fields */ \"../saltcorn-data/dist/base-plugin/viewtemplates/viewable_fields.js\");\nconst { picked_fields_to_query } = __webpack_require__(/*! @saltcorn/data/plugin-helper */ \"../saltcorn-data/dist/plugin-helper.js\");\nconst isNode = typeof window === \"undefined\";\n\n//copy from server/routes/list.js\nconst typeToGridType = (t, field, header_filters, column, calculators) => {\n const jsgField = { field: field.name, title: field.label, editor: true };\n if (column.fieldview === \"show_with_html\") {\n jsgField.formatter = \"html\";\n const rndid = \"col\" + hashCol(column);\n\n calculators.push((row) => {\n row[rndid] = row[column.field_name]\n ? interpolate(column.configuration?.code || column.code, {\n it: row[column.field_name],\n })\n : \"\";\n });\n jsgField.field = rndid;\n jsgField.headerFilter = !!header_filters && \"input\";\n jsgField.editor = false;\n } else if (\n t.name === \"String\" &&\n field.attributes &&\n field.attributes.options\n ) {\n jsgField.editor = \"list\";\n\n const values = field.attributes.options.split(\",\").map((o) => o.trim());\n if (!field.required) values.unshift(\"\");\n\n jsgField.editorParams = { values, autocomplete: true, listOnEmpty: true };\n if (header_filters) jsgField.headerFilterParams = { values };\n jsgField.headerFilter = !!header_filters;\n } else if (t.name === \"String\") {\n jsgField.headerFilter = !!header_filters;\n jsgField.sorter = \"string\";\n if (column.fieldview === \"textarea\") {\n jsgField.formatter = \"textarea\";\n jsgField.editor = \"textarea\";\n if (jsgField.headerFilter) jsgField.headerFilter = \"input\";\n } else if (column.fieldview === \"ellipsize\") {\n jsgField.formatter = \"__ellipsizeFormatter\";\n jsgField.formatterParams = {\n nchars: column.nchars || 20,\n };\n jsgField.editor = \"input\";\n }\n } else if (t === \"Key\" || t === \"File\") {\n if (\n column.fieldview === \"Select\" ||\n column.fieldview === \"show\" ||\n !column.fieldview\n ) {\n jsgField.editor = \"list\";\n const values = {};\n (field.options || []).forEach(\n ({ label, value }) => (values[value] = label),\n );\n calculators.push((row) => {\n if (row[field.name]) row[field.name] = `${row[field.name]}`;\n });\n jsgField.editorParams = { values, autocomplete: true, listOnEmpty: true };\n jsgField.formatterParams = { values };\n if (header_filters) jsgField.headerFilterParams = { values };\n jsgField.formatter = \"__lookupIntToString\";\n jsgField.headerFilter = !!header_filters;\n jsgField.headerFilterFunc = \"=\";\n } else {\n jsgField.formatter = \"__optionalImageFormatter\";\n jsgField.formatterParams = {\n fieldview: column.fieldview,\n height: field.attributes?.height\n ? `${field.attributes?.height || 50}px`\n : undefined,\n width: `${field.attributes?.width || 50}px`,\n urlPrefix:\n `/files/resize/${field.attributes?.width || 50}/` +\n (field.attributes?.height ? `${field.attributes.height}/` : \"0/\"),\n expand: column.expand,\n };\n jsgField.editor = false;\n }\n } else if (t.name === \"Float\" || t.name === \"Integer\") {\n jsgField.editor = \"number\";\n jsgField.sorter = \"number\";\n jsgField.hozAlign = \"right\";\n jsgField.headerHozAlign = \"right\";\n jsgField.editorParams = {\n step: t.name === \"Integer\" ? 1 : undefined,\n min:\n typeof field.attributes.min !== \"undefined\"\n ? field.attributes.min\n : undefined,\n max:\n typeof field.attributes.max !== \"undefined\"\n ? field.attributes.max\n : undefined,\n };\n jsgField.headerFilter = !!header_filters && \"__minMaxFilterEditor\";\n jsgField.headerFilterFunc = \"__minMaxFilterFunction\";\n jsgField.headerFilterLiveFilter = false;\n if (column.fieldview === \"to_locale_string\") {\n jsgField.formatter = \"__toLocaleStringFormatter\";\n jsgField.formatterParams = column;\n }\n if (column.fieldview === \"show_star_rating\") {\n jsgField.formatter = \"star\";\n jsgField.formatterParams = {\n stars: (field.attributes?.max || 5) - (field.attributes?.min || 1) + 1,\n };\n jsgField.editor = \"star\";\n }\n if (column.fieldview === \"progress_bar\") {\n jsgField.formatter = \"progress\";\n jsgField.formatterParams = {};\n if (column.max && !isNaN(+column.max))\n jsgField.formatterParams.max = +column.max;\n else if (typeof field.attributes.max !== \"undefined\")\n jsgField.formatterParams.max = +field.attributes.max;\n if (column.min && !isNaN(+column.min))\n jsgField.formatterParams.min = +column.min;\n else if (typeof field.attributes.min !== \"undefined\")\n jsgField.formatterParams.min = +field.attributes.min;\n\n if (column.bar_color) jsgField.formatterParams.color = column.bar_color;\n\n jsgField.hozAlign = \"left\";\n jsgField.headerHozAlign = \"left\";\n }\n if (column.fieldview === \"heat_cell\") {\n jsgField.formatter = \"__heatCellFormatter\";\n jsgField.formatterParams = { ...column };\n if (typeof field.attributes.max !== \"undefined\")\n jsgField.formatterParams.max = +field.attributes.max;\n if (typeof field.attributes.min !== \"undefined\")\n jsgField.formatterParams.min = +field.attributes.min;\n }\n } else if (t.name === \"Bool\") {\n jsgField.editor = \"tickCross\";\n jsgField.formatter = \"tickCross\";\n jsgField.hozAlign = \"center\";\n jsgField.vertAlign = \"center\";\n jsgField.editorParams = field.required\n ? {}\n : { tristate: true, indeterminateValue: \"\" };\n jsgField.formatterParams = field.required ? {} : { allowEmpty: true };\n jsgField.headerFilter = !!header_filters;\n calculators.push((row) => {\n if (row[column.field_name] === null) row[column.field_name] = \"\";\n });\n } else if (t.name === \"Date\") {\n jsgField.sorter = \"date\";\n\n jsgField.sorter = \"date\";\n jsgField.sorterParams = {\n format: \"iso\",\n };\n jsgField.editor = \"__flatpickerEditor\";\n if (column.fieldview === \"showDay\" || field.fieldview === \"showDay\") {\n jsgField.editorParams = { dayOnly: true };\n jsgField.formatter = \"__isoDateFormatter\";\n } else if (column.fieldview === \"format\" || field.fieldview === \"format\") {\n jsgField.formatter = \"__isoDateFormatter\";\n jsgField.formatterParams = {\n format: column.format || field.attributes.format,\n };\n } else if (\n column.fieldview === \"relative\" ||\n field.fieldview === \"relative\"\n ) {\n jsgField.formatter = \"__relativeDateFormatter\";\n } else {\n jsgField.formatter = \"datetime\";\n jsgField.formatterParams = {\n inputFormat: \"iso\",\n };\n }\n jsgField.headerFilter = !!header_filters && \"__dateFilterEditor\";\n jsgField.headerFilterFunc = \"__dateFilterFunction\";\n jsgField.headerFilterLiveFilter = false;\n } else if (t.name === \"Color\") {\n jsgField.editor = \"__colorEditor\";\n jsgField.formatter = \"__colorFormatter\";\n jsgField.hozAlign = \"center\";\n jsgField.vertAlign = \"center\";\n } else if (t.name === \"JSON\") {\n if (column.fieldview === \"keys_expand_columns\") {\n const fv = t.fieldviews.keys_expand_columns;\n const ex = fv.expandColumns(field, column, column);\n jsgField.subcolumns = ex;\n jsgField.field = field;\n } else {\n jsgField.formatter = \"__jsonFormatter\";\n jsgField.editor = \"__jsonEditor\";\n }\n } else if (t.name === \"SharedFileLink\") {\n //console.log(t, column);\n jsgField.formatter = \"html\";\n const rndid = \"col\" + hashCol(column);\n const fv = t.fieldviews[column.fieldview];\n\n calculators.push((row) => {\n row[rndid] =\n fv && row[column.field_name]\n ? fv.run(row[column.field_name], undefined, field.attributes)\n : \"\";\n });\n jsgField.field = rndid;\n jsgField.clipboard = false;\n jsgField.headerFilter = !!header_filters && \"input\";\n jsgField.editor = false;\n }\n\n if (field.calculated) {\n jsgField.editor = false;\n }\n if (field.primary_key) {\n jsgField.editor = false;\n }\n return jsgField;\n};\n\nconst hashCol = (col) =>\n crypto\n .createHash(\"sha1\")\n .update(JSON.stringify(col))\n .digest(\"hex\")\n .substring(0, 8);\n\nconst set_json_col = (tcol, field, key, header_filters) => {\n if (field?.attributes?.hasSchema && field.attributes.schema) {\n const schemaType = field.attributes.schema.find((t) => t.key === key);\n //console.log(schemaType);\n switch (schemaType?.type) {\n case \"Integer\":\n case \"Float\":\n tcol.sorter = \"number\";\n tcol.hozAlign = \"right\";\n tcol.headerHozAlign = \"right\";\n tcol.headerFilter = header_filters && \"__minMaxFilterEditor\";\n tcol.headerFilterFunc = \"__minMaxFilterFunction\";\n tcol.headerFilterLiveFilter = false;\n break;\n case \"String\":\n if (schemaType.options) {\n tcol.editor = \"list\";\n\n const values = schemaType.options.split(\",\").map((o) => o.trim());\n if (!field.required) values.unshift(\"\");\n\n tcol.editorParams = {\n values,\n autocomplete: true,\n listOnEmpty: true,\n };\n tcol.cellEditing = \"__storeRowEditing\";\n tcol.jsonEditSubfield = schemaType.key;\n if (header_filters) tcol.headerFilterParams = { values };\n } else tcol.headerFilter = header_filters && \"input\";\n break;\n case \"Bool\":\n tcol.formatter = \"tickCross\";\n tcol.hozAlign = \"center\";\n tcol.vertAlign = \"center\";\n break;\n default:\n break;\n }\n if (schemaType?.type.startsWith(\"Key to\")) {\n tcol.headerFilter = header_filters && \"input\";\n\n tcol.lookupFkeys = {\n table: schemaType.type.replace(\"Key to \", \"\"),\n field: schemaType.summary_field,\n };\n }\n }\n};\n\nconst set_join_fieldviews = async ({ columns, fields }) => {\n for (const segment of columns) {\n const { join_field, join_fieldview, type } = segment;\n if (!join_fieldview || type !== \"JoinField\") continue;\n const keypath = join_field.split(\".\");\n\n let field,\n theFields = fields;\n for (let i = 0; i < keypath.length; i++) {\n const refNm = keypath[i];\n field = theFields.find((f) => f.name === refNm);\n if (!field || !field.reftable_name) break;\n const table = await Table.findOne({ name: field.reftable_name });\n if (!table) break;\n theFields = await table.getFields();\n }\n if (!field) continue;\n segment.field_obj = field;\n if (field && field.type === \"File\") {\n await field.fill_fkey_options();\n segment.field_type = \"File\";\n } else if (\n field?.type.name &&\n field.type.fieldviews &&\n field.type.fieldviews[join_fieldview]\n ) {\n segment.field_type = field.type.name;\n segment.fieldview = join_fieldview;\n }\n }\n};\n\nconst get_tabulator_columns = async (\n viewname,\n table,\n fields,\n columns,\n isShow,\n req,\n header_filters,\n vert_col_headers,\n dropdown_frozen,\n layout,\n) => {\n if (layout?.list_columns && layout.besides) {\n const typeMap = {\n field: \"Field\",\n join_field: \"JoinField\",\n view_link: \"ViewLink\",\n view: \"View\",\n link: \"Link\",\n action: \"Action\",\n blank: \"Text\",\n aggregation: \"Aggregation\",\n dropdown_menu: \"DropdownMenu\",\n };\n const toArray = (x) =>\n !x ? [] : Array.isArray(x) ? x : x.above ? x.above : [x];\n let dropCols = [];\n const layoutCol2Col = ({ contents, ...rest }) => {\n if (!contents) contents = rest;\n const col = {\n ...rest?.configuration,\n ...contents?.configuration,\n ...contents,\n ...rest,\n type: typeMap[contents.type] || contents.type,\n };\n switch (contents.type) {\n case \"link\":\n col.link_text = contents.text;\n col.link_url = contents.url;\n col.link_url_formula = contents.isFormula?.url;\n col.link_text_formula = contents.isFormula?.text;\n break;\n case \"view_link\":\n col.view_label_formula = contents.isFormula?.label;\n break;\n case \"dropdown_menu\":\n dropCols = [\n ...dropCols,\n ...toArray(contents.contents).map(layoutCol2Col),\n ];\n break;\n case \"blank\":\n if (contents.isFormula?.text) {\n col.type = \"FormulaValue\";\n col.formula = col.contents;\n }\n if (contents.isHTML)\n col.interpolator = (row) =>\n interpolate(contents.contents, row, req?.user);\n break;\n case \"action\":\n col.action_label_formula = contents.isFormula?.action_label;\n break;\n case \"join_field\":\n col.join_fieldview = contents.fieldview;\n }\n return col;\n };\n const newCols = layout.besides.map(layoutCol2Col);\n dropCols.forEach((c) => {\n c.in_dropdown = true;\n });\n const allNewCols = [...newCols, ...dropCols];\n //console.log(allNewCols);\n picked_fields_to_query(allNewCols, fields);\n await set_join_fieldviews({ columns: allNewCols, fields });\n return await get_tabulator_columns(\n viewname,\n table,\n fields,\n allNewCols,\n isShow,\n req,\n header_filters,\n vert_col_headers,\n dropdown_frozen,\n );\n }\n\n const tabcols = [];\n const calculators = [];\n const dropdown_actions = [];\n const cellStyles = {};\n for (const column of columns) {\n let tcol = {};\n if (column.type === \"Field\") {\n let f = fields.find((fld) => fld.name === column.field_name);\n if (!f) return {};\n if ((f.is_fkey || f.type === \"File\") && typeof f.options === \"undefined\")\n await f.fill_fkey_options();\n\n Object.assign(f.attributes, column);\n f.fieldview = column.fieldview;\n if (column.fieldview === \"subfield\") {\n tcol.editor = \"__jsonSubEditor\";\n\n tcol.field = f.name;\n\n tcol.formatter = \"__jsonSubFormatter\";\n tcol.title = column.key;\n\n tcol.headerFilter = !!header_filters;\n tcol.formatterParams = { subfield: column.key };\n tcol.editorParams = { subfield: column.key };\n //tcol.accessorDownload = \"__jsonSubAccessor\";\n //tcol.accessorDownloadParams = { subfield: column.key, field: f.name };\n set_json_col(tcol, f, column.key, header_filters);\n } else\n tcol = typeToGridType(f.type, f, header_filters, column, calculators);\n if (column.showif) tcol.showif = column.showif;\n } else if (column.type === \"Text\") {\n const rndid = \"col\" + hashCol(column);\n if (column.style) cellStyles[rndid] = column.style;\n calculators.push((row) => {\n if (column.showif && !eval_expression(column.showif, row, req.user)) {\n row[rndid] = \"\";\n return;\n }\n row[rndid] = column.interpolator\n ? column.interpolator(row)\n : text(column.contents);\n });\n tcol.field = rndid;\n tcol.headerFilter = !!header_filters && \"input\";\n } else if (column.type === \"JoinField\") {\n let refNm, targetNm, through, key, type;\n if (column.join_field.includes(\"->\")) {\n const [relation, target] = column.join_field.split(\"->\");\n const [ontable, ref] = relation.split(\".\");\n targetNm = target;\n refNm = ref;\n key = `${ref}_${ontable}_${target}`;\n } else {\n const keypath = column.join_field.split(\".\");\n refNm = keypath[0];\n targetNm = keypath[keypath.length - 1];\n key = keypath.join(\"_\");\n }\n if (column.field_type === \"File\") {\n tcol = typeToGridType(\n \"File\",\n column.field_obj,\n header_filters,\n column,\n calculators,\n );\n tcol.field = key;\n } else if (column.fieldview === \"subfield\") {\n const f = await table.getField(column.join_field);\n tcol.editor = false;\n const jkey = `${key}_${column.key}`;\n calculators.push((row) => {\n row[jkey] = (row[key] || {})[column.key];\n });\n tcol.field = jkey;\n tcol.title = column.key;\n tcol.headerFilter = !!header_filters;\n set_json_col(tcol, f, column.key, header_filters);\n } else {\n if (column.field_type && column.field_obj) {\n tcol = typeToGridType(\n getState().types[column.field_type],\n column.field_obj,\n header_filters,\n column,\n calculators,\n );\n }\n\n tcol.field = key;\n }\n tcol.editor = false;\n if (typeof tcol.headerFilter === \"undefined\")\n tcol.headerFilter = !!header_filters;\n\n if (column.showif) tcol.showif = column.showif;\n } else if (column.type === \"Aggregation\") {\n let table, fld, through;\n const rndid = \"col\" + hashCol(column);\n if (column.agg_relation.includes(\"->\")) {\n let restpath;\n [through, restpath] = column.agg_relation.split(\"->\");\n [table, fld] = restpath.split(\".\");\n } else {\n [table, fld] = column.agg_relation.split(\".\");\n }\n const targetNm =\n column.targetNm ||\n db.sqlsanitize(\n (\n column.stat.replace(\" \", \"\") +\n \"_\" +\n table +\n \"_\" +\n fld +\n db.sqlsanitize(column.aggwhere || \"\")\n ).toLowerCase(),\n );\n if (column.agg_fieldview === \"format\" && column.format) {\n tcol.formatter = \"__isoDateFormatter\";\n tcol.formatterParams = {\n format: column.format,\n };\n tcol.field = targetNm;\n\n tcol.headerFilter = !!header_filters;\n } else if (column.agg_fieldview === \"show_with_html\") {\n tcol.formatter = \"html\";\n const rndid = \"col\" + hashCol(column);\n\n calculators.push((row) => {\n row[rndid] = row[targetNm]\n ? interpolate(column.configuration?.code || column.code, {\n it: row[targetNm],\n })\n : \"\";\n });\n tcol.field = rndid;\n tcol.headerFilter = !!header_filters && \"input\";\n tcol.editor = false;\n } else {\n tcol.formatter = \"html\";\n let showValue = (value) => {\n if (value === true)\n return i({\n class: \"fas fa-lg fa-check-circle text-success\",\n });\n else if (value === false)\n return i({\n class: \"fas fa-lg fa-times-circle text-danger\",\n });\n if (value instanceof Date) return localeDateTime(value);\n if (Array.isArray(value))\n return value.map((v) => showValue(v)).join(\", \");\n return value?.toString ? value.toString() : value;\n };\n if (column.agg_fieldview && column.agg_field?.includes(\"@\")) {\n const tname = column.agg_field.split(\"@\")[1];\n const type = getState().types[tname];\n if (type?.fieldviews[column.agg_fieldview])\n showValue = (x) =>\n type.fieldviews[column.agg_fieldview].run(x, req, column);\n }\n calculators.push((row) => {\n if (column.showif && !eval_expression(column.showif, row, req.user)) {\n row[rndid] = \"\";\n return;\n }\n let value = row[targetNm];\n\n row[rndid] = showValue(value);\n });\n tcol.field = rndid; //db.sqlsanitize(targetNm);\n tcol.headerFilter = !!header_filters;\n }\n } else if (column.type === \"FormulaValue\") {\n const rndid = \"col\" + hashCol(column);\n if (column.style) cellStyles[rndid] = column.style;\n calculators.push((row) => {\n if (column.showif && !eval_expression(column.showif, row, req.user)) {\n row[rndid] = \"\";\n return;\n }\n row[rndid] = eval_expression(column.formula, row, req.user);\n });\n tcol.field = rndid;\n tcol.formatter = \"html\";\n tcol.headerFilter = !!header_filters && \"input\";\n } else if (column.type === \"ViewLink\") {\n tcol.formatter = \"html\";\n const rndid = \"col\" + hashCol(column);\n const { key } = view_linker(\n column,\n fields,\n req?.__ ? req.__ : (s) => s,\n isNode,\n req?.user,\n \"\",\n {},\n req,\n viewname,\n true, //get label in data for sorting\n );\n calculators.push((row) => {\n if (column.showif && !eval_expression(column.showif, row, req.user)) {\n row[rndid] = \"\";\n return;\n }\n row[rndid] = key(row);\n });\n tcol.field = rndid;\n tcol.clipboard = false;\n tcol.headerFilter = !!header_filters && \"input\";\n if (column.in_dropdown) {\n dropdown_actions.push({\n column,\n rndid,\n wholeLink: true,\n label: column.label || column.action_name,\n });\n tcol = false;\n }\n } else if (column.type === \"Link\") {\n tcol.formatter = \"html\";\n const rndid = \"col\" + hashCol(column);\n\n const { key } = make_link(column, fields);\n calculators.push((row) => {\n if (column.showif && !eval_expression(column.showif, row, req.user)) {\n row[rndid] = \"\";\n return;\n }\n row[rndid] = key(row);\n });\n tcol.field = rndid;\n tcol.clipboard = false;\n tcol.headerFilter = !!header_filters && \"input\";\n if (column.in_dropdown) {\n dropdown_actions.push({\n column,\n rndid,\n wholeLink: true,\n label: column.label || column.action_name,\n });\n tcol = false;\n }\n } else if (\n column.type === \"Action\" &&\n column.action_name === \"Delete\" &&\n !column.in_dropdown\n ) {\n tcol = {\n formatter: \"buttonCross\",\n title: i({ class: \"far fa-trash-alt\" }),\n width: 40,\n formatterParams: { confirm: column.confirm, tableName: table.name },\n hozAlign: \"center\",\n headerSort: false,\n clipboard: false,\n cellClick: \"__delete_tabulator_row\",\n };\n } else if (column.type === \"Action\") {\n tcol.formatter = \"html\";\n //console.log(\"actioncol\", column);\n const rndid = \"col\" + hashCol(column);\n calculators.push((row) => {\n if (column.showif && !eval_expression(column.showif, row, req.user)) {\n row[rndid] = \"\";\n return;\n }\n const url = action_url(\n viewname,\n table,\n column.action_name,\n row,\n column.rndid || column.action_name,\n column.rndid ? \"rndid\" : \"action_name\",\n column.confirm,\n );\n const action_label =\n (column.icon ? i({ class: column.icon }) : \"\") +\n (column.action_label_formula\n ? eval_expression(column.action_label, row)\n : column.action_label || column.action_name);\n row[rndid] = column.in_dropdown\n ? url\n : action_link(url, req, { ...column, action_label });\n });\n tcol.field = rndid;\n tcol.clipboard = false;\n if (column.in_dropdown) {\n dropdown_actions.push({\n column,\n rndid,\n label: column.label || column.action_name,\n });\n tcol = false;\n }\n }\n if (!tcol) continue;\n if (tcol.subcolumns) {\n for (const { label, row_key } of tcol.subcolumns) {\n const [fld, subfld] = row_key;\n const scol = {};\n\n //scol.editor = false;\n //const key = `${fld}_${subfld}`;\n //calculators.push((row) => {\n //row[key] = (row[fld] || {})[subfld];\n //});\n scol.field = fld;\n scol.title = subfld;\n scol.editor = \"__jsonSubEditor\";\n scol.formatter = \"__jsonSubFormatter\";\n scol.formatterParams = { subfield: subfld };\n scol.editorParams = { subfield: subfld };\n //scol.accessorDownload = \"__jsonSubAccessor\";\n //scol.accessorDownloadParams = { subfield: subfld, field: fld };\n if (vert_col_headers) scol.headerVertical = true;\n set_json_col(scol, tcol.field, subfld, header_filters);\n tabcols.push(scol);\n }\n continue;\n }\n if (column.alignment && column.alignment !== \"Default\") {\n tcol.hozAlign = column.alignment.toLowerCase();\n }\n if (column.header_label) tcol.title = column.header_label;\n if (column.frozen) tcol.frozen = true;\n if (column.cssClass) tcol.cssClass = column.cssClass;\n if (column.disable_edit) tcol.editor = false;\n if (vert_col_headers) tcol.headerVertical = true;\n if (column.column_calculation) {\n tcol.bottomCalc = column.column_calculation;\n if (column.calc_dps)\n tcol.bottomCalcParams = { precision: column.calc_dps };\n }\n if (column.col_width)\n tcol.width =\n column.col_width_units === \"%\"\n ? `${column.col_width}%`\n : column.col_width;\n if (column.in_context_menu) tcol.in_context_menu = true;\n tabcols.push(tcol);\n }\n let arndid;\n\n if (dropdown_actions.length > 0) {\n arndid = \"col_action_dd\";\n calculators.push((row) => {\n let html = \"\";\n row[arndid] = button(\n {\n class: \"btn btn-sm btn-xs btn-outline-secondary dropdown-toggle\",\n disabled: true,\n },\n \"Action\",\n );\n dropdown_actions.forEach(({ label, column, rndid, wholeLink }) => {\n const action = row[rndid];\n if (action.javascript)\n html += a({ href: `javascript:${action.javascript}` }, label);\n else if (wholeLink) html += action;\n else\n html += post_btn(action, label, req.csrfToken(), {\n small: true,\n ajax: true,\n reload_on_done: true,\n btnClass: \"dropdown-item\",\n confirm: column.confirm,\n req,\n });\n });\n row._dropdown = html;\n });\n //const values = {};\n //dropdown_actions.forEach(({ label, rndid }) => {\n // values[rndid] = label;\n //});\n\n tabcols.push({\n field: arndid,\n title: \"Actions\",\n clipboard: false,\n //editorParams: { values },\n formatter: \"html\",\n headerSort: false,\n clickPopup: \"__actionPopup\",\n frozen: !!dropdown_frozen,\n });\n }\n return {\n tabcolumns: tabcols,\n calculators,\n dropdown_id: arndid,\n dropdown_actions,\n cellStyles,\n };\n};\n\n//https://stackoverflow.com/a/55241491\nconst nest = (items, id = null) => {\n return items\n .filter((item) => item._parent === id)\n .map((item) => ({\n ...item,\n _children: !item.id ? [] : nest(items, item.id),\n }));\n};\n\nfunction addFiveToColor(hexColor) {\n const decimalColor = parseInt(hexColor.replace(\"#\", \"\"), 16);\n let red = (decimalColor >> 16) & 0xff;\n let green = (decimalColor >> 8) & 0xff;\n let blue = decimalColor & 0xff;\n red = Math.min(255, red + 5);\n green = Math.min(255, green + 5);\n blue = Math.min(255, blue + 5);\n return `#${((red << 16) | (green << 8) | blue)\n .toString(16)\n .padStart(6, \"0\")}`;\n}\n\nconst isDark = (req) => {\n const state = getState();\n\n // first, try to use central method for detecting if in dark mode. if this is wrong, fix it in Saltcorn core.\n if (state.getLightDarkMode)\n return state.getLightDarkMode(req.user) === \"dark\";\n\n // this is only for legacy saltcorn versions that dont have getLightDarkMode\n if (req?.user?._attributes?.layout?.config?.mode)\n return req?.user?._attributes?.layout?.config?.mode === \"dark\";\n if (state.plugin_cfgs) {\n const layout_name = state.getLayoutPlugin(req?.user).plugin_name;\n const plugin_cfg = state.plugin_cfgs[layout_name];\n if (plugin_cfg?.mode) return plugin_cfg.mode === \"dark\";\n }\n return false;\n};\n\nconst getDarkStyle = async (req) => {\n const state = getState();\n const buildDarkStyle = ({ backgroundColorDark }) => {\n return backgroundColorDark\n ? `\n .tabulator-row, .tabulator-header, .tabulator-header-filter,\n .tabulator-footer, tabulator-footer-contents,\n .tabulator-col, tabulator-paginator,\n .tabulator * {\n background-color: ${backgroundColorDark} !important;\n }\n .tabulator-row-even * {\n background-color: ${addFiveToColor(backgroundColorDark)} !important;\n }\n `\n : null;\n };\n if (state.getLightDarkMode) {\n if (state.getLightDarkMode(req.user) === \"light\") return null;\n }\n const layout = state.getLayout(req.user);\n\n if (layout?.config?.backgroundColorDark)\n return buildDarkStyle({\n backgroundColorDark: layout?.config?.backgroundColorDark,\n });\n if (state.plugin_cfgs && !state.getLightDarkMode) {\n let anyBsThemeCfg = state.plugin_cfgs[\"any-bootstrap-theme\"];\n if (!anyBsThemeCfg)\n anyBsThemeCfg = state.plugin_cfgs[\"@saltcorn/any-bootstrap-theme\"];\n\n if (req.user?.id) {\n // does an user overwrite the global setting?\n const user = await User.findOne({ id: req.user.id });\n if (user?._attributes?.layout?.config?.mode) {\n if (user._attributes.layout.config.mode === \"dark\")\n return buildDarkStyle(anyBsThemeCfg);\n else return null;\n }\n }\n // does the global setting say dark mode?\n if (anyBsThemeCfg?.mode === \"dark\") return buildDarkStyle(anyBsThemeCfg);\n }\n return state.getLightDarkMode\n ? buildDarkStyle({\n //in dark mode but no background color found, use a default\n backgroundColorDark: \"#424242\",\n })\n : null;\n};\n\nmodule.exports = {\n typeToGridType,\n hashCol,\n nest,\n get_tabulator_columns,\n getDarkStyle,\n set_join_fieldviews,\n isDark,\n};\n\n\n//# sourceURL=webpack://saltcorn/../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/common.js?\n}");
28
+
29
+ /***/ },
30
+
31
+ /***/ "../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/index.js"
32
+ /*!**************************************************************************************************!*\
33
+ !*** ../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/index.js ***!
34
+ \**************************************************************************************************/
35
+ (module, __unused_webpack_exports, __webpack_require__) {
36
+
37
+ eval("{const Field = __webpack_require__(/*! @saltcorn/data/models/field */ \"../saltcorn-data/dist/models/field.js\");\nconst User = __webpack_require__(/*! @saltcorn/data/models/user */ \"../saltcorn-data/dist/models/user.js\");\nconst FieldRepeat = __webpack_require__(/*! @saltcorn/data/models/fieldrepeat */ \"../saltcorn-data/dist/models/fieldrepeat.js\");\n\nconst Table = __webpack_require__(/*! @saltcorn/data/models/table */ \"../saltcorn-data/dist/models/table.js\");\nconst Library = __webpack_require__(/*! @saltcorn/data/models/library */ \"../saltcorn-data/dist/models/library.js\");\nconst Page = __webpack_require__(/*! @saltcorn/data/models/page */ \"../saltcorn-data/dist/models/page.js\");\nconst PageGroup = __webpack_require__(/*! @saltcorn/data/models/page_group */ \"../saltcorn-data/dist/models/page_group.js\");\nconst Trigger = __webpack_require__(/*! @saltcorn/data/models/trigger */ \"../saltcorn-data/dist/models/trigger.js\");\nconst { getState, features } = __webpack_require__(/*! @saltcorn/data/db/state */ \"../saltcorn-data/dist/db/state.js\");\nconst Form = __webpack_require__(/*! @saltcorn/data/models/form */ \"../saltcorn-data/dist/models/form.js\");\nconst File = __webpack_require__(/*! @saltcorn/data/models/file */ \"../saltcorn-data/dist/models/file.js\");\nconst View = __webpack_require__(/*! @saltcorn/data/models/view */ \"../saltcorn-data/dist/models/view.js\");\nconst Workflow = __webpack_require__(/*! @saltcorn/data/models/workflow */ \"../saltcorn-data/dist/models/workflow.js\");\nconst {\n eval_expression,\n jsexprToWhere,\n} = __webpack_require__(/*! @saltcorn/data/models/expression */ \"../saltcorn-data/dist/models/expression.js\");\nconst { check_view_columns } = __webpack_require__(/*! @saltcorn/data/plugin-testing */ \"../saltcorn-data/dist/plugin-testing.js\");\nconst { mergeIntoWhere } = __webpack_require__(/*! @saltcorn/data/utils */ \"../saltcorn-data/dist/utils.js\");\nconst {\n field_picker_fields,\n picked_fields_to_query,\n stateFieldsToWhere,\n initial_config_all_fields,\n stateToQueryString,\n stateFieldsToQuery,\n link_view,\n getActionConfigFields,\n readState,\n run_action_column,\n calcfldViewOptions,\n calcrelViewOptions,\n} = __webpack_require__(/*! @saltcorn/data/plugin-helper */ \"../saltcorn-data/dist/plugin-helper.js\");\nconst {\n text,\n div,\n h5,\n style,\n a,\n script,\n pre,\n domReady,\n button,\n i,\n form,\n input,\n label,\n text_attr,\n select,\n option,\n code,\n link,\n} = __webpack_require__(/*! @saltcorn/markup/tags */ \"../saltcorn-markup/dist/tags.js\");\nconst { post_btn, localeDate, localeDateTime } = __webpack_require__(/*! @saltcorn/markup */ \"../saltcorn-markup/dist/index.js\");\nconst db = __webpack_require__(/*! @saltcorn/data/db */ \"../saltcorn-data/dist/db/index.js\");\n\nconst {\n action_url,\n view_linker,\n parse_view_select,\n action_link,\n make_link,\n splitUniques,\n} = __webpack_require__(/*! @saltcorn/data/base-plugin/viewtemplates/viewable_fields */ \"../saltcorn-data/dist/base-plugin/viewtemplates/viewable_fields.js\");\nconst { mockReqRes } = __webpack_require__(/*! @saltcorn/data/tests/mocks */ \"../saltcorn-data/dist/tests/mocks.js\");\nconst {\n typeToGridType,\n hashCol,\n nest,\n get_tabulator_columns,\n getDarkStyle,\n set_join_fieldviews,\n isDark,\n} = __webpack_require__(/*! ./common */ \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/common.js\");\nconst configuration_workflow = () =>\n new Workflow({\n steps: [\n {\n name: \"views\",\n form: async (context) => {\n return new Form({\n fields: [\n {\n name: \"stylesheet\",\n label: \"Stylesheet\",\n type: \"String\",\n required: true,\n attributes: {\n options: [\n \"bootstrap5\",\n \"bootstrap4\",\n \"midnight\",\n \"modern\",\n \"simple\",\n \"site\",\n \"site_dark\",\n ],\n },\n },\n ],\n });\n },\n },\n ],\n });\n\nconst public_user_role = features?.public_user_role || 10;\n\nconst old_columns_step = (req) => ({\n name: \"Columns\",\n form: async (context) => {\n const table = await Table.findOne(\n context.table_id\n ? { id: context.table_id }\n : { name: context.exttable_name }\n );\n //console.log(context);\n const field_picker_repeat = await field_picker_fields({\n table,\n viewname: context.viewname,\n req,\n has_align: true,\n has_showif: true,\n });\n field_picker_repeat.push({\n name: \"frozen\",\n label: \"Frozen\",\n type: \"Bool\",\n });\n field_picker_repeat.push({\n name: \"cssClass\",\n label: \"CSS Class\",\n type: \"String\",\n });\n field_picker_repeat.push({\n name: \"disable_edit\",\n label: \"Disable editing\",\n type: \"Bool\",\n showIf: { type: \"Field\" },\n });\n field_picker_repeat.push({\n name: \"column_calculation\",\n label: \"Column Calculation\",\n type: \"String\",\n attributes: {\n options: [\n \"\",\n \"avg\",\n \"max\",\n \"min\",\n \"sum\",\n \"count\",\n { name: \"__tabulator_colcalc_unique\", label: \"count unique\" },\n { name: \"__tabulator_colcalc_counttrue\", label: \"count true\" },\n {\n name: \"__tabulator_colcalc_countfalse\",\n label: \"count false\",\n },\n {\n name: \"__tabulator_colcalc_avgnonulls\",\n label: \"avg no nulls\",\n },\n {\n name: \"__tabulator_colcalc_sumroundquarter\",\n label: \"sum round to quarter\",\n },\n ],\n },\n });\n field_picker_repeat.push({\n name: \"calc_dps\",\n label: \"Calculation decimal places\",\n type: \"Integer\",\n showIf: {\n column_calculation: [\n \"avg\",\n \"max\",\n \"min\",\n \"sum\",\n \"__tabulator_colcalc_avgnonulls\",\n ],\n },\n });\n const use_field_picker_repeat = field_picker_repeat.filter(\n (f) => ![\"state_field\"].includes(f.name)\n );\n const cwunit_fld = field_picker_repeat.find(\n (c) => c.name === \"col_width_units\"\n );\n if (cwunit_fld) {\n cwunit_fld.attributes.options = [\"px\", \"%\"];\n cwunit_fld.default = \"px\";\n }\n const fvs = field_picker_repeat.filter((c) => c.name === \"fieldview\");\n fvs.forEach((fv) => {\n if (fv?.attributes?.calcOptions?.[1])\n Object.values(fv.attributes.calcOptions[1]).forEach((fvlst) => {\n if (fvlst[0] === \"as_text\") fvlst.push(\"textarea\");\n });\n });\n // fix legacy values missing view_name\n (context?.columns || []).forEach((column) => {\n if (column.type === \"ViewLink\" && column.view && !column.view_name) {\n const view_select = parse_view_select(column.view);\n column.view_name = view_select.viewname;\n }\n });\n return new Form({\n fields: [\n new FieldRepeat({\n name: \"columns\",\n fancyMenuEditor: true,\n fields: use_field_picker_repeat,\n }),\n ],\n });\n },\n});\n\nconst new_columns_step = (req) => ({\n name: req.__(\"Columns\"),\n builder: async (context) => {\n const table = Table.findOne(context.table_id || context.exttable_name);\n const fields = table.getFields();\n\n const boolfields = fields.filter((f) => f.type && f.type.name === \"Bool\");\n const stateActions = Object.entries(getState().actions).filter(\n ([k, v]) => !v.disableInBuilder\n );\n const builtInActions = [\n \"Delete\",\n \"GoBack\",\n ...boolfields.map((f) => `Toggle ${f.name}`),\n ];\n const actions = [...builtInActions, ...stateActions.map(([k, v]) => k)];\n const triggerActions = [];\n (\n await Trigger.find({\n when_trigger: { or: [\"API call\", \"Never\"] },\n })\n ).forEach((tr) => {\n actions.push(tr.name);\n triggerActions.push(tr.name);\n });\n (\n await Trigger.find({\n table_id: context.table_id,\n })\n ).forEach((tr) => {\n actions.push(tr.name);\n triggerActions.push(tr.name);\n });\n for (const field of fields) {\n if (field.type === \"Key\") {\n field.reftable = Table.findOne({\n name: field.reftable_name,\n });\n if (field.reftable) await field.reftable.getFields();\n }\n }\n const actionConfigForms = {};\n for (const [name, action] of stateActions) {\n if (action.configFields) {\n actionConfigForms[name] = await getActionConfigFields(action, table, {\n mode: \"list\",\n });\n }\n }\n //const fieldViewConfigForms = await calcfldViewConfig(fields, false);\n const { field_view_options, handlesTextStyle } = calcfldViewOptions(\n fields,\n \"list\"\n );\n if (table.name === \"users\") {\n fields.push(\n new Field({\n name: \"verification_url\",\n label: \"Verification URL\",\n type: \"String\",\n })\n );\n field_view_options.verification_url = [\"as_text\", \"as_link\"];\n }\n for (const field of fields) {\n if (field_view_options[field.name]?.[0] === \"as_text\")\n field_view_options[field.name].push(\"textarea\");\n if (field.type === \"File\")\n field_view_options[field.name].unshift(\"Select\");\n }\n const rel_field_view_options = await calcrelViewOptions(table, \"list\");\n const roles = await User.get_roles();\n const { parent_field_list } = await table.get_parent_relations(true, true);\n\n const { child_field_list, child_relations } =\n await table.get_child_relations(true);\n var agg_field_opts = {};\n child_relations.forEach(({ table, key_field, through }) => {\n const aggKey =\n (through ? `${through.name}->` : \"\") +\n `${table.name}.${key_field.name}`;\n agg_field_opts[aggKey] = table.fields\n .filter((f) => !f.calculated || f.stored)\n .map((f) => ({\n name: f.name,\n label: f.label,\n ftype: f.type.name || f.type,\n table_name: table.name,\n table_id: table.id,\n }));\n });\n const agg_fieldview_options = {};\n\n Object.values(getState().types).forEach((t) => {\n agg_fieldview_options[t.name] = Object.entries(t.fieldviews)\n .filter(([k, v]) => !v.isEdit && !v.isFilter)\n .map(([k, v]) => k);\n });\n const pages = await Page.find();\n const groups = (await PageGroup.find()).map((g) => ({\n name: g.name,\n }));\n const images = await File.find({ mime_super: \"image\" });\n const library = (await Library.find({})).filter((l) =>\n l.suitableFor(\"list\")\n );\n const myviewrow = View.findOne({ name: context.viewname });\n // generate layout for legacy views\n if (!context.layout?.list_columns) {\n const newCols = [];\n const actionDropdown = [];\n const typeMap = {\n Field: \"field\",\n JoinField: \"join_field\",\n ViewLink: \"view_link\",\n Link: \"link\",\n Action: \"action\",\n Text: \"blank\",\n DropdownMenu: \"dropdown_menu\",\n Aggregation: \"aggregation\",\n FormulaValue: \"blank\",\n };\n (context.columns || []).forEach((col) => {\n const newCol = {\n ...col,\n contents: {\n ...col,\n configuration: { ...col },\n type: typeMap[col.type],\n },\n };\n delete newCol._columndef;\n delete newCol.type;\n\n delete newCol.contents._columndef;\n delete newCol.contents.configuration._columndef;\n delete newCol.contents.configuration.type;\n\n switch (col.type) {\n case \"FormulaValue\":\n newCol.contents.isFormula = {\n text: true,\n };\n newCol.contents.contents = col.formula;\n break;\n case \"Action\":\n newCol.contents.isFormula = {\n action_label: !!col.action_label_formula,\n };\n break;\n case \"ViewLink\":\n newCol.contents.isFormula = {\n label: !!col.view_label_formula,\n };\n break;\n case \"Link\":\n newCol.contents.isFormula = {\n url: !!col.link_url_formula,\n text: !!col.link_text_formula,\n };\n newCol.contents.text = col.link_text;\n newCol.contents.url = col.link_url;\n break;\n }\n if (col.in_dropdown)\n actionDropdown.push({ ...col, type: typeMap[col.type] });\n else newCols.push(newCol);\n });\n if (actionDropdown.length) {\n newCols.push({ type: \"dropdown_menu\", contents: actionDropdown });\n }\n context.layout = {\n besides: newCols,\n list_columns: true,\n };\n }\n return {\n tableName: table.name,\n fields: fields.map((f) => f.toBuilder),\n images,\n actions,\n triggerActions,\n builtInActions,\n actionConfigForms,\n agg_fieldview_options,\n //fieldViewConfigForms,\n field_view_options: {\n ...field_view_options,\n ...rel_field_view_options,\n },\n parent_field_list,\n child_field_list,\n agg_field_opts,\n min_role: (myviewrow || {}).min_role,\n roles,\n library,\n additionalColumnFields: [\n {\n name: \"frozen\",\n label: \"Frozen\",\n type: \"Bool\",\n },\n {\n name: \"in_context_menu\",\n label: \"In context menu\",\n sublabel:\n \"The context menu appears when the user right-clicks on a row\",\n type: \"Bool\",\n },\n {\n name: \"cssClass\",\n label: \"CSS Class\",\n type: \"String\",\n },\n {\n name: \"disable_edit\",\n label: \"Disable editing\",\n type: \"Bool\",\n },\n {\n name: \"column_calculation\",\n label: \"Column Calculation\",\n type: \"String\",\n required: true,\n attributes: {\n options: [\n \"\",\n \"avg\",\n \"max\",\n \"min\",\n \"sum\",\n \"count\",\n { name: \"__tabulator_colcalc_unique\", label: \"count unique\" },\n { name: \"__tabulator_colcalc_counttrue\", label: \"count true\" },\n {\n name: \"__tabulator_colcalc_countfalse\",\n label: \"count false\",\n },\n {\n name: \"__tabulator_colcalc_avgnonulls\",\n label: \"avg no nulls\",\n },\n {\n name: \"__tabulator_colcalc_sumroundquarter\",\n label: \"sum round to quarter\",\n },\n ],\n },\n },\n {\n name: \"calc_dps\",\n label: \"Calculation decimal places\",\n type: \"Integer\",\n showIf: {\n column_calculation: [\n \"avg\",\n \"max\",\n \"min\",\n \"sum\",\n \"__tabulator_colcalc_avgnonulls\",\n ],\n },\n },\n ],\n pages,\n page_groups: groups,\n allowMultiStepAction: true,\n handlesTextStyle,\n mode: \"list\",\n ownership:\n !!table.ownership_field_id ||\n !!table.ownership_formula ||\n table.name === \"users\",\n };\n },\n});\n\nconst view_configuration_workflow = (req) =>\n new Workflow({\n steps: [\n features?.list_builder ? new_columns_step(req) : old_columns_step(req),\n {\n name: \"Options\",\n form: async (context) => {\n const table = await Table.findOne(\n context.table_id\n ? { id: context.table_id }\n : { name: context.exttable_name }\n );\n const fields = await table.getFields();\n for (const field of fields) {\n await field.fill_fkey_options();\n }\n const { tabcolumns } = await get_tabulator_columns(\n context.viewname,\n table,\n fields,\n context.columns,\n false,\n undefined,\n false\n );\n const colFields = tabcolumns\n .filter((c) =>\n [\"Field\", \"JoinField\", \"Aggregation\", \"FormulaValue\"].includes(\n c.type\n )\n )\n .map((c) => c.field)\n .filter((s) => s);\n const groupByOptions = new Set([\n ...colFields,\n ...fields.map((f) => f.name),\n \"Selected by user\",\n ]);\n const boolGroupOptions = new Set([\n ...fields\n .filter((f) => f?.type?.name === \"Bool\")\n .map((f) => f.name),\n ...colFields\n .filter((f) => f.formatter === \"tickCross\")\n .map((f) => f.field),\n ]);\n const roles = await User.get_roles();\n let tree_field_options = [];\n //self join\n for (const field of fields) {\n if (field.is_fkey && field.reftable_name == table.name)\n tree_field_options.push(field.name);\n }\n\n const action_options = (\n await Trigger.find({\n when_trigger: { or: [\"API call\", \"Never\"] },\n })\n ).map((tr) => tr.name);\n const editViewOnTable = await View.find({\n table_id: table.id,\n viewtemplate: \"Edit\",\n });\n action_options.push(\n ...editViewOnTable.map((v) => ({\n label: `${v.name} [Edit]`,\n name: `Edit:` + v.name,\n }))\n );\n\n return new Form({\n fields: [\n {\n name: \"fit\",\n label: \"Layout Fit\",\n type: \"String\",\n required: true,\n tab: \"Layout\",\n attributes: {\n options: [\n \"Columns\",\n \"Data\",\n \"DataFill\",\n \"DataStretch\",\n \"DataTable\",\n ],\n },\n },\n {\n name: \"responsiveLayout\",\n label: \"Responsive Layout\",\n type: \"String\",\n required: false,\n tab: \"Layout\",\n attributes: {\n options: [\"hide\", \"collapse\"],\n },\n },\n {\n name: \"groupBy\",\n label: \"Group by\",\n type: \"String\",\n tab: \"Content\",\n attributes: {\n options: [...groupByOptions],\n },\n },\n {\n name: \"default_group_by\",\n label: \"Default group by\",\n type: \"String\",\n tab: \"Content\",\n attributes: {\n options: [...groupByOptions].filter(\n (f) => f !== \"Selected by user\"\n ),\n },\n showIf: { groupBy: \"Selected by user\" },\n },\n {\n name: \"group_true_label\",\n label: \"Group True label\",\n type: \"String\",\n tab: \"Content\",\n showIf: { groupBy: [...boolGroupOptions] },\n },\n {\n name: \"group_false_label\",\n label: \"Group False label\",\n type: \"String\",\n tab: \"Content\",\n showIf: { groupBy: [...boolGroupOptions] },\n },\n {\n name: \"group_null_label\",\n label: \"Group null label\",\n type: \"String\",\n tab: \"Content\",\n showIf: { groupBy: [...boolGroupOptions] },\n },\n {\n name: \"group_order_desc\",\n label: \"Group order descending\",\n type: \"Bool\",\n tab: \"Content\",\n showIf: { groupBy: [...groupByOptions] },\n },\n {\n name: \"tree_field\",\n label: \"Tree field\",\n type: \"String\",\n tab: \"Content\",\n attributes: {\n options: tree_field_options,\n },\n },\n {\n name: \"def_order_field\",\n label: req.__(\"Default order by\"),\n type: \"String\",\n tab: \"Content\",\n attributes: {\n options: fields.map((f) => f.name),\n },\n },\n {\n name: \"def_order_descending\",\n label: req.__(\"Default order descending?\"),\n type: \"Bool\",\n tab: \"Content\",\n },\n {\n name: \"include_fml\",\n label: req.__(\"Row inclusion formula\"),\n class: \"validate-expression\",\n tab: \"Content\",\n sublabel:\n req.__(\"Only include rows where this formula is true. \") +\n req.__(\"In scope:\") +\n \" \" +\n [\n ...fields.map((f) => f.name),\n \"user\",\n \"year\",\n \"month\",\n \"day\",\n \"today()\",\n ]\n .map((s) => code(s))\n .join(\", \"),\n type: \"String\",\n },\n {\n name: \"hideColsBtn\",\n label: \"Show/hide columns\",\n type: \"Bool\",\n tab: \"Functionality\",\n sublabel: \"Display drop-down menu to select shown columns\",\n },\n {\n name: \"column_visibility_presets\",\n label: \"Column visibility presets\",\n type: \"Bool\",\n tab: \"Functionality\",\n showIf: { hideColsBtn: true },\n },\n {\n name: \"min_role_preset_edit\",\n label: \"Role to edit\",\n sublabel: \"Role required to edit presets\",\n input_type: \"select\",\n tab: \"Functionality\",\n showIf: { hideColsBtn: true, column_visibility_presets: true },\n options: roles.map((r) => ({ value: r.id, label: r.role })),\n },\n {\n name: \"hide_null_columns\",\n label: \"Hide null columns\",\n sublabel:\n \"Do not display a column if it contains entirely missing values\",\n type: \"Bool\",\n tab: \"Content\",\n },\n {\n name: \"addRowBtn\",\n label: \"Add row button\",\n type: \"Bool\",\n tab: \"Functionality\",\n },\n {\n name: \"header_wrap\",\n label: \"Wrap column headers\",\n type: \"Bool\",\n tab: \"Layout\",\n },\n {\n name: \"selectable\",\n label: \"Selectable\",\n type: \"Bool\",\n tab: \"Functionality\",\n },\n {\n name: \"remove_unselected_btn\",\n label: \"Show selection button\",\n type: \"Bool\",\n tab: \"Functionality\",\n showIf: { selectable: true },\n },\n {\n name: \"download_csv\",\n label: \"Download CSV\",\n type: \"Bool\",\n tab: \"Functionality\",\n },\n {\n name: \"header_filters\",\n label: \"Header filters\",\n type: \"Bool\",\n tab: \"Functionality\",\n },\n {\n name: \"movable_cols\",\n label: \"Movable columns\",\n type: \"Bool\",\n tab: \"Layout\",\n },\n {\n name: \"vert_col_headers\",\n label: \"Vertical column headers\",\n type: \"Bool\",\n tab: \"Layout\",\n },\n {\n name: \"history\",\n label: \"History (undo/redo)\",\n type: \"Bool\",\n tab: \"Functionality\",\n },\n {\n name: \"persistent\",\n label: \"Persistent configuration\",\n type: \"Bool\",\n tab: \"Functionality\",\n },\n {\n name: \"reset_persistent_btn\",\n label: \"Reset persistent button\",\n sublabel:\n \"Show button to reset persistent configuration and filters\",\n type: \"Bool\",\n showIf: { persistent: true },\n tab: \"Functionality\",\n },\n {\n name: \"select_range\",\n label: \"Select range\",\n sublabel: \"Select range for copy/paste\",\n type: \"Bool\",\n tab: \"Functionality\",\n },\n {\n name: \"confirm_edits\",\n label: \"Confirm all edits\",\n sublabel:\n \"Every time the user edits a cell, confirm with popup\",\n type: \"Bool\",\n tab: \"Functionality\",\n },\n {\n name: \"dropdown_frozen\",\n label: \"Action dropdown column frozen\",\n type: \"Bool\",\n tab: \"Content\",\n },\n {\n name: \"ajax_load\",\n label: \"Progressive loading\",\n type: \"Bool\",\n tab: \"Content\",\n },\n {\n name: \"pagination_enabled\",\n label: \"Pagination\",\n type: \"Bool\",\n tab: \"Layout\",\n },\n {\n name: \"auto_pagination_size\",\n label: \"Auto pagination size\",\n sublabel:\n \"Automatically fit rows to viewport height (overrides Pagination size)\",\n type: \"Bool\",\n tab: \"Layout\",\n showIf: { pagination_enabled: true },\n },\n {\n name: \"pagination_size\",\n label: \"Pagination size\",\n type: \"Integer\",\n default: 20,\n tab: \"Layout\",\n showIf: { pagination_enabled: true, auto_pagination_size: false },\n },\n {\n name: \"selected_rows_action\",\n label: \"Selected rows action\",\n type: \"String\",\n tab: \"Functionality\",\n attributes: {\n options: [...action_options],\n },\n },\n {\n name: \"disable_edit_if\",\n label: \"Disable edit if\",\n sublabel: \"Formula\",\n type: \"String\",\n tab: \"Functionality\",\n class: \"validate-expression\",\n },\n {\n name: \"row_color_formula\",\n label: \"Row color formula\",\n sublabel:\n \"Formula for row background color. Ex.: <code>age>65 ?'#aaffaa': null</code>\",\n type: \"String\",\n tab: \"Functionality\",\n class: \"validate-expression\",\n },\n {\n name: \"selected_rows_action_once\",\n label: \"Run action once for all rows\",\n type: \"Bool\",\n tab: \"Functionality\",\n sublabel:\n \"Tick to run action once with all rows (<code>rows</code> variable). Untick to run multiple times, once for each row (<code>row</code> variable).\",\n showIf: { selected_rows_action: [...action_options] },\n },\n {\n name: \"override_stylesheet\",\n label: \"Override stylesheet\",\n type: \"String\",\n attributes: {\n options: [\n \"bootstrap5\",\n \"bootstrap4\",\n \"midnight\",\n \"modern\",\n \"simple\",\n \"site\",\n \"site_dark\",\n ],\n },\n tab: \"Layout\",\n },\n {\n name: \"height\",\n label: \"Height\",\n type: \"String\",\n sublabel: \"Example: 500px or 50vh. Default is 100%\",\n tab: \"Layout\",\n },\n ],\n });\n },\n },\n ],\n });\n\nconst get_state_fields = async (table_id, viewname, { show_view }) => {\n const table = Table.findOne(table_id);\n const table_fields = table.fields;\n return table_fields\n .filter((f) => !f.primary_key)\n .map((f) => {\n const sf = new Field(f);\n sf.required = false;\n return sf;\n });\n};\n\nconst initial_config = async ({ table_id, exttable_name }) => {\n const table = Table.findOne(\n table_id ? { id: table_id } : { name: exttable_name }\n );\n\n const fields = table.getFields().filter((f) => !f.primary_key);\n const columns = [];\n const layoutCols = [];\n fields.forEach((f) => {\n if (!f.type) return;\n if (f.type === \"File\") {\n const col = {\n type: \"field\",\n fieldview: \"Link\",\n field_name: f.name,\n };\n columns.push({ ...col, type: \"Field\" });\n layoutCols.push({ contents: col, header_label: f.label });\n } else if (f.is_fkey) {\n const col = {\n type: \"join_field\",\n fieldview: \"as_text\",\n join_field: `${f.name}.${f.attributes?.summary_field || \"id\"}`,\n };\n columns.push({ ...col, type: \"JoinField\" });\n layoutCols.push({ contents: col, header_label: f.label });\n } else {\n const fieldview = f.type?.fieldviews?.show\n ? \"show\"\n : f.type?.fieldviews?.as_text\n ? \"as_text\"\n : undefined;\n const col = {\n type: \"field\",\n fieldview,\n field_name: f.name,\n };\n columns.push({ ...col, type: \"Field\" });\n layoutCols.push({ contents: col, header_label: f.label });\n }\n });\n\n return { columns, layout: { list_columns: true, besides: layoutCols } };\n};\n\nconst addRowButton = (rndid) =>\n button(\n {\n class: \"btn btn-sm btn-primary mx-1\",\n onClick: `add_tabview_row('${rndid}')`,\n },\n i({ class: \"fas fa-plus me-1\" }),\n \"Add row\"\n );\n\nconst selectGroupBy = (\n fields,\n columns,\n rndid,\n orderFld,\n orderDesc,\n default_group_by\n) => {\n const groupByOptions = {};\n columns.forEach((c) => {\n if ([\"Field\", \"JoinField\", \"Aggregation\"].includes(c.type) && c.field)\n groupByOptions[c.field] = c.title || c.field;\n });\n fields.forEach((f) => {\n groupByOptions[f.name] = f.label || f.name;\n });\n\n return select(\n {\n onChange: `tabUserGroupBy(this, '${rndid}'${\n orderFld ? `, '${orderFld}', ${!!orderDesc}` : \"\"\n })`,\n class: \"mx-1 form-select d-inline\",\n style: \"width:unset\",\n },\n option(\n { value: \"\", disabled: true, selected: !default_group_by },\n \"Group by...\"\n ),\n option({ value: \"\" }, \"No grouping\"),\n Object.entries(groupByOptions).map(([k, v]) =>\n option({ value: k, selected: k === default_group_by }, v)\n )\n );\n};\n\nconst hideShowColsBtn = (\n tabcolumns,\n column_visibility_presets,\n presets,\n can_edit,\n viewname,\n rndid\n) =>\n div(\n { class: \"dropdown d-inline mx-1\" },\n button(\n {\n class: \"btn btn-sm btn-outline-secondary dropdown-toggle\",\n \"data-boundary\": \"viewport\",\n type: \"button\",\n id: \"btnHideCols\",\n \"data-bs-toggle\": \"dropdown\",\n \"aria-haspopup\": \"true\",\n \"aria-expanded\": \"false\",\n },\n \"Show/hide fields\"\n ),\n div(\n {\n class: \"dropdown-menu\",\n \"aria-labelledby\": \"btnHideCols\",\n },\n form(\n { class: \"px-2 tabShowHideCols\" },\n a({ onclick: `allnonecols(true,this)`, href: \"javascript:;\" }, \"All\"),\n \" | \",\n a({ onclick: `allnonecols(false,this)`, href: \"javascript:;\" }, \"None\"),\n !!column_visibility_presets && div(\"Presets:\"),\n column_visibility_presets &&\n Object.entries(presets || {}).map(([k, v]) =>\n div(\n a(\n {\n href: `javascript:activate_preset('${encodeURIComponent(\n JSON.stringify(v)\n )}', '${rndid}');`,\n },\n k\n ),\n can_edit &&\n a(\n {\n href: `javascript:delete_preset('${viewname}','${k}');`,\n },\n i({ class: \"fas fa-trash-alt\" })\n )\n )\n ),\n can_edit &&\n !!column_visibility_presets &&\n a(\n {\n class: \"d-block\",\n href: `javascript:add_preset('${viewname}');`,\n },\n i({ class: \"fas fa-plus\" }),\n \"Add\"\n ),\n\n tabcolumns.map(\n (f) =>\n f.field &&\n !f.frozen &&\n div(\n { class: \"form-check\" },\n input({\n type: \"checkbox\",\n onChange: `showHideColView('${f.field}', this, '${rndid}')`,\n class: \"form-check-input\",\n checked: true,\n \"data-fieldname\": f.field,\n }),\n label(f.title || f.field)\n )\n )\n )\n )\n );\nconst run = async (table_id, viewname, cfg, state, extraArgs, queriesObj) => {\n const {\n columns,\n layout,\n fit,\n responsiveLayout,\n hideColsBtn,\n hide_null_columns,\n addRowBtn,\n selectable,\n remove_unselected_btn,\n download_csv,\n header_filters,\n pagination_enabled,\n pagination_size,\n movable_cols,\n history,\n persistent,\n groupBy,\n dropdown_frozen,\n vert_col_headers,\n reset_persistent_btn,\n def_order_field,\n def_order_descending,\n column_visibility_presets,\n presets,\n min_role_preset_edit,\n tree_field,\n selected_rows_action,\n group_true_label,\n group_false_label,\n group_null_label,\n default_group_by,\n group_order_desc,\n header_wrap,\n override_stylesheet,\n ajax_load,\n confirm_edits,\n disable_edit_if,\n row_color_formula,\n select_range,\n height,\n auto_pagination_size,\n } = cfg;\n const table = await Table.findOne({ id: table_id });\n const fields = await table.getFields();\n readState(state, fields);\n let groupBy1 = groupBy;\n if (groupBy1) {\n if (groupBy === \"Selected by user\" && default_group_by)\n groupBy1 = default_group_by;\n const groupField = fields.find((f) => f.name === groupBy1);\n if (groupField && groupField.is_fkey) {\n let orginalName = groupBy1;\n groupBy1 = `${groupBy1}_${groupField?.attributes?.summary_field || \"id\"}`;\n }\n }\n\n let rows = [];\n if (!ajax_load || hide_null_columns)\n rows = (\n await get_db_rows(\n table,\n fields,\n viewname,\n cfg,\n state,\n extraArgs.req,\n extraArgs.isPreview,\n queriesObj\n )\n ).rows;\n else {\n //needed to set agg targetNm\n picked_fields_to_query(columns, fields);\n }\n\n await set_join_fieldviews({ columns, fields });\n const { tabcolumns, dropdown_id, dropdown_actions, cellStyles } =\n await get_tabulator_columns(\n viewname,\n table,\n fields,\n columns,\n false,\n extraArgs.req,\n header_filters,\n vert_col_headers,\n dropdown_frozen,\n layout\n );\n\n if (selectable)\n tabcolumns.unshift({\n formatter: \"rowSelection\",\n titleFormatter: \"rowSelection\",\n headerSort: false,\n width: \"20\",\n clipboard: false,\n frozen: tabcolumns[0].frozen,\n });\n const use_tabcolumns0 = hide_null_columns\n ? tabcolumns.filter(\n (c) =>\n !c.field ||\n rows.some(\n (row) =>\n row[c.field] !== null && typeof row[c.field] !== \"undefined\"\n )\n )\n : tabcolumns;\n const use_tabcolumns = use_tabcolumns0.filter((c) => !c.in_context_menu);\n const context_menu_tabcolumns = use_tabcolumns0.filter(\n (c) => c.in_context_menu\n );\n if (ajax_load && hide_null_columns) rows = [];\n\n const pgSz = pagination_size || 20;\n const paginationSizeChoices = [\n Math.round(pgSz / 2),\n Math.round(pgSz * 0.75),\n pgSz,\n Math.round(pgSz * 1.5),\n pgSz * 2,\n pgSz * 3,\n true,\n ];\n const hasCalculated =\n fields.some((f) => f.calculated) ||\n columns.some((c) => c.type === \"FormulaValue\") ||\n columns.some((c) => c.type === \"JoinField\");\n const selected_rows_action_name = selected_rows_action\n ? selected_rows_action.startsWith(\"Edit:\")\n ? ((x) => x?.description || x?.name)(\n View.findOne({ name: selected_rows_action.replaceAll(\"Edit:\", \"\") })\n ) || selected_rows_action.replaceAll(\"Edit:\", \"\")\n : ((x) => x?.description || x?.name)(\n getState().triggers.find((tr) => tr.name === selected_rows_action)\n ) || selected_rows_action\n : \"\";\n\n const rndid = Math.floor(Math.random() * 16777215).toString(16);\n for (const col of use_tabcolumns) {\n if (col.lookupFkeys) {\n const table = Table.findOne(col.lookupFkeys.table);\n const ids = [\n ...new Set(\n rows.map((r) => r[col.field]).filter((x) => x && !isNaN(+x))\n ),\n ];\n const lu_map = {};\n (await table.getRows({ id: { in: ids } })).forEach((r) => {\n lu_map[r.id] = r;\n });\n rows.forEach((r) => {\n if (r[col.field] && lu_map[r[col.field]])\n r[col.field] = lu_map[r[col.field]][col.lookupFkeys.field];\n });\n }\n if (col.showif)\n rows.forEach((r) => {\n if (!eval_expression(col.showif, r, extraArgs.req?.user))\n r[col.field] = null;\n });\n\n if (header_wrap) col.headerWordWrap = true;\n }\n if (disable_edit_if) {\n use_tabcolumns.forEach((col) => {\n col.editable = \"__tabulator_edit_check\";\n });\n }\n let rowContextMenu = undefined;\n if (context_menu_tabcolumns.length) {\n const menuCode = context_menu_tabcolumns.map((c) => {\n if (c.formatter === \"html\" || !c.formatter)\n return `menu.push({\n label: component.getData().${c.field},\n action: function(){}\n });`;\n });\n rowContextMenu = `function(e, component){\n //component - column/cell/row component that triggered the menu\n //e - click event object\n\n var menu = [];\n\n ${menuCode.join(\"\\n\")}\n\n return menu;\n }`;\n }\n\n const darkStyle = await getDarkStyle(extraArgs.req);\n\n let selected_rows_label;\n if (selected_rows_action) {\n }\n\n return fragment(\n //script(`var edit_fields=${JSON.stringify(jsfields)};`),\n //script(domReady(versionsField(table.name))),\n style(`.tabulator-popup-container {background: white}`),\n style(\n Object.entries(cellStyles || {})\n .map(\n ([fld, style]) =>\n `.tabulator-cell[tabulator-field=\"${fld}\"] {${Object.entries(\n style || {}\n )\n .map(([k, v]) => `${k}: ${v};`)\n .join(\"\")}}`\n )\n .join(\"\\n\")\n ),\n script(\n domReady(`\n ${\n darkStyle\n ? `\n var styleElement = document.createElement('style');\n styleElement.textContent = ${JSON.stringify(darkStyle)};\n document.head.appendChild(styleElement);`\n : \"\"\n }\n\n const columns=${JSON.stringify(use_tabcolumns)}; \n const dropdown_actions = ${JSON.stringify(dropdown_actions)};\n window.actionPopup = (e, row) => {\n return row.getRow().getData()._dropdown;\n }\n columns.forEach(col=>{\n Object.entries(col).forEach(([k,v])=>{\n if(typeof v === \"string\" && v.startsWith(\"__\")) {\n col[k] = window[v.substring(2)];\n }\n })\n })\n ${\n persistent\n ? `let initialHeaderFilter=[];\n try {\n initialHeaderFilter = JSON.parse(localStorage.getItem('tabfiltr_${viewname}'));\n } catch(e) {\n }`\n : \"\"\n }\n const isWeb = getIsNode();\n const buildMobileAjaxParams = () => {\n if (isWeb) return {};\n const { jwt, tenantAppName } = parent.saltcorn.data.state.getState().mobileConfig;\n const result = {\n \"X-Requested-With\": \"XMLHttpRequest\",\n \"X-Saltcorn-Client\": \"mobile-app\",\n Authorization: \\`jwt \\${jwt}\\`\n };\n if (tenantAppName) result[\"X-Saltcorn-App\"] = tenantAppName;\n return result;\n };\n\n const buildMobileAjaxUrl = () => {\n if (isWeb) return {};\n const path = \"/view/${viewname}/get_rows\";\n const { server_path } = parent.saltcorn.data.state.getState().mobileConfig;\n return \\`\\${server_path}\\${path}\\`;\n };\n window.addEventListener(\"resize\", function(event) {\n if (document.getElementsByClassName(\"tabulator-editing\").length) {\n event.stopImmediatePropagation();\n }\n }, true);\n window.tabulator_table_${rndid} = new Tabulator(\"#tabgrid${viewname.replaceAll(\n \" \",\n \"\"\n )}${rndid}\", {\n ${\n ajax_load\n ? `\n ajaxURL: isWeb ? \n \"/view/${viewname}/get_rows\" : buildMobileAjaxUrl(),\n ${\n pagination_enabled\n ? 'paginationMode:\"remote\",'\n : extraArgs.isPreview\n ? \"\"\n : `progressiveLoad:\"scroll\",`\n }\n ajaxParams: {state:${JSON.stringify(state)}},\n filterMode:\"remote\",\n sortMode:\"remote\",\n ajaxContentType:\"json\",\n ajaxConfig:{\n method: \"POST\",\n headers: isWeb ? {\n \"CSRF-Token\": _sc_globalCsrf,\n } : buildMobileAjaxParams()\n },\n `\n : `data: ${JSON.stringify(rows)},`\n }\n ${\n disable_edit_if || row_color_formula\n ? `rowFormatter: function(row) {\n if(row.getData()._disable_edit) {\n row.getElement().style.backgroundColor = \"#cccccc\";\n } ${\n row_color_formula\n ? `const rowcol = (new Function(\"{${fields\n .map((f) => f.name)\n .join(\",\")}}\", \"return \"+${JSON.stringify(\n row_color_formula\n )}))(row.getData());\n if(rowcol) {\n row.getElement().style.backgroundColor = rowcol;\n }`\n : \"\"\n }\n },`\n : ``\n }\n layout:\"fit${fit || \"Columns\"}\", \n ${responsiveLayout ? `responsiveLayout: \"${responsiveLayout}\",` : \"\"}\n columns,\n pagination:${!!pagination_enabled},\n paginationSize:${\n !pagination_enabled && ajax_load ? 100 : pagination_size || 20\n },\n paginationSizeSelector: ${auto_pagination_size ? false : JSON.stringify(paginationSizeChoices)},\n clipboard:true,\n ${\n select_range\n ? `selectableRange:1,\n selectableRangeColumns:true,\n selectableRangeRows:true,\n selectableRangeClearCells:true,\n editTriggerEvent:\"dblclick\",\n clipboardCopyStyled:false,\n clipboardCopyConfig:{\n rowHeaders:false,\n columnHeaders:false,\n },\n clipboardCopyRowRange:\"range\",\n clipboardPasteParser:customPasteParser,\n clipboardPasteAction:\"range\",`\n : \"\"\n }\n ${persistent ? `initialHeaderFilter,` : \"\"}\n persistence:${!!persistent}, \n persistenceID:\"tabview_${viewname}\",\n movableColumns: ${!!movable_cols},\n downloadEncoder: sc_tab_downloadEncoder,\n ${rowContextMenu ? `rowContextMenu: ${rowContextMenu},` : \"\"}\n history: ${!!history},\n ${\n tree_field\n ? \"dataTree:true,dataTreeStartExpanded:true,dataTreeSelectPropagate:true,\"\n : \"\"\n }\n ${\n tree_field && selectable\n ? `dataTreeElementColumn:\"${\n use_tabcolumns.find((c) => c.field).field\n }\",`\n : \"\"\n }\n ${\n groupBy1\n ? `groupBy: ${\n group_true_label || group_false_label\n ? `(data)=>\n data.${groupBy1}===true\n ? \"${group_true_label || \"True\"}\"\n : data.${groupBy1}===false\n ? \"${group_false_label || \"False\"}\"\n : \"${group_null_label || \"N/A\"}\"`\n : groupBy1 === \"Selected by user\"\n ? \"false\"\n : `\"${groupBy1}\"`\n },`\n : \"\"\n }\n ${\n def_order_field && !groupBy1\n ? `initialSort:[\n \n {column:\"${def_order_field}\", dir:\"${\n def_order_descending ? \"desc\" : \"asc\"\n }\"},\n ],`\n : \"\"\n }\n ajaxResponse:function(url, params, response){ \n if(typeof response.success!==\"undefined\")\n return response.success; //return the tableData property of a response json object\n else return response\n },\n });\n ${\n auto_pagination_size && pagination_enabled\n ? `\n (function(){\n const _tab = window.tabulator_table_${rndid};\n const _tabEl = document.getElementById(\"tabgrid${viewname.replaceAll(\" \", \"\")}${rndid}\");\n function _tab_fill_h() {\n if (!_tabEl) return 400;\n const viewH = (window.visualViewport ? window.visualViewport.height : window.innerHeight);\n return Math.max(200, Math.floor(viewH - _tabEl.getBoundingClientRect().top - 10));\n }\n function _tab_calc_sz() {\n const holder = _tabEl ? _tabEl.querySelector('.tabulator-tableholder') : null;\n if (!holder || !window._tab_row_h_${rndid}) return ${pagination_size || 20};\n return Math.max(5, Math.floor(holder.clientHeight / window._tab_row_h_${rndid}));\n }\n _tab.on(\"tableBuilt\", function() {\n const h = _tab_fill_h();\n _tabEl.style.height = h + \"px\";\n _tab.setHeight(h);\n const vhPx = (window.visualViewport ? window.visualViewport.height : window.innerHeight) + \"px\";\n document.documentElement.style.height = vhPx;\n document.documentElement.style.maxHeight = vhPx;\n document.documentElement.style.overflow = \"hidden\";\n document.body.style.height = vhPx;\n document.body.style.maxHeight = vhPx;\n document.body.style.overflow = \"hidden\";\n });\n var _tab_adjusting_${rndid} = false;\n _tab.on(\"renderComplete\", function() {\n if (_tab_adjusting_${rndid}) return;\n requestAnimationFrame(function() {\n const rows = _tab.getRows(\"visible\");\n if (rows && rows.length) {\n const rh = rows[0].getElement().offsetHeight;\n if (rh > 0) window._tab_row_h_${rndid} = rh;\n }\n const newSz = _tab_calc_sz();\n if (newSz !== _tab.getPageSize()) {\n _tab_adjusting_${rndid} = true;\n _tab.setPageSize(newSz);\n setTimeout(function() { _tab_adjusting_${rndid} = false; }, 200);\n }\n });\n });\n var _tab_resize_timer_${rndid};\n var _tab_editing_${rndid} = false;\n _tab.on(\"cellEditing\", function() { _tab_editing_${rndid} = true; });\n _tab.on(\"cellEditCancelled\", function() { _tab_editing_${rndid} = false; });\n _tab.on(\"cellEdited\", function() { _tab_editing_${rndid} = false; });\n const _tab_on_resize_${rndid} = function() {\n if (_tab_editing_${rndid}) return;\n clearTimeout(_tab_resize_timer_${rndid});\n _tab_resize_timer_${rndid} = setTimeout(function() {\n const h = _tab_fill_h();\n _tabEl.style.height = h + \"px\";\n _tab.setHeight(h);\n _tab.setPageSize(_tab_calc_sz());\n }, 150);\n };\n window.addEventListener(\"resize\", _tab_on_resize_${rndid});\n if (window.visualViewport) {\n window.visualViewport.addEventListener(\"resize\", _tab_on_resize_${rndid});\n }\n })();\n `\n : \"\"\n }\n const save_row_from_cell= gen_save_row_from_cell(${JSON.stringify({\n confirm_edits,\n hasCalculated,\n rndid,\n table_name: table.name,\n viewname,\n })});\n if(${!!persistent}) {\n var firstFilter = true;\n window.tabulator_table_${rndid}.on(\"dataFiltered\", function(filters, rows){\n if(firstFilter) {firstFilter= false; return;}\n localStorage.setItem('tabfiltr_${viewname}', JSON.stringify(filters));\n });\n setTimeout(()=>{\n try {\n const filters = JSON.parse(localStorage.getItem('tabfiltr_${viewname}'));\n for(const filter of filters||[])\n window.tabulator_table_${rndid}.setHeaderFilterValue(filter.field, filter.value);\n } catch(e) {\n console.error(e)\n }\n })\n }\n ${\n select_range\n ? `window.tabulator_table_${rndid}.on(\"clipboardPasted\", function(clipboard, rowData, rows){\n rows.forEach((row, ix)=>{\n const keys = Object.keys(rowData[ix])\n keys.forEach((key)=>{\n save_row_from_cell(row.data, key)\n })\n })\n\n })`\n : ``\n }\n window.tabulator_table_${rndid}.on(\"cellEditing\", function(cell) {storeRowEditing(cell)})\n window.tabulator_table_${rndid}.on(\"cellEdited\", function(cell){\n const row=cell.getRow().getData();\n if(cell.getField()===\"${dropdown_id}\"){\n const val = cell.getValue();\n const action= row[val]\n if(typeof action===\"string\") {\n const form = document.createElement('form');\n form.method = 'POST';\n form.action = action;\n const hiddenField = document.createElement('input');\n hiddenField.type = 'hidden';\n hiddenField.name = '_csrf';\n hiddenField.value = _sc_globalCsrf;\n form.appendChild(hiddenField);\n document.body.appendChild(form);\n form.submit();\n } \n if(action && action.javascript)\n eval(action.javascript) \n }\n else save_row_from_cell(row, cell)\n });\n window.tabulator_table_${rndid}.on(\"historyUndo\", function(action, component, data){\n \n switch (action) {\n case \"cellEdit\": \n save_row_from_cell(component.getRow().getData(), component)\n break;\n case \"rowDelete\": \n const {id, ...delRow} = data.data\n save_row_from_cell( data.data, undefined, true)\n break;\n }\n })\n window.tabulator_table_${rndid}.on(\"historyRedo\", function(action, component, data){\n switch (action) {\n case \"cellEdit\": \n save_row_from_cell(component.getRow().getData(), component)\n break;\n }\n })\n window.tabulator_table_name_${rndid}=\"${table.name}\";\n window.tab_remove_unselected = () =>{\n const allRowCount = window.tabulator_table_${rndid}.getDataCount();\n const selRowCount = window.tabulator_table_${rndid}.getDataCount(\"selected\");\n if(selRowCount < allRowCount/2) {\n const rows = window.tabulator_table_${rndid}.getData(\"selected\");\n window.tabulator_table_${rndid}.clearData();\n for(const row of rows) \n window.tabulator_table_${rndid}.addRow(row);\n } else {\n const selected = new Set(window.tabulator_table_${rndid}.getSelectedRows().map(r=>r.getIndex()));\n const rows = window.tabulator_table_${rndid}.getRows();\n const to_delete=[]\n for(const row of rows) \n if(!selected.has(row.getIndex())) \n to_delete.push(row); \n \n window.tabulator_table_${rndid}.deleteRow(to_delete);\n }\n }\n window.tab_reset_persistcfg = () =>{\n for (const key in localStorage){\n if(key.startsWith('tabulator-tabview_${viewname}-'))\n localStorage.removeItem(key);\n }\n window.tabulator_table_${rndid}.clearFilter(true);\n location.reload();\n }\n window.allnonecols= (do_show, e) =>{\n columns.forEach(col=>{\n if(col.frozen && !do_show) return;\n if (do_show) window.tabulator_table_${rndid}.showColumn(col.field);\n else window.tabulator_table_${rndid}.hideColumn(col.field);\n $(e).closest(\"form\").find(\"input\").prop(\"checked\", do_show)\n })\n }\n ${\n download_csv\n ? `document.getElementById(\"tabulator-download-csv\").addEventListener(\"click\", function(){\n const selectedData = window.tabulator_table_${rndid}.getSelectedData();\n window.tabulator_table_${rndid}.download(tabCustomCsvDownload, \"${viewname}.csv\",{}, selectedData.length>0 ? \"selected\" : \"all\");\n });`\n : \"\"\n }`)\n ),\n\n history &&\n button(\n {\n class: \"btn btn-sm btn-primary mx-1\",\n title: \"Undo\",\n onClick: `window.tabulator_table_${rndid}.undo()`,\n },\n i({ class: \"fas fa-undo\" })\n ),\n history &&\n button(\n {\n class: \"btn btn-sm btn-primary mx-1\",\n title: \"Redo\",\n onClick: `window.tabulator_table_${rndid}.redo()`,\n },\n i({ class: \"fas fa-redo\" })\n ),\n groupBy === \"Selected by user\" &&\n selectGroupBy(\n fields,\n columns,\n rndid,\n def_order_field,\n def_order_descending,\n default_group_by\n ),\n selected_rows_action &&\n button(\n {\n class: \"btn btn-sm btn-primary mx-1 tabselrowaction\",\n title: \"on selected rows\",\n onClick: `press_store_button(this);run_selected_rows_action('${viewname}', ${selectable}, '${rndid}', ${!!tree_field})`,\n \"data-label\": selected_rows_action_name,\n },\n selected_rows_action_name\n ),\n\n remove_unselected_btn &&\n button(\n {\n class: \"btn btn-sm btn-primary mx-1\",\n title: \"Redo\",\n onClick: `tab_remove_unselected()`,\n },\n \"Show selection\"\n ),\n download_csv &&\n button(\n {\n class: \"btn btn-sm btn-primary mx-1\",\n id: \"tabulator-download-csv\",\n },\n i({ class: \"fas fa-download me-1\" }),\n \"Download\"\n ),\n reset_persistent_btn &&\n button(\n {\n class: \"btn btn-sm btn-primary mx-1\",\n title: \"Reset\",\n onClick: `tab_reset_persistcfg()`,\n },\n \"Reset\"\n ),\n addRowBtn && addRowButton(rndid),\n hideColsBtn &&\n hideShowColsBtn(\n tabcolumns,\n column_visibility_presets,\n presets,\n (extraArgs.req?.user?.role_id || public_user_role) <=\n (min_role_preset_edit || 1),\n viewname,\n rndid\n ),\n override_stylesheet &&\n link({\n rel: \"stylesheet\",\n href: `/plugins/public/tabulator@${\n (__webpack_require__(/*! ./package.json */ \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/package.json\").version)\n }/tabulator_${override_stylesheet}.min.css`,\n }),\n\n div({ id: \"jsGridNotify\", class: \"my-1\" }),\n\n div({\n id: `tabgrid${viewname.replaceAll(\" \", \"\")}${rndid}`,\n class: isDark(extraArgs.req) ? \"table-dark\" : undefined,\n style: { height: auto_pagination_size && pagination_enabled ? \"400px\" : height || \"100%\" },\n })\n );\n};\n\nconst add_preset = async (\n table_id,\n viewname,\n { presets, min_role_preset_edit },\n body,\n { req, res }\n) => {\n if ((req.user?.role_id || public_user_role) > (min_role_preset_edit || 1)) {\n console.log(\"not authorized\", min_role_preset_edit);\n return;\n }\n const newPresets = presets || {};\n newPresets[body.name] = body.preset;\n const view = await View.findOne({ name: viewname });\n const newConfig = {\n configuration: { ...view.configuration, presets: newPresets },\n };\n await View.update(newConfig, view.id);\n};\n\nconst delete_preset = async (\n table_id,\n viewname,\n { presets, min_role_preset_edit },\n body,\n { req, res }\n) => {\n if ((req.user?.role_id || public_user_role) > +(min_role_preset_edit || 1)) {\n console.log(\"not authorized\");\n return;\n }\n\n const newPresets = presets || {};\n delete newPresets[body.name];\n const view = await View.findOne({ name: viewname });\n const newConfig = {\n configuration: { ...view.configuration, presets: newPresets },\n };\n await View.update(newConfig, view.id);\n};\nconst get_db_rows = async (\n table,\n fields,\n viewname,\n {\n layout,\n columns,\n groupBy,\n def_order_field,\n def_order_descending,\n tree_field,\n default_group_by,\n group_order_desc,\n header_filters,\n vert_col_headers,\n dropdown_frozen,\n disable_edit_if,\n include_fml,\n },\n state,\n req,\n isPreview,\n queriesObj,\n limit,\n offset,\n alsoCount,\n filter,\n sort\n) => {\n const fieldNames = new Set(fields.map((f) => f.name));\n\n const where = await stateFieldsToWhere({\n fields,\n state,\n table,\n prefix: \"a.\",\n });\n const whereForCount = stateFieldsToWhere({\n fields,\n state,\n table,\n });\n const q = await stateFieldsToQuery({ state, fields, prefix: \"a.\" });\n let postFetchSort;\n let postFetchFilter;\n if (filter) {\n filter.forEach(({ field, type, value }) => {\n if (fieldNames.has(field)) {\n const wh_val =\n type === \"like\"\n ? { ilike: value }\n : value.start || value.end\n ? { gt: value.start, lt: value.end }\n : value;\n where[field] = wh_val;\n whereForCount[field] = wh_val;\n } else {\n if (!postFetchFilter) postFetchFilter = [];\n const valS = `${value}`;\n if (type === \"like\")\n postFetchFilter.push((r) =>\n `${r[field] || \"\"}`.toLowerCase().includes(valS.toLocaleLowerCase())\n );\n else if (value.start || value.end)\n postFetchFilter.push((r) => {\n let v = r[field];\n if (isNaN(v)) return false;\n return value.start && value.end\n ? v >= value.start && v <= value.end\n : value.start\n ? v >= value.start\n : v <= value.end;\n });\n else if (value.start === \"\" && value.end == \"\") {\n //do nothing\n } else postFetchFilter.push((r) => `${r[field] || \"\"}` == value);\n }\n });\n }\n\n if (sort && sort.length === 1) {\n sort.forEach(({ field, dir }) => {\n if (fieldNames.has(field)) {\n q.orderBy = field;\n q.orderDesc = dir === \"desc\";\n } else postFetchSort = { field, desc: dir === \"desc\" };\n });\n }\n //const rows_per_page = default_state && default_state._rows_per_page;\n //if (!q.limit && rows_per_page) q.limit = rows_per_page;\n if (!q.orderBy) q.orderBy = def_order_field || table.pk_name;\n if (limit && !postFetchSort && !postFetchFilter) q.limit = limit;\n else if (isPreview) q.limit = 20;\n if (offset && !postFetchSort && !postFetchFilter) q.offset = offset;\n //if (!q.orderDesc) q.orderDesc = default_state && default_state._descending;\n const current_page = parseInt(state._page) || 1;\n const { joinFields, aggregations } = picked_fields_to_query(columns, fields);\n await set_join_fieldviews({ columns, fields });\n let groupBy1 = groupBy;\n if (groupBy1) {\n if (groupBy === \"Selected by user\" && default_group_by)\n groupBy1 = default_group_by;\n const groupField = fields.find((f) => f.name === groupBy1);\n if (groupField && groupField.is_fkey) {\n let orginalName = groupBy1;\n groupBy1 = `${groupBy1}_${groupField?.attributes?.summary_field || \"id\"}`;\n if (!joinFields[groupBy1])\n joinFields[groupBy1] = {\n ref: orginalName,\n target: groupField?.attributes?.summary_field || \"id\",\n };\n }\n }\n\n if (\n def_order_field &&\n def_order_descending &&\n typeof q.orderDesc === \"undefined\"\n ) {\n q.orderDesc = true;\n }\n\n // console.log(aggregations);\n if (include_fml) {\n const ctx = { ...state, user_id: req.user?.id || null, user: req.user };\n let where1 = jsexprToWhere(include_fml, ctx, fields);\n mergeIntoWhere(where, where1 || {});\n mergeIntoWhere(whereForCount, where1 || {});\n }\n let rows = queriesObj?.get_rows_query\n ? await queriesObj.get_rows_query(where, joinFields, aggregations, q)\n : await table.getJoinedRows({\n where,\n joinFields,\n aggregations,\n ...q,\n forPublic: !req.user,\n forUser: req.user,\n });\n const { calculators } = await get_tabulator_columns(\n viewname,\n table,\n fields,\n columns,\n false,\n req,\n header_filters,\n vert_col_headers,\n dropdown_frozen,\n layout\n );\n calculators.forEach((f) => {\n rows.forEach(f);\n });\n\n if (postFetchFilter) {\n let f = (x) => true;\n postFetchFilter.forEach((filter) => {\n const oldf = f;\n const newf = (x) => filter(x) && oldf(x);\n f = newf;\n });\n rows = rows.filter(f);\n }\n if (postFetchSort) {\n const dirDown = postFetchSort.desc ? 1 : -1;\n const dirUp = postFetchSort.desc ? -1 : 1;\n const cmp = (a, b) => {\n const va = a[postFetchSort.field];\n const vb = b[postFetchSort.field];\n if (typeof va === \"undefined\" && typeof vb !== \"undefined\")\n return dirDown;\n if (typeof va !== \"undefined\" && typeof vb === \"undefined\") return dirUp;\n //console.log({ va, vb, res: va > vb ? dirUp : vb > va ? dirDown : 0 });\n return va > vb ? dirUp : vb > va ? dirDown : 0;\n };\n //console.log(\"sorting\", rows[0]);\n rows.sort(cmp);\n }\n\n if ((postFetchFilter || postFetchSort) && offset) {\n rows = rows.slice(offset);\n }\n if ((postFetchFilter || postFetchSort) && limit) {\n rows = rows.slice(0, limit);\n }\n\n if (tree_field) {\n const my_ids = new Set(rows.map((r) => r.id));\n for (const row of rows) {\n if (row[tree_field] && my_ids.has(row[tree_field]))\n row._parent = row[tree_field];\n else row._parent = null;\n }\n\n rows = nest(rows);\n }\n if (groupBy1 && def_order_field) {\n const dir = def_order_descending ? -1 : 1;\n const dirGroup = group_order_desc ? -1 : 1;\n\n rows.sort((a, b) =>\n a[groupBy1] > b[groupBy1]\n ? dirGroup\n : b[groupBy1] > a[groupBy1]\n ? -1 * dirGroup\n : a[def_order_field] > b[def_order_field]\n ? dir\n : b[def_order_field] > a[def_order_field]\n ? -1 * dir\n : 0\n );\n } else if (groupBy1) {\n const dir = group_order_desc ? -1 : 1;\n\n rows.sort((a, b) =>\n a[groupBy1] > b[groupBy1] ? dir : b[groupBy1] > a[groupBy1] ? -1 * dir : 0\n );\n }\n\n if (disable_edit_if) {\n const set_disable_edit = (row) => {\n if (eval_expression(disable_edit_if, row)) row._disable_edit = true;\n (row._children || []).forEach(set_disable_edit);\n };\n rows.forEach(set_disable_edit);\n }\n\n if (alsoCount) {\n const count = await table.countRows(whereForCount);\n return { rows, count };\n } else return { rows };\n};\nconst get_rows = async (\n table_id,\n viewname,\n cfg,\n { state, page, size, filter, sort },\n { req, res }\n) => {\n //console.log({ filter, sort, state, page, size });\n const table = await Table.findOne({ id: table_id });\n const fields = await table.getFields();\n let limit =\n size === \"true\" || size === true\n ? undefined\n : size || cfg.pagination_size || 50;\n const offset = page && limit ? (+page - 1) * (+limit || 20) : 0;\n const { rows, count } = await get_db_rows(\n table,\n fields,\n viewname,\n cfg,\n state,\n req,\n false,\n undefined,\n limit,\n offset,\n !!page,\n filter,\n sort\n );\n console.log({ size, page, nrows: rows.length });\n\n if (page) {\n if (size)\n return {\n json: {\n data: rows,\n last_page: size === true ? 1 : Math.ceil(count / +size),\n },\n };\n else return { json: { data: rows } };\n } else return { json: rows };\n};\n\nconst run_action = async (\n table_id,\n viewname,\n { columns, layout },\n body,\n { req, res }\n) => {\n const col = body.rndid\n ? columns.find((c) => c.type === \"Action\" && c.rndid === body.rndid)\n : columns.find(\n //legacy\n (c) =>\n c.type === \"Action\" &&\n c.action_name === body.action_name &&\n body.action_name\n );\n //console.log({ col, body });\n const table = await Table.findOne({ id: table_id });\n const pk = table.pk_name;\n const row = await table.getRow({ [pk]: body[pk] });\n const state_action = getState().actions[col.action_name];\n col.configuration = col.configuration || {};\n if (state_action) {\n const cfgFields = await getActionConfigFields(state_action, table);\n cfgFields.forEach(({ name }) => {\n if (typeof col[name] !== \"undefined\") col.configuration[name] = col[name];\n });\n }\n try {\n const result = await run_action_column({\n col,\n req,\n res,\n table,\n row,\n user: req.user,\n referrer: req.get(\"Referrer\"),\n });\n return { json: { success: \"ok\", ...(result || {}) } };\n } catch (e) {\n return { json: { error: e.message || e } };\n }\n};\n\nconst run_selected_rows_action = async (\n table_id,\n viewname,\n { selected_rows_action, selected_rows_action_once },\n { rows, action_edit_row, rndid },\n { req, res }\n) => {\n if (selected_rows_action.startsWith(\"Edit:\")) {\n if (action_edit_row) {\n const table = Table.findOne(table_id);\n const fields = new Set(table.fields.map((f) => f.name));\n const upd = {};\n Object.keys(action_edit_row).forEach((k) => {\n const v = action_edit_row[k];\n if (v === \"\" || typeof v === \"undefined\") return;\n if (fields.has(k)) upd[k] = v;\n });\n for (const row of rows) {\n await table.updateRow(\n upd,\n row[table.pk_name],\n req.user || { role_id: 100 }\n );\n }\n return {};\n } else\n return {\n json: {\n eval_js: `run_action_multi_edit(\"${selected_rows_action.replaceAll(\n \"Edit:\",\n \"\"\n )}\", \"${rndid}\", \"${viewname}\")`,\n },\n };\n }\n const table = await Table.findOne({ id: table_id });\n\n const trigger = await Trigger.findOne({ name: selected_rows_action });\n if (!trigger)\n return { json: { error: \"Trigger not found: \" + selected_rows_action } };\n const action = getState().actions[trigger.action];\n if (!action)\n return { json: { error: \"Action not found: \" + trigger.action } };\n\n let result;\n const actionArg = {\n referrer: req.get(\"Referrer\"),\n table,\n req,\n Table,\n user: req.user,\n configuration: trigger.configuration,\n };\n if (selected_rows_action_once)\n result = await action.run({\n rows,\n ...actionArg,\n });\n else\n for (const row of rows)\n result = await action.run({\n row,\n ...actionArg,\n });\n\n return { json: { success: \"ok\", ...(result || {}) } };\n};\n\nconst createBasicView = async ({\n table,\n viewname,\n template_view,\n template_table,\n all_views_created,\n}) => {\n /* \n FROM TEMPLATE TABLE\n\n - has show link? label, style, hdr label\n - has edit link? label, style, hdr label\n */\n\n const configuration = await initial_config_all_fields(false)({\n table_id: table.id,\n });\n delete configuration.layout;\n let template_table_views = {};\n if (template_view) {\n (\n await View.find({\n table_id: template_table.id,\n })\n ).forEach((v) => {\n template_table_views[v.name] = v.viewtemplate;\n });\n\n template_view.configuration.columns.forEach((c) => {\n if (c.type === \"Field\") {\n const field = template_table.getField(c.field_name);\n c.field_type = field.type.name || field.type;\n }\n });\n configuration.columns.forEach((mycol) => {\n if (mycol.type === \"Field\") {\n const field_name = mycol.field_name;\n const field = table.getField(field_name);\n const field_type = field.type.name || field.type;\n const matched = template_view.configuration.columns.find(\n (c) => c.field_type === field_type\n );\n if (matched) {\n if (matched.configuration)\n Object.assign(mycol, matched.configuration);\n Object.assign(mycol, matched);\n mycol.field_name = field_name;\n }\n }\n });\n }\n //show link\n if (all_views_created.Show) {\n if (template_view) {\n //find link to show view\n const col = template_view.configuration.columns.find(\n (c) =>\n c.type === \"ViewLink\" &&\n template_table_views[c.view?.split?.(\":\")[1]] === \"Show\"\n );\n if (col) {\n configuration.columns.push({\n ...col,\n view: `Own:${all_views_created.Show}`,\n view_name: all_views_created.Show,\n relation: undefined,\n view_label: col.view_label || col.label,\n });\n }\n } else\n configuration.columns.push({\n type: \"ViewLink\",\n view: `Own:${all_views_created.Show}`,\n view_name: all_views_created.Show,\n link_style: \"\",\n view_label: \"Show\",\n header_label: \"Show\",\n });\n }\n\n //edit link\n if (all_views_created.Edit) {\n if (template_view) {\n //find link to show view\n const col = template_view.configuration.columns.find(\n (c) =>\n c.type === \"ViewLink\" &&\n template_table_views[c.view?.split?.(\":\")[1]] === \"Edit\"\n );\n if (col) {\n configuration.columns.push({\n ...col,\n view: `Own:${all_views_created.Edit}`,\n view_name: all_views_created.Edit,\n relation: undefined,\n view_label: col.view_label || col.label,\n });\n }\n } else\n configuration.columns.push({\n type: \"ViewLink\",\n view: `Own:${all_views_created.Edit}`,\n view_name: all_views_created.Edit,\n link_style: \"\",\n view_label: \"Edit\",\n header_label: \"Edit\",\n });\n }\n if (template_view) {\n const matched = template_view.configuration.columns.filter(\n (c) => c.type === \"Action\"\n );\n if (matched.length) configuration.columns.push(...matched);\n } else\n configuration.columns.push({\n type: \"Action\",\n action_name: \"Delete\",\n action_style: \"btn-primary\",\n });\n\n const copy_cfg = (keys) => {\n for (const key of Array.isArray(keys)\n ? keys\n : keys.split(\" \").filter(Boolean)) {\n configuration[key] = template_view.configuration[key];\n }\n };\n\n // create new row options\n\n if (template_view && all_views_created.Edit) {\n copy_cfg(\n \"fit responsiveLayout hideColsBtn hide_null_columns addRowBtn selectable remove_unselected_btn download_csv header_filters pagination_enabled pagination_size auto_pagination_size movable_cols history persistent dropdown_frozen vert_col_headers reset_persistent_btn def_order_descending column_visibility_presets presets min_role_preset_edit tree_field selected_rows_action group_true_label group_false_label group_null_label group_order_desc header_wrap override_stylesheet ajax_load confirm_edits disable_edit_if row_color_formula select_range height\"\n );\n }\n return configuration;\n};\n\nmodule.exports = {\n headers: ({ stylesheet }) => [\n {\n script: `/plugins/public/tabulator${\n features?.version_plugin_serve_path\n ? \"@\" + (__webpack_require__(/*! ./package.json */ \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/package.json\").version)\n : \"\"\n }/tabulator.min.js`,\n onlyViews: [\"Tabulator\", \"Tabulator Pivot Edit\"],\n },\n {\n script: `/plugins/public/tabulator${\n features?.version_plugin_serve_path\n ? \"@\" + (__webpack_require__(/*! ./package.json */ \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/package.json\").version)\n : \"\"\n }/custom.js`,\n onlyViews: [\"Tabulator\", \"Tabulator Pivot Edit\"],\n },\n {\n script: `/plugins/public/tabulator@${\n (__webpack_require__(/*! ./package.json */ \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/package.json\").version)\n }/luxon.min.js`,\n onlyViews: [\"Tabulator\", \"Tabulator Pivot Edit\"],\n },\n {\n script: `/static_assets/${db.connectObj.version_tag}/flatpickr.min.js`,\n },\n {\n css: `/static_assets/${db.connectObj.version_tag}/flatpickr.min.css`,\n },\n {\n script: `/static_assets/${db.connectObj.version_tag}/gridedit.js`,\n },\n {\n css: `/plugins/public/tabulator${\n features?.version_plugin_serve_path\n ? \"@\" + (__webpack_require__(/*! ./package.json */ \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/package.json\").version)\n : \"\"\n }/tabulator_${stylesheet || \"bootstrap5\"}.min.css`,\n onlyViews: [\"Tabulator\", \"Tabulator Pivot Edit\"],\n },\n ],\n sc_plugin_api_version: 1,\n plugin_name: \"tabulator\",\n configuration_workflow,\n fieldviews: features.ellipsize\n ? undefined\n : () => ({\n ellipsize: {\n type: \"String\",\n isEdit: false,\n configFields: [\n {\n name: \"nchars\",\n label: \"Number of characters\",\n type: \"Integer\",\n default: 20,\n },\n ],\n description:\n \"Show First N characters of text followed by ... if truncated\",\n run: (s, req, attrs = {}) => {\n if (!s || !s.length) return \"\";\n if (s.length <= (attrs.nchars || 20)) return text_attr(s);\n return text_attr(s.substr(0, (attrs.nchars || 20) - 3)) + \"...\";\n },\n },\n }),\n viewtemplates: () => [\n {\n name: \"Tabulator\",\n display_state_form: false,\n get_state_fields,\n configuration_workflow: view_configuration_workflow,\n run,\n initial_config,\n createBasicView,\n configCheck: async (view) => {\n const colcheck = await check_view_columns(\n view,\n view.configuration.columns\n );\n const { errors, warnings } = Array.isArray(colcheck) // legacy\n ? { errors: colcheck, warnings: [] }\n : colcheck;\n const selected_rows_action = view.configuration.selected_rows_action;\n if (selected_rows_action) {\n const trigger = await Trigger.findOne({ name: selected_rows_action });\n if (!trigger)\n errors.push(\n `In view ${view.name}, Trigger for selected_rows_action not found: ` +\n selected_rows_action\n );\n else if (!getState().actions[trigger.action])\n errors.push(\n `In view ${view.name}, Action for selected_rows_action not found: ` +\n trigger.action\n );\n }\n if (view.configuration.ajax_load) {\n const table = await Table.findOne({ id: view.table_id });\n const fields = await table.getFields();\n const { rows } = await get_db_rows(\n table,\n fields,\n view.viewname,\n view.configuration,\n {},\n mockReqRes.req,\n false,\n undefined,\n 5\n );\n if (!Array.isArray(rows))\n errors.push(\n `In view ${view.name}, something went wrong when retriving rows.`\n );\n }\n return { errors, warnings };\n },\n routes: {\n run_action,\n get_rows,\n run_selected_rows_action,\n add_preset,\n delete_preset,\n },\n queries: ({ table_id, req }) => ({\n async get_rows_query(where, joinFields, aggregations, q) {\n const table = await Table.findOne({ id: table_id });\n return await table.getJoinedRows({\n where,\n joinFields,\n aggregations,\n ...q,\n forPublic: !req.user,\n forUser: req.user,\n });\n },\n }),\n },\n __webpack_require__(/*! ./pivot-edit */ \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/pivot-edit.js\"),\n ],\n ready_for_mobile: true,\n};\n\nconst fragment = (...args) => args.filter((s) => s).join(\"\");\n\n\n//# sourceURL=webpack://saltcorn/../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/index.js?\n}");
38
+
39
+ /***/ },
40
+
41
+ /***/ "../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale sync recursive ^\\.\\/.*$"
42
+ /*!***********************************************************************************************************************************!*\
43
+ !*** ../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ sync ^\.\/.*$ ***!
44
+ \***********************************************************************************************************************************/
45
+ (module, __unused_webpack_exports, __webpack_require__) {
46
+
47
+ eval("{var map = {\n\t\"./af\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/af.js\",\n\t\"./af.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/af.js\",\n\t\"./ar\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ar.js\",\n\t\"./ar-dz\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ar-dz.js\",\n\t\"./ar-dz.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ar-dz.js\",\n\t\"./ar-kw\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ar-kw.js\",\n\t\"./ar-kw.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ar-kw.js\",\n\t\"./ar-ly\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ar-ly.js\",\n\t\"./ar-ly.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ar-ly.js\",\n\t\"./ar-ma\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ar-ma.js\",\n\t\"./ar-ma.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ar-ma.js\",\n\t\"./ar-sa\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ar-sa.js\",\n\t\"./ar-sa.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ar-sa.js\",\n\t\"./ar-tn\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ar-tn.js\",\n\t\"./ar-tn.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ar-tn.js\",\n\t\"./ar.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ar.js\",\n\t\"./az\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/az.js\",\n\t\"./az.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/az.js\",\n\t\"./be\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/be.js\",\n\t\"./be.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/be.js\",\n\t\"./bg\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/bg.js\",\n\t\"./bg.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/bg.js\",\n\t\"./bm\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/bm.js\",\n\t\"./bm.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/bm.js\",\n\t\"./bn\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/bn.js\",\n\t\"./bn-bd\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/bn-bd.js\",\n\t\"./bn-bd.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/bn-bd.js\",\n\t\"./bn.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/bn.js\",\n\t\"./bo\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/bo.js\",\n\t\"./bo.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/bo.js\",\n\t\"./br\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/br.js\",\n\t\"./br.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/br.js\",\n\t\"./bs\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/bs.js\",\n\t\"./bs.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/bs.js\",\n\t\"./ca\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ca.js\",\n\t\"./ca.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ca.js\",\n\t\"./cs\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/cs.js\",\n\t\"./cs.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/cs.js\",\n\t\"./cv\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/cv.js\",\n\t\"./cv.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/cv.js\",\n\t\"./cy\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/cy.js\",\n\t\"./cy.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/cy.js\",\n\t\"./da\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/da.js\",\n\t\"./da.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/da.js\",\n\t\"./de\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/de.js\",\n\t\"./de-at\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/de-at.js\",\n\t\"./de-at.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/de-at.js\",\n\t\"./de-ch\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/de-ch.js\",\n\t\"./de-ch.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/de-ch.js\",\n\t\"./de.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/de.js\",\n\t\"./dv\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/dv.js\",\n\t\"./dv.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/dv.js\",\n\t\"./el\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/el.js\",\n\t\"./el.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/el.js\",\n\t\"./en-au\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/en-au.js\",\n\t\"./en-au.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/en-au.js\",\n\t\"./en-ca\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/en-ca.js\",\n\t\"./en-ca.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/en-ca.js\",\n\t\"./en-gb\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/en-gb.js\",\n\t\"./en-gb.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/en-gb.js\",\n\t\"./en-ie\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/en-ie.js\",\n\t\"./en-ie.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/en-ie.js\",\n\t\"./en-il\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/en-il.js\",\n\t\"./en-il.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/en-il.js\",\n\t\"./en-in\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/en-in.js\",\n\t\"./en-in.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/en-in.js\",\n\t\"./en-nz\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/en-nz.js\",\n\t\"./en-nz.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/en-nz.js\",\n\t\"./en-sg\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/en-sg.js\",\n\t\"./en-sg.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/en-sg.js\",\n\t\"./eo\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/eo.js\",\n\t\"./eo.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/eo.js\",\n\t\"./es\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/es.js\",\n\t\"./es-do\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/es-do.js\",\n\t\"./es-do.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/es-do.js\",\n\t\"./es-mx\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/es-mx.js\",\n\t\"./es-mx.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/es-mx.js\",\n\t\"./es-us\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/es-us.js\",\n\t\"./es-us.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/es-us.js\",\n\t\"./es.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/es.js\",\n\t\"./et\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/et.js\",\n\t\"./et.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/et.js\",\n\t\"./eu\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/eu.js\",\n\t\"./eu.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/eu.js\",\n\t\"./fa\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/fa.js\",\n\t\"./fa.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/fa.js\",\n\t\"./fi\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/fi.js\",\n\t\"./fi.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/fi.js\",\n\t\"./fil\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/fil.js\",\n\t\"./fil.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/fil.js\",\n\t\"./fo\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/fo.js\",\n\t\"./fo.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/fo.js\",\n\t\"./fr\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/fr.js\",\n\t\"./fr-ca\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/fr-ca.js\",\n\t\"./fr-ca.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/fr-ca.js\",\n\t\"./fr-ch\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/fr-ch.js\",\n\t\"./fr-ch.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/fr-ch.js\",\n\t\"./fr.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/fr.js\",\n\t\"./fy\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/fy.js\",\n\t\"./fy.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/fy.js\",\n\t\"./ga\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ga.js\",\n\t\"./ga.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ga.js\",\n\t\"./gd\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/gd.js\",\n\t\"./gd.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/gd.js\",\n\t\"./gl\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/gl.js\",\n\t\"./gl.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/gl.js\",\n\t\"./gom-deva\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/gom-deva.js\",\n\t\"./gom-deva.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/gom-deva.js\",\n\t\"./gom-latn\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/gom-latn.js\",\n\t\"./gom-latn.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/gom-latn.js\",\n\t\"./gu\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/gu.js\",\n\t\"./gu.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/gu.js\",\n\t\"./he\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/he.js\",\n\t\"./he.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/he.js\",\n\t\"./hi\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/hi.js\",\n\t\"./hi.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/hi.js\",\n\t\"./hr\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/hr.js\",\n\t\"./hr.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/hr.js\",\n\t\"./hu\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/hu.js\",\n\t\"./hu.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/hu.js\",\n\t\"./hy-am\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/hy-am.js\",\n\t\"./hy-am.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/hy-am.js\",\n\t\"./id\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/id.js\",\n\t\"./id.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/id.js\",\n\t\"./is\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/is.js\",\n\t\"./is.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/is.js\",\n\t\"./it\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/it.js\",\n\t\"./it-ch\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/it-ch.js\",\n\t\"./it-ch.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/it-ch.js\",\n\t\"./it.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/it.js\",\n\t\"./ja\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ja.js\",\n\t\"./ja.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ja.js\",\n\t\"./jv\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/jv.js\",\n\t\"./jv.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/jv.js\",\n\t\"./ka\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ka.js\",\n\t\"./ka.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ka.js\",\n\t\"./kk\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/kk.js\",\n\t\"./kk.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/kk.js\",\n\t\"./km\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/km.js\",\n\t\"./km.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/km.js\",\n\t\"./kn\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/kn.js\",\n\t\"./kn.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/kn.js\",\n\t\"./ko\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ko.js\",\n\t\"./ko.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ko.js\",\n\t\"./ku\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ku.js\",\n\t\"./ku.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ku.js\",\n\t\"./ky\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ky.js\",\n\t\"./ky.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ky.js\",\n\t\"./lb\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/lb.js\",\n\t\"./lb.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/lb.js\",\n\t\"./lo\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/lo.js\",\n\t\"./lo.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/lo.js\",\n\t\"./lt\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/lt.js\",\n\t\"./lt.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/lt.js\",\n\t\"./lv\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/lv.js\",\n\t\"./lv.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/lv.js\",\n\t\"./me\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/me.js\",\n\t\"./me.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/me.js\",\n\t\"./mi\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/mi.js\",\n\t\"./mi.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/mi.js\",\n\t\"./mk\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/mk.js\",\n\t\"./mk.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/mk.js\",\n\t\"./ml\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ml.js\",\n\t\"./ml.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ml.js\",\n\t\"./mn\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/mn.js\",\n\t\"./mn.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/mn.js\",\n\t\"./mr\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/mr.js\",\n\t\"./mr.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/mr.js\",\n\t\"./ms\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ms.js\",\n\t\"./ms-my\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ms-my.js\",\n\t\"./ms-my.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ms-my.js\",\n\t\"./ms.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ms.js\",\n\t\"./mt\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/mt.js\",\n\t\"./mt.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/mt.js\",\n\t\"./my\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/my.js\",\n\t\"./my.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/my.js\",\n\t\"./nb\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/nb.js\",\n\t\"./nb.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/nb.js\",\n\t\"./ne\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ne.js\",\n\t\"./ne.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ne.js\",\n\t\"./nl\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/nl.js\",\n\t\"./nl-be\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/nl-be.js\",\n\t\"./nl-be.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/nl-be.js\",\n\t\"./nl.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/nl.js\",\n\t\"./nn\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/nn.js\",\n\t\"./nn.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/nn.js\",\n\t\"./oc-lnc\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/oc-lnc.js\",\n\t\"./oc-lnc.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/oc-lnc.js\",\n\t\"./pa-in\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/pa-in.js\",\n\t\"./pa-in.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/pa-in.js\",\n\t\"./pl\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/pl.js\",\n\t\"./pl.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/pl.js\",\n\t\"./pt\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/pt.js\",\n\t\"./pt-br\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/pt-br.js\",\n\t\"./pt-br.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/pt-br.js\",\n\t\"./pt.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/pt.js\",\n\t\"./ro\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ro.js\",\n\t\"./ro.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ro.js\",\n\t\"./ru\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ru.js\",\n\t\"./ru.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ru.js\",\n\t\"./sd\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/sd.js\",\n\t\"./sd.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/sd.js\",\n\t\"./se\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/se.js\",\n\t\"./se.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/se.js\",\n\t\"./si\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/si.js\",\n\t\"./si.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/si.js\",\n\t\"./sk\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/sk.js\",\n\t\"./sk.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/sk.js\",\n\t\"./sl\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/sl.js\",\n\t\"./sl.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/sl.js\",\n\t\"./sq\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/sq.js\",\n\t\"./sq.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/sq.js\",\n\t\"./sr\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/sr.js\",\n\t\"./sr-cyrl\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/sr-cyrl.js\",\n\t\"./sr-cyrl.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/sr-cyrl.js\",\n\t\"./sr.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/sr.js\",\n\t\"./ss\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ss.js\",\n\t\"./ss.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ss.js\",\n\t\"./sv\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/sv.js\",\n\t\"./sv.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/sv.js\",\n\t\"./sw\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/sw.js\",\n\t\"./sw.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/sw.js\",\n\t\"./ta\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ta.js\",\n\t\"./ta.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ta.js\",\n\t\"./te\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/te.js\",\n\t\"./te.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/te.js\",\n\t\"./tet\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tet.js\",\n\t\"./tet.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tet.js\",\n\t\"./tg\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tg.js\",\n\t\"./tg.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tg.js\",\n\t\"./th\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/th.js\",\n\t\"./th.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/th.js\",\n\t\"./tk\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tk.js\",\n\t\"./tk.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tk.js\",\n\t\"./tl-ph\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tl-ph.js\",\n\t\"./tl-ph.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tl-ph.js\",\n\t\"./tlh\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tlh.js\",\n\t\"./tlh.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tlh.js\",\n\t\"./tr\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tr.js\",\n\t\"./tr.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tr.js\",\n\t\"./tzl\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tzl.js\",\n\t\"./tzl.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tzl.js\",\n\t\"./tzm\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tzm.js\",\n\t\"./tzm-latn\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tzm-latn.js\",\n\t\"./tzm-latn.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tzm-latn.js\",\n\t\"./tzm.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/tzm.js\",\n\t\"./ug-cn\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ug-cn.js\",\n\t\"./ug-cn.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ug-cn.js\",\n\t\"./uk\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/uk.js\",\n\t\"./uk.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/uk.js\",\n\t\"./ur\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ur.js\",\n\t\"./ur.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/ur.js\",\n\t\"./uz\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/uz.js\",\n\t\"./uz-latn\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/uz-latn.js\",\n\t\"./uz-latn.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/uz-latn.js\",\n\t\"./uz.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/uz.js\",\n\t\"./vi\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/vi.js\",\n\t\"./vi.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/vi.js\",\n\t\"./x-pseudo\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/x-pseudo.js\",\n\t\"./x-pseudo.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/x-pseudo.js\",\n\t\"./yo\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/yo.js\",\n\t\"./yo.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/yo.js\",\n\t\"./zh-cn\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/zh-cn.js\",\n\t\"./zh-cn.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/zh-cn.js\",\n\t\"./zh-hk\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/zh-hk.js\",\n\t\"./zh-hk.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/zh-hk.js\",\n\t\"./zh-mo\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/zh-mo.js\",\n\t\"./zh-mo.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/zh-mo.js\",\n\t\"./zh-tw\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/zh-tw.js\",\n\t\"./zh-tw.js\": \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/zh-tw.js\"\n};\n\n\nfunction webpackContext(req) {\n\tvar id = webpackContextResolve(req);\n\treturn __webpack_require__(id);\n}\nfunction webpackContextResolve(req) {\n\tif(!__webpack_require__.o(map, req)) {\n\t\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\t\te.code = 'MODULE_NOT_FOUND';\n\t\tthrow e;\n\t}\n\treturn map[req];\n}\nwebpackContext.keys = function webpackContextKeys() {\n\treturn Object.keys(map);\n};\nwebpackContext.resolve = webpackContextResolve;\nmodule.exports = webpackContext;\nwebpackContext.id = \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale sync recursive ^\\\\.\\\\/.*$\";\n\n//# sourceURL=webpack://saltcorn/../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/locale/_sync_^\\.\\/.*$?\n}");
48
+
49
+ /***/ },
50
+
51
+ /***/ "../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/pivot-edit.js"
52
+ /*!*******************************************************************************************************!*\
53
+ !*** ../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/pivot-edit.js ***!
54
+ \*******************************************************************************************************/
55
+ (module, __unused_webpack_exports, __webpack_require__) {
56
+
57
+ eval("{const Field = __webpack_require__(/*! @saltcorn/data/models/field */ \"../saltcorn-data/dist/models/field.js\");\nconst User = __webpack_require__(/*! @saltcorn/data/models/user */ \"../saltcorn-data/dist/models/user.js\");\nconst FieldRepeat = __webpack_require__(/*! @saltcorn/data/models/fieldrepeat */ \"../saltcorn-data/dist/models/fieldrepeat.js\");\n\nconst Table = __webpack_require__(/*! @saltcorn/data/models/table */ \"../saltcorn-data/dist/models/table.js\");\nconst { getState, features } = __webpack_require__(/*! @saltcorn/data/db/state */ \"../saltcorn-data/dist/db/state.js\");\nconst db = __webpack_require__(/*! @saltcorn/data/db */ \"../saltcorn-data/dist/db/index.js\");\nconst Form = __webpack_require__(/*! @saltcorn/data/models/form */ \"../saltcorn-data/dist/models/form.js\");\nconst View = __webpack_require__(/*! @saltcorn/data/models/view */ \"../saltcorn-data/dist/models/view.js\");\nconst Workflow = __webpack_require__(/*! @saltcorn/data/models/workflow */ \"../saltcorn-data/dist/models/workflow.js\");\nconst {\n jsexprToWhere,\n eval_expression,\n} = __webpack_require__(/*! @saltcorn/data/models/expression */ \"../saltcorn-data/dist/models/expression.js\");\nconst {\n parse_view_select,\n} = __webpack_require__(/*! @saltcorn/data/base-plugin/viewtemplates/viewable_fields */ \"../saltcorn-data/dist/base-plugin/viewtemplates/viewable_fields.js\");\nconst {\n field_picker_fields,\n picked_fields_to_query,\n stateFieldsToWhere,\n initial_config_all_fields,\n stateToQueryString,\n stateFieldsToQuery,\n link_view,\n getActionConfigFields,\n readState,\n run_action_column,\n} = __webpack_require__(/*! @saltcorn/data/plugin-helper */ \"../saltcorn-data/dist/plugin-helper.js\");\nconst {\n text,\n div,\n h5,\n style,\n a,\n script,\n pre,\n domReady,\n button,\n i,\n form,\n input,\n label,\n text_attr,\n select,\n option,\n link,\n} = __webpack_require__(/*! @saltcorn/markup/tags */ \"../saltcorn-markup/dist/tags.js\");\nconst {\n typeToGridType,\n nest,\n get_tabulator_columns,\n getDarkStyle,\n} = __webpack_require__(/*! ./common */ \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/common.js\");\nconst moment = __webpack_require__(/*! moment */ \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/node_modules/moment/moment.js\");\n\nconst get_state_fields = async (table_id, viewname, { show_view }) => {\n const table = Table.findOne(table_id);\n const table_fields = table.fields;\n return table_fields\n .filter((f) => !f.primary_key)\n .map((f) => {\n const sf = new Field(f);\n sf.required = false;\n return sf;\n });\n};\n\nconst configuration_workflow = (req) =>\n new Workflow({\n steps: [\n {\n name: \"Pivot grid\",\n form: async (context) => {\n const table = await Table.findOne(\n context.table_id\n ? { id: context.table_id }\n : { name: context.exttable_name }\n );\n const fields = await table.getFields();\n const fk_fields = fields.filter((f) => f.is_fkey && f.reftable_name);\n const fk_date_fields = fields.filter(\n (f) => (f.is_fkey && f.reftable_name) || f.type?.name === \"Date\"\n );\n const date_fields = fields.filter((f) => f.type?.name === \"Date\");\n const group_by_options = {};\n for (const fk_field of fk_fields) {\n const reftable = Table.findOne({ name: fk_field.reftable_name });\n if (reftable) {\n const reffields = await reftable.getFields();\n group_by_options[fk_field.name] = [\n \"\",\n ...reffields.map((f) => f.name),\n ];\n }\n }\n const edit_views = await View.find_table_views_where(\n context.table_id,\n ({ state_fields, viewtemplate, viewrow }) =>\n viewrow.name !== context.viewname\n );\n const edit_view_opts = edit_views.map((v) => v.name);\n return new Form({\n fields: [\n { input_type: \"section_header\", label: \"Rows\" },\n {\n name: \"row_field\",\n label: \"Row field\",\n type: \"String\",\n required: true,\n attributes: {\n options: fk_fields.map((f) => f.name),\n },\n },\n {\n name: \"row_where\",\n label: \"Where\",\n sublabel: \"include the rows that match this formula\",\n type: \"String\",\n },\n {\n name: \"groupBy\",\n label: \"Group by\",\n type: \"String\",\n attributes: {\n calcOptions: [\"row_field\", group_by_options],\n },\n },\n {\n input_type: \"section_header\",\n label: \"Columns\",\n disabled: true,\n },\n {\n name: \"col_field\",\n label: \"Column field\",\n type: \"String\",\n required: true,\n attributes: {\n options: fk_date_fields.map((f) => f.name),\n },\n },\n {\n name: \"col_field_format\",\n label: \"Column format\",\n type: \"String\",\n sublabel: \"moment.js format specifier\",\n showIf: {\n col_field: date_fields.map((f) => f.name),\n },\n },\n {\n name: \"col_bin_weeks\",\n label: \"Weekly columns\",\n type: \"Bool\",\n sublabel: \"Instead of daily\",\n showIf: {\n col_field: date_fields.map((f) => f.name),\n },\n },\n {\n name: \"col_no_weekends\",\n label: \"No weekend columns\",\n type: \"Bool\",\n sublabel: \"Exclude weekend days from columns\",\n showIf: {\n col_field: date_fields.map((f) => f.name),\n col_bin_weeks: false,\n },\n },\n {\n name: \"col_width\",\n label: \"Column width (px)\",\n sublabel: \"Optional\",\n type: \"Integer\",\n },\n {\n name: \"vertical_headers\",\n label: \"Vertical headers\",\n type: \"Bool\",\n },\n { input_type: \"section_header\", label: \"Values\" },\n\n {\n name: \"value_field\",\n label: \"Value field\",\n type: \"String\",\n required: true,\n attributes: {\n options: fields.map((f) => f.name),\n },\n },\n {\n name: \"edit_view\",\n label: \"Edit view\",\n sublabel: \"Edit in pop-up view instead of directly in cell\",\n type: \"String\",\n required: false,\n attributes: {\n options: edit_view_opts,\n },\n },\n {\n name: \"new_row_formula\",\n label: \"New row formula\",\n sublabel:\n \"Formula for JavaScript object that will be added to new rows, in addition to values for row, column and value fields. State variable may be used here.\",\n type: \"String\",\n class: \"validate-expression\",\n },\n { input_type: \"section_header\", label: \"Calculated row\" },\n\n {\n name: \"column_calculation\",\n label: \"Column Calculation\",\n type: \"String\",\n attributes: {\n options: [\"avg\", \"max\", \"min\", \"sum\", \"count\"],\n },\n },\n {\n name: \"group_calcs\",\n label: \"Group calculations\",\n type: \"Bool\",\n sublabel: \"Calculations by group\",\n showIf: {\n column_calculation: [\"avg\", \"max\", \"min\", \"sum\", \"count\"],\n },\n },\n {\n name: \"calc_pos\",\n label: \"Calculation position\",\n type: \"String\",\n fieldview: \"radio_group\",\n attributes: {\n options: [\"Top\", \"Bottom\"],\n inline: true,\n },\n showIf: {\n column_calculation: [\"avg\", \"max\", \"min\", \"sum\", \"count\"],\n },\n },\n {\n name: \"target_value\",\n label: \"Target value\",\n sublabel:\n \"Optional. Show matching columns in blue, others in red\",\n type: \"Integer\",\n showIf: {\n column_calculation: [\"avg\", \"max\", \"min\", \"sum\", \"count\"],\n },\n },\n ],\n });\n },\n },\n {\n name: \"Additional columns\",\n form: async (context) => {\n const celltable = await Table.findOne(\n context.table_id\n ? { id: context.table_id }\n : { name: context.exttable_name }\n );\n //console.log(context);\n const row_field = await celltable.getField(context.row_field);\n const table = Table.findOne(row_field.reftable_name);\n const field_picker_repeat = await field_picker_fields({\n table,\n viewname: context.viewname,\n req,\n });\n field_picker_repeat.push({\n name: \"frozen\",\n label: \"Frozen\",\n type: \"Bool\",\n });\n field_picker_repeat.push({\n name: \"disable_edit\",\n label: \"Disable editing\",\n type: \"Bool\",\n showIf: { type: \"Field\" },\n });\n field_picker_repeat.push({\n name: \"column_calculation\",\n label: \"Column Calculation\",\n type: \"String\",\n attributes: {\n options: [\n \"avg\",\n \"max\",\n \"min\",\n \"sum\",\n \"count\",\n { name: \"__tabulator_colcalc_unique\", label: \"count unique\" },\n { name: \"__tabulator_colcalc_counttrue\", label: \"count true\" },\n {\n name: \"__tabulator_colcalc_countfalse\",\n label: \"count false\",\n },\n {\n name: \"__tabulator_colcalc_avgnonulls\",\n label: \"avg no nulls\",\n },\n {\n name: \"__tabulator_colcalc_sumroundquarter\",\n label: \"sum round to quarter\",\n },\n ],\n },\n });\n field_picker_repeat.push({\n name: \"calc_dps\",\n label: \"Calculation decimal places\",\n type: \"Integer\",\n showIf: {\n column_calculation: [\n \"avg\",\n \"max\",\n \"min\",\n \"sum\",\n \"__tabulator_colcalc_avgnonulls\",\n ],\n },\n });\n const use_field_picker_repeat = field_picker_repeat.filter(\n (f) => ![\"state_field\", \"col_width_units\"].includes(f.name)\n );\n field_picker_repeat.find((c) => c.name === \"col_width\").label =\n \"Column width (px)\";\n const fvs = field_picker_repeat.filter((c) => c.name === \"fieldview\");\n fvs.forEach((fv) => {\n if (fv?.attributes?.calcOptions?.[1])\n Object.values(fv.attributes.calcOptions[1]).forEach((fvlst) => {\n if (fvlst[0] === \"as_text\") fvlst.push(\"textarea\");\n });\n });\n // fix legacy values missing view_name\n (context?.columns || []).forEach((column) => {\n if (\n column.type === \"ViewLink\" &&\n column.view &&\n !column.view_name\n ) {\n const view_select = parse_view_select(column.view);\n column.view_name = view_select.viewname;\n }\n });\n return new Form({\n fields: [\n new FieldRepeat({\n name: \"columns\",\n fancyMenuEditor: true,\n fields: use_field_picker_repeat,\n }),\n ],\n });\n },\n },\n {\n name: \"Additional options\",\n form: async (context) => {\n const celltable = await Table.findOne(\n context.table_id\n ? { id: context.table_id }\n : { name: context.exttable_name }\n );\n //console.log(context);\n const row_field = await celltable.getField(context.row_field);\n const table = Table.findOne(row_field.reftable_name);\n const fields = table.fields;\n for (const field of fields) {\n await field.fill_fkey_options();\n }\n let tree_field_options = [];\n //self join\n for (const field of fields) {\n if (field.is_fkey && field.reftable_name == table.name)\n tree_field_options.push(field.name);\n }\n return new Form({\n fields: [\n {\n name: \"tree_field\",\n label: \"Tree field\",\n type: \"String\",\n attributes: {\n options: tree_field_options,\n },\n },\n {\n name: \"row_order_field\",\n label: \"Row order by\",\n type: \"String\",\n attributes: {\n options: fields.map((f) => f.name),\n },\n },\n {\n name: \"row_order_desc\",\n label: \"Descending?\",\n type: \"Bool\",\n showIf: { row_order_field: fields.map((f) => f.name) },\n },\n {\n name: \"disable_edit_if\",\n label: \"Disable row edit if\",\n sublabel: \"Formula\",\n type: \"String\",\n class: \"validate-expression\",\n },\n {\n name: \"fit\",\n label: \"Layout Fit\",\n type: \"String\",\n required: true,\n attributes: {\n options: [\n \"Columns\",\n \"Data\",\n \"DataFill\",\n \"DataStretch\",\n \"DataTable\",\n ],\n },\n },\n {\n name: \"header_wrap\",\n label: \"Wrap column headers\",\n type: \"Bool\",\n },\n {\n name: \"override_stylesheet\",\n label: \"Override stylesheet\",\n type: \"String\",\n attributes: {\n options: [\n \"bootstrap5\",\n \"bootstrap4\",\n \"midnight\",\n \"modern\",\n \"simple\",\n \"site\",\n \"site_dark\",\n ],\n },\n },\n ],\n });\n },\n },\n ],\n });\n\nconst isWeekend = (date) => ((d) => d === 0 || d === 6)(date.getDay());\n\nconst get_db_rows = async (\n table,\n fields,\n viewname,\n {\n row_field,\n col_field,\n value_field,\n vertical_headers,\n col_field_format,\n new_row_formula,\n column_calculation,\n row_where,\n groupBy,\n col_no_weekends,\n group_calcs,\n calc_pos,\n col_width,\n target_value,\n edit_view,\n col_bin_weeks,\n columns,\n disable_edit_if,\n tree_field,\n row_order_field,\n row_order_desc,\n header_wrap,\n },\n state,\n extraArgs\n) => {\n readState(state, fields);\n const where = await stateFieldsToWhere({ fields, state });\n const q = await stateFieldsToQuery({ state, fields, prefix: \"a.\" });\n\n const rowField = fields.find((f) => f.name === row_field);\n const colField = fields.find((f) => f.name === col_field);\n const valField = fields.find((f) => f.name === value_field);\n const rowTable = Table.findOne(rowField.reftable_name);\n\n const joinFields = {};\n let row_field_name = row_field;\n let col_field_name = col_field;\n if (rowField?.attributes?.summary_field) {\n joinFields[\"rowfield\"] = {\n ref: row_field,\n target: rowField?.attributes?.summary_field,\n };\n row_field_name = \"rowfield\";\n }\n if (colField?.attributes?.summary_field) {\n joinFields[\"colField\"] = {\n ref: col_field,\n target: colField?.attributes?.summary_field,\n };\n col_field_name = \"colfield\";\n }\n\n let rows = await table.getJoinedRows({\n where,\n joinFields,\n ...q,\n forPublic: !extraArgs.req.user,\n forUser: extraArgs.req.user,\n });\n const row_values = new Set([]);\n const col_values = new Set([]);\n const rawColValues = {};\n const allValues = {};\n let xformCol = (x) => x;\n\n if (colField.type?.name === \"Date\") {\n rows.forEach((r) => {\n if (r[col_field]) {\n r[col_field] = new Date(r[col_field]).toISOString().split(\"T\")[0];\n }\n });\n //if (col_field_format)\n // xformCol = (day) => moment(day).format(col_field_format);\n if (state[\"_fromdate_\" + col_field] && state[\"_todate_\" + col_field]) {\n let start = new Date(state[\"_fromdate_\" + col_field]);\n let end = new Date(state[\"_todate_\" + col_field]);\n let day = start;\n if (col_bin_weeks) {\n start.setDate(start.getDate() - ((start.getDay() + 6) % 7));\n end.setDate(end.getDate() - ((end.getDay() + 6) % 7));\n }\n while (day <= end) {\n if (!col_no_weekends || !isWeekend(day) || col_bin_weeks) {\n const dayStr = day.toISOString().split(\"T\")[0];\n const xdayStr = xformCol(dayStr);\n col_values.add(\n //col_field_format ? moment(day).format(col_field_format) :\n dayStr\n );\n rawColValues[xdayStr] = dayStr;\n }\n day = new Date(day);\n day.setDate(day.getDate() + (col_bin_weeks ? 7 : 1));\n }\n }\n }\n\n if (rowField.is_fkey && rowField.reftable_name) {\n const reftable = Table.findOne({ name: rowField.reftable_name });\n const reffields = await reftable.getFields();\n\n const { joinFields, aggregations } = picked_fields_to_query(\n columns || [],\n reffields\n );\n let groupBy1 = groupBy;\n if (groupBy) {\n const groupField = reffields.find((f) => f.name === groupBy);\n if (groupField.is_fkey && groupField.attributes?.summary_field) {\n joinFields.groupbyval = {\n target: groupField.attributes?.summary_field,\n ref: groupBy,\n };\n groupBy1 = \"groupbyval\";\n }\n }\n\n const rowWhere = row_where ? jsexprToWhere(row_where) : {};\n if (where[row_field]) {\n rowWhere[reftable.pk_name] = where[row_field];\n }\n\n const refVals = await reftable.getJoinedRows({\n where: rowWhere,\n joinFields,\n aggregations,\n orderBy: row_order_field || undefined,\n orderDesc: row_order_desc || undefined,\n });\n refVals.forEach((refRow) => {\n const value = refRow[reftable.pk_name];\n const label = refRow[rowField.attributes.summary_field];\n row_values.add(label);\n allValues[label] = {\n rawRowValue: value,\n rowValue: label,\n groupVal: groupBy ? refRow[groupBy1] : undefined,\n ids: {},\n ...refRow,\n };\n if (disable_edit_if) {\n if (eval_expression(disable_edit_if, refRow))\n allValues[label]._disable_edit = true;\n }\n });\n }\n if (colField.is_fkey) {\n await colField.fill_fkey_options();\n colField.options.forEach(({ label, value }) => {\n col_values.add(label);\n rawColValues[label] = value;\n });\n }\n /*if (rowField.type?.name === \"Date\") {\n rows.forEach((r) => {\n if (r[row_field]) {\n r[row_field] = new Date(r[row_field]).toISOString().split(\"T\")[0];\n }\n });\n }*/\n\n for (const r of rows) {\n const rowValue = r[row_field_name];\n const colValue = xformCol(r[col_field_name]);\n row_values.add(rowValue);\n col_values.add(colValue);\n if (!allValues[rowValue]) {\n allValues[rowValue] = {\n rawRowValue: r[row_field],\n rowValue,\n ids: {},\n };\n }\n const theCell = r[value_field];\n if (allValues[rowValue][colValue]) {\n //MULTIPLE PRESENT\n allValues[rowValue][\n colValue\n ] = `${allValues[rowValue][colValue]} ${theCell}`;\n } else {\n allValues[rowValue][colValue] = theCell;\n allValues[rowValue].ids[colValue] = r[table.pk_name];\n rawColValues[colValue] = r[col_field];\n }\n }\n\n const valueCell0 = typeToGridType(\n valField.type,\n valField,\n false,\n {\n type: \"Field\",\n },\n []\n );\n const valueCell = edit_view\n ? { ...valueCell0, editor: false, cellClick: \"__pivot_edit_popup\" }\n : valueCell0;\n const colValuesArray = [...col_values];\n if (colField.type?.name === \"Date\") {\n colValuesArray.sort((a, b) => {\n const da = new Date(rawColValues[a]);\n const db = new Date(rawColValues[b]);\n return da > db ? 1 : db > da ? -1 : 0;\n });\n }\n\n const { tabcolumns, dropdown_id, dropdown_actions, calculators } =\n await get_tabulator_columns(\n viewname,\n rowTable,\n rowTable.fields,\n columns || [],\n false,\n extraArgs.req,\n false, //header_filters,\n false,\n false\n );\n\n const tabCols = [\n {\n field: \"rowValue\",\n title: rowField.label,\n editor: false,\n frozen: true,\n },\n ...tabcolumns,\n ...colValuesArray.map((cv) => ({\n ...valueCell,\n field: `${cv}`,\n title: col_field_format ? moment(cv).format(col_field_format) : `${cv}`,\n editable: \"__pivotEditCheck\",\n headerVertical: vertical_headers,\n [(calc_pos || \"Bottom\").toLowerCase() + \"Calc\"]:\n (group_calcs || !groupBy) && column_calculation\n ? column_calculation\n : undefined,\n headerWordWrap: true,\n width: col_width || undefined,\n })),\n ];\n\n tabCols.forEach((col) => {\n if (disable_edit_if && !col.editable)\n col.editable = \"__tabulator_edit_check\";\n if (header_wrap) col.headerWordWrap = true;\n });\n\n let allValuesArray = Object.values(allValues);\n calculators.forEach((f) => {\n allValuesArray.forEach(f);\n });\n\n if (tree_field) {\n const my_ids = new Set(allValuesArray.map((r) => r.id));\n for (const row of allValuesArray) {\n if (row[tree_field] && my_ids.has(row[tree_field]))\n row._parent = row[tree_field];\n else row._parent = null;\n }\n allValuesArray = nest(allValuesArray);\n }\n\n if (groupBy && !group_calcs && column_calculation) {\n const calcRow = {\n ids: {},\n disableEdit: true,\n rowValue: column_calculation,\n groupVal: \"Total\",\n };\n colValuesArray.forEach((cv) => {\n let result;\n //[\"avg\", \"max\", \"min\", \"sum\", \"count\"]\n const values = [...row_values].map((rv) => allValues[rv][cv]);\n switch (column_calculation) {\n case \"sum\":\n result = values.reduce((partialSum, a) => partialSum + (a || 0), 0);\n break;\n case \"max\":\n result = Math.max(...values);\n break;\n case \"min\":\n result = Math.min(...values);\n break;\n case \"avg\":\n result =\n values.reduce((partialSum, a) => partialSum + (a || 0), 0) /\n values.filter((v) => typeof v !== \"undefined\" && v !== null).length;\n break;\n case \"count\":\n result = values.filter(\n (v) => typeof v !== \"undefined\" && v !== null\n ).length;\n break;\n default:\n break;\n }\n calcRow[cv] = result;\n });\n if (calc_pos === \"Top\") allValuesArray.unshift(calcRow);\n else allValuesArray.push(calcRow);\n //row_values.add(column_calculation);\n }\n return {\n tabCols,\n allValuesArray,\n col_field_name,\n tabcolumns,\n rowField,\n rawColValues,\n valueCell,\n };\n};\n\nconst run = async (table_id, viewname, config, state, extraArgs) => {\n const {\n row_field,\n col_field,\n value_field,\n vertical_headers,\n col_field_format,\n new_row_formula,\n column_calculation,\n row_where,\n groupBy,\n col_no_weekends,\n group_calcs,\n calc_pos,\n col_width,\n target_value,\n edit_view,\n col_bin_weeks,\n columns,\n disable_edit_if,\n tree_field,\n row_order_field,\n row_order_desc,\n fit,\n override_stylesheet,\n } = config;\n const table = await Table.findOne({ id: table_id });\n const fields = await table.getFields();\n const {\n tabCols,\n allValuesArray,\n col_field_name,\n tabcolumns,\n rowField,\n rawColValues,\n valueCell,\n } = await get_db_rows(table, fields, viewname, config, state, extraArgs);\n\n const rndid = Math.floor(Math.random() * 16777215).toString(16);\n const newRowState = {};\n Object.entries(state).forEach(([k, v]) => {\n if (k.includes(\".\") || k.includes(\"-\") || k.includes(\">\")) return;\n newRowState[k] = v;\n });\n const new_row_obj = new_row_formula\n ? eval_expression(new_row_formula, {\n ...newRowState,\n user: extraArgs.req.user,\n })\n : {};\n const darkStyle = await getDarkStyle(extraArgs.req);\n return (\n script(\n domReady(`\n ${\n darkStyle\n ? `\n var styleElement = document.createElement('style');\n styleElement.textContent = ${JSON.stringify(darkStyle)};\n document.head.appendChild(styleElement);`\n : \"\"\n }\n const columns=${JSON.stringify(tabCols, null, 2)}; \n columns.forEach(col=>{\n Object.entries(col).forEach(([k,v])=>{\n if(typeof v === \"string\" && v.startsWith(\"__\")) {\n col[k] = window[v.substring(2)];\n }\n })\n })\n window.tabulator_table_${rndid} = new Tabulator(\"#tabgrid${viewname.replaceAll(\n \" \",\n \"\"\n )}${rndid}\", {\n data: ${JSON.stringify(allValuesArray, null, 2)},\n layout:\"fit${fit || \"Columns\"}\", \n columns,\n clipboard:true, \n ${\n disable_edit_if\n ? `rowFormatter: function(row) {\n if(row.getData()._disable_edit) {\n row.getElement().style.backgroundColor = \"#cccccc\";\n }\n },`\n : ``\n }\n ${\n tree_field\n ? \"dataTree:true,dataTreeStartExpanded:true,dataTreeSelectPropagate:true,\"\n : \"\"\n }\n ${groupBy ? `groupBy: \"groupVal\",` : \"\"}\n ${\n groupBy && !group_calcs && column_calculation && calc_pos === \"Top\"\n ? `frozenRows:1`\n : \"\"\n }\n });\n ${\n edit_view\n ? `\n window.pivot_tabulator_edit_view = '${edit_view}';\n window.pivot_tabulator_table_pk = '${table.pk_name}';\n window.pivot_tabulator_row_field = '${row_field}';\n window.pivot_tabulator_col_field_name = '${col_field_name}';\n `\n : \"\"\n }\n\n window.tabulator_table_${rndid}.on(\"cellEdited\", function(cell){\n if(${JSON.stringify(\n tabcolumns.map((c) => c.field)\n )}.includes(cell.getField())) {\n const row=cell.getRow().getData();\n gen_save_row_from_cell(${JSON.stringify({\n rndid,\n table_name: rowField.reftable_name,\n viewname,\n hasCalculated: true,\n })})(row, cell);\n return;\n }\n const rawColValues = ${JSON.stringify(rawColValues)};\n const row=cell.getRow().getData();\n if(row.disableEdit) return;\n const fld = cell.getField()\n const id = row.ids[fld]\n let value = row[fld]\n if(value===\"\" && ${JSON.stringify(valueCell.editor === \"number\")}) {\n value = 0\n cell.setValue(0)\n }\n const saveRow = {...${JSON.stringify(new_row_obj)}, ${value_field}: value}\n if(!id) {\n saveRow.${row_field} = row.rawRowValue;\n saveRow.${col_field} = rawColValues[fld];\n saveRow._rowId = row.rawRowValue;\n } else {\n saveRow._rowId = row.rawRowValue;\n saveRow.id = id\n }\n saveRow._state = ${JSON.stringify(state)}\n $.ajax({\n type: \"POST\",\n url: \"/view/${viewname}/edit_value\",\n data: saveRow,\n headers: {\n \"CSRF-Token\": _sc_globalCsrf,\n },\n error: tabulator_error_handler,\n }).done(function (resp) {\n if(Array.isArray(resp.success)) {\n window.tabulator_table_${rndid}.updateRow(cell.getRow(), resp.success[0]); \n }\n ${\n groupBy && !group_calcs && column_calculation\n ? `pivotEditRecalc(cell, ${JSON.stringify({\n column_calculation,\n calc_pos,\n })});${target_value ? \"setCalcColors();\" : \"\"}`\n : \"\"\n }\n })\n });\n ${\n target_value\n ? `const setCalcColors = ()=> {\n const rows = window.tabulator_table_${rndid}.getRows();\n const wantIx = ${calc_pos === \"Top\" ? 0 : `rows.length-1`};\n const [cell0, ...cells] = rows[wantIx].getCells()\n for(const cell of cells) {\n const data = cell.getValue()\n if(data===${target_value})\n cell.getElement().style.color = \"blue\";\n else \n cell.getElement().style.color = \"red\";\n\n }\n };\n setTimeout(setCalcColors)\n `\n : \"\"\n }\n `)\n ) +\n div({\n id: `tabgrid${viewname.replaceAll(\" \", \"\")}${rndid}`,\n style: { height: \"100%\" },\n }) +\n (override_stylesheet\n ? link({\n rel: \"stylesheet\",\n href: `/plugins/public/tabulator@${\n (__webpack_require__(/*! ./package.json */ \"../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/package.json\").version)\n }/tabulator_${override_stylesheet}.min.css`,\n })\n : \"\")\n );\n};\n\nconst edit_value = async (table_id, viewname, config, body, { req, res }) => {\n const {\n row_field,\n col_field,\n value_field,\n vertical_headers,\n col_field_format,\n new_row_formula,\n column_calculation,\n row_where,\n groupBy,\n col_no_weekends,\n group_calcs,\n calc_pos,\n col_width,\n } = config;\n let { id, _rowId, _state, ...rowValues } = body;\n const table = await Table.findOne({ id: table_id });\n const fields = await table.getFields();\n\n if (id) {\n await table.updateRow(rowValues, id, req.user);\n } else {\n id = await table.insertRow(rowValues, req.user);\n }\n const { allValuesArray } = await get_db_rows(\n table,\n fields,\n viewname,\n config,\n { [config.row_field]: _rowId, ...(_state || {}) },\n { req, res }\n );\n return {\n json: {\n success: _rowId\n ? allValuesArray.filter((xs) => xs.groupVal !== \"Total\")\n : allValuesArray,\n },\n };\n};\n\nconst get_rows = async (table_id, viewname, config, body, extraArgs) => {\n const table = await Table.findOne({ id: table_id });\n const fields = await table.getFields();\n\n const state = body.state?.id ? { [config.row_field]: body.state.id } : {};\n const {\n tabCols,\n allValuesArray,\n col_field_name,\n tabcolumns,\n rowField,\n rawColValues,\n valueCell,\n } = await get_db_rows(table, fields, viewname, config, state, extraArgs);\n return {\n json: {\n success: body.state?.id\n ? allValuesArray.filter((xs) => xs.groupVal !== \"Total\")\n : allValuesArray,\n },\n };\n};\n\nmodule.exports = {\n name: \"Tabulator Pivot Edit\",\n display_state_form: false,\n get_state_fields,\n configuration_workflow,\n run,\n routes: {\n edit_value,\n get_rows,\n },\n mobile_render_server_side: true,\n};\n\n\n//# sourceURL=webpack://saltcorn/../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/pivot-edit.js?\n}");
58
+
59
+ /***/ },
60
+
61
+ /***/ "../saltcorn-data/dist/base-plugin/viewtemplates/viewable_fields.js"
62
+ /*!**************************************************************************!*\
63
+ !*** ../saltcorn-data/dist/base-plugin/viewtemplates/viewable_fields.js ***!
64
+ \**************************************************************************/
65
+ (module, __unused_webpack_exports, __webpack_require__) {
66
+
67
+ "use strict";
68
+ eval("{\n//for backwards compatibility - some modules import from here\nconst viewable_fields = __webpack_require__(/*! ../../viewable_fields */ \"../saltcorn-data/dist/viewable_fields.js\");\nmodule.exports = viewable_fields;\n//# sourceMappingURL=viewable_fields.js.map\n\n//# sourceURL=webpack://saltcorn/../saltcorn-data/dist/base-plugin/viewtemplates/viewable_fields.js?\n}");
69
+
70
+ /***/ },
71
+
72
+ /***/ "../saltcorn-data/dist/contracts.js"
73
+ /*!******************************************!*\
74
+ !*** ../saltcorn-data/dist/contracts.js ***!
75
+ \******************************************/
76
+ (module, __unused_webpack_exports, __webpack_require__) {
77
+
78
+ "use strict";
79
+ eval("{\n/**\n * @category saltcorn-data\n * @module contract\n */\nconst { contract, is } = __webpack_require__(/*! contractis */ \"../../node_modules/contractis/index.js\");\n/**\n * @type {function}\n */\nconst fieldlike = is.obj({\n name: is.str,\n input_type: is.maybe(is.str),\n type: is.maybe(is.or(is.str, is.obj({ name: is.str }))),\n}, (o) => o.type || o.input_type);\n/**\n * @type {function}\n */\nconst is_header = is.obj({ script: is.maybe(is.str) });\n/**\n * @type {function}\n */\nconst is_menu_item = is.obj({\n label: is.str,\n link: is.maybe(is.str),\n subitems: is.maybe(is.array(is.obj({\n label: is.str,\n link: is.maybe(is.str),\n }))),\n});\n/**\n * @type {function}\n */\nconst is_layout_container = is.or(is.eq(null), is.obj({\n type: is.one_of(\"blank card hero pageHeader footer image link line_break view\".split(\" \")),\n}), is.obj({}));\n/**\n * @type {function}\n */\nconst is_layout = is.or(is.obj({\n above: is.maybe(is.array(is.or(is_layout_container, is.obj({ besides: is.array(is_layout_container) }), is.obj({ above: is.array(is_layout_container) })))),\n besides: is.maybe(is.array(is.or(is_layout_container, is.obj({ above: is.array(is_layout_container) }), is.obj({ besides: is.array(is_layout_container) })))),\n}, (l) => (l.above && !l.besides) || (!l.above && l.besides)), is.and(is_layout_container, is.obj({})));\n/**\n * @type {function}\n */\nconst is_plugin_wrap_arg = is.obj({\n title: is.str,\n body: is.or(is.str, is_layout),\n currentUrl: is.str,\n brand: is.obj({ name: is.str }),\n menu: is.array(is.obj({\n section: is.str,\n items: is.array(is_menu_item),\n })),\n alerts: is.array(is.obj({\n type: is.one_of([\"error\", \"danger\", \"success\", \"warning\"]),\n msg: is.or(is.str, is.array(is.str)),\n })),\n headers: is.array(is_header),\n});\n/**\n * @type {function}\n */\nconst is_plugin_authwrap_arg = is.obj({\n title: is.str,\n form: is.class(\"Form\"),\n afterForm: is.maybe(is.str),\n brand: is.obj({ name: is.str, logo: is.maybe(is.str) }),\n menu: is.array(is.obj({\n section: is.str,\n items: is.array(is_menu_item),\n })),\n alerts: is.array(is.obj({\n type: is.one_of([\"error\", \"danger\", \"success\", \"warning\"]),\n msg: is.or(is.str, is.array(is.str)),\n })),\n headers: is.array(is_header),\n authLinks: is.obj({\n login: is.maybe(is.str),\n signup: is.maybe(is.str),\n forgot: is.maybe(is.str),\n }),\n});\n/**\n * @type {function}\n */\nconst is_plugin_wrap = is.fun(is_plugin_wrap_arg, is.str);\n/**\n * @type {function}\n */\nconst is_plugin_layout = is.obj({\n wrap: is_plugin_wrap,\n authWrap: is.maybe(is.fun(is_plugin_authwrap_arg, is.str)),\n});\nconst is_attribute = is.obj({ name: is.str, type: is.str });\n/**\n * @type {function}\n */\nconst is_plugin_type = is.obj({\n name: is.str,\n sql_name: is.str,\n contract: is.maybe(is.fun(is.obj(), is.contract)),\n fieldviews: is.objVals(is.obj({\n isEdit: is.bool,\n run: is.or(is.fun(is.any, is.str), is.fun([\n is.str,\n is.any,\n is.maybe(is.obj()),\n is.str,\n is.bool,\n is.maybe(is.obj({})),\n is.maybe(is.obj({})),\n ], is.str)),\n })),\n attributes: is.maybe(is.or(is.fun(is.obj(), is.array(is_attribute)), is.array(is_attribute))),\n readFromFormRecord: is.maybe(is.fun([is.obj(), is.str], is.any)),\n read: is.fun(is.any, is.any),\n readFromDB: is.maybe(is.fun(is.any, is.any)),\n validate: is.maybe(is.fun(is.obj(), is.fun(is.any, is.bool))),\n presets: is.maybe(is.objVals(is.fun([], is.any))),\n});\n/**\n * @type {function}\n */\nconst is_table_query = is.obj({\n joinFields: is.maybe(is.objVals(is.obj({ ref: is.str, target: is.str }))),\n aggregations: is.maybe(is.objVals(is.obj({\n ref: is.str,\n table: is.str,\n field: is.str,\n aggregate: is.str,\n }))),\n where: is.maybe(is.obj()),\n limit: is.maybe(is.positive),\n offset: is.maybe(is.positive),\n orderBy: is.maybe(is.or(is.str, is.obj({}))),\n orderDesc: is.maybe(is.bool),\n});\n/**\n * @type {function}\n */\nconst is_viewtemplate = is.obj({\n name: is.str,\n get_state_fields: is.maybe(is.fun([is.posint, is.str, is.any], is.promise(fieldlike))),\n configuration_workflow: is.fun(is.obj({ __: is.fun(is.str, is.str) }), is.class(\"Workflow\")),\n view_quantity: is.maybe(is.one_of(\"Many\", \"ZeroOrOne\", \"One\")),\n initial_config: is.maybe(is.fun(is.obj({ table_id: is.posint }), is.promise(is.obj()))),\n run: is.fun([is.posint, is.str, is.any, is.obj(), is.obj()], is.promise(is.str)),\n});\nconst is_plugin_function = is.obj({\n run: is.fun(is.any, is.any),\n returns: is.maybe(is.str),\n arguments: is.maybe(is.array(is.str)),\n isAsync: is.maybe(is.bool),\n});\n/**\n *\n * @param {*} a\n * @returns {function}\n */\nconst is_maybe_cfg_fun = (a) => is.or(is.fun(is.obj, a), a, is.undefined);\n/**\n * @type {function}\n */\nconst is_plugin = is.obj({\n sc_plugin_api_version: is.posint,\n headers: is_maybe_cfg_fun(is.array(is_header)),\n functions: is_maybe_cfg_fun(is.objVals(is.or(is_plugin_function, is.fun(is.any, is.any)))),\n layout: is_maybe_cfg_fun(is_plugin_layout),\n types: is_maybe_cfg_fun(is.array(is_plugin_type)),\n viewtemplates: is_maybe_cfg_fun(is.array(is_viewtemplate)),\n configuration_workflow: is.maybe(is.fun([], is.class(\"Workflow\"))),\n fieldviews: is.maybe(is.objVals(is.obj({\n type: is.str,\n isEdit: is.bool,\n run: is.or(is.fun(is.any, is.str), is.fun([is.str, is.any, is.maybe(is.obj()), is.str, is.bool], is.str)),\n }))),\n dependencies: is.maybe(is.array(is.str)),\n});\n/**\n * @type {function}\n */\nconst is_pack = is.obj({\n tables: is.array(is.obj({ name: is.str, fields: is.array(fieldlike) })),\n views: is.array(is.obj({ name: is.str, viewtemplate: is.str, configuration: is.any })),\n plugins: is.array(is.obj({ name: is.str, source: is.str, location: is.str })),\n});\n/**\n * @type {function}\n */\nconst is_column = is.obj({\n type: is.one_of([\n \"Action\",\n \"ViewLink\",\n \"Link\",\n \"JoinField\",\n \"Aggregation\",\n \"Field\",\n ]),\n});\n/**\n * @type {function}\n */\nconst is_tablely = is.or(is.class(\"Table\"), is.obj({ external: is.eq(true) }));\nconst deprecate = (fn, name) => {\n if (typeof fn !== \"function\")\n return fn;\n let warned = false;\n const original = fn;\n function wrapped(...args) {\n if (!warned) {\n console.warn(`[DEPRECATED] ${name} is deprecated and will be removed in a future version.`);\n warned = true;\n }\n return original(...args);\n }\n Object.setPrototypeOf(wrapped, Object.getPrototypeOf(original));\n Object.defineProperties(wrapped, Object.getOwnPropertyDescriptors(original));\n return wrapped;\n};\nmodule.exports = Object.fromEntries(Object.entries({\n is_table_query,\n is_plugin_wrap,\n is_plugin_wrap_arg,\n is_plugin_type,\n is_plugin,\n fieldlike,\n is_viewtemplate,\n is_header,\n is_pack,\n is_column,\n is_plugin_layout,\n is_tablely,\n}).map(([key, value]) => [key, deprecate(value, key)]));\n//# sourceMappingURL=contracts.js.map\n\n//# sourceURL=webpack://saltcorn/../saltcorn-data/dist/contracts.js?\n}");
80
+
81
+ /***/ },
82
+
83
+ /***/ "../saltcorn-data/dist/plugin-testing.js"
84
+ /*!***********************************************!*\
85
+ !*** ../saltcorn-data/dist/plugin-testing.js ***!
86
+ \***********************************************/
87
+ (__unused_webpack_module, exports, __webpack_require__) {
88
+
89
+ "use strict";
90
+ eval("{\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.check_view_columns = exports.generate_attributes = exports.auto_test_plugin = void 0;\n/**\n * @category saltcorn-data\n * @module plugin-testing\n */\nconst { contract, is, auto_test } = __webpack_require__(/*! contractis */ \"../../node_modules/contractis/index.js\");\nconst { is_plugin_wrap, is_plugin } = __webpack_require__(/*! ./contracts */ \"../saltcorn-data/dist/contracts.js\");\nconst { getState } = __webpack_require__(/*! ./db/state */ \"../saltcorn-data/dist/db/state.js\");\nconst { renderForm } = __webpack_require__(/*! @saltcorn/markup */ \"../saltcorn-markup/dist/index.js\");\nconst { mockReqRes } = __webpack_require__(/*! ./tests/mocks */ \"../saltcorn-data/dist/tests/mocks.js\");\nconst field_1 = __importDefault(__webpack_require__(/*! ./models/field */ \"../saltcorn-data/dist/models/field.js\"));\nconst table_1 = __importDefault(__webpack_require__(/*! ./models/table */ \"../saltcorn-data/dist/models/table.js\"));\nconst trigger_1 = __importDefault(__webpack_require__(/*! ./models/trigger */ \"../saltcorn-data/dist/models/trigger.js\"));\nconst { expressionValidator } = __webpack_require__(/*! ./models/expression */ \"../saltcorn-data/dist/models/expression.js\");\nconst { parse_view_select } = __webpack_require__(/*! ./viewable_fields */ \"../saltcorn-data/dist/viewable_fields.js\");\nconst view_1 = __importDefault(__webpack_require__(/*! ./models/view */ \"../saltcorn-data/dist/models/view.js\"));\nconst base_types_1 = __webpack_require__(/*! @saltcorn/types/base_types */ \"../saltcorn-types/dist/base_types.js\");\nconst auto_test_wrap = (wrap) => {\n auto_test(contract(is_plugin_wrap, wrap, { n: 5 }));\n};\nconst generate_attributes = (typeattrs, validate, table_id) => {\n var res = {};\n const attrs = field_1.default.getTypeAttributes(typeattrs, table_id);\n (attrs || []).forEach((a) => {\n if (a.type && (a.required || is.bool.generate())) {\n const contract = a.type.contract || getState().types[a.type].contract;\n const gen = contract({}).generate;\n if (gen)\n res[a.name] = gen();\n }\n });\n if (validate && !validate(res))\n return generate_attributes(attrs, validate, table_id);\n else\n return res;\n};\nexports.generate_attributes = generate_attributes;\nconst auto_test_type = (t) => {\n const fvs = t.fieldviews || {};\n //run edit field views without a value\n Object.values(fvs).forEach((fv) => {\n if ((0, base_types_1.instanceOfFieldViewEdit)(fv)) {\n const attr = generate_attributes(t.attributes, t.validate_attributes);\n is.str(fv.run(\"foo\", undefined, attr, \"myclass\", true, {\n type: \"foo\",\n name: \"foo\",\n }));\n is.str(fv.run(\"foo\", undefined, attr, \"myclass\", false, {\n type: \"foo\",\n name: \"foo\",\n }));\n }\n });\n //find examples, run all fieldview on each example\n const has_contract = t.contract && t.contract.generate;\n const numex = has_contract ? 20 : 200;\n for (let index = 0; index < numex; index++) {\n const x = has_contract\n ? t.contract.generate()\n : t.read?.(is.any.generate());\n const attribs = generate_attributes(t.attributes, t.validate_attributes);\n if (has_contract || (typeof x !== \"undefined\" && x !== null))\n if ((t.validate && t.validate(attribs)(x)) || !t.validate) {\n Object.values(fvs).forEach((fv) => {\n if ((0, base_types_1.instanceOfFieldViewEdit)(fv)) {\n is.str(fv.run(\"foo\", x, attribs, \"myclass\", true, {\n type: \"foo\",\n name: \"foo\",\n }));\n is.str(fv.run(\"foo\", x, attribs, \"myclass\", false, {\n type: \"foo\",\n name: \"foo\",\n }));\n }\n else if ((0, base_types_1.instanceOfFieldViewShow)(fv)) {\n is.str(fv.run(x, mockReqRes.req, {}));\n }\n });\n if (t.readFromFormRecord)\n t.readFromFormRecord({ akey: x }, \"akey\");\n }\n }\n if (t.readFromFormRecord) {\n t.readFromFormRecord({}, \"akey\");\n }\n //todo: try creating a table with this type\n};\nconst auto_test_workflow = async (wf, initialCtx) => {\n const step = async (wf, ctx) => {\n is.obj(ctx);\n const res = await wf.run(ctx);\n if (res?.renderForm) {\n is.str(renderForm(res.renderForm, \"\"));\n const vs = await res.renderForm.generate();\n return await step(wf, vs);\n }\n else\n return res;\n };\n return await step(wf, initialCtx);\n};\nconst auto_test_viewtemplate = async (vt) => {\n if (vt.noAutoTest)\n return;\n const wf = vt.configuration_workflow\n ? vt.configuration_workflow(mockReqRes.req)\n : undefined;\n is.class(\"Workflow\")(wf);\n for (let index = 0; index < 10; index++) {\n var cfg;\n if (vt.initial_config && Math.random() > 0.5)\n cfg = await vt.initial_config({ table_id: 2 });\n else if (wf)\n cfg = await auto_test_workflow(wf, {\n table_id: 2,\n viewname: \"newview\",\n });\n const sfs = vt.get_state_fields\n ? await vt.get_state_fields(1, \"newview\", cfg)\n : [];\n const res = await vt.run(2, \"newview\", cfg, {}, mockReqRes, {});\n is.or(is.str, is.array(is.str))(res);\n if (sfs.some((sf) => sf.name === \"id\")) {\n const resid = await vt.run(2, \"newview\", cfg, { id: 1 }, mockReqRes);\n is.or(is.str, is.array(is.str))(resid);\n }\n }\n};\nconst auto_test_plugin = async (plugin) => {\n is_plugin(plugin);\n getState().registerPlugin(\"test_plugin\", plugin);\n if (plugin.layout) {\n auto_test_wrap((typeof plugin.layout === \"function\" ? plugin.layout({}) : plugin.layout)\n .wrap);\n }\n if (plugin.types && Array.isArray(plugin.types)) {\n plugin.types.forEach(auto_test_type);\n }\n const vts = typeof plugin.viewtemplates === \"function\"\n ? plugin.viewtemplates({}) || []\n : plugin.viewtemplates || [];\n for (const vt of vts || [])\n await auto_test_viewtemplate(vt);\n //is each header reachable\n};\nexports.auto_test_plugin = auto_test_plugin;\nconst check_view_columns = async (view, columns) => {\n const errs = [];\n const warnings = [];\n const table = table_1.default.findOne(view.table_id\n ? { id: view.table_id }\n : view.exttable_name\n ? { name: view.exttable_name }\n : { id: -1 });\n let fields;\n if (table)\n fields = table.getFields();\n const check_formula = (s, loc) => {\n const v = expressionValidator(s, loc);\n if (v === true)\n return;\n if (typeof v === \"string\")\n errs.push(`In view ${view.name}, ${loc} ${s}\\n${v}`);\n };\n const trigger_actions = (await trigger_1.default.find({\n when_trigger: { or: [\"API call\", \"Never\"] },\n })).map((tr) => tr.name);\n for (const column of columns) {\n switch (column.type) {\n // in general, if formula checked, make sure it is present\n case \"Field\":\n //field exists\n if (table?.name === \"users\" &&\n [\"remember\", \"passwordRepeat\", \"password\"].includes(column.field_name))\n break;\n if (!fields)\n break;\n const f = fields.find((fld) => fld.name === column.field_name);\n if (!f) {\n warnings.push(`In view ${view.name}, field ${column.field_name} does not exist in table ${table?.name}`);\n break;\n }\n if (column.fieldview &&\n !(f.is_fkey || f.type === \"File\") &&\n f.type &&\n typeof f.type !== \"string\" &&\n f.type.fieldviews &&\n !f.type.fieldviews[column.fieldview])\n warnings.push(`In view ${view.name}, field ${column.field_name} of type ${typeof f.type === \"string\" ? f.type : f.type?.name} table ${table?.name} does not have fieldview ${column.fieldview}`);\n break;\n case \"Action\":\n if (column.action_label_formula)\n check_formula(column.action_label, `Label for action ${column.action_name}`);\n if (column.action_name.startsWith(\"Toggle \") ||\n column.action_name.startsWith(\"Login with \") ||\n [\n \"GoBack\",\n \"Delete\",\n \"Save\",\n \"Reset\",\n \"SaveAndContinue\",\n \"Login\",\n \"Sign up\",\n \"Cancel\",\n ].includes(column.action_name))\n break;\n if (column.action_name !== \"Multi-step action\" &&\n !(column.action_name == \"UpdateMatchingRows\" &&\n view.viewtemplate == \"Edit\") &&\n !getState().actions[column.action_name] &&\n !trigger_actions.includes(column.action_name))\n errs.push(`In view ${view.name}, action ${column.action_name} does not exist`);\n break;\n case \"ViewLink\":\n {\n if (column.view_label_formula)\n check_formula(column.view_label, `Label for view link`);\n if (column.extra_state_fml)\n check_formula(column.extra_state_fml, `View link extra state formula`);\n const { viewname } = parse_view_select(column.view);\n const linkedview = view_1.default.findOne({ name: viewname });\n if (!linkedview)\n errs.push(`In view ${view.name}, linked view ${viewname} does not exist`);\n }\n break;\n case \"JoinField\":\n if (table && column.join_field) {\n const jf = table.getField(column.join_field);\n if (!jf)\n errs.push(`In view ${view.name}, join field ${column.join_field} does not exist`);\n }\n break;\n case \"Link\":\n if (column.link_text_formula)\n check_formula(column.link_text, `Link text`);\n if (column.link_url_formula)\n check_formula(column.link_url, `Link URL`);\n break;\n case \"Aggregation\":\n break;\n default:\n break;\n }\n }\n return { errors: errs, warnings };\n};\nexports.check_view_columns = check_view_columns;\n//# sourceMappingURL=plugin-testing.js.map\n\n//# sourceURL=webpack://saltcorn/../saltcorn-data/dist/plugin-testing.js?\n}");
91
+
92
+ /***/ },
93
+
94
+ /***/ "../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/package.json"
95
+ /*!******************************************************************************************************!*\
96
+ !*** ../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/package.json ***!
97
+ \******************************************************************************************************/
98
+ (module) {
99
+
100
+ "use strict";
101
+ eval("{module.exports = /*#__PURE__*/JSON.parse('{\"name\":\"@saltcorn/tabulator\",\"version\":\"0.10.21\",\"description\":\"Grid editing view based on Tabulator\",\"main\":\"index.js\",\"dependencies\":{\"moment\":\"2.29.4\"},\"author\":\"Tom Nielsen\",\"license\":\"MIT\",\"eslintConfig\":{\"extends\":\"eslint:recommended\",\"parserOptions\":{\"ecmaVersion\":2020},\"env\":{\"node\":true,\"es6\":true},\"rules\":{\"no-unused-vars\":\"off\",\"no-case-declarations\":\"off\",\"no-empty\":\"warn\",\"no-fallthrough\":\"warn\"}}}');\n\n//# sourceURL=webpack://saltcorn/../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/package.json?\n}");
102
+
103
+ /***/ }
104
+
105
+ },
106
+ /******/ __webpack_require__ => { // webpackRuntimeModules
107
+ /******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
108
+ /******/ __webpack_require__.O(0, ["common_chunks","data"], () => (__webpack_exec__("../../../.local/share/saltcorn-plugins/plugins_folder/@saltcorn/tabulator/0.10.21/index.js")));
109
+ /******/ var __webpack_exports__ = __webpack_require__.O();
110
+ /******/ return __webpack_exports__;
111
+ /******/ }
112
+ ]);
113
+ });