const Controller = require('libflitter/controller/Controller') const Database = require('../../../models/api/db/Database.model') const ColumnDef = require('../../../models/api/db/ColumnDef.model') const DBEntry = require('../../../models/api/db/DBEntry.model') /* * Database Controller * ------------------------------------------------------------- * Put some description here! */ class FormDatabase extends Controller { async create_new(req, res) { const { page, node } = req.form const db = new Database({ Name: req.body.name || req.body.Name || 'New Database', NodeId: node.UUID, PageId: page.UUID, }) if ( req.body.UUID ) { const existingUUID = await Database.findOne({ UUID: req.body.UUID }) if ( !existingUUID ) { db.UUID = req.body.UUID } } await db.version_save(`Added to page "${page.Name}"`, req.user.id) req.user.allow(`database:${db.UUID}`); await req.user.save() return res.api(db) } async get_config(req, res) { const { page, node, database } = req.form return res.api(database) } async get_columns(req, res) { const { page, node, database } = req.form const columns = [] for ( const col_id of database.ColumnIds ) { const rec = await ColumnDef.findOne({UUID: col_id}) if ( rec ) { rec.additionalData = rec.data() columns.push(rec) } } // Fallback for backwards compat if ( columns.length < 1 ) { return res.api((await ColumnDef.find({DatabaseId: database.UUID})).map(x => { x.additionalData = x.data() return x })) } return res.api(columns) } async set_name(req, res) { if ( !req.body.Name ) { return res.status(400) .message('Missing required field: Name') .api() } const { page, node, database } = req.form if ( req.body.Name !== database.Name ) { database.Name = req.body.Name await database.version_save(`Changed database name to "${req.body.Name}"`, req.user.id) } else { await database.save() } return res.api(database) } async set_columns(req, res) { const { page, node, database } = req.form const existing_columns = await ColumnDef.find({ DatabaseId: database.UUID }) const assoc_columns = [] existing_columns.forEach(col => assoc_columns[col.UUID] = col) const update_columns = [] for ( const col of req.body.columns ) { if ( col.UUID && assoc_columns[col.UUID] ) { assoc_columns[col.UUID].headerName = col.headerName assoc_columns[col.UUID].field = col.field assoc_columns[col.UUID].DatabaseId = database.UUID assoc_columns[col.UUID].Type = col.Type assoc_columns[col.UUID].additionalData = JSON.stringify(col.additionalData) await assoc_columns[col.UUID].version_save(`Updated in page "${page.Name}"`, req.user.id) update_columns.push(assoc_columns[col.UUID]) } else { const new_col = new ColumnDef({ headerName: col.headerName, field: col.field, DatabaseId: database.UUID, Type: col.Type, additionalData: JSON.stringify(col.additionalData), }) if ( col.UUID ) { const existingUUID = await ColumnDef.findOne({ UUID: col.UUID }) if ( !existingUUID ) { new_col.UUID = col.UUID } } await new_col.version_save(`Added to database`, req.user.id) update_columns.push(new_col) } } for ( const col of existing_columns ) { if ( !update_columns.includes(col) ) { await col.delete() } } const new_cols = update_columns.map(x => x.UUID) const no_updates = (new_cols.length === database.ColumnIds.length) && (new_cols.every(val => database.ColumnIds.includes(val))); if ( !no_updates ) { database.ColumnIds = new_cols await database.version_save('Updated columns', req.user.id) } else { await database.save() } return res.api(update_columns) } async get_data(req, res) { const { page, node, database } = req.form const entries = await DBEntry.find({DatabaseId: database.UUID}) entries.forEach(entry => entry.RowData.UUID = entry.UUID) return res.api(entries) } async set_data(req, res) { const { page, node, database } = req.form await DBEntry.deleteMany({DatabaseId: database.UUID}) const new_recs = [] for ( const rec of req.body ) { const data = {DatabaseId: database.UUID} if ( rec.UUID ) data.UUID = rec.UUID delete rec.UUID data.RowData = rec const dbe = new DBEntry(data) await dbe.save() dbe.RowData.UUID = dbe.UUID new_recs.push(dbe) } await database.version_save('Updated data', req.user.id) return res.api(await this._set_indices(database, new_recs)) } async drop_database(req, res) { const { page, node, database } = req.form await DBEntry.deleteMany({DatabaseId: database.UUID}) await database.version_save('Deleted', req.user.id) await database.delete() return res.api({}) } async _set_indices(db, data) { const index_columns = await ColumnDef.find({DatabaseId: db.UUID, Type: 'index'}) for ( const col of index_columns ) { let max_val = 0 data.forEach(row => { const val = row.RowData[col.field] if ( val && val > max_val ) max_val = val }); let next_val = max_val + 1 for ( const row of data ) { if ( !row.RowData[col.field] ) { row.RowData[col.field] = next_val next_val += 1 await row.save() } } } return data } } module.exports = exports = FormDatabase