You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

206 lines
6.4 KiB

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