import { DBModule, DBTable, MapData, ModuleInstruction, loadLanguageModule, parseXML } from "@cyklang/core"
import loglevel from 'loglevel'
import { useCykStore } from "./cykStore"
import { dbRemote, getDBManager, structure, verifyAccessRight } from "./cykLang"
import { AlertException } from "./cykRun"
const logger = loglevel.getLogger('adminTable')
logger.setLevel('debug')
/**
*
* @param tableName
*/
export async function generateTableCRUD(tableName: string, browserLanguage?: string | undefined) {
try {
const store = useCykStore()
if (!store.user.logged) {
await store.currentuser()
if (!store.user.logged) {
// store.loginRoute = route.path
window.location.hash = '/login'
}
}
const dbManager = await getDBManager()
const dbTable = await dbManager.dbTableExist(tableName)
if (!dbTable) {
throw 'table ' + tableName + ' not found'
}
logger.debug(`generateTableCRUD browserLanguage=${browserLanguage}, dbTable.packageName=${dbTable.packageName}`)
await loadLanguageModule(structure.scope, dbManager, dbTable.packageName || '', [store.user.user_lang, browserLanguage, 'en-US'])
const source_code = await admin_table_generate(dbTable)
store.module.source_edit = source_code
// logger.debug('generated_code: ', source_code)
}
catch (err) {
alert(String(err))
}
}
const LS_SELECT_OPTIONS_LIMIT = 'cyk:SELECT-OPTIONS-LIMIT'
const item_select_options_limit = localStorage.getItem(LS_SELECT_OPTIONS_LIMIT)
const SELECT_OPTIONS_LIMIT = Number(item_select_options_limit) || 100
if (!item_select_options_limit) {
localStorage.setItem(LS_SELECT_OPTIONS_LIMIT, String(SELECT_OPTIONS_LIMIT))
}
/**
*
* @param dbTable
* @returns
*/
async function scan_columns(dbTable: DBTable): Promise<{ fields: string, template: string, order_by: string, columns: string }> {
let template = ''
let fields = ''
let columns = ''
const dbColumns = dbTable.objectDataType?.dbColumns
if (!dbColumns) throw 'dbColumns undefined'
const order_by = dbColumns.primaryColumns.map((value) => value.name).join(',')
for (let ind = 0; ind < dbColumns.columns.length; ind++) {
const dbColumn = dbColumns.columns[ind]
if (dbColumn.name.endsWith('__meta')) continue
if (dbColumn.dbType === 'bytea') continue
if (dbColumn.computed) continue
let component = dbColumn.component
if (dbColumn.parentTable) {
const { count } = await (await getDBManager()).dcount('*', dbColumn.parentTable)
logger.debug(`dcount('*', ${dbColumn.parentTable} ) = ${count}`)
if (count < SELECT_OPTIONS_LIMIT)
component = 'select'
}
if (!component) {
component = 'input'
}
let label = dbColumn.label || dbColumn.name
let readonly = ''
if (dbColumn.dbPrimary && dbColumn.dbGenerated) {
readonly = " readonly='true' "
}
// let computed = ''
// if (dbColumn.computed) {
// const escaped = dbColumn.computed.replace(/'/g, "'")
// computed = ` computed='${escaped}' `
// }
let tag
if (component === 'select' && dbColumn.parentTable) {
tag = `
`
}
else if (component === 'input') {
let type: string = ''
if (dbColumn.dbType === 'text' || dbColumn.dbType === 'jsonb') {
type = ` type="textarea"`
}
let mask: string = ''
if (dbColumn.mask && dbColumn.mask !== '') {
mask = ` mask="${dbColumn.mask}"`
}
tag = `
`
}
else if (component === 'checkbox') {
tag = `
`
}
else if (component === 'qimg') {
//
const field_name = dbColumn.name.substring(0, dbColumn.name.length - 5)
// template = 'expand'
// if (dbColumns.primaryColumns.length > 1) throw 'qimg more than 1 primary column unsupported'
if (dbColumns.primaryColumns.length === 0) throw 'qimg no primary column is unsupported'
tag = `
"${dbTable.name}"
"${field_name}"
temp.dbkey()
`
}
else if (component === 'file') {
//
const field_name = dbColumn.name.substring(0, dbColumn.name.length - 5)
if (dbColumns.primaryColumns.length === 0) throw 'file no primary column is unsupported'
tag = `
"${dbTable.name}"
"${field_name}"
temp.dbkey()
`
logger.debug(`component file: ${tag}`)
}
fields += tag
if (columns !== '') columns += ','
columns += dbColumn.name
}
return { fields, template, order_by, columns }
}
/**
*
* @param dbTable
*/
function scan_primary_columns(dbTable: DBTable) {
let pkey_params_dcl = ''
let pkey_equals = ''
let pkey_params_val = ''
const primaryColumns = dbTable.objectDataType?.dbColumns?.primaryColumns
if (!primaryColumns) throw 'dbTable has no primary column: ' + dbTable.name
for (let ind = 0; ind < primaryColumns.length; ind++) {
const primaryColumn = primaryColumns[ind]
if (ind > 0) pkey_equals += ' AND '
pkey_equals += `${primaryColumn.name} = {{ ${primaryColumn.name}}}`
pkey_params_dcl += `<${primaryColumn.dataTypeName} name="${primaryColumn.name}" />`
pkey_params_val += `<${primaryColumn.dataTypeName} name="${primaryColumn.name}">${dbTable.name}.${primaryColumn.name}${primaryColumn.dataTypeName}>`
}
return {
pkey_params_dcl,
pkey_equals,
pkey_params_val
}
}
const LS_QUERY_LIMIT = 'cyk:QUERY-LIMIT'
const item = localStorage.getItem(LS_QUERY_LIMIT)
const QUERY_LIMIT = Number(item) || 1000
if (!item) {
localStorage.setItem(LS_QUERY_LIMIT, String(QUERY_LIMIT))
}
/**
*
* @param dbTable
* @returns
*/
export async function admin_table_generate(dbTable: DBTable):
Promise {
try {
const tableName = dbTable.name
if (dbTable.objectDataType?.dbColumns?.primaryColumns.length === 0) throw 'table has no primary key: ' + dbTable.name
const primaryColumnName = dbTable.objectDataType?.dbColumns?.primaryColumns[0].name
const { fields, template, order_by, columns } = await scan_columns(dbTable)
const { pkey_params_dcl, pkey_equals, pkey_params_val } = scan_primary_columns(dbTable)
let buttonHistory = ''
if (dbTable.log) {
buttonHistory = `
`
}
let result = `
SELECT log_mvt,log_id,log_user,log_date,${dbTable.log}__meta,log_diff
FROM ${dbTable.log}
WHERE ${pkey_equals}
ORDER BY log_id DESC
${pkey_params_val}
confirm(format("Delete record {0} from {1} table ?", ${tableName}.${primaryColumnName}, "${tableName}"))
true
false
select ${columns},
${tableName}__meta
from ${tableName}
order by ${order_by}
limit ${QUERY_LIMIT}
query_${tableName}
`
return result
}
catch (err) {
logger.error(err)
throw err
}
}