274 lines
7.2 KiB
JavaScript
274 lines
7.2 KiB
JavaScript
const GenericDBApi = require('./base.api');
|
|
const db = require('../models');
|
|
const Utils = require('../utils');
|
|
const {
|
|
applyRuntimeEnvironment,
|
|
applyRuntimeProjectFilter,
|
|
} = require('./runtime-context');
|
|
|
|
const Sequelize = db.Sequelize;
|
|
const Op = Sequelize.Op;
|
|
|
|
class Project_transition_settingsDBApi extends GenericDBApi {
|
|
static get MODEL() {
|
|
return db.project_transition_settings;
|
|
}
|
|
|
|
static get TABLE_NAME() {
|
|
return 'project_transition_settings';
|
|
}
|
|
|
|
static get SEARCHABLE_FIELDS() {
|
|
return ['source_key', 'transition_type', 'easing', 'overlay_color'];
|
|
}
|
|
|
|
static get RANGE_FIELDS() {
|
|
return ['duration_ms'];
|
|
}
|
|
|
|
static get ENUM_FIELDS() {
|
|
return ['environment'];
|
|
}
|
|
|
|
static get CSV_FIELDS() {
|
|
return [
|
|
'id',
|
|
'environment',
|
|
'source_key',
|
|
'transition_type',
|
|
'duration_ms',
|
|
'easing',
|
|
'overlay_color',
|
|
'createdAt',
|
|
];
|
|
}
|
|
|
|
static get AUTOCOMPLETE_FIELD() {
|
|
return 'transition_type';
|
|
}
|
|
|
|
static get ASSOCIATIONS() {
|
|
return [{ field: 'project', setter: 'setProject', isArray: false }];
|
|
}
|
|
|
|
static getFieldMapping(data) {
|
|
// Note: environment and projectId are NOT included here because they are
|
|
// set explicitly in upsertForProject and should never be changed via data
|
|
return {
|
|
id: data.id || undefined,
|
|
source_key: data.source_key || null,
|
|
transition_type: data.transition_type || 'fade',
|
|
duration_ms: data.duration_ms !== undefined ? data.duration_ms : 700,
|
|
easing: data.easing || 'ease-in-out',
|
|
overlay_color: data.overlay_color || '#000000',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Find settings by project ID and environment.
|
|
* This is the primary method for fetching transition settings.
|
|
*
|
|
* @param {string} projectId - Project ID
|
|
* @param {string} environment - Environment (dev, stage, production)
|
|
* @param {object} options - Query options
|
|
* @returns {object|null} Settings record or null
|
|
*/
|
|
static async findByProjectAndEnvironment(projectId, environment, options = {}) {
|
|
const transaction = options.transaction;
|
|
|
|
const record = await this.MODEL.findOne({
|
|
where: {
|
|
projectId,
|
|
environment,
|
|
},
|
|
transaction,
|
|
include: [
|
|
{
|
|
model: db.projects,
|
|
as: 'project',
|
|
},
|
|
],
|
|
});
|
|
|
|
if (!record) return null;
|
|
return record.get({ plain: true });
|
|
}
|
|
|
|
/**
|
|
* Create or update settings for a project/environment combination.
|
|
* Uses upsert semantics - creates if not exists, updates if exists.
|
|
*
|
|
* @param {string} projectId - Project ID
|
|
* @param {string} environment - Environment (dev, stage, production)
|
|
* @param {object} data - Settings data
|
|
* @param {object} options - Query options
|
|
* @returns {object} Created or updated record
|
|
*/
|
|
static async upsertForProject(projectId, environment, data, options = {}) {
|
|
const transaction = options.transaction;
|
|
const currentUser = options.currentUser;
|
|
|
|
// Check if record exists
|
|
const existing = await this.MODEL.findOne({
|
|
where: { projectId, environment },
|
|
transaction,
|
|
});
|
|
|
|
if (existing) {
|
|
// Update existing record
|
|
await existing.update(
|
|
{
|
|
...this.getFieldMapping(data),
|
|
updatedById: currentUser?.id || null,
|
|
},
|
|
{ transaction },
|
|
);
|
|
return existing.get({ plain: true });
|
|
}
|
|
|
|
// Create new record
|
|
const newRecord = await this.MODEL.create(
|
|
{
|
|
...this.getFieldMapping(data),
|
|
projectId,
|
|
environment,
|
|
createdById: currentUser?.id || null,
|
|
updatedById: currentUser?.id || null,
|
|
},
|
|
{ transaction },
|
|
);
|
|
|
|
return newRecord.get({ plain: true });
|
|
}
|
|
|
|
static async findBy(where, options = {}) {
|
|
const transaction = options.transaction;
|
|
const queryWhere = applyRuntimeEnvironment({ ...where }, options);
|
|
const projectInclude = applyRuntimeProjectFilter(
|
|
{ model: db.projects, as: 'project' },
|
|
options,
|
|
);
|
|
|
|
const record = await this.MODEL.findOne({
|
|
where: queryWhere,
|
|
transaction,
|
|
include: [projectInclude],
|
|
});
|
|
|
|
if (!record) return null;
|
|
return record.get({ plain: true });
|
|
}
|
|
|
|
static async findAll(filter = {}, options = {}) {
|
|
filter = filter || {};
|
|
const limit = filter.limit || 0;
|
|
const currentPage = +filter.page || 0;
|
|
const offset = currentPage * limit;
|
|
|
|
let where = {};
|
|
|
|
const terms = filter.project ? filter.project.split('|') : [];
|
|
const validUuids = Utils.filterValidUuids(terms);
|
|
|
|
let include = [
|
|
{
|
|
model: db.projects,
|
|
as: 'project',
|
|
where: filter.project
|
|
? {
|
|
[Op.or]: [
|
|
...(validUuids.length > 0
|
|
? [{ id: { [Op.in]: validUuids } }]
|
|
: []),
|
|
{
|
|
name: {
|
|
[Op.or]: terms.map((term) => ({ [Op.iLike]: `%${term}%` })),
|
|
},
|
|
},
|
|
],
|
|
}
|
|
: {},
|
|
},
|
|
];
|
|
|
|
include[0] = applyRuntimeProjectFilter(include[0], options);
|
|
|
|
if (filter.id) {
|
|
if (!Utils.isValidUuid(filter.id)) {
|
|
return { rows: [], count: 0 };
|
|
}
|
|
where.id = filter.id;
|
|
}
|
|
|
|
for (const field of this.SEARCHABLE_FIELDS) {
|
|
if (filter[field]) {
|
|
where[Op.and] = Utils.ilike(this.TABLE_NAME, field, filter[field]);
|
|
}
|
|
}
|
|
|
|
for (const field of this.RANGE_FIELDS) {
|
|
const rangeKey = `${field}Range`;
|
|
if (filter[rangeKey]) {
|
|
const [start, end] = filter[rangeKey];
|
|
if (start !== undefined && start !== null && start !== '') {
|
|
where[field] = { ...where[field], [Op.gte]: start };
|
|
}
|
|
if (end !== undefined && end !== null && end !== '') {
|
|
where[field] = { ...where[field], [Op.lte]: end };
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const field of this.ENUM_FIELDS) {
|
|
if (filter[field] !== undefined) {
|
|
where[field] = filter[field];
|
|
}
|
|
}
|
|
|
|
if (filter.active !== undefined) {
|
|
where.active = filter.active === true || filter.active === 'true';
|
|
}
|
|
|
|
if (filter.createdAtRange) {
|
|
const [start, end] = filter.createdAtRange;
|
|
if (start !== undefined && start !== null && start !== '') {
|
|
where.createdAt = { ...where.createdAt, [Op.gte]: start };
|
|
}
|
|
if (end !== undefined && end !== null && end !== '') {
|
|
where.createdAt = { ...where.createdAt, [Op.lte]: end };
|
|
}
|
|
}
|
|
|
|
where = applyRuntimeEnvironment(where, options);
|
|
|
|
const queryOptions = {
|
|
where,
|
|
include,
|
|
distinct: true,
|
|
order:
|
|
filter.field && filter.sort
|
|
? [[filter.field, filter.sort]]
|
|
: [['createdAt', 'desc']],
|
|
transaction: options.transaction,
|
|
};
|
|
|
|
if (!options.countOnly) {
|
|
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
}
|
|
|
|
try {
|
|
const { rows, count } = await this.MODEL.findAndCountAll(queryOptions);
|
|
return {
|
|
rows: options.countOnly ? [] : rows,
|
|
count,
|
|
};
|
|
} catch (error) {
|
|
console.error('Error executing query:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = Project_transition_settingsDBApi;
|