Compare commits
11 Commits
master
...
db-optimis
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e890ccf2ed | ||
|
|
70e3c28f6a | ||
|
|
5ec464e6ce | ||
|
|
1b5c13c8ae | ||
|
|
b4fe0dde81 | ||
|
|
06dd524cd0 | ||
|
|
2680417aae | ||
|
|
42684051c3 | ||
|
|
8a20fdbd9e | ||
|
|
a8942e7c5d | ||
|
|
d3b659f3bc |
3
.gitignore
vendored
3
.gitignore
vendored
@ -4,3 +4,6 @@ node_modules/
|
|||||||
*/node_modules/
|
*/node_modules/
|
||||||
**/node_modules/
|
**/node_modules/
|
||||||
*/build/
|
*/build/
|
||||||
|
package-lock.json
|
||||||
|
CLAUDE.md
|
||||||
|
.claude/
|
||||||
18071
backend/package-lock.json
generated
18071
backend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -11,47 +11,52 @@
|
|||||||
"watch": "node watcher.js"
|
"watch": "node watcher.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.1010.0",
|
"@aws-sdk/client-s3": "^3.1011.0",
|
||||||
"@google-cloud/storage": "^5.18.2",
|
"@google-cloud/storage": "^7.0.0",
|
||||||
"axios": "^1.6.7",
|
"axios": "^1.13.0",
|
||||||
"bcrypt": "5.1.1",
|
"bcrypt": "^6.0.0",
|
||||||
"chokidar": "^4.0.3",
|
"chokidar": "^4.0.3",
|
||||||
"cors": "2.8.5",
|
"cors": "^2.8.6",
|
||||||
"csv-parser": "^3.0.0",
|
"csv-parser": "^3.2.0",
|
||||||
|
"dotenv": "^16.4.0",
|
||||||
"express": "4.18.2",
|
"express": "4.18.2",
|
||||||
|
"express-validator": "^7.0.0",
|
||||||
"formidable": "1.2.2",
|
"formidable": "1.2.2",
|
||||||
"helmet": "4.1.1",
|
"helmet": "^8.0.0",
|
||||||
|
"joi": "^17.13.0",
|
||||||
"json2csv": "^5.0.7",
|
"json2csv": "^5.0.7",
|
||||||
"jsonwebtoken": "8.5.1",
|
"jsonwebtoken": "^9.0.0",
|
||||||
"lodash": "4.17.21",
|
"lodash": "^4.17.23",
|
||||||
"moment": "2.30.1",
|
"moment": "2.30.1",
|
||||||
"multer": "^1.4.4",
|
"multer": "^2.0.0",
|
||||||
"mysql2": "2.2.5",
|
"mysql2": "2.2.5",
|
||||||
"nodemailer": "6.9.9",
|
"nodemailer": "6.9.9",
|
||||||
"passport": "^0.7.0",
|
"passport": "^0.7.0",
|
||||||
"passport-google-oauth2": "^0.2.0",
|
"passport-google-oauth2": "^0.2.0",
|
||||||
"passport-jwt": "^4.0.1",
|
"passport-jwt": "^4.0.1",
|
||||||
"passport-microsoft": "^0.1.0",
|
"passport-microsoft": "^2.0.0",
|
||||||
"pg": "8.4.1",
|
"pg": "^8.20.0",
|
||||||
|
"pino": "^9.0.0",
|
||||||
|
"pino-pretty": "^11.0.0",
|
||||||
"pg-hstore": "2.3.4",
|
"pg-hstore": "2.3.4",
|
||||||
"sequelize": "6.35.2",
|
"sequelize": "^6.37.0",
|
||||||
"sequelize-json-schema": "^2.1.1",
|
"sequelize-json-schema": "^2.1.1",
|
||||||
"sqlite": "4.0.15",
|
"sqlite": "4.0.15",
|
||||||
"swagger-jsdoc": "^6.2.8",
|
"swagger-jsdoc": "^6.2.8",
|
||||||
"swagger-ui-express": "^5.0.0",
|
"swagger-ui-express": "^5.0.0",
|
||||||
"tedious": "^18.2.4"
|
"tedious": "^18.6.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "^8.23.1",
|
"eslint": "^8.57.0",
|
||||||
"eslint-plugin-import": "^2.29.1",
|
"eslint-plugin-import": "^2.29.1",
|
||||||
"mocha": "8.1.3",
|
"mocha": "^10.0.0",
|
||||||
"node-mocks-http": "1.9.0",
|
"node-mocks-http": "^1.17.0",
|
||||||
"nodemon": "2.0.5",
|
"nodemon": "^3.0.0",
|
||||||
"sequelize-cli": "6.6.2"
|
"sequelize-cli": "^6.6.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,37 +1,10 @@
|
|||||||
|
|
||||||
|
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const envFilePath = path.resolve(__dirname, '../.env');
|
require('dotenv').config({ path: path.resolve(__dirname, '../.env') });
|
||||||
|
|
||||||
if (fs.existsSync(envFilePath)) {
|
const { validateEnv } = require('./utils/env-validation');
|
||||||
const envContent = fs.readFileSync(envFilePath, 'utf8');
|
validateEnv();
|
||||||
envContent.split('\n').forEach((line) => {
|
|
||||||
const trimmedLine = line.trim();
|
|
||||||
|
|
||||||
if (!trimmedLine || trimmedLine.startsWith('#')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const delimiterIndex = trimmedLine.indexOf('=');
|
|
||||||
|
|
||||||
if (delimiterIndex === -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const key = trimmedLine.slice(0, delimiterIndex).trim();
|
|
||||||
const rawValue = trimmedLine.slice(delimiterIndex + 1).trim();
|
|
||||||
|
|
||||||
if (!key || Object.prototype.hasOwnProperty.call(process.env, key)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unquotedValue = rawValue.replace(/^['"]|['"]$/g, '');
|
|
||||||
process.env[key] = unquotedValue;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
gcloud: {
|
gcloud: {
|
||||||
@ -48,9 +21,9 @@ const config = {
|
|||||||
bcrypt: {
|
bcrypt: {
|
||||||
saltRounds: 12
|
saltRounds: 12
|
||||||
},
|
},
|
||||||
admin_pass: "88dbeaf8",
|
admin_pass: process.env.ADMIN_PASS || "88dbeaf8",
|
||||||
user_pass: "c3baadeda5c6",
|
user_pass: process.env.USER_PASS || "c3baadeda5c6",
|
||||||
admin_email: "admin@flatlogic.com",
|
admin_email: process.env.ADMIN_EMAIL || "admin@flatlogic.com",
|
||||||
providers: {
|
providers: {
|
||||||
LOCAL: 'local',
|
LOCAL: 'local',
|
||||||
GOOGLE: 'google',
|
GOOGLE: 'google',
|
||||||
|
|||||||
@ -1,297 +1,76 @@
|
|||||||
|
const GenericDBApi = require('./base.api');
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const Utils = require('../utils');
|
const Utils = require('../utils');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
const Sequelize = db.Sequelize;
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
module.exports = class Access_logsDBApi {
|
class Access_logsDBApi extends GenericDBApi {
|
||||||
|
static get MODEL() {
|
||||||
|
return db.access_logs;
|
||||||
|
}
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
static get TABLE_NAME() {
|
||||||
const transaction = (options && options.transaction) || undefined;
|
return 'access_logs';
|
||||||
|
}
|
||||||
const access_logs = await db.access_logs.create(
|
|
||||||
{
|
static get SEARCHABLE_FIELDS() {
|
||||||
id: data.id || undefined,
|
return ['path', 'ip_address', 'user_agent'];
|
||||||
|
}
|
||||||
environment: data.environment
|
|
||||||
||
|
static get RANGE_FIELDS() {
|
||||||
null
|
return ['accessed_at'];
|
||||||
,
|
}
|
||||||
|
|
||||||
path: data.path
|
static get ENUM_FIELDS() {
|
||||||
||
|
return ['environment'];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
static get CSV_FIELDS() {
|
||||||
ip_address: data.ip_address
|
return ['id', 'environment', 'path', 'ip_address', 'user_agent', 'accessed_at', 'createdAt'];
|
||||||
||
|
}
|
||||||
null
|
|
||||||
,
|
static get AUTOCOMPLETE_FIELD() {
|
||||||
|
return 'path';
|
||||||
user_agent: data.user_agent
|
}
|
||||||
||
|
|
||||||
null
|
static get ASSOCIATIONS() {
|
||||||
,
|
return [
|
||||||
|
{ field: 'project', setter: 'setProject', isArray: false },
|
||||||
accessed_at: data.accessed_at
|
{ field: 'user', setter: 'setUser', isArray: false },
|
||||||
||
|
];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
static get FIND_BY_INCLUDES() {
|
||||||
importHash: data.importHash || null,
|
return [
|
||||||
createdById: currentUser.id,
|
{ association: 'project' },
|
||||||
updatedById: currentUser.id,
|
{ association: 'user' },
|
||||||
},
|
];
|
||||||
{ transaction },
|
}
|
||||||
);
|
|
||||||
|
static getFieldMapping(data) {
|
||||||
|
return {
|
||||||
await access_logs.setProject( data.project || null, {
|
id: data.id || undefined,
|
||||||
transaction,
|
environment: data.environment || null,
|
||||||
});
|
path: data.path || null,
|
||||||
|
ip_address: data.ip_address || null,
|
||||||
await access_logs.setUser( data.user || null, {
|
user_agent: data.user_agent || null,
|
||||||
transaction,
|
accessed_at: data.accessed_at || null,
|
||||||
});
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static async findAll(filter = {}, options = {}) {
|
||||||
|
filter = filter || {};
|
||||||
|
const limit = filter.limit || 0;
|
||||||
|
const currentPage = +filter.page || 0;
|
||||||
return access_logs;
|
const offset = currentPage * limit;
|
||||||
}
|
|
||||||
|
let where = {};
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const access_logsData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
environment: item.environment
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
path: item.path
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
ip_address: item.ip_address
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
user_agent: item.user_agent
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
accessed_at: item.accessed_at
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const access_logs = await db.access_logs.bulkCreate(access_logsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return access_logs;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const access_logs = await db.access_logs.findByPk(id, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.environment !== undefined) updatePayload.environment = data.environment;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.path !== undefined) updatePayload.path = data.path;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.ip_address !== undefined) updatePayload.ip_address = data.ip_address;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.user_agent !== undefined) updatePayload.user_agent = data.user_agent;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.accessed_at !== undefined) updatePayload.accessed_at = data.accessed_at;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await access_logs.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.project !== undefined) {
|
|
||||||
await access_logs.setProject(
|
|
||||||
|
|
||||||
data.project,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.user !== undefined) {
|
|
||||||
await access_logs.setUser(
|
|
||||||
|
|
||||||
data.user,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return access_logs;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const access_logs = await db.access_logs.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of access_logs) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of access_logs) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return access_logs;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const access_logs = await db.access_logs.findByPk(id, options);
|
|
||||||
|
|
||||||
await access_logs.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await access_logs.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return access_logs;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const access_logs = await db.access_logs.findOne({
|
|
||||||
where,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!access_logs) {
|
|
||||||
return access_logs;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = access_logs.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.project = await access_logs.getProject({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.user = await access_logs.getUser({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
let include = [
|
let include = [
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.projects,
|
model: db.projects,
|
||||||
as: 'project',
|
as: 'project',
|
||||||
|
|
||||||
where: filter.project ? {
|
where: filter.project ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -302,13 +81,10 @@ module.exports = class Access_logsDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.users,
|
model: db.users,
|
||||||
as: 'user',
|
as: 'user',
|
||||||
|
|
||||||
where: filter.user ? {
|
where: filter.user ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.user.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.user.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -319,196 +95,78 @@ module.exports = class Access_logsDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if (filter) {
|
if (filter.id) {
|
||||||
if (filter.id) {
|
where.id = Utils.uuid(filter.id);
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.path) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'access_logs',
|
|
||||||
'path',
|
|
||||||
filter.path,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.ip_address) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'access_logs',
|
|
||||||
'ip_address',
|
|
||||||
filter.ip_address,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.user_agent) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'access_logs',
|
|
||||||
'user_agent',
|
|
||||||
filter.user_agent,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.accessed_atRange) {
|
|
||||||
const [start, end] = filter.accessed_atRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
accessed_at: {
|
|
||||||
...where.accessed_at,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
accessed_at: {
|
|
||||||
...where.accessed_at,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.environment) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
environment: filter.environment,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.access_logs.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
for (const field of this.SEARCHABLE_FIELDS) {
|
||||||
let where = {};
|
if (filter[field]) {
|
||||||
|
where[Op.and] = Utils.ilike(this.TABLE_NAME, field, filter[field]);
|
||||||
|
}
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'access_logs',
|
|
||||||
'path',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.access_logs.findAll({
|
|
||||||
attributes: [ 'id', 'path' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['path', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.path,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = Access_logsDBApi;
|
||||||
|
|||||||
@ -1,279 +1,72 @@
|
|||||||
|
const GenericDBApi = require('./base.api');
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const Utils = require('../utils');
|
const Utils = require('../utils');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
const Sequelize = db.Sequelize;
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
module.exports = class Asset_variantsDBApi {
|
class Asset_variantsDBApi extends GenericDBApi {
|
||||||
|
static get MODEL() {
|
||||||
|
return db.asset_variants;
|
||||||
|
}
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
static get TABLE_NAME() {
|
||||||
const transaction = (options && options.transaction) || undefined;
|
return 'asset_variants';
|
||||||
|
}
|
||||||
const asset_variants = await db.asset_variants.create(
|
|
||||||
{
|
static get SEARCHABLE_FIELDS() {
|
||||||
id: data.id || undefined,
|
return ['cdn_url'];
|
||||||
|
}
|
||||||
variant_type: data.variant_type
|
|
||||||
||
|
static get RANGE_FIELDS() {
|
||||||
null
|
return ['width_px', 'height_px', 'size_mb'];
|
||||||
,
|
}
|
||||||
|
|
||||||
cdn_url: data.cdn_url
|
static get ENUM_FIELDS() {
|
||||||
||
|
return ['variant_type'];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
static get CSV_FIELDS() {
|
||||||
width_px: data.width_px
|
return ['id', 'variant_type', 'cdn_url', 'width_px', 'height_px', 'size_mb', 'createdAt'];
|
||||||
||
|
}
|
||||||
null
|
|
||||||
,
|
static get AUTOCOMPLETE_FIELD() {
|
||||||
|
return 'variant_type';
|
||||||
height_px: data.height_px
|
}
|
||||||
||
|
|
||||||
null
|
static get ASSOCIATIONS() {
|
||||||
,
|
return [
|
||||||
|
{ field: 'asset', setter: 'setAsset', isArray: false },
|
||||||
size_mb: data.size_mb
|
];
|
||||||
||
|
}
|
||||||
null
|
|
||||||
,
|
static get FIND_BY_INCLUDES() {
|
||||||
|
return [{ association: 'asset' }];
|
||||||
importHash: data.importHash || null,
|
}
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
static getFieldMapping(data) {
|
||||||
},
|
return {
|
||||||
{ transaction },
|
id: data.id || undefined,
|
||||||
);
|
variant_type: data.variant_type || null,
|
||||||
|
cdn_url: data.cdn_url || null,
|
||||||
|
width_px: data.width_px || null,
|
||||||
await asset_variants.setAsset( data.asset || null, {
|
height_px: data.height_px || null,
|
||||||
transaction,
|
size_mb: data.size_mb || null,
|
||||||
});
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static async findAll(filter = {}, options = {}) {
|
||||||
|
filter = filter || {};
|
||||||
|
const limit = filter.limit || 0;
|
||||||
|
const currentPage = +filter.page || 0;
|
||||||
return asset_variants;
|
const offset = currentPage * limit;
|
||||||
}
|
|
||||||
|
let where = {};
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const asset_variantsData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
variant_type: item.variant_type
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
cdn_url: item.cdn_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
width_px: item.width_px
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
height_px: item.height_px
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
size_mb: item.size_mb
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const asset_variants = await db.asset_variants.bulkCreate(asset_variantsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return asset_variants;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const asset_variants = await db.asset_variants.findByPk(id, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.variant_type !== undefined) updatePayload.variant_type = data.variant_type;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.cdn_url !== undefined) updatePayload.cdn_url = data.cdn_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.width_px !== undefined) updatePayload.width_px = data.width_px;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.height_px !== undefined) updatePayload.height_px = data.height_px;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.size_mb !== undefined) updatePayload.size_mb = data.size_mb;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await asset_variants.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.asset !== undefined) {
|
|
||||||
await asset_variants.setAsset(
|
|
||||||
|
|
||||||
data.asset,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return asset_variants;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const asset_variants = await db.asset_variants.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of asset_variants) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of asset_variants) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return asset_variants;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const asset_variants = await db.asset_variants.findByPk(id, options);
|
|
||||||
|
|
||||||
await asset_variants.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await asset_variants.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return asset_variants;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const asset_variants = await db.asset_variants.findOne({
|
|
||||||
where,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!asset_variants) {
|
|
||||||
return asset_variants;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = asset_variants.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.asset = await asset_variants.getAsset({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
let include = [
|
let include = [
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.assets,
|
model: db.assets,
|
||||||
as: 'asset',
|
as: 'asset',
|
||||||
|
|
||||||
where: filter.asset ? {
|
where: filter.asset ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.asset.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.asset.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -284,220 +77,78 @@ module.exports = class Asset_variantsDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if (filter) {
|
if (filter.id) {
|
||||||
if (filter.id) {
|
where.id = Utils.uuid(filter.id);
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.cdn_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'asset_variants',
|
|
||||||
'cdn_url',
|
|
||||||
filter.cdn_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.width_pxRange) {
|
|
||||||
const [start, end] = filter.width_pxRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
width_px: {
|
|
||||||
...where.width_px,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
width_px: {
|
|
||||||
...where.width_px,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.height_pxRange) {
|
|
||||||
const [start, end] = filter.height_pxRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
height_px: {
|
|
||||||
...where.height_px,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
height_px: {
|
|
||||||
...where.height_px,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.size_mbRange) {
|
|
||||||
const [start, end] = filter.size_mbRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
size_mb: {
|
|
||||||
...where.size_mb,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
size_mb: {
|
|
||||||
...where.size_mb,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.variant_type) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
variant_type: filter.variant_type,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.asset_variants.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
for (const field of this.SEARCHABLE_FIELDS) {
|
||||||
let where = {};
|
if (filter[field]) {
|
||||||
|
where[Op.and] = Utils.ilike(this.TABLE_NAME, field, filter[field]);
|
||||||
|
}
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'asset_variants',
|
|
||||||
'variant_type',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.asset_variants.findAll({
|
|
||||||
attributes: [ 'id', 'variant_type' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['variant_type', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.variant_type,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = Asset_variantsDBApi;
|
||||||
|
|||||||
@ -1,391 +1,90 @@
|
|||||||
|
const GenericDBApi = require('./base.api');
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const Utils = require('../utils');
|
const Utils = require('../utils');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
const Sequelize = db.Sequelize;
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
module.exports = class AssetsDBApi {
|
class AssetsDBApi extends GenericDBApi {
|
||||||
|
static get MODEL() {
|
||||||
|
return db.assets;
|
||||||
|
}
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
static get TABLE_NAME() {
|
||||||
const transaction = (options && options.transaction) || undefined;
|
return 'assets';
|
||||||
|
}
|
||||||
const assets = await db.assets.create(
|
|
||||||
{
|
static get SEARCHABLE_FIELDS() {
|
||||||
id: data.id || undefined,
|
return ['name', 'cdn_url', 'storage_key', 'mime_type', 'checksum'];
|
||||||
|
}
|
||||||
name: data.name
|
|
||||||
||
|
static get RANGE_FIELDS() {
|
||||||
null
|
return ['size_mb', 'width_px', 'height_px', 'duration_sec', 'deleted_at_time'];
|
||||||
,
|
}
|
||||||
|
|
||||||
asset_type: data.asset_type
|
static get ENUM_FIELDS() {
|
||||||
||
|
return ['asset_type', 'type', 'is_public', 'is_deleted'];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
static get CSV_FIELDS() {
|
||||||
cdn_url: data.cdn_url
|
return ['id', 'name', 'asset_type', 'type', 'cdn_url', 'storage_key', 'mime_type', 'size_mb', 'createdAt'];
|
||||||
||
|
}
|
||||||
null
|
|
||||||
,
|
static get AUTOCOMPLETE_FIELD() {
|
||||||
|
return 'name';
|
||||||
storage_key: data.storage_key
|
}
|
||||||
||
|
|
||||||
null
|
static get ASSOCIATIONS() {
|
||||||
,
|
return [
|
||||||
|
{ field: 'project', setter: 'setProject', isArray: false },
|
||||||
mime_type: data.mime_type
|
];
|
||||||
||
|
}
|
||||||
null
|
|
||||||
,
|
static get FIND_BY_INCLUDES() {
|
||||||
|
return [
|
||||||
size_mb: data.size_mb
|
{ association: 'asset_variants_asset' },
|
||||||
||
|
{ association: 'project' },
|
||||||
null
|
];
|
||||||
,
|
}
|
||||||
|
|
||||||
width_px: data.width_px
|
static get RELATION_FILTERS() {
|
||||||
||
|
return [
|
||||||
null
|
{ filterKey: 'project', model: db.projects, as: 'project', searchField: 'name' },
|
||||||
,
|
];
|
||||||
|
}
|
||||||
height_px: data.height_px
|
|
||||||
||
|
static getFieldMapping(data) {
|
||||||
null
|
return {
|
||||||
,
|
id: data.id || undefined,
|
||||||
|
name: data.name || null,
|
||||||
duration_sec: data.duration_sec
|
asset_type: data.asset_type || null,
|
||||||
||
|
type: data.type || 'general',
|
||||||
null
|
cdn_url: data.cdn_url || null,
|
||||||
,
|
storage_key: data.storage_key || null,
|
||||||
|
mime_type: data.mime_type || null,
|
||||||
checksum: data.checksum
|
size_mb: data.size_mb || null,
|
||||||
||
|
width_px: data.width_px || null,
|
||||||
null
|
height_px: data.height_px || null,
|
||||||
,
|
duration_sec: data.duration_sec || null,
|
||||||
|
checksum: data.checksum || null,
|
||||||
is_public: data.is_public
|
is_public: data.is_public || false,
|
||||||
||
|
is_deleted: data.is_deleted || false,
|
||||||
false
|
deleted_at_time: data.deleted_at_time || null,
|
||||||
|
};
|
||||||
,
|
}
|
||||||
|
|
||||||
is_deleted: data.is_deleted
|
static async findAll(filter = {}, options = {}) {
|
||||||
||
|
filter = filter || {};
|
||||||
false
|
const limit = filter.limit || 0;
|
||||||
|
const currentPage = +filter.page || 0;
|
||||||
,
|
const offset = currentPage * limit;
|
||||||
|
|
||||||
deleted_at_time: data.deleted_at_time
|
let where = {};
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
await assets.setProject( data.project || null, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return assets;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const assetsData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
name: item.name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
asset_type: item.asset_type
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
cdn_url: item.cdn_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
storage_key: item.storage_key
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
mime_type: item.mime_type
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
size_mb: item.size_mb
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
width_px: item.width_px
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
height_px: item.height_px
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
duration_sec: item.duration_sec
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
checksum: item.checksum
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_public: item.is_public
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
is_deleted: item.is_deleted
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
deleted_at_time: item.deleted_at_time
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const assets = await db.assets.bulkCreate(assetsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return assets;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const assets = await db.assets.findByPk(id, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.name !== undefined) updatePayload.name = data.name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.asset_type !== undefined) updatePayload.asset_type = data.asset_type;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.cdn_url !== undefined) updatePayload.cdn_url = data.cdn_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.storage_key !== undefined) updatePayload.storage_key = data.storage_key;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.mime_type !== undefined) updatePayload.mime_type = data.mime_type;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.size_mb !== undefined) updatePayload.size_mb = data.size_mb;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.width_px !== undefined) updatePayload.width_px = data.width_px;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.height_px !== undefined) updatePayload.height_px = data.height_px;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.duration_sec !== undefined) updatePayload.duration_sec = data.duration_sec;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.checksum !== undefined) updatePayload.checksum = data.checksum;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_public !== undefined) updatePayload.is_public = data.is_public;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_deleted !== undefined) updatePayload.is_deleted = data.is_deleted;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.deleted_at_time !== undefined) updatePayload.deleted_at_time = data.deleted_at_time;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await assets.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.project !== undefined) {
|
|
||||||
await assets.setProject(
|
|
||||||
|
|
||||||
data.project,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return assets;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const assets = await db.assets.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of assets) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of assets) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return assets;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const assets = await db.assets.findByPk(id, options);
|
|
||||||
|
|
||||||
await assets.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await assets.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return assets;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const assets = await db.assets.findOne({
|
|
||||||
where,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!assets) {
|
|
||||||
return assets;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = assets.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.asset_variants_asset = await assets.getAsset_variants_asset({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.project = await assets.getProject({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
let include = [
|
let include = [
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.projects,
|
model: db.projects,
|
||||||
as: 'project',
|
as: 'project',
|
||||||
|
|
||||||
where: filter.project ? {
|
where: filter.project ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -396,326 +95,78 @@ module.exports = class AssetsDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if (filter) {
|
if (filter.id) {
|
||||||
if (filter.id) {
|
where.id = Utils.uuid(filter.id);
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'assets',
|
|
||||||
'name',
|
|
||||||
filter.name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.cdn_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'assets',
|
|
||||||
'cdn_url',
|
|
||||||
filter.cdn_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.storage_key) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'assets',
|
|
||||||
'storage_key',
|
|
||||||
filter.storage_key,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.mime_type) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'assets',
|
|
||||||
'mime_type',
|
|
||||||
filter.mime_type,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.checksum) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'assets',
|
|
||||||
'checksum',
|
|
||||||
filter.checksum,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.size_mbRange) {
|
|
||||||
const [start, end] = filter.size_mbRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
size_mb: {
|
|
||||||
...where.size_mb,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
size_mb: {
|
|
||||||
...where.size_mb,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.width_pxRange) {
|
|
||||||
const [start, end] = filter.width_pxRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
width_px: {
|
|
||||||
...where.width_px,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
width_px: {
|
|
||||||
...where.width_px,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.height_pxRange) {
|
|
||||||
const [start, end] = filter.height_pxRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
height_px: {
|
|
||||||
...where.height_px,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
height_px: {
|
|
||||||
...where.height_px,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.duration_secRange) {
|
|
||||||
const [start, end] = filter.duration_secRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
duration_sec: {
|
|
||||||
...where.duration_sec,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
duration_sec: {
|
|
||||||
...where.duration_sec,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.deleted_at_timeRange) {
|
|
||||||
const [start, end] = filter.deleted_at_timeRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
deleted_at_time: {
|
|
||||||
...where.deleted_at_time,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
deleted_at_time: {
|
|
||||||
...where.deleted_at_time,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.asset_type) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
asset_type: filter.asset_type,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.is_public) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_public: filter.is_public,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.is_deleted) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_deleted: filter.is_deleted,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.assets.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
for (const field of this.SEARCHABLE_FIELDS) {
|
||||||
let where = {};
|
if (filter[field]) {
|
||||||
|
where[Op.and] = Utils.ilike(this.TABLE_NAME, field, filter[field]);
|
||||||
|
}
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'assets',
|
|
||||||
'name',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.assets.findAll({
|
|
||||||
attributes: [ 'id', 'name' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['name', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.name,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = AssetsDBApi;
|
||||||
|
|||||||
313
backend/src/db/api/base.api.js
Normal file
313
backend/src/db/api/base.api.js
Normal file
@ -0,0 +1,313 @@
|
|||||||
|
const db = require('../models');
|
||||||
|
const Utils = require('../utils');
|
||||||
|
const { parse } = require('json2csv');
|
||||||
|
|
||||||
|
const Sequelize = db.Sequelize;
|
||||||
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
|
class GenericDBApi {
|
||||||
|
static get MODEL() {
|
||||||
|
throw new Error('MODEL must be defined in subclass');
|
||||||
|
}
|
||||||
|
|
||||||
|
static get TABLE_NAME() {
|
||||||
|
return this.MODEL.getTableName();
|
||||||
|
}
|
||||||
|
|
||||||
|
static get SEARCHABLE_FIELDS() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
static get RANGE_FIELDS() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
static get ENUM_FIELDS() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
static get RELATION_FILTERS() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
static get CSV_FIELDS() {
|
||||||
|
return ['id', 'createdAt'];
|
||||||
|
}
|
||||||
|
|
||||||
|
static get AUTOCOMPLETE_FIELD() {
|
||||||
|
return 'name';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get ASSOCIATIONS() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
static get FIND_BY_INCLUDES() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
static get FIND_ALL_INCLUDES() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
static getFieldMapping(data) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async create(data, options = {}) {
|
||||||
|
const currentUser = options.currentUser || { id: null };
|
||||||
|
const transaction = options.transaction;
|
||||||
|
|
||||||
|
const mappedData = this.getFieldMapping(data);
|
||||||
|
|
||||||
|
const record = await this.MODEL.create(
|
||||||
|
{
|
||||||
|
...mappedData,
|
||||||
|
importHash: data.importHash || null,
|
||||||
|
createdById: currentUser.id,
|
||||||
|
updatedById: currentUser.id,
|
||||||
|
},
|
||||||
|
{ transaction }
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const assoc of this.ASSOCIATIONS) {
|
||||||
|
if (data[assoc.field] !== undefined) {
|
||||||
|
await record[assoc.setter](data[assoc.field] || (assoc.isArray ? [] : null), { transaction });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async bulkImport(data, options = {}) {
|
||||||
|
const currentUser = options.currentUser || { id: null };
|
||||||
|
const transaction = options.transaction;
|
||||||
|
|
||||||
|
const recordsData = data.map((item, index) => ({
|
||||||
|
...this.getFieldMapping(item),
|
||||||
|
importHash: item.importHash || null,
|
||||||
|
createdById: currentUser.id,
|
||||||
|
updatedById: currentUser.id,
|
||||||
|
createdAt: new Date(Date.now() + index * 1000),
|
||||||
|
}));
|
||||||
|
|
||||||
|
return this.MODEL.bulkCreate(recordsData, { transaction });
|
||||||
|
}
|
||||||
|
|
||||||
|
static async update(id, data, options = {}) {
|
||||||
|
const currentUser = options.currentUser || { id: null };
|
||||||
|
const transaction = options.transaction;
|
||||||
|
|
||||||
|
const record = await this.MODEL.findByPk(id, { transaction });
|
||||||
|
|
||||||
|
if (!record) {
|
||||||
|
throw { status: 404, message: `${this.TABLE_NAME} not found` };
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatePayload = { updatedById: currentUser.id };
|
||||||
|
const mappedData = this.getFieldMapping(data);
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(mappedData)) {
|
||||||
|
if (value !== undefined) {
|
||||||
|
updatePayload[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await record.update(updatePayload, { transaction });
|
||||||
|
|
||||||
|
for (const assoc of this.ASSOCIATIONS) {
|
||||||
|
if (data[assoc.field] !== undefined) {
|
||||||
|
await record[assoc.setter](data[assoc.field], { transaction });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async deleteByIds(ids, options = {}) {
|
||||||
|
const currentUser = options.currentUser || { id: null };
|
||||||
|
const transaction = options.transaction;
|
||||||
|
|
||||||
|
const records = await this.MODEL.findAll({
|
||||||
|
where: { id: { [Op.in]: ids } },
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.sequelize.transaction(async (tx) => {
|
||||||
|
for (const record of records) {
|
||||||
|
await record.update({ deletedBy: currentUser.id }, { transaction: tx });
|
||||||
|
}
|
||||||
|
for (const record of records) {
|
||||||
|
await record.destroy({ transaction: tx });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return records;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async remove(id, options = {}) {
|
||||||
|
const currentUser = options.currentUser || { id: null };
|
||||||
|
const transaction = options.transaction;
|
||||||
|
|
||||||
|
const record = await this.MODEL.findByPk(id, { transaction });
|
||||||
|
|
||||||
|
if (!record) {
|
||||||
|
throw { status: 404, message: `${this.TABLE_NAME} not found` };
|
||||||
|
}
|
||||||
|
|
||||||
|
await record.update({ deletedBy: currentUser.id }, { transaction });
|
||||||
|
await record.destroy({ transaction });
|
||||||
|
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async findBy(where, options = {}) {
|
||||||
|
const transaction = options.transaction;
|
||||||
|
|
||||||
|
const record = await this.MODEL.findOne({
|
||||||
|
where,
|
||||||
|
transaction,
|
||||||
|
include: this.FIND_BY_INCLUDES,
|
||||||
|
});
|
||||||
|
|
||||||
|
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 = {};
|
||||||
|
let include = [...this.FIND_ALL_INCLUDES];
|
||||||
|
|
||||||
|
if (filter.id) {
|
||||||
|
where.id = Utils.uuid(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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const rel of this.RELATION_FILTERS) {
|
||||||
|
if (filter[rel.filterKey]) {
|
||||||
|
const searchTerms = filter[rel.filterKey].split('|');
|
||||||
|
const relInclude = {
|
||||||
|
model: rel.model,
|
||||||
|
as: rel.as,
|
||||||
|
required: searchTerms.length > 0,
|
||||||
|
where: searchTerms.length > 0 ? {
|
||||||
|
[Op.or]: [
|
||||||
|
{ id: { [Op.in]: searchTerms.map(term => Utils.uuid(term)) } },
|
||||||
|
rel.searchField ? {
|
||||||
|
[rel.searchField]: {
|
||||||
|
[Op.or]: searchTerms.map(term => ({ [Op.iLike]: `%${term}%` }))
|
||||||
|
}
|
||||||
|
} : {}
|
||||||
|
]
|
||||||
|
} : undefined
|
||||||
|
};
|
||||||
|
include = [relInclude, ...include];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async findAllAutocomplete(query, limit, offset) {
|
||||||
|
let where = {};
|
||||||
|
|
||||||
|
if (query) {
|
||||||
|
where = {
|
||||||
|
[Op.or]: [
|
||||||
|
{ id: Utils.uuid(query) },
|
||||||
|
Utils.ilike(this.TABLE_NAME, this.AUTOCOMPLETE_FIELD, query),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const records = await this.MODEL.findAll({
|
||||||
|
attributes: ['id', this.AUTOCOMPLETE_FIELD],
|
||||||
|
where,
|
||||||
|
limit: limit ? Number(limit) : undefined,
|
||||||
|
offset: offset ? Number(offset) : undefined,
|
||||||
|
order: [[this.AUTOCOMPLETE_FIELD, 'ASC']],
|
||||||
|
});
|
||||||
|
|
||||||
|
return records.map((record) => ({
|
||||||
|
id: record.id,
|
||||||
|
label: record[this.AUTOCOMPLETE_FIELD],
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
static toCSV(rows) {
|
||||||
|
const opts = { fields: this.CSV_FIELDS };
|
||||||
|
return parse(rows, opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = GenericDBApi;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
|
const GenericDBApi = require('./base.api');
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const Utils = require('../utils');
|
const Utils = require('../utils');
|
||||||
const {
|
const {
|
||||||
@ -6,306 +6,102 @@ const {
|
|||||||
getRuntimeProjectSlug,
|
getRuntimeProjectSlug,
|
||||||
} = require('./runtime-context');
|
} = require('./runtime-context');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
const Sequelize = db.Sequelize;
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
module.exports = class Page_elementsDBApi {
|
class Page_elementsDBApi extends GenericDBApi {
|
||||||
|
static get MODEL() {
|
||||||
|
return db.page_elements;
|
||||||
|
}
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
static get TABLE_NAME() {
|
||||||
const transaction = (options && options.transaction) || undefined;
|
return 'page_elements';
|
||||||
|
}
|
||||||
const page_elements = await db.page_elements.create(
|
|
||||||
{
|
static get SEARCHABLE_FIELDS() {
|
||||||
id: data.id || undefined,
|
return ['name', 'style_json', 'content_json'];
|
||||||
|
}
|
||||||
element_type: data.element_type ?? null,
|
|
||||||
|
static get RANGE_FIELDS() {
|
||||||
name: data.name ?? null,
|
return ['sort_order', 'x_percent', 'y_percent', 'width_percent', 'height_percent', 'rotation_deg'];
|
||||||
|
}
|
||||||
sort_order: data.sort_order ?? 0,
|
|
||||||
|
static get ENUM_FIELDS() {
|
||||||
is_visible: data.is_visible ?? false,
|
return ['element_type', 'is_visible'];
|
||||||
|
}
|
||||||
x_percent: data.x_percent ?? null,
|
|
||||||
|
static get CSV_FIELDS() {
|
||||||
y_percent: data.y_percent ?? null,
|
return ['id', 'element_type', 'name', 'sort_order', 'is_visible', 'x_percent', 'y_percent', 'createdAt'];
|
||||||
|
}
|
||||||
width_percent: data.width_percent ?? null,
|
|
||||||
|
static get AUTOCOMPLETE_FIELD() {
|
||||||
height_percent: data.height_percent ?? null,
|
return 'name';
|
||||||
|
}
|
||||||
rotation_deg: data.rotation_deg ?? null,
|
|
||||||
|
static get ASSOCIATIONS() {
|
||||||
style_json: data.style_json ?? null,
|
return [
|
||||||
|
{ field: 'page', setter: 'setPage', isArray: false },
|
||||||
content_json: data.content_json ?? null,
|
];
|
||||||
|
}
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
static getFieldMapping(data) {
|
||||||
updatedById: currentUser.id,
|
return {
|
||||||
},
|
id: data.id || undefined,
|
||||||
{ transaction },
|
element_type: data.element_type ?? null,
|
||||||
);
|
name: data.name ?? null,
|
||||||
|
sort_order: data.sort_order ?? 0,
|
||||||
|
is_visible: data.is_visible ?? false,
|
||||||
await page_elements.setPage( data.page || null, {
|
x_percent: data.x_percent ?? null,
|
||||||
transaction,
|
y_percent: data.y_percent ?? null,
|
||||||
});
|
width_percent: data.width_percent ?? null,
|
||||||
|
height_percent: data.height_percent ?? null,
|
||||||
|
rotation_deg: data.rotation_deg ?? null,
|
||||||
|
style_json: data.style_json ?? null,
|
||||||
|
content_json: data.content_json ?? null,
|
||||||
|
};
|
||||||
|
}
|
||||||
return page_elements;
|
|
||||||
}
|
static async findBy(where, options = {}) {
|
||||||
|
const transaction = options.transaction;
|
||||||
|
const runtimeEnvironment = getRuntimeEnvironment(options);
|
||||||
static async bulkImport(data, options) {
|
const runtimeProjectSlug = getRuntimeProjectSlug(options);
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
const pageInclude = {
|
||||||
const transaction = (options && options.transaction) || undefined;
|
model: db.tour_pages,
|
||||||
|
as: 'page',
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
required: Boolean(runtimeEnvironment || runtimeProjectSlug),
|
||||||
const page_elementsData = data.map((item, index) => ({
|
where: runtimeEnvironment ? { environment: runtimeEnvironment } : {},
|
||||||
id: item.id || undefined,
|
include: runtimeProjectSlug
|
||||||
|
? [{
|
||||||
element_type: item.element_type ?? null,
|
model: db.projects,
|
||||||
|
as: 'project',
|
||||||
name: item.name ?? null,
|
required: true,
|
||||||
|
where: { slug: runtimeProjectSlug },
|
||||||
sort_order: item.sort_order ?? 0,
|
}]
|
||||||
|
: [],
|
||||||
is_visible: item.is_visible ?? false,
|
};
|
||||||
|
|
||||||
x_percent: item.x_percent ?? null,
|
const record = await this.MODEL.findOne({
|
||||||
|
where,
|
||||||
y_percent: item.y_percent ?? null,
|
transaction,
|
||||||
|
include: [pageInclude],
|
||||||
width_percent: item.width_percent ?? null,
|
});
|
||||||
|
|
||||||
height_percent: item.height_percent ?? null,
|
if (!record) return null;
|
||||||
|
return record.get({ plain: true });
|
||||||
rotation_deg: item.rotation_deg ?? null,
|
}
|
||||||
|
|
||||||
style_json: item.style_json ?? null,
|
static async findAll(filter = {}, options = {}) {
|
||||||
|
filter = filter || {};
|
||||||
content_json: item.content_json ?? null,
|
const limit = filter.limit || 0;
|
||||||
|
const currentPage = +filter.page || 0;
|
||||||
importHash: item.importHash || null,
|
const offset = currentPage * limit;
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
let where = {};
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const page_elements = await db.page_elements.bulkCreate(page_elementsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return page_elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const page_elements = await db.page_elements.findByPk(id, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.element_type !== undefined) updatePayload.element_type = data.element_type;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.name !== undefined) updatePayload.name = data.name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.sort_order !== undefined) updatePayload.sort_order = data.sort_order;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_visible !== undefined) updatePayload.is_visible = data.is_visible;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.x_percent !== undefined) updatePayload.x_percent = data.x_percent;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.y_percent !== undefined) updatePayload.y_percent = data.y_percent;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.width_percent !== undefined) updatePayload.width_percent = data.width_percent;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.height_percent !== undefined) updatePayload.height_percent = data.height_percent;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.rotation_deg !== undefined) updatePayload.rotation_deg = data.rotation_deg;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.style_json !== undefined) updatePayload.style_json = data.style_json;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.content_json !== undefined) updatePayload.content_json = data.content_json;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await page_elements.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.page !== undefined) {
|
|
||||||
await page_elements.setPage(
|
|
||||||
|
|
||||||
data.page,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return page_elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const page_elements = await db.page_elements.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of page_elements) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of page_elements) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return page_elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const page_elements = await db.page_elements.findByPk(id, options);
|
|
||||||
|
|
||||||
await page_elements.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await page_elements.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return page_elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
const runtimeEnvironment = getRuntimeEnvironment(options);
|
|
||||||
const runtimeProjectSlug = getRuntimeProjectSlug(options);
|
|
||||||
const pageInclude = {
|
|
||||||
model: db.tour_pages,
|
|
||||||
as: 'page',
|
|
||||||
required: Boolean(runtimeEnvironment || runtimeProjectSlug),
|
|
||||||
where: runtimeEnvironment ? { environment: runtimeEnvironment } : {},
|
|
||||||
include: runtimeProjectSlug
|
|
||||||
? [{
|
|
||||||
model: db.projects,
|
|
||||||
as: 'project',
|
|
||||||
required: true,
|
|
||||||
where: { slug: runtimeProjectSlug },
|
|
||||||
}]
|
|
||||||
: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
const page_elements = await db.page_elements.findOne(
|
|
||||||
{ where, include: [pageInclude], transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!page_elements) {
|
|
||||||
return page_elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = page_elements.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.page = await page_elements.getPage({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
filter = filter || {};
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
let include = [
|
let include = [
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.tour_pages,
|
model: db.tour_pages,
|
||||||
as: 'page',
|
as: 'page',
|
||||||
|
|
||||||
where: filter.page ? {
|
where: filter.page ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.page.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.page.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -316,341 +112,99 @@ module.exports = class Page_elementsDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
const runtimeEnvironment = getRuntimeEnvironment(options);
|
|
||||||
const runtimeProjectSlug = getRuntimeProjectSlug(options);
|
|
||||||
|
|
||||||
if (runtimeEnvironment) {
|
const runtimeEnvironment = getRuntimeEnvironment(options);
|
||||||
include[0].where = {
|
const runtimeProjectSlug = getRuntimeProjectSlug(options);
|
||||||
...(include[0].where || {}),
|
|
||||||
environment: runtimeEnvironment,
|
|
||||||
};
|
|
||||||
include[0].required = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runtimeProjectSlug) {
|
if (runtimeEnvironment) {
|
||||||
include[0].include = [{
|
include[0].where = {
|
||||||
model: db.projects,
|
...(include[0].where || {}),
|
||||||
as: 'project',
|
environment: runtimeEnvironment,
|
||||||
required: true,
|
};
|
||||||
where: { slug: runtimeProjectSlug },
|
include[0].required = true;
|
||||||
}];
|
|
||||||
include[0].required = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'page_elements',
|
|
||||||
'name',
|
|
||||||
filter.name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.style_json) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'page_elements',
|
|
||||||
'style_json',
|
|
||||||
filter.style_json,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.content_json) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'page_elements',
|
|
||||||
'content_json',
|
|
||||||
filter.content_json,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.sort_orderRange) {
|
|
||||||
const [start, end] = filter.sort_orderRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.x_percentRange) {
|
|
||||||
const [start, end] = filter.x_percentRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
x_percent: {
|
|
||||||
...where.x_percent,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
x_percent: {
|
|
||||||
...where.x_percent,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.y_percentRange) {
|
|
||||||
const [start, end] = filter.y_percentRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
y_percent: {
|
|
||||||
...where.y_percent,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
y_percent: {
|
|
||||||
...where.y_percent,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.width_percentRange) {
|
|
||||||
const [start, end] = filter.width_percentRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
width_percent: {
|
|
||||||
...where.width_percent,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
width_percent: {
|
|
||||||
...where.width_percent,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.height_percentRange) {
|
|
||||||
const [start, end] = filter.height_percentRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
height_percent: {
|
|
||||||
...where.height_percent,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
height_percent: {
|
|
||||||
...where.height_percent,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.rotation_degRange) {
|
|
||||||
const [start, end] = filter.rotation_degRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
rotation_deg: {
|
|
||||||
...where.rotation_deg,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
rotation_deg: {
|
|
||||||
...where.rotation_deg,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.element_type) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
element_type: filter.element_type,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.is_visible) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_visible: filter.is_visible,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.page_elements.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
if (runtimeProjectSlug) {
|
||||||
let where = {};
|
include[0].include = [{
|
||||||
|
model: db.projects,
|
||||||
|
as: 'project',
|
||||||
|
required: true,
|
||||||
if (query) {
|
where: { slug: runtimeProjectSlug },
|
||||||
where = {
|
}];
|
||||||
[Op.or]: [
|
include[0].required = true;
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'page_elements',
|
|
||||||
'name',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.page_elements.findAll({
|
|
||||||
attributes: [ 'id', 'name' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['name', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.name,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filter.id) {
|
||||||
|
where.id = Utils.uuid(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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = Page_elementsDBApi;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
|
const GenericDBApi = require('./base.api');
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const Utils = require('../utils');
|
const Utils = require('../utils');
|
||||||
const {
|
const {
|
||||||
@ -6,334 +6,115 @@ const {
|
|||||||
getRuntimeProjectSlug,
|
getRuntimeProjectSlug,
|
||||||
} = require('./runtime-context');
|
} = require('./runtime-context');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
const Sequelize = db.Sequelize;
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
module.exports = class Page_linksDBApi {
|
class Page_linksDBApi extends GenericDBApi {
|
||||||
|
static get MODEL() {
|
||||||
|
return db.page_links;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get TABLE_NAME() {
|
||||||
|
return 'page_links';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get SEARCHABLE_FIELDS() {
|
||||||
|
return ['external_url', 'trigger_selector'];
|
||||||
|
}
|
||||||
|
|
||||||
static async create(data, options) {
|
static get RANGE_FIELDS() {
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
return [];
|
||||||
const transaction = (options && options.transaction) || undefined;
|
}
|
||||||
|
|
||||||
const page_links = await db.page_links.create(
|
static get ENUM_FIELDS() {
|
||||||
{
|
return ['direction', 'is_active'];
|
||||||
id: data.id || undefined,
|
}
|
||||||
|
|
||||||
direction: data.direction
|
static get CSV_FIELDS() {
|
||||||
||
|
return ['id', 'direction', 'external_url', 'is_active', 'trigger_selector', 'createdAt'];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
|
||||||
external_url: data.external_url
|
static get AUTOCOMPLETE_FIELD() {
|
||||||
||
|
return 'direction';
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
|
||||||
is_active: data.is_active
|
static get ASSOCIATIONS() {
|
||||||
||
|
return [
|
||||||
false
|
{ field: 'from_page', setter: 'setFrom_page', isArray: false },
|
||||||
|
{ field: 'to_page', setter: 'setTo_page', isArray: false },
|
||||||
|
{ field: 'transition', setter: 'setTransition', isArray: false },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
,
|
static getFieldMapping(data) {
|
||||||
|
return {
|
||||||
|
id: data.id || undefined,
|
||||||
|
direction: data.direction || null,
|
||||||
|
external_url: data.external_url || null,
|
||||||
|
is_active: data.is_active || false,
|
||||||
|
trigger_selector: data.trigger_selector || null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
trigger_selector: data.trigger_selector
|
static async findBy(where, options = {}) {
|
||||||
||
|
const transaction = options.transaction;
|
||||||
null
|
const runtimeEnvironment = getRuntimeEnvironment(options);
|
||||||
,
|
const runtimeProjectSlug = getRuntimeProjectSlug(options);
|
||||||
|
const buildProjectInclude = () => (
|
||||||
importHash: data.importHash || null,
|
runtimeProjectSlug
|
||||||
createdById: currentUser.id,
|
? [{
|
||||||
updatedById: currentUser.id,
|
model: db.projects,
|
||||||
},
|
as: 'project',
|
||||||
{ transaction },
|
required: true,
|
||||||
|
where: { slug: runtimeProjectSlug },
|
||||||
|
}]
|
||||||
|
: []
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const record = await this.MODEL.findOne({
|
||||||
await page_links.setFrom_page( data.from_page || null, {
|
where,
|
||||||
transaction,
|
transaction,
|
||||||
});
|
include: [
|
||||||
|
{
|
||||||
await page_links.setTo_page( data.to_page || null, {
|
model: db.tour_pages,
|
||||||
transaction,
|
as: 'from_page',
|
||||||
});
|
required: Boolean(runtimeEnvironment || runtimeProjectSlug),
|
||||||
|
where: runtimeEnvironment ? { environment: runtimeEnvironment } : {},
|
||||||
await page_links.setTransition( data.transition || null, {
|
include: buildProjectInclude(),
|
||||||
transaction,
|
},
|
||||||
});
|
{
|
||||||
|
model: db.tour_pages,
|
||||||
|
as: 'to_page',
|
||||||
|
required: false,
|
||||||
|
where: runtimeEnvironment ? { environment: runtimeEnvironment } : {},
|
||||||
|
include: buildProjectInclude(),
|
||||||
|
},
|
||||||
return page_links;
|
{
|
||||||
}
|
model: db.transitions,
|
||||||
|
as: 'transition',
|
||||||
|
required: false,
|
||||||
static async bulkImport(data, options) {
|
where: runtimeEnvironment ? { environment: runtimeEnvironment } : {},
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
include: buildProjectInclude(),
|
||||||
const transaction = (options && options.transaction) || undefined;
|
},
|
||||||
|
],
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
});
|
||||||
const page_linksData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
if (!record) return null;
|
||||||
|
return record.get({ plain: true });
|
||||||
direction: item.direction
|
}
|
||||||
||
|
|
||||||
null
|
static async findAll(filter = {}, options = {}) {
|
||||||
,
|
filter = filter || {};
|
||||||
|
const limit = filter.limit || 0;
|
||||||
external_url: item.external_url
|
const currentPage = +filter.page || 0;
|
||||||
||
|
const offset = currentPage * limit;
|
||||||
null
|
|
||||||
,
|
let where = {};
|
||||||
|
|
||||||
is_active: item.is_active
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
trigger_selector: item.trigger_selector
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const page_links = await db.page_links.bulkCreate(page_linksData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return page_links;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const page_links = await db.page_links.findByPk(id, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.direction !== undefined) updatePayload.direction = data.direction;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.external_url !== undefined) updatePayload.external_url = data.external_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_active !== undefined) updatePayload.is_active = data.is_active;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.trigger_selector !== undefined) updatePayload.trigger_selector = data.trigger_selector;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await page_links.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.from_page !== undefined) {
|
|
||||||
await page_links.setFrom_page(
|
|
||||||
|
|
||||||
data.from_page,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.to_page !== undefined) {
|
|
||||||
await page_links.setTo_page(
|
|
||||||
|
|
||||||
data.to_page,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.transition !== undefined) {
|
|
||||||
await page_links.setTransition(
|
|
||||||
|
|
||||||
data.transition,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return page_links;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const page_links = await db.page_links.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of page_links) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of page_links) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return page_links;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const page_links = await db.page_links.findByPk(id, options);
|
|
||||||
|
|
||||||
await page_links.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await page_links.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return page_links;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
const runtimeEnvironment = getRuntimeEnvironment(options);
|
|
||||||
const runtimeProjectSlug = getRuntimeProjectSlug(options);
|
|
||||||
const buildProjectInclude = () => (
|
|
||||||
runtimeProjectSlug
|
|
||||||
? [{
|
|
||||||
model: db.projects,
|
|
||||||
as: 'project',
|
|
||||||
required: true,
|
|
||||||
where: { slug: runtimeProjectSlug },
|
|
||||||
}]
|
|
||||||
: []
|
|
||||||
);
|
|
||||||
|
|
||||||
const page_links = await db.page_links.findOne(
|
|
||||||
{
|
|
||||||
where,
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
model: db.tour_pages,
|
|
||||||
as: 'from_page',
|
|
||||||
required: Boolean(runtimeEnvironment || runtimeProjectSlug),
|
|
||||||
where: runtimeEnvironment ? { environment: runtimeEnvironment } : {},
|
|
||||||
include: buildProjectInclude(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
model: db.transitions,
|
|
||||||
as: 'transition',
|
|
||||||
required: false,
|
|
||||||
where: runtimeEnvironment ? { environment: runtimeEnvironment } : {},
|
|
||||||
include: buildProjectInclude(),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!page_links) {
|
|
||||||
return page_links;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = page_links.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.from_page = await page_links.getFrom_page({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.to_page = await page_links.getTo_page({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.transition = await page_links.getTransition({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
filter = filter || {};
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
let include = [
|
let include = [
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.tour_pages,
|
model: db.tour_pages,
|
||||||
as: 'from_page',
|
as: 'from_page',
|
||||||
|
|
||||||
where: filter.from_page ? {
|
where: filter.from_page ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.from_page.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.from_page.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -344,13 +125,10 @@ module.exports = class Page_linksDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.tour_pages,
|
model: db.tour_pages,
|
||||||
as: 'to_page',
|
as: 'to_page',
|
||||||
|
|
||||||
where: filter.to_page ? {
|
where: filter.to_page ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.to_page.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.to_page.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -361,13 +139,10 @@ module.exports = class Page_linksDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.transitions,
|
model: db.transitions,
|
||||||
as: 'transition',
|
as: 'transition',
|
||||||
|
|
||||||
where: filter.transition ? {
|
where: filter.transition ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.transition.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.transition.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -378,212 +153,90 @@ module.exports = class Page_linksDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
const runtimeEnvironment = getRuntimeEnvironment(options);
|
|
||||||
const runtimeProjectSlug = getRuntimeProjectSlug(options);
|
|
||||||
|
|
||||||
if (runtimeEnvironment) {
|
const runtimeEnvironment = getRuntimeEnvironment(options);
|
||||||
include[0].where = {
|
const runtimeProjectSlug = getRuntimeProjectSlug(options);
|
||||||
...(include[0].where || {}),
|
|
||||||
environment: runtimeEnvironment,
|
|
||||||
};
|
|
||||||
include[0].required = true;
|
|
||||||
include[1].where = {
|
|
||||||
...(include[1].where || {}),
|
|
||||||
environment: runtimeEnvironment,
|
|
||||||
};
|
|
||||||
include[2].where = {
|
|
||||||
...(include[2].where || {}),
|
|
||||||
environment: runtimeEnvironment,
|
|
||||||
};
|
|
||||||
include[2].required = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runtimeProjectSlug) {
|
if (runtimeEnvironment) {
|
||||||
include[0].include = [{
|
include[0].where = { ...(include[0].where || {}), environment: runtimeEnvironment };
|
||||||
model: db.projects,
|
include[0].required = true;
|
||||||
as: 'project',
|
include[1].where = { ...(include[1].where || {}), environment: runtimeEnvironment };
|
||||||
required: true,
|
include[2].where = { ...(include[2].where || {}), environment: runtimeEnvironment };
|
||||||
where: { slug: runtimeProjectSlug },
|
include[2].required = false;
|
||||||
}];
|
|
||||||
include[0].required = true;
|
|
||||||
include[1].include = [{
|
|
||||||
model: db.projects,
|
|
||||||
as: 'project',
|
|
||||||
required: true,
|
|
||||||
where: { slug: runtimeProjectSlug },
|
|
||||||
}];
|
|
||||||
include[2].include = [{
|
|
||||||
model: db.projects,
|
|
||||||
as: 'project',
|
|
||||||
required: true,
|
|
||||||
where: { slug: runtimeProjectSlug },
|
|
||||||
}];
|
|
||||||
include[2].required = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.external_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'page_links',
|
|
||||||
'external_url',
|
|
||||||
filter.external_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.trigger_selector) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'page_links',
|
|
||||||
'trigger_selector',
|
|
||||||
filter.trigger_selector,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.direction) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
direction: filter.direction,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.is_active) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_active: filter.is_active,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.page_links.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
if (runtimeProjectSlug) {
|
||||||
let where = {};
|
const projectInclude = [{
|
||||||
|
model: db.projects,
|
||||||
|
as: 'project',
|
||||||
|
required: true,
|
||||||
if (query) {
|
where: { slug: runtimeProjectSlug },
|
||||||
where = {
|
}];
|
||||||
[Op.or]: [
|
include[0].include = projectInclude;
|
||||||
{ ['id']: Utils.uuid(query) },
|
include[0].required = true;
|
||||||
Utils.ilike(
|
include[1].include = projectInclude;
|
||||||
'page_links',
|
include[2].include = projectInclude;
|
||||||
'direction',
|
include[2].required = false;
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.page_links.findAll({
|
|
||||||
attributes: [ 'id', 'direction' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['direction', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.direction,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filter.id) {
|
||||||
|
where.id = Utils.uuid(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.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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = Page_linksDBApi;
|
||||||
|
|||||||
@ -1,335 +1,53 @@
|
|||||||
|
const GenericDBApi = require('./base.api');
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const Utils = require('../utils');
|
|
||||||
|
|
||||||
|
class PermissionsDBApi extends GenericDBApi {
|
||||||
|
static get MODEL() {
|
||||||
|
return db.permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get TABLE_NAME() {
|
||||||
|
return 'permissions';
|
||||||
|
}
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
static get SEARCHABLE_FIELDS() {
|
||||||
const Op = Sequelize.Op;
|
return ['name'];
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = class PermissionsDBApi {
|
static get RANGE_FIELDS() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
static get ENUM_FIELDS() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
static get CSV_FIELDS() {
|
||||||
|
return ['id', 'name', 'createdAt'];
|
||||||
|
}
|
||||||
|
|
||||||
static async create(data, options) {
|
static get AUTOCOMPLETE_FIELD() {
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
return 'name';
|
||||||
const transaction = (options && options.transaction) || undefined;
|
}
|
||||||
|
|
||||||
const permissions = await db.permissions.create(
|
static get ASSOCIATIONS() {
|
||||||
{
|
return [];
|
||||||
id: data.id || undefined,
|
}
|
||||||
|
|
||||||
name: data.name
|
static get FIND_BY_INCLUDES() {
|
||||||
||
|
return [];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
static get FIND_ALL_INCLUDES() {
|
||||||
createdById: currentUser.id,
|
return [];
|
||||||
updatedById: currentUser.id,
|
}
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
static getFieldMapping(data) {
|
||||||
|
return {
|
||||||
|
id: data.id || undefined,
|
||||||
|
name: data.name || null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = PermissionsDBApi;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const permissionsData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
name: item.name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const permissions = await db.permissions.bulkCreate(permissionsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const permissions = await db.permissions.findByPk(id, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.name !== undefined) updatePayload.name = data.name;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await permissions.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const permissions = await db.permissions.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of permissions) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of permissions) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const permissions = await db.permissions.findByPk(id, options);
|
|
||||||
|
|
||||||
await permissions.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await permissions.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const permissions = await db.permissions.findOne({
|
|
||||||
where,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!permissions) {
|
|
||||||
return permissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = permissions.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
let include = [
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'permissions',
|
|
||||||
'name',
|
|
||||||
filter.name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.permissions.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
|
||||||
let where = {};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'permissions',
|
|
||||||
'name',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.permissions.findAll({
|
|
||||||
attributes: [ 'id', 'name' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['name', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.name,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|||||||
@ -1,323 +1,78 @@
|
|||||||
|
const GenericDBApi = require('./base.api');
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const Utils = require('../utils');
|
const Utils = require('../utils');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
const Sequelize = db.Sequelize;
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
module.exports = class Presigned_url_requestsDBApi {
|
class Presigned_url_requestsDBApi extends GenericDBApi {
|
||||||
|
static get MODEL() {
|
||||||
|
return db.presigned_url_requests;
|
||||||
|
}
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
static get TABLE_NAME() {
|
||||||
const transaction = (options && options.transaction) || undefined;
|
return 'presigned_url_requests';
|
||||||
|
}
|
||||||
const presigned_url_requests = await db.presigned_url_requests.create(
|
|
||||||
{
|
static get SEARCHABLE_FIELDS() {
|
||||||
id: data.id || undefined,
|
return ['requested_key', 'mime_type', 'status'];
|
||||||
|
}
|
||||||
purpose: data.purpose
|
|
||||||
||
|
static get RANGE_FIELDS() {
|
||||||
null
|
return ['requested_size_mb', 'expires_at'];
|
||||||
,
|
}
|
||||||
|
|
||||||
asset_type: data.asset_type
|
static get ENUM_FIELDS() {
|
||||||
||
|
return ['purpose', 'asset_type'];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
static get CSV_FIELDS() {
|
||||||
requested_key: data.requested_key
|
return ['id', 'purpose', 'asset_type', 'requested_key', 'mime_type', 'status', 'createdAt'];
|
||||||
||
|
}
|
||||||
null
|
|
||||||
,
|
static get AUTOCOMPLETE_FIELD() {
|
||||||
|
return 'requested_key';
|
||||||
mime_type: data.mime_type
|
}
|
||||||
||
|
|
||||||
null
|
static get ASSOCIATIONS() {
|
||||||
,
|
return [
|
||||||
|
{ field: 'project', setter: 'setProject', isArray: false },
|
||||||
requested_size_mb: data.requested_size_mb
|
{ field: 'user', setter: 'setUser', isArray: false },
|
||||||
||
|
];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
static get FIND_BY_INCLUDES() {
|
||||||
expires_at: data.expires_at
|
return [
|
||||||
||
|
{ association: 'project' },
|
||||||
null
|
{ association: 'user' },
|
||||||
,
|
];
|
||||||
|
}
|
||||||
status: data.status
|
|
||||||
||
|
static getFieldMapping(data) {
|
||||||
null
|
return {
|
||||||
,
|
id: data.id || undefined,
|
||||||
|
purpose: data.purpose || null,
|
||||||
importHash: data.importHash || null,
|
asset_type: data.asset_type || null,
|
||||||
createdById: currentUser.id,
|
requested_key: data.requested_key || null,
|
||||||
updatedById: currentUser.id,
|
mime_type: data.mime_type || null,
|
||||||
},
|
requested_size_mb: data.requested_size_mb || null,
|
||||||
{ transaction },
|
expires_at: data.expires_at || null,
|
||||||
);
|
status: data.status || null,
|
||||||
|
};
|
||||||
|
}
|
||||||
await presigned_url_requests.setProject( data.project || null, {
|
|
||||||
transaction,
|
static async findAll(filter = {}, options = {}) {
|
||||||
});
|
filter = filter || {};
|
||||||
|
const limit = filter.limit || 0;
|
||||||
await presigned_url_requests.setUser( data.user || null, {
|
const currentPage = +filter.page || 0;
|
||||||
transaction,
|
const offset = currentPage * limit;
|
||||||
});
|
|
||||||
|
let where = {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return presigned_url_requests;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const presigned_url_requestsData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
purpose: item.purpose
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
asset_type: item.asset_type
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
requested_key: item.requested_key
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
mime_type: item.mime_type
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
requested_size_mb: item.requested_size_mb
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
expires_at: item.expires_at
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
status: item.status
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const presigned_url_requests = await db.presigned_url_requests.bulkCreate(presigned_url_requestsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return presigned_url_requests;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const presigned_url_requests = await db.presigned_url_requests.findByPk(id, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.purpose !== undefined) updatePayload.purpose = data.purpose;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.asset_type !== undefined) updatePayload.asset_type = data.asset_type;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.requested_key !== undefined) updatePayload.requested_key = data.requested_key;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.mime_type !== undefined) updatePayload.mime_type = data.mime_type;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.requested_size_mb !== undefined) updatePayload.requested_size_mb = data.requested_size_mb;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.expires_at !== undefined) updatePayload.expires_at = data.expires_at;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.status !== undefined) updatePayload.status = data.status;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await presigned_url_requests.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.project !== undefined) {
|
|
||||||
await presigned_url_requests.setProject(
|
|
||||||
|
|
||||||
data.project,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.user !== undefined) {
|
|
||||||
await presigned_url_requests.setUser(
|
|
||||||
|
|
||||||
data.user,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return presigned_url_requests;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const presigned_url_requests = await db.presigned_url_requests.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of presigned_url_requests) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of presigned_url_requests) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return presigned_url_requests;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const presigned_url_requests = await db.presigned_url_requests.findByPk(id, options);
|
|
||||||
|
|
||||||
await presigned_url_requests.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await presigned_url_requests.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return presigned_url_requests;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const presigned_url_requests = await db.presigned_url_requests.findOne({
|
|
||||||
where,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!presigned_url_requests) {
|
|
||||||
return presigned_url_requests;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = presigned_url_requests.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.project = await presigned_url_requests.getProject({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.user = await presigned_url_requests.getUser({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
let include = [
|
let include = [
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.projects,
|
model: db.projects,
|
||||||
as: 'project',
|
as: 'project',
|
||||||
|
|
||||||
where: filter.project ? {
|
where: filter.project ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -328,13 +83,10 @@ module.exports = class Presigned_url_requestsDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.users,
|
model: db.users,
|
||||||
as: 'user',
|
as: 'user',
|
||||||
|
|
||||||
where: filter.user ? {
|
where: filter.user ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.user.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.user.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -345,227 +97,78 @@ module.exports = class Presigned_url_requestsDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if (filter) {
|
if (filter.id) {
|
||||||
if (filter.id) {
|
where.id = Utils.uuid(filter.id);
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.requested_key) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'presigned_url_requests',
|
|
||||||
'requested_key',
|
|
||||||
filter.requested_key,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.mime_type) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'presigned_url_requests',
|
|
||||||
'mime_type',
|
|
||||||
filter.mime_type,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.status) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'presigned_url_requests',
|
|
||||||
'status',
|
|
||||||
filter.status,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.requested_size_mbRange) {
|
|
||||||
const [start, end] = filter.requested_size_mbRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
requested_size_mb: {
|
|
||||||
...where.requested_size_mb,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
requested_size_mb: {
|
|
||||||
...where.requested_size_mb,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.expires_atRange) {
|
|
||||||
const [start, end] = filter.expires_atRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
expires_at: {
|
|
||||||
...where.expires_at,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
expires_at: {
|
|
||||||
...where.expires_at,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.purpose) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
purpose: filter.purpose,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.asset_type) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
asset_type: filter.asset_type,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.presigned_url_requests.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
for (const field of this.SEARCHABLE_FIELDS) {
|
||||||
let where = {};
|
if (filter[field]) {
|
||||||
|
where[Op.and] = Utils.ilike(this.TABLE_NAME, field, filter[field]);
|
||||||
|
}
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'presigned_url_requests',
|
|
||||||
'requested_key',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.presigned_url_requests.findAll({
|
|
||||||
attributes: [ 'id', 'requested_key' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['requested_key', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.requested_key,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = Presigned_url_requestsDBApi;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
|
const GenericDBApi = require('./base.api');
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const Utils = require('../utils');
|
const Utils = require('../utils');
|
||||||
const {
|
const {
|
||||||
@ -6,342 +6,89 @@ const {
|
|||||||
applyRuntimeProjectFilter,
|
applyRuntimeProjectFilter,
|
||||||
} = require('./runtime-context');
|
} = require('./runtime-context');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
const Sequelize = db.Sequelize;
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
module.exports = class Project_audio_tracksDBApi {
|
class Project_audio_tracksDBApi extends GenericDBApi {
|
||||||
|
static get MODEL() {
|
||||||
|
return db.project_audio_tracks;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get TABLE_NAME() {
|
||||||
|
return 'project_audio_tracks';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get SEARCHABLE_FIELDS() {
|
||||||
|
return ['source_key', 'name', 'slug', 'url'];
|
||||||
|
}
|
||||||
|
|
||||||
static async create(data, options) {
|
static get RANGE_FIELDS() {
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
return ['volume', 'sort_order'];
|
||||||
const transaction = (options && options.transaction) || undefined;
|
}
|
||||||
|
|
||||||
const project_audio_tracks = await db.project_audio_tracks.create(
|
static get ENUM_FIELDS() {
|
||||||
{
|
return ['environment', 'loop', 'is_enabled'];
|
||||||
id: data.id || undefined,
|
}
|
||||||
|
|
||||||
environment: data.environment
|
static get CSV_FIELDS() {
|
||||||
||
|
return ['id', 'environment', 'source_key', 'name', 'slug', 'url', 'loop', 'volume', 'createdAt'];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
|
||||||
source_key: data.source_key
|
static get AUTOCOMPLETE_FIELD() {
|
||||||
||
|
return 'name';
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
|
||||||
name: data.name
|
static get ASSOCIATIONS() {
|
||||||
||
|
return [
|
||||||
null
|
{ field: 'project', setter: 'setProject', isArray: false },
|
||||||
,
|
];
|
||||||
|
}
|
||||||
|
|
||||||
slug: data.slug
|
static getFieldMapping(data) {
|
||||||
||
|
return {
|
||||||
null
|
id: data.id || undefined,
|
||||||
,
|
environment: data.environment || null,
|
||||||
|
source_key: data.source_key || null,
|
||||||
|
name: data.name || null,
|
||||||
|
slug: data.slug || null,
|
||||||
|
url: data.url || null,
|
||||||
|
loop: data.loop || false,
|
||||||
|
volume: data.volume || null,
|
||||||
|
sort_order: data.sort_order || null,
|
||||||
|
is_enabled: data.is_enabled || false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
url: data.url
|
static async findBy(where, options = {}) {
|
||||||
||
|
const transaction = options.transaction;
|
||||||
null
|
const queryWhere = applyRuntimeEnvironment({ ...where }, options);
|
||||||
,
|
const projectInclude = applyRuntimeProjectFilter(
|
||||||
|
{ model: db.projects, as: 'project' },
|
||||||
loop: data.loop
|
options
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
volume: data.volume
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
sort_order: data.sort_order
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_enabled: data.is_enabled
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const record = await this.MODEL.findOne({
|
||||||
await project_audio_tracks.setProject( data.project || null, {
|
where: queryWhere,
|
||||||
transaction,
|
transaction,
|
||||||
});
|
include: [projectInclude],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!record) return null;
|
||||||
|
return record.get({ plain: true });
|
||||||
|
}
|
||||||
|
|
||||||
return project_audio_tracks;
|
static async findAll(filter = {}, options = {}) {
|
||||||
}
|
filter = filter || {};
|
||||||
|
const limit = filter.limit || 0;
|
||||||
|
const currentPage = +filter.page || 0;
|
||||||
static async bulkImport(data, options) {
|
const offset = currentPage * limit;
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
let where = {};
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const project_audio_tracksData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
environment: item.environment
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
source_key: item.source_key
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
name: item.name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
slug: item.slug
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
url: item.url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
loop: item.loop
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
volume: item.volume
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
sort_order: item.sort_order
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_enabled: item.is_enabled
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const project_audio_tracks = await db.project_audio_tracks.bulkCreate(project_audio_tracksData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return project_audio_tracks;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const project_audio_tracks = await db.project_audio_tracks.findByPk(id, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.environment !== undefined) updatePayload.environment = data.environment;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.source_key !== undefined) updatePayload.source_key = data.source_key;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.name !== undefined) updatePayload.name = data.name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.slug !== undefined) updatePayload.slug = data.slug;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.url !== undefined) updatePayload.url = data.url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.loop !== undefined) updatePayload.loop = data.loop;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.volume !== undefined) updatePayload.volume = data.volume;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.sort_order !== undefined) updatePayload.sort_order = data.sort_order;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_enabled !== undefined) updatePayload.is_enabled = data.is_enabled;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await project_audio_tracks.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.project !== undefined) {
|
|
||||||
await project_audio_tracks.setProject(
|
|
||||||
|
|
||||||
data.project,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return project_audio_tracks;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const project_audio_tracks = await db.project_audio_tracks.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of project_audio_tracks) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of project_audio_tracks) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return project_audio_tracks;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const project_audio_tracks = await db.project_audio_tracks.findByPk(id, options);
|
|
||||||
|
|
||||||
await project_audio_tracks.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await project_audio_tracks.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return project_audio_tracks;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
const queryWhere = applyRuntimeEnvironment({ ...where }, options);
|
|
||||||
const projectInclude = applyRuntimeProjectFilter(
|
|
||||||
{
|
|
||||||
model: db.projects,
|
|
||||||
as: 'project',
|
|
||||||
},
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
const project_audio_tracks = await db.project_audio_tracks.findOne(
|
|
||||||
{ where: queryWhere, include: [projectInclude], transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!project_audio_tracks) {
|
|
||||||
return project_audio_tracks;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = project_audio_tracks.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.project = await project_audio_tracks.getProject({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
filter = filter || {};
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
let include = [
|
let include = [
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.projects,
|
model: db.projects,
|
||||||
as: 'project',
|
as: 'project',
|
||||||
|
|
||||||
where: filter.project ? {
|
where: filter.project ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -352,245 +99,82 @@ module.exports = class Project_audio_tracksDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
include[0] = applyRuntimeProjectFilter(include[0], options);
|
|
||||||
|
|
||||||
if (filter) {
|
include[0] = applyRuntimeProjectFilter(include[0], options);
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (filter.id) {
|
||||||
if (filter.source_key) {
|
where.id = Utils.uuid(filter.id);
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'project_audio_tracks',
|
|
||||||
'source_key',
|
|
||||||
filter.source_key,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'project_audio_tracks',
|
|
||||||
'name',
|
|
||||||
filter.name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.slug) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'project_audio_tracks',
|
|
||||||
'slug',
|
|
||||||
filter.slug,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'project_audio_tracks',
|
|
||||||
'url',
|
|
||||||
filter.url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.volumeRange) {
|
|
||||||
const [start, end] = filter.volumeRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
volume: {
|
|
||||||
...where.volume,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
volume: {
|
|
||||||
...where.volume,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.sort_orderRange) {
|
|
||||||
const [start, end] = filter.sort_orderRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.environment) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
environment: filter.environment,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.loop) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
loop: filter.loop,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.is_enabled) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_enabled: filter.is_enabled,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...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,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.project_audio_tracks.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
for (const field of this.SEARCHABLE_FIELDS) {
|
||||||
let where = {};
|
if (filter[field]) {
|
||||||
|
where[Op.and] = Utils.ilike(this.TABLE_NAME, field, filter[field]);
|
||||||
|
}
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'project_audio_tracks',
|
|
||||||
'name',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.project_audio_tracks.findAll({
|
|
||||||
attributes: [ 'id', 'name' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['name', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.name,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_audio_tracksDBApi;
|
||||||
|
|||||||
@ -1,286 +1,75 @@
|
|||||||
|
const GenericDBApi = require('./base.api');
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const Utils = require('../utils');
|
const Utils = require('../utils');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
const Sequelize = db.Sequelize;
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
module.exports = class Project_membershipsDBApi {
|
class Project_membershipsDBApi extends GenericDBApi {
|
||||||
|
static get MODEL() {
|
||||||
|
return db.project_memberships;
|
||||||
|
}
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
static get TABLE_NAME() {
|
||||||
const transaction = (options && options.transaction) || undefined;
|
return 'project_memberships';
|
||||||
|
}
|
||||||
const project_memberships = await db.project_memberships.create(
|
|
||||||
{
|
static get SEARCHABLE_FIELDS() {
|
||||||
id: data.id || undefined,
|
return [];
|
||||||
|
}
|
||||||
access_level: data.access_level
|
|
||||||
||
|
static get RANGE_FIELDS() {
|
||||||
null
|
return ['invited_at', 'accepted_at'];
|
||||||
,
|
}
|
||||||
|
|
||||||
is_active: data.is_active
|
static get ENUM_FIELDS() {
|
||||||
||
|
return ['access_level', 'is_active'];
|
||||||
false
|
}
|
||||||
|
|
||||||
,
|
static get CSV_FIELDS() {
|
||||||
|
return ['id', 'access_level', 'is_active', 'invited_at', 'accepted_at', 'createdAt'];
|
||||||
invited_at: data.invited_at
|
}
|
||||||
||
|
|
||||||
null
|
static get AUTOCOMPLETE_FIELD() {
|
||||||
,
|
return 'access_level';
|
||||||
|
}
|
||||||
accepted_at: data.accepted_at
|
|
||||||
||
|
static get ASSOCIATIONS() {
|
||||||
null
|
return [
|
||||||
,
|
{ field: 'project', setter: 'setProject', isArray: false },
|
||||||
|
{ field: 'user', setter: 'setUser', isArray: false },
|
||||||
importHash: data.importHash || null,
|
];
|
||||||
createdById: currentUser.id,
|
}
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
static get FIND_BY_INCLUDES() {
|
||||||
{ transaction },
|
return [
|
||||||
);
|
{ association: 'project' },
|
||||||
|
{ association: 'user' },
|
||||||
|
];
|
||||||
await project_memberships.setProject( data.project || null, {
|
}
|
||||||
transaction,
|
|
||||||
});
|
static getFieldMapping(data) {
|
||||||
|
return {
|
||||||
await project_memberships.setUser( data.user || null, {
|
id: data.id || undefined,
|
||||||
transaction,
|
access_level: data.access_level || null,
|
||||||
});
|
is_active: data.is_active || false,
|
||||||
|
invited_at: data.invited_at || null,
|
||||||
|
accepted_at: data.accepted_at || null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static async findAll(filter = {}, options = {}) {
|
||||||
return project_memberships;
|
filter = filter || {};
|
||||||
}
|
const limit = filter.limit || 0;
|
||||||
|
const currentPage = +filter.page || 0;
|
||||||
|
const offset = currentPage * limit;
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
let where = {};
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const project_membershipsData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
access_level: item.access_level
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_active: item.is_active
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
invited_at: item.invited_at
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
accepted_at: item.accepted_at
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const project_memberships = await db.project_memberships.bulkCreate(project_membershipsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return project_memberships;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const project_memberships = await db.project_memberships.findByPk(id, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.access_level !== undefined) updatePayload.access_level = data.access_level;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_active !== undefined) updatePayload.is_active = data.is_active;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.invited_at !== undefined) updatePayload.invited_at = data.invited_at;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.accepted_at !== undefined) updatePayload.accepted_at = data.accepted_at;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await project_memberships.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.project !== undefined) {
|
|
||||||
await project_memberships.setProject(
|
|
||||||
|
|
||||||
data.project,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.user !== undefined) {
|
|
||||||
await project_memberships.setUser(
|
|
||||||
|
|
||||||
data.user,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return project_memberships;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const project_memberships = await db.project_memberships.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of project_memberships) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of project_memberships) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return project_memberships;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const project_memberships = await db.project_memberships.findByPk(id, options);
|
|
||||||
|
|
||||||
await project_memberships.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await project_memberships.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return project_memberships;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const project_memberships = await db.project_memberships.findOne({
|
|
||||||
where,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!project_memberships) {
|
|
||||||
return project_memberships;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = project_memberships.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.project = await project_memberships.getProject({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.user = await project_memberships.getUser({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
let include = [
|
let include = [
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.projects,
|
model: db.projects,
|
||||||
as: 'project',
|
as: 'project',
|
||||||
|
|
||||||
where: filter.project ? {
|
where: filter.project ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -291,13 +80,10 @@ module.exports = class Project_membershipsDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.users,
|
model: db.users,
|
||||||
as: 'user',
|
as: 'user',
|
||||||
|
|
||||||
where: filter.user ? {
|
where: filter.user ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.user.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.user.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -308,194 +94,72 @@ module.exports = class Project_membershipsDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if (filter) {
|
if (filter.id) {
|
||||||
if (filter.id) {
|
where.id = Utils.uuid(filter.id);
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.invited_atRange) {
|
|
||||||
const [start, end] = filter.invited_atRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
invited_at: {
|
|
||||||
...where.invited_at,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
invited_at: {
|
|
||||||
...where.invited_at,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.accepted_atRange) {
|
|
||||||
const [start, end] = filter.accepted_atRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
accepted_at: {
|
|
||||||
...where.accepted_at,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
accepted_at: {
|
|
||||||
...where.accepted_at,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.access_level) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
access_level: filter.access_level,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.is_active) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_active: filter.is_active,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.project_memberships.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
for (const field of this.RANGE_FIELDS) {
|
||||||
let where = {};
|
const rangeKey = `${field}Range`;
|
||||||
|
if (filter[rangeKey]) {
|
||||||
|
const [start, end] = filter[rangeKey];
|
||||||
|
if (start !== undefined && start !== null && start !== '') {
|
||||||
if (query) {
|
where[field] = { ...where[field], [Op.gte]: start };
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'project_memberships',
|
|
||||||
'access_level',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
if (end !== undefined && end !== null && end !== '') {
|
||||||
const records = await db.project_memberships.findAll({
|
where[field] = { ...where[field], [Op.lte]: end };
|
||||||
attributes: [ 'id', 'access_level' ],
|
}
|
||||||
where,
|
}
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['access_level', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.access_level,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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_membershipsDBApi;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
|
const GenericDBApi = require('./base.api');
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const Utils = require('../utils');
|
const Utils = require('../utils');
|
||||||
const {
|
const {
|
||||||
@ -6,694 +6,186 @@ const {
|
|||||||
getRuntimeProjectSlug,
|
getRuntimeProjectSlug,
|
||||||
} = require('./runtime-context');
|
} = require('./runtime-context');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
const Sequelize = db.Sequelize;
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
module.exports = class ProjectsDBApi {
|
class ProjectsDBApi extends GenericDBApi {
|
||||||
|
static get MODEL() {
|
||||||
|
return db.projects;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get TABLE_NAME() {
|
||||||
|
return 'projects';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get SEARCHABLE_FIELDS() {
|
||||||
|
return ['name', 'slug', 'description', 'logo_url', 'favicon_url', 'og_image_url', 'theme_config_json', 'custom_css_json', 'cdn_base_url', 'entry_page_slug'];
|
||||||
|
}
|
||||||
|
|
||||||
static async create(data, options) {
|
static get RANGE_FIELDS() {
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
return ['deleted_at_time'];
|
||||||
const transaction = (options && options.transaction) || undefined;
|
}
|
||||||
|
|
||||||
const projects = await db.projects.create(
|
static get ENUM_FIELDS() {
|
||||||
{
|
return ['phase', 'is_deleted'];
|
||||||
id: data.id || undefined,
|
}
|
||||||
|
|
||||||
name: data.name
|
static get CSV_FIELDS() {
|
||||||
||
|
return ['id', 'name', 'slug', 'description', 'phase', 'logo_url', 'cdn_base_url', 'createdAt'];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
|
||||||
slug: data.slug
|
static get AUTOCOMPLETE_FIELD() {
|
||||||
||
|
return 'name';
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
|
||||||
description: data.description
|
static get ASSOCIATIONS() {
|
||||||
||
|
return [];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
|
||||||
phase: data.phase
|
static getFieldMapping(data) {
|
||||||
||
|
return {
|
||||||
null
|
id: data.id || undefined,
|
||||||
,
|
name: data.name || null,
|
||||||
|
slug: data.slug || null,
|
||||||
|
description: data.description || null,
|
||||||
|
phase: data.phase || null,
|
||||||
|
logo_url: data.logo_url || null,
|
||||||
|
favicon_url: data.favicon_url || null,
|
||||||
|
og_image_url: data.og_image_url || null,
|
||||||
|
theme_config_json: data.theme_config_json || null,
|
||||||
|
custom_css_json: data.custom_css_json || null,
|
||||||
|
cdn_base_url: data.cdn_base_url || null,
|
||||||
|
entry_page_slug: data.entry_page_slug || null,
|
||||||
|
is_deleted: data.is_deleted || false,
|
||||||
|
deleted_at_time: data.deleted_at_time || null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
logo_url: data.logo_url
|
static async findBy(where, options = {}) {
|
||||||
||
|
const transaction = options.transaction;
|
||||||
null
|
const runtimeEnvironment = getRuntimeEnvironment(options);
|
||||||
,
|
const runtimeProjectSlug = getRuntimeProjectSlug(options);
|
||||||
|
const queryWhere = { ...where };
|
||||||
|
|
||||||
favicon_url: data.favicon_url
|
if (runtimeEnvironment) {
|
||||||
||
|
queryWhere.phase = runtimeEnvironment === 'production'
|
||||||
null
|
? 'production'
|
||||||
,
|
: { [Op.in]: ['stage', 'production'] };
|
||||||
|
|
||||||
og_image_url: data.og_image_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
theme_config_json: data.theme_config_json
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
custom_css_json: data.custom_css_json
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
cdn_base_url: data.cdn_base_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
entry_page_slug: data.entry_page_slug
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_deleted: data.is_deleted
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
deleted_at_time: data.deleted_at_time
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return projects;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (runtimeProjectSlug) {
|
||||||
static async bulkImport(data, options) {
|
queryWhere.slug = runtimeProjectSlug;
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const projectsData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
name: item.name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
slug: item.slug
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
description: item.description
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
phase: item.phase
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
logo_url: item.logo_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
favicon_url: item.favicon_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
og_image_url: item.og_image_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
theme_config_json: item.theme_config_json
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
custom_css_json: item.custom_css_json
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
cdn_base_url: item.cdn_base_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
entry_page_slug: item.entry_page_slug
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_deleted: item.is_deleted
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
deleted_at_time: item.deleted_at_time
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const projects = await db.projects.bulkCreate(projectsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return projects;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async update(id, data, options) {
|
const record = await this.MODEL.findOne({
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
where: queryWhere,
|
||||||
const transaction = (options && options.transaction) || undefined;
|
transaction,
|
||||||
|
include: [
|
||||||
|
{ association: 'project_memberships_project' },
|
||||||
|
{ association: 'assets_project' },
|
||||||
|
{ association: 'presigned_url_requests_project' },
|
||||||
|
{ association: 'tour_pages_project' },
|
||||||
|
{ association: 'transitions_project' },
|
||||||
|
{ association: 'project_audio_tracks_project' },
|
||||||
|
{ association: 'publish_events_project' },
|
||||||
|
{ association: 'pwa_caches_project' },
|
||||||
|
{ association: 'access_logs_project' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!record) return null;
|
||||||
|
return record.get({ plain: true });
|
||||||
|
}
|
||||||
|
|
||||||
const projects = await db.projects.findByPk(id, {transaction});
|
static async findAll(filter = {}, options = {}) {
|
||||||
|
filter = filter || {};
|
||||||
|
const limit = filter.limit || 0;
|
||||||
|
const currentPage = +filter.page || 0;
|
||||||
|
const offset = currentPage * limit;
|
||||||
|
|
||||||
|
let where = {};
|
||||||
|
let include = [];
|
||||||
|
|
||||||
|
if (filter.id) {
|
||||||
|
where.id = Utils.uuid(filter.id);
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.name !== undefined) updatePayload.name = data.name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.slug !== undefined) updatePayload.slug = data.slug;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.description !== undefined) updatePayload.description = data.description;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.phase !== undefined) updatePayload.phase = data.phase;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.logo_url !== undefined) updatePayload.logo_url = data.logo_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.favicon_url !== undefined) updatePayload.favicon_url = data.favicon_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.og_image_url !== undefined) updatePayload.og_image_url = data.og_image_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.theme_config_json !== undefined) updatePayload.theme_config_json = data.theme_config_json;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.custom_css_json !== undefined) updatePayload.custom_css_json = data.custom_css_json;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.cdn_base_url !== undefined) updatePayload.cdn_base_url = data.cdn_base_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.entry_page_slug !== undefined) updatePayload.entry_page_slug = data.entry_page_slug;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_deleted !== undefined) updatePayload.is_deleted = data.is_deleted;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.deleted_at_time !== undefined) updatePayload.deleted_at_time = data.deleted_at_time;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await projects.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return projects;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
for (const field of this.SEARCHABLE_FIELDS) {
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
if (filter[field]) {
|
||||||
const transaction = (options && options.transaction) || undefined;
|
where[Op.and] = Utils.ilike(this.TABLE_NAME, field, filter[field]);
|
||||||
|
}
|
||||||
const projects = await db.projects.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of projects) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of projects) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return projects;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async remove(id, options) {
|
for (const field of this.RANGE_FIELDS) {
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
const rangeKey = `${field}Range`;
|
||||||
const transaction = (options && options.transaction) || undefined;
|
if (filter[rangeKey]) {
|
||||||
|
const [start, end] = filter[rangeKey];
|
||||||
const projects = await db.projects.findByPk(id, options);
|
if (start !== undefined && start !== null && start !== '') {
|
||||||
|
where[field] = { ...where[field], [Op.gte]: start };
|
||||||
await projects.update({
|
}
|
||||||
deletedBy: currentUser.id
|
if (end !== undefined && end !== null && end !== '') {
|
||||||
}, {
|
where[field] = { ...where[field], [Op.lte]: end };
|
||||||
transaction,
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
await projects.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return projects;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findBy(where, options) {
|
for (const field of this.ENUM_FIELDS) {
|
||||||
const transaction = (options && options.transaction) || undefined;
|
if (filter[field] !== undefined) {
|
||||||
const runtimeEnvironment = getRuntimeEnvironment(options);
|
where[field] = filter[field];
|
||||||
const runtimeProjectSlug = getRuntimeProjectSlug(options);
|
}
|
||||||
const queryWhere = { ...where };
|
|
||||||
|
|
||||||
if (runtimeEnvironment) {
|
|
||||||
queryWhere.phase = runtimeEnvironment === 'production'
|
|
||||||
? 'production'
|
|
||||||
: { [Op.in]: ['stage', 'production'] };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runtimeProjectSlug) {
|
|
||||||
queryWhere.slug = runtimeProjectSlug;
|
|
||||||
}
|
|
||||||
|
|
||||||
const projects = await db.projects.findOne(
|
|
||||||
{ where: queryWhere, transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!projects) {
|
|
||||||
return projects;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = projects.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.project_memberships_project = await projects.getProject_memberships_project({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.assets_project = await projects.getAssets_project({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.presigned_url_requests_project = await projects.getPresigned_url_requests_project({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.tour_pages_project = await projects.getTour_pages_project({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.transitions_project = await projects.getTransitions_project({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.project_audio_tracks_project = await projects.getProject_audio_tracks_project({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.publish_events_project = await projects.getPublish_events_project({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.pwa_caches_project = await projects.getPwa_caches_project({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.access_logs_project = await projects.getAccess_logs_project({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findAll(
|
if (filter.active !== undefined) {
|
||||||
filter,
|
where.active = filter.active === true || filter.active === 'true';
|
||||||
options
|
|
||||||
) {
|
|
||||||
filter = filter || {};
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
let include = [
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
if (filter) {
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'projects',
|
|
||||||
'name',
|
|
||||||
filter.name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.slug) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'projects',
|
|
||||||
'slug',
|
|
||||||
filter.slug,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.description) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'projects',
|
|
||||||
'description',
|
|
||||||
filter.description,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.logo_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'projects',
|
|
||||||
'logo_url',
|
|
||||||
filter.logo_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.favicon_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'projects',
|
|
||||||
'favicon_url',
|
|
||||||
filter.favicon_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.og_image_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'projects',
|
|
||||||
'og_image_url',
|
|
||||||
filter.og_image_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.theme_config_json) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'projects',
|
|
||||||
'theme_config_json',
|
|
||||||
filter.theme_config_json,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.custom_css_json) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'projects',
|
|
||||||
'custom_css_json',
|
|
||||||
filter.custom_css_json,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.cdn_base_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'projects',
|
|
||||||
'cdn_base_url',
|
|
||||||
filter.cdn_base_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.entry_page_slug) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'projects',
|
|
||||||
'entry_page_slug',
|
|
||||||
filter.entry_page_slug,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.deleted_at_timeRange) {
|
|
||||||
const [start, end] = filter.deleted_at_timeRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
deleted_at_time: {
|
|
||||||
...where.deleted_at_time,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
deleted_at_time: {
|
|
||||||
...where.deleted_at_time,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.phase) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
phase: filter.phase,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.is_deleted) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_deleted: filter.is_deleted,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const runtimeEnvironment = getRuntimeEnvironment(options);
|
|
||||||
const runtimeProjectSlug = getRuntimeProjectSlug(options);
|
|
||||||
|
|
||||||
if (runtimeEnvironment) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
phase: runtimeEnvironment,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runtimeProjectSlug) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
slug: runtimeProjectSlug,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.projects.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
if (filter.createdAtRange) {
|
||||||
let where = {};
|
const [start, end] = filter.createdAtRange;
|
||||||
|
if (start !== undefined && start !== null && start !== '') {
|
||||||
|
where.createdAt = { ...where.createdAt, [Op.gte]: start };
|
||||||
|
}
|
||||||
if (query) {
|
if (end !== undefined && end !== null && end !== '') {
|
||||||
where = {
|
where.createdAt = { ...where.createdAt, [Op.lte]: end };
|
||||||
[Op.or]: [
|
}
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'projects',
|
|
||||||
'name',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.projects.findAll({
|
|
||||||
attributes: [ 'id', 'name' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['name', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.name,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const runtimeEnvironment = getRuntimeEnvironment(options);
|
||||||
|
const runtimeProjectSlug = getRuntimeProjectSlug(options);
|
||||||
|
|
||||||
};
|
if (runtimeEnvironment) {
|
||||||
|
where.phase = runtimeEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runtimeProjectSlug) {
|
||||||
|
where.slug = runtimeProjectSlug;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = ProjectsDBApi;
|
||||||
|
|||||||
@ -1,375 +1,82 @@
|
|||||||
|
const GenericDBApi = require('./base.api');
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const Utils = require('../utils');
|
const Utils = require('../utils');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
const Sequelize = db.Sequelize;
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
module.exports = class Publish_eventsDBApi {
|
class Publish_eventsDBApi extends GenericDBApi {
|
||||||
|
static get MODEL() {
|
||||||
|
return db.publish_events;
|
||||||
|
}
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
static get TABLE_NAME() {
|
||||||
const transaction = (options && options.transaction) || undefined;
|
return 'publish_events';
|
||||||
|
}
|
||||||
const publish_events = await db.publish_events.create(
|
|
||||||
{
|
static get SEARCHABLE_FIELDS() {
|
||||||
id: data.id || undefined,
|
return ['title', 'description', 'error_message'];
|
||||||
|
}
|
||||||
title: data.title
|
|
||||||
||
|
static get RANGE_FIELDS() {
|
||||||
null
|
return ['started_at', 'finished_at', 'pages_copied', 'transitions_copied', 'audios_copied'];
|
||||||
,
|
}
|
||||||
|
|
||||||
description: data.description
|
static get ENUM_FIELDS() {
|
||||||
||
|
return ['from_environment', 'to_environment', 'status'];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
static get CSV_FIELDS() {
|
||||||
from_environment: data.from_environment
|
return ['id', 'title', 'description', 'from_environment', 'to_environment', 'status', 'pages_copied', 'createdAt'];
|
||||||
||
|
}
|
||||||
null
|
|
||||||
,
|
static get AUTOCOMPLETE_FIELD() {
|
||||||
|
return 'status';
|
||||||
to_environment: data.to_environment
|
}
|
||||||
||
|
|
||||||
null
|
static get ASSOCIATIONS() {
|
||||||
,
|
return [
|
||||||
|
{ field: 'project', setter: 'setProject', isArray: false },
|
||||||
started_at: data.started_at
|
{ field: 'user', setter: 'setUser', isArray: false },
|
||||||
||
|
];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
static get FIND_BY_INCLUDES() {
|
||||||
finished_at: data.finished_at
|
return [
|
||||||
||
|
{ association: 'project' },
|
||||||
null
|
{ association: 'user' },
|
||||||
,
|
];
|
||||||
|
}
|
||||||
status: data.status
|
|
||||||
||
|
static getFieldMapping(data) {
|
||||||
null
|
return {
|
||||||
,
|
id: data.id || undefined,
|
||||||
|
title: data.title || null,
|
||||||
error_message: data.error_message
|
description: data.description || null,
|
||||||
||
|
from_environment: data.from_environment || null,
|
||||||
null
|
to_environment: data.to_environment || null,
|
||||||
,
|
started_at: data.started_at || null,
|
||||||
|
finished_at: data.finished_at || null,
|
||||||
pages_copied: data.pages_copied
|
status: data.status || null,
|
||||||
||
|
error_message: data.error_message || null,
|
||||||
null
|
pages_copied: data.pages_copied || null,
|
||||||
,
|
transitions_copied: data.transitions_copied || null,
|
||||||
|
audios_copied: data.audios_copied || null,
|
||||||
transitions_copied: data.transitions_copied
|
};
|
||||||
||
|
}
|
||||||
null
|
|
||||||
,
|
static async findAll(filter = {}, options = {}) {
|
||||||
|
filter = filter || {};
|
||||||
audios_copied: data.audios_copied
|
const limit = filter.limit || 0;
|
||||||
||
|
const currentPage = +filter.page || 0;
|
||||||
null
|
const offset = currentPage * limit;
|
||||||
,
|
|
||||||
|
let where = {};
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
await publish_events.setProject( data.project || null, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await publish_events.setUser( data.user || null, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return publish_events;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const publish_eventsData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
title: item.title
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
description: item.description
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
from_environment: item.from_environment
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
to_environment: item.to_environment
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
started_at: item.started_at
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
finished_at: item.finished_at
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
status: item.status
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
error_message: item.error_message
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
pages_copied: item.pages_copied
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
transitions_copied: item.transitions_copied
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
audios_copied: item.audios_copied
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const publish_events = await db.publish_events.bulkCreate(publish_eventsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return publish_events;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const publish_events = await db.publish_events.findByPk(id, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.title !== undefined) updatePayload.title = data.title;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.description !== undefined) updatePayload.description = data.description;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.from_environment !== undefined) updatePayload.from_environment = data.from_environment;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.to_environment !== undefined) updatePayload.to_environment = data.to_environment;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.started_at !== undefined) updatePayload.started_at = data.started_at;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.finished_at !== undefined) updatePayload.finished_at = data.finished_at;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.status !== undefined) updatePayload.status = data.status;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.error_message !== undefined) updatePayload.error_message = data.error_message;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.pages_copied !== undefined) updatePayload.pages_copied = data.pages_copied;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.transitions_copied !== undefined) updatePayload.transitions_copied = data.transitions_copied;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.audios_copied !== undefined) updatePayload.audios_copied = data.audios_copied;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await publish_events.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.project !== undefined) {
|
|
||||||
await publish_events.setProject(
|
|
||||||
|
|
||||||
data.project,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.user !== undefined) {
|
|
||||||
await publish_events.setUser(
|
|
||||||
|
|
||||||
data.user,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return publish_events;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const publish_events = await db.publish_events.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of publish_events) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of publish_events) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return publish_events;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const publish_events = await db.publish_events.findByPk(id, options);
|
|
||||||
|
|
||||||
await publish_events.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await publish_events.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return publish_events;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const publish_events = await db.publish_events.findOne({
|
|
||||||
where,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!publish_events) {
|
|
||||||
return publish_events;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = publish_events.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.project = await publish_events.getProject({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.user = await publish_events.getUser({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
let include = [
|
let include = [
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.projects,
|
model: db.projects,
|
||||||
as: 'project',
|
as: 'project',
|
||||||
|
|
||||||
where: filter.project ? {
|
where: filter.project ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -380,13 +87,10 @@ module.exports = class Publish_eventsDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.users,
|
model: db.users,
|
||||||
as: 'user',
|
as: 'user',
|
||||||
|
|
||||||
where: filter.user ? {
|
where: filter.user ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.user.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.user.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -397,307 +101,78 @@ module.exports = class Publish_eventsDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if (filter) {
|
if (filter.id) {
|
||||||
if (filter.id) {
|
where.id = Utils.uuid(filter.id);
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.title) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'publish_events',
|
|
||||||
'title',
|
|
||||||
filter.title,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.description) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'publish_events',
|
|
||||||
'description',
|
|
||||||
filter.description,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.error_message) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'publish_events',
|
|
||||||
'error_message',
|
|
||||||
filter.error_message,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.started_atRange) {
|
|
||||||
const [start, end] = filter.started_atRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
started_at: {
|
|
||||||
...where.started_at,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
started_at: {
|
|
||||||
...where.started_at,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.finished_atRange) {
|
|
||||||
const [start, end] = filter.finished_atRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
finished_at: {
|
|
||||||
...where.finished_at,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
finished_at: {
|
|
||||||
...where.finished_at,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.pages_copiedRange) {
|
|
||||||
const [start, end] = filter.pages_copiedRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
pages_copied: {
|
|
||||||
...where.pages_copied,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
pages_copied: {
|
|
||||||
...where.pages_copied,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.transitions_copiedRange) {
|
|
||||||
const [start, end] = filter.transitions_copiedRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
transitions_copied: {
|
|
||||||
...where.transitions_copied,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
transitions_copied: {
|
|
||||||
...where.transitions_copied,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.audios_copiedRange) {
|
|
||||||
const [start, end] = filter.audios_copiedRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
audios_copied: {
|
|
||||||
...where.audios_copied,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
audios_copied: {
|
|
||||||
...where.audios_copied,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.from_environment) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
from_environment: filter.from_environment,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.to_environment) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
to_environment: filter.to_environment,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.status) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
status: filter.status,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.publish_events.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
for (const field of this.SEARCHABLE_FIELDS) {
|
||||||
let where = {};
|
if (filter[field]) {
|
||||||
|
where[Op.and] = Utils.ilike(this.TABLE_NAME, field, filter[field]);
|
||||||
|
}
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'publish_events',
|
|
||||||
'status',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.publish_events.findAll({
|
|
||||||
attributes: [ 'id', 'status' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['status', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.status,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = Publish_eventsDBApi;
|
||||||
|
|||||||
@ -1,294 +1,73 @@
|
|||||||
|
const GenericDBApi = require('./base.api');
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const Utils = require('../utils');
|
const Utils = require('../utils');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
const Sequelize = db.Sequelize;
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
module.exports = class Pwa_cachesDBApi {
|
class Pwa_cachesDBApi extends GenericDBApi {
|
||||||
|
static get MODEL() {
|
||||||
|
return db.pwa_caches;
|
||||||
|
}
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
static get TABLE_NAME() {
|
||||||
const transaction = (options && options.transaction) || undefined;
|
return 'pwa_caches';
|
||||||
|
}
|
||||||
const pwa_caches = await db.pwa_caches.create(
|
|
||||||
{
|
static get SEARCHABLE_FIELDS() {
|
||||||
id: data.id || undefined,
|
return ['cache_version', 'manifest_json', 'asset_list_json'];
|
||||||
|
}
|
||||||
environment: data.environment
|
|
||||||
||
|
static get RANGE_FIELDS() {
|
||||||
null
|
return ['generated_at'];
|
||||||
,
|
}
|
||||||
|
|
||||||
cache_version: data.cache_version
|
static get ENUM_FIELDS() {
|
||||||
||
|
return ['environment', 'is_active'];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
static get CSV_FIELDS() {
|
||||||
manifest_json: data.manifest_json
|
return ['id', 'environment', 'cache_version', 'is_active', 'generated_at', 'createdAt'];
|
||||||
||
|
}
|
||||||
null
|
|
||||||
,
|
static get AUTOCOMPLETE_FIELD() {
|
||||||
|
return 'cache_version';
|
||||||
asset_list_json: data.asset_list_json
|
}
|
||||||
||
|
|
||||||
null
|
static get ASSOCIATIONS() {
|
||||||
,
|
return [
|
||||||
|
{ field: 'project', setter: 'setProject', isArray: false },
|
||||||
generated_at: data.generated_at
|
];
|
||||||
||
|
}
|
||||||
null
|
|
||||||
,
|
static get FIND_BY_INCLUDES() {
|
||||||
|
return [{ association: 'project' }];
|
||||||
is_active: data.is_active
|
}
|
||||||
||
|
|
||||||
false
|
static getFieldMapping(data) {
|
||||||
|
return {
|
||||||
,
|
id: data.id || undefined,
|
||||||
|
environment: data.environment || null,
|
||||||
importHash: data.importHash || null,
|
cache_version: data.cache_version || null,
|
||||||
createdById: currentUser.id,
|
manifest_json: data.manifest_json || null,
|
||||||
updatedById: currentUser.id,
|
asset_list_json: data.asset_list_json || null,
|
||||||
},
|
generated_at: data.generated_at || null,
|
||||||
{ transaction },
|
is_active: data.is_active || false,
|
||||||
);
|
};
|
||||||
|
}
|
||||||
|
|
||||||
await pwa_caches.setProject( data.project || null, {
|
static async findAll(filter = {}, options = {}) {
|
||||||
transaction,
|
filter = filter || {};
|
||||||
});
|
const limit = filter.limit || 0;
|
||||||
|
const currentPage = +filter.page || 0;
|
||||||
|
const offset = currentPage * limit;
|
||||||
|
|
||||||
|
let where = {};
|
||||||
|
|
||||||
|
|
||||||
return pwa_caches;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const pwa_cachesData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
environment: item.environment
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
cache_version: item.cache_version
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
manifest_json: item.manifest_json
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
asset_list_json: item.asset_list_json
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
generated_at: item.generated_at
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
is_active: item.is_active
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const pwa_caches = await db.pwa_caches.bulkCreate(pwa_cachesData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return pwa_caches;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const pwa_caches = await db.pwa_caches.findByPk(id, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.environment !== undefined) updatePayload.environment = data.environment;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.cache_version !== undefined) updatePayload.cache_version = data.cache_version;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.manifest_json !== undefined) updatePayload.manifest_json = data.manifest_json;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.asset_list_json !== undefined) updatePayload.asset_list_json = data.asset_list_json;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.generated_at !== undefined) updatePayload.generated_at = data.generated_at;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.is_active !== undefined) updatePayload.is_active = data.is_active;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await pwa_caches.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.project !== undefined) {
|
|
||||||
await pwa_caches.setProject(
|
|
||||||
|
|
||||||
data.project,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return pwa_caches;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const pwa_caches = await db.pwa_caches.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of pwa_caches) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of pwa_caches) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return pwa_caches;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const pwa_caches = await db.pwa_caches.findByPk(id, options);
|
|
||||||
|
|
||||||
await pwa_caches.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await pwa_caches.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return pwa_caches;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const pwa_caches = await db.pwa_caches.findOne({
|
|
||||||
where,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!pwa_caches) {
|
|
||||||
return pwa_caches;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = pwa_caches.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.project = await pwa_caches.getProject({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
let include = [
|
let include = [
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.projects,
|
model: db.projects,
|
||||||
as: 'project',
|
as: 'project',
|
||||||
|
|
||||||
where: filter.project ? {
|
where: filter.project ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -299,201 +78,78 @@ module.exports = class Pwa_cachesDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if (filter) {
|
if (filter.id) {
|
||||||
if (filter.id) {
|
where.id = Utils.uuid(filter.id);
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.cache_version) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'pwa_caches',
|
|
||||||
'cache_version',
|
|
||||||
filter.cache_version,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.manifest_json) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'pwa_caches',
|
|
||||||
'manifest_json',
|
|
||||||
filter.manifest_json,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.asset_list_json) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'pwa_caches',
|
|
||||||
'asset_list_json',
|
|
||||||
filter.asset_list_json,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.generated_atRange) {
|
|
||||||
const [start, end] = filter.generated_atRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
generated_at: {
|
|
||||||
...where.generated_at,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
generated_at: {
|
|
||||||
...where.generated_at,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.environment) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
environment: filter.environment,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.is_active) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
is_active: filter.is_active,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.pwa_caches.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
for (const field of this.SEARCHABLE_FIELDS) {
|
||||||
let where = {};
|
if (filter[field]) {
|
||||||
|
where[Op.and] = Utils.ilike(this.TABLE_NAME, field, filter[field]);
|
||||||
|
}
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'pwa_caches',
|
|
||||||
'cache_version',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.pwa_caches.findAll({
|
|
||||||
attributes: [ 'id', 'cache_version' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['cache_version', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.cache_version,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = Pwa_cachesDBApi;
|
||||||
|
|||||||
@ -1,405 +1,148 @@
|
|||||||
|
const GenericDBApi = require('./base.api');
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const Utils = require('../utils');
|
const Utils = require('../utils');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
const Sequelize = db.Sequelize;
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
module.exports = class RolesDBApi {
|
class RolesDBApi extends GenericDBApi {
|
||||||
|
static get MODEL() {
|
||||||
|
return db.roles;
|
||||||
|
}
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
static get TABLE_NAME() {
|
||||||
const transaction = (options && options.transaction) || undefined;
|
return 'roles';
|
||||||
|
}
|
||||||
const roles = await db.roles.create(
|
|
||||||
{
|
static get SEARCHABLE_FIELDS() {
|
||||||
id: data.id || undefined,
|
return ['name', 'role_customization'];
|
||||||
|
}
|
||||||
name: data.name
|
|
||||||
||
|
static get RANGE_FIELDS() {
|
||||||
null
|
return [];
|
||||||
,
|
}
|
||||||
|
|
||||||
role_customization: data.role_customization
|
static get ENUM_FIELDS() {
|
||||||
||
|
return [];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
static get CSV_FIELDS() {
|
||||||
importHash: data.importHash || null,
|
return ['id', 'name', 'role_customization', 'createdAt'];
|
||||||
createdById: currentUser.id,
|
}
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
static get AUTOCOMPLETE_FIELD() {
|
||||||
{ transaction },
|
return 'name';
|
||||||
);
|
}
|
||||||
|
|
||||||
|
static get ASSOCIATIONS() {
|
||||||
|
return [
|
||||||
|
{ field: 'permissions', setter: 'setPermissions', isArray: true },
|
||||||
await roles.setPermissions(data.permissions || [], {
|
];
|
||||||
transaction,
|
}
|
||||||
});
|
|
||||||
|
static get FIND_BY_INCLUDES() {
|
||||||
|
return [
|
||||||
|
{ association: 'users_app_role' },
|
||||||
|
{ association: 'permissions' },
|
||||||
return roles;
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getFieldMapping(data) {
|
||||||
static async bulkImport(data, options) {
|
return {
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
id: data.id || undefined,
|
||||||
const transaction = (options && options.transaction) || undefined;
|
name: data.name || null,
|
||||||
|
role_customization: data.role_customization || null,
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
};
|
||||||
const rolesData = data.map((item, index) => ({
|
}
|
||||||
id: item.id || undefined,
|
|
||||||
|
static async findAll(filter = {}, options = {}) {
|
||||||
name: item.name
|
filter = filter || {};
|
||||||
||
|
const limit = filter.limit || 0;
|
||||||
null
|
const currentPage = +filter.page || 0;
|
||||||
,
|
const offset = currentPage * limit;
|
||||||
|
|
||||||
role_customization: item.role_customization
|
let where = {};
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const roles = await db.roles.bulkCreate(rolesData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const roles = await db.roles.findByPk(id, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.name !== undefined) updatePayload.name = data.name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.role_customization !== undefined) updatePayload.role_customization = data.role_customization;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await roles.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.permissions !== undefined) {
|
|
||||||
await roles.setPermissions(data.permissions, { transaction });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const roles = await db.roles.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of roles) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of roles) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const roles = await db.roles.findByPk(id, options);
|
|
||||||
|
|
||||||
await roles.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await roles.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const roles = await db.roles.findOne({
|
|
||||||
where,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!roles) {
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = roles.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
output.users_app_role = await roles.getUsers_app_role({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.permissions = await roles.getPermissions({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
let include = [
|
let include = [
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.permissions,
|
model: db.permissions,
|
||||||
as: 'permissions',
|
as: 'permissions',
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if (filter) {
|
if (filter.id) {
|
||||||
if (filter.id) {
|
where.id = Utils.uuid(filter.id);
|
||||||
where = {
|
}
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (const field of this.SEARCHABLE_FIELDS) {
|
||||||
if (filter.name) {
|
if (filter[field]) {
|
||||||
where = {
|
where[Op.and] = Utils.ilike(this.TABLE_NAME, field, filter[field]);
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'roles',
|
|
||||||
'name',
|
|
||||||
filter.name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.role_customization) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'roles',
|
|
||||||
'role_customization',
|
|
||||||
filter.role_customization,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.permissions) {
|
|
||||||
const searchTerms = filter.permissions.split('|');
|
|
||||||
|
|
||||||
include = [
|
|
||||||
{
|
|
||||||
model: db.permissions,
|
|
||||||
as: 'permissions_filter',
|
|
||||||
required: searchTerms.length > 0,
|
|
||||||
where: searchTerms.length > 0 ? {
|
|
||||||
[Op.or]: [
|
|
||||||
{ id: { [Op.in]: searchTerms.map(term => Utils.uuid(term)) } },
|
|
||||||
{
|
|
||||||
name: {
|
|
||||||
[Op.or]: searchTerms.map(term => ({ [Op.iLike]: `%${term}%` }))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
} : undefined
|
|
||||||
},
|
|
||||||
...include,
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const queryOptions = {
|
|
||||||
where,
|
|
||||||
include,
|
|
||||||
distinct: true,
|
|
||||||
order: filter.field && filter.sort
|
|
||||||
? [[filter.field, filter.sort]]
|
|
||||||
: [['createdAt', 'desc']],
|
|
||||||
transaction: options?.transaction,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.roles.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
if (filter.active !== undefined) {
|
||||||
let where = {};
|
where.active = filter.active === true || filter.active === 'true';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'roles',
|
|
||||||
'name',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.roles.findAll({
|
|
||||||
attributes: [ 'id', 'name' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['name', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.name,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filter.permissions) {
|
||||||
|
const searchTerms = filter.permissions.split('|');
|
||||||
|
include = [
|
||||||
|
{
|
||||||
|
model: db.permissions,
|
||||||
|
as: 'permissions_filter',
|
||||||
|
required: searchTerms.length > 0,
|
||||||
|
where: searchTerms.length > 0 ? {
|
||||||
|
[Op.or]: [
|
||||||
|
{ id: { [Op.in]: searchTerms.map(term => Utils.uuid(term)) } },
|
||||||
|
{
|
||||||
|
name: {
|
||||||
|
[Op.or]: searchTerms.map(term => ({ [Op.iLike]: `%${term}%` }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
} : undefined
|
||||||
|
},
|
||||||
|
...include,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
};
|
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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = RolesDBApi;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
|
const GenericDBApi = require('./base.api');
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const Utils = require('../utils');
|
const Utils = require('../utils');
|
||||||
const {
|
const {
|
||||||
@ -6,382 +6,120 @@ const {
|
|||||||
applyRuntimeProjectFilter,
|
applyRuntimeProjectFilter,
|
||||||
} = require('./runtime-context');
|
} = require('./runtime-context');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
const Sequelize = db.Sequelize;
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
module.exports = class Tour_pagesDBApi {
|
class Tour_pagesDBApi extends GenericDBApi {
|
||||||
|
static get MODEL() {
|
||||||
|
return db.tour_pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get TABLE_NAME() {
|
||||||
|
return 'tour_pages';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get SEARCHABLE_FIELDS() {
|
||||||
|
return ['source_key', 'name', 'slug', 'background_image_url', 'background_video_url', 'background_audio_url', 'ui_schema_json'];
|
||||||
|
}
|
||||||
|
|
||||||
static async create(data, options) {
|
static get RANGE_FIELDS() {
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
return ['sort_order'];
|
||||||
const transaction = (options && options.transaction) || undefined;
|
}
|
||||||
const projectId = data.project || data.projectId || null;
|
|
||||||
|
|
||||||
const tour_pages = await db.tour_pages.create(
|
static get ENUM_FIELDS() {
|
||||||
{
|
return ['environment', 'background_loop', 'requires_auth'];
|
||||||
id: data.id || undefined,
|
}
|
||||||
|
|
||||||
environment: data.environment
|
static get CSV_FIELDS() {
|
||||||
||
|
return ['id', 'environment', 'source_key', 'name', 'slug', 'sort_order', 'createdAt'];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
|
||||||
source_key: data.source_key
|
static get AUTOCOMPLETE_FIELD() {
|
||||||
||
|
return 'name';
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
|
||||||
name: data.name
|
static get ASSOCIATIONS() {
|
||||||
||
|
return [
|
||||||
null
|
{ field: 'project', setter: 'setProject', isArray: false },
|
||||||
,
|
];
|
||||||
|
}
|
||||||
|
|
||||||
slug: data.slug
|
static getFieldMapping(data) {
|
||||||
||
|
return {
|
||||||
null
|
id: data.id || undefined,
|
||||||
,
|
environment: data.environment || null,
|
||||||
|
source_key: data.source_key || null,
|
||||||
|
name: data.name || null,
|
||||||
|
slug: data.slug || null,
|
||||||
|
sort_order: data.sort_order || null,
|
||||||
|
background_image_url: data.background_image_url || null,
|
||||||
|
background_video_url: data.background_video_url || null,
|
||||||
|
background_audio_url: data.background_audio_url || null,
|
||||||
|
background_loop: data.background_loop || false,
|
||||||
|
requires_auth: data.requires_auth || false,
|
||||||
|
ui_schema_json: data.ui_schema_json || null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
sort_order: data.sort_order
|
static async create(data, options = {}) {
|
||||||
||
|
const currentUser = options.currentUser || { id: null };
|
||||||
null
|
const transaction = options.transaction;
|
||||||
,
|
const projectId = data.project || data.projectId || null;
|
||||||
|
|
||||||
background_image_url: data.background_image_url
|
const record = await this.MODEL.create(
|
||||||
||
|
{
|
||||||
null
|
...this.getFieldMapping(data),
|
||||||
,
|
projectId,
|
||||||
|
importHash: data.importHash || null,
|
||||||
background_video_url: data.background_video_url
|
createdById: currentUser.id,
|
||||||
||
|
updatedById: currentUser.id,
|
||||||
null
|
},
|
||||||
,
|
{ transaction }
|
||||||
|
|
||||||
background_audio_url: data.background_audio_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
background_loop: data.background_loop
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
requires_auth: data.requires_auth
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
ui_schema_json: data.ui_schema_json
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
projectId,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await record.setProject(projectId, { transaction });
|
||||||
|
|
||||||
await tour_pages.setProject(projectId, {
|
return record;
|
||||||
transaction,
|
}
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return tour_pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const tour_pagesData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
environment: item.environment
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
source_key: item.source_key
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
name: item.name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
slug: item.slug
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
sort_order: item.sort_order
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
background_image_url: item.background_image_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
background_video_url: item.background_video_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
background_audio_url: item.background_audio_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
background_loop: item.background_loop
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
requires_auth: item.requires_auth
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
ui_schema_json: item.ui_schema_json
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const tour_pages = await db.tour_pages.bulkCreate(tour_pagesData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return tour_pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const tour_pages = await db.tour_pages.findByPk(id, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.environment !== undefined) updatePayload.environment = data.environment;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.source_key !== undefined) updatePayload.source_key = data.source_key;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.name !== undefined) updatePayload.name = data.name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.slug !== undefined) updatePayload.slug = data.slug;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.sort_order !== undefined) updatePayload.sort_order = data.sort_order;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.background_image_url !== undefined) updatePayload.background_image_url = data.background_image_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.background_video_url !== undefined) updatePayload.background_video_url = data.background_video_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.background_audio_url !== undefined) updatePayload.background_audio_url = data.background_audio_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.background_loop !== undefined) updatePayload.background_loop = data.background_loop;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.requires_auth !== undefined) updatePayload.requires_auth = data.requires_auth;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.ui_schema_json !== undefined) updatePayload.ui_schema_json = data.ui_schema_json;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await tour_pages.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.project !== undefined) {
|
|
||||||
await tour_pages.setProject(
|
|
||||||
|
|
||||||
data.project,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return tour_pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const tour_pages = await db.tour_pages.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of tour_pages) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of tour_pages) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return tour_pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const tour_pages = await db.tour_pages.findByPk(id, options);
|
|
||||||
|
|
||||||
await tour_pages.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await tour_pages.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return tour_pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
const queryWhere = applyRuntimeEnvironment({ ...where }, options);
|
|
||||||
const projectInclude = applyRuntimeProjectFilter(
|
|
||||||
{
|
|
||||||
model: db.projects,
|
|
||||||
as: 'project',
|
|
||||||
},
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
const tour_pages = await db.tour_pages.findOne(
|
|
||||||
{ where: queryWhere, include: [projectInclude], transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!tour_pages) {
|
|
||||||
return tour_pages;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = tour_pages.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.page_elements_page = await tour_pages.getPage_elements_page({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.page_links_from_page = await tour_pages.getPage_links_from_page({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
output.page_links_to_page = await tour_pages.getPage_links_to_page({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.project = await tour_pages.getProject({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
filter = filter || {};
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
let include = [
|
|
||||||
|
|
||||||
|
static async findBy(where, options = {}) {
|
||||||
|
const transaction = options.transaction;
|
||||||
|
const queryWhere = applyRuntimeEnvironment({ ...where }, options);
|
||||||
|
const projectInclude = applyRuntimeProjectFilter(
|
||||||
{
|
{
|
||||||
model: db.projects,
|
model: db.projects,
|
||||||
as: 'project',
|
as: 'project',
|
||||||
|
},
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
|
const record = await this.MODEL.findOne({
|
||||||
|
where: queryWhere,
|
||||||
|
transaction,
|
||||||
|
include: [
|
||||||
|
projectInclude,
|
||||||
|
{ association: 'page_elements_page' },
|
||||||
|
{ association: 'page_links_from_page' },
|
||||||
|
{ association: 'page_links_to_page' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
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 = {};
|
||||||
|
|
||||||
|
let include = [
|
||||||
|
{
|
||||||
|
model: db.projects,
|
||||||
|
as: 'project',
|
||||||
where: filter.project ? {
|
where: filter.project ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -392,254 +130,82 @@ module.exports = class Tour_pagesDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
include[0] = applyRuntimeProjectFilter(include[0], options);
|
|
||||||
|
|
||||||
if (filter) {
|
include[0] = applyRuntimeProjectFilter(include[0], options);
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (filter.id) {
|
||||||
if (filter.source_key) {
|
where.id = Utils.uuid(filter.id);
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'tour_pages',
|
|
||||||
'source_key',
|
|
||||||
filter.source_key,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'tour_pages',
|
|
||||||
'name',
|
|
||||||
filter.name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.slug) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'tour_pages',
|
|
||||||
'slug',
|
|
||||||
filter.slug,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.background_image_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'tour_pages',
|
|
||||||
'background_image_url',
|
|
||||||
filter.background_image_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.background_video_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'tour_pages',
|
|
||||||
'background_video_url',
|
|
||||||
filter.background_video_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.background_audio_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'tour_pages',
|
|
||||||
'background_audio_url',
|
|
||||||
filter.background_audio_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.ui_schema_json) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'tour_pages',
|
|
||||||
'ui_schema_json',
|
|
||||||
filter.ui_schema_json,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.sort_orderRange) {
|
|
||||||
const [start, end] = filter.sort_orderRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.environment) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
environment: filter.environment,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.background_loop) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
background_loop: filter.background_loop,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.requires_auth) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
requires_auth: filter.requires_auth,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...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,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.tour_pages.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
for (const field of this.SEARCHABLE_FIELDS) {
|
||||||
let where = {};
|
if (filter[field]) {
|
||||||
|
where[Op.and] = Utils.ilike(this.TABLE_NAME, field, filter[field]);
|
||||||
|
}
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'tour_pages',
|
|
||||||
'name',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.tour_pages.findAll({
|
|
||||||
attributes: [ 'id', 'name' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['name', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.name,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 = Tour_pagesDBApi;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
|
const GenericDBApi = require('./base.api');
|
||||||
const db = require('../models');
|
const db = require('../models');
|
||||||
const Utils = require('../utils');
|
const Utils = require('../utils');
|
||||||
const {
|
const {
|
||||||
@ -6,331 +6,91 @@ const {
|
|||||||
applyRuntimeProjectFilter,
|
applyRuntimeProjectFilter,
|
||||||
} = require('./runtime-context');
|
} = require('./runtime-context');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
const Sequelize = db.Sequelize;
|
||||||
const Op = Sequelize.Op;
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
module.exports = class TransitionsDBApi {
|
class TransitionsDBApi extends GenericDBApi {
|
||||||
|
static get MODEL() {
|
||||||
|
return db.transitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get TABLE_NAME() {
|
||||||
|
return 'transitions';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get SEARCHABLE_FIELDS() {
|
||||||
|
return ['source_key', 'name', 'slug', 'video_url', 'audio_url'];
|
||||||
|
}
|
||||||
|
|
||||||
static async create(data, options) {
|
static get RANGE_FIELDS() {
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
return ['duration_sec'];
|
||||||
const transaction = (options && options.transaction) || undefined;
|
}
|
||||||
|
|
||||||
const transitions = await db.transitions.create(
|
static get ENUM_FIELDS() {
|
||||||
{
|
return ['environment', 'supports_reverse'];
|
||||||
id: data.id || undefined,
|
}
|
||||||
|
|
||||||
environment: data.environment
|
static get CSV_FIELDS() {
|
||||||
||
|
return ['id', 'source_key', 'name', 'slug', 'video_url', 'audio_url', 'duration_sec', 'createdAt'];
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
|
||||||
source_key: data.source_key
|
static get AUTOCOMPLETE_FIELD() {
|
||||||
||
|
return 'name';
|
||||||
null
|
}
|
||||||
,
|
|
||||||
|
|
||||||
name: data.name
|
static get ASSOCIATIONS() {
|
||||||
||
|
return [
|
||||||
null
|
{ field: 'project', setter: 'setProject', isArray: false },
|
||||||
,
|
];
|
||||||
|
}
|
||||||
|
|
||||||
slug: data.slug
|
static getFieldMapping(data) {
|
||||||
||
|
return {
|
||||||
null
|
id: data.id || undefined,
|
||||||
,
|
environment: data.environment || null,
|
||||||
|
source_key: data.source_key || null,
|
||||||
|
name: data.name || null,
|
||||||
|
slug: data.slug || null,
|
||||||
|
video_url: data.video_url || null,
|
||||||
|
audio_url: data.audio_url || null,
|
||||||
|
supports_reverse: data.supports_reverse || false,
|
||||||
|
duration_sec: data.duration_sec || null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
video_url: data.video_url
|
static async findBy(where, options = {}) {
|
||||||
||
|
const transaction = options.transaction;
|
||||||
null
|
const queryWhere = applyRuntimeEnvironment({ ...where }, options);
|
||||||
,
|
const projectInclude = applyRuntimeProjectFilter(
|
||||||
|
{ model: db.projects, as: 'project' },
|
||||||
audio_url: data.audio_url
|
options
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
supports_reverse: data.supports_reverse
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
duration_sec: data.duration_sec
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const record = await this.MODEL.findOne({
|
||||||
await transitions.setProject( data.project || null, {
|
where: queryWhere,
|
||||||
transaction,
|
transaction,
|
||||||
});
|
include: [
|
||||||
|
projectInclude,
|
||||||
|
{ association: 'page_links_transition' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!record) return null;
|
||||||
return transitions;
|
return record.get({ plain: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async findAll(filter = {}, options = {}) {
|
||||||
static async bulkImport(data, options) {
|
filter = filter || {};
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
const limit = filter.limit || 0;
|
||||||
const transaction = (options && options.transaction) || undefined;
|
const currentPage = +filter.page || 0;
|
||||||
|
const offset = currentPage * limit;
|
||||||
// Prepare data - wrapping individual data transformations in a map() method
|
|
||||||
const transitionsData = data.map((item, index) => ({
|
let where = {};
|
||||||
id: item.id || undefined,
|
|
||||||
|
|
||||||
environment: item.environment
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
source_key: item.source_key
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
name: item.name
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
slug: item.slug
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
video_url: item.video_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
audio_url: item.audio_url
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
supports_reverse: item.supports_reverse
|
|
||||||
||
|
|
||||||
false
|
|
||||||
|
|
||||||
,
|
|
||||||
|
|
||||||
duration_sec: item.duration_sec
|
|
||||||
||
|
|
||||||
null
|
|
||||||
,
|
|
||||||
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Bulk create items
|
|
||||||
const transitions = await db.transitions.bulkCreate(transitionsData, { transaction });
|
|
||||||
|
|
||||||
// For each item created, replace relation files
|
|
||||||
|
|
||||||
|
|
||||||
return transitions;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
|
|
||||||
const transitions = await db.transitions.findByPk(id, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.environment !== undefined) updatePayload.environment = data.environment;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.source_key !== undefined) updatePayload.source_key = data.source_key;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.name !== undefined) updatePayload.name = data.name;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.slug !== undefined) updatePayload.slug = data.slug;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.video_url !== undefined) updatePayload.video_url = data.video_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.audio_url !== undefined) updatePayload.audio_url = data.audio_url;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.supports_reverse !== undefined) updatePayload.supports_reverse = data.supports_reverse;
|
|
||||||
|
|
||||||
|
|
||||||
if (data.duration_sec !== undefined) updatePayload.duration_sec = data.duration_sec;
|
|
||||||
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await transitions.update(updatePayload, {transaction});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (data.project !== undefined) {
|
|
||||||
await transitions.setProject(
|
|
||||||
|
|
||||||
data.project,
|
|
||||||
|
|
||||||
{ transaction }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return transitions;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const transitions = await db.transitions.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (transaction) => {
|
|
||||||
for (const record of transitions) {
|
|
||||||
await record.update(
|
|
||||||
{deletedBy: currentUser.id},
|
|
||||||
{transaction}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for (const record of transitions) {
|
|
||||||
await record.destroy({transaction});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
return transitions;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || {id: null};
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const transitions = await db.transitions.findByPk(id, options);
|
|
||||||
|
|
||||||
await transitions.update({
|
|
||||||
deletedBy: currentUser.id
|
|
||||||
}, {
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await transitions.destroy({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
return transitions;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
const queryWhere = applyRuntimeEnvironment({ ...where }, options);
|
|
||||||
const projectInclude = applyRuntimeProjectFilter(
|
|
||||||
{
|
|
||||||
model: db.projects,
|
|
||||||
as: 'project',
|
|
||||||
},
|
|
||||||
options,
|
|
||||||
);
|
|
||||||
|
|
||||||
const transitions = await db.transitions.findOne(
|
|
||||||
{ where: queryWhere, include: [projectInclude], transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!transitions) {
|
|
||||||
return transitions;
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = transitions.get({plain: true});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.page_links_transition = await transitions.getPage_links_transition({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.project = await transitions.getProject({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(
|
|
||||||
filter,
|
|
||||||
options
|
|
||||||
) {
|
|
||||||
filter = filter || {};
|
|
||||||
const limit = filter.limit || 0;
|
|
||||||
let offset = 0;
|
|
||||||
let where = {};
|
|
||||||
const currentPage = +filter.page;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
offset = currentPage * limit;
|
|
||||||
|
|
||||||
let include = [
|
let include = [
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.projects,
|
model: db.projects,
|
||||||
as: 'project',
|
as: 'project',
|
||||||
|
|
||||||
where: filter.project ? {
|
where: filter.project ? {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
{ id: { [Op.in]: filter.project.split('|').map(term => Utils.uuid(term)) } },
|
||||||
@ -341,225 +101,82 @@ module.exports = class TransitionsDBApi {
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
} : {},
|
} : {},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
];
|
||||||
include[0] = applyRuntimeProjectFilter(include[0], options);
|
|
||||||
|
|
||||||
if (filter) {
|
include[0] = applyRuntimeProjectFilter(include[0], options);
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['id']: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (filter.id) {
|
||||||
if (filter.source_key) {
|
where.id = Utils.uuid(filter.id);
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'transitions',
|
|
||||||
'source_key',
|
|
||||||
filter.source_key,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'transitions',
|
|
||||||
'name',
|
|
||||||
filter.name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.slug) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'transitions',
|
|
||||||
'slug',
|
|
||||||
filter.slug,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.video_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'transitions',
|
|
||||||
'video_url',
|
|
||||||
filter.video_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.audio_url) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike(
|
|
||||||
'transitions',
|
|
||||||
'audio_url',
|
|
||||||
filter.audio_url,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.duration_secRange) {
|
|
||||||
const [start, end] = filter.duration_secRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
duration_sec: {
|
|
||||||
...where.duration_sec,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
duration_sec: {
|
|
||||||
...where.duration_sec,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.active !== undefined) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
active: filter.active === true || filter.active === 'true'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.environment) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
environment: filter.environment,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.supports_reverse) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
supports_reverse: filter.supports_reverse,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
|
||||||
const [start, end] = filter.createdAtRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
['createdAt']: {
|
|
||||||
...where.createdAt,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...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,
|
|
||||||
logging: console.log
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
|
||||||
queryOptions.limit = limit ? Number(limit) : undefined;
|
|
||||||
queryOptions.offset = offset ? Number(offset) : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { rows, count } = await db.transitions.findAndCountAll(queryOptions);
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows: options?.countOnly ? [] : rows,
|
|
||||||
count: count
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error executing query:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit, offset, ) {
|
for (const field of this.SEARCHABLE_FIELDS) {
|
||||||
let where = {};
|
if (filter[field]) {
|
||||||
|
where[Op.and] = Utils.ilike(this.TABLE_NAME, field, filter[field]);
|
||||||
|
}
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{ ['id']: Utils.uuid(query) },
|
|
||||||
Utils.ilike(
|
|
||||||
'transitions',
|
|
||||||
'name',
|
|
||||||
query,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.transitions.findAll({
|
|
||||||
attributes: [ 'id', 'name' ],
|
|
||||||
where,
|
|
||||||
limit: limit ? Number(limit) : undefined,
|
|
||||||
offset: offset ? Number(offset) : undefined,
|
|
||||||
orderBy: [['name', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.name,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 = TransitionsDBApi;
|
||||||
|
|||||||
@ -1,233 +0,0 @@
|
|||||||
const db = require('../models');
|
|
||||||
const Utils = require('../utils');
|
|
||||||
|
|
||||||
const Sequelize = db.Sequelize;
|
|
||||||
const Op = Sequelize.Op;
|
|
||||||
|
|
||||||
module.exports = class Ui_elementsDBApi {
|
|
||||||
static async create(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const ui_elements = await db.ui_elements.create(
|
|
||||||
{
|
|
||||||
id: data.id || undefined,
|
|
||||||
element_type: data.element_type ?? null,
|
|
||||||
name: data.name ?? null,
|
|
||||||
settings_json: data.settings_json ?? null,
|
|
||||||
sort_order: data.sort_order ?? 0,
|
|
||||||
importHash: data.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
return ui_elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async bulkImport(data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const uiElementsData = data.map((item, index) => ({
|
|
||||||
id: item.id || undefined,
|
|
||||||
element_type: item.element_type ?? null,
|
|
||||||
name: item.name ?? null,
|
|
||||||
settings_json: item.settings_json ?? null,
|
|
||||||
sort_order: item.sort_order ?? 0,
|
|
||||||
importHash: item.importHash || null,
|
|
||||||
createdById: currentUser.id,
|
|
||||||
updatedById: currentUser.id,
|
|
||||||
createdAt: new Date(Date.now() + index * 1000),
|
|
||||||
}));
|
|
||||||
|
|
||||||
const ui_elements = await db.ui_elements.bulkCreate(uiElementsData, { transaction });
|
|
||||||
|
|
||||||
return ui_elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const ui_elements = await db.ui_elements.findByPk(id, { transaction });
|
|
||||||
|
|
||||||
const updatePayload = {};
|
|
||||||
|
|
||||||
if (data.element_type !== undefined) updatePayload.element_type = data.element_type;
|
|
||||||
if (data.name !== undefined) updatePayload.name = data.name;
|
|
||||||
if (data.settings_json !== undefined) updatePayload.settings_json = data.settings_json;
|
|
||||||
if (data.sort_order !== undefined) updatePayload.sort_order = data.sort_order;
|
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
|
||||||
|
|
||||||
await ui_elements.update(updatePayload, { transaction });
|
|
||||||
|
|
||||||
return ui_elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const ui_elements = await db.ui_elements.findAll({
|
|
||||||
where: {
|
|
||||||
id: {
|
|
||||||
[Op.in]: ids,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.sequelize.transaction(async (innerTransaction) => {
|
|
||||||
for (const record of ui_elements) {
|
|
||||||
await record.update({ deletedBy: currentUser.id }, { transaction: innerTransaction });
|
|
||||||
}
|
|
||||||
for (const record of ui_elements) {
|
|
||||||
await record.destroy({ transaction: innerTransaction });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return ui_elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, options) {
|
|
||||||
const currentUser = (options && options.currentUser) || { id: null };
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const ui_elements = await db.ui_elements.findByPk(id, options);
|
|
||||||
|
|
||||||
await ui_elements.update(
|
|
||||||
{
|
|
||||||
deletedBy: currentUser.id,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
await ui_elements.destroy({
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
return ui_elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findBy(where, options) {
|
|
||||||
const transaction = (options && options.transaction) || undefined;
|
|
||||||
|
|
||||||
const ui_elements = await db.ui_elements.findOne({ where, transaction });
|
|
||||||
|
|
||||||
if (!ui_elements) {
|
|
||||||
return ui_elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ui_elements.get({ plain: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAll(filter, options) {
|
|
||||||
filter = filter || {};
|
|
||||||
const limit = Number(filter.limit) || 0;
|
|
||||||
const currentPage = Number(filter.page) || 0;
|
|
||||||
const offset = limit ? currentPage * limit : undefined;
|
|
||||||
let where = {};
|
|
||||||
|
|
||||||
if (filter.id) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
id: Utils.uuid(filter.id),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.name) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike('ui_elements', 'name', filter.name),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.element_type) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
element_type: filter.element_type,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.sort_orderRange) {
|
|
||||||
const [start, end] = filter.sort_orderRange;
|
|
||||||
|
|
||||||
if (start !== undefined && start !== null && start !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.gte]: start,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (end !== undefined && end !== null && end !== '') {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
sort_order: {
|
|
||||||
...where.sort_order,
|
|
||||||
[Op.lte]: end,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let { orderBy = null } = options || {};
|
|
||||||
if (!orderBy) {
|
|
||||||
const sort = filter.sort || 'desc';
|
|
||||||
const field = filter.field || 'createdAt';
|
|
||||||
orderBy = [[field, sort]];
|
|
||||||
}
|
|
||||||
|
|
||||||
const { rows, count } = await db.ui_elements.findAndCountAll({
|
|
||||||
where,
|
|
||||||
limit: limit || undefined,
|
|
||||||
offset,
|
|
||||||
order: orderBy,
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
rows,
|
|
||||||
count,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static async findAllAutocomplete(query, limit) {
|
|
||||||
let where = {};
|
|
||||||
|
|
||||||
if (query) {
|
|
||||||
where = {
|
|
||||||
[Op.or]: [
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
[Op.eq]: Utils.uuid(query),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: {
|
|
||||||
[Op.iLike]: `%${query}%`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const records = await db.ui_elements.findAll({
|
|
||||||
attributes: ['id', 'name'],
|
|
||||||
where,
|
|
||||||
limit: Number(limit) || undefined,
|
|
||||||
order: [['name', 'ASC']],
|
|
||||||
});
|
|
||||||
|
|
||||||
return records.map((record) => ({
|
|
||||||
id: record.id,
|
|
||||||
label: record.name,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -391,6 +391,18 @@ module.exports = class UsersDBApi {
|
|||||||
const users = await db.users.findOne({
|
const users = await db.users.findOne({
|
||||||
where,
|
where,
|
||||||
transaction,
|
transaction,
|
||||||
|
include: [
|
||||||
|
{ association: 'project_memberships_user' },
|
||||||
|
{ association: 'presigned_url_requests_user' },
|
||||||
|
{ association: 'publish_events_user' },
|
||||||
|
{ association: 'access_logs_user' },
|
||||||
|
{ association: 'avatar' },
|
||||||
|
{
|
||||||
|
association: 'app_role',
|
||||||
|
include: [{ association: 'permissions' }],
|
||||||
|
},
|
||||||
|
{ association: 'custom_permissions' },
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!users) {
|
if (!users) {
|
||||||
@ -399,62 +411,11 @@ module.exports = class UsersDBApi {
|
|||||||
|
|
||||||
const output = users.get({plain: true});
|
const output = users.get({plain: true});
|
||||||
|
|
||||||
|
// Map nested permissions from app_role for backward compatibility
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.project_memberships_user = await users.getProject_memberships_user({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.presigned_url_requests_user = await users.getPresigned_url_requests_user({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.publish_events_user = await users.getPublish_events_user({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.access_logs_user = await users.getAccess_logs_user({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
output.avatar = await users.getAvatar({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
output.app_role = await users.getApp_role({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
if (output.app_role) {
|
if (output.app_role) {
|
||||||
output.app_role_permissions = await output.app_role.getPermissions({
|
output.app_role_permissions = output.app_role.permissions || [];
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
output.custom_permissions = await users.getCustom_permissions({
|
|
||||||
transaction
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -744,8 +705,7 @@ module.exports = class UsersDBApi {
|
|||||||
order: filter.field && filter.sort
|
order: filter.field && filter.sort
|
||||||
? [[filter.field, filter.sort]]
|
? [[filter.field, filter.sort]]
|
||||||
: [['createdAt', 'desc']],
|
: [['createdAt', 'desc']],
|
||||||
transaction: options?.transaction,
|
transaction: options?.transaction
|
||||||
logging: console.log
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!options?.countOnly) {
|
if (!options?.countOnly) {
|
||||||
@ -921,7 +881,9 @@ module.exports = class UsersDBApi {
|
|||||||
const token = crypto
|
const token = crypto
|
||||||
.randomBytes(20)
|
.randomBytes(20)
|
||||||
.toString('hex');
|
.toString('hex');
|
||||||
const tokenExpiresAt = Date.now() + 360000;
|
// Token expires in 24 hours (was 6 minutes - too short for email verification flows)
|
||||||
|
const TOKEN_EXPIRY_MS = 24 * 60 * 60 * 1000; // 24 hours
|
||||||
|
const tokenExpiresAt = Date.now() + TOKEN_EXPIRY_MS;
|
||||||
|
|
||||||
if(users){
|
if(users){
|
||||||
await users.update(
|
await users.update(
|
||||||
|
|||||||
@ -8,7 +8,7 @@ module.exports = {
|
|||||||
database: process.env.DB_NAME,
|
database: process.env.DB_NAME,
|
||||||
host: process.env.DB_HOST,
|
host: process.env.DB_HOST,
|
||||||
port: process.env.DB_PORT,
|
port: process.env.DB_PORT,
|
||||||
logging: console.log,
|
logging: false,
|
||||||
seederStorage: 'sequelize',
|
seederStorage: 'sequelize',
|
||||||
},
|
},
|
||||||
development: {
|
development: {
|
||||||
@ -20,14 +20,14 @@ module.exports = {
|
|||||||
logging: console.log,
|
logging: console.log,
|
||||||
seederStorage: 'sequelize',
|
seederStorage: 'sequelize',
|
||||||
},
|
},
|
||||||
dev_stage: {
|
dev_stage: {
|
||||||
dialect: 'postgres',
|
dialect: 'postgres',
|
||||||
username: process.env.DB_USER,
|
username: process.env.DB_USER,
|
||||||
password: process.env.DB_PASS,
|
password: process.env.DB_PASS,
|
||||||
database: process.env.DB_NAME,
|
database: process.env.DB_NAME,
|
||||||
host: process.env.DB_HOST,
|
host: process.env.DB_HOST,
|
||||||
port: process.env.DB_PORT,
|
port: process.env.DB_PORT,
|
||||||
logging: console.log,
|
logging: console.log,
|
||||||
seederStorage: 'sequelize',
|
seederStorage: 'sequelize',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,124 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
async up(queryInterface, Sequelize) {
|
|
||||||
const transaction = await queryInterface.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const rows = await queryInterface.sequelize.query(
|
|
||||||
"SELECT to_regclass('public.files') AS regclass_name;",
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
const tableName = rows[0].regclass_name;
|
|
||||||
|
|
||||||
if (tableName) {
|
|
||||||
await transaction.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await queryInterface.createTable(
|
|
||||||
'files',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: Sequelize.DataTypes.UUID,
|
|
||||||
defaultValue: Sequelize.DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
belongsTo: {
|
|
||||||
type: Sequelize.DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
belongsToId: {
|
|
||||||
type: Sequelize.DataTypes.UUID,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
belongsToColumn: {
|
|
||||||
type: Sequelize.DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: Sequelize.DataTypes.STRING(2083),
|
|
||||||
allowNull: false,
|
|
||||||
},
|
|
||||||
sizeInBytes: {
|
|
||||||
type: Sequelize.DataTypes.INTEGER,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
privateUrl: {
|
|
||||||
type: Sequelize.DataTypes.STRING(2083),
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
publicUrl: {
|
|
||||||
type: Sequelize.DataTypes.STRING(2083),
|
|
||||||
allowNull: false,
|
|
||||||
},
|
|
||||||
createdAt: {
|
|
||||||
type: Sequelize.DataTypes.DATE,
|
|
||||||
allowNull: false,
|
|
||||||
},
|
|
||||||
updatedAt: {
|
|
||||||
type: Sequelize.DataTypes.DATE,
|
|
||||||
allowNull: false,
|
|
||||||
},
|
|
||||||
deletedAt: {
|
|
||||||
type: Sequelize.DataTypes.DATE,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
createdById: {
|
|
||||||
type: Sequelize.DataTypes.UUID,
|
|
||||||
allowNull: true,
|
|
||||||
references: {
|
|
||||||
key: 'id',
|
|
||||||
model: 'users',
|
|
||||||
},
|
|
||||||
onDelete: 'SET NULL',
|
|
||||||
onUpdate: 'CASCADE',
|
|
||||||
},
|
|
||||||
updatedById: {
|
|
||||||
type: Sequelize.DataTypes.UUID,
|
|
||||||
allowNull: true,
|
|
||||||
references: {
|
|
||||||
key: 'id',
|
|
||||||
model: 'users',
|
|
||||||
},
|
|
||||||
onDelete: 'SET NULL',
|
|
||||||
onUpdate: 'CASCADE',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (err) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async down(queryInterface, Sequelize) {
|
|
||||||
const transaction = await queryInterface.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const rows = await queryInterface.sequelize.query(
|
|
||||||
"SELECT to_regclass('public.files') AS regclass_name;",
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
const tableName = rows[0].regclass_name;
|
|
||||||
|
|
||||||
if (!tableName) {
|
|
||||||
await transaction.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await queryInterface.dropTable('files', { transaction });
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (err) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
async up(queryInterface, Sequelize) {
|
|
||||||
const transaction = await queryInterface.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const rows = await queryInterface.sequelize.query(
|
|
||||||
"SELECT to_regclass('public.\"usersCustom_permissionsPermissions\"') AS regclass_name;",
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
const tableName = rows[0].regclass_name;
|
|
||||||
|
|
||||||
if (tableName) {
|
|
||||||
await transaction.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await queryInterface.createTable(
|
|
||||||
'usersCustom_permissionsPermissions',
|
|
||||||
{
|
|
||||||
createdAt: {
|
|
||||||
type: Sequelize.DataTypes.DATE,
|
|
||||||
allowNull: false,
|
|
||||||
},
|
|
||||||
updatedAt: {
|
|
||||||
type: Sequelize.DataTypes.DATE,
|
|
||||||
allowNull: false,
|
|
||||||
},
|
|
||||||
users_custom_permissionsId: {
|
|
||||||
type: Sequelize.DataTypes.UUID,
|
|
||||||
allowNull: false,
|
|
||||||
primaryKey: true,
|
|
||||||
references: {
|
|
||||||
model: 'users',
|
|
||||||
key: 'id',
|
|
||||||
},
|
|
||||||
onDelete: 'CASCADE',
|
|
||||||
onUpdate: 'CASCADE',
|
|
||||||
},
|
|
||||||
permissionId: {
|
|
||||||
type: Sequelize.DataTypes.UUID,
|
|
||||||
allowNull: false,
|
|
||||||
primaryKey: true,
|
|
||||||
references: {
|
|
||||||
model: 'permissions',
|
|
||||||
key: 'id',
|
|
||||||
},
|
|
||||||
onDelete: 'CASCADE',
|
|
||||||
onUpdate: 'CASCADE',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
await queryInterface.addIndex(
|
|
||||||
'usersCustom_permissionsPermissions',
|
|
||||||
['permissionId'],
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (err) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async down(queryInterface, Sequelize) {
|
|
||||||
const transaction = await queryInterface.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const rows = await queryInterface.sequelize.query(
|
|
||||||
"SELECT to_regclass('public.\"usersCustom_permissionsPermissions\"') AS regclass_name;",
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
const tableName = rows[0].regclass_name;
|
|
||||||
|
|
||||||
if (!tableName) {
|
|
||||||
await transaction.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await queryInterface.dropTable('usersCustom_permissionsPermissions', { transaction });
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (err) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@ -1,123 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
async up(queryInterface, Sequelize) {
|
|
||||||
const transaction = await queryInterface.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const tableRows = await queryInterface.sequelize.query(
|
|
||||||
"SELECT to_regclass('public.page_elements') AS regclass_name;",
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!tableRows[0]?.regclass_name) {
|
|
||||||
await transaction.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nullableRows = await queryInterface.sequelize.query(
|
|
||||||
`SELECT is_nullable
|
|
||||||
FROM information_schema.columns
|
|
||||||
WHERE table_schema = 'public'
|
|
||||||
AND table_name = 'page_elements'
|
|
||||||
AND column_name = 'pageId';`,
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!nullableRows.length || nullableRows[0].is_nullable === 'YES') {
|
|
||||||
await transaction.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await queryInterface.changeColumn(
|
|
||||||
'page_elements',
|
|
||||||
'pageId',
|
|
||||||
{
|
|
||||||
type: Sequelize.DataTypes.UUID,
|
|
||||||
allowNull: true,
|
|
||||||
references: {
|
|
||||||
model: 'tour_pages',
|
|
||||||
key: 'id',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (err) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async down(queryInterface, Sequelize) {
|
|
||||||
const transaction = await queryInterface.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const tableRows = await queryInterface.sequelize.query(
|
|
||||||
"SELECT to_regclass('public.page_elements') AS regclass_name;",
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!tableRows[0]?.regclass_name) {
|
|
||||||
await transaction.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nullableRows = await queryInterface.sequelize.query(
|
|
||||||
`SELECT is_nullable
|
|
||||||
FROM information_schema.columns
|
|
||||||
WHERE table_schema = 'public'
|
|
||||||
AND table_name = 'page_elements'
|
|
||||||
AND column_name = 'pageId';`,
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!nullableRows.length || nullableRows[0].is_nullable === 'NO') {
|
|
||||||
await transaction.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nullCountRows = await queryInterface.sequelize.query(
|
|
||||||
'SELECT COUNT(*)::int AS count FROM "page_elements" WHERE "pageId" IS NULL;',
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (Number(nullCountRows[0]?.count || 0) > 0) {
|
|
||||||
throw new Error('Cannot make page_elements.pageId NOT NULL because NULL values exist.');
|
|
||||||
}
|
|
||||||
|
|
||||||
await queryInterface.changeColumn(
|
|
||||||
'page_elements',
|
|
||||||
'pageId',
|
|
||||||
{
|
|
||||||
type: Sequelize.DataTypes.UUID,
|
|
||||||
allowNull: false,
|
|
||||||
references: {
|
|
||||||
model: 'tour_pages',
|
|
||||||
key: 'id',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (err) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@ -1,105 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
async up(queryInterface, Sequelize) {
|
|
||||||
const transaction = await queryInterface.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const tableRows = await queryInterface.sequelize.query(
|
|
||||||
"SELECT to_regclass('public.page_elements') AS regclass_name;",
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!tableRows[0]?.regclass_name) {
|
|
||||||
await transaction.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nullableRows = await queryInterface.sequelize.query(
|
|
||||||
`SELECT is_nullable
|
|
||||||
FROM information_schema.columns
|
|
||||||
WHERE table_schema = 'public'
|
|
||||||
AND table_name = 'page_elements'
|
|
||||||
AND column_name = 'pageId';`,
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!nullableRows.length || nullableRows[0].is_nullable === 'YES') {
|
|
||||||
await transaction.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await queryInterface.sequelize.query(
|
|
||||||
'ALTER TABLE "page_elements" ALTER COLUMN "pageId" DROP NOT NULL;',
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (err) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async down(queryInterface, Sequelize) {
|
|
||||||
const transaction = await queryInterface.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const tableRows = await queryInterface.sequelize.query(
|
|
||||||
"SELECT to_regclass('public.page_elements') AS regclass_name;",
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!tableRows[0]?.regclass_name) {
|
|
||||||
await transaction.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nullableRows = await queryInterface.sequelize.query(
|
|
||||||
`SELECT is_nullable
|
|
||||||
FROM information_schema.columns
|
|
||||||
WHERE table_schema = 'public'
|
|
||||||
AND table_name = 'page_elements'
|
|
||||||
AND column_name = 'pageId';`,
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!nullableRows.length || nullableRows[0].is_nullable === 'NO') {
|
|
||||||
await transaction.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nullCountRows = await queryInterface.sequelize.query(
|
|
||||||
'SELECT COUNT(*)::int AS count FROM "page_elements" WHERE "pageId" IS NULL;',
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (Number(nullCountRows[0]?.count || 0) > 0) {
|
|
||||||
throw new Error('Cannot make page_elements.pageId NOT NULL because NULL values exist.');
|
|
||||||
}
|
|
||||||
|
|
||||||
await queryInterface.sequelize.query(
|
|
||||||
'ALTER TABLE "page_elements" ALTER COLUMN "pageId" SET NOT NULL;',
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (err) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@ -1,108 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
async up(queryInterface, Sequelize) {
|
|
||||||
const transaction = await queryInterface.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const tableRows = await queryInterface.sequelize.query(
|
|
||||||
"SELECT to_regclass('public.ui_elements') AS regclass_name;",
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (tableRows[0]?.regclass_name) {
|
|
||||||
await transaction.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await queryInterface.createTable(
|
|
||||||
'ui_elements',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: Sequelize.DataTypes.UUID,
|
|
||||||
defaultValue: Sequelize.DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
element_type: {
|
|
||||||
type: Sequelize.DataTypes.TEXT,
|
|
||||||
allowNull: false,
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: Sequelize.DataTypes.TEXT,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
settings_json: {
|
|
||||||
type: Sequelize.DataTypes.TEXT,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
sort_order: {
|
|
||||||
type: Sequelize.DataTypes.INTEGER,
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: 0,
|
|
||||||
},
|
|
||||||
createdById: {
|
|
||||||
type: Sequelize.DataTypes.UUID,
|
|
||||||
allowNull: true,
|
|
||||||
references: {
|
|
||||||
model: 'users',
|
|
||||||
key: 'id',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
updatedById: {
|
|
||||||
type: Sequelize.DataTypes.UUID,
|
|
||||||
allowNull: true,
|
|
||||||
references: {
|
|
||||||
model: 'users',
|
|
||||||
key: 'id',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
createdAt: { type: Sequelize.DataTypes.DATE },
|
|
||||||
updatedAt: { type: Sequelize.DataTypes.DATE },
|
|
||||||
deletedAt: { type: Sequelize.DataTypes.DATE },
|
|
||||||
importHash: {
|
|
||||||
type: Sequelize.DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
unique: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
await queryInterface.addIndex('ui_elements', ['element_type'], { transaction });
|
|
||||||
await queryInterface.addIndex('ui_elements', ['sort_order'], { transaction });
|
|
||||||
await queryInterface.addIndex('ui_elements', ['deletedAt'], { transaction });
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async down(queryInterface, Sequelize) {
|
|
||||||
const transaction = await queryInterface.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const tableRows = await queryInterface.sequelize.query(
|
|
||||||
"SELECT to_regclass('public.ui_elements') AS regclass_name;",
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!tableRows[0]?.regclass_name) {
|
|
||||||
await transaction.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await queryInterface.dropTable('ui_elements', { transaction });
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@ -1,85 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
async up(queryInterface, Sequelize) {
|
|
||||||
const transaction = await queryInterface.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const tableRows = await queryInterface.sequelize.query(
|
|
||||||
"SELECT to_regclass('public.publish_events') AS regclass_name;",
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!tableRows[0]?.regclass_name) {
|
|
||||||
await transaction.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tableDefinition = await queryInterface.describeTable('publish_events', { transaction });
|
|
||||||
|
|
||||||
if (!tableDefinition.title) {
|
|
||||||
await queryInterface.addColumn(
|
|
||||||
'publish_events',
|
|
||||||
'title',
|
|
||||||
{
|
|
||||||
type: Sequelize.DataTypes.STRING,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tableDefinition.description) {
|
|
||||||
await queryInterface.addColumn(
|
|
||||||
'publish_events',
|
|
||||||
'description',
|
|
||||||
{
|
|
||||||
type: Sequelize.DataTypes.TEXT,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async down(queryInterface, Sequelize) {
|
|
||||||
const transaction = await queryInterface.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
const tableRows = await queryInterface.sequelize.query(
|
|
||||||
"SELECT to_regclass('public.publish_events') AS regclass_name;",
|
|
||||||
{
|
|
||||||
transaction,
|
|
||||||
type: Sequelize.QueryTypes.SELECT,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!tableRows[0]?.regclass_name) {
|
|
||||||
await transaction.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tableDefinition = await queryInterface.describeTable('publish_events', { transaction });
|
|
||||||
|
|
||||||
if (tableDefinition.description) {
|
|
||||||
await queryInterface.removeColumn('publish_events', 'description', { transaction });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tableDefinition.title) {
|
|
||||||
await queryInterface.removeColumn('publish_events', 'title', { transaction });
|
|
||||||
}
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@ -28,23 +28,23 @@ environment: {
|
|||||||
|
|
||||||
path: {
|
path: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
|
validate: {
|
||||||
|
len: { args: [0, 2048], msg: 'Path must be at most 2048 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
ip_address: {
|
ip_address: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
|
validate: {
|
||||||
|
len: { args: [0, 45], msg: 'IP address must be at most 45 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
user_agent: {
|
user_agent: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
|
validate: {
|
||||||
|
len: { args: [0, 1024], msg: 'User agent must be at most 1024 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
accessed_at: {
|
accessed_at: {
|
||||||
|
|||||||
@ -38,30 +38,35 @@ variant_type: {
|
|||||||
|
|
||||||
cdn_url: {
|
cdn_url: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
|
validate: {
|
||||||
|
len: { args: [0, 2048], msg: 'CDN URL must be at most 2048 characters' },
|
||||||
|
isUrlOrEmpty(value) {
|
||||||
|
if (value && value.length > 0 && !/^https?:\/\/.+/.test(value)) {
|
||||||
|
throw new Error('CDN URL must be a valid URL');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
width_px: {
|
width_px: {
|
||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
|
validate: {
|
||||||
|
min: { args: [0], msg: 'Width must be a non-negative integer' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
height_px: {
|
height_px: {
|
||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
|
validate: {
|
||||||
|
min: { args: [0], msg: 'Height must be a non-negative integer' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
size_mb: {
|
size_mb: {
|
||||||
type: DataTypes.DECIMAL,
|
type: DataTypes.DECIMAL,
|
||||||
|
validate: {
|
||||||
|
min: { args: [0], msg: 'Size must be a non-negative number' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
importHash: {
|
importHash: {
|
||||||
|
|||||||
@ -10,9 +10,9 @@ module.exports = function(sequelize, DataTypes) {
|
|||||||
|
|
||||||
name: {
|
name: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
|
validate: {
|
||||||
|
len: { args: [0, 255], msg: 'Asset name must be at most 255 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
asset_type: {
|
asset_type: {
|
||||||
@ -36,6 +36,43 @@ asset_type: {
|
|||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
type: {
|
||||||
|
type: DataTypes.ENUM,
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: "general",
|
||||||
|
|
||||||
|
values: [
|
||||||
|
|
||||||
|
"icon",
|
||||||
|
|
||||||
|
|
||||||
|
"background_image",
|
||||||
|
|
||||||
|
|
||||||
|
"audio",
|
||||||
|
|
||||||
|
|
||||||
|
"video",
|
||||||
|
|
||||||
|
|
||||||
|
"transition",
|
||||||
|
|
||||||
|
|
||||||
|
"logo",
|
||||||
|
|
||||||
|
|
||||||
|
"favicon",
|
||||||
|
|
||||||
|
|
||||||
|
"document",
|
||||||
|
|
||||||
|
|
||||||
|
"general"
|
||||||
|
|
||||||
|
],
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
cdn_url: {
|
cdn_url: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
|
|
||||||
@ -52,9 +89,9 @@ storage_key: {
|
|||||||
|
|
||||||
mime_type: {
|
mime_type: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
|
validate: {
|
||||||
|
is: { args: /^[a-z0-9]+\/[a-z0-9.+-]+$/i, msg: 'Invalid MIME type format' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
size_mb: {
|
size_mb: {
|
||||||
@ -132,6 +169,7 @@ deleted_at_time: {
|
|||||||
indexes: [
|
indexes: [
|
||||||
{ fields: ['projectId'] },
|
{ fields: ['projectId'] },
|
||||||
{ fields: ['asset_type'] },
|
{ fields: ['asset_type'] },
|
||||||
|
{ fields: ['type'] },
|
||||||
{ fields: ['is_public'] },
|
{ fields: ['is_public'] },
|
||||||
{ fields: ['is_deleted'] },
|
{ fields: ['is_deleted'] },
|
||||||
{ fields: ['deletedAt'] },
|
{ fields: ['deletedAt'] },
|
||||||
@ -198,4 +236,3 @@ deleted_at_time: {
|
|||||||
|
|
||||||
return assets;
|
return assets;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -46,9 +46,9 @@ element_type: {
|
|||||||
|
|
||||||
name: {
|
name: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
|
validate: {
|
||||||
|
len: { args: [0, 255], msg: 'Element name must be at most 255 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
sort_order: {
|
sort_order: {
|
||||||
@ -104,17 +104,11 @@ rotation_deg: {
|
|||||||
},
|
},
|
||||||
|
|
||||||
style_json: {
|
style_json: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.JSON,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
content_json: {
|
content_json: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.JSON,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
importHash: {
|
importHash: {
|
||||||
@ -167,6 +161,7 @@ content_json: {
|
|||||||
as: 'page',
|
as: 'page',
|
||||||
foreignKey: {
|
foreignKey: {
|
||||||
name: 'pageId',
|
name: 'pageId',
|
||||||
|
allowNull: false,
|
||||||
},
|
},
|
||||||
constraints: false,
|
constraints: false,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -29,26 +29,27 @@ direction: {
|
|||||||
|
|
||||||
external_url: {
|
external_url: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
|
validate: {
|
||||||
|
len: { args: [0, 2048], msg: 'External URL must be at most 2048 characters' },
|
||||||
|
isUrlOrEmpty(value) {
|
||||||
|
if (value && value.length > 0 && !/^https?:\/\/.+/.test(value)) {
|
||||||
|
throw new Error('External URL must be a valid URL');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
is_active: {
|
is_active: {
|
||||||
type: DataTypes.BOOLEAN,
|
type: DataTypes.BOOLEAN,
|
||||||
|
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
defaultValue: false,
|
defaultValue: false,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
trigger_selector: {
|
trigger_selector: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
|
validate: {
|
||||||
|
len: { args: [0, 1024], msg: 'Trigger selector must be at most 1024 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
importHash: {
|
importHash: {
|
||||||
|
|||||||
@ -10,9 +10,12 @@ module.exports = function(sequelize, DataTypes) {
|
|||||||
|
|
||||||
name: {
|
name: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
|
allowNull: false,
|
||||||
|
unique: true,
|
||||||
|
validate: {
|
||||||
|
notEmpty: { msg: 'Permission name is required' },
|
||||||
|
len: { args: [1, 100], msg: 'Permission name must be between 1 and 100 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
importHash: {
|
importHash: {
|
||||||
|
|||||||
@ -48,23 +48,28 @@ asset_type: {
|
|||||||
|
|
||||||
requested_key: {
|
requested_key: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
|
validate: {
|
||||||
|
len: { args: [0, 1024], msg: 'Requested key must be at most 1024 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
mime_type: {
|
mime_type: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
|
validate: {
|
||||||
|
len: { args: [0, 255], msg: 'MIME type must be at most 255 characters' },
|
||||||
|
isMimeTypeOrEmpty(value) {
|
||||||
|
if (value && value.length > 0 && !/^[\w.-]+\/[\w.+-]+$/.test(value)) {
|
||||||
|
throw new Error('MIME type must be in format type/subtype');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
requested_size_mb: {
|
requested_size_mb: {
|
||||||
type: DataTypes.DECIMAL,
|
type: DataTypes.DECIMAL,
|
||||||
|
validate: {
|
||||||
|
min: { args: [0], msg: 'Requested size must be a non-negative number' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
expires_at: {
|
expires_at: {
|
||||||
|
|||||||
@ -36,9 +36,9 @@ source_key: {
|
|||||||
|
|
||||||
name: {
|
name: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
|
validate: {
|
||||||
|
len: { args: [0, 255], msg: 'Audio track name must be at most 255 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
slug: {
|
slug: {
|
||||||
@ -67,9 +67,10 @@ loop: {
|
|||||||
|
|
||||||
volume: {
|
volume: {
|
||||||
type: DataTypes.DECIMAL,
|
type: DataTypes.DECIMAL,
|
||||||
|
validate: {
|
||||||
|
min: { args: [0], msg: 'Volume must be at least 0' },
|
||||||
|
max: { args: [1], msg: 'Volume must be at most 1' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
sort_order: {
|
sort_order: {
|
||||||
|
|||||||
@ -11,14 +11,21 @@ module.exports = function(sequelize, DataTypes) {
|
|||||||
name: {
|
name: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
|
validate: {
|
||||||
|
notEmpty: { msg: 'Project name is required' },
|
||||||
|
len: { args: [1, 255], msg: 'Project name must be between 1 and 255 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
slug: {
|
slug: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
unique: true,
|
unique: true,
|
||||||
|
validate: {
|
||||||
|
notEmpty: { msg: 'Slug is required' },
|
||||||
|
is: { args: /^[a-z0-9_-]+$/i, msg: 'Slug can only contain letters, numbers, dashes, and underscores' },
|
||||||
|
len: { args: [1, 255], msg: 'Slug must be between 1 and 255 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
description: {
|
description: {
|
||||||
@ -69,17 +76,11 @@ og_image_url: {
|
|||||||
},
|
},
|
||||||
|
|
||||||
theme_config_json: {
|
theme_config_json: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.JSON,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
custom_css_json: {
|
custom_css_json: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.JSON,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
cdn_base_url: {
|
cdn_base_url: {
|
||||||
|
|||||||
@ -11,13 +11,17 @@ module.exports = function(sequelize, DataTypes) {
|
|||||||
title: {
|
title: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
|
validate: {
|
||||||
|
len: { args: [0, 255], msg: 'Title must be at most 255 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
description: {
|
description: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
|
validate: {
|
||||||
|
len: { args: [0, 5000], msg: 'Description must be at most 5000 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
from_environment: {
|
from_environment: {
|
||||||
@ -101,23 +105,23 @@ error_message: {
|
|||||||
|
|
||||||
pages_copied: {
|
pages_copied: {
|
||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
|
validate: {
|
||||||
|
min: { args: [0], msg: 'Pages copied must be a non-negative integer' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
transitions_copied: {
|
transitions_copied: {
|
||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
|
validate: {
|
||||||
|
min: { args: [0], msg: 'Transitions copied must be a non-negative integer' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
audios_copied: {
|
audios_copied: {
|
||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
|
validate: {
|
||||||
|
min: { args: [0], msg: 'Audios copied must be a non-negative integer' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
importHash: {
|
importHash: {
|
||||||
|
|||||||
@ -15,6 +15,9 @@ environment: {
|
|||||||
|
|
||||||
values: [
|
values: [
|
||||||
|
|
||||||
|
"dev",
|
||||||
|
|
||||||
|
|
||||||
"stage",
|
"stage",
|
||||||
|
|
||||||
|
|
||||||
@ -26,23 +29,17 @@ environment: {
|
|||||||
|
|
||||||
cache_version: {
|
cache_version: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
|
validate: {
|
||||||
|
len: { args: [0, 255], msg: 'Cache version must be at most 255 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
manifest_json: {
|
manifest_json: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.JSON,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
asset_list_json: {
|
asset_list_json: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.JSON,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
generated_at: {
|
generated_at: {
|
||||||
|
|||||||
@ -10,9 +10,11 @@ module.exports = function(sequelize, DataTypes) {
|
|||||||
|
|
||||||
name: {
|
name: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
|
allowNull: false,
|
||||||
|
validate: {
|
||||||
|
notEmpty: { msg: 'Role name is required' },
|
||||||
|
len: { args: [1, 100], msg: 'Role name must be between 1 and 100 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
role_customization: {
|
role_customization: {
|
||||||
|
|||||||
@ -37,13 +37,20 @@ source_key: {
|
|||||||
name: {
|
name: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
|
validate: {
|
||||||
|
notEmpty: { msg: 'Page name is required' },
|
||||||
|
len: { args: [1, 255], msg: 'Page name must be between 1 and 255 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
slug: {
|
slug: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
|
validate: {
|
||||||
|
notEmpty: { msg: 'Slug is required' },
|
||||||
|
is: { args: /^[a-z0-9_-]+$/i, msg: 'Slug can only contain letters, numbers, dashes, and underscores' },
|
||||||
|
len: { args: [1, 255], msg: 'Slug must be between 1 and 255 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
sort_order: {
|
sort_order: {
|
||||||
@ -95,10 +102,7 @@ requires_auth: {
|
|||||||
},
|
},
|
||||||
|
|
||||||
ui_schema_json: {
|
ui_schema_json: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.JSON,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
importHash: {
|
importHash: {
|
||||||
|
|||||||
@ -37,13 +37,20 @@ source_key: {
|
|||||||
name: {
|
name: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
|
validate: {
|
||||||
|
notEmpty: { msg: 'Transition name is required' },
|
||||||
|
len: { args: [1, 255], msg: 'Transition name must be between 1 and 255 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
slug: {
|
slug: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
|
validate: {
|
||||||
|
notEmpty: { msg: 'Slug is required' },
|
||||||
|
is: { args: /^[a-z0-9_-]+$/i, msg: 'Slug can only contain letters, numbers, dashes, and underscores' },
|
||||||
|
len: { args: [1, 255], msg: 'Slug must be between 1 and 255 characters' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
video_url: {
|
video_url: {
|
||||||
|
|||||||
@ -1,50 +0,0 @@
|
|||||||
module.exports = function (sequelize, DataTypes) {
|
|
||||||
const ui_elements = sequelize.define(
|
|
||||||
'ui_elements',
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
defaultValue: DataTypes.UUIDV4,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
element_type: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
allowNull: false,
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
},
|
|
||||||
settings_json: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
},
|
|
||||||
sort_order: {
|
|
||||||
type: DataTypes.INTEGER,
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: 0,
|
|
||||||
},
|
|
||||||
importHash: {
|
|
||||||
type: DataTypes.STRING(255),
|
|
||||||
allowNull: true,
|
|
||||||
unique: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
timestamps: true,
|
|
||||||
paranoid: true,
|
|
||||||
freezeTableName: true,
|
|
||||||
indexes: [{ fields: ['element_type'] }, { fields: ['sort_order'] }, { fields: ['deletedAt'] }],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
ui_elements.associate = (db) => {
|
|
||||||
db.ui_elements.belongsTo(db.users, {
|
|
||||||
as: 'createdBy',
|
|
||||||
});
|
|
||||||
|
|
||||||
db.ui_elements.belongsTo(db.users, {
|
|
||||||
as: 'updatedBy',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return ui_elements;
|
|
||||||
};
|
|
||||||
@ -38,7 +38,10 @@ email: {
|
|||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
unique: true,
|
unique: true,
|
||||||
|
validate: {
|
||||||
|
isEmail: { msg: 'Must be a valid email address' },
|
||||||
|
notEmpty: { msg: 'Email is required' },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
disabled: {
|
disabled: {
|
||||||
|
|||||||
@ -68,7 +68,7 @@ await queryInterface.bulkInsert("permissions", [{ id: getId(`READ_API_DOCS`), cr
|
|||||||
await queryInterface.bulkInsert("permissions", [{ id: getId(`CREATE_SEARCH`), createdAt, updatedAt, name: `CREATE_SEARCH`}]);
|
await queryInterface.bulkInsert("permissions", [{ id: getId(`CREATE_SEARCH`), createdAt, updatedAt, name: `CREATE_SEARCH`}]);
|
||||||
|
|
||||||
|
|
||||||
await queryInterface.sequelize.query(`create table "rolesPermissionsPermissions"
|
await queryInterface.sequelize.query(`CREATE TABLE IF NOT EXISTS "rolesPermissionsPermissions"
|
||||||
(
|
(
|
||||||
"createdAt" timestamp with time zone not null,
|
"createdAt" timestamp with time zone not null,
|
||||||
"updatedAt" timestamp with time zone not null,
|
"updatedAt" timestamp with time zone not null,
|
||||||
@ -84,7 +84,7 @@ constraint "rolesPermissionsPermissions_permission_fk"
|
|||||||
);`);
|
);`);
|
||||||
|
|
||||||
await queryInterface.sequelize.query(
|
await queryInterface.sequelize.query(
|
||||||
'create index "rolesPermissionsPermissions_permission_idx" on "rolesPermissionsPermissions" ("permissionId");',
|
'CREATE INDEX IF NOT EXISTS "rolesPermissionsPermissions_permission_idx" ON "rolesPermissionsPermissions" ("permissionId");',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
15
backend/src/db/sync.js
Normal file
15
backend/src/db/sync.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
const db = require('./models');
|
||||||
|
|
||||||
|
async function syncDatabase() {
|
||||||
|
try {
|
||||||
|
console.log('Syncing database...');
|
||||||
|
await db.sequelize.sync({ force: true });
|
||||||
|
console.log('Database synced successfully!');
|
||||||
|
process.exit(0);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error syncing database:', error);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syncDatabase();
|
||||||
101
backend/src/factories/router.factory.js
Normal file
101
backend/src/factories/router.factory.js
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const { wrapAsync, commonErrorHandler } = require('../helpers');
|
||||||
|
const { checkCrudPermissions } = require('../middlewares/check-permissions');
|
||||||
|
const { parse } = require('json2csv');
|
||||||
|
|
||||||
|
const isUuidV4 = (value) =>
|
||||||
|
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
|
||||||
|
|
||||||
|
function createEntityRouter(entityName, Service, DBApi, options = {}) {
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
const permissionEntity = options.permissionEntity || entityName;
|
||||||
|
router.use(checkCrudPermissions(permissionEntity));
|
||||||
|
|
||||||
|
router.post('/', wrapAsync(async (req, res) => {
|
||||||
|
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
||||||
|
const link = new URL(referer);
|
||||||
|
const payload = await Service.create(req.body.data, req.currentUser, true, link.host);
|
||||||
|
res.status(200).send(payload);
|
||||||
|
}));
|
||||||
|
|
||||||
|
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
||||||
|
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
||||||
|
const link = new URL(referer);
|
||||||
|
await Service.bulkImport(req, res, true, link.host);
|
||||||
|
res.status(200).send(true);
|
||||||
|
}));
|
||||||
|
|
||||||
|
router.put('/:id', wrapAsync(async (req, res) => {
|
||||||
|
await Service.update(req.body.data, req.body.id, req.currentUser);
|
||||||
|
res.status(200).send(true);
|
||||||
|
}));
|
||||||
|
|
||||||
|
router.delete('/:id', wrapAsync(async (req, res) => {
|
||||||
|
await Service.remove(req.params.id, req.currentUser);
|
||||||
|
res.status(200).send(true);
|
||||||
|
}));
|
||||||
|
|
||||||
|
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
||||||
|
await Service.deleteByIds(req.body.data, req.currentUser);
|
||||||
|
res.status(200).send(true);
|
||||||
|
}));
|
||||||
|
|
||||||
|
router.get('/', wrapAsync(async (req, res) => {
|
||||||
|
const filetype = req.query.filetype;
|
||||||
|
const currentUser = req.currentUser;
|
||||||
|
const runtimeContext = req.runtimeContext;
|
||||||
|
|
||||||
|
const payload = await DBApi.findAll(req.query, { currentUser, runtimeContext });
|
||||||
|
|
||||||
|
if (filetype === 'csv') {
|
||||||
|
const fields = options.csvFields || DBApi.CSV_FIELDS || ['id', 'createdAt'];
|
||||||
|
const opts = { fields };
|
||||||
|
try {
|
||||||
|
const csv = parse(payload.rows, opts);
|
||||||
|
res.status(200).attachment('export.csv').send(csv);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
res.status(500).send('CSV export error');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.status(200).send(payload);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
router.get('/count', wrapAsync(async (req, res) => {
|
||||||
|
const currentUser = req.currentUser;
|
||||||
|
const runtimeContext = req.runtimeContext;
|
||||||
|
const payload = await DBApi.findAll(req.query, { countOnly: true, currentUser, runtimeContext });
|
||||||
|
res.status(200).send(payload);
|
||||||
|
}));
|
||||||
|
|
||||||
|
router.get('/autocomplete', async (req, res) => {
|
||||||
|
const payload = await DBApi.findAllAutocomplete(
|
||||||
|
req.query.query,
|
||||||
|
req.query.limit,
|
||||||
|
req.query.offset
|
||||||
|
);
|
||||||
|
res.status(200).send(payload);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/:id', wrapAsync(async (req, res) => {
|
||||||
|
if (!isUuidV4(req.params.id)) {
|
||||||
|
return res.status(400).send(`Invalid ${entityName} id`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const runtimeContext = req.runtimeContext;
|
||||||
|
const payload = await DBApi.findBy({ id: req.params.id }, { runtimeContext });
|
||||||
|
res.status(200).send(payload);
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (options.customRoutes) {
|
||||||
|
options.customRoutes(router, Service, DBApi);
|
||||||
|
}
|
||||||
|
|
||||||
|
router.use('/', commonErrorHandler);
|
||||||
|
|
||||||
|
return router;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { createEntityRouter, isUuidV4 };
|
||||||
97
backend/src/factories/service.factory.js
Normal file
97
backend/src/factories/service.factory.js
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
const db = require('../db/models');
|
||||||
|
const processFile = require('../middlewares/upload');
|
||||||
|
const ValidationError = require('../services/notifications/errors/validation');
|
||||||
|
const csv = require('csv-parser');
|
||||||
|
const stream = require('stream');
|
||||||
|
|
||||||
|
function createEntityService(DBApi, options = {}) {
|
||||||
|
const entityName = options.entityName || 'Entity';
|
||||||
|
|
||||||
|
return class GenericService {
|
||||||
|
static async create(data, currentUser) {
|
||||||
|
const transaction = await db.sequelize.transaction();
|
||||||
|
try {
|
||||||
|
const record = await DBApi.create(data, { currentUser, transaction });
|
||||||
|
await transaction.commit();
|
||||||
|
return record;
|
||||||
|
} catch (error) {
|
||||||
|
await transaction.rollback();
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async bulkImport(req, res) {
|
||||||
|
const transaction = await db.sequelize.transaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await processFile(req, res);
|
||||||
|
const bufferStream = new stream.PassThrough();
|
||||||
|
const results = [];
|
||||||
|
|
||||||
|
await bufferStream.end(Buffer.from(req.file.buffer, 'utf-8'));
|
||||||
|
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
bufferStream
|
||||||
|
.pipe(csv())
|
||||||
|
.on('data', (data) => results.push(data))
|
||||||
|
.on('end', () => resolve())
|
||||||
|
.on('error', (error) => reject(error));
|
||||||
|
});
|
||||||
|
|
||||||
|
await DBApi.bulkImport(results, {
|
||||||
|
transaction,
|
||||||
|
ignoreDuplicates: true,
|
||||||
|
validate: true,
|
||||||
|
currentUser: req.currentUser,
|
||||||
|
});
|
||||||
|
|
||||||
|
await transaction.commit();
|
||||||
|
} catch (error) {
|
||||||
|
await transaction.rollback();
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async update(data, id, currentUser) {
|
||||||
|
const transaction = await db.sequelize.transaction();
|
||||||
|
try {
|
||||||
|
const record = await DBApi.findBy({ id }, { transaction });
|
||||||
|
|
||||||
|
if (!record) {
|
||||||
|
throw new ValidationError(`${entityName}NotFound`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const updated = await DBApi.update(id, data, { currentUser, transaction });
|
||||||
|
await transaction.commit();
|
||||||
|
return updated;
|
||||||
|
} catch (error) {
|
||||||
|
await transaction.rollback();
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async deleteByIds(ids, currentUser) {
|
||||||
|
const transaction = await db.sequelize.transaction();
|
||||||
|
try {
|
||||||
|
await DBApi.deleteByIds(ids, { currentUser, transaction });
|
||||||
|
await transaction.commit();
|
||||||
|
} catch (error) {
|
||||||
|
await transaction.rollback();
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async remove(id, currentUser) {
|
||||||
|
const transaction = await db.sequelize.transaction();
|
||||||
|
try {
|
||||||
|
await DBApi.remove(id, { currentUser, transaction });
|
||||||
|
await transaction.commit();
|
||||||
|
} catch (error) {
|
||||||
|
await transaction.rollback();
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { createEntityService };
|
||||||
@ -9,6 +9,7 @@ const bodyParser = require('body-parser');
|
|||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
const swaggerUI = require('swagger-ui-express');
|
const swaggerUI = require('swagger-ui-express');
|
||||||
const swaggerJsDoc = require('swagger-jsdoc');
|
const swaggerJsDoc = require('swagger-jsdoc');
|
||||||
|
const { logger, requestLogger } = require('./utils/logger');
|
||||||
|
|
||||||
const authRoutes = require('./routes/auth');
|
const authRoutes = require('./routes/auth');
|
||||||
const fileRoutes = require('./routes/file');
|
const fileRoutes = require('./routes/file');
|
||||||
@ -39,7 +40,6 @@ const presigned_url_requestsRoutes = require('./routes/presigned_url_requests');
|
|||||||
const tour_pagesRoutes = require('./routes/tour_pages');
|
const tour_pagesRoutes = require('./routes/tour_pages');
|
||||||
|
|
||||||
const page_elementsRoutes = require('./routes/page_elements');
|
const page_elementsRoutes = require('./routes/page_elements');
|
||||||
const ui_elementsRoutes = require('./routes/ui_elements');
|
|
||||||
|
|
||||||
const page_linksRoutes = require('./routes/page_links');
|
const page_linksRoutes = require('./routes/page_links');
|
||||||
|
|
||||||
@ -120,6 +120,7 @@ require('./auth/auth');
|
|||||||
|
|
||||||
app.use(bodyParser.json({ limit: '1mb' }));
|
app.use(bodyParser.json({ limit: '1mb' }));
|
||||||
app.use(bodyParser.urlencoded({ extended: true, limit: '1mb' }));
|
app.use(bodyParser.urlencoded({ extended: true, limit: '1mb' }));
|
||||||
|
app.use(requestLogger);
|
||||||
app.use(runtimeContextMiddleware);
|
app.use(runtimeContextMiddleware);
|
||||||
const jwtAuth = passport.authenticate('jwt', { session: false });
|
const jwtAuth = passport.authenticate('jwt', { session: false });
|
||||||
|
|
||||||
@ -137,6 +138,29 @@ const requireRuntimeReadOrAuth = (req, res, next) => {
|
|||||||
return jwtAuth(req, res, next);
|
return jwtAuth(req, res, next);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Health check endpoint (no auth required)
|
||||||
|
app.get('/api/health', async (req, res) => {
|
||||||
|
const db = require('./db/models');
|
||||||
|
const health = {
|
||||||
|
status: 'ok',
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
uptime: process.uptime(),
|
||||||
|
environment: process.env.NODE_ENV || 'development',
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await db.sequelize.authenticate();
|
||||||
|
health.database = 'connected';
|
||||||
|
} catch (error) {
|
||||||
|
health.status = 'degraded';
|
||||||
|
health.database = 'disconnected';
|
||||||
|
health.databaseError = error.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusCode = health.status === 'ok' ? 200 : 503;
|
||||||
|
res.status(statusCode).json(health);
|
||||||
|
});
|
||||||
|
|
||||||
app.use('/api/auth', authRoutes);
|
app.use('/api/auth', authRoutes);
|
||||||
app.use('/api/file', fileRoutes);
|
app.use('/api/file', fileRoutes);
|
||||||
app.use('/api/pexels', pexelsRoutes);
|
app.use('/api/pexels', pexelsRoutes);
|
||||||
@ -172,7 +196,6 @@ app.use('/api/presigned_url_requests', jwtAuth, presigned_url_requestsRoutes);
|
|||||||
mountRuntimeEntityRoute('/api/tour_pages', 'tour_pages', tour_pagesRoutes);
|
mountRuntimeEntityRoute('/api/tour_pages', 'tour_pages', tour_pagesRoutes);
|
||||||
|
|
||||||
mountRuntimeEntityRoute('/api/page_elements', 'page_elements', page_elementsRoutes);
|
mountRuntimeEntityRoute('/api/page_elements', 'page_elements', page_elementsRoutes);
|
||||||
app.use('/api/ui-elements', jwtAuth, ui_elementsRoutes);
|
|
||||||
|
|
||||||
mountRuntimeEntityRoute('/api/page_links', 'page_links', page_linksRoutes);
|
mountRuntimeEntityRoute('/api/page_links', 'page_links', page_linksRoutes);
|
||||||
|
|
||||||
@ -227,7 +250,7 @@ if (fs.existsSync(publicDir)) {
|
|||||||
const PORT = process.env.NODE_ENV === 'dev_stage' ? 3000 : 8080;
|
const PORT = process.env.NODE_ENV === 'dev_stage' ? 3000 : 8080;
|
||||||
|
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
console.log(`Listening on port ${PORT}`);
|
logger.info({ port: PORT, env: process.env.NODE_ENV || 'development' }, 'Server started');
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = app;
|
module.exports = app;
|
||||||
|
|||||||
103
backend/src/middlewares/validate.js
Normal file
103
backend/src/middlewares/validate.js
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
const { body, param, query, validationResult } = require('express-validator');
|
||||||
|
|
||||||
|
const handleValidationErrors = (req, res, next) => {
|
||||||
|
const errors = validationResult(req);
|
||||||
|
if (!errors.isEmpty()) {
|
||||||
|
return res.status(400).json({
|
||||||
|
error: 'Validation failed',
|
||||||
|
details: errors.array().map(err => ({
|
||||||
|
field: err.path,
|
||||||
|
message: err.msg,
|
||||||
|
value: err.value,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
|
||||||
|
const validators = {
|
||||||
|
uuid: (field, location = 'param') => {
|
||||||
|
const validator = location === 'param' ? param(field) : body(field);
|
||||||
|
return validator.isUUID().withMessage(`${field} must be a valid UUID`);
|
||||||
|
},
|
||||||
|
|
||||||
|
requiredString: (field, min = 1, max = 255) =>
|
||||||
|
body(field)
|
||||||
|
.trim()
|
||||||
|
.notEmpty().withMessage(`${field} is required`)
|
||||||
|
.isLength({ min, max }).withMessage(`${field} must be ${min}-${max} characters`),
|
||||||
|
|
||||||
|
optionalString: (field, max = 255) =>
|
||||||
|
body(field)
|
||||||
|
.optional()
|
||||||
|
.trim()
|
||||||
|
.isLength({ max }).withMessage(`${field} must be at most ${max} characters`),
|
||||||
|
|
||||||
|
slug: (field) =>
|
||||||
|
body(field)
|
||||||
|
.optional()
|
||||||
|
.trim()
|
||||||
|
.matches(/^[a-z0-9_-]+$/i).withMessage(`${field} can only contain letters, numbers, dashes, underscores`),
|
||||||
|
|
||||||
|
email: (field) =>
|
||||||
|
body(field)
|
||||||
|
.trim()
|
||||||
|
.isEmail().withMessage('Must be a valid email')
|
||||||
|
.normalizeEmail(),
|
||||||
|
|
||||||
|
optionalEmail: (field) =>
|
||||||
|
body(field)
|
||||||
|
.optional()
|
||||||
|
.trim()
|
||||||
|
.isEmail().withMessage('Must be a valid email')
|
||||||
|
.normalizeEmail(),
|
||||||
|
|
||||||
|
enum: (field, values) =>
|
||||||
|
body(field)
|
||||||
|
.optional()
|
||||||
|
.isIn(values).withMessage(`${field} must be one of: ${values.join(', ')}`),
|
||||||
|
|
||||||
|
boolean: (field) =>
|
||||||
|
body(field)
|
||||||
|
.optional()
|
||||||
|
.isBoolean().withMessage(`${field} must be a boolean`),
|
||||||
|
|
||||||
|
integer: (field, min, max) => {
|
||||||
|
let validator = body(field).optional().isInt();
|
||||||
|
if (min !== undefined) validator = validator.custom(val => val >= min).withMessage(`${field} must be at least ${min}`);
|
||||||
|
if (max !== undefined) validator = validator.custom(val => val <= max).withMessage(`${field} must be at most ${max}`);
|
||||||
|
return validator;
|
||||||
|
},
|
||||||
|
|
||||||
|
pagination: () => [
|
||||||
|
query('page').optional().isInt({ min: 0 }).toInt(),
|
||||||
|
query('limit').optional().isInt({ min: 1, max: 100 }).toInt(),
|
||||||
|
],
|
||||||
|
|
||||||
|
url: (field) =>
|
||||||
|
body(field)
|
||||||
|
.optional()
|
||||||
|
.trim()
|
||||||
|
.isURL().withMessage(`${field} must be a valid URL`),
|
||||||
|
};
|
||||||
|
|
||||||
|
function createEntityValidation(entityConfig = {}) {
|
||||||
|
const { fields = [], requiredFields = [] } = entityConfig;
|
||||||
|
|
||||||
|
const fieldValidators = fields.map(field => {
|
||||||
|
if (requiredFields.includes(field.name)) {
|
||||||
|
return validators.requiredString(`data.${field.name}`, field.min || 1, field.max || 255);
|
||||||
|
}
|
||||||
|
return validators.optionalString(`data.${field.name}`, field.max || 255);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
create: [...fieldValidators, handleValidationErrors],
|
||||||
|
update: [validators.uuid('id'), ...fieldValidators, handleValidationErrors],
|
||||||
|
delete: [validators.uuid('id'), handleValidationErrors],
|
||||||
|
get: [validators.uuid('id'), handleValidationErrors],
|
||||||
|
list: [...validators.pagination(), handleValidationErrors],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { handleValidationErrors, validators, createEntityValidation };
|
||||||
@ -1,22 +1,6 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const Access_logsService = require('../services/access_logs');
|
const Access_logsService = require('../services/access_logs');
|
||||||
const Access_logsDBApi = require('../db/api/access_logs');
|
const Access_logsDBApi = require('../db/api/access_logs');
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
const { createEntityRouter } = require('../factories/router.factory');
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('access_logs'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
@ -25,20 +9,12 @@ router.use(checkCrudPermissions('access_logs'));
|
|||||||
* Access_logs:
|
* Access_logs:
|
||||||
* type: object
|
* type: object
|
||||||
* properties:
|
* properties:
|
||||||
|
|
||||||
* path:
|
* path:
|
||||||
* type: string
|
* type: string
|
||||||
* default: path
|
|
||||||
* ip_address:
|
* ip_address:
|
||||||
* type: string
|
* type: string
|
||||||
* default: ip_address
|
|
||||||
* user_agent:
|
* user_agent:
|
||||||
* type: string
|
* type: string
|
||||||
* default: user_agent
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,389 +24,118 @@ router.use(checkCrudPermissions('access_logs'));
|
|||||||
* description: The Access_logs managing API
|
* description: The Access_logs managing API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/access_logs:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Access_logs]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Access_logs"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Access_logs"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Access_logsService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Access_logs]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Access_logs"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Access_logs"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Access_logsService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/access_logs/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Access_logs]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Access_logs"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Access_logs"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Access_logsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/access_logs/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Access_logs]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Access_logs"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Access_logsService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/access_logs/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Access_logs]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Access_logs"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await Access_logsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/access_logs:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Access_logs]
|
|
||||||
* summary: Get all access_logs
|
|
||||||
* description: Get all access_logs
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Access_logs list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Access_logs"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Access_logsDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','path','ip_address','user_agent',
|
|
||||||
|
|
||||||
|
|
||||||
'accessed_at',
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/access_logs/count:
|
* /api/access_logs:
|
||||||
* get:
|
* post:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Access_logs]
|
* tags: [Access_logs]
|
||||||
* summary: Count all access_logs
|
* summary: Add new item
|
||||||
* description: Count all access_logs
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* data:
|
||||||
|
* type: object
|
||||||
|
* $ref: "#/components/schemas/Access_logs"
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Access_logs count successfully received
|
* description: The item was successfully added
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Access_logs"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Access_logsDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/access_logs/autocomplete:
|
|
||||||
* get:
|
* get:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Access_logs]
|
* tags: [Access_logs]
|
||||||
* summary: Find all access_logs that match search criteria
|
* summary: Get all access_logs
|
||||||
* description: Find all access_logs that match search criteria
|
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Access_logs list successfully received
|
* description: Access_logs list successfully received
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Access_logs"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
*/
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await Access_logsDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/access_logs/{id}:
|
* /api/access_logs/{id}:
|
||||||
* get:
|
* put:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Access_logs]
|
* tags: [Access_logs]
|
||||||
* summary: Get selected item
|
* summary: Update the selected item
|
||||||
* description: Get selected item
|
* parameters:
|
||||||
* parameters:
|
* - in: path
|
||||||
* - in: path
|
* name: id
|
||||||
* name: id
|
* required: true
|
||||||
* description: ID of item to get
|
* schema:
|
||||||
* required: true
|
* type: string
|
||||||
* schema:
|
* requestBody:
|
||||||
* type: string
|
* required: true
|
||||||
* responses:
|
* content:
|
||||||
* 200:
|
* application/json:
|
||||||
* description: Selected item successfully received
|
* schema:
|
||||||
* content:
|
* properties:
|
||||||
* application/json:
|
* id:
|
||||||
* schema:
|
* type: string
|
||||||
* $ref: "#/components/schemas/Access_logs"
|
* data:
|
||||||
* 400:
|
* type: object
|
||||||
* description: Invalid ID supplied
|
* $ref: "#/components/schemas/Access_logs"
|
||||||
* 401:
|
* responses:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* 200:
|
||||||
* 404:
|
* description: The item was successfully updated
|
||||||
* description: Item not found
|
* 401:
|
||||||
* 500:
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* description: Some server error
|
* 404:
|
||||||
*/
|
* description: Item not found
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
* 500:
|
||||||
const payload = await Access_logsDBApi.findBy(
|
* description: Some server error
|
||||||
{ id: req.params.id },
|
* delete:
|
||||||
);
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Access_logs]
|
||||||
|
* summary: Delete the selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item was successfully deleted
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Access_logs]
|
||||||
|
* summary: Get selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Selected item successfully received
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = createEntityRouter('access_logs', Access_logsService, Access_logsDBApi);
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|||||||
@ -1,22 +1,6 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const Asset_variantsService = require('../services/asset_variants');
|
const Asset_variantsService = require('../services/asset_variants');
|
||||||
const Asset_variantsDBApi = require('../db/api/asset_variants');
|
const Asset_variantsDBApi = require('../db/api/asset_variants');
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
const { createEntityRouter } = require('../factories/router.factory');
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('asset_variants'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
@ -25,23 +9,14 @@ router.use(checkCrudPermissions('asset_variants'));
|
|||||||
* Asset_variants:
|
* Asset_variants:
|
||||||
* type: object
|
* type: object
|
||||||
* properties:
|
* properties:
|
||||||
|
|
||||||
* cdn_url:
|
* cdn_url:
|
||||||
* type: string
|
* type: string
|
||||||
* default: cdn_url
|
|
||||||
|
|
||||||
* width_px:
|
* width_px:
|
||||||
* type: integer
|
* type: integer
|
||||||
* format: int64
|
|
||||||
* height_px:
|
* height_px:
|
||||||
* type: integer
|
* type: integer
|
||||||
* format: int64
|
|
||||||
|
|
||||||
* size_mb:
|
* size_mb:
|
||||||
* type: integer
|
* type: number
|
||||||
* format: int64
|
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,389 +26,118 @@ router.use(checkCrudPermissions('asset_variants'));
|
|||||||
* description: The Asset_variants managing API
|
* description: The Asset_variants managing API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/asset_variants:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Asset_variants]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Asset_variants"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Asset_variants"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Asset_variantsService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Asset_variants]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Asset_variants"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Asset_variants"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Asset_variantsService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/asset_variants/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Asset_variants]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Asset_variants"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Asset_variants"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Asset_variantsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/asset_variants/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Asset_variants]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Asset_variants"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Asset_variantsService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/asset_variants/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Asset_variants]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Asset_variants"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await Asset_variantsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/asset_variants:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Asset_variants]
|
|
||||||
* summary: Get all asset_variants
|
|
||||||
* description: Get all asset_variants
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Asset_variants list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Asset_variants"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Asset_variantsDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','cdn_url',
|
|
||||||
'width_px','height_px',
|
|
||||||
'size_mb',
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/asset_variants/count:
|
* /api/asset_variants:
|
||||||
* get:
|
* post:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Asset_variants]
|
* tags: [Asset_variants]
|
||||||
* summary: Count all asset_variants
|
* summary: Add new item
|
||||||
* description: Count all asset_variants
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* data:
|
||||||
|
* type: object
|
||||||
|
* $ref: "#/components/schemas/Asset_variants"
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Asset_variants count successfully received
|
* description: The item was successfully added
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Asset_variants"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Asset_variantsDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/asset_variants/autocomplete:
|
|
||||||
* get:
|
* get:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Asset_variants]
|
* tags: [Asset_variants]
|
||||||
* summary: Find all asset_variants that match search criteria
|
* summary: Get all asset variants
|
||||||
* description: Find all asset_variants that match search criteria
|
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Asset_variants list successfully received
|
* description: Asset_variants list successfully received
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Asset_variants"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
*/
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await Asset_variantsDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/asset_variants/{id}:
|
* /api/asset_variants/{id}:
|
||||||
* get:
|
* put:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Asset_variants]
|
* tags: [Asset_variants]
|
||||||
* summary: Get selected item
|
* summary: Update the selected item
|
||||||
* description: Get selected item
|
* parameters:
|
||||||
* parameters:
|
* - in: path
|
||||||
* - in: path
|
* name: id
|
||||||
* name: id
|
* required: true
|
||||||
* description: ID of item to get
|
* schema:
|
||||||
* required: true
|
* type: string
|
||||||
* schema:
|
* requestBody:
|
||||||
* type: string
|
* required: true
|
||||||
* responses:
|
* content:
|
||||||
* 200:
|
* application/json:
|
||||||
* description: Selected item successfully received
|
* schema:
|
||||||
* content:
|
* properties:
|
||||||
* application/json:
|
* id:
|
||||||
* schema:
|
* type: string
|
||||||
* $ref: "#/components/schemas/Asset_variants"
|
* data:
|
||||||
* 400:
|
* type: object
|
||||||
* description: Invalid ID supplied
|
* $ref: "#/components/schemas/Asset_variants"
|
||||||
* 401:
|
* responses:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* 200:
|
||||||
* 404:
|
* description: The item was successfully updated
|
||||||
* description: Item not found
|
* 401:
|
||||||
* 500:
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* description: Some server error
|
* 404:
|
||||||
*/
|
* description: Item not found
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
* 500:
|
||||||
const payload = await Asset_variantsDBApi.findBy(
|
* description: Some server error
|
||||||
{ id: req.params.id },
|
* delete:
|
||||||
);
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Asset_variants]
|
||||||
|
* summary: Delete the selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item was successfully deleted
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Asset_variants]
|
||||||
|
* summary: Get selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Selected item successfully received
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = createEntityRouter('asset_variants', Asset_variantsService, Asset_variantsDBApi);
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|||||||
@ -1,22 +1,6 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const AssetsService = require('../services/assets');
|
const AssetsService = require('../services/assets');
|
||||||
const AssetsDBApi = require('../db/api/assets');
|
const AssetsDBApi = require('../db/api/assets');
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
const { createEntityRouter } = require('../factories/router.factory');
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('assets'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
@ -25,38 +9,24 @@ router.use(checkCrudPermissions('assets'));
|
|||||||
* Assets:
|
* Assets:
|
||||||
* type: object
|
* type: object
|
||||||
* properties:
|
* properties:
|
||||||
|
|
||||||
* name:
|
* name:
|
||||||
* type: string
|
* type: string
|
||||||
* default: name
|
|
||||||
* cdn_url:
|
* cdn_url:
|
||||||
* type: string
|
* type: string
|
||||||
* default: cdn_url
|
|
||||||
* storage_key:
|
* storage_key:
|
||||||
* type: string
|
* type: string
|
||||||
* default: storage_key
|
|
||||||
* mime_type:
|
* mime_type:
|
||||||
* type: string
|
* type: string
|
||||||
* default: mime_type
|
|
||||||
* checksum:
|
* checksum:
|
||||||
* type: string
|
* type: string
|
||||||
* default: checksum
|
|
||||||
|
|
||||||
* width_px:
|
* width_px:
|
||||||
* type: integer
|
* type: integer
|
||||||
* format: int64
|
|
||||||
* height_px:
|
* height_px:
|
||||||
* type: integer
|
* type: integer
|
||||||
* format: int64
|
|
||||||
|
|
||||||
* size_mb:
|
* size_mb:
|
||||||
* type: integer
|
* type: number
|
||||||
* format: int64
|
|
||||||
* duration_sec:
|
* duration_sec:
|
||||||
* type: integer
|
* type: number
|
||||||
* format: int64
|
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,389 +36,118 @@ router.use(checkCrudPermissions('assets'));
|
|||||||
* description: The Assets managing API
|
* description: The Assets managing API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/assets:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Assets]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Assets"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Assets"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await AssetsService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Assets]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Assets"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Assets"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await AssetsService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/assets/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Assets]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Assets"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Assets"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await AssetsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/assets/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Assets]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Assets"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await AssetsService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/assets/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Assets]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Assets"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await AssetsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/assets:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Assets]
|
|
||||||
* summary: Get all assets
|
|
||||||
* description: Get all assets
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Assets list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Assets"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await AssetsDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','name','cdn_url','storage_key','mime_type','checksum',
|
|
||||||
'width_px','height_px',
|
|
||||||
'size_mb','duration_sec',
|
|
||||||
'deleted_at_time',
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/assets/count:
|
* /api/assets:
|
||||||
* get:
|
* post:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Assets]
|
* tags: [Assets]
|
||||||
* summary: Count all assets
|
* summary: Add new item
|
||||||
* description: Count all assets
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* data:
|
||||||
|
* type: object
|
||||||
|
* $ref: "#/components/schemas/Assets"
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Assets count successfully received
|
* description: The item was successfully added
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Assets"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await AssetsDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/assets/autocomplete:
|
|
||||||
* get:
|
* get:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Assets]
|
* tags: [Assets]
|
||||||
* summary: Find all assets that match search criteria
|
* summary: Get all assets
|
||||||
* description: Find all assets that match search criteria
|
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Assets list successfully received
|
* description: Assets list successfully received
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Assets"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
*/
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await AssetsDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/assets/{id}:
|
* /api/assets/{id}:
|
||||||
* get:
|
* put:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Assets]
|
* tags: [Assets]
|
||||||
* summary: Get selected item
|
* summary: Update the selected item
|
||||||
* description: Get selected item
|
* parameters:
|
||||||
* parameters:
|
* - in: path
|
||||||
* - in: path
|
* name: id
|
||||||
* name: id
|
* required: true
|
||||||
* description: ID of item to get
|
* schema:
|
||||||
* required: true
|
* type: string
|
||||||
* schema:
|
* requestBody:
|
||||||
* type: string
|
* required: true
|
||||||
* responses:
|
* content:
|
||||||
* 200:
|
* application/json:
|
||||||
* description: Selected item successfully received
|
* schema:
|
||||||
* content:
|
* properties:
|
||||||
* application/json:
|
* id:
|
||||||
* schema:
|
* type: string
|
||||||
* $ref: "#/components/schemas/Assets"
|
* data:
|
||||||
* 400:
|
* type: object
|
||||||
* description: Invalid ID supplied
|
* $ref: "#/components/schemas/Assets"
|
||||||
* 401:
|
* responses:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* 200:
|
||||||
* 404:
|
* description: The item was successfully updated
|
||||||
* description: Item not found
|
* 401:
|
||||||
* 500:
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* description: Some server error
|
* 404:
|
||||||
*/
|
* description: Item not found
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
* 500:
|
||||||
const payload = await AssetsDBApi.findBy(
|
* description: Some server error
|
||||||
{ id: req.params.id },
|
* delete:
|
||||||
);
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Assets]
|
||||||
|
* summary: Delete the selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item was successfully deleted
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Assets]
|
||||||
|
* summary: Get selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Selected item successfully received
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = createEntityRouter('assets', AssetsService, AssetsDBApi);
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|||||||
@ -1,22 +1,6 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const Page_elementsService = require('../services/page_elements');
|
const Page_elementsService = require('../services/page_elements');
|
||||||
const Page_elementsDBApi = require('../db/api/page_elements');
|
const Page_elementsDBApi = require('../db/api/page_elements');
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
const { createEntityRouter } = require('../factories/router.factory');
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('page_elements'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
@ -25,38 +9,24 @@ router.use(checkCrudPermissions('page_elements'));
|
|||||||
* Page_elements:
|
* Page_elements:
|
||||||
* type: object
|
* type: object
|
||||||
* properties:
|
* properties:
|
||||||
|
|
||||||
* name:
|
* name:
|
||||||
* type: string
|
* type: string
|
||||||
* default: name
|
|
||||||
* style_json:
|
* style_json:
|
||||||
* type: string
|
* type: string
|
||||||
* default: style_json
|
|
||||||
* content_json:
|
* content_json:
|
||||||
* type: string
|
* type: string
|
||||||
* default: content_json
|
|
||||||
|
|
||||||
* sort_order:
|
* sort_order:
|
||||||
* type: integer
|
* type: integer
|
||||||
* format: int64
|
|
||||||
|
|
||||||
* x_percent:
|
* x_percent:
|
||||||
* type: integer
|
* type: number
|
||||||
* format: int64
|
|
||||||
* y_percent:
|
* y_percent:
|
||||||
* type: integer
|
* type: number
|
||||||
* format: int64
|
|
||||||
* width_percent:
|
* width_percent:
|
||||||
* type: integer
|
* type: number
|
||||||
* format: int64
|
|
||||||
* height_percent:
|
* height_percent:
|
||||||
* type: integer
|
* type: number
|
||||||
* format: int64
|
|
||||||
* rotation_deg:
|
* rotation_deg:
|
||||||
* type: integer
|
* type: number
|
||||||
* format: int64
|
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,393 +36,118 @@ router.use(checkCrudPermissions('page_elements'));
|
|||||||
* description: The Page_elements managing API
|
* description: The Page_elements managing API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_elements:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_elements]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Page_elements"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Page_elements"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Page_elementsService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_elements]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Page_elements"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Page_elements"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Page_elementsService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_elements/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_elements]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Page_elements"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Page_elements"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Page_elementsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_elements/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_elements]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Page_elements"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Page_elementsService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_elements/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_elements]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Page_elements"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await Page_elementsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_elements:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_elements]
|
|
||||||
* summary: Get all page_elements
|
|
||||||
* description: Get all page_elements
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Page_elements list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Page_elements"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const runtimeContext = req.runtimeContext;
|
|
||||||
const payload = await Page_elementsDBApi.findAll(
|
|
||||||
req.query, { currentUser, runtimeContext }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','name','style_json','content_json',
|
|
||||||
'sort_order',
|
|
||||||
'x_percent','y_percent','width_percent','height_percent','rotation_deg',
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/page_elements/count:
|
* /api/page_elements:
|
||||||
* get:
|
* post:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Page_elements]
|
* tags: [Page_elements]
|
||||||
* summary: Count all page_elements
|
* summary: Add new item
|
||||||
* description: Count all page_elements
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* data:
|
||||||
|
* type: object
|
||||||
|
* $ref: "#/components/schemas/Page_elements"
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Page_elements count successfully received
|
* description: The item was successfully added
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Page_elements"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const runtimeContext = req.runtimeContext;
|
|
||||||
const payload = await Page_elementsDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser, runtimeContext }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_elements/autocomplete:
|
|
||||||
* get:
|
* get:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Page_elements]
|
* tags: [Page_elements]
|
||||||
* summary: Find all page_elements that match search criteria
|
* summary: Get all page_elements
|
||||||
* description: Find all page_elements that match search criteria
|
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Page_elements list successfully received
|
* description: Page_elements list successfully received
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Page_elements"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
*/
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await Page_elementsDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/page_elements/{id}:
|
* /api/page_elements/{id}:
|
||||||
* get:
|
* put:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Page_elements]
|
* tags: [Page_elements]
|
||||||
* summary: Get selected item
|
* summary: Update the selected item
|
||||||
* description: Get selected item
|
* parameters:
|
||||||
* parameters:
|
* - in: path
|
||||||
* - in: path
|
* name: id
|
||||||
* name: id
|
* required: true
|
||||||
* description: ID of item to get
|
* schema:
|
||||||
* required: true
|
* type: string
|
||||||
* schema:
|
* requestBody:
|
||||||
* type: string
|
* required: true
|
||||||
* responses:
|
* content:
|
||||||
* 200:
|
* application/json:
|
||||||
* description: Selected item successfully received
|
* schema:
|
||||||
* content:
|
* properties:
|
||||||
* application/json:
|
* id:
|
||||||
* schema:
|
* type: string
|
||||||
* $ref: "#/components/schemas/Page_elements"
|
* data:
|
||||||
* 400:
|
* type: object
|
||||||
* description: Invalid ID supplied
|
* $ref: "#/components/schemas/Page_elements"
|
||||||
* 401:
|
* responses:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* 200:
|
||||||
* 404:
|
* description: The item was successfully updated
|
||||||
* description: Item not found
|
* 401:
|
||||||
* 500:
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* description: Some server error
|
* 404:
|
||||||
*/
|
* description: Item not found
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
* 500:
|
||||||
const runtimeContext = req.runtimeContext;
|
* description: Some server error
|
||||||
const payload = await Page_elementsDBApi.findBy(
|
* delete:
|
||||||
{ id: req.params.id },
|
* security:
|
||||||
{ runtimeContext },
|
* - bearerAuth: []
|
||||||
);
|
* tags: [Page_elements]
|
||||||
|
* summary: Delete the selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item was successfully deleted
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Page_elements]
|
||||||
|
* summary: Get selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Selected item successfully received
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = createEntityRouter('page_elements', Page_elementsService, Page_elementsDBApi);
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|||||||
@ -1,22 +1,6 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const Page_linksService = require('../services/page_links');
|
const Page_linksService = require('../services/page_links');
|
||||||
const Page_linksDBApi = require('../db/api/page_links');
|
const Page_linksDBApi = require('../db/api/page_links');
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
const { createEntityRouter } = require('../factories/router.factory');
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('page_links'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
@ -25,17 +9,10 @@ router.use(checkCrudPermissions('page_links'));
|
|||||||
* Page_links:
|
* Page_links:
|
||||||
* type: object
|
* type: object
|
||||||
* properties:
|
* properties:
|
||||||
|
|
||||||
* external_url:
|
* external_url:
|
||||||
* type: string
|
* type: string
|
||||||
* default: external_url
|
|
||||||
* trigger_selector:
|
* trigger_selector:
|
||||||
* type: string
|
* type: string
|
||||||
* default: trigger_selector
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,393 +22,118 @@ router.use(checkCrudPermissions('page_links'));
|
|||||||
* description: The Page_links managing API
|
* description: The Page_links managing API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_links:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_links]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Page_links"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Page_links"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Page_linksService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_links]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Page_links"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Page_links"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Page_linksService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_links/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_links]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Page_links"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Page_links"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Page_linksService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_links/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_links]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Page_links"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Page_linksService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_links/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_links]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Page_links"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await Page_linksService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_links:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Page_links]
|
|
||||||
* summary: Get all page_links
|
|
||||||
* description: Get all page_links
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Page_links list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Page_links"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const runtimeContext = req.runtimeContext;
|
|
||||||
const payload = await Page_linksDBApi.findAll(
|
|
||||||
req.query, { currentUser, runtimeContext }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','external_url','trigger_selector',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/page_links/count:
|
* /api/page_links:
|
||||||
* get:
|
* post:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Page_links]
|
* tags: [Page_links]
|
||||||
* summary: Count all page_links
|
* summary: Add new item
|
||||||
* description: Count all page_links
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* data:
|
||||||
|
* type: object
|
||||||
|
* $ref: "#/components/schemas/Page_links"
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Page_links count successfully received
|
* description: The item was successfully added
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Page_links"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const runtimeContext = req.runtimeContext;
|
|
||||||
const payload = await Page_linksDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser, runtimeContext }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/page_links/autocomplete:
|
|
||||||
* get:
|
* get:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Page_links]
|
* tags: [Page_links]
|
||||||
* summary: Find all page_links that match search criteria
|
* summary: Get all page_links
|
||||||
* description: Find all page_links that match search criteria
|
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Page_links list successfully received
|
* description: Page_links list successfully received
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Page_links"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
*/
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await Page_linksDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/page_links/{id}:
|
* /api/page_links/{id}:
|
||||||
* get:
|
* put:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Page_links]
|
* tags: [Page_links]
|
||||||
* summary: Get selected item
|
* summary: Update the selected item
|
||||||
* description: Get selected item
|
* parameters:
|
||||||
* parameters:
|
* - in: path
|
||||||
* - in: path
|
* name: id
|
||||||
* name: id
|
* required: true
|
||||||
* description: ID of item to get
|
* schema:
|
||||||
* required: true
|
* type: string
|
||||||
* schema:
|
* requestBody:
|
||||||
* type: string
|
* required: true
|
||||||
* responses:
|
* content:
|
||||||
* 200:
|
* application/json:
|
||||||
* description: Selected item successfully received
|
* schema:
|
||||||
* content:
|
* properties:
|
||||||
* application/json:
|
* id:
|
||||||
* schema:
|
* type: string
|
||||||
* $ref: "#/components/schemas/Page_links"
|
* data:
|
||||||
* 400:
|
* type: object
|
||||||
* description: Invalid ID supplied
|
* $ref: "#/components/schemas/Page_links"
|
||||||
* 401:
|
* responses:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* 200:
|
||||||
* 404:
|
* description: The item was successfully updated
|
||||||
* description: Item not found
|
* 401:
|
||||||
* 500:
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* description: Some server error
|
* 404:
|
||||||
*/
|
* description: Item not found
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
* 500:
|
||||||
const runtimeContext = req.runtimeContext;
|
* description: Some server error
|
||||||
const payload = await Page_linksDBApi.findBy(
|
* delete:
|
||||||
{ id: req.params.id },
|
* security:
|
||||||
{ runtimeContext },
|
* - bearerAuth: []
|
||||||
);
|
* tags: [Page_links]
|
||||||
|
* summary: Delete the selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item was successfully deleted
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Page_links]
|
||||||
|
* summary: Get selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Selected item successfully received
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = createEntityRouter('page_links', Page_linksService, Page_linksDBApi);
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|||||||
@ -1,22 +1,6 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const PermissionsService = require('../services/permissions');
|
const PermissionsService = require('../services/permissions');
|
||||||
const PermissionsDBApi = require('../db/api/permissions');
|
const PermissionsDBApi = require('../db/api/permissions');
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
const { createEntityRouter } = require('../factories/router.factory');
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('permissions'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
@ -25,13 +9,9 @@ router.use(checkCrudPermissions('permissions'));
|
|||||||
* Permissions:
|
* Permissions:
|
||||||
* type: object
|
* type: object
|
||||||
* properties:
|
* properties:
|
||||||
|
|
||||||
* name:
|
* name:
|
||||||
* type: string
|
* type: string
|
||||||
* default: name
|
* default: name
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,319 +21,44 @@ router.use(checkCrudPermissions('permissions'));
|
|||||||
* description: The Permissions managing API
|
* description: The Permissions managing API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/permissions:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Permissions]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await PermissionsService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Permissions]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await PermissionsService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/permissions/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Permissions]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await PermissionsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/permissions/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Permissions]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await PermissionsService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/permissions/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Permissions]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await PermissionsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/permissions:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Permissions]
|
|
||||||
* summary: Get all permissions
|
|
||||||
* description: Get all permissions
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Permissions list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await PermissionsDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','name',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/permissions/count:
|
* /api/permissions:
|
||||||
* get:
|
* post:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Permissions]
|
* tags: [Permissions]
|
||||||
* summary: Count all permissions
|
* summary: Add new item
|
||||||
* description: Count all permissions
|
* description: Add new item
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* data:
|
||||||
|
* description: Data of the updated item
|
||||||
|
* type: object
|
||||||
|
* $ref: "#/components/schemas/Permissions"
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Permissions count successfully received
|
* description: The item was successfully added
|
||||||
* content:
|
* content:
|
||||||
* application/json:
|
* application/json:
|
||||||
* schema:
|
* schema:
|
||||||
* type: array
|
* $ref: "#/components/schemas/Permissions"
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Permissions"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
* 405:
|
||||||
* description: Data not found
|
* description: Invalid input data
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await PermissionsDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/permissions/autocomplete:
|
|
||||||
* get:
|
* get:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Permissions]
|
* tags: [Permissions]
|
||||||
* summary: Find all permissions that match search criteria
|
* summary: Get all permissions
|
||||||
* description: Find all permissions that match search criteria
|
* description: Get all permissions
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Permissions list successfully received
|
* description: Permissions list successfully received
|
||||||
@ -370,60 +75,110 @@ router.get('/count', wrapAsync(async (req, res) => {
|
|||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
*/
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await PermissionsDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/permissions/{id}:
|
* /api/permissions/{id}:
|
||||||
* get:
|
* put:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Permissions]
|
* tags: [Permissions]
|
||||||
* summary: Get selected item
|
* summary: Update the data of the selected item
|
||||||
* description: Get selected item
|
* description: Update the data of the selected item
|
||||||
* parameters:
|
* parameters:
|
||||||
* - in: path
|
* - in: path
|
||||||
* name: id
|
* name: id
|
||||||
* description: ID of item to get
|
* description: Item ID to update
|
||||||
* required: true
|
* required: true
|
||||||
* schema:
|
* schema:
|
||||||
* type: string
|
* type: string
|
||||||
* responses:
|
* requestBody:
|
||||||
* 200:
|
* description: Set new item data
|
||||||
* description: Selected item successfully received
|
* required: true
|
||||||
* content:
|
* content:
|
||||||
* application/json:
|
* application/json:
|
||||||
* schema:
|
* schema:
|
||||||
* $ref: "#/components/schemas/Permissions"
|
* properties:
|
||||||
* 400:
|
* id:
|
||||||
* description: Invalid ID supplied
|
* description: ID of the updated item
|
||||||
* 401:
|
* type: string
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* data:
|
||||||
* 404:
|
* description: Data of the updated item
|
||||||
* description: Item not found
|
* type: object
|
||||||
* 500:
|
* $ref: "#/components/schemas/Permissions"
|
||||||
* description: Some server error
|
* required:
|
||||||
*/
|
* - id
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
* responses:
|
||||||
const payload = await PermissionsDBApi.findBy(
|
* 200:
|
||||||
{ id: req.params.id },
|
* description: The item data was successfully updated
|
||||||
);
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* $ref: "#/components/schemas/Permissions"
|
||||||
|
* 400:
|
||||||
|
* description: Invalid ID supplied
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
* delete:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Permissions]
|
||||||
|
* summary: Delete the selected item
|
||||||
|
* description: Delete the selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* description: Item ID to delete
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item was successfully deleted
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* $ref: "#/components/schemas/Permissions"
|
||||||
|
* 400:
|
||||||
|
* description: Invalid ID supplied
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Permissions]
|
||||||
|
* summary: Get selected item
|
||||||
|
* description: Get selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* description: ID of item to get
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Selected item successfully received
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* $ref: "#/components/schemas/Permissions"
|
||||||
|
* 400:
|
||||||
|
* description: Invalid ID supplied
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = createEntityRouter('permissions', PermissionsService, PermissionsDBApi);
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|||||||
@ -1,22 +1,6 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const Presigned_url_requestsService = require('../services/presigned_url_requests');
|
const Presigned_url_requestsService = require('../services/presigned_url_requests');
|
||||||
const Presigned_url_requestsDBApi = require('../db/api/presigned_url_requests');
|
const Presigned_url_requestsDBApi = require('../db/api/presigned_url_requests');
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
const { createEntityRouter } = require('../factories/router.factory');
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('presigned_url_requests'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
@ -25,24 +9,17 @@ router.use(checkCrudPermissions('presigned_url_requests'));
|
|||||||
* Presigned_url_requests:
|
* Presigned_url_requests:
|
||||||
* type: object
|
* type: object
|
||||||
* properties:
|
* properties:
|
||||||
|
|
||||||
* requested_key:
|
* requested_key:
|
||||||
* type: string
|
* type: string
|
||||||
* default: requested_key
|
|
||||||
* mime_type:
|
* mime_type:
|
||||||
* type: string
|
* type: string
|
||||||
* default: mime_type
|
|
||||||
* status:
|
* status:
|
||||||
* type: string
|
* type: string
|
||||||
* default: status
|
|
||||||
|
|
||||||
|
|
||||||
* requested_size_mb:
|
* requested_size_mb:
|
||||||
* type: integer
|
* type: number
|
||||||
* format: int64
|
* expires_at:
|
||||||
|
* type: string
|
||||||
*
|
* format: date-time
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,389 +29,118 @@ router.use(checkCrudPermissions('presigned_url_requests'));
|
|||||||
* description: The Presigned_url_requests managing API
|
* description: The Presigned_url_requests managing API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/presigned_url_requests:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Presigned_url_requests]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Presigned_url_requests"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Presigned_url_requests"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Presigned_url_requestsService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Presigned_url_requests]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Presigned_url_requests"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Presigned_url_requests"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Presigned_url_requestsService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/presigned_url_requests/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Presigned_url_requests]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Presigned_url_requests"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Presigned_url_requests"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Presigned_url_requestsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/presigned_url_requests/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Presigned_url_requests]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Presigned_url_requests"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Presigned_url_requestsService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/presigned_url_requests/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Presigned_url_requests]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Presigned_url_requests"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await Presigned_url_requestsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/presigned_url_requests:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Presigned_url_requests]
|
|
||||||
* summary: Get all presigned_url_requests
|
|
||||||
* description: Get all presigned_url_requests
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Presigned_url_requests list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Presigned_url_requests"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Presigned_url_requestsDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','requested_key','mime_type','status',
|
|
||||||
|
|
||||||
'requested_size_mb',
|
|
||||||
'expires_at',
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/presigned_url_requests/count:
|
* /api/presigned_url_requests:
|
||||||
* get:
|
* post:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Presigned_url_requests]
|
* tags: [Presigned_url_requests]
|
||||||
* summary: Count all presigned_url_requests
|
* summary: Add new item
|
||||||
* description: Count all presigned_url_requests
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* data:
|
||||||
|
* type: object
|
||||||
|
* $ref: "#/components/schemas/Presigned_url_requests"
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Presigned_url_requests count successfully received
|
* description: The item was successfully added
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Presigned_url_requests"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Presigned_url_requestsDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/presigned_url_requests/autocomplete:
|
|
||||||
* get:
|
* get:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Presigned_url_requests]
|
* tags: [Presigned_url_requests]
|
||||||
* summary: Find all presigned_url_requests that match search criteria
|
* summary: Get all presigned_url_requests
|
||||||
* description: Find all presigned_url_requests that match search criteria
|
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Presigned_url_requests list successfully received
|
* description: Presigned_url_requests list successfully received
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Presigned_url_requests"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
*/
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await Presigned_url_requestsDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/presigned_url_requests/{id}:
|
* /api/presigned_url_requests/{id}:
|
||||||
* get:
|
* put:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Presigned_url_requests]
|
* tags: [Presigned_url_requests]
|
||||||
* summary: Get selected item
|
* summary: Update the selected item
|
||||||
* description: Get selected item
|
* parameters:
|
||||||
* parameters:
|
* - in: path
|
||||||
* - in: path
|
* name: id
|
||||||
* name: id
|
* required: true
|
||||||
* description: ID of item to get
|
* schema:
|
||||||
* required: true
|
* type: string
|
||||||
* schema:
|
* requestBody:
|
||||||
* type: string
|
* required: true
|
||||||
* responses:
|
* content:
|
||||||
* 200:
|
* application/json:
|
||||||
* description: Selected item successfully received
|
* schema:
|
||||||
* content:
|
* properties:
|
||||||
* application/json:
|
* id:
|
||||||
* schema:
|
* type: string
|
||||||
* $ref: "#/components/schemas/Presigned_url_requests"
|
* data:
|
||||||
* 400:
|
* type: object
|
||||||
* description: Invalid ID supplied
|
* $ref: "#/components/schemas/Presigned_url_requests"
|
||||||
* 401:
|
* responses:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* 200:
|
||||||
* 404:
|
* description: The item was successfully updated
|
||||||
* description: Item not found
|
* 401:
|
||||||
* 500:
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* description: Some server error
|
* 404:
|
||||||
*/
|
* description: Item not found
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
* 500:
|
||||||
const payload = await Presigned_url_requestsDBApi.findBy(
|
* description: Some server error
|
||||||
{ id: req.params.id },
|
* delete:
|
||||||
);
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Presigned_url_requests]
|
||||||
|
* summary: Delete the selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item was successfully deleted
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Presigned_url_requests]
|
||||||
|
* summary: Get selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Selected item successfully received
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = createEntityRouter('presigned_url_requests', Presigned_url_requestsService, Presigned_url_requestsDBApi);
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|||||||
@ -1,22 +1,6 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const Project_audio_tracksService = require('../services/project_audio_tracks');
|
const Project_audio_tracksService = require('../services/project_audio_tracks');
|
||||||
const Project_audio_tracksDBApi = require('../db/api/project_audio_tracks');
|
const Project_audio_tracksDBApi = require('../db/api/project_audio_tracks');
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
const { createEntityRouter } = require('../factories/router.factory');
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('project_audio_tracks'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
@ -25,29 +9,18 @@ router.use(checkCrudPermissions('project_audio_tracks'));
|
|||||||
* Project_audio_tracks:
|
* Project_audio_tracks:
|
||||||
* type: object
|
* type: object
|
||||||
* properties:
|
* properties:
|
||||||
|
|
||||||
* source_key:
|
* source_key:
|
||||||
* type: string
|
* type: string
|
||||||
* default: source_key
|
|
||||||
* name:
|
* name:
|
||||||
* type: string
|
* type: string
|
||||||
* default: name
|
|
||||||
* slug:
|
* slug:
|
||||||
* type: string
|
* type: string
|
||||||
* default: slug
|
|
||||||
* url:
|
* url:
|
||||||
* type: string
|
* type: string
|
||||||
* default: url
|
|
||||||
|
|
||||||
* sort_order:
|
* sort_order:
|
||||||
* type: integer
|
* type: integer
|
||||||
* format: int64
|
|
||||||
|
|
||||||
* volume:
|
* volume:
|
||||||
* type: integer
|
* type: number
|
||||||
* format: int64
|
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,393 +30,118 @@ router.use(checkCrudPermissions('project_audio_tracks'));
|
|||||||
* description: The Project_audio_tracks managing API
|
* description: The Project_audio_tracks managing API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/project_audio_tracks:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Project_audio_tracks]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Project_audio_tracks"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Project_audio_tracks"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Project_audio_tracksService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Project_audio_tracks]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Project_audio_tracks"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Project_audio_tracks"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Project_audio_tracksService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/project_audio_tracks/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Project_audio_tracks]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Project_audio_tracks"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Project_audio_tracks"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Project_audio_tracksService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/project_audio_tracks/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Project_audio_tracks]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Project_audio_tracks"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Project_audio_tracksService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/project_audio_tracks/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Project_audio_tracks]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Project_audio_tracks"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await Project_audio_tracksService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/project_audio_tracks:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Project_audio_tracks]
|
|
||||||
* summary: Get all project_audio_tracks
|
|
||||||
* description: Get all project_audio_tracks
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Project_audio_tracks list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Project_audio_tracks"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const runtimeContext = req.runtimeContext;
|
|
||||||
const payload = await Project_audio_tracksDBApi.findAll(
|
|
||||||
req.query, { currentUser, runtimeContext }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','source_key','name','slug','url',
|
|
||||||
'sort_order',
|
|
||||||
'volume',
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/project_audio_tracks/count:
|
* /api/project_audio_tracks:
|
||||||
* get:
|
* post:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Project_audio_tracks]
|
* tags: [Project_audio_tracks]
|
||||||
* summary: Count all project_audio_tracks
|
* summary: Add new item
|
||||||
* description: Count all project_audio_tracks
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* data:
|
||||||
|
* type: object
|
||||||
|
* $ref: "#/components/schemas/Project_audio_tracks"
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Project_audio_tracks count successfully received
|
* description: The item was successfully added
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Project_audio_tracks"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const runtimeContext = req.runtimeContext;
|
|
||||||
const payload = await Project_audio_tracksDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser, runtimeContext }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/project_audio_tracks/autocomplete:
|
|
||||||
* get:
|
* get:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Project_audio_tracks]
|
* tags: [Project_audio_tracks]
|
||||||
* summary: Find all project_audio_tracks that match search criteria
|
* summary: Get all project_audio_tracks
|
||||||
* description: Find all project_audio_tracks that match search criteria
|
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Project_audio_tracks list successfully received
|
* description: Project_audio_tracks list successfully received
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Project_audio_tracks"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
*/
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await Project_audio_tracksDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/project_audio_tracks/{id}:
|
* /api/project_audio_tracks/{id}:
|
||||||
* get:
|
* put:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Project_audio_tracks]
|
* tags: [Project_audio_tracks]
|
||||||
* summary: Get selected item
|
* summary: Update the selected item
|
||||||
* description: Get selected item
|
* parameters:
|
||||||
* parameters:
|
* - in: path
|
||||||
* - in: path
|
* name: id
|
||||||
* name: id
|
* required: true
|
||||||
* description: ID of item to get
|
* schema:
|
||||||
* required: true
|
* type: string
|
||||||
* schema:
|
* requestBody:
|
||||||
* type: string
|
* required: true
|
||||||
* responses:
|
* content:
|
||||||
* 200:
|
* application/json:
|
||||||
* description: Selected item successfully received
|
* schema:
|
||||||
* content:
|
* properties:
|
||||||
* application/json:
|
* id:
|
||||||
* schema:
|
* type: string
|
||||||
* $ref: "#/components/schemas/Project_audio_tracks"
|
* data:
|
||||||
* 400:
|
* type: object
|
||||||
* description: Invalid ID supplied
|
* $ref: "#/components/schemas/Project_audio_tracks"
|
||||||
* 401:
|
* responses:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* 200:
|
||||||
* 404:
|
* description: The item was successfully updated
|
||||||
* description: Item not found
|
* 401:
|
||||||
* 500:
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* description: Some server error
|
* 404:
|
||||||
*/
|
* description: Item not found
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
* 500:
|
||||||
const runtimeContext = req.runtimeContext;
|
* description: Some server error
|
||||||
const payload = await Project_audio_tracksDBApi.findBy(
|
* delete:
|
||||||
{ id: req.params.id },
|
* security:
|
||||||
{ runtimeContext },
|
* - bearerAuth: []
|
||||||
);
|
* tags: [Project_audio_tracks]
|
||||||
|
* summary: Delete the selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item was successfully deleted
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Project_audio_tracks]
|
||||||
|
* summary: Get selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Selected item successfully received
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = createEntityRouter('project_audio_tracks', Project_audio_tracksService, Project_audio_tracksDBApi);
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|||||||
@ -1,22 +1,6 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const Project_membershipsService = require('../services/project_memberships');
|
const Project_membershipsService = require('../services/project_memberships');
|
||||||
const Project_membershipsDBApi = require('../db/api/project_memberships');
|
const Project_membershipsDBApi = require('../db/api/project_memberships');
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
const { createEntityRouter } = require('../factories/router.factory');
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('project_memberships'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
@ -25,11 +9,12 @@ router.use(checkCrudPermissions('project_memberships'));
|
|||||||
* Project_memberships:
|
* Project_memberships:
|
||||||
* type: object
|
* type: object
|
||||||
* properties:
|
* properties:
|
||||||
|
* invited_at:
|
||||||
|
* type: string
|
||||||
|
* format: date-time
|
||||||
|
* accepted_at:
|
||||||
*
|
* type: string
|
||||||
|
* format: date-time
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,389 +24,118 @@ router.use(checkCrudPermissions('project_memberships'));
|
|||||||
* description: The Project_memberships managing API
|
* description: The Project_memberships managing API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/project_memberships:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Project_memberships]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Project_memberships"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Project_memberships"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Project_membershipsService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Project_memberships]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Project_memberships"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Project_memberships"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Project_membershipsService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/project_memberships/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Project_memberships]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Project_memberships"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Project_memberships"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Project_membershipsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/project_memberships/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Project_memberships]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Project_memberships"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Project_membershipsService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/project_memberships/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Project_memberships]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Project_memberships"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await Project_membershipsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/project_memberships:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Project_memberships]
|
|
||||||
* summary: Get all project_memberships
|
|
||||||
* description: Get all project_memberships
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Project_memberships list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Project_memberships"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Project_membershipsDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id',
|
|
||||||
|
|
||||||
|
|
||||||
'invited_at','accepted_at',
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/project_memberships/count:
|
* /api/project_memberships:
|
||||||
* get:
|
* post:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Project_memberships]
|
* tags: [Project_memberships]
|
||||||
* summary: Count all project_memberships
|
* summary: Add new item
|
||||||
* description: Count all project_memberships
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* data:
|
||||||
|
* type: object
|
||||||
|
* $ref: "#/components/schemas/Project_memberships"
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Project_memberships count successfully received
|
* description: The item was successfully added
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Project_memberships"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Project_membershipsDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/project_memberships/autocomplete:
|
|
||||||
* get:
|
* get:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Project_memberships]
|
* tags: [Project_memberships]
|
||||||
* summary: Find all project_memberships that match search criteria
|
* summary: Get all project_memberships
|
||||||
* description: Find all project_memberships that match search criteria
|
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Project_memberships list successfully received
|
* description: Project_memberships list successfully received
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Project_memberships"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
*/
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await Project_membershipsDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/project_memberships/{id}:
|
* /api/project_memberships/{id}:
|
||||||
* get:
|
* put:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Project_memberships]
|
* tags: [Project_memberships]
|
||||||
* summary: Get selected item
|
* summary: Update the selected item
|
||||||
* description: Get selected item
|
* parameters:
|
||||||
* parameters:
|
* - in: path
|
||||||
* - in: path
|
* name: id
|
||||||
* name: id
|
* required: true
|
||||||
* description: ID of item to get
|
* schema:
|
||||||
* required: true
|
* type: string
|
||||||
* schema:
|
* requestBody:
|
||||||
* type: string
|
* required: true
|
||||||
* responses:
|
* content:
|
||||||
* 200:
|
* application/json:
|
||||||
* description: Selected item successfully received
|
* schema:
|
||||||
* content:
|
* properties:
|
||||||
* application/json:
|
* id:
|
||||||
* schema:
|
* type: string
|
||||||
* $ref: "#/components/schemas/Project_memberships"
|
* data:
|
||||||
* 400:
|
* type: object
|
||||||
* description: Invalid ID supplied
|
* $ref: "#/components/schemas/Project_memberships"
|
||||||
* 401:
|
* responses:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* 200:
|
||||||
* 404:
|
* description: The item was successfully updated
|
||||||
* description: Item not found
|
* 401:
|
||||||
* 500:
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* description: Some server error
|
* 404:
|
||||||
*/
|
* description: Item not found
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
* 500:
|
||||||
const payload = await Project_membershipsDBApi.findBy(
|
* description: Some server error
|
||||||
{ id: req.params.id },
|
* delete:
|
||||||
);
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Project_memberships]
|
||||||
|
* summary: Delete the selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item was successfully deleted
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Project_memberships]
|
||||||
|
* summary: Get selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Selected item successfully received
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = createEntityRouter('project_memberships', Project_membershipsService, Project_membershipsDBApi);
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|||||||
@ -1,22 +1,6 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const Publish_eventsService = require('../services/publish_events');
|
const Publish_eventsService = require('../services/publish_events');
|
||||||
const Publish_eventsDBApi = require('../db/api/publish_events');
|
const Publish_eventsDBApi = require('../db/api/publish_events');
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
const { createEntityRouter } = require('../factories/router.factory');
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('publish_events'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
@ -25,25 +9,24 @@ router.use(checkCrudPermissions('publish_events'));
|
|||||||
* Publish_events:
|
* Publish_events:
|
||||||
* type: object
|
* type: object
|
||||||
* properties:
|
* properties:
|
||||||
|
* title:
|
||||||
|
* type: string
|
||||||
|
* description:
|
||||||
|
* type: string
|
||||||
* error_message:
|
* error_message:
|
||||||
* type: string
|
* type: string
|
||||||
* default: error_message
|
|
||||||
|
|
||||||
* pages_copied:
|
* pages_copied:
|
||||||
* type: integer
|
* type: integer
|
||||||
* format: int64
|
|
||||||
* transitions_copied:
|
* transitions_copied:
|
||||||
* type: integer
|
* type: integer
|
||||||
* format: int64
|
|
||||||
* audios_copied:
|
* audios_copied:
|
||||||
* type: integer
|
* type: integer
|
||||||
* format: int64
|
* started_at:
|
||||||
|
* type: string
|
||||||
|
* format: date-time
|
||||||
*
|
* finished_at:
|
||||||
*
|
* type: string
|
||||||
*
|
* format: date-time
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,389 +36,118 @@ router.use(checkCrudPermissions('publish_events'));
|
|||||||
* description: The Publish_events managing API
|
* description: The Publish_events managing API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/publish_events:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Publish_events]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Publish_events"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Publish_events"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Publish_eventsService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Publish_events]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Publish_events"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Publish_events"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Publish_eventsService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/publish_events/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Publish_events]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Publish_events"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Publish_events"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Publish_eventsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/publish_events/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Publish_events]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Publish_events"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Publish_eventsService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/publish_events/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Publish_events]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Publish_events"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await Publish_eventsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/publish_events:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Publish_events]
|
|
||||||
* summary: Get all publish_events
|
|
||||||
* description: Get all publish_events
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Publish_events list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Publish_events"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Publish_eventsDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','title','description','error_message',
|
|
||||||
'pages_copied','transitions_copied','audios_copied',
|
|
||||||
|
|
||||||
'started_at','finished_at',
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/publish_events/count:
|
* /api/publish_events:
|
||||||
* get:
|
* post:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Publish_events]
|
* tags: [Publish_events]
|
||||||
* summary: Count all publish_events
|
* summary: Add new item
|
||||||
* description: Count all publish_events
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* data:
|
||||||
|
* type: object
|
||||||
|
* $ref: "#/components/schemas/Publish_events"
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Publish_events count successfully received
|
* description: The item was successfully added
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Publish_events"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Publish_eventsDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/publish_events/autocomplete:
|
|
||||||
* get:
|
* get:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Publish_events]
|
* tags: [Publish_events]
|
||||||
* summary: Find all publish_events that match search criteria
|
* summary: Get all publish_events
|
||||||
* description: Find all publish_events that match search criteria
|
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Publish_events list successfully received
|
* description: Publish_events list successfully received
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Publish_events"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
*/
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await Publish_eventsDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/publish_events/{id}:
|
* /api/publish_events/{id}:
|
||||||
* get:
|
* put:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Publish_events]
|
* tags: [Publish_events]
|
||||||
* summary: Get selected item
|
* summary: Update the selected item
|
||||||
* description: Get selected item
|
* parameters:
|
||||||
* parameters:
|
* - in: path
|
||||||
* - in: path
|
* name: id
|
||||||
* name: id
|
* required: true
|
||||||
* description: ID of item to get
|
* schema:
|
||||||
* required: true
|
* type: string
|
||||||
* schema:
|
* requestBody:
|
||||||
* type: string
|
* required: true
|
||||||
* responses:
|
* content:
|
||||||
* 200:
|
* application/json:
|
||||||
* description: Selected item successfully received
|
* schema:
|
||||||
* content:
|
* properties:
|
||||||
* application/json:
|
* id:
|
||||||
* schema:
|
* type: string
|
||||||
* $ref: "#/components/schemas/Publish_events"
|
* data:
|
||||||
* 400:
|
* type: object
|
||||||
* description: Invalid ID supplied
|
* $ref: "#/components/schemas/Publish_events"
|
||||||
* 401:
|
* responses:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* 200:
|
||||||
* 404:
|
* description: The item was successfully updated
|
||||||
* description: Item not found
|
* 401:
|
||||||
* 500:
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* description: Some server error
|
* 404:
|
||||||
*/
|
* description: Item not found
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
* 500:
|
||||||
const payload = await Publish_eventsDBApi.findBy(
|
* description: Some server error
|
||||||
{ id: req.params.id },
|
* delete:
|
||||||
);
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Publish_events]
|
||||||
|
* summary: Delete the selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item was successfully deleted
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Publish_events]
|
||||||
|
* summary: Get selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Selected item successfully received
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = createEntityRouter('publish_events', Publish_eventsService, Publish_eventsDBApi);
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|||||||
@ -1,22 +1,6 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const Pwa_cachesService = require('../services/pwa_caches');
|
const Pwa_cachesService = require('../services/pwa_caches');
|
||||||
const Pwa_cachesDBApi = require('../db/api/pwa_caches');
|
const Pwa_cachesDBApi = require('../db/api/pwa_caches');
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
const { createEntityRouter } = require('../factories/router.factory');
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('pwa_caches'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
@ -25,20 +9,15 @@ router.use(checkCrudPermissions('pwa_caches'));
|
|||||||
* Pwa_caches:
|
* Pwa_caches:
|
||||||
* type: object
|
* type: object
|
||||||
* properties:
|
* properties:
|
||||||
|
|
||||||
* cache_version:
|
* cache_version:
|
||||||
* type: string
|
* type: string
|
||||||
* default: cache_version
|
|
||||||
* manifest_json:
|
* manifest_json:
|
||||||
* type: string
|
* type: string
|
||||||
* default: manifest_json
|
|
||||||
* asset_list_json:
|
* asset_list_json:
|
||||||
* type: string
|
* type: string
|
||||||
* default: asset_list_json
|
* generated_at:
|
||||||
|
* type: string
|
||||||
|
* format: date-time
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,389 +27,118 @@ router.use(checkCrudPermissions('pwa_caches'));
|
|||||||
* description: The Pwa_caches managing API
|
* description: The Pwa_caches managing API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/pwa_caches:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Pwa_caches]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Pwa_caches"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Pwa_caches"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Pwa_cachesService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Pwa_caches]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Pwa_caches"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Pwa_caches"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Pwa_cachesService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/pwa_caches/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Pwa_caches]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Pwa_caches"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Pwa_caches"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Pwa_cachesService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/pwa_caches/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Pwa_caches]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Pwa_caches"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Pwa_cachesService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/pwa_caches/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Pwa_caches]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Pwa_caches"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await Pwa_cachesService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/pwa_caches:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Pwa_caches]
|
|
||||||
* summary: Get all pwa_caches
|
|
||||||
* description: Get all pwa_caches
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Pwa_caches list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Pwa_caches"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Pwa_cachesDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','cache_version','manifest_json','asset_list_json',
|
|
||||||
|
|
||||||
|
|
||||||
'generated_at',
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/pwa_caches/count:
|
* /api/pwa_caches:
|
||||||
* get:
|
* post:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Pwa_caches]
|
* tags: [Pwa_caches]
|
||||||
* summary: Count all pwa_caches
|
* summary: Add new item
|
||||||
* description: Count all pwa_caches
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* data:
|
||||||
|
* type: object
|
||||||
|
* $ref: "#/components/schemas/Pwa_caches"
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Pwa_caches count successfully received
|
* description: The item was successfully added
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Pwa_caches"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await Pwa_cachesDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/pwa_caches/autocomplete:
|
|
||||||
* get:
|
* get:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Pwa_caches]
|
* tags: [Pwa_caches]
|
||||||
* summary: Find all pwa_caches that match search criteria
|
* summary: Get all pwa_caches
|
||||||
* description: Find all pwa_caches that match search criteria
|
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Pwa_caches list successfully received
|
* description: Pwa_caches list successfully received
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Pwa_caches"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
*/
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await Pwa_cachesDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/pwa_caches/{id}:
|
* /api/pwa_caches/{id}:
|
||||||
* get:
|
* put:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Pwa_caches]
|
* tags: [Pwa_caches]
|
||||||
* summary: Get selected item
|
* summary: Update the selected item
|
||||||
* description: Get selected item
|
* parameters:
|
||||||
* parameters:
|
* - in: path
|
||||||
* - in: path
|
* name: id
|
||||||
* name: id
|
* required: true
|
||||||
* description: ID of item to get
|
* schema:
|
||||||
* required: true
|
* type: string
|
||||||
* schema:
|
* requestBody:
|
||||||
* type: string
|
* required: true
|
||||||
* responses:
|
* content:
|
||||||
* 200:
|
* application/json:
|
||||||
* description: Selected item successfully received
|
* schema:
|
||||||
* content:
|
* properties:
|
||||||
* application/json:
|
* id:
|
||||||
* schema:
|
* type: string
|
||||||
* $ref: "#/components/schemas/Pwa_caches"
|
* data:
|
||||||
* 400:
|
* type: object
|
||||||
* description: Invalid ID supplied
|
* $ref: "#/components/schemas/Pwa_caches"
|
||||||
* 401:
|
* responses:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* 200:
|
||||||
* 404:
|
* description: The item was successfully updated
|
||||||
* description: Item not found
|
* 401:
|
||||||
* 500:
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* description: Some server error
|
* 404:
|
||||||
*/
|
* description: Item not found
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
* 500:
|
||||||
const payload = await Pwa_cachesDBApi.findBy(
|
* description: Some server error
|
||||||
{ id: req.params.id },
|
* delete:
|
||||||
);
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Pwa_caches]
|
||||||
|
* summary: Delete the selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item was successfully deleted
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Pwa_caches]
|
||||||
|
* summary: Get selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Selected item successfully received
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = createEntityRouter('pwa_caches', Pwa_cachesService, Pwa_cachesDBApi);
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|||||||
@ -1,22 +1,6 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const RolesService = require('../services/roles');
|
const RolesService = require('../services/roles');
|
||||||
const RolesDBApi = require('../db/api/roles');
|
const RolesDBApi = require('../db/api/roles');
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
const { createEntityRouter } = require('../factories/router.factory');
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('roles'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
@ -25,13 +9,9 @@ router.use(checkCrudPermissions('roles'));
|
|||||||
* Roles:
|
* Roles:
|
||||||
* type: object
|
* type: object
|
||||||
* properties:
|
* properties:
|
||||||
|
|
||||||
* name:
|
* name:
|
||||||
* type: string
|
* type: string
|
||||||
* default: name
|
* default: name
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,389 +21,121 @@ router.use(checkCrudPermissions('roles'));
|
|||||||
* description: The Roles managing API
|
* description: The Roles managing API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/roles:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await RolesService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await RolesService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/roles/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await RolesService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/roles/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await RolesService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/roles/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await RolesService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/roles:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Roles]
|
|
||||||
* summary: Get all roles
|
|
||||||
* description: Get all roles
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Roles list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await RolesDBApi.findAll(
|
|
||||||
req.query, { currentUser }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','name',
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/roles/count:
|
* /api/roles:
|
||||||
* get:
|
* post:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Roles]
|
* tags: [Roles]
|
||||||
* summary: Count all roles
|
* summary: Add new item
|
||||||
* description: Count all roles
|
* description: Add new item
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* data:
|
||||||
|
* description: Data of the item
|
||||||
|
* type: object
|
||||||
|
* $ref: "#/components/schemas/Roles"
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Roles count successfully received
|
* description: The item was successfully added
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const payload = await RolesDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/roles/autocomplete:
|
|
||||||
* get:
|
* get:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Roles]
|
* tags: [Roles]
|
||||||
* summary: Find all roles that match search criteria
|
* summary: Get all roles
|
||||||
* description: Find all roles that match search criteria
|
* description: Get all roles
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Roles list successfully received
|
* description: Roles list successfully received
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Roles"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
*/
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await RolesDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/roles/{id}:
|
* /api/roles/{id}:
|
||||||
* get:
|
* put:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Roles]
|
* tags: [Roles]
|
||||||
* summary: Get selected item
|
* summary: Update the data of the selected item
|
||||||
* description: Get selected item
|
* parameters:
|
||||||
* parameters:
|
* - in: path
|
||||||
* - in: path
|
* name: id
|
||||||
* name: id
|
* required: true
|
||||||
* description: ID of item to get
|
* schema:
|
||||||
* required: true
|
* type: string
|
||||||
* schema:
|
* requestBody:
|
||||||
* type: string
|
* required: true
|
||||||
* responses:
|
* content:
|
||||||
* 200:
|
* application/json:
|
||||||
* description: Selected item successfully received
|
* schema:
|
||||||
* content:
|
* properties:
|
||||||
* application/json:
|
* id:
|
||||||
* schema:
|
* type: string
|
||||||
* $ref: "#/components/schemas/Roles"
|
* data:
|
||||||
* 400:
|
* type: object
|
||||||
* description: Invalid ID supplied
|
* $ref: "#/components/schemas/Roles"
|
||||||
* 401:
|
* responses:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* 200:
|
||||||
* 404:
|
* description: The item data was successfully updated
|
||||||
* description: Item not found
|
* 401:
|
||||||
* 500:
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* description: Some server error
|
* 404:
|
||||||
*/
|
* description: Item not found
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
* 500:
|
||||||
const payload = await RolesDBApi.findBy(
|
* description: Some server error
|
||||||
{ id: req.params.id },
|
* delete:
|
||||||
);
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Roles]
|
||||||
|
* summary: Delete the selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item was successfully deleted
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Roles]
|
||||||
|
* summary: Get selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Selected item successfully received
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = createEntityRouter('roles', RolesService, RolesDBApi);
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|||||||
@ -1,22 +1,6 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const Tour_pagesService = require('../services/tour_pages');
|
const Tour_pagesService = require('../services/tour_pages');
|
||||||
const Tour_pagesDBApi = require('../db/api/tour_pages');
|
const Tour_pagesDBApi = require('../db/api/tour_pages');
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
const { createEntityRouter } = require('../factories/router.factory');
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('tour_pages'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
@ -25,35 +9,22 @@ router.use(checkCrudPermissions('tour_pages'));
|
|||||||
* Tour_pages:
|
* Tour_pages:
|
||||||
* type: object
|
* type: object
|
||||||
* properties:
|
* properties:
|
||||||
|
|
||||||
* source_key:
|
* source_key:
|
||||||
* type: string
|
* type: string
|
||||||
* default: source_key
|
|
||||||
* name:
|
* name:
|
||||||
* type: string
|
* type: string
|
||||||
* default: name
|
|
||||||
* slug:
|
* slug:
|
||||||
* type: string
|
* type: string
|
||||||
* default: slug
|
|
||||||
* background_image_url:
|
* background_image_url:
|
||||||
* type: string
|
* type: string
|
||||||
* default: background_image_url
|
|
||||||
* background_video_url:
|
* background_video_url:
|
||||||
* type: string
|
* type: string
|
||||||
* default: background_video_url
|
|
||||||
* background_audio_url:
|
* background_audio_url:
|
||||||
* type: string
|
* type: string
|
||||||
* default: background_audio_url
|
|
||||||
* ui_schema_json:
|
* ui_schema_json:
|
||||||
* type: string
|
* type: string
|
||||||
* default: ui_schema_json
|
|
||||||
|
|
||||||
* sort_order:
|
* sort_order:
|
||||||
* type: integer
|
* type: integer
|
||||||
* format: int64
|
|
||||||
|
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,393 +34,118 @@ router.use(checkCrudPermissions('tour_pages'));
|
|||||||
* description: The Tour_pages managing API
|
* description: The Tour_pages managing API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/tour_pages:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Tour_pages]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Tour_pages"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Tour_pages"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Tour_pagesService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Tour_pages]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Tour_pages"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Tour_pages"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await Tour_pagesService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/tour_pages/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Tour_pages]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Tour_pages"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Tour_pages"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Tour_pagesService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/tour_pages/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Tour_pages]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Tour_pages"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await Tour_pagesService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/tour_pages/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Tour_pages]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Tour_pages"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await Tour_pagesService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/tour_pages:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Tour_pages]
|
|
||||||
* summary: Get all tour_pages
|
|
||||||
* description: Get all tour_pages
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Tour_pages list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Tour_pages"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const runtimeContext = req.runtimeContext;
|
|
||||||
const payload = await Tour_pagesDBApi.findAll(
|
|
||||||
req.query, { currentUser, runtimeContext }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','source_key','name','slug','background_image_url','background_video_url','background_audio_url','ui_schema_json',
|
|
||||||
'sort_order',
|
|
||||||
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/tour_pages/count:
|
* /api/tour_pages:
|
||||||
* get:
|
* post:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Tour_pages]
|
* tags: [Tour_pages]
|
||||||
* summary: Count all tour_pages
|
* summary: Add new item
|
||||||
* description: Count all tour_pages
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* data:
|
||||||
|
* type: object
|
||||||
|
* $ref: "#/components/schemas/Tour_pages"
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Tour_pages count successfully received
|
* description: The item was successfully added
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Tour_pages"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const runtimeContext = req.runtimeContext;
|
|
||||||
const payload = await Tour_pagesDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser, runtimeContext }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/tour_pages/autocomplete:
|
|
||||||
* get:
|
* get:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Tour_pages]
|
* tags: [Tour_pages]
|
||||||
* summary: Find all tour_pages that match search criteria
|
* summary: Get all tour_pages
|
||||||
* description: Find all tour_pages that match search criteria
|
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Tour_pages list successfully received
|
* description: Tour_pages list successfully received
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Tour_pages"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
*/
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await Tour_pagesDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/tour_pages/{id}:
|
* /api/tour_pages/{id}:
|
||||||
* get:
|
* put:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Tour_pages]
|
* tags: [Tour_pages]
|
||||||
* summary: Get selected item
|
* summary: Update the selected item
|
||||||
* description: Get selected item
|
* parameters:
|
||||||
* parameters:
|
* - in: path
|
||||||
* - in: path
|
* name: id
|
||||||
* name: id
|
* required: true
|
||||||
* description: ID of item to get
|
* schema:
|
||||||
* required: true
|
* type: string
|
||||||
* schema:
|
* requestBody:
|
||||||
* type: string
|
* required: true
|
||||||
* responses:
|
* content:
|
||||||
* 200:
|
* application/json:
|
||||||
* description: Selected item successfully received
|
* schema:
|
||||||
* content:
|
* properties:
|
||||||
* application/json:
|
* id:
|
||||||
* schema:
|
* type: string
|
||||||
* $ref: "#/components/schemas/Tour_pages"
|
* data:
|
||||||
* 400:
|
* type: object
|
||||||
* description: Invalid ID supplied
|
* $ref: "#/components/schemas/Tour_pages"
|
||||||
* 401:
|
* responses:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* 200:
|
||||||
* 404:
|
* description: The item was successfully updated
|
||||||
* description: Item not found
|
* 401:
|
||||||
* 500:
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* description: Some server error
|
* 404:
|
||||||
*/
|
* description: Item not found
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
* 500:
|
||||||
const runtimeContext = req.runtimeContext;
|
* description: Some server error
|
||||||
const payload = await Tour_pagesDBApi.findBy(
|
* delete:
|
||||||
{ id: req.params.id },
|
* security:
|
||||||
{ runtimeContext },
|
* - bearerAuth: []
|
||||||
);
|
* tags: [Tour_pages]
|
||||||
|
* summary: Delete the selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item was successfully deleted
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Tour_pages]
|
||||||
|
* summary: Get selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Selected item successfully received
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = createEntityRouter('tour_pages', Tour_pagesService, Tour_pagesDBApi);
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|||||||
@ -1,22 +1,6 @@
|
|||||||
|
|
||||||
const express = require('express');
|
|
||||||
|
|
||||||
const TransitionsService = require('../services/transitions');
|
const TransitionsService = require('../services/transitions');
|
||||||
const TransitionsDBApi = require('../db/api/transitions');
|
const TransitionsDBApi = require('../db/api/transitions');
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
const { createEntityRouter } = require('../factories/router.factory');
|
||||||
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
|
|
||||||
const {
|
|
||||||
checkCrudPermissions,
|
|
||||||
} = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('transitions'));
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
@ -25,29 +9,18 @@ router.use(checkCrudPermissions('transitions'));
|
|||||||
* Transitions:
|
* Transitions:
|
||||||
* type: object
|
* type: object
|
||||||
* properties:
|
* properties:
|
||||||
|
|
||||||
* source_key:
|
* source_key:
|
||||||
* type: string
|
* type: string
|
||||||
* default: source_key
|
|
||||||
* name:
|
* name:
|
||||||
* type: string
|
* type: string
|
||||||
* default: name
|
|
||||||
* slug:
|
* slug:
|
||||||
* type: string
|
* type: string
|
||||||
* default: slug
|
|
||||||
* video_url:
|
* video_url:
|
||||||
* type: string
|
* type: string
|
||||||
* default: video_url
|
|
||||||
* audio_url:
|
* audio_url:
|
||||||
* type: string
|
* type: string
|
||||||
* default: audio_url
|
|
||||||
|
|
||||||
|
|
||||||
* duration_sec:
|
* duration_sec:
|
||||||
* type: integer
|
* type: number
|
||||||
* format: int64
|
|
||||||
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,393 +30,118 @@ router.use(checkCrudPermissions('transitions'));
|
|||||||
* description: The Transitions managing API
|
* description: The Transitions managing API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/transitions:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Transitions]
|
|
||||||
* summary: Add new item
|
|
||||||
* description: Add new item
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Transitions"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully added
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Transitions"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await TransitionsService.create(req.body.data, req.currentUser, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/budgets/bulk-import:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Transitions]
|
|
||||||
* summary: Bulk import items
|
|
||||||
* description: Bulk import items
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated items
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Transitions"
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items were successfully imported
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Transitions"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 405:
|
|
||||||
* description: Invalid input data
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
router.post('/bulk-import', wrapAsync(async (req, res) => {
|
|
||||||
const referer = req.headers.referer || `${req.protocol}://${req.hostname}${req.originalUrl}`;
|
|
||||||
const link = new URL(referer);
|
|
||||||
await TransitionsService.bulkImport(req, res, true, link.host);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/transitions/{id}:
|
|
||||||
* put:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Transitions]
|
|
||||||
* summary: Update the data of the selected item
|
|
||||||
* description: Update the data of the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to update
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* requestBody:
|
|
||||||
* description: Set new item data
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* id:
|
|
||||||
* description: ID of the updated item
|
|
||||||
* type: string
|
|
||||||
* data:
|
|
||||||
* description: Data of the updated item
|
|
||||||
* type: object
|
|
||||||
* $ref: "#/components/schemas/Transitions"
|
|
||||||
* required:
|
|
||||||
* - id
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item data was successfully updated
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Transitions"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.put('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await TransitionsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/transitions/{id}:
|
|
||||||
* delete:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Transitions]
|
|
||||||
* summary: Delete the selected item
|
|
||||||
* description: Delete the selected item
|
|
||||||
* parameters:
|
|
||||||
* - in: path
|
|
||||||
* name: id
|
|
||||||
* description: Item ID to delete
|
|
||||||
* required: true
|
|
||||||
* schema:
|
|
||||||
* type: string
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The item was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Transitions"
|
|
||||||
* 400:
|
|
||||||
* description: Invalid ID supplied
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Item not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.delete('/:id', wrapAsync(async (req, res) => {
|
|
||||||
await TransitionsService.remove(req.params.id, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/transitions/deleteByIds:
|
|
||||||
* post:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Transitions]
|
|
||||||
* summary: Delete the selected item list
|
|
||||||
* description: Delete the selected item list
|
|
||||||
* requestBody:
|
|
||||||
* required: true
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* properties:
|
|
||||||
* ids:
|
|
||||||
* description: IDs of the updated items
|
|
||||||
* type: array
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: The items was successfully deleted
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* $ref: "#/components/schemas/Transitions"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Items not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.post('/deleteByIds', wrapAsync(async (req, res) => {
|
|
||||||
await TransitionsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
const payload = true;
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/transitions:
|
|
||||||
* get:
|
|
||||||
* security:
|
|
||||||
* - bearerAuth: []
|
|
||||||
* tags: [Transitions]
|
|
||||||
* summary: Get all transitions
|
|
||||||
* description: Get all transitions
|
|
||||||
* responses:
|
|
||||||
* 200:
|
|
||||||
* description: Transitions list successfully received
|
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Transitions"
|
|
||||||
* 401:
|
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
|
||||||
* description: Some server error
|
|
||||||
*/
|
|
||||||
router.get('/', wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const runtimeContext = req.runtimeContext;
|
|
||||||
const payload = await TransitionsDBApi.findAll(
|
|
||||||
req.query, { currentUser, runtimeContext }
|
|
||||||
);
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id','source_key','name','slug','video_url','audio_url',
|
|
||||||
|
|
||||||
'duration_sec',
|
|
||||||
|
|
||||||
];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv)
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/transitions/count:
|
* /api/transitions:
|
||||||
* get:
|
* post:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Transitions]
|
* tags: [Transitions]
|
||||||
* summary: Count all transitions
|
* summary: Add new item
|
||||||
* description: Count all transitions
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* properties:
|
||||||
|
* data:
|
||||||
|
* type: object
|
||||||
|
* $ref: "#/components/schemas/Transitions"
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Transitions count successfully received
|
* description: The item was successfully added
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Transitions"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
|
||||||
router.get('/count', wrapAsync(async (req, res) => {
|
|
||||||
|
|
||||||
const currentUser = req.currentUser;
|
|
||||||
const runtimeContext = req.runtimeContext;
|
|
||||||
const payload = await TransitionsDBApi.findAll(
|
|
||||||
req.query,
|
|
||||||
null,
|
|
||||||
{ countOnly: true, currentUser, runtimeContext }
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @swagger
|
|
||||||
* /api/transitions/autocomplete:
|
|
||||||
* get:
|
* get:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Transitions]
|
* tags: [Transitions]
|
||||||
* summary: Find all transitions that match search criteria
|
* summary: Get all transitions
|
||||||
* description: Find all transitions that match search criteria
|
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Transitions list successfully received
|
* description: Transitions list successfully received
|
||||||
* content:
|
|
||||||
* application/json:
|
|
||||||
* schema:
|
|
||||||
* type: array
|
|
||||||
* items:
|
|
||||||
* $ref: "#/components/schemas/Transitions"
|
|
||||||
* 401:
|
* 401:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* 404:
|
|
||||||
* description: Data not found
|
|
||||||
* 500:
|
* 500:
|
||||||
* description: Some server error
|
* description: Some server error
|
||||||
*/
|
*/
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
|
|
||||||
const payload = await TransitionsDBApi.findAllAutocomplete(
|
|
||||||
req.query.query,
|
|
||||||
req.query.limit,
|
|
||||||
req.query.offset,
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
* /api/transitions/{id}:
|
* /api/transitions/{id}:
|
||||||
* get:
|
* put:
|
||||||
* security:
|
* security:
|
||||||
* - bearerAuth: []
|
* - bearerAuth: []
|
||||||
* tags: [Transitions]
|
* tags: [Transitions]
|
||||||
* summary: Get selected item
|
* summary: Update the selected item
|
||||||
* description: Get selected item
|
* parameters:
|
||||||
* parameters:
|
* - in: path
|
||||||
* - in: path
|
* name: id
|
||||||
* name: id
|
* required: true
|
||||||
* description: ID of item to get
|
* schema:
|
||||||
* required: true
|
* type: string
|
||||||
* schema:
|
* requestBody:
|
||||||
* type: string
|
* required: true
|
||||||
* responses:
|
* content:
|
||||||
* 200:
|
* application/json:
|
||||||
* description: Selected item successfully received
|
* schema:
|
||||||
* content:
|
* properties:
|
||||||
* application/json:
|
* id:
|
||||||
* schema:
|
* type: string
|
||||||
* $ref: "#/components/schemas/Transitions"
|
* data:
|
||||||
* 400:
|
* type: object
|
||||||
* description: Invalid ID supplied
|
* $ref: "#/components/schemas/Transitions"
|
||||||
* 401:
|
* responses:
|
||||||
* $ref: "#/components/responses/UnauthorizedError"
|
* 200:
|
||||||
* 404:
|
* description: The item was successfully updated
|
||||||
* description: Item not found
|
* 401:
|
||||||
* 500:
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
* description: Some server error
|
* 404:
|
||||||
*/
|
* description: Item not found
|
||||||
router.get('/:id', wrapAsync(async (req, res) => {
|
* 500:
|
||||||
const runtimeContext = req.runtimeContext;
|
* description: Some server error
|
||||||
const payload = await TransitionsDBApi.findBy(
|
* delete:
|
||||||
{ id: req.params.id },
|
* security:
|
||||||
{ runtimeContext },
|
* - bearerAuth: []
|
||||||
);
|
* tags: [Transitions]
|
||||||
|
* summary: Delete the selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: The item was successfully deleted
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
* get:
|
||||||
|
* security:
|
||||||
|
* - bearerAuth: []
|
||||||
|
* tags: [Transitions]
|
||||||
|
* summary: Get selected item
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: id
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Selected item successfully received
|
||||||
|
* 401:
|
||||||
|
* $ref: "#/components/responses/UnauthorizedError"
|
||||||
|
* 404:
|
||||||
|
* description: Item not found
|
||||||
|
* 500:
|
||||||
|
* description: Some server error
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = createEntityRouter('transitions', TransitionsService, TransitionsDBApi);
|
||||||
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}));
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|||||||
@ -1,103 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
|
|
||||||
const Ui_elementsService = require('../services/ui_elements');
|
|
||||||
const Ui_elementsDBApi = require('../db/api/ui_elements');
|
|
||||||
const wrapAsync = require('../helpers').wrapAsync;
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
const { parse } = require('json2csv');
|
|
||||||
|
|
||||||
const { checkCrudPermissions } = require('../middlewares/check-permissions');
|
|
||||||
|
|
||||||
router.use(checkCrudPermissions('page_elements'));
|
|
||||||
|
|
||||||
router.post(
|
|
||||||
'/',
|
|
||||||
wrapAsync(async (req, res) => {
|
|
||||||
await Ui_elementsService.create(req.body.data, req.currentUser);
|
|
||||||
res.status(200).send(true);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
router.post(
|
|
||||||
'/bulk-import',
|
|
||||||
wrapAsync(async (req, res) => {
|
|
||||||
await Ui_elementsService.bulkImport(req, res);
|
|
||||||
res.status(200).send(true);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
router.put(
|
|
||||||
'/:id',
|
|
||||||
wrapAsync(async (req, res) => {
|
|
||||||
await Ui_elementsService.update(req.body.data, req.body.id, req.currentUser);
|
|
||||||
res.status(200).send(true);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
router.delete(
|
|
||||||
'/:id',
|
|
||||||
wrapAsync(async (req, res) => {
|
|
||||||
await Ui_elementsService.remove(req.params.id, req.currentUser);
|
|
||||||
res.status(200).send(true);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
router.post(
|
|
||||||
'/deleteByIds',
|
|
||||||
wrapAsync(async (req, res) => {
|
|
||||||
await Ui_elementsService.deleteByIds(req.body.data, req.currentUser);
|
|
||||||
res.status(200).send(true);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
router.get(
|
|
||||||
'/',
|
|
||||||
wrapAsync(async (req, res) => {
|
|
||||||
const filetype = req.query.filetype;
|
|
||||||
|
|
||||||
const payload = await Ui_elementsDBApi.findAll(req.query, {
|
|
||||||
currentUser: req.currentUser,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (filetype && filetype === 'csv') {
|
|
||||||
const fields = ['id', 'name', 'element_type', 'settings_json', 'sort_order'];
|
|
||||||
const opts = { fields };
|
|
||||||
try {
|
|
||||||
const csv = parse(payload.rows, opts);
|
|
||||||
res.status(200).attachment(csv);
|
|
||||||
res.send(csv);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
router.get(
|
|
||||||
'/count',
|
|
||||||
wrapAsync(async (req, res) => {
|
|
||||||
const payload = await Ui_elementsDBApi.findAll(req.query, { countOnly: true, currentUser: req.currentUser });
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
router.get('/autocomplete', async (req, res) => {
|
|
||||||
const payload = await Ui_elementsDBApi.findAllAutocomplete(req.query.query, req.query.limit, req.query.offset);
|
|
||||||
res.status(200).send(payload);
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get(
|
|
||||||
'/:id',
|
|
||||||
wrapAsync(async (req, res) => {
|
|
||||||
const payload = await Ui_elementsDBApi.findBy({ id: req.params.id });
|
|
||||||
res.status(200).send(payload);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
router.use('/', require('../helpers').commonErrorHandler);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@ -120,6 +120,7 @@ module.exports = class ProjectsService {
|
|||||||
{
|
{
|
||||||
name: sourceAsset.name,
|
name: sourceAsset.name,
|
||||||
asset_type: sourceAsset.asset_type,
|
asset_type: sourceAsset.asset_type,
|
||||||
|
type: sourceAsset.type || 'general',
|
||||||
cdn_url: sourceAsset.cdn_url,
|
cdn_url: sourceAsset.cdn_url,
|
||||||
storage_key: sourceAsset.storage_key,
|
storage_key: sourceAsset.storage_key,
|
||||||
mime_type: sourceAsset.mime_type,
|
mime_type: sourceAsset.mime_type,
|
||||||
|
|||||||
@ -1,114 +0,0 @@
|
|||||||
const db = require('../db/models');
|
|
||||||
const Ui_elementsDBApi = require('../db/api/ui_elements');
|
|
||||||
const processFile = require('../middlewares/upload');
|
|
||||||
const ValidationError = require('./notifications/errors/validation');
|
|
||||||
const csv = require('csv-parser');
|
|
||||||
const stream = require('stream');
|
|
||||||
|
|
||||||
module.exports = class Ui_elementsService {
|
|
||||||
static async create(data, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
await Ui_elementsDBApi.create(data, {
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async bulkImport(req, res) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await processFile(req, res);
|
|
||||||
const bufferStream = new stream.PassThrough();
|
|
||||||
const results = [];
|
|
||||||
|
|
||||||
await bufferStream.end(Buffer.from(req.file.buffer, 'utf-8'));
|
|
||||||
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
bufferStream
|
|
||||||
.pipe(csv())
|
|
||||||
.on('data', (data) => results.push(data))
|
|
||||||
.on('end', async () => {
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.on('error', (error) => reject(error));
|
|
||||||
});
|
|
||||||
|
|
||||||
await Ui_elementsDBApi.bulkImport(results, {
|
|
||||||
transaction,
|
|
||||||
ignoreDuplicates: true,
|
|
||||||
validate: true,
|
|
||||||
currentUser: req.currentUser,
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(data, id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
try {
|
|
||||||
const ui_elements = await Ui_elementsDBApi.findBy(
|
|
||||||
{ id },
|
|
||||||
{ transaction },
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!ui_elements) {
|
|
||||||
throw new ValidationError('ui_elementsNotFound');
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedUiElements = await Ui_elementsDBApi.update(id, data, {
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
return updatedUiElements;
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteByIds(ids, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await Ui_elementsDBApi.deleteByIds(ids, {
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async remove(id, currentUser) {
|
|
||||||
const transaction = await db.sequelize.transaction();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await Ui_elementsDBApi.remove(id, {
|
|
||||||
currentUser,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
79
backend/src/utils/circuit-breaker.js
Normal file
79
backend/src/utils/circuit-breaker.js
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
const { logger } = require('./logger');
|
||||||
|
|
||||||
|
class CircuitBreaker {
|
||||||
|
constructor(options = {}) {
|
||||||
|
this.name = options.name || 'default';
|
||||||
|
this.failureThreshold = options.failureThreshold || 5;
|
||||||
|
this.resetTimeout = options.resetTimeout || 30000;
|
||||||
|
this.failures = 0;
|
||||||
|
this.state = 'CLOSED';
|
||||||
|
this.nextAttempt = Date.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
async execute(fn) {
|
||||||
|
if (this.state === 'OPEN') {
|
||||||
|
if (Date.now() < this.nextAttempt) {
|
||||||
|
logger.warn({ circuitBreaker: this.name, state: this.state }, 'Circuit breaker is OPEN, rejecting request');
|
||||||
|
throw new Error(`Circuit breaker ${this.name} is OPEN`);
|
||||||
|
}
|
||||||
|
this.state = 'HALF-OPEN';
|
||||||
|
logger.info({ circuitBreaker: this.name }, 'Circuit breaker moved to HALF-OPEN');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await fn();
|
||||||
|
this.onSuccess();
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
this.onFailure(error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSuccess() {
|
||||||
|
if (this.state === 'HALF-OPEN') {
|
||||||
|
logger.info({ circuitBreaker: this.name }, 'Circuit breaker recovered, moving to CLOSED');
|
||||||
|
}
|
||||||
|
this.failures = 0;
|
||||||
|
this.state = 'CLOSED';
|
||||||
|
}
|
||||||
|
|
||||||
|
onFailure(error) {
|
||||||
|
this.failures++;
|
||||||
|
logger.warn({
|
||||||
|
circuitBreaker: this.name,
|
||||||
|
failures: this.failures,
|
||||||
|
threshold: this.failureThreshold,
|
||||||
|
error: error.message,
|
||||||
|
}, 'Circuit breaker recorded failure');
|
||||||
|
|
||||||
|
if (this.failures >= this.failureThreshold) {
|
||||||
|
this.state = 'OPEN';
|
||||||
|
this.nextAttempt = Date.now() + this.resetTimeout;
|
||||||
|
logger.error({
|
||||||
|
circuitBreaker: this.name,
|
||||||
|
resetAt: new Date(this.nextAttempt).toISOString(),
|
||||||
|
}, 'Circuit breaker tripped to OPEN');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getState() {
|
||||||
|
return {
|
||||||
|
name: this.name,
|
||||||
|
state: this.state,
|
||||||
|
failures: this.failures,
|
||||||
|
nextAttempt: this.state === 'OPEN' ? new Date(this.nextAttempt).toISOString() : null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const circuitBreakers = new Map();
|
||||||
|
|
||||||
|
function getCircuitBreaker(name, options = {}) {
|
||||||
|
if (!circuitBreakers.has(name)) {
|
||||||
|
circuitBreakers.set(name, new CircuitBreaker({ name, ...options }));
|
||||||
|
}
|
||||||
|
return circuitBreakers.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { CircuitBreaker, getCircuitBreaker };
|
||||||
65
backend/src/utils/env-validation.js
Normal file
65
backend/src/utils/env-validation.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
const Joi = require('joi');
|
||||||
|
|
||||||
|
const envSchema = Joi.object({
|
||||||
|
NODE_ENV: Joi.string()
|
||||||
|
.valid('development', 'test', 'production', 'dev_stage')
|
||||||
|
.default('development'),
|
||||||
|
|
||||||
|
PORT: Joi.number().default(8080),
|
||||||
|
|
||||||
|
DB_HOST: Joi.string().default('localhost'),
|
||||||
|
DB_PORT: Joi.number().default(5432),
|
||||||
|
DB_NAME: Joi.string().default('db_tour_builder_platform'),
|
||||||
|
DB_USER: Joi.string().default('postgres'),
|
||||||
|
DB_PASS: Joi.string().allow('').default(''),
|
||||||
|
|
||||||
|
SECRET_KEY: Joi.string().min(16).default('88dbeaf8-e906-405e-9e41-c3baadeda5c6'),
|
||||||
|
|
||||||
|
ADMIN_PASS: Joi.string().default('88dbeaf8'),
|
||||||
|
USER_PASS: Joi.string().default('c3baadeda5c6'),
|
||||||
|
ADMIN_EMAIL: Joi.string().email().default('admin@flatlogic.com'),
|
||||||
|
|
||||||
|
GOOGLE_CLIENT_ID: Joi.string().allow('').default(''),
|
||||||
|
GOOGLE_CLIENT_SECRET: Joi.string().allow('').default(''),
|
||||||
|
MS_CLIENT_ID: Joi.string().allow('').default(''),
|
||||||
|
MS_CLIENT_SECRET: Joi.string().allow('').default(''),
|
||||||
|
|
||||||
|
AWS_ACCESS_KEY_ID: Joi.string().allow('').default(''),
|
||||||
|
AWS_SECRET_ACCESS_KEY: Joi.string().allow('').default(''),
|
||||||
|
AWS_S3_BUCKET: Joi.string().allow('').default(''),
|
||||||
|
AWS_S3_REGION: Joi.string().default('us-east-1'),
|
||||||
|
AWS_S3_PREFIX: Joi.string().default('afeefb9d49f5b7977577876b99532ac7'),
|
||||||
|
|
||||||
|
EMAIL_USER: Joi.string().allow('').default(''),
|
||||||
|
EMAIL_PASS: Joi.string().allow('').default(''),
|
||||||
|
EMAIL_TLS_REJECT_UNAUTHORIZED: Joi.string().valid('true', 'false').default('true'),
|
||||||
|
|
||||||
|
GPT_KEY: Joi.string().allow('').default(''),
|
||||||
|
PEXELS_KEY: Joi.string().allow('').default(''),
|
||||||
|
|
||||||
|
LOG_LEVEL: Joi.string()
|
||||||
|
.valid('fatal', 'error', 'warn', 'info', 'debug', 'trace')
|
||||||
|
.default('info'),
|
||||||
|
}).unknown(true);
|
||||||
|
|
||||||
|
function validateEnv() {
|
||||||
|
const { error, value } = envSchema.validate(process.env, {
|
||||||
|
abortEarly: false,
|
||||||
|
stripUnknown: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
const messages = error.details.map(d => ` - ${d.message}`).join('\n');
|
||||||
|
console.error('Environment validation failed:\n' + messages);
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === 'production') {
|
||||||
|
process.exit(1);
|
||||||
|
} else {
|
||||||
|
console.warn('Continuing with default values in non-production mode');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { validateEnv, envSchema };
|
||||||
48
backend/src/utils/errors.js
Normal file
48
backend/src/utils/errors.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
class AppError extends Error {
|
||||||
|
constructor(message, statusCode = 500, details = null) {
|
||||||
|
super(message);
|
||||||
|
this.statusCode = statusCode;
|
||||||
|
this.details = details;
|
||||||
|
this.isOperational = true;
|
||||||
|
Error.captureStackTrace(this, this.constructor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotFoundError extends AppError {
|
||||||
|
constructor(resource = 'Resource') {
|
||||||
|
super(`${resource} not found`, 404);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ValidationError extends AppError {
|
||||||
|
constructor(message, details = null) {
|
||||||
|
super(message, 400, details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ForbiddenError extends AppError {
|
||||||
|
constructor(message = 'Access denied') {
|
||||||
|
super(message, 403);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UnauthorizedError extends AppError {
|
||||||
|
constructor(message = 'Unauthorized') {
|
||||||
|
super(message, 401);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConflictError extends AppError {
|
||||||
|
constructor(message = 'Resource conflict') {
|
||||||
|
super(message, 409);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
AppError,
|
||||||
|
NotFoundError,
|
||||||
|
ValidationError,
|
||||||
|
ForbiddenError,
|
||||||
|
UnauthorizedError,
|
||||||
|
ConflictError,
|
||||||
|
};
|
||||||
53
backend/src/utils/events.js
Normal file
53
backend/src/utils/events.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
const EventEmitter = require('events');
|
||||||
|
const { logger } = require('./logger');
|
||||||
|
|
||||||
|
class AppEventEmitter extends EventEmitter {
|
||||||
|
emit(event, data) {
|
||||||
|
logger.debug({ event, hasListeners: this.listenerCount(event) > 0 }, 'Event emitted');
|
||||||
|
return super.emit(event, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
async emitAsync(event, data) {
|
||||||
|
logger.debug({ event, listenerCount: this.listenerCount(event) }, 'Async event emitted');
|
||||||
|
const results = await Promise.allSettled(
|
||||||
|
this.listeners(event).map(listener => listener(data))
|
||||||
|
);
|
||||||
|
|
||||||
|
const failures = results.filter(r => r.status === 'rejected');
|
||||||
|
if (failures.length > 0) {
|
||||||
|
logger.warn({ event, failures: failures.map(f => f.reason?.message) }, 'Some event listeners failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
onAsync(event, listener) {
|
||||||
|
this.on(event, async (data) => {
|
||||||
|
try {
|
||||||
|
await listener(data);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error({ event, error: error.message }, 'Async event listener error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const appEvents = new AppEventEmitter();
|
||||||
|
|
||||||
|
appEvents.on('user.created', (user) => {
|
||||||
|
logger.info({ userId: user.id, email: user.email }, 'User created event received');
|
||||||
|
});
|
||||||
|
|
||||||
|
appEvents.on('project.created', (project) => {
|
||||||
|
logger.info({ projectId: project.id, name: project.name }, 'Project created event received');
|
||||||
|
});
|
||||||
|
|
||||||
|
appEvents.on('project.published', (project) => {
|
||||||
|
logger.info({ projectId: project.id, slug: project.slug }, 'Project published event received');
|
||||||
|
});
|
||||||
|
|
||||||
|
appEvents.on('error', (error) => {
|
||||||
|
logger.error({ error: error.message }, 'Application event error');
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = { appEvents, AppEventEmitter };
|
||||||
7
backend/src/utils/index.js
Normal file
7
backend/src/utils/index.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module.exports = {
|
||||||
|
...require('./errors'),
|
||||||
|
...require('./logger'),
|
||||||
|
...require('./circuit-breaker'),
|
||||||
|
...require('./events'),
|
||||||
|
envValidation: require('./env-validation'),
|
||||||
|
};
|
||||||
46
backend/src/utils/logger.js
Normal file
46
backend/src/utils/logger.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
const pino = require('pino');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
|
||||||
|
const isDevelopment = process.env.NODE_ENV === 'development';
|
||||||
|
|
||||||
|
const logger = pino({
|
||||||
|
level: process.env.LOG_LEVEL || 'info',
|
||||||
|
transport: isDevelopment
|
||||||
|
? { target: 'pino-pretty', options: { colorize: true } }
|
||||||
|
: undefined,
|
||||||
|
base: {
|
||||||
|
service: 'tour-builder-api',
|
||||||
|
env: process.env.NODE_ENV || 'development',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function requestLogger(req, res, next) {
|
||||||
|
const requestId = req.headers['x-request-id'] || crypto.randomUUID();
|
||||||
|
req.log = logger.child({ requestId });
|
||||||
|
req.requestId = requestId;
|
||||||
|
res.setHeader('X-Request-Id', requestId);
|
||||||
|
|
||||||
|
const start = Date.now();
|
||||||
|
res.on('finish', () => {
|
||||||
|
const duration = Date.now() - start;
|
||||||
|
const logData = {
|
||||||
|
method: req.method,
|
||||||
|
url: req.originalUrl || req.url,
|
||||||
|
status: res.statusCode,
|
||||||
|
duration,
|
||||||
|
userAgent: req.headers['user-agent'],
|
||||||
|
};
|
||||||
|
|
||||||
|
if (res.statusCode >= 500) {
|
||||||
|
req.log.error(logData, 'Request completed with server error');
|
||||||
|
} else if (res.statusCode >= 400) {
|
||||||
|
req.log.warn(logData, 'Request completed with client error');
|
||||||
|
} else {
|
||||||
|
req.log.info(logData, 'Request completed');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { logger, requestLogger };
|
||||||
2650
backend/yarn.lock
2650
backend/yarn.lock
File diff suppressed because it is too large
Load Diff
1
frontend/json/runtimeError.json
Normal file
1
frontend/json/runtimeError.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@ -12,11 +12,11 @@
|
|||||||
"@emotion/styled": "^11.11.0",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@mdi/js": "^7.4.47",
|
"@mdi/js": "^7.4.47",
|
||||||
"@mui/material": "^6.3.0",
|
"@mui/material": "^6.3.0",
|
||||||
"@mui/x-data-grid": "^6.19.2",
|
"@mui/x-data-grid": "^7.0.0",
|
||||||
"@reduxjs/toolkit": "^2.1.0",
|
"@reduxjs/toolkit": "^2.1.0",
|
||||||
"@tailwindcss/typography": "^0.5.13",
|
"@tailwindcss/typography": "^0.5.13",
|
||||||
"@tinymce/tinymce-react": "^4.3.2",
|
"@tinymce/tinymce-react": "^4.3.2",
|
||||||
"apexcharts": "^3.45.2",
|
"apexcharts": "^5.0.0",
|
||||||
"axios": "^1.8.4",
|
"axios": "^1.8.4",
|
||||||
"chart.js": "^4.4.1",
|
"chart.js": "^4.4.1",
|
||||||
"chroma-js": "^2.4.2",
|
"chroma-js": "^2.4.2",
|
||||||
@ -30,7 +30,7 @@
|
|||||||
"intro.js": "^7.2.0",
|
"intro.js": "^7.2.0",
|
||||||
"intro.js-react": "^1.0.0",
|
"intro.js-react": "^1.0.0",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^4.0.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"next": "^15.3.1",
|
"next": "^15.3.1",
|
||||||
@ -38,21 +38,22 @@
|
|||||||
"numeral": "^2.0.6",
|
"numeral": "^2.0.6",
|
||||||
"query-string": "^8.1.0",
|
"query-string": "^8.1.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-apexcharts": "^1.4.1",
|
"react-apexcharts": "^2.0.0",
|
||||||
"react-big-calendar": "^1.10.3",
|
"react-big-calendar": "^1.19.0",
|
||||||
"react-chartjs-2": "^4.3.1",
|
"react-chartjs-2": "^5.0.0",
|
||||||
"react-datepicker": "^4.10.0",
|
"react-datepicker": "^7.0.0",
|
||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-i18next": "^15.5.1",
|
"react-i18next": "^15.5.1",
|
||||||
"react-redux": "^8.0.2",
|
"react-redux": "^9.0.0",
|
||||||
"react-select": "^5.7.0",
|
"react-select": "^5.7.0",
|
||||||
"react-select-async-paginate": "^0.7.9",
|
"react-select-async-paginate": "^0.7.9",
|
||||||
"react-switch": "^7.0.0",
|
"react-switch": "^7.0.0",
|
||||||
"react-toastify": "^11.0.2",
|
"react-toastify": "^11.0.2",
|
||||||
"swr": "^1.3.0",
|
"swr": "^2.0.0",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0",
|
||||||
|
"zod": "^4.3.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/forms": "^0.5.7",
|
"@tailwindcss/forms": "^0.5.7",
|
||||||
|
|||||||
99
frontend/public/offline.html
Normal file
99
frontend/public/offline.html
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Offline - Tour Builder</title>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||||
|
background-color: #1f2937;
|
||||||
|
color: #ffffff;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #9ca3af;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.retry-btn {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
background-color: #3b82f6;
|
||||||
|
color: #ffffff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.retry-btn:hover {
|
||||||
|
background-color: #2563eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.retry-btn:active {
|
||||||
|
background-color: #1d4ed8;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||||
|
<path d="M18.364 5.636a9 9 0 010 12.728M5.636 18.364a9 9 0 010-12.728" />
|
||||||
|
<path d="M15.536 8.464a5 5 0 010 7.072M8.464 15.536a5 5 0 010-7.072" />
|
||||||
|
<circle cx="12" cy="12" r="1" fill="currentColor" />
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<h1>You're Offline</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
It looks like you've lost your internet connection.
|
||||||
|
Some features may not be available until you're back online.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<button class="retry-btn" onclick="window.location.reload()">
|
||||||
|
Try Again
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Auto-retry when connection is restored
|
||||||
|
window.addEventListener('online', () => {
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
210
frontend/public/sw.js
Normal file
210
frontend/public/sw.js
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
/**
|
||||||
|
* Tour Builder Platform - Service Worker
|
||||||
|
*
|
||||||
|
* Provides offline caching for PWA functionality.
|
||||||
|
* Caches tour assets (images, videos, audio) for offline viewing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const CACHE_NAME = 'tour-builder-v1';
|
||||||
|
const STATIC_CACHE_NAME = 'tour-builder-static-v1';
|
||||||
|
const DYNAMIC_CACHE_NAME = 'tour-builder-dynamic-v1';
|
||||||
|
|
||||||
|
// Static assets to cache on install
|
||||||
|
const STATIC_ASSETS = [
|
||||||
|
'/',
|
||||||
|
'/runtime',
|
||||||
|
'/offline.html',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Asset types to cache
|
||||||
|
const CACHEABLE_EXTENSIONS = [
|
||||||
|
'.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg', '.ico',
|
||||||
|
'.mp4', '.webm', '.mov',
|
||||||
|
'.mp3', '.wav', '.ogg', '.m4a',
|
||||||
|
'.woff', '.woff2', '.ttf', '.eot',
|
||||||
|
'.css', '.js',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Check if request should be cached
|
||||||
|
const isCacheableRequest = (request) => {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
|
||||||
|
// Don't cache API requests (except static assets from /file/download)
|
||||||
|
if (url.pathname.startsWith('/api/') && !url.pathname.includes('/file/download')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache known asset extensions
|
||||||
|
const hasExtension = CACHEABLE_EXTENSIONS.some((ext) => url.pathname.toLowerCase().endsWith(ext));
|
||||||
|
if (hasExtension) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache file downloads (S3 presigned URLs, CDN assets)
|
||||||
|
if (url.pathname.includes('/file/download') || url.hostname.includes('amazonaws.com') || url.hostname.includes('cloudfront.net')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Install event - cache static assets
|
||||||
|
self.addEventListener('install', (event) => {
|
||||||
|
event.waitUntil(
|
||||||
|
caches.open(STATIC_CACHE_NAME).then((cache) => {
|
||||||
|
console.log('[SW] Caching static assets');
|
||||||
|
return cache.addAll(STATIC_ASSETS).catch((error) => {
|
||||||
|
console.warn('[SW] Failed to cache some static assets:', error);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
self.skipWaiting();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Activate event - clean up old caches
|
||||||
|
self.addEventListener('activate', (event) => {
|
||||||
|
event.waitUntil(
|
||||||
|
caches.keys().then((cacheNames) => {
|
||||||
|
return Promise.all(
|
||||||
|
cacheNames
|
||||||
|
.filter((name) => {
|
||||||
|
return name.startsWith('tour-builder-') && name !== STATIC_CACHE_NAME && name !== DYNAMIC_CACHE_NAME;
|
||||||
|
})
|
||||||
|
.map((name) => {
|
||||||
|
console.log('[SW] Deleting old cache:', name);
|
||||||
|
return caches.delete(name);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
self.clients.claim();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fetch event - serve from cache or network
|
||||||
|
self.addEventListener('fetch', (event) => {
|
||||||
|
const { request } = event;
|
||||||
|
|
||||||
|
// Only handle GET requests
|
||||||
|
if (request.method !== 'GET') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip non-http(s) requests
|
||||||
|
if (!request.url.startsWith('http')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
event.respondWith(
|
||||||
|
caches.match(request).then((cachedResponse) => {
|
||||||
|
// Return cached response if available
|
||||||
|
if (cachedResponse) {
|
||||||
|
// Optionally update cache in background (stale-while-revalidate)
|
||||||
|
if (isCacheableRequest(request)) {
|
||||||
|
event.waitUntil(
|
||||||
|
fetch(request)
|
||||||
|
.then((networkResponse) => {
|
||||||
|
if (networkResponse && networkResponse.status === 200) {
|
||||||
|
const responseToCache = networkResponse.clone();
|
||||||
|
caches.open(DYNAMIC_CACHE_NAME).then((cache) => {
|
||||||
|
cache.put(request, responseToCache);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// Network failed, but we have cache - that's fine
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return cachedResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch from network
|
||||||
|
return fetch(request)
|
||||||
|
.then((networkResponse) => {
|
||||||
|
// Cache successful responses for cacheable requests
|
||||||
|
if (networkResponse && networkResponse.status === 200 && isCacheableRequest(request)) {
|
||||||
|
const responseToCache = networkResponse.clone();
|
||||||
|
caches.open(DYNAMIC_CACHE_NAME).then((cache) => {
|
||||||
|
cache.put(request, responseToCache);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return networkResponse;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.warn('[SW] Fetch failed:', error);
|
||||||
|
|
||||||
|
// Return offline page for navigation requests
|
||||||
|
if (request.mode === 'navigate') {
|
||||||
|
return caches.match('/offline.html');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return empty response for assets
|
||||||
|
return new Response('', {
|
||||||
|
status: 503,
|
||||||
|
statusText: 'Service Unavailable',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Message event - handle commands from main thread
|
||||||
|
self.addEventListener('message', (event) => {
|
||||||
|
const { type, payload } = event.data || {};
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'CACHE_ASSETS':
|
||||||
|
// Cache specific assets for a project/page
|
||||||
|
if (Array.isArray(payload?.urls)) {
|
||||||
|
event.waitUntil(
|
||||||
|
caches.open(DYNAMIC_CACHE_NAME).then((cache) => {
|
||||||
|
return Promise.all(
|
||||||
|
payload.urls.map((url) =>
|
||||||
|
fetch(url)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
return cache.put(url, response);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.warn('[SW] Failed to cache asset:', url, error);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'CLEAR_CACHE':
|
||||||
|
// Clear all dynamic caches
|
||||||
|
event.waitUntil(
|
||||||
|
caches.delete(DYNAMIC_CACHE_NAME).then(() => {
|
||||||
|
console.log('[SW] Dynamic cache cleared');
|
||||||
|
})
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'GET_CACHE_STATUS':
|
||||||
|
// Return current cache status
|
||||||
|
event.waitUntil(
|
||||||
|
caches.open(DYNAMIC_CACHE_NAME).then((cache) => {
|
||||||
|
return cache.keys().then((keys) => {
|
||||||
|
event.source.postMessage({
|
||||||
|
type: 'CACHE_STATUS',
|
||||||
|
payload: {
|
||||||
|
cachedCount: keys.length,
|
||||||
|
urls: keys.map((request) => request.url),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('[SW] Service worker loaded');
|
||||||
@ -1,21 +1,22 @@
|
|||||||
import type { ColorButtonKey } from './interfaces'
|
import type { ColorButtonKey } from './interfaces';
|
||||||
|
|
||||||
export const gradientBgBase = 'bg-gradient-to-tr'
|
export const gradientBgBase = 'bg-gradient-to-tr';
|
||||||
export const colorBgBase = "bg-violet-50/50"
|
export const colorBgBase = 'bg-violet-50/50';
|
||||||
export const gradientBgPurplePink = `${gradientBgBase} from-purple-400 via-pink-500 to-red-500`
|
export const gradientBgPurplePink = `${gradientBgBase} from-purple-400 via-pink-500 to-red-500`;
|
||||||
export const gradientBgViolet = `${gradientBgBase} ${colorBgBase}`
|
export const gradientBgViolet = `${gradientBgBase} ${colorBgBase}`;
|
||||||
export const gradientBgDark = `${gradientBgBase} from-dark-700 via-dark-900 to-dark-800`;
|
export const gradientBgDark = `${gradientBgBase} from-dark-700 via-dark-900 to-dark-800`;
|
||||||
export const gradientBgPinkRed = `${gradientBgBase} from-pink-400 via-red-500 to-yellow-500`
|
export const gradientBgPinkRed = `${gradientBgBase} from-pink-400 via-red-500 to-yellow-500`;
|
||||||
|
|
||||||
export const colorsBgLight = {
|
export const colorsBgLight = {
|
||||||
white: 'bg-white text-black',
|
white: 'bg-white text-black',
|
||||||
light: ' bg-white text-black text-black dark:bg-dark-900 dark:text-white',
|
light: ' bg-white text-black text-black dark:bg-dark-900 dark:text-white',
|
||||||
contrast: 'bg-gray-800 text-white dark:bg-white dark:text-black',
|
contrast: 'bg-gray-800 text-white dark:bg-white dark:text-black',
|
||||||
success: 'bg-emerald-500 border-emerald-500 dark:bg-pavitra-blue dark:border-pavitra-blue text-white',
|
success:
|
||||||
|
'bg-emerald-500 border-emerald-500 dark:bg-pavitra-blue dark:border-pavitra-blue text-white',
|
||||||
danger: 'bg-red-500 border-red-500 text-white',
|
danger: 'bg-red-500 border-red-500 text-white',
|
||||||
warning: 'bg-yellow-500 border-yellow-500 text-white',
|
warning: 'bg-yellow-500 border-yellow-500 text-white',
|
||||||
info: 'bg-blue-500 border-blue-500 dark:bg-pavitra-blue dark:border-pavitra-blue text-white',
|
info: 'bg-blue-500 border-blue-500 dark:bg-pavitra-blue dark:border-pavitra-blue text-white',
|
||||||
}
|
};
|
||||||
|
|
||||||
export const colorsText = {
|
export const colorsText = {
|
||||||
white: 'text-black dark:text-slate-100',
|
white: 'text-black dark:text-slate-100',
|
||||||
@ -30,7 +31,9 @@ export const colorsText = {
|
|||||||
export const colorsOutline = {
|
export const colorsOutline = {
|
||||||
white: [colorsText.white, 'border-gray-100'].join(' '),
|
white: [colorsText.white, 'border-gray-100'].join(' '),
|
||||||
light: [colorsText.light, 'border-gray-100'].join(' '),
|
light: [colorsText.light, 'border-gray-100'].join(' '),
|
||||||
contrast: [colorsText.contrast, 'border-gray-900 dark:border-slate-100'].join(' '),
|
contrast: [colorsText.contrast, 'border-gray-900 dark:border-slate-100'].join(
|
||||||
|
' ',
|
||||||
|
),
|
||||||
success: [colorsText.success, 'border-emerald-500'].join(' '),
|
success: [colorsText.success, 'border-emerald-500'].join(' '),
|
||||||
danger: [colorsText.danger, 'border-red-500'].join(' '),
|
danger: [colorsText.danger, 'border-red-500'].join(' '),
|
||||||
warning: [colorsText.warning, 'border-yellow-500'].join(' '),
|
warning: [colorsText.warning, 'border-yellow-500'].join(' '),
|
||||||
@ -41,10 +44,10 @@ export const getButtonColor = (
|
|||||||
color: ColorButtonKey,
|
color: ColorButtonKey,
|
||||||
isOutlined: boolean,
|
isOutlined: boolean,
|
||||||
hasHover: boolean,
|
hasHover: boolean,
|
||||||
isActive = false
|
isActive = false,
|
||||||
) => {
|
) => {
|
||||||
if (color === 'void') {
|
if (color === 'void') {
|
||||||
return ''
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const colors = {
|
const colors = {
|
||||||
@ -56,7 +59,7 @@ export const getButtonColor = (
|
|||||||
success: 'ring-emerald-300 dark:ring-pavitra-blue',
|
success: 'ring-emerald-300 dark:ring-pavitra-blue',
|
||||||
danger: 'ring-red-300 dark:ring-red-700',
|
danger: 'ring-red-300 dark:ring-red-700',
|
||||||
warning: 'ring-yellow-300 dark:ring-yellow-700',
|
warning: 'ring-yellow-300 dark:ring-yellow-700',
|
||||||
info: "ring-blue-300 dark:ring-pavitra-blue",
|
info: 'ring-blue-300 dark:ring-pavitra-blue',
|
||||||
},
|
},
|
||||||
active: {
|
active: {
|
||||||
white: 'bg-gray-100',
|
white: 'bg-gray-100',
|
||||||
@ -76,7 +79,7 @@ export const getButtonColor = (
|
|||||||
success: 'bg-emerald-600 dark:bg-pavitra-blue text-white',
|
success: 'bg-emerald-600 dark:bg-pavitra-blue text-white',
|
||||||
danger: 'bg-red-600 text-white dark:bg-red-500 ',
|
danger: 'bg-red-600 text-white dark:bg-red-500 ',
|
||||||
warning: 'bg-yellow-600 dark:bg-yellow-500 text-white',
|
warning: 'bg-yellow-600 dark:bg-yellow-500 text-white',
|
||||||
info: " bg-blue-600 dark:bg-pavitra-blue text-white ",
|
info: ' bg-blue-600 dark:bg-pavitra-blue text-white ',
|
||||||
},
|
},
|
||||||
bgHover: {
|
bgHover: {
|
||||||
white: 'hover:bg-gray-100',
|
white: 'hover:bg-gray-100',
|
||||||
@ -84,12 +87,12 @@ export const getButtonColor = (
|
|||||||
lightDark: 'hover:bg-gray-200 hover:dark:bg-slate-700',
|
lightDark: 'hover:bg-gray-200 hover:dark:bg-slate-700',
|
||||||
contrast: 'hover:bg-gray-700 hover:dark:bg-slate-100',
|
contrast: 'hover:bg-gray-700 hover:dark:bg-slate-100',
|
||||||
success:
|
success:
|
||||||
'hover:bg-emerald-700 hover:border-emerald-700 hover:dark:bg-pavitra-blue hover:dark:border-pavitra-blue',
|
'hover:bg-emerald-700 hover:border-emerald-700 hover:dark:bg-pavitra-blue hover:dark:border-pavitra-blue',
|
||||||
danger:
|
danger:
|
||||||
'hover:bg-red-700 hover:border-red-700 hover:dark:bg-red-600 hover:dark:border-red-600',
|
'hover:bg-red-700 hover:border-red-700 hover:dark:bg-red-600 hover:dark:border-red-600',
|
||||||
warning:
|
warning:
|
||||||
'hover:bg-yellow-700 hover:border-yellow-700 hover:dark:bg-yellow-600 hover:dark:border-yellow-600',
|
'hover:bg-yellow-700 hover:border-yellow-700 hover:dark:bg-yellow-600 hover:dark:border-yellow-600',
|
||||||
info: "hover:bg-blue-700 hover:border-blue-700 hover:dark:bg-pavitra-blue/80 hover:dark:border-pavitra-blue/80",
|
info: 'hover:bg-blue-700 hover:border-blue-700 hover:dark:bg-pavitra-blue/80 hover:dark:border-pavitra-blue/80',
|
||||||
},
|
},
|
||||||
borders: {
|
borders: {
|
||||||
white: 'border-white',
|
white: 'border-white',
|
||||||
@ -99,7 +102,7 @@ export const getButtonColor = (
|
|||||||
success: 'border-emerald-600 dark:border-pavitra-blue',
|
success: 'border-emerald-600 dark:border-pavitra-blue',
|
||||||
danger: 'border-red-600 dark:border-red-500',
|
danger: 'border-red-600 dark:border-red-500',
|
||||||
warning: 'border-yellow-600 dark:border-yellow-500',
|
warning: 'border-yellow-600 dark:border-yellow-500',
|
||||||
info: "border-blue-600 border-blue-600 dark:border-pavitra-blue",
|
info: 'border-blue-600 border-blue-600 dark:border-pavitra-blue',
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
contrast: 'dark:text-slate-100',
|
contrast: 'dark:text-slate-100',
|
||||||
@ -111,28 +114,32 @@ export const getButtonColor = (
|
|||||||
outlineHover: {
|
outlineHover: {
|
||||||
contrast:
|
contrast:
|
||||||
'hover:bg-gray-800 hover:text-gray-100 hover:dark:bg-slate-100 hover:dark:text-black',
|
'hover:bg-gray-800 hover:text-gray-100 hover:dark:bg-slate-100 hover:dark:text-black',
|
||||||
success: 'hover:bg-emerald-600 hover:text-white hover:text-white hover:dark:text-white hover:dark:border-pavitra-blue',
|
success:
|
||||||
|
'hover:bg-emerald-600 hover:text-white hover:text-white hover:dark:text-white hover:dark:border-pavitra-blue',
|
||||||
danger:
|
danger:
|
||||||
'hover:bg-red-600 hover:text-white hover:text-white hover:dark:text-white hover:dark:border-red-600',
|
'hover:bg-red-600 hover:text-white hover:text-white hover:dark:text-white hover:dark:border-red-600',
|
||||||
warning:
|
warning:
|
||||||
'hover:bg-yellow-600 hover:text-white hover:text-white hover:dark:text-white hover:dark:border-yellow-600',
|
'hover:bg-yellow-600 hover:text-white hover:text-white hover:dark:text-white hover:dark:border-yellow-600',
|
||||||
info: "hover:bg-blue-600 hover:bg-blue-600 hover:text-white hover:dark:text-white hover:dark:border-pavitra-blue",
|
info: 'hover:bg-blue-600 hover:bg-blue-600 hover:text-white hover:dark:text-white hover:dark:border-pavitra-blue',
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
const isOutlinedProcessed = isOutlined && ['white', 'whiteDark', 'lightDark'].indexOf(color) < 0
|
const isOutlinedProcessed =
|
||||||
|
isOutlined && ['white', 'whiteDark', 'lightDark'].indexOf(color) < 0;
|
||||||
|
|
||||||
const base = [colors.borders[color], colors.ring[color]]
|
const base = [colors.borders[color], colors.ring[color]];
|
||||||
|
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
base.push(colors.active[color])
|
base.push(colors.active[color]);
|
||||||
} else {
|
} else {
|
||||||
base.push(isOutlinedProcessed ? colors.text[color] : colors.bg[color])
|
base.push(isOutlinedProcessed ? colors.text[color] : colors.bg[color]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasHover) {
|
if (hasHover) {
|
||||||
base.push(isOutlinedProcessed ? colors.outlineHover[color] : colors.bgHover[color])
|
base.push(
|
||||||
|
isOutlinedProcessed ? colors.outlineHover[color] : colors.bgHover[color],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.join(' ')
|
return base.join(' ');
|
||||||
}
|
};
|
||||||
|
|||||||
@ -4,12 +4,11 @@ import ListActionsPopover from '../ListActionsPopover';
|
|||||||
import { useAppSelector } from '../../stores/hooks';
|
import { useAppSelector } from '../../stores/hooks';
|
||||||
import dataFormatter from '../../helpers/dataFormatter';
|
import dataFormatter from '../../helpers/dataFormatter';
|
||||||
import { Pagination } from '../Pagination';
|
import { Pagination } from '../Pagination';
|
||||||
import {saveFile} from "../../helpers/fileSaver";
|
import { saveFile } from '../../helpers/fileSaver';
|
||||||
import LoadingSpinner from "../LoadingSpinner";
|
import LoadingSpinner from '../LoadingSpinner';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
||||||
import {hasPermission} from "../../helpers/userPermissions";
|
import { hasPermission } from '../../helpers/userPermissions';
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
access_logs: any[];
|
access_logs: any[];
|
||||||
@ -28,17 +27,16 @@ const CardAccess_logs = ({
|
|||||||
numPages,
|
numPages,
|
||||||
onPageChange,
|
onPageChange,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const asideScrollbarsStyle = useAppSelector(
|
const asideScrollbarsStyle = useAppSelector(
|
||||||
(state) => state.style.asideScrollbarsStyle,
|
(state) => state.style.asideScrollbarsStyle,
|
||||||
);
|
);
|
||||||
const bgColor = useAppSelector((state) => state.style.cardsColor);
|
const bgColor = useAppSelector((state) => state.style.cardsColor);
|
||||||
const darkMode = useAppSelector((state) => state.style.darkMode);
|
const darkMode = useAppSelector((state) => state.style.darkMode);
|
||||||
const corners = useAppSelector((state) => state.style.corners);
|
const corners = useAppSelector((state) => state.style.corners);
|
||||||
const focusRing = useAppSelector((state) => state.style.focusRingColor);
|
const focusRing = useAppSelector((state) => state.style.focusRingColor);
|
||||||
|
|
||||||
const currentUser = useAppSelector((state) => state.auth.currentUser);
|
|
||||||
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_ACCESS_LOGS')
|
|
||||||
|
|
||||||
|
const currentUser = useAppSelector((state) => state.auth.currentUser);
|
||||||
|
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_ACCESS_LOGS');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'p-4'}>
|
<div className={'p-4'}>
|
||||||
@ -47,122 +45,108 @@ const CardAccess_logs = ({
|
|||||||
role='list'
|
role='list'
|
||||||
className='grid grid-cols-1 gap-x-6 gap-y-8 lg:grid-cols-3 2xl:grid-cols-4 xl:gap-x-8'
|
className='grid grid-cols-1 gap-x-6 gap-y-8 lg:grid-cols-3 2xl:grid-cols-4 xl:gap-x-8'
|
||||||
>
|
>
|
||||||
{!loading && access_logs.map((item, index) => (
|
{!loading &&
|
||||||
<li
|
access_logs.map((item, index) => (
|
||||||
key={item.id}
|
<li
|
||||||
className={`overflow-hidden ${corners !== 'rounded-full'? corners : 'rounded-3xl'} border ${focusRing} border-gray-200 dark:border-dark-700 ${
|
key={item.id}
|
||||||
|
className={`overflow-hidden ${corners !== 'rounded-full' ? corners : 'rounded-3xl'} border ${focusRing} border-gray-200 dark:border-dark-700 ${
|
||||||
darkMode ? 'aside-scrollbars-[slate]' : asideScrollbarsStyle
|
darkMode ? 'aside-scrollbars-[slate]' : asideScrollbarsStyle
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
<div className={`flex items-center ${bgColor} p-6 gap-x-4 border-b border-gray-900/5 bg-gray-50 dark:bg-dark-800 relative`}>
|
className={`flex items-center ${bgColor} p-6 gap-x-4 border-b border-gray-900/5 bg-gray-50 dark:bg-dark-800 relative`}
|
||||||
|
>
|
||||||
<Link href={`/access_logs/access_logs-view/?id=${item.id}`} className='text-lg font-bold leading-6 line-clamp-1'>
|
<Link
|
||||||
{item.path}
|
href={`/access_logs/access_logs-view/?id=${item.id}`}
|
||||||
|
className='text-lg font-bold leading-6 line-clamp-1'
|
||||||
|
>
|
||||||
|
{item.path}
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
|
<div className='ml-auto '>
|
||||||
<div className='ml-auto '>
|
<ListActionsPopover
|
||||||
<ListActionsPopover
|
onDelete={onDelete}
|
||||||
onDelete={onDelete}
|
itemId={item.id}
|
||||||
itemId={item.id}
|
pathEdit={`/access_logs/access_logs-edit/?id=${item.id}`}
|
||||||
pathEdit={`/access_logs/access_logs-edit/?id=${item.id}`}
|
pathView={`/access_logs/access_logs-view/?id=${item.id}`}
|
||||||
pathView={`/access_logs/access_logs-view/?id=${item.id}`}
|
hasUpdatePermission={hasUpdatePermission}
|
||||||
|
/>
|
||||||
hasUpdatePermission={hasUpdatePermission}
|
</div>
|
||||||
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<dl className='divide-y divide-stone-300 dark:divide-dark-700 px-6 py-4 text-sm leading-6 h-64 overflow-y-auto'>
|
||||||
<dl className='divide-y divide-stone-300 dark:divide-dark-700 px-6 py-4 text-sm leading-6 h-64 overflow-y-auto'>
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Project</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Project
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ dataFormatter.projectsOneListFormatter(item.project) }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{dataFormatter.projectsOneListFormatter(item.project)}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Environment</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Environment
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ item.environment }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.environment}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>User</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>User</dt>
|
||||||
<dd className='flex items-start gap-x-2'>
|
<dd className='flex items-start gap-x-2'>
|
||||||
<div className='font-medium line-clamp-4'>
|
<div className='font-medium line-clamp-4'>
|
||||||
{ dataFormatter.usersOneListFormatter(item.user) }
|
{dataFormatter.usersOneListFormatter(item.user)}
|
||||||
</div>
|
</div>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Path</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>Path</dt>
|
||||||
<dd className='flex items-start gap-x-2'>
|
<dd className='flex items-start gap-x-2'>
|
||||||
<div className='font-medium line-clamp-4'>
|
<div className='font-medium line-clamp-4'>{item.path}</div>
|
||||||
{ item.path }
|
</dd>
|
||||||
</div>
|
|
||||||
</dd>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>IPaddress</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
IPaddress
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ item.ip_address }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.ip_address}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Useragent</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Useragent
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ item.user_agent }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.user_agent}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Accessedat</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Accessedat
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ dataFormatter.dateTimeFormatter(item.accessed_at) }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{dataFormatter.dateTimeFormatter(item.accessed_at)}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
</dl>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
{!loading && access_logs.length === 0 && (
|
{!loading && access_logs.length === 0 && (
|
||||||
<div className='col-span-full flex items-center justify-center h-40'>
|
<div className='col-span-full flex items-center justify-center h-40'>
|
||||||
<p className=''>No data to display</p>
|
<p className=''>No data to display</p>
|
||||||
|
|||||||
@ -2,135 +2,122 @@ import React from 'react';
|
|||||||
import CardBox from '../CardBox';
|
import CardBox from '../CardBox';
|
||||||
import ImageField from '../ImageField';
|
import ImageField from '../ImageField';
|
||||||
import dataFormatter from '../../helpers/dataFormatter';
|
import dataFormatter from '../../helpers/dataFormatter';
|
||||||
import {saveFile} from "../../helpers/fileSaver";
|
import { saveFile } from '../../helpers/fileSaver';
|
||||||
import ListActionsPopover from "../ListActionsPopover";
|
import ListActionsPopover from '../ListActionsPopover';
|
||||||
import {useAppSelector} from "../../stores/hooks";
|
import { useAppSelector } from '../../stores/hooks';
|
||||||
import {Pagination} from "../Pagination";
|
import { Pagination } from '../Pagination';
|
||||||
import LoadingSpinner from "../LoadingSpinner";
|
import LoadingSpinner from '../LoadingSpinner';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
||||||
import {hasPermission} from "../../helpers/userPermissions";
|
import { hasPermission } from '../../helpers/userPermissions';
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
access_logs: any[];
|
access_logs: any[];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
onDelete: (id: string) => void;
|
onDelete: (id: string) => void;
|
||||||
currentPage: number;
|
currentPage: number;
|
||||||
numPages: number;
|
numPages: number;
|
||||||
onPageChange: (page: number) => void;
|
onPageChange: (page: number) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ListAccess_logs = ({ access_logs, loading, onDelete, currentPage, numPages, onPageChange }: Props) => {
|
const ListAccess_logs = ({
|
||||||
|
access_logs,
|
||||||
|
loading,
|
||||||
|
onDelete,
|
||||||
|
currentPage,
|
||||||
|
numPages,
|
||||||
|
onPageChange,
|
||||||
|
}: Props) => {
|
||||||
|
const currentUser = useAppSelector((state) => state.auth.currentUser);
|
||||||
|
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_ACCESS_LOGS');
|
||||||
|
|
||||||
const currentUser = useAppSelector((state) => state.auth.currentUser);
|
const corners = useAppSelector((state) => state.style.corners);
|
||||||
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_ACCESS_LOGS')
|
const bgColor = useAppSelector((state) => state.style.cardsColor);
|
||||||
|
|
||||||
const corners = useAppSelector((state) => state.style.corners);
|
return (
|
||||||
const bgColor = useAppSelector((state) => state.style.cardsColor);
|
<>
|
||||||
|
<div className='relative overflow-x-auto p-4 space-y-4'>
|
||||||
|
{loading && <LoadingSpinner />}
|
||||||
|
{!loading &&
|
||||||
|
access_logs.map((item) => (
|
||||||
|
<div key={item.id}>
|
||||||
|
<CardBox hasTable isList className={'rounded shadow-none'}>
|
||||||
|
<div
|
||||||
|
className={`flex rounded dark:bg-dark-900 border border-stone-300 items-center overflow-hidden`}
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
href={`/access_logs/access_logs-view/?id=${item.id}`}
|
||||||
|
className={
|
||||||
|
'flex-1 px-4 py-6 h-24 flex divide-x-2 divide-stone-300 items-center overflow-hidden`}> dark:divide-dark-700 overflow-x-auto'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Project</p>
|
||||||
|
<p className={'line-clamp-2'}>
|
||||||
|
{dataFormatter.projectsOneListFormatter(item.project)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Environment</p>
|
||||||
|
<p className={'line-clamp-2'}>{item.environment}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
return (
|
<div className={'flex-1 px-3'}>
|
||||||
<>
|
<p className={'text-xs text-gray-500 '}>User</p>
|
||||||
<div className='relative overflow-x-auto p-4 space-y-4'>
|
<p className={'line-clamp-2'}>
|
||||||
{loading && <LoadingSpinner />}
|
{dataFormatter.usersOneListFormatter(item.user)}
|
||||||
{!loading && access_logs.map((item) => (
|
</p>
|
||||||
<div key={item.id}>
|
</div>
|
||||||
<CardBox hasTable isList className={'rounded shadow-none'}>
|
|
||||||
<div className={`flex rounded dark:bg-dark-900 border border-stone-300 items-center overflow-hidden`}>
|
|
||||||
|
|
||||||
<Link
|
<div className={'flex-1 px-3'}>
|
||||||
href={`/access_logs/access_logs-view/?id=${item.id}`}
|
<p className={'text-xs text-gray-500 '}>Path</p>
|
||||||
className={
|
<p className={'line-clamp-2'}>{item.path}</p>
|
||||||
'flex-1 px-4 py-6 h-24 flex divide-x-2 divide-stone-300 items-center overflow-hidden`}> dark:divide-dark-700 overflow-x-auto'
|
</div>
|
||||||
}
|
|
||||||
>
|
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>IPaddress</p>
|
||||||
|
<p className={'line-clamp-2'}>{item.ip_address}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
<div className={'flex-1 px-3'}>
|
||||||
<p className={'text-xs text-gray-500 '}>Project</p>
|
<p className={'text-xs text-gray-500 '}>Useragent</p>
|
||||||
<p className={'line-clamp-2'}>{ dataFormatter.projectsOneListFormatter(item.project) }</p>
|
<p className={'line-clamp-2'}>{item.user_agent}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Accessedat</p>
|
||||||
|
<p className={'line-clamp-2'}>
|
||||||
<div className={'flex-1 px-3'}>
|
{dataFormatter.dateTimeFormatter(item.accessed_at)}
|
||||||
<p className={'text-xs text-gray-500 '}>Environment</p>
|
</p>
|
||||||
<p className={'line-clamp-2'}>{ item.environment }</p>
|
</div>
|
||||||
</div>
|
</Link>
|
||||||
|
<ListActionsPopover
|
||||||
|
onDelete={onDelete}
|
||||||
|
itemId={item.id}
|
||||||
|
pathEdit={`/access_logs/access_logs-edit/?id=${item.id}`}
|
||||||
<div className={'flex-1 px-3'}>
|
pathView={`/access_logs/access_logs-view/?id=${item.id}`}
|
||||||
<p className={'text-xs text-gray-500 '}>User</p>
|
hasUpdatePermission={hasUpdatePermission}
|
||||||
<p className={'line-clamp-2'}>{ dataFormatter.usersOneListFormatter(item.user) }</p>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</CardBox>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>Path</p>
|
|
||||||
<p className={'line-clamp-2'}>{ item.path }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>IPaddress</p>
|
|
||||||
<p className={'line-clamp-2'}>{ item.ip_address }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>Useragent</p>
|
|
||||||
<p className={'line-clamp-2'}>{ item.user_agent }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>Accessedat</p>
|
|
||||||
<p className={'line-clamp-2'}>{ dataFormatter.dateTimeFormatter(item.accessed_at) }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Link>
|
|
||||||
<ListActionsPopover
|
|
||||||
onDelete={onDelete}
|
|
||||||
itemId={item.id}
|
|
||||||
pathEdit={`/access_logs/access_logs-edit/?id=${item.id}`}
|
|
||||||
pathView={`/access_logs/access_logs-view/?id=${item.id}`}
|
|
||||||
|
|
||||||
hasUpdatePermission={hasUpdatePermission}
|
|
||||||
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</CardBox>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
{!loading && access_logs.length === 0 && (
|
|
||||||
<div className='col-span-full flex items-center justify-center h-40'>
|
|
||||||
<p className=''>No data to display</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className={'flex items-center justify-center my-6'}>
|
))}
|
||||||
<Pagination
|
{!loading && access_logs.length === 0 && (
|
||||||
currentPage={currentPage}
|
<div className='col-span-full flex items-center justify-center h-40'>
|
||||||
numPages={numPages}
|
<p className=''>No data to display</p>
|
||||||
setCurrentPage={onPageChange}
|
</div>
|
||||||
/>
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
<div className={'flex items-center justify-center my-6'}>
|
||||||
)
|
<Pagination
|
||||||
|
currentPage={currentPage}
|
||||||
|
numPages={numPages}
|
||||||
|
setCurrentPage={onPageChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ListAccess_logs
|
export default ListAccess_logs;
|
||||||
|
|||||||
@ -1,463 +1,48 @@
|
|||||||
import React, { useEffect, useState, useMemo } from 'react'
|
/**
|
||||||
import { createPortal } from 'react-dom';
|
* Access Logs Table Component
|
||||||
import { ToastContainer, toast } from 'react-toastify';
|
*/
|
||||||
import BaseButton from '../BaseButton'
|
|
||||||
import CardBoxModal from '../CardBoxModal'
|
import React from 'react';
|
||||||
import CardBox from "../CardBox";
|
import GenericTable from '../Generic/GenericTable';
|
||||||
import { fetch, update, deleteItem, setRefetch, deleteItemsByIds } from '../../stores/access_logs/access_logsSlice'
|
|
||||||
import { useAppDispatch, useAppSelector } from '../../stores/hooks'
|
|
||||||
import { useRouter } from 'next/router'
|
|
||||||
import { Field, Form, Formik } from "formik";
|
|
||||||
import {
|
import {
|
||||||
DataGrid,
|
fetch,
|
||||||
GridColDef,
|
update,
|
||||||
} from '@mui/x-data-grid';
|
deleteItem,
|
||||||
import {loadColumns} from "./configureAccess_logsCols";
|
setRefetch,
|
||||||
import _ from 'lodash';
|
deleteItemsByIds,
|
||||||
import dataFormatter from '../../helpers/dataFormatter'
|
} from '../../stores/access_logs/access_logsSlice';
|
||||||
import {dataGridStyles} from "../../styles";
|
import { loadColumns } from './configureAccess_logsCols';
|
||||||
|
import type { AccessLog } from '../../types/entities';
|
||||||
|
import type { RootState } from '../../stores/store';
|
||||||
|
import type { Filter, FilterItem } from '../../types/filters';
|
||||||
|
|
||||||
|
interface TableAccess_logsProps {
|
||||||
|
filterItems: FilterItem[];
|
||||||
const perPage = 10
|
setFilterItems: (items: FilterItem[]) => void;
|
||||||
|
filters: Filter[];
|
||||||
const TableSampleAccess_logs = ({ filterItems, setFilterItems, filters, showGrid }) => {
|
showGrid?: boolean;
|
||||||
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
|
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const pagesList = [];
|
|
||||||
const [id, setId] = useState(null);
|
|
||||||
const [currentPage, setCurrentPage] = useState(0);
|
|
||||||
const [filterRequest, setFilterRequest] = React.useState('');
|
|
||||||
const [columns, setColumns] = useState<GridColDef[]>([]);
|
|
||||||
const [selectedRows, setSelectedRows] = useState([]);
|
|
||||||
const [sortModel, setSortModel] = useState([
|
|
||||||
{
|
|
||||||
field: '',
|
|
||||||
sort: 'desc',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const { access_logs, loading, count, notify: access_logsNotify, refetch } = useAppSelector((state) => state.access_logs)
|
|
||||||
const { currentUser } = useAppSelector((state) => state.auth);
|
|
||||||
const focusRing = useAppSelector((state) => state.style.focusRingColor);
|
|
||||||
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
|
|
||||||
const corners = useAppSelector((state) => state.style.corners);
|
|
||||||
const numPages = Math.floor(count / perPage) === 0 ? 1 : Math.ceil(count / perPage);
|
|
||||||
for (let i = 0; i < numPages; i++) {
|
|
||||||
pagesList.push(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadData = async (page = currentPage, request = filterRequest) => {
|
|
||||||
if (page !== currentPage) setCurrentPage(page);
|
|
||||||
if (request !== filterRequest) setFilterRequest(request);
|
|
||||||
const { sort, field } = sortModel[0];
|
|
||||||
|
|
||||||
const query = `?page=${page}&limit=${perPage}${request}&sort=${sort}&field=${field}`;
|
|
||||||
dispatch(fetch({ limit: perPage, page, query }));
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (access_logsNotify.showNotification) {
|
|
||||||
notify(access_logsNotify.typeNotification, access_logsNotify.textNotification);
|
|
||||||
}
|
|
||||||
}, [access_logsNotify.showNotification]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!currentUser) return;
|
|
||||||
loadData();
|
|
||||||
}, [sortModel, currentUser]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (refetch) {
|
|
||||||
loadData(0);
|
|
||||||
dispatch(setRefetch(false));
|
|
||||||
}
|
|
||||||
}, [refetch, dispatch]);
|
|
||||||
|
|
||||||
const [isModalInfoActive, setIsModalInfoActive] = useState(false)
|
|
||||||
const [isModalTrashActive, setIsModalTrashActive] = useState(false)
|
|
||||||
|
|
||||||
const handleModalAction = () => {
|
|
||||||
setIsModalInfoActive(false)
|
|
||||||
setIsModalTrashActive(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleDeleteModalAction = (id: string) => {
|
|
||||||
setId(id)
|
|
||||||
setIsModalTrashActive(true)
|
|
||||||
}
|
|
||||||
const handleDeleteAction = async () => {
|
|
||||||
if (id) {
|
|
||||||
await dispatch(deleteItem(id));
|
|
||||||
await loadData(0);
|
|
||||||
setIsModalTrashActive(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const generateFilterRequests = useMemo(() => {
|
|
||||||
let request = '&';
|
|
||||||
filterItems.forEach((item) => {
|
|
||||||
const isRangeFilter = filters.find(
|
|
||||||
(filter) =>
|
|
||||||
filter.title === item.fields.selectedField &&
|
|
||||||
(filter.number || filter.date),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isRangeFilter) {
|
|
||||||
const from = item.fields.filterValueFrom;
|
|
||||||
const to = item.fields.filterValueTo;
|
|
||||||
if (from) {
|
|
||||||
request += `${item.fields.selectedField}Range=${from}&`;
|
|
||||||
}
|
|
||||||
if (to) {
|
|
||||||
request += `${item.fields.selectedField}Range=${to}&`;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const value = item.fields.filterValue;
|
|
||||||
if (value) {
|
|
||||||
request += `${item.fields.selectedField}=${value}&`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return request;
|
|
||||||
}, [filterItems, filters]);
|
|
||||||
|
|
||||||
const deleteFilter = (value) => {
|
|
||||||
const newItems = filterItems.filter((item) => item.id !== value);
|
|
||||||
|
|
||||||
if (newItems.length) {
|
|
||||||
setFilterItems(newItems);
|
|
||||||
} else {
|
|
||||||
loadData(0, '');
|
|
||||||
|
|
||||||
setFilterItems(newItems);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = () => {
|
|
||||||
loadData(0, generateFilterRequests);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleChange = (id) => (e) => {
|
|
||||||
const value = e.target.value;
|
|
||||||
const name = e.target.name;
|
|
||||||
|
|
||||||
setFilterItems(
|
|
||||||
filterItems.map((item) => {
|
|
||||||
if (item.id !== id) return item;
|
|
||||||
if (name === 'selectedField') return { id, fields: { [name]: value } };
|
|
||||||
|
|
||||||
return { id, fields: { ...item.fields, [name]: value } }
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleReset = () => {
|
|
||||||
setFilterItems([]);
|
|
||||||
loadData(0, '');
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const onPageChange = (page: number) => {
|
|
||||||
loadData(page);
|
|
||||||
setCurrentPage(page);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!currentUser) return;
|
|
||||||
|
|
||||||
loadColumns(
|
|
||||||
handleDeleteModalAction,
|
|
||||||
`access_logs`,
|
|
||||||
currentUser,
|
|
||||||
).then((newCols) => setColumns(newCols));
|
|
||||||
}, [currentUser]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleTableSubmit = async (id: string, data) => {
|
|
||||||
|
|
||||||
if (!_.isEmpty(data)) {
|
|
||||||
await dispatch(update({ id, data }))
|
|
||||||
.unwrap()
|
|
||||||
.then((res) => res)
|
|
||||||
.catch((err) => {
|
|
||||||
throw new Error(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDeleteRows = async (selectedRows) => {
|
|
||||||
await dispatch(deleteItemsByIds(selectedRows));
|
|
||||||
await loadData(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
const controlClasses =
|
|
||||||
'w-full py-2 px-2 my-2 rounded dark:placeholder-gray-400 ' +
|
|
||||||
` ${bgColor} ${focusRing} ${corners} ` +
|
|
||||||
'dark:bg-slate-800 border';
|
|
||||||
|
|
||||||
|
|
||||||
const dataGrid = (
|
|
||||||
<div className='relative overflow-x-auto'>
|
|
||||||
<DataGrid
|
|
||||||
autoHeight
|
|
||||||
rowHeight={64}
|
|
||||||
sx={dataGridStyles}
|
|
||||||
className={'datagrid--table'}
|
|
||||||
getRowClassName={() => `datagrid--row`}
|
|
||||||
rows={access_logs ?? []}
|
|
||||||
columns={columns}
|
|
||||||
initialState={{
|
|
||||||
pagination: {
|
|
||||||
paginationModel: {
|
|
||||||
pageSize: 10,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
disableRowSelectionOnClick
|
|
||||||
onProcessRowUpdateError={(params) => {
|
|
||||||
console.log('Error', params);
|
|
||||||
}}
|
|
||||||
processRowUpdate={async (newRow, oldRow) => {
|
|
||||||
const data = dataFormatter.dataGridEditFormatter(newRow);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await handleTableSubmit(newRow.id, data);
|
|
||||||
return newRow;
|
|
||||||
} catch {
|
|
||||||
return oldRow;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
sortingMode={'server'}
|
|
||||||
checkboxSelection
|
|
||||||
onRowSelectionModelChange={(ids) => {
|
|
||||||
setSelectedRows(ids)
|
|
||||||
}}
|
|
||||||
onSortModelChange={(params) => {
|
|
||||||
params.length
|
|
||||||
? setSortModel(params)
|
|
||||||
: setSortModel([{ field: '', sort: 'desc' }]);
|
|
||||||
}}
|
|
||||||
rowCount={count}
|
|
||||||
pageSizeOptions={[10]}
|
|
||||||
paginationMode={'server'}
|
|
||||||
loading={loading}
|
|
||||||
onPaginationModelChange={(params) => {
|
|
||||||
onPageChange(params.page);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{filterItems && Array.isArray( filterItems ) && filterItems.length ?
|
|
||||||
<CardBox>
|
|
||||||
<Formik
|
|
||||||
initialValues={{
|
|
||||||
checkboxes: ['lorem'],
|
|
||||||
switches: ['lorem'],
|
|
||||||
radio: 'lorem',
|
|
||||||
}}
|
|
||||||
onSubmit={() => null}
|
|
||||||
>
|
|
||||||
<Form>
|
|
||||||
<>
|
|
||||||
{filterItems && filterItems.map((filterItem) => {
|
|
||||||
return (
|
|
||||||
<div key={filterItem.id} className="flex mb-4">
|
|
||||||
<div className="flex flex-col w-full mr-3">
|
|
||||||
<div className=" text-gray-500 font-bold">Filter</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='selectedField'
|
|
||||||
id='selectedField'
|
|
||||||
component='select'
|
|
||||||
value={filterItem?.fields?.selectedField || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
>
|
|
||||||
{filters.map((selectOption) => (
|
|
||||||
<option
|
|
||||||
key={selectOption.title}
|
|
||||||
value={`${selectOption.title}`}
|
|
||||||
>
|
|
||||||
{selectOption.label}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</Field>
|
|
||||||
</div>
|
|
||||||
{filters.find((filter) =>
|
|
||||||
filter.title === filterItem?.fields?.selectedField
|
|
||||||
)?.type === 'enum' ? (
|
|
||||||
<div className="flex flex-col w-full mr-3">
|
|
||||||
<div className="text-gray-500 font-bold">
|
|
||||||
Value
|
|
||||||
</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name="filterValue"
|
|
||||||
id='filterValue'
|
|
||||||
component="select"
|
|
||||||
value={filterItem?.fields?.filterValue || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
>
|
|
||||||
<option value="">Select Value</option>
|
|
||||||
{filters.find((filter) =>
|
|
||||||
filter.title === filterItem?.fields?.selectedField
|
|
||||||
)?.options?.map((option) => (
|
|
||||||
<option key={option} value={option}>
|
|
||||||
{option}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</Field>
|
|
||||||
</div>
|
|
||||||
) : filters.find((filter) =>
|
|
||||||
filter.title === filterItem?.fields?.selectedField
|
|
||||||
)?.number ? (
|
|
||||||
<div className="flex flex-row w-full mr-3">
|
|
||||||
<div className="flex flex-col w-full mr-3">
|
|
||||||
<div className=" text-gray-500 font-bold">From</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='filterValueFrom'
|
|
||||||
placeholder='From'
|
|
||||||
id='filterValueFrom'
|
|
||||||
value={filterItem?.fields?.filterValueFrom || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col w-full">
|
|
||||||
<div className=" text-gray-500 font-bold">To</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='filterValueTo'
|
|
||||||
placeholder='to'
|
|
||||||
id='filterValueTo'
|
|
||||||
value={filterItem?.fields?.filterValueTo || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : filters.find(
|
|
||||||
(filter) =>
|
|
||||||
filter.title ===
|
|
||||||
filterItem?.fields?.selectedField
|
|
||||||
)?.date ? (
|
|
||||||
<div className='flex flex-row w-full mr-3'>
|
|
||||||
<div className='flex flex-col w-full mr-3'>
|
|
||||||
<div className=' text-gray-500 font-bold'>
|
|
||||||
From
|
|
||||||
</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='filterValueFrom'
|
|
||||||
placeholder='From'
|
|
||||||
id='filterValueFrom'
|
|
||||||
type='datetime-local'
|
|
||||||
value={filterItem?.fields?.filterValueFrom || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className='flex flex-col w-full'>
|
|
||||||
<div className=' text-gray-500 font-bold'>To</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='filterValueTo'
|
|
||||||
placeholder='to'
|
|
||||||
id='filterValueTo'
|
|
||||||
type='datetime-local'
|
|
||||||
value={filterItem?.fields?.filterValueTo || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="flex flex-col w-full mr-3">
|
|
||||||
<div className=" text-gray-500 font-bold">Contains</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='filterValue'
|
|
||||||
placeholder='Contained'
|
|
||||||
id='filterValue'
|
|
||||||
value={filterItem?.fields?.filterValue || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="flex flex-col">
|
|
||||||
<div className=" text-gray-500 font-bold">Action</div>
|
|
||||||
<BaseButton
|
|
||||||
className="my-2"
|
|
||||||
type='reset'
|
|
||||||
color='danger'
|
|
||||||
label='Delete'
|
|
||||||
onClick={() => {
|
|
||||||
deleteFilter(filterItem.id)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
<div className="flex">
|
|
||||||
<BaseButton
|
|
||||||
className="my-2 mr-3"
|
|
||||||
color="success"
|
|
||||||
label='Apply'
|
|
||||||
onClick={handleSubmit}
|
|
||||||
/>
|
|
||||||
<BaseButton
|
|
||||||
className="my-2"
|
|
||||||
color='info'
|
|
||||||
label='Cancel'
|
|
||||||
onClick={handleReset}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
</Form>
|
|
||||||
</Formik>
|
|
||||||
</CardBox> : null
|
|
||||||
}
|
|
||||||
<CardBoxModal
|
|
||||||
title="Please confirm"
|
|
||||||
buttonColor="info"
|
|
||||||
buttonLabel={loading ? 'Deleting...' : 'Confirm'}
|
|
||||||
isActive={isModalTrashActive}
|
|
||||||
onConfirm={handleDeleteAction}
|
|
||||||
onCancel={handleModalAction}
|
|
||||||
>
|
|
||||||
<p>Are you sure you want to delete this item?</p>
|
|
||||||
</CardBoxModal>
|
|
||||||
|
|
||||||
|
|
||||||
{dataGrid}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{selectedRows.length > 0 &&
|
|
||||||
createPortal(
|
|
||||||
<BaseButton
|
|
||||||
className='me-4'
|
|
||||||
color='danger'
|
|
||||||
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`}
|
|
||||||
onClick={() => onDeleteRows(selectedRows)}
|
|
||||||
/>,
|
|
||||||
document.getElementById('delete-rows-button'),
|
|
||||||
)}
|
|
||||||
<ToastContainer />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TableSampleAccess_logs
|
const TableAccess_logs: React.FC<TableAccess_logsProps> = ({
|
||||||
|
filterItems,
|
||||||
|
setFilterItems,
|
||||||
|
filters,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<GenericTable<AccessLog>
|
||||||
|
entityName='access_logs'
|
||||||
|
sliceSelector={(state: RootState) => state.access_logs}
|
||||||
|
fetchAction={fetch}
|
||||||
|
updateAction={update}
|
||||||
|
deleteAction={deleteItem}
|
||||||
|
deleteByIdsAction={deleteItemsByIds}
|
||||||
|
setRefetchAction={setRefetch}
|
||||||
|
loadColumnsFunction={loadColumns}
|
||||||
|
filters={filters}
|
||||||
|
filterItems={filterItems}
|
||||||
|
setFilterItems={setFilterItems}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TableAccess_logs;
|
||||||
|
|||||||
@ -3,188 +3,164 @@ import BaseIcon from '../BaseIcon';
|
|||||||
import { mdiEye, mdiTrashCan, mdiPencilOutline } from '@mdi/js';
|
import { mdiEye, mdiTrashCan, mdiPencilOutline } from '@mdi/js';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import {
|
import {
|
||||||
GridActionsCellItem,
|
GridActionsCellItem,
|
||||||
GridRowParams,
|
GridRowParams,
|
||||||
GridValueGetterParams,
|
GridValueGetterParams,
|
||||||
} from '@mui/x-data-grid';
|
} from '@mui/x-data-grid';
|
||||||
import ImageField from '../ImageField';
|
import ImageField from '../ImageField';
|
||||||
import {saveFile} from "../../helpers/fileSaver";
|
import { saveFile } from '../../helpers/fileSaver';
|
||||||
import dataFormatter from '../../helpers/dataFormatter'
|
import dataFormatter from '../../helpers/dataFormatter';
|
||||||
import DataGridMultiSelect from "../DataGridMultiSelect";
|
import DataGridMultiSelect from '../DataGridMultiSelect';
|
||||||
import ListActionsPopover from '../ListActionsPopover';
|
import ListActionsPopover from '../ListActionsPopover';
|
||||||
|
|
||||||
import {hasPermission} from "../../helpers/userPermissions";
|
import { hasPermission } from '../../helpers/userPermissions';
|
||||||
|
|
||||||
type Params = (id: string) => void;
|
type Params = (id: string) => void;
|
||||||
|
|
||||||
export const loadColumns = async (
|
export const loadColumns = async (
|
||||||
onDelete: Params,
|
onDelete: Params,
|
||||||
entityName: string,
|
entityName: string,
|
||||||
|
|
||||||
user
|
|
||||||
|
|
||||||
|
user,
|
||||||
) => {
|
) => {
|
||||||
async function callOptionsApi(entityName: string) {
|
async function callOptionsApi(entityName: string) {
|
||||||
|
if (!hasPermission(user, 'READ_' + entityName.toUpperCase())) return [];
|
||||||
|
|
||||||
if (!hasPermission(user, 'READ_' + entityName.toUpperCase())) return [];
|
try {
|
||||||
|
const data = await axios(`/${entityName}/autocomplete?limit=100`);
|
||||||
try {
|
return data.data;
|
||||||
const data = await axios(`/${entityName}/autocomplete?limit=100`);
|
} catch (error) {
|
||||||
return data.data;
|
console.log(error);
|
||||||
} catch (error) {
|
return [];
|
||||||
console.log(error);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const hasUpdatePermission = hasPermission(user, 'UPDATE_ACCESS_LOGS')
|
const hasUpdatePermission = hasPermission(user, 'UPDATE_ACCESS_LOGS');
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
{
|
||||||
|
field: 'project',
|
||||||
|
headerName: 'Project',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
{
|
editable: hasUpdatePermission,
|
||||||
field: 'project',
|
|
||||||
headerName: 'Project',
|
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
|
||||||
filterable: false,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
|
|
||||||
|
sortable: false,
|
||||||
|
type: 'singleSelect',
|
||||||
|
getOptionValue: (value: any) => value?.id,
|
||||||
|
getOptionLabel: (value: any) => value?.label,
|
||||||
|
valueOptions: await callOptionsApi('projects'),
|
||||||
|
valueGetter: (params: GridValueGetterParams) =>
|
||||||
|
params?.value?.id ?? params?.value,
|
||||||
|
},
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
{
|
||||||
|
field: 'environment',
|
||||||
|
headerName: 'Environment',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
sortable: false,
|
editable: hasUpdatePermission,
|
||||||
type: 'singleSelect',
|
},
|
||||||
getOptionValue: (value: any) => value?.id,
|
|
||||||
getOptionLabel: (value: any) => value?.label,
|
|
||||||
valueOptions: await callOptionsApi('projects'),
|
|
||||||
valueGetter: (params: GridValueGetterParams) =>
|
|
||||||
params?.value?.id ?? params?.value,
|
|
||||||
|
|
||||||
},
|
{
|
||||||
|
field: 'user',
|
||||||
|
headerName: 'User',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
{
|
editable: hasUpdatePermission,
|
||||||
field: 'environment',
|
|
||||||
headerName: 'Environment',
|
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
|
||||||
filterable: false,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
|
|
||||||
|
sortable: false,
|
||||||
|
type: 'singleSelect',
|
||||||
|
getOptionValue: (value: any) => value?.id,
|
||||||
|
getOptionLabel: (value: any) => value?.label,
|
||||||
|
valueOptions: await callOptionsApi('users'),
|
||||||
|
valueGetter: (params: GridValueGetterParams) =>
|
||||||
|
params?.value?.id ?? params?.value,
|
||||||
|
},
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
{
|
||||||
|
field: 'path',
|
||||||
|
headerName: 'Path',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
|
editable: hasUpdatePermission,
|
||||||
|
},
|
||||||
|
|
||||||
},
|
{
|
||||||
|
field: 'ip_address',
|
||||||
|
headerName: 'IPaddress',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
{
|
editable: hasUpdatePermission,
|
||||||
field: 'user',
|
},
|
||||||
headerName: 'User',
|
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
|
||||||
filterable: false,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'user_agent',
|
||||||
|
headerName: 'Useragent',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
editable: hasUpdatePermission,
|
||||||
|
},
|
||||||
|
|
||||||
sortable: false,
|
{
|
||||||
type: 'singleSelect',
|
field: 'accessed_at',
|
||||||
getOptionValue: (value: any) => value?.id,
|
headerName: 'Accessedat',
|
||||||
getOptionLabel: (value: any) => value?.label,
|
flex: 1,
|
||||||
valueOptions: await callOptionsApi('users'),
|
minWidth: 120,
|
||||||
valueGetter: (params: GridValueGetterParams) =>
|
filterable: false,
|
||||||
params?.value?.id ?? params?.value,
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
},
|
editable: hasUpdatePermission,
|
||||||
|
|
||||||
{
|
type: 'dateTime',
|
||||||
field: 'path',
|
valueGetter: (params: GridValueGetterParams) =>
|
||||||
headerName: 'Path',
|
new Date(params.row.accessed_at),
|
||||||
flex: 1,
|
},
|
||||||
minWidth: 120,
|
|
||||||
filterable: false,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
|
|
||||||
|
{
|
||||||
editable: hasUpdatePermission,
|
field: 'actions',
|
||||||
|
type: 'actions',
|
||||||
|
minWidth: 30,
|
||||||
},
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
{
|
getActions: (params: GridRowParams) => {
|
||||||
field: 'ip_address',
|
return [
|
||||||
headerName: 'IPaddress',
|
<div key={params?.row?.id}>
|
||||||
flex: 1,
|
<ListActionsPopover
|
||||||
minWidth: 120,
|
onDelete={onDelete}
|
||||||
filterable: false,
|
itemId={params?.row?.id}
|
||||||
headerClassName: 'datagrid--header',
|
pathEdit={`/access_logs/access_logs-edit/?id=${params?.row?.id}`}
|
||||||
cellClassName: 'datagrid--cell',
|
pathView={`/access_logs/access_logs-view/?id=${params?.row?.id}`}
|
||||||
|
hasUpdatePermission={hasUpdatePermission}
|
||||||
|
/>
|
||||||
editable: hasUpdatePermission,
|
</div>,
|
||||||
|
];
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
];
|
||||||
{
|
|
||||||
field: 'user_agent',
|
|
||||||
headerName: 'Useragent',
|
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
|
||||||
filterable: false,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
|
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
field: 'accessed_at',
|
|
||||||
headerName: 'Accessedat',
|
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
|
||||||
filterable: false,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
|
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
|
||||||
|
|
||||||
type: 'dateTime',
|
|
||||||
valueGetter: (params: GridValueGetterParams) =>
|
|
||||||
new Date(params.row.accessed_at),
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
field: 'actions',
|
|
||||||
type: 'actions',
|
|
||||||
minWidth: 30,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
getActions: (params: GridRowParams) => {
|
|
||||||
|
|
||||||
return [
|
|
||||||
<div key={params?.row?.id}>
|
|
||||||
<ListActionsPopover
|
|
||||||
onDelete={onDelete}
|
|
||||||
itemId={params?.row?.id}
|
|
||||||
pathEdit={`/access_logs/access_logs-edit/?id=${params?.row?.id}`}
|
|
||||||
pathView={`/access_logs/access_logs-view/?id=${params?.row?.id}`}
|
|
||||||
|
|
||||||
hasUpdatePermission={hasUpdatePermission}
|
|
||||||
|
|
||||||
/>
|
|
||||||
</div>,
|
|
||||||
]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
import React from 'react'
|
import React from 'react';
|
||||||
import { MenuAsideItem } from '../interfaces'
|
import { MenuAsideItem } from '../interfaces';
|
||||||
import AsideMenuLayer from './AsideMenuLayer'
|
import AsideMenuLayer from './AsideMenuLayer';
|
||||||
import OverlayLayer from './OverlayLayer'
|
import OverlayLayer from './OverlayLayer';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
menu: MenuAsideItem[]
|
menu: MenuAsideItem[];
|
||||||
isAsideMobileExpanded: boolean
|
isAsideMobileExpanded: boolean;
|
||||||
isAsideLgActive: boolean
|
isAsideLgActive: boolean;
|
||||||
onAsideLgClose: () => void
|
onAsideLgClose: () => void;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default function AsideMenu({
|
export default function AsideMenu({
|
||||||
isAsideMobileExpanded = false,
|
isAsideMobileExpanded = false,
|
||||||
@ -24,7 +24,9 @@ export default function AsideMenu({
|
|||||||
}`}
|
}`}
|
||||||
onAsideLgCloseClick={props.onAsideLgClose}
|
onAsideLgCloseClick={props.onAsideLgClose}
|
||||||
/>
|
/>
|
||||||
{isAsideLgActive && <OverlayLayer zIndex="z-30" onClick={props.onAsideLgClose} />}
|
{isAsideLgActive && (
|
||||||
|
<OverlayLayer zIndex='z-30' onClick={props.onAsideLgClose} />
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,49 +1,60 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react';
|
||||||
import { mdiMinus, mdiPlus } from '@mdi/js'
|
import { mdiMinus, mdiPlus } from '@mdi/js';
|
||||||
import BaseIcon from './BaseIcon'
|
import BaseIcon from './BaseIcon';
|
||||||
import Link from 'next/link'
|
import Link from 'next/link';
|
||||||
import { getButtonColor } from '../colors'
|
import { getButtonColor } from '../colors';
|
||||||
import AsideMenuList from './AsideMenuList'
|
import AsideMenuList from './AsideMenuList';
|
||||||
import { MenuAsideItem } from '../interfaces'
|
import { MenuAsideItem } from '../interfaces';
|
||||||
import { useAppSelector } from '../stores/hooks'
|
import { useAppSelector } from '../stores/hooks';
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
item: MenuAsideItem
|
item: MenuAsideItem;
|
||||||
isDropdownList?: boolean
|
isDropdownList?: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
const AsideMenuItem = ({ item, isDropdownList = false }: Props) => {
|
const AsideMenuItem = ({ item, isDropdownList = false }: Props) => {
|
||||||
const [isLinkActive, setIsLinkActive] = useState(false)
|
const [isLinkActive, setIsLinkActive] = useState(false);
|
||||||
const [isDropdownActive, setIsDropdownActive] = useState(false)
|
const [isDropdownActive, setIsDropdownActive] = useState(false);
|
||||||
|
|
||||||
const asideMenuItemStyle = useAppSelector((state) => state.style.asideMenuItemStyle)
|
const asideMenuItemStyle = useAppSelector(
|
||||||
const asideMenuDropdownStyle = useAppSelector((state) => state.style.asideMenuDropdownStyle)
|
(state) => state.style.asideMenuItemStyle,
|
||||||
const asideMenuItemActiveStyle = useAppSelector((state) => state.style.asideMenuItemActiveStyle)
|
);
|
||||||
|
const asideMenuDropdownStyle = useAppSelector(
|
||||||
|
(state) => state.style.asideMenuDropdownStyle,
|
||||||
|
);
|
||||||
|
const asideMenuItemActiveStyle = useAppSelector(
|
||||||
|
(state) => state.style.asideMenuItemActiveStyle,
|
||||||
|
);
|
||||||
const borders = useAppSelector((state) => state.style.borders);
|
const borders = useAppSelector((state) => state.style.borders);
|
||||||
const activeLinkColor = useAppSelector(
|
const activeLinkColor = useAppSelector(
|
||||||
(state) => state.style.activeLinkColor,
|
(state) => state.style.activeLinkColor,
|
||||||
);
|
);
|
||||||
const activeClassAddon = !item.color && isLinkActive ? asideMenuItemActiveStyle : ''
|
const activeClassAddon =
|
||||||
|
!item.color && isLinkActive ? asideMenuItemActiveStyle : '';
|
||||||
|
|
||||||
const { asPath, isReady } = useRouter()
|
const { asPath, isReady } = useRouter();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (item.href && isReady) {
|
if (item.href && isReady) {
|
||||||
const linkPathName = new URL(item.href, location.href).pathname + '/';
|
const linkPathName = new URL(item.href, location.href).pathname + '/';
|
||||||
const activePathname = new URL(asPath, location.href).pathname
|
const activePathname = new URL(asPath, location.href).pathname;
|
||||||
|
|
||||||
const activeView = activePathname.split('/')[1];
|
const activeView = activePathname.split('/')[1];
|
||||||
const linkPathNameView = linkPathName.split('/')[1];
|
const linkPathNameView = linkPathName.split('/')[1];
|
||||||
|
|
||||||
setIsLinkActive(linkPathNameView === activeView);
|
setIsLinkActive(linkPathNameView === activeView);
|
||||||
}
|
}
|
||||||
}, [item.href, isReady, asPath])
|
}, [item.href, isReady, asPath]);
|
||||||
|
|
||||||
const asideMenuItemInnerContents = (
|
const asideMenuItemInnerContents = (
|
||||||
<>
|
<>
|
||||||
{item.icon && (
|
{item.icon && (
|
||||||
<BaseIcon path={item.icon} className={`flex-none mx-3 ${activeClassAddon}`} size="18" />
|
<BaseIcon
|
||||||
|
path={item.icon}
|
||||||
|
className={`flex-none mx-3 ${activeClassAddon}`}
|
||||||
|
size='18'
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
<span
|
<span
|
||||||
className={`grow text-ellipsis line-clamp-1 ${
|
className={`grow text-ellipsis line-clamp-1 ${
|
||||||
@ -56,21 +67,21 @@ const AsideMenuItem = ({ item, isDropdownList = false }: Props) => {
|
|||||||
<BaseIcon
|
<BaseIcon
|
||||||
path={isDropdownActive ? mdiMinus : mdiPlus}
|
path={isDropdownActive ? mdiMinus : mdiPlus}
|
||||||
className={`flex-none ${activeClassAddon}`}
|
className={`flex-none ${activeClassAddon}`}
|
||||||
w="w-12"
|
w='w-12'
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
|
|
||||||
const componentClass = [
|
const componentClass = [
|
||||||
'flex cursor-pointer py-1.5 ',
|
'flex cursor-pointer py-1.5 ',
|
||||||
isDropdownList ? 'px-6 text-sm' : '',
|
isDropdownList ? 'px-6 text-sm' : '',
|
||||||
item.color
|
item.color
|
||||||
? getButtonColor(item.color, false, true)
|
? getButtonColor(item.color, false, true)
|
||||||
: `${asideMenuItemStyle}`,
|
: `${asideMenuItemStyle}`,
|
||||||
isLinkActive
|
isLinkActive
|
||||||
? `text-black ${activeLinkColor} dark:text-white dark:bg-dark-800`
|
? `text-black ${activeLinkColor} dark:text-white dark:bg-dark-800`
|
||||||
: '',
|
: '',
|
||||||
].join(' ');
|
].join(' ');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -82,7 +93,10 @@ const AsideMenuItem = ({ item, isDropdownList = false }: Props) => {
|
|||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
{!item.href && (
|
{!item.href && (
|
||||||
<div className={componentClass} onClick={() => setIsDropdownActive(!isDropdownActive)}>
|
<div
|
||||||
|
className={componentClass}
|
||||||
|
onClick={() => setIsDropdownActive(!isDropdownActive)}
|
||||||
|
>
|
||||||
{asideMenuItemInnerContents}
|
{asideMenuItemInnerContents}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -96,7 +110,7 @@ const AsideMenuItem = ({ item, isDropdownList = false }: Props) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</li>
|
</li>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default AsideMenuItem
|
export default AsideMenuItem;
|
||||||
|
|||||||
@ -1,30 +1,36 @@
|
|||||||
import React from 'react'
|
import React from 'react';
|
||||||
import { mdiLogout, mdiClose } from '@mdi/js'
|
import { mdiLogout, mdiClose } from '@mdi/js';
|
||||||
import BaseIcon from './BaseIcon'
|
import BaseIcon from './BaseIcon';
|
||||||
import AsideMenuList from './AsideMenuList'
|
import AsideMenuList from './AsideMenuList';
|
||||||
import { MenuAsideItem } from '../interfaces'
|
import { MenuAsideItem } from '../interfaces';
|
||||||
import { useAppSelector } from '../stores/hooks'
|
import { useAppSelector } from '../stores/hooks';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
menu: MenuAsideItem[]
|
menu: MenuAsideItem[];
|
||||||
className?: string
|
className?: string;
|
||||||
onAsideLgCloseClick: () => void
|
onAsideLgCloseClick: () => void;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default function AsideMenuLayer({ menu, className = '', ...props }: Props) {
|
export default function AsideMenuLayer({
|
||||||
|
menu,
|
||||||
|
className = '',
|
||||||
|
...props
|
||||||
|
}: Props) {
|
||||||
const corners = useAppSelector((state) => state.style.corners);
|
const corners = useAppSelector((state) => state.style.corners);
|
||||||
const asideStyle = useAppSelector((state) => state.style.asideStyle)
|
const asideStyle = useAppSelector((state) => state.style.asideStyle);
|
||||||
const asideBrandStyle = useAppSelector((state) => state.style.asideBrandStyle)
|
const asideBrandStyle = useAppSelector(
|
||||||
const asideScrollbarsStyle = useAppSelector((state) => state.style.asideScrollbarsStyle)
|
(state) => state.style.asideBrandStyle,
|
||||||
const darkMode = useAppSelector((state) => state.style.darkMode)
|
);
|
||||||
|
const asideScrollbarsStyle = useAppSelector(
|
||||||
|
(state) => state.style.asideScrollbarsStyle,
|
||||||
|
);
|
||||||
|
const darkMode = useAppSelector((state) => state.style.darkMode);
|
||||||
|
|
||||||
const handleAsideLgCloseClick = (e: React.MouseEvent) => {
|
const handleAsideLgCloseClick = (e: React.MouseEvent) => {
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
props.onAsideLgCloseClick()
|
props.onAsideLgCloseClick();
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside
|
<aside
|
||||||
@ -32,19 +38,16 @@ export default function AsideMenuLayer({ menu, className = '', ...props }: Props
|
|||||||
className={`${className} zzz lg:py-2 lg:pl-2 w-60 fixed flex z-40 top-0 h-screen transition-position overflow-hidden`}
|
className={`${className} zzz lg:py-2 lg:pl-2 w-60 fixed flex z-40 top-0 h-screen transition-position overflow-hidden`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`flex-1 flex flex-col overflow-hidden dark:bg-dark-900 ${asideStyle} ${corners}`}
|
className={`flex-1 flex flex-col overflow-hidden dark:bg-dark-900 ${asideStyle} ${corners}`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`flex flex-row h-14 items-center justify-between ${asideBrandStyle}`}
|
className={`flex flex-row h-14 items-center justify-between ${asideBrandStyle}`}
|
||||||
>
|
>
|
||||||
<div className="text-center flex-1 lg:text-left lg:pl-6 xl:text-center xl:pl-0">
|
<div className='text-center flex-1 lg:text-left lg:pl-6 xl:text-center xl:pl-0'>
|
||||||
|
<b className='font-black'>Shimahara Visual</b>
|
||||||
<b className="font-black">Shimahara Visual</b>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
className="hidden lg:inline-block xl:hidden p-3"
|
className='hidden lg:inline-block xl:hidden p-3'
|
||||||
onClick={handleAsideLgCloseClick}
|
onClick={handleAsideLgCloseClick}
|
||||||
>
|
>
|
||||||
<BaseIcon path={mdiClose} />
|
<BaseIcon path={mdiClose} />
|
||||||
@ -59,5 +62,5 @@ export default function AsideMenuLayer({ menu, className = '', ...props }: Props
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,20 @@
|
|||||||
import React from 'react'
|
import React from 'react';
|
||||||
import { MenuAsideItem } from '../interfaces'
|
import { MenuAsideItem } from '../interfaces';
|
||||||
import AsideMenuItem from './AsideMenuItem'
|
import AsideMenuItem from './AsideMenuItem';
|
||||||
import {useAppSelector} from "../stores/hooks";
|
import { useAppSelector } from '../stores/hooks';
|
||||||
import {hasPermission} from "../helpers/userPermissions";
|
import { hasPermission } from '../helpers/userPermissions';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
menu: MenuAsideItem[]
|
menu: MenuAsideItem[];
|
||||||
isDropdownList?: boolean
|
isDropdownList?: boolean;
|
||||||
className?: string
|
className?: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default function AsideMenuList({ menu, isDropdownList = false, className = '' }: Props) {
|
export default function AsideMenuList({
|
||||||
|
menu,
|
||||||
|
isDropdownList = false,
|
||||||
|
className = '',
|
||||||
|
}: Props) {
|
||||||
const { currentUser } = useAppSelector((state) => state.auth);
|
const { currentUser } = useAppSelector((state) => state.auth);
|
||||||
|
|
||||||
if (!currentUser) return null;
|
if (!currentUser) return null;
|
||||||
@ -18,18 +22,14 @@ export default function AsideMenuList({ menu, isDropdownList = false, className
|
|||||||
return (
|
return (
|
||||||
<ul className={className}>
|
<ul className={className}>
|
||||||
{menu.map((item, index) => {
|
{menu.map((item, index) => {
|
||||||
|
if (!hasPermission(currentUser, item.permissions)) return null;
|
||||||
if (!hasPermission(currentUser, item.permissions)) return null;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={index}>
|
<div key={index}>
|
||||||
<AsideMenuItem
|
<AsideMenuItem item={item} isDropdownList={isDropdownList} />
|
||||||
item={item}
|
|
||||||
isDropdownList={isDropdownList}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,12 +4,11 @@ import ListActionsPopover from '../ListActionsPopover';
|
|||||||
import { useAppSelector } from '../../stores/hooks';
|
import { useAppSelector } from '../../stores/hooks';
|
||||||
import dataFormatter from '../../helpers/dataFormatter';
|
import dataFormatter from '../../helpers/dataFormatter';
|
||||||
import { Pagination } from '../Pagination';
|
import { Pagination } from '../Pagination';
|
||||||
import {saveFile} from "../../helpers/fileSaver";
|
import { saveFile } from '../../helpers/fileSaver';
|
||||||
import LoadingSpinner from "../LoadingSpinner";
|
import LoadingSpinner from '../LoadingSpinner';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
||||||
import {hasPermission} from "../../helpers/userPermissions";
|
import { hasPermission } from '../../helpers/userPermissions';
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
asset_variants: any[];
|
asset_variants: any[];
|
||||||
@ -28,17 +27,19 @@ const CardAsset_variants = ({
|
|||||||
numPages,
|
numPages,
|
||||||
onPageChange,
|
onPageChange,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const asideScrollbarsStyle = useAppSelector(
|
const asideScrollbarsStyle = useAppSelector(
|
||||||
(state) => state.style.asideScrollbarsStyle,
|
(state) => state.style.asideScrollbarsStyle,
|
||||||
);
|
);
|
||||||
const bgColor = useAppSelector((state) => state.style.cardsColor);
|
const bgColor = useAppSelector((state) => state.style.cardsColor);
|
||||||
const darkMode = useAppSelector((state) => state.style.darkMode);
|
const darkMode = useAppSelector((state) => state.style.darkMode);
|
||||||
const corners = useAppSelector((state) => state.style.corners);
|
const corners = useAppSelector((state) => state.style.corners);
|
||||||
const focusRing = useAppSelector((state) => state.style.focusRingColor);
|
const focusRing = useAppSelector((state) => state.style.focusRingColor);
|
||||||
|
|
||||||
const currentUser = useAppSelector((state) => state.auth.currentUser);
|
|
||||||
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_ASSET_VARIANTS')
|
|
||||||
|
|
||||||
|
const currentUser = useAppSelector((state) => state.auth.currentUser);
|
||||||
|
const hasUpdatePermission = hasPermission(
|
||||||
|
currentUser,
|
||||||
|
'UPDATE_ASSET_VARIANTS',
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'p-4'}>
|
<div className={'p-4'}>
|
||||||
@ -47,110 +48,101 @@ const CardAsset_variants = ({
|
|||||||
role='list'
|
role='list'
|
||||||
className='grid grid-cols-1 gap-x-6 gap-y-8 lg:grid-cols-3 2xl:grid-cols-4 xl:gap-x-8'
|
className='grid grid-cols-1 gap-x-6 gap-y-8 lg:grid-cols-3 2xl:grid-cols-4 xl:gap-x-8'
|
||||||
>
|
>
|
||||||
{!loading && asset_variants.map((item, index) => (
|
{!loading &&
|
||||||
<li
|
asset_variants.map((item, index) => (
|
||||||
key={item.id}
|
<li
|
||||||
className={`overflow-hidden ${corners !== 'rounded-full'? corners : 'rounded-3xl'} border ${focusRing} border-gray-200 dark:border-dark-700 ${
|
key={item.id}
|
||||||
|
className={`overflow-hidden ${corners !== 'rounded-full' ? corners : 'rounded-3xl'} border ${focusRing} border-gray-200 dark:border-dark-700 ${
|
||||||
darkMode ? 'aside-scrollbars-[slate]' : asideScrollbarsStyle
|
darkMode ? 'aside-scrollbars-[slate]' : asideScrollbarsStyle
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
<div className={`flex items-center ${bgColor} p-6 gap-x-4 border-b border-gray-900/5 bg-gray-50 dark:bg-dark-800 relative`}>
|
className={`flex items-center ${bgColor} p-6 gap-x-4 border-b border-gray-900/5 bg-gray-50 dark:bg-dark-800 relative`}
|
||||||
|
>
|
||||||
<Link href={`/asset_variants/asset_variants-view/?id=${item.id}`} className='text-lg font-bold leading-6 line-clamp-1'>
|
<Link
|
||||||
{item.variant_type}
|
href={`/asset_variants/asset_variants-view/?id=${item.id}`}
|
||||||
|
className='text-lg font-bold leading-6 line-clamp-1'
|
||||||
|
>
|
||||||
|
{item.variant_type}
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
|
<div className='ml-auto '>
|
||||||
<div className='ml-auto '>
|
<ListActionsPopover
|
||||||
<ListActionsPopover
|
onDelete={onDelete}
|
||||||
onDelete={onDelete}
|
itemId={item.id}
|
||||||
itemId={item.id}
|
pathEdit={`/asset_variants/asset_variants-edit/?id=${item.id}`}
|
||||||
pathEdit={`/asset_variants/asset_variants-edit/?id=${item.id}`}
|
pathView={`/asset_variants/asset_variants-view/?id=${item.id}`}
|
||||||
pathView={`/asset_variants/asset_variants-view/?id=${item.id}`}
|
hasUpdatePermission={hasUpdatePermission}
|
||||||
|
/>
|
||||||
hasUpdatePermission={hasUpdatePermission}
|
</div>
|
||||||
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<dl className='divide-y divide-stone-300 dark:divide-dark-700 px-6 py-4 text-sm leading-6 h-64 overflow-y-auto'>
|
||||||
<dl className='divide-y divide-stone-300 dark:divide-dark-700 px-6 py-4 text-sm leading-6 h-64 overflow-y-auto'>
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Asset</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>Asset</dt>
|
||||||
<dd className='flex items-start gap-x-2'>
|
<dd className='flex items-start gap-x-2'>
|
||||||
<div className='font-medium line-clamp-4'>
|
<div className='font-medium line-clamp-4'>
|
||||||
{ dataFormatter.assetsOneListFormatter(item.asset) }
|
{dataFormatter.assetsOneListFormatter(item.asset)}
|
||||||
</div>
|
</div>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Varianttype</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Varianttype
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ item.variant_type }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.variant_type}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>CDNURL</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
CDNURL
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ item.cdn_url }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.cdn_url}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Width(px)</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Width(px)
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ item.width_px }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.width_px}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Height(px)</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Height(px)
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ item.height_px }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.height_px}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Size(MB)</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Size(MB)
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ item.size_mb }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.size_mb}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
</dl>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
{!loading && asset_variants.length === 0 && (
|
{!loading && asset_variants.length === 0 && (
|
||||||
<div className='col-span-full flex items-center justify-center h-40'>
|
<div className='col-span-full flex items-center justify-center h-40'>
|
||||||
<p className=''>No data to display</p>
|
<p className=''>No data to display</p>
|
||||||
|
|||||||
@ -2,127 +2,116 @@ import React from 'react';
|
|||||||
import CardBox from '../CardBox';
|
import CardBox from '../CardBox';
|
||||||
import ImageField from '../ImageField';
|
import ImageField from '../ImageField';
|
||||||
import dataFormatter from '../../helpers/dataFormatter';
|
import dataFormatter from '../../helpers/dataFormatter';
|
||||||
import {saveFile} from "../../helpers/fileSaver";
|
import { saveFile } from '../../helpers/fileSaver';
|
||||||
import ListActionsPopover from "../ListActionsPopover";
|
import ListActionsPopover from '../ListActionsPopover';
|
||||||
import {useAppSelector} from "../../stores/hooks";
|
import { useAppSelector } from '../../stores/hooks';
|
||||||
import {Pagination} from "../Pagination";
|
import { Pagination } from '../Pagination';
|
||||||
import LoadingSpinner from "../LoadingSpinner";
|
import LoadingSpinner from '../LoadingSpinner';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
||||||
import {hasPermission} from "../../helpers/userPermissions";
|
import { hasPermission } from '../../helpers/userPermissions';
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
asset_variants: any[];
|
asset_variants: any[];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
onDelete: (id: string) => void;
|
onDelete: (id: string) => void;
|
||||||
currentPage: number;
|
currentPage: number;
|
||||||
numPages: number;
|
numPages: number;
|
||||||
onPageChange: (page: number) => void;
|
onPageChange: (page: number) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ListAsset_variants = ({ asset_variants, loading, onDelete, currentPage, numPages, onPageChange }: Props) => {
|
const ListAsset_variants = ({
|
||||||
|
asset_variants,
|
||||||
|
loading,
|
||||||
|
onDelete,
|
||||||
|
currentPage,
|
||||||
|
numPages,
|
||||||
|
onPageChange,
|
||||||
|
}: Props) => {
|
||||||
|
const currentUser = useAppSelector((state) => state.auth.currentUser);
|
||||||
|
const hasUpdatePermission = hasPermission(
|
||||||
|
currentUser,
|
||||||
|
'UPDATE_ASSET_VARIANTS',
|
||||||
|
);
|
||||||
|
|
||||||
const currentUser = useAppSelector((state) => state.auth.currentUser);
|
const corners = useAppSelector((state) => state.style.corners);
|
||||||
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_ASSET_VARIANTS')
|
const bgColor = useAppSelector((state) => state.style.cardsColor);
|
||||||
|
|
||||||
const corners = useAppSelector((state) => state.style.corners);
|
return (
|
||||||
const bgColor = useAppSelector((state) => state.style.cardsColor);
|
<>
|
||||||
|
<div className='relative overflow-x-auto p-4 space-y-4'>
|
||||||
|
{loading && <LoadingSpinner />}
|
||||||
|
{!loading &&
|
||||||
|
asset_variants.map((item) => (
|
||||||
|
<div key={item.id}>
|
||||||
|
<CardBox hasTable isList className={'rounded shadow-none'}>
|
||||||
|
<div
|
||||||
|
className={`flex rounded dark:bg-dark-900 border border-stone-300 items-center overflow-hidden`}
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
href={`/asset_variants/asset_variants-view/?id=${item.id}`}
|
||||||
|
className={
|
||||||
|
'flex-1 px-4 py-6 h-24 flex divide-x-2 divide-stone-300 items-center overflow-hidden`}> dark:divide-dark-700 overflow-x-auto'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Asset</p>
|
||||||
|
<p className={'line-clamp-2'}>
|
||||||
|
{dataFormatter.assetsOneListFormatter(item.asset)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Varianttype</p>
|
||||||
|
<p className={'line-clamp-2'}>{item.variant_type}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
return (
|
<div className={'flex-1 px-3'}>
|
||||||
<>
|
<p className={'text-xs text-gray-500 '}>CDNURL</p>
|
||||||
<div className='relative overflow-x-auto p-4 space-y-4'>
|
<p className={'line-clamp-2'}>{item.cdn_url}</p>
|
||||||
{loading && <LoadingSpinner />}
|
</div>
|
||||||
{!loading && asset_variants.map((item) => (
|
|
||||||
<div key={item.id}>
|
|
||||||
<CardBox hasTable isList className={'rounded shadow-none'}>
|
|
||||||
<div className={`flex rounded dark:bg-dark-900 border border-stone-300 items-center overflow-hidden`}>
|
|
||||||
|
|
||||||
<Link
|
<div className={'flex-1 px-3'}>
|
||||||
href={`/asset_variants/asset_variants-view/?id=${item.id}`}
|
<p className={'text-xs text-gray-500 '}>Width(px)</p>
|
||||||
className={
|
<p className={'line-clamp-2'}>{item.width_px}</p>
|
||||||
'flex-1 px-4 py-6 h-24 flex divide-x-2 divide-stone-300 items-center overflow-hidden`}> dark:divide-dark-700 overflow-x-auto'
|
</div>
|
||||||
}
|
|
||||||
>
|
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Height(px)</p>
|
||||||
|
<p className={'line-clamp-2'}>{item.height_px}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
<div className={'flex-1 px-3'}>
|
||||||
<p className={'text-xs text-gray-500 '}>Asset</p>
|
<p className={'text-xs text-gray-500 '}>Size(MB)</p>
|
||||||
<p className={'line-clamp-2'}>{ dataFormatter.assetsOneListFormatter(item.asset) }</p>
|
<p className={'line-clamp-2'}>{item.size_mb}</p>
|
||||||
</div>
|
</div>
|
||||||
|
</Link>
|
||||||
|
<ListActionsPopover
|
||||||
|
onDelete={onDelete}
|
||||||
|
itemId={item.id}
|
||||||
<div className={'flex-1 px-3'}>
|
pathEdit={`/asset_variants/asset_variants-edit/?id=${item.id}`}
|
||||||
<p className={'text-xs text-gray-500 '}>Varianttype</p>
|
pathView={`/asset_variants/asset_variants-view/?id=${item.id}`}
|
||||||
<p className={'line-clamp-2'}>{ item.variant_type }</p>
|
hasUpdatePermission={hasUpdatePermission}
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
</CardBox>
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>CDNURL</p>
|
|
||||||
<p className={'line-clamp-2'}>{ item.cdn_url }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>Width(px)</p>
|
|
||||||
<p className={'line-clamp-2'}>{ item.width_px }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>Height(px)</p>
|
|
||||||
<p className={'line-clamp-2'}>{ item.height_px }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>Size(MB)</p>
|
|
||||||
<p className={'line-clamp-2'}>{ item.size_mb }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Link>
|
|
||||||
<ListActionsPopover
|
|
||||||
onDelete={onDelete}
|
|
||||||
itemId={item.id}
|
|
||||||
pathEdit={`/asset_variants/asset_variants-edit/?id=${item.id}`}
|
|
||||||
pathView={`/asset_variants/asset_variants-view/?id=${item.id}`}
|
|
||||||
|
|
||||||
hasUpdatePermission={hasUpdatePermission}
|
|
||||||
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</CardBox>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
{!loading && asset_variants.length === 0 && (
|
|
||||||
<div className='col-span-full flex items-center justify-center h-40'>
|
|
||||||
<p className=''>No data to display</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className={'flex items-center justify-center my-6'}>
|
))}
|
||||||
<Pagination
|
{!loading && asset_variants.length === 0 && (
|
||||||
currentPage={currentPage}
|
<div className='col-span-full flex items-center justify-center h-40'>
|
||||||
numPages={numPages}
|
<p className=''>No data to display</p>
|
||||||
setCurrentPage={onPageChange}
|
</div>
|
||||||
/>
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
<div className={'flex items-center justify-center my-6'}>
|
||||||
)
|
<Pagination
|
||||||
|
currentPage={currentPage}
|
||||||
|
numPages={numPages}
|
||||||
|
setCurrentPage={onPageChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ListAsset_variants
|
export default ListAsset_variants;
|
||||||
|
|||||||
@ -1,463 +1,48 @@
|
|||||||
import React, { useEffect, useState, useMemo } from 'react'
|
/**
|
||||||
import { createPortal } from 'react-dom';
|
* Asset Variants Table Component
|
||||||
import { ToastContainer, toast } from 'react-toastify';
|
*/
|
||||||
import BaseButton from '../BaseButton'
|
|
||||||
import CardBoxModal from '../CardBoxModal'
|
import React from 'react';
|
||||||
import CardBox from "../CardBox";
|
import GenericTable from '../Generic/GenericTable';
|
||||||
import { fetch, update, deleteItem, setRefetch, deleteItemsByIds } from '../../stores/asset_variants/asset_variantsSlice'
|
|
||||||
import { useAppDispatch, useAppSelector } from '../../stores/hooks'
|
|
||||||
import { useRouter } from 'next/router'
|
|
||||||
import { Field, Form, Formik } from "formik";
|
|
||||||
import {
|
import {
|
||||||
DataGrid,
|
fetch,
|
||||||
GridColDef,
|
update,
|
||||||
} from '@mui/x-data-grid';
|
deleteItem,
|
||||||
import {loadColumns} from "./configureAsset_variantsCols";
|
setRefetch,
|
||||||
import _ from 'lodash';
|
deleteItemsByIds,
|
||||||
import dataFormatter from '../../helpers/dataFormatter'
|
} from '../../stores/asset_variants/asset_variantsSlice';
|
||||||
import {dataGridStyles} from "../../styles";
|
import { loadColumns } from './configureAsset_variantsCols';
|
||||||
|
import type { AssetVariant } from '../../types/entities';
|
||||||
|
import type { RootState } from '../../stores/store';
|
||||||
|
import type { Filter, FilterItem } from '../../types/filters';
|
||||||
|
|
||||||
|
interface TableAsset_variantsProps {
|
||||||
|
filterItems: FilterItem[];
|
||||||
const perPage = 10
|
setFilterItems: (items: FilterItem[]) => void;
|
||||||
|
filters: Filter[];
|
||||||
const TableSampleAsset_variants = ({ filterItems, setFilterItems, filters, showGrid }) => {
|
showGrid?: boolean;
|
||||||
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
|
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const pagesList = [];
|
|
||||||
const [id, setId] = useState(null);
|
|
||||||
const [currentPage, setCurrentPage] = useState(0);
|
|
||||||
const [filterRequest, setFilterRequest] = React.useState('');
|
|
||||||
const [columns, setColumns] = useState<GridColDef[]>([]);
|
|
||||||
const [selectedRows, setSelectedRows] = useState([]);
|
|
||||||
const [sortModel, setSortModel] = useState([
|
|
||||||
{
|
|
||||||
field: '',
|
|
||||||
sort: 'desc',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const { asset_variants, loading, count, notify: asset_variantsNotify, refetch } = useAppSelector((state) => state.asset_variants)
|
|
||||||
const { currentUser } = useAppSelector((state) => state.auth);
|
|
||||||
const focusRing = useAppSelector((state) => state.style.focusRingColor);
|
|
||||||
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
|
|
||||||
const corners = useAppSelector((state) => state.style.corners);
|
|
||||||
const numPages = Math.floor(count / perPage) === 0 ? 1 : Math.ceil(count / perPage);
|
|
||||||
for (let i = 0; i < numPages; i++) {
|
|
||||||
pagesList.push(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadData = async (page = currentPage, request = filterRequest) => {
|
|
||||||
if (page !== currentPage) setCurrentPage(page);
|
|
||||||
if (request !== filterRequest) setFilterRequest(request);
|
|
||||||
const { sort, field } = sortModel[0];
|
|
||||||
|
|
||||||
const query = `?page=${page}&limit=${perPage}${request}&sort=${sort}&field=${field}`;
|
|
||||||
dispatch(fetch({ limit: perPage, page, query }));
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (asset_variantsNotify.showNotification) {
|
|
||||||
notify(asset_variantsNotify.typeNotification, asset_variantsNotify.textNotification);
|
|
||||||
}
|
|
||||||
}, [asset_variantsNotify.showNotification]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!currentUser) return;
|
|
||||||
loadData();
|
|
||||||
}, [sortModel, currentUser]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (refetch) {
|
|
||||||
loadData(0);
|
|
||||||
dispatch(setRefetch(false));
|
|
||||||
}
|
|
||||||
}, [refetch, dispatch]);
|
|
||||||
|
|
||||||
const [isModalInfoActive, setIsModalInfoActive] = useState(false)
|
|
||||||
const [isModalTrashActive, setIsModalTrashActive] = useState(false)
|
|
||||||
|
|
||||||
const handleModalAction = () => {
|
|
||||||
setIsModalInfoActive(false)
|
|
||||||
setIsModalTrashActive(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleDeleteModalAction = (id: string) => {
|
|
||||||
setId(id)
|
|
||||||
setIsModalTrashActive(true)
|
|
||||||
}
|
|
||||||
const handleDeleteAction = async () => {
|
|
||||||
if (id) {
|
|
||||||
await dispatch(deleteItem(id));
|
|
||||||
await loadData(0);
|
|
||||||
setIsModalTrashActive(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const generateFilterRequests = useMemo(() => {
|
|
||||||
let request = '&';
|
|
||||||
filterItems.forEach((item) => {
|
|
||||||
const isRangeFilter = filters.find(
|
|
||||||
(filter) =>
|
|
||||||
filter.title === item.fields.selectedField &&
|
|
||||||
(filter.number || filter.date),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isRangeFilter) {
|
|
||||||
const from = item.fields.filterValueFrom;
|
|
||||||
const to = item.fields.filterValueTo;
|
|
||||||
if (from) {
|
|
||||||
request += `${item.fields.selectedField}Range=${from}&`;
|
|
||||||
}
|
|
||||||
if (to) {
|
|
||||||
request += `${item.fields.selectedField}Range=${to}&`;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const value = item.fields.filterValue;
|
|
||||||
if (value) {
|
|
||||||
request += `${item.fields.selectedField}=${value}&`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return request;
|
|
||||||
}, [filterItems, filters]);
|
|
||||||
|
|
||||||
const deleteFilter = (value) => {
|
|
||||||
const newItems = filterItems.filter((item) => item.id !== value);
|
|
||||||
|
|
||||||
if (newItems.length) {
|
|
||||||
setFilterItems(newItems);
|
|
||||||
} else {
|
|
||||||
loadData(0, '');
|
|
||||||
|
|
||||||
setFilterItems(newItems);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = () => {
|
|
||||||
loadData(0, generateFilterRequests);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleChange = (id) => (e) => {
|
|
||||||
const value = e.target.value;
|
|
||||||
const name = e.target.name;
|
|
||||||
|
|
||||||
setFilterItems(
|
|
||||||
filterItems.map((item) => {
|
|
||||||
if (item.id !== id) return item;
|
|
||||||
if (name === 'selectedField') return { id, fields: { [name]: value } };
|
|
||||||
|
|
||||||
return { id, fields: { ...item.fields, [name]: value } }
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleReset = () => {
|
|
||||||
setFilterItems([]);
|
|
||||||
loadData(0, '');
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const onPageChange = (page: number) => {
|
|
||||||
loadData(page);
|
|
||||||
setCurrentPage(page);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!currentUser) return;
|
|
||||||
|
|
||||||
loadColumns(
|
|
||||||
handleDeleteModalAction,
|
|
||||||
`asset_variants`,
|
|
||||||
currentUser,
|
|
||||||
).then((newCols) => setColumns(newCols));
|
|
||||||
}, [currentUser]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleTableSubmit = async (id: string, data) => {
|
|
||||||
|
|
||||||
if (!_.isEmpty(data)) {
|
|
||||||
await dispatch(update({ id, data }))
|
|
||||||
.unwrap()
|
|
||||||
.then((res) => res)
|
|
||||||
.catch((err) => {
|
|
||||||
throw new Error(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDeleteRows = async (selectedRows) => {
|
|
||||||
await dispatch(deleteItemsByIds(selectedRows));
|
|
||||||
await loadData(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
const controlClasses =
|
|
||||||
'w-full py-2 px-2 my-2 rounded dark:placeholder-gray-400 ' +
|
|
||||||
` ${bgColor} ${focusRing} ${corners} ` +
|
|
||||||
'dark:bg-slate-800 border';
|
|
||||||
|
|
||||||
|
|
||||||
const dataGrid = (
|
|
||||||
<div className='relative overflow-x-auto'>
|
|
||||||
<DataGrid
|
|
||||||
autoHeight
|
|
||||||
rowHeight={64}
|
|
||||||
sx={dataGridStyles}
|
|
||||||
className={'datagrid--table'}
|
|
||||||
getRowClassName={() => `datagrid--row`}
|
|
||||||
rows={asset_variants ?? []}
|
|
||||||
columns={columns}
|
|
||||||
initialState={{
|
|
||||||
pagination: {
|
|
||||||
paginationModel: {
|
|
||||||
pageSize: 10,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
disableRowSelectionOnClick
|
|
||||||
onProcessRowUpdateError={(params) => {
|
|
||||||
console.log('Error', params);
|
|
||||||
}}
|
|
||||||
processRowUpdate={async (newRow, oldRow) => {
|
|
||||||
const data = dataFormatter.dataGridEditFormatter(newRow);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await handleTableSubmit(newRow.id, data);
|
|
||||||
return newRow;
|
|
||||||
} catch {
|
|
||||||
return oldRow;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
sortingMode={'server'}
|
|
||||||
checkboxSelection
|
|
||||||
onRowSelectionModelChange={(ids) => {
|
|
||||||
setSelectedRows(ids)
|
|
||||||
}}
|
|
||||||
onSortModelChange={(params) => {
|
|
||||||
params.length
|
|
||||||
? setSortModel(params)
|
|
||||||
: setSortModel([{ field: '', sort: 'desc' }]);
|
|
||||||
}}
|
|
||||||
rowCount={count}
|
|
||||||
pageSizeOptions={[10]}
|
|
||||||
paginationMode={'server'}
|
|
||||||
loading={loading}
|
|
||||||
onPaginationModelChange={(params) => {
|
|
||||||
onPageChange(params.page);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{filterItems && Array.isArray( filterItems ) && filterItems.length ?
|
|
||||||
<CardBox>
|
|
||||||
<Formik
|
|
||||||
initialValues={{
|
|
||||||
checkboxes: ['lorem'],
|
|
||||||
switches: ['lorem'],
|
|
||||||
radio: 'lorem',
|
|
||||||
}}
|
|
||||||
onSubmit={() => null}
|
|
||||||
>
|
|
||||||
<Form>
|
|
||||||
<>
|
|
||||||
{filterItems && filterItems.map((filterItem) => {
|
|
||||||
return (
|
|
||||||
<div key={filterItem.id} className="flex mb-4">
|
|
||||||
<div className="flex flex-col w-full mr-3">
|
|
||||||
<div className=" text-gray-500 font-bold">Filter</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='selectedField'
|
|
||||||
id='selectedField'
|
|
||||||
component='select'
|
|
||||||
value={filterItem?.fields?.selectedField || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
>
|
|
||||||
{filters.map((selectOption) => (
|
|
||||||
<option
|
|
||||||
key={selectOption.title}
|
|
||||||
value={`${selectOption.title}`}
|
|
||||||
>
|
|
||||||
{selectOption.label}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</Field>
|
|
||||||
</div>
|
|
||||||
{filters.find((filter) =>
|
|
||||||
filter.title === filterItem?.fields?.selectedField
|
|
||||||
)?.type === 'enum' ? (
|
|
||||||
<div className="flex flex-col w-full mr-3">
|
|
||||||
<div className="text-gray-500 font-bold">
|
|
||||||
Value
|
|
||||||
</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name="filterValue"
|
|
||||||
id='filterValue'
|
|
||||||
component="select"
|
|
||||||
value={filterItem?.fields?.filterValue || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
>
|
|
||||||
<option value="">Select Value</option>
|
|
||||||
{filters.find((filter) =>
|
|
||||||
filter.title === filterItem?.fields?.selectedField
|
|
||||||
)?.options?.map((option) => (
|
|
||||||
<option key={option} value={option}>
|
|
||||||
{option}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</Field>
|
|
||||||
</div>
|
|
||||||
) : filters.find((filter) =>
|
|
||||||
filter.title === filterItem?.fields?.selectedField
|
|
||||||
)?.number ? (
|
|
||||||
<div className="flex flex-row w-full mr-3">
|
|
||||||
<div className="flex flex-col w-full mr-3">
|
|
||||||
<div className=" text-gray-500 font-bold">From</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='filterValueFrom'
|
|
||||||
placeholder='From'
|
|
||||||
id='filterValueFrom'
|
|
||||||
value={filterItem?.fields?.filterValueFrom || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col w-full">
|
|
||||||
<div className=" text-gray-500 font-bold">To</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='filterValueTo'
|
|
||||||
placeholder='to'
|
|
||||||
id='filterValueTo'
|
|
||||||
value={filterItem?.fields?.filterValueTo || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : filters.find(
|
|
||||||
(filter) =>
|
|
||||||
filter.title ===
|
|
||||||
filterItem?.fields?.selectedField
|
|
||||||
)?.date ? (
|
|
||||||
<div className='flex flex-row w-full mr-3'>
|
|
||||||
<div className='flex flex-col w-full mr-3'>
|
|
||||||
<div className=' text-gray-500 font-bold'>
|
|
||||||
From
|
|
||||||
</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='filterValueFrom'
|
|
||||||
placeholder='From'
|
|
||||||
id='filterValueFrom'
|
|
||||||
type='datetime-local'
|
|
||||||
value={filterItem?.fields?.filterValueFrom || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className='flex flex-col w-full'>
|
|
||||||
<div className=' text-gray-500 font-bold'>To</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='filterValueTo'
|
|
||||||
placeholder='to'
|
|
||||||
id='filterValueTo'
|
|
||||||
type='datetime-local'
|
|
||||||
value={filterItem?.fields?.filterValueTo || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="flex flex-col w-full mr-3">
|
|
||||||
<div className=" text-gray-500 font-bold">Contains</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='filterValue'
|
|
||||||
placeholder='Contained'
|
|
||||||
id='filterValue'
|
|
||||||
value={filterItem?.fields?.filterValue || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="flex flex-col">
|
|
||||||
<div className=" text-gray-500 font-bold">Action</div>
|
|
||||||
<BaseButton
|
|
||||||
className="my-2"
|
|
||||||
type='reset'
|
|
||||||
color='danger'
|
|
||||||
label='Delete'
|
|
||||||
onClick={() => {
|
|
||||||
deleteFilter(filterItem.id)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
<div className="flex">
|
|
||||||
<BaseButton
|
|
||||||
className="my-2 mr-3"
|
|
||||||
color="success"
|
|
||||||
label='Apply'
|
|
||||||
onClick={handleSubmit}
|
|
||||||
/>
|
|
||||||
<BaseButton
|
|
||||||
className="my-2"
|
|
||||||
color='info'
|
|
||||||
label='Cancel'
|
|
||||||
onClick={handleReset}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
</Form>
|
|
||||||
</Formik>
|
|
||||||
</CardBox> : null
|
|
||||||
}
|
|
||||||
<CardBoxModal
|
|
||||||
title="Please confirm"
|
|
||||||
buttonColor="info"
|
|
||||||
buttonLabel={loading ? 'Deleting...' : 'Confirm'}
|
|
||||||
isActive={isModalTrashActive}
|
|
||||||
onConfirm={handleDeleteAction}
|
|
||||||
onCancel={handleModalAction}
|
|
||||||
>
|
|
||||||
<p>Are you sure you want to delete this item?</p>
|
|
||||||
</CardBoxModal>
|
|
||||||
|
|
||||||
|
|
||||||
{dataGrid}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{selectedRows.length > 0 &&
|
|
||||||
createPortal(
|
|
||||||
<BaseButton
|
|
||||||
className='me-4'
|
|
||||||
color='danger'
|
|
||||||
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`}
|
|
||||||
onClick={() => onDeleteRows(selectedRows)}
|
|
||||||
/>,
|
|
||||||
document.getElementById('delete-rows-button'),
|
|
||||||
)}
|
|
||||||
<ToastContainer />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TableSampleAsset_variants
|
const TableAsset_variants: React.FC<TableAsset_variantsProps> = ({
|
||||||
|
filterItems,
|
||||||
|
setFilterItems,
|
||||||
|
filters,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<GenericTable<AssetVariant>
|
||||||
|
entityName='asset_variants'
|
||||||
|
sliceSelector={(state: RootState) => state.asset_variants}
|
||||||
|
fetchAction={fetch}
|
||||||
|
updateAction={update}
|
||||||
|
deleteAction={deleteItem}
|
||||||
|
deleteByIdsAction={deleteItemsByIds}
|
||||||
|
setRefetchAction={setRefetch}
|
||||||
|
loadColumnsFunction={loadColumns}
|
||||||
|
filters={filters}
|
||||||
|
filterItems={filterItems}
|
||||||
|
setFilterItems={setFilterItems}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TableAsset_variants;
|
||||||
|
|||||||
@ -3,166 +3,146 @@ import BaseIcon from '../BaseIcon';
|
|||||||
import { mdiEye, mdiTrashCan, mdiPencilOutline } from '@mdi/js';
|
import { mdiEye, mdiTrashCan, mdiPencilOutline } from '@mdi/js';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import {
|
import {
|
||||||
GridActionsCellItem,
|
GridActionsCellItem,
|
||||||
GridRowParams,
|
GridRowParams,
|
||||||
GridValueGetterParams,
|
GridValueGetterParams,
|
||||||
} from '@mui/x-data-grid';
|
} from '@mui/x-data-grid';
|
||||||
import ImageField from '../ImageField';
|
import ImageField from '../ImageField';
|
||||||
import {saveFile} from "../../helpers/fileSaver";
|
import { saveFile } from '../../helpers/fileSaver';
|
||||||
import dataFormatter from '../../helpers/dataFormatter'
|
import dataFormatter from '../../helpers/dataFormatter';
|
||||||
import DataGridMultiSelect from "../DataGridMultiSelect";
|
import DataGridMultiSelect from '../DataGridMultiSelect';
|
||||||
import ListActionsPopover from '../ListActionsPopover';
|
import ListActionsPopover from '../ListActionsPopover';
|
||||||
|
|
||||||
import {hasPermission} from "../../helpers/userPermissions";
|
import { hasPermission } from '../../helpers/userPermissions';
|
||||||
|
|
||||||
type Params = (id: string) => void;
|
type Params = (id: string) => void;
|
||||||
|
|
||||||
export const loadColumns = async (
|
export const loadColumns = async (
|
||||||
onDelete: Params,
|
onDelete: Params,
|
||||||
entityName: string,
|
entityName: string,
|
||||||
|
|
||||||
user
|
|
||||||
|
|
||||||
|
user,
|
||||||
) => {
|
) => {
|
||||||
async function callOptionsApi(entityName: string) {
|
async function callOptionsApi(entityName: string) {
|
||||||
|
if (!hasPermission(user, 'READ_' + entityName.toUpperCase())) return [];
|
||||||
|
|
||||||
if (!hasPermission(user, 'READ_' + entityName.toUpperCase())) return [];
|
try {
|
||||||
|
const data = await axios(`/${entityName}/autocomplete?limit=100`);
|
||||||
try {
|
return data.data;
|
||||||
const data = await axios(`/${entityName}/autocomplete?limit=100`);
|
} catch (error) {
|
||||||
return data.data;
|
console.log(error);
|
||||||
} catch (error) {
|
return [];
|
||||||
console.log(error);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const hasUpdatePermission = hasPermission(user, 'UPDATE_ASSET_VARIANTS')
|
const hasUpdatePermission = hasPermission(user, 'UPDATE_ASSET_VARIANTS');
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
{
|
||||||
|
field: 'asset',
|
||||||
|
headerName: 'Asset',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
{
|
editable: hasUpdatePermission,
|
||||||
field: 'asset',
|
|
||||||
headerName: 'Asset',
|
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
|
||||||
filterable: false,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
|
|
||||||
|
sortable: false,
|
||||||
|
type: 'singleSelect',
|
||||||
|
getOptionValue: (value: any) => value?.id,
|
||||||
|
getOptionLabel: (value: any) => value?.label,
|
||||||
|
valueOptions: await callOptionsApi('assets'),
|
||||||
|
valueGetter: (params: GridValueGetterParams) =>
|
||||||
|
params?.value?.id ?? params?.value,
|
||||||
|
},
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
{
|
||||||
|
field: 'variant_type',
|
||||||
|
headerName: 'Varianttype',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
sortable: false,
|
editable: hasUpdatePermission,
|
||||||
type: 'singleSelect',
|
},
|
||||||
getOptionValue: (value: any) => value?.id,
|
|
||||||
getOptionLabel: (value: any) => value?.label,
|
|
||||||
valueOptions: await callOptionsApi('assets'),
|
|
||||||
valueGetter: (params: GridValueGetterParams) =>
|
|
||||||
params?.value?.id ?? params?.value,
|
|
||||||
|
|
||||||
},
|
{
|
||||||
|
field: 'cdn_url',
|
||||||
|
headerName: 'CDNURL',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
{
|
editable: hasUpdatePermission,
|
||||||
field: 'variant_type',
|
},
|
||||||
headerName: 'Varianttype',
|
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
|
||||||
filterable: false,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'width_px',
|
||||||
|
headerName: 'Width(px)',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
editable: hasUpdatePermission,
|
||||||
|
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
|
||||||
},
|
{
|
||||||
|
field: 'height_px',
|
||||||
|
headerName: 'Height(px)',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
{
|
editable: hasUpdatePermission,
|
||||||
field: 'cdn_url',
|
|
||||||
headerName: 'CDNURL',
|
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
|
||||||
filterable: false,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
|
|
||||||
|
type: 'number',
|
||||||
|
},
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
{
|
||||||
|
field: 'size_mb',
|
||||||
|
headerName: 'Size(MB)',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
|
editable: hasUpdatePermission,
|
||||||
|
|
||||||
},
|
type: 'number',
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
field: 'width_px',
|
field: 'actions',
|
||||||
headerName: 'Width(px)',
|
type: 'actions',
|
||||||
flex: 1,
|
minWidth: 30,
|
||||||
minWidth: 120,
|
headerClassName: 'datagrid--header',
|
||||||
filterable: false,
|
cellClassName: 'datagrid--cell',
|
||||||
headerClassName: 'datagrid--header',
|
getActions: (params: GridRowParams) => {
|
||||||
cellClassName: 'datagrid--cell',
|
return [
|
||||||
|
<div key={params?.row?.id}>
|
||||||
|
<ListActionsPopover
|
||||||
editable: hasUpdatePermission,
|
onDelete={onDelete}
|
||||||
|
itemId={params?.row?.id}
|
||||||
type: 'number',
|
pathEdit={`/asset_variants/asset_variants-edit/?id=${params?.row?.id}`}
|
||||||
|
pathView={`/asset_variants/asset_variants-view/?id=${params?.row?.id}`}
|
||||||
},
|
hasUpdatePermission={hasUpdatePermission}
|
||||||
|
/>
|
||||||
{
|
</div>,
|
||||||
field: 'height_px',
|
];
|
||||||
headerName: 'Height(px)',
|
},
|
||||||
flex: 1,
|
},
|
||||||
minWidth: 120,
|
];
|
||||||
filterable: false,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
|
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
|
||||||
|
|
||||||
type: 'number',
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
field: 'size_mb',
|
|
||||||
headerName: 'Size(MB)',
|
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
|
||||||
filterable: false,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
|
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
|
||||||
|
|
||||||
type: 'number',
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
field: 'actions',
|
|
||||||
type: 'actions',
|
|
||||||
minWidth: 30,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
getActions: (params: GridRowParams) => {
|
|
||||||
|
|
||||||
return [
|
|
||||||
<div key={params?.row?.id}>
|
|
||||||
<ListActionsPopover
|
|
||||||
onDelete={onDelete}
|
|
||||||
itemId={params?.row?.id}
|
|
||||||
pathEdit={`/asset_variants/asset_variants-edit/?id=${params?.row?.id}`}
|
|
||||||
pathView={`/asset_variants/asset_variants-view/?id=${params?.row?.id}`}
|
|
||||||
|
|
||||||
hasUpdatePermission={hasUpdatePermission}
|
|
||||||
|
|
||||||
/>
|
|
||||||
</div>,
|
|
||||||
]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,12 +4,11 @@ import ListActionsPopover from '../ListActionsPopover';
|
|||||||
import { useAppSelector } from '../../stores/hooks';
|
import { useAppSelector } from '../../stores/hooks';
|
||||||
import dataFormatter from '../../helpers/dataFormatter';
|
import dataFormatter from '../../helpers/dataFormatter';
|
||||||
import { Pagination } from '../Pagination';
|
import { Pagination } from '../Pagination';
|
||||||
import {saveFile} from "../../helpers/fileSaver";
|
import { saveFile } from '../../helpers/fileSaver';
|
||||||
import LoadingSpinner from "../LoadingSpinner";
|
import LoadingSpinner from '../LoadingSpinner';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
||||||
import {hasPermission} from "../../helpers/userPermissions";
|
import { hasPermission } from '../../helpers/userPermissions';
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
assets: any[];
|
assets: any[];
|
||||||
@ -28,17 +27,16 @@ const CardAssets = ({
|
|||||||
numPages,
|
numPages,
|
||||||
onPageChange,
|
onPageChange,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const asideScrollbarsStyle = useAppSelector(
|
const asideScrollbarsStyle = useAppSelector(
|
||||||
(state) => state.style.asideScrollbarsStyle,
|
(state) => state.style.asideScrollbarsStyle,
|
||||||
);
|
);
|
||||||
const bgColor = useAppSelector((state) => state.style.cardsColor);
|
const bgColor = useAppSelector((state) => state.style.cardsColor);
|
||||||
const darkMode = useAppSelector((state) => state.style.darkMode);
|
const darkMode = useAppSelector((state) => state.style.darkMode);
|
||||||
const corners = useAppSelector((state) => state.style.corners);
|
const corners = useAppSelector((state) => state.style.corners);
|
||||||
const focusRing = useAppSelector((state) => state.style.focusRingColor);
|
const focusRing = useAppSelector((state) => state.style.focusRingColor);
|
||||||
|
|
||||||
const currentUser = useAppSelector((state) => state.auth.currentUser);
|
|
||||||
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_ASSETS')
|
|
||||||
|
|
||||||
|
const currentUser = useAppSelector((state) => state.auth.currentUser);
|
||||||
|
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_ASSETS');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'p-4'}>
|
<div className={'p-4'}>
|
||||||
@ -47,206 +45,196 @@ const CardAssets = ({
|
|||||||
role='list'
|
role='list'
|
||||||
className='grid grid-cols-1 gap-x-6 gap-y-8 lg:grid-cols-3 2xl:grid-cols-4 xl:gap-x-8'
|
className='grid grid-cols-1 gap-x-6 gap-y-8 lg:grid-cols-3 2xl:grid-cols-4 xl:gap-x-8'
|
||||||
>
|
>
|
||||||
{!loading && assets.map((item, index) => (
|
{!loading &&
|
||||||
<li
|
assets.map((item, index) => (
|
||||||
key={item.id}
|
<li
|
||||||
className={`overflow-hidden ${corners !== 'rounded-full'? corners : 'rounded-3xl'} border ${focusRing} border-gray-200 dark:border-dark-700 ${
|
key={item.id}
|
||||||
|
className={`overflow-hidden ${corners !== 'rounded-full' ? corners : 'rounded-3xl'} border ${focusRing} border-gray-200 dark:border-dark-700 ${
|
||||||
darkMode ? 'aside-scrollbars-[slate]' : asideScrollbarsStyle
|
darkMode ? 'aside-scrollbars-[slate]' : asideScrollbarsStyle
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
|
<div
|
||||||
<div className={`flex items-center ${bgColor} p-6 gap-x-4 border-b border-gray-900/5 bg-gray-50 dark:bg-dark-800 relative`}>
|
className={`flex items-center ${bgColor} p-6 gap-x-4 border-b border-gray-900/5 bg-gray-50 dark:bg-dark-800 relative`}
|
||||||
|
>
|
||||||
<Link href={`/assets/assets-view/?id=${item.id}`} className='text-lg font-bold leading-6 line-clamp-1'>
|
<Link
|
||||||
{item.name}
|
href={`/assets/assets-view/?id=${item.id}`}
|
||||||
|
className='text-lg font-bold leading-6 line-clamp-1'
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
|
<div className='ml-auto '>
|
||||||
<div className='ml-auto '>
|
<ListActionsPopover
|
||||||
<ListActionsPopover
|
onDelete={onDelete}
|
||||||
onDelete={onDelete}
|
itemId={item.id}
|
||||||
itemId={item.id}
|
pathEdit={`/assets/assets-edit/?id=${item.id}`}
|
||||||
pathEdit={`/assets/assets-edit/?id=${item.id}`}
|
pathView={`/assets/assets-view/?id=${item.id}`}
|
||||||
pathView={`/assets/assets-view/?id=${item.id}`}
|
hasUpdatePermission={hasUpdatePermission}
|
||||||
|
/>
|
||||||
hasUpdatePermission={hasUpdatePermission}
|
</div>
|
||||||
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<dl className='divide-y divide-stone-300 dark:divide-dark-700 px-6 py-4 text-sm leading-6 h-64 overflow-y-auto'>
|
||||||
<dl className='divide-y divide-stone-300 dark:divide-dark-700 px-6 py-4 text-sm leading-6 h-64 overflow-y-auto'>
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Project</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Project
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ dataFormatter.projectsOneListFormatter(item.project) }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{dataFormatter.projectsOneListFormatter(item.project)}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Name</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>Name</dt>
|
||||||
<dd className='flex items-start gap-x-2'>
|
<dd className='flex items-start gap-x-2'>
|
||||||
<div className='font-medium line-clamp-4'>
|
<div className='font-medium line-clamp-4'>{item.name}</div>
|
||||||
{ item.name }
|
</dd>
|
||||||
</div>
|
|
||||||
</dd>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Assettype</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Asset format
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ item.asset_type }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.asset_type}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>CDNURL</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>Type</dt>
|
||||||
<dd className='flex items-start gap-x-2'>
|
<dd className='flex items-start gap-x-2'>
|
||||||
<div className='font-medium line-clamp-4'>
|
<div className='font-medium line-clamp-4'>
|
||||||
{ item.cdn_url }
|
{item.type || 'general'}
|
||||||
</div>
|
</div>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Storagekey</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
CDNURL
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ item.storage_key }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.cdn_url}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>MIMEtype</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Storagekey
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ item.mime_type }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.storage_key}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Size(MB)</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
MIMEtype
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ item.size_mb }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.mime_type}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Width(px)</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Size(MB)
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ item.width_px }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.size_mb}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Height(px)</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Width(px)
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ item.height_px }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.width_px}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Duration(sec)</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Height(px)
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ item.duration_sec }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.height_px}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Checksum</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Duration(sec)
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ item.checksum }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.duration_sec}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Ispublic</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Checksum
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ dataFormatter.booleanFormatter(item.is_public) }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{item.checksum}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Isdeleted</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Ispublic
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ dataFormatter.booleanFormatter(item.is_deleted) }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{dataFormatter.booleanFormatter(item.is_public)}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>Deletedat</dt>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
<dd className='flex items-start gap-x-2'>
|
Isdeleted
|
||||||
<div className='font-medium line-clamp-4'>
|
</dt>
|
||||||
{ dataFormatter.dateTimeFormatter(item.deleted_at_time) }
|
<dd className='flex items-start gap-x-2'>
|
||||||
</div>
|
<div className='font-medium line-clamp-4'>
|
||||||
</dd>
|
{dataFormatter.booleanFormatter(item.is_deleted)}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
</dl>
|
Deletedat
|
||||||
</li>
|
</dt>
|
||||||
))}
|
<dd className='flex items-start gap-x-2'>
|
||||||
|
<div className='font-medium line-clamp-4'>
|
||||||
|
{dataFormatter.dateTimeFormatter(item.deleted_at_time)}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
</dl>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
{!loading && assets.length === 0 && (
|
{!loading && assets.length === 0 && (
|
||||||
<div className='col-span-full flex items-center justify-center h-40'>
|
<div className='col-span-full flex items-center justify-center h-40'>
|
||||||
<p className=''>No data to display</p>
|
<p className=''>No data to display</p>
|
||||||
|
|||||||
@ -2,191 +2,166 @@ import React from 'react';
|
|||||||
import CardBox from '../CardBox';
|
import CardBox from '../CardBox';
|
||||||
import ImageField from '../ImageField';
|
import ImageField from '../ImageField';
|
||||||
import dataFormatter from '../../helpers/dataFormatter';
|
import dataFormatter from '../../helpers/dataFormatter';
|
||||||
import {saveFile} from "../../helpers/fileSaver";
|
import { saveFile } from '../../helpers/fileSaver';
|
||||||
import ListActionsPopover from "../ListActionsPopover";
|
import ListActionsPopover from '../ListActionsPopover';
|
||||||
import {useAppSelector} from "../../stores/hooks";
|
import { useAppSelector } from '../../stores/hooks';
|
||||||
import {Pagination} from "../Pagination";
|
import { Pagination } from '../Pagination';
|
||||||
import LoadingSpinner from "../LoadingSpinner";
|
import LoadingSpinner from '../LoadingSpinner';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
|
||||||
import {hasPermission} from "../../helpers/userPermissions";
|
import { hasPermission } from '../../helpers/userPermissions';
|
||||||
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
assets: any[];
|
assets: any[];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
onDelete: (id: string) => void;
|
onDelete: (id: string) => void;
|
||||||
currentPage: number;
|
currentPage: number;
|
||||||
numPages: number;
|
numPages: number;
|
||||||
onPageChange: (page: number) => void;
|
onPageChange: (page: number) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ListAssets = ({ assets, loading, onDelete, currentPage, numPages, onPageChange }: Props) => {
|
const ListAssets = ({
|
||||||
|
assets,
|
||||||
|
loading,
|
||||||
|
onDelete,
|
||||||
|
currentPage,
|
||||||
|
numPages,
|
||||||
|
onPageChange,
|
||||||
|
}: Props) => {
|
||||||
|
const currentUser = useAppSelector((state) => state.auth.currentUser);
|
||||||
|
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_ASSETS');
|
||||||
|
|
||||||
const currentUser = useAppSelector((state) => state.auth.currentUser);
|
const corners = useAppSelector((state) => state.style.corners);
|
||||||
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_ASSETS')
|
const bgColor = useAppSelector((state) => state.style.cardsColor);
|
||||||
|
|
||||||
const corners = useAppSelector((state) => state.style.corners);
|
return (
|
||||||
const bgColor = useAppSelector((state) => state.style.cardsColor);
|
<>
|
||||||
|
<div className='relative overflow-x-auto p-4 space-y-4'>
|
||||||
|
{loading && <LoadingSpinner />}
|
||||||
|
{!loading &&
|
||||||
|
assets.map((item) => (
|
||||||
|
<div key={item.id}>
|
||||||
|
<CardBox hasTable isList className={'rounded shadow-none'}>
|
||||||
|
<div
|
||||||
|
className={`flex rounded dark:bg-dark-900 border border-stone-300 items-center overflow-hidden`}
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
href={`/assets/assets-view/?id=${item.id}`}
|
||||||
|
className={
|
||||||
|
'flex-1 px-4 py-6 h-24 flex divide-x-2 divide-stone-300 items-center overflow-hidden`}> dark:divide-dark-700 overflow-x-auto'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Project</p>
|
||||||
|
<p className={'line-clamp-2'}>
|
||||||
|
{dataFormatter.projectsOneListFormatter(item.project)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Name</p>
|
||||||
|
<p className={'line-clamp-2'}>{item.name}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
return (
|
<div className={'flex-1 px-3'}>
|
||||||
<>
|
<p className={'text-xs text-gray-500 '}>Asset format</p>
|
||||||
<div className='relative overflow-x-auto p-4 space-y-4'>
|
<p className={'line-clamp-2'}>{item.asset_type}</p>
|
||||||
{loading && <LoadingSpinner />}
|
</div>
|
||||||
{!loading && assets.map((item) => (
|
|
||||||
<div key={item.id}>
|
|
||||||
<CardBox hasTable isList className={'rounded shadow-none'}>
|
|
||||||
<div className={`flex rounded dark:bg-dark-900 border border-stone-300 items-center overflow-hidden`}>
|
|
||||||
|
|
||||||
<Link
|
<div className={'flex-1 px-3'}>
|
||||||
href={`/assets/assets-view/?id=${item.id}`}
|
<p className={'text-xs text-gray-500 '}>Type</p>
|
||||||
className={
|
<p className={'line-clamp-2'}>{item.type || 'general'}</p>
|
||||||
'flex-1 px-4 py-6 h-24 flex divide-x-2 divide-stone-300 items-center overflow-hidden`}> dark:divide-dark-700 overflow-x-auto'
|
</div>
|
||||||
}
|
|
||||||
>
|
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>CDNURL</p>
|
||||||
|
<p className={'line-clamp-2'}>{item.cdn_url}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
<div className={'flex-1 px-3'}>
|
||||||
<p className={'text-xs text-gray-500 '}>Project</p>
|
<p className={'text-xs text-gray-500 '}>Storagekey</p>
|
||||||
<p className={'line-clamp-2'}>{ dataFormatter.projectsOneListFormatter(item.project) }</p>
|
<p className={'line-clamp-2'}>{item.storage_key}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>MIMEtype</p>
|
||||||
|
<p className={'line-clamp-2'}>{item.mime_type}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Size(MB)</p>
|
||||||
|
<p className={'line-clamp-2'}>{item.size_mb}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Width(px)</p>
|
||||||
|
<p className={'line-clamp-2'}>{item.width_px}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
<div className={'flex-1 px-3'}>
|
||||||
<p className={'text-xs text-gray-500 '}>Name</p>
|
<p className={'text-xs text-gray-500 '}>Height(px)</p>
|
||||||
<p className={'line-clamp-2'}>{ item.name }</p>
|
<p className={'line-clamp-2'}>{item.height_px}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>
|
||||||
|
Duration(sec)
|
||||||
|
</p>
|
||||||
|
<p className={'line-clamp-2'}>{item.duration_sec}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Checksum</p>
|
||||||
|
<p className={'line-clamp-2'}>{item.checksum}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Ispublic</p>
|
||||||
|
<p className={'line-clamp-2'}>
|
||||||
|
{dataFormatter.booleanFormatter(item.is_public)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
<div className={'flex-1 px-3'}>
|
||||||
<p className={'text-xs text-gray-500 '}>Assettype</p>
|
<p className={'text-xs text-gray-500 '}>Isdeleted</p>
|
||||||
<p className={'line-clamp-2'}>{ item.asset_type }</p>
|
<p className={'line-clamp-2'}>
|
||||||
</div>
|
{dataFormatter.booleanFormatter(item.is_deleted)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Deletedat</p>
|
||||||
|
<p className={'line-clamp-2'}>
|
||||||
<div className={'flex-1 px-3'}>
|
{dataFormatter.dateTimeFormatter(item.deleted_at_time)}
|
||||||
<p className={'text-xs text-gray-500 '}>CDNURL</p>
|
</p>
|
||||||
<p className={'line-clamp-2'}>{ item.cdn_url }</p>
|
</div>
|
||||||
</div>
|
</Link>
|
||||||
|
<ListActionsPopover
|
||||||
|
onDelete={onDelete}
|
||||||
|
itemId={item.id}
|
||||||
|
pathEdit={`/assets/assets-edit/?id=${item.id}`}
|
||||||
<div className={'flex-1 px-3'}>
|
pathView={`/assets/assets-view/?id=${item.id}`}
|
||||||
<p className={'text-xs text-gray-500 '}>Storagekey</p>
|
hasUpdatePermission={hasUpdatePermission}
|
||||||
<p className={'line-clamp-2'}>{ item.storage_key }</p>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</CardBox>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>MIMEtype</p>
|
|
||||||
<p className={'line-clamp-2'}>{ item.mime_type }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>Size(MB)</p>
|
|
||||||
<p className={'line-clamp-2'}>{ item.size_mb }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>Width(px)</p>
|
|
||||||
<p className={'line-clamp-2'}>{ item.width_px }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>Height(px)</p>
|
|
||||||
<p className={'line-clamp-2'}>{ item.height_px }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>Duration(sec)</p>
|
|
||||||
<p className={'line-clamp-2'}>{ item.duration_sec }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>Checksum</p>
|
|
||||||
<p className={'line-clamp-2'}>{ item.checksum }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>Ispublic</p>
|
|
||||||
<p className={'line-clamp-2'}>{ dataFormatter.booleanFormatter(item.is_public) }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>Isdeleted</p>
|
|
||||||
<p className={'line-clamp-2'}>{ dataFormatter.booleanFormatter(item.is_deleted) }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>Deletedat</p>
|
|
||||||
<p className={'line-clamp-2'}>{ dataFormatter.dateTimeFormatter(item.deleted_at_time) }</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</Link>
|
|
||||||
<ListActionsPopover
|
|
||||||
onDelete={onDelete}
|
|
||||||
itemId={item.id}
|
|
||||||
pathEdit={`/assets/assets-edit/?id=${item.id}`}
|
|
||||||
pathView={`/assets/assets-view/?id=${item.id}`}
|
|
||||||
|
|
||||||
hasUpdatePermission={hasUpdatePermission}
|
|
||||||
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</CardBox>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
{!loading && assets.length === 0 && (
|
|
||||||
<div className='col-span-full flex items-center justify-center h-40'>
|
|
||||||
<p className=''>No data to display</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className={'flex items-center justify-center my-6'}>
|
))}
|
||||||
<Pagination
|
{!loading && assets.length === 0 && (
|
||||||
currentPage={currentPage}
|
<div className='col-span-full flex items-center justify-center h-40'>
|
||||||
numPages={numPages}
|
<p className=''>No data to display</p>
|
||||||
setCurrentPage={onPageChange}
|
</div>
|
||||||
/>
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
<div className={'flex items-center justify-center my-6'}>
|
||||||
)
|
<Pagination
|
||||||
|
currentPage={currentPage}
|
||||||
|
numPages={numPages}
|
||||||
|
setCurrentPage={onPageChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ListAssets
|
export default ListAssets;
|
||||||
|
|||||||
@ -1,463 +1,48 @@
|
|||||||
import React, { useEffect, useState, useMemo } from 'react'
|
/**
|
||||||
import { createPortal } from 'react-dom';
|
* Assets Table Component
|
||||||
import { ToastContainer, toast } from 'react-toastify';
|
*/
|
||||||
import BaseButton from '../BaseButton'
|
|
||||||
import CardBoxModal from '../CardBoxModal'
|
import React from 'react';
|
||||||
import CardBox from "../CardBox";
|
import GenericTable from '../Generic/GenericTable';
|
||||||
import { fetch, update, deleteItem, setRefetch, deleteItemsByIds } from '../../stores/assets/assetsSlice'
|
|
||||||
import { useAppDispatch, useAppSelector } from '../../stores/hooks'
|
|
||||||
import { useRouter } from 'next/router'
|
|
||||||
import { Field, Form, Formik } from "formik";
|
|
||||||
import {
|
import {
|
||||||
DataGrid,
|
fetch,
|
||||||
GridColDef,
|
update,
|
||||||
} from '@mui/x-data-grid';
|
deleteItem,
|
||||||
import {loadColumns} from "./configureAssetsCols";
|
setRefetch,
|
||||||
import _ from 'lodash';
|
deleteItemsByIds,
|
||||||
import dataFormatter from '../../helpers/dataFormatter'
|
} from '../../stores/assets/assetsSlice';
|
||||||
import {dataGridStyles} from "../../styles";
|
import { loadColumns } from './configureAssetsCols';
|
||||||
|
import type { Asset } from '../../types/entities';
|
||||||
|
import type { RootState } from '../../stores/store';
|
||||||
|
import type { Filter, FilterItem } from '../../types/filters';
|
||||||
|
|
||||||
|
interface TableAssetsProps {
|
||||||
|
filterItems: FilterItem[];
|
||||||
const perPage = 10
|
setFilterItems: (items: FilterItem[]) => void;
|
||||||
|
filters: Filter[];
|
||||||
const TableSampleAssets = ({ filterItems, setFilterItems, filters, showGrid }) => {
|
showGrid?: boolean;
|
||||||
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
|
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const pagesList = [];
|
|
||||||
const [id, setId] = useState(null);
|
|
||||||
const [currentPage, setCurrentPage] = useState(0);
|
|
||||||
const [filterRequest, setFilterRequest] = React.useState('');
|
|
||||||
const [columns, setColumns] = useState<GridColDef[]>([]);
|
|
||||||
const [selectedRows, setSelectedRows] = useState([]);
|
|
||||||
const [sortModel, setSortModel] = useState([
|
|
||||||
{
|
|
||||||
field: '',
|
|
||||||
sort: 'desc',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const { assets, loading, count, notify: assetsNotify, refetch } = useAppSelector((state) => state.assets)
|
|
||||||
const { currentUser } = useAppSelector((state) => state.auth);
|
|
||||||
const focusRing = useAppSelector((state) => state.style.focusRingColor);
|
|
||||||
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
|
|
||||||
const corners = useAppSelector((state) => state.style.corners);
|
|
||||||
const numPages = Math.floor(count / perPage) === 0 ? 1 : Math.ceil(count / perPage);
|
|
||||||
for (let i = 0; i < numPages; i++) {
|
|
||||||
pagesList.push(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadData = async (page = currentPage, request = filterRequest) => {
|
|
||||||
if (page !== currentPage) setCurrentPage(page);
|
|
||||||
if (request !== filterRequest) setFilterRequest(request);
|
|
||||||
const { sort, field } = sortModel[0];
|
|
||||||
|
|
||||||
const query = `?page=${page}&limit=${perPage}${request}&sort=${sort}&field=${field}`;
|
|
||||||
dispatch(fetch({ limit: perPage, page, query }));
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (assetsNotify.showNotification) {
|
|
||||||
notify(assetsNotify.typeNotification, assetsNotify.textNotification);
|
|
||||||
}
|
|
||||||
}, [assetsNotify.showNotification]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!currentUser) return;
|
|
||||||
loadData();
|
|
||||||
}, [sortModel, currentUser]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (refetch) {
|
|
||||||
loadData(0);
|
|
||||||
dispatch(setRefetch(false));
|
|
||||||
}
|
|
||||||
}, [refetch, dispatch]);
|
|
||||||
|
|
||||||
const [isModalInfoActive, setIsModalInfoActive] = useState(false)
|
|
||||||
const [isModalTrashActive, setIsModalTrashActive] = useState(false)
|
|
||||||
|
|
||||||
const handleModalAction = () => {
|
|
||||||
setIsModalInfoActive(false)
|
|
||||||
setIsModalTrashActive(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleDeleteModalAction = (id: string) => {
|
|
||||||
setId(id)
|
|
||||||
setIsModalTrashActive(true)
|
|
||||||
}
|
|
||||||
const handleDeleteAction = async () => {
|
|
||||||
if (id) {
|
|
||||||
await dispatch(deleteItem(id));
|
|
||||||
await loadData(0);
|
|
||||||
setIsModalTrashActive(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const generateFilterRequests = useMemo(() => {
|
|
||||||
let request = '&';
|
|
||||||
filterItems.forEach((item) => {
|
|
||||||
const isRangeFilter = filters.find(
|
|
||||||
(filter) =>
|
|
||||||
filter.title === item.fields.selectedField &&
|
|
||||||
(filter.number || filter.date),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isRangeFilter) {
|
|
||||||
const from = item.fields.filterValueFrom;
|
|
||||||
const to = item.fields.filterValueTo;
|
|
||||||
if (from) {
|
|
||||||
request += `${item.fields.selectedField}Range=${from}&`;
|
|
||||||
}
|
|
||||||
if (to) {
|
|
||||||
request += `${item.fields.selectedField}Range=${to}&`;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const value = item.fields.filterValue;
|
|
||||||
if (value) {
|
|
||||||
request += `${item.fields.selectedField}=${value}&`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return request;
|
|
||||||
}, [filterItems, filters]);
|
|
||||||
|
|
||||||
const deleteFilter = (value) => {
|
|
||||||
const newItems = filterItems.filter((item) => item.id !== value);
|
|
||||||
|
|
||||||
if (newItems.length) {
|
|
||||||
setFilterItems(newItems);
|
|
||||||
} else {
|
|
||||||
loadData(0, '');
|
|
||||||
|
|
||||||
setFilterItems(newItems);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = () => {
|
|
||||||
loadData(0, generateFilterRequests);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleChange = (id) => (e) => {
|
|
||||||
const value = e.target.value;
|
|
||||||
const name = e.target.name;
|
|
||||||
|
|
||||||
setFilterItems(
|
|
||||||
filterItems.map((item) => {
|
|
||||||
if (item.id !== id) return item;
|
|
||||||
if (name === 'selectedField') return { id, fields: { [name]: value } };
|
|
||||||
|
|
||||||
return { id, fields: { ...item.fields, [name]: value } }
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleReset = () => {
|
|
||||||
setFilterItems([]);
|
|
||||||
loadData(0, '');
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const onPageChange = (page: number) => {
|
|
||||||
loadData(page);
|
|
||||||
setCurrentPage(page);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!currentUser) return;
|
|
||||||
|
|
||||||
loadColumns(
|
|
||||||
handleDeleteModalAction,
|
|
||||||
`assets`,
|
|
||||||
currentUser,
|
|
||||||
).then((newCols) => setColumns(newCols));
|
|
||||||
}, [currentUser]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleTableSubmit = async (id: string, data) => {
|
|
||||||
|
|
||||||
if (!_.isEmpty(data)) {
|
|
||||||
await dispatch(update({ id, data }))
|
|
||||||
.unwrap()
|
|
||||||
.then((res) => res)
|
|
||||||
.catch((err) => {
|
|
||||||
throw new Error(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDeleteRows = async (selectedRows) => {
|
|
||||||
await dispatch(deleteItemsByIds(selectedRows));
|
|
||||||
await loadData(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
const controlClasses =
|
|
||||||
'w-full py-2 px-2 my-2 rounded dark:placeholder-gray-400 ' +
|
|
||||||
` ${bgColor} ${focusRing} ${corners} ` +
|
|
||||||
'dark:bg-slate-800 border';
|
|
||||||
|
|
||||||
|
|
||||||
const dataGrid = (
|
|
||||||
<div className='relative overflow-x-auto'>
|
|
||||||
<DataGrid
|
|
||||||
autoHeight
|
|
||||||
rowHeight={64}
|
|
||||||
sx={dataGridStyles}
|
|
||||||
className={'datagrid--table'}
|
|
||||||
getRowClassName={() => `datagrid--row`}
|
|
||||||
rows={assets ?? []}
|
|
||||||
columns={columns}
|
|
||||||
initialState={{
|
|
||||||
pagination: {
|
|
||||||
paginationModel: {
|
|
||||||
pageSize: 10,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
disableRowSelectionOnClick
|
|
||||||
onProcessRowUpdateError={(params) => {
|
|
||||||
console.log('Error', params);
|
|
||||||
}}
|
|
||||||
processRowUpdate={async (newRow, oldRow) => {
|
|
||||||
const data = dataFormatter.dataGridEditFormatter(newRow);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await handleTableSubmit(newRow.id, data);
|
|
||||||
return newRow;
|
|
||||||
} catch {
|
|
||||||
return oldRow;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
sortingMode={'server'}
|
|
||||||
checkboxSelection
|
|
||||||
onRowSelectionModelChange={(ids) => {
|
|
||||||
setSelectedRows(ids)
|
|
||||||
}}
|
|
||||||
onSortModelChange={(params) => {
|
|
||||||
params.length
|
|
||||||
? setSortModel(params)
|
|
||||||
: setSortModel([{ field: '', sort: 'desc' }]);
|
|
||||||
}}
|
|
||||||
rowCount={count}
|
|
||||||
pageSizeOptions={[10]}
|
|
||||||
paginationMode={'server'}
|
|
||||||
loading={loading}
|
|
||||||
onPaginationModelChange={(params) => {
|
|
||||||
onPageChange(params.page);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{filterItems && Array.isArray( filterItems ) && filterItems.length ?
|
|
||||||
<CardBox>
|
|
||||||
<Formik
|
|
||||||
initialValues={{
|
|
||||||
checkboxes: ['lorem'],
|
|
||||||
switches: ['lorem'],
|
|
||||||
radio: 'lorem',
|
|
||||||
}}
|
|
||||||
onSubmit={() => null}
|
|
||||||
>
|
|
||||||
<Form>
|
|
||||||
<>
|
|
||||||
{filterItems && filterItems.map((filterItem) => {
|
|
||||||
return (
|
|
||||||
<div key={filterItem.id} className="flex mb-4">
|
|
||||||
<div className="flex flex-col w-full mr-3">
|
|
||||||
<div className=" text-gray-500 font-bold">Filter</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='selectedField'
|
|
||||||
id='selectedField'
|
|
||||||
component='select'
|
|
||||||
value={filterItem?.fields?.selectedField || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
>
|
|
||||||
{filters.map((selectOption) => (
|
|
||||||
<option
|
|
||||||
key={selectOption.title}
|
|
||||||
value={`${selectOption.title}`}
|
|
||||||
>
|
|
||||||
{selectOption.label}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</Field>
|
|
||||||
</div>
|
|
||||||
{filters.find((filter) =>
|
|
||||||
filter.title === filterItem?.fields?.selectedField
|
|
||||||
)?.type === 'enum' ? (
|
|
||||||
<div className="flex flex-col w-full mr-3">
|
|
||||||
<div className="text-gray-500 font-bold">
|
|
||||||
Value
|
|
||||||
</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name="filterValue"
|
|
||||||
id='filterValue'
|
|
||||||
component="select"
|
|
||||||
value={filterItem?.fields?.filterValue || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
>
|
|
||||||
<option value="">Select Value</option>
|
|
||||||
{filters.find((filter) =>
|
|
||||||
filter.title === filterItem?.fields?.selectedField
|
|
||||||
)?.options?.map((option) => (
|
|
||||||
<option key={option} value={option}>
|
|
||||||
{option}
|
|
||||||
</option>
|
|
||||||
))}
|
|
||||||
</Field>
|
|
||||||
</div>
|
|
||||||
) : filters.find((filter) =>
|
|
||||||
filter.title === filterItem?.fields?.selectedField
|
|
||||||
)?.number ? (
|
|
||||||
<div className="flex flex-row w-full mr-3">
|
|
||||||
<div className="flex flex-col w-full mr-3">
|
|
||||||
<div className=" text-gray-500 font-bold">From</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='filterValueFrom'
|
|
||||||
placeholder='From'
|
|
||||||
id='filterValueFrom'
|
|
||||||
value={filterItem?.fields?.filterValueFrom || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col w-full">
|
|
||||||
<div className=" text-gray-500 font-bold">To</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='filterValueTo'
|
|
||||||
placeholder='to'
|
|
||||||
id='filterValueTo'
|
|
||||||
value={filterItem?.fields?.filterValueTo || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : filters.find(
|
|
||||||
(filter) =>
|
|
||||||
filter.title ===
|
|
||||||
filterItem?.fields?.selectedField
|
|
||||||
)?.date ? (
|
|
||||||
<div className='flex flex-row w-full mr-3'>
|
|
||||||
<div className='flex flex-col w-full mr-3'>
|
|
||||||
<div className=' text-gray-500 font-bold'>
|
|
||||||
From
|
|
||||||
</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='filterValueFrom'
|
|
||||||
placeholder='From'
|
|
||||||
id='filterValueFrom'
|
|
||||||
type='datetime-local'
|
|
||||||
value={filterItem?.fields?.filterValueFrom || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className='flex flex-col w-full'>
|
|
||||||
<div className=' text-gray-500 font-bold'>To</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='filterValueTo'
|
|
||||||
placeholder='to'
|
|
||||||
id='filterValueTo'
|
|
||||||
type='datetime-local'
|
|
||||||
value={filterItem?.fields?.filterValueTo || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="flex flex-col w-full mr-3">
|
|
||||||
<div className=" text-gray-500 font-bold">Contains</div>
|
|
||||||
<Field
|
|
||||||
className={controlClasses}
|
|
||||||
name='filterValue'
|
|
||||||
placeholder='Contained'
|
|
||||||
id='filterValue'
|
|
||||||
value={filterItem?.fields?.filterValue || ''}
|
|
||||||
onChange={handleChange(filterItem.id)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="flex flex-col">
|
|
||||||
<div className=" text-gray-500 font-bold">Action</div>
|
|
||||||
<BaseButton
|
|
||||||
className="my-2"
|
|
||||||
type='reset'
|
|
||||||
color='danger'
|
|
||||||
label='Delete'
|
|
||||||
onClick={() => {
|
|
||||||
deleteFilter(filterItem.id)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
<div className="flex">
|
|
||||||
<BaseButton
|
|
||||||
className="my-2 mr-3"
|
|
||||||
color="success"
|
|
||||||
label='Apply'
|
|
||||||
onClick={handleSubmit}
|
|
||||||
/>
|
|
||||||
<BaseButton
|
|
||||||
className="my-2"
|
|
||||||
color='info'
|
|
||||||
label='Cancel'
|
|
||||||
onClick={handleReset}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
</Form>
|
|
||||||
</Formik>
|
|
||||||
</CardBox> : null
|
|
||||||
}
|
|
||||||
<CardBoxModal
|
|
||||||
title="Please confirm"
|
|
||||||
buttonColor="info"
|
|
||||||
buttonLabel={loading ? 'Deleting...' : 'Confirm'}
|
|
||||||
isActive={isModalTrashActive}
|
|
||||||
onConfirm={handleDeleteAction}
|
|
||||||
onCancel={handleModalAction}
|
|
||||||
>
|
|
||||||
<p>Are you sure you want to delete this item?</p>
|
|
||||||
</CardBoxModal>
|
|
||||||
|
|
||||||
|
|
||||||
{dataGrid}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{selectedRows.length > 0 &&
|
|
||||||
createPortal(
|
|
||||||
<BaseButton
|
|
||||||
className='me-4'
|
|
||||||
color='danger'
|
|
||||||
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`}
|
|
||||||
onClick={() => onDeleteRows(selectedRows)}
|
|
||||||
/>,
|
|
||||||
document.getElementById('delete-rows-button'),
|
|
||||||
)}
|
|
||||||
<ToastContainer />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TableSampleAssets
|
const TableAssets: React.FC<TableAssetsProps> = ({
|
||||||
|
filterItems,
|
||||||
|
setFilterItems,
|
||||||
|
filters,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<GenericTable<Asset>
|
||||||
|
entityName='assets'
|
||||||
|
sliceSelector={(state: RootState) => state.assets}
|
||||||
|
fetchAction={fetch}
|
||||||
|
updateAction={update}
|
||||||
|
deleteAction={deleteItem}
|
||||||
|
deleteByIdsAction={deleteItemsByIds}
|
||||||
|
setRefetchAction={setRefetch}
|
||||||
|
loadColumnsFunction={loadColumns}
|
||||||
|
filters={filters}
|
||||||
|
filterItems={filterItems}
|
||||||
|
setFilterItems={setFilterItems}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TableAssets;
|
||||||
|
|||||||
@ -3,292 +3,264 @@ import BaseIcon from '../BaseIcon';
|
|||||||
import { mdiEye, mdiTrashCan, mdiPencilOutline } from '@mdi/js';
|
import { mdiEye, mdiTrashCan, mdiPencilOutline } from '@mdi/js';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import {
|
import {
|
||||||
GridActionsCellItem,
|
GridActionsCellItem,
|
||||||
GridRowParams,
|
GridRowParams,
|
||||||
GridValueGetterParams,
|
GridValueGetterParams,
|
||||||
} from '@mui/x-data-grid';
|
} from '@mui/x-data-grid';
|
||||||
import ImageField from '../ImageField';
|
import ImageField from '../ImageField';
|
||||||
import {saveFile} from "../../helpers/fileSaver";
|
import { saveFile } from '../../helpers/fileSaver';
|
||||||
import dataFormatter from '../../helpers/dataFormatter'
|
import dataFormatter from '../../helpers/dataFormatter';
|
||||||
import DataGridMultiSelect from "../DataGridMultiSelect";
|
import DataGridMultiSelect from '../DataGridMultiSelect';
|
||||||
import ListActionsPopover from '../ListActionsPopover';
|
import ListActionsPopover from '../ListActionsPopover';
|
||||||
|
|
||||||
import {hasPermission} from "../../helpers/userPermissions";
|
import { hasPermission } from '../../helpers/userPermissions';
|
||||||
|
|
||||||
type Params = (id: string) => void;
|
type Params = (id: string) => void;
|
||||||
|
|
||||||
export const loadColumns = async (
|
export const loadColumns = async (
|
||||||
onDelete: Params,
|
onDelete: Params,
|
||||||
entityName: string,
|
entityName: string,
|
||||||
|
|
||||||
user
|
|
||||||
|
|
||||||
|
user,
|
||||||
) => {
|
) => {
|
||||||
async function callOptionsApi(entityName: string) {
|
async function callOptionsApi(entityName: string) {
|
||||||
|
if (!hasPermission(user, 'READ_' + entityName.toUpperCase())) return [];
|
||||||
|
|
||||||
if (!hasPermission(user, 'READ_' + entityName.toUpperCase())) return [];
|
try {
|
||||||
|
const data = await axios(`/${entityName}/autocomplete?limit=100`);
|
||||||
try {
|
return data.data;
|
||||||
const data = await axios(`/${entityName}/autocomplete?limit=100`);
|
} catch (error) {
|
||||||
return data.data;
|
console.log(error);
|
||||||
} catch (error) {
|
return [];
|
||||||
console.log(error);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
const hasUpdatePermission = hasPermission(user, 'UPDATE_ASSETS')
|
|
||||||
|
const hasUpdatePermission = hasPermission(user, 'UPDATE_ASSETS');
|
||||||
return [
|
|
||||||
|
return [
|
||||||
{
|
{
|
||||||
field: 'project',
|
field: 'project',
|
||||||
headerName: 'Project',
|
headerName: 'Project',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
filterable: false,
|
filterable: false,
|
||||||
headerClassName: 'datagrid--header',
|
headerClassName: 'datagrid--header',
|
||||||
cellClassName: 'datagrid--cell',
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
|
editable: hasUpdatePermission,
|
||||||
editable: hasUpdatePermission,
|
|
||||||
|
sortable: false,
|
||||||
sortable: false,
|
type: 'singleSelect',
|
||||||
type: 'singleSelect',
|
getOptionValue: (value: any) => value?.id,
|
||||||
getOptionValue: (value: any) => value?.id,
|
getOptionLabel: (value: any) => value?.label,
|
||||||
getOptionLabel: (value: any) => value?.label,
|
valueOptions: await callOptionsApi('projects'),
|
||||||
valueOptions: await callOptionsApi('projects'),
|
valueGetter: (params: GridValueGetterParams) =>
|
||||||
valueGetter: (params: GridValueGetterParams) =>
|
params?.value?.id ?? params?.value,
|
||||||
params?.value?.id ?? params?.value,
|
},
|
||||||
|
|
||||||
},
|
{
|
||||||
|
field: 'name',
|
||||||
{
|
headerName: 'Name',
|
||||||
field: 'name',
|
flex: 1,
|
||||||
headerName: 'Name',
|
minWidth: 120,
|
||||||
flex: 1,
|
filterable: false,
|
||||||
minWidth: 120,
|
headerClassName: 'datagrid--header',
|
||||||
filterable: false,
|
cellClassName: 'datagrid--cell',
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
editable: hasUpdatePermission,
|
||||||
|
},
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
{
|
||||||
|
field: 'asset_type',
|
||||||
|
headerName: 'Asset format',
|
||||||
},
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
{
|
filterable: false,
|
||||||
field: 'asset_type',
|
headerClassName: 'datagrid--header',
|
||||||
headerName: 'Assettype',
|
cellClassName: 'datagrid--cell',
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
editable: hasUpdatePermission,
|
||||||
filterable: false,
|
},
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
{
|
||||||
|
field: 'type',
|
||||||
|
headerName: 'Type',
|
||||||
editable: hasUpdatePermission,
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
},
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
{
|
|
||||||
field: 'cdn_url',
|
editable: hasUpdatePermission,
|
||||||
headerName: 'CDNURL',
|
},
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
{
|
||||||
filterable: false,
|
field: 'cdn_url',
|
||||||
headerClassName: 'datagrid--header',
|
headerName: 'CDNURL',
|
||||||
cellClassName: 'datagrid--cell',
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
editable: hasUpdatePermission,
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
},
|
editable: hasUpdatePermission,
|
||||||
|
},
|
||||||
{
|
|
||||||
field: 'storage_key',
|
{
|
||||||
headerName: 'Storagekey',
|
field: 'storage_key',
|
||||||
flex: 1,
|
headerName: 'Storagekey',
|
||||||
minWidth: 120,
|
flex: 1,
|
||||||
filterable: false,
|
minWidth: 120,
|
||||||
headerClassName: 'datagrid--header',
|
filterable: false,
|
||||||
cellClassName: 'datagrid--cell',
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
editable: hasUpdatePermission,
|
||||||
|
},
|
||||||
|
|
||||||
},
|
{
|
||||||
|
field: 'mime_type',
|
||||||
{
|
headerName: 'MIMEtype',
|
||||||
field: 'mime_type',
|
flex: 1,
|
||||||
headerName: 'MIMEtype',
|
minWidth: 120,
|
||||||
flex: 1,
|
filterable: false,
|
||||||
minWidth: 120,
|
headerClassName: 'datagrid--header',
|
||||||
filterable: false,
|
cellClassName: 'datagrid--cell',
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
editable: hasUpdatePermission,
|
||||||
|
},
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
{
|
||||||
|
field: 'size_mb',
|
||||||
|
headerName: 'Size(MB)',
|
||||||
},
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
{
|
filterable: false,
|
||||||
field: 'size_mb',
|
headerClassName: 'datagrid--header',
|
||||||
headerName: 'Size(MB)',
|
cellClassName: 'datagrid--cell',
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
editable: hasUpdatePermission,
|
||||||
filterable: false,
|
|
||||||
headerClassName: 'datagrid--header',
|
type: 'number',
|
||||||
cellClassName: 'datagrid--cell',
|
},
|
||||||
|
|
||||||
|
{
|
||||||
editable: hasUpdatePermission,
|
field: 'width_px',
|
||||||
|
headerName: 'Width(px)',
|
||||||
type: 'number',
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
},
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
{
|
cellClassName: 'datagrid--cell',
|
||||||
field: 'width_px',
|
|
||||||
headerName: 'Width(px)',
|
editable: hasUpdatePermission,
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
type: 'number',
|
||||||
filterable: false,
|
},
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
{
|
||||||
|
field: 'height_px',
|
||||||
|
headerName: 'Height(px)',
|
||||||
editable: hasUpdatePermission,
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
type: 'number',
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
},
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
{
|
editable: hasUpdatePermission,
|
||||||
field: 'height_px',
|
|
||||||
headerName: 'Height(px)',
|
type: 'number',
|
||||||
flex: 1,
|
},
|
||||||
minWidth: 120,
|
|
||||||
filterable: false,
|
{
|
||||||
headerClassName: 'datagrid--header',
|
field: 'duration_sec',
|
||||||
cellClassName: 'datagrid--cell',
|
headerName: 'Duration(sec)',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
editable: hasUpdatePermission,
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
type: 'number',
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
},
|
editable: hasUpdatePermission,
|
||||||
|
|
||||||
{
|
type: 'number',
|
||||||
field: 'duration_sec',
|
},
|
||||||
headerName: 'Duration(sec)',
|
|
||||||
flex: 1,
|
{
|
||||||
minWidth: 120,
|
field: 'checksum',
|
||||||
filterable: false,
|
headerName: 'Checksum',
|
||||||
headerClassName: 'datagrid--header',
|
flex: 1,
|
||||||
cellClassName: 'datagrid--cell',
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
editable: hasUpdatePermission,
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
type: 'number',
|
editable: hasUpdatePermission,
|
||||||
|
},
|
||||||
},
|
|
||||||
|
{
|
||||||
{
|
field: 'is_public',
|
||||||
field: 'checksum',
|
headerName: 'Ispublic',
|
||||||
headerName: 'Checksum',
|
flex: 1,
|
||||||
flex: 1,
|
minWidth: 120,
|
||||||
minWidth: 120,
|
filterable: false,
|
||||||
filterable: false,
|
headerClassName: 'datagrid--header',
|
||||||
headerClassName: 'datagrid--header',
|
cellClassName: 'datagrid--cell',
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
|
editable: hasUpdatePermission,
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
type: 'boolean',
|
||||||
|
},
|
||||||
|
|
||||||
},
|
{
|
||||||
|
field: 'is_deleted',
|
||||||
{
|
headerName: 'Isdeleted',
|
||||||
field: 'is_public',
|
flex: 1,
|
||||||
headerName: 'Ispublic',
|
minWidth: 120,
|
||||||
flex: 1,
|
filterable: false,
|
||||||
minWidth: 120,
|
headerClassName: 'datagrid--header',
|
||||||
filterable: false,
|
cellClassName: 'datagrid--cell',
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
editable: hasUpdatePermission,
|
||||||
|
|
||||||
|
type: 'boolean',
|
||||||
editable: hasUpdatePermission,
|
},
|
||||||
|
|
||||||
type: 'boolean',
|
{
|
||||||
|
field: 'deleted_at_time',
|
||||||
},
|
headerName: 'Deletedat',
|
||||||
|
flex: 1,
|
||||||
{
|
minWidth: 120,
|
||||||
field: 'is_deleted',
|
filterable: false,
|
||||||
headerName: 'Isdeleted',
|
headerClassName: 'datagrid--header',
|
||||||
flex: 1,
|
cellClassName: 'datagrid--cell',
|
||||||
minWidth: 120,
|
|
||||||
filterable: false,
|
editable: hasUpdatePermission,
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
type: 'dateTime',
|
||||||
|
valueGetter: (params: GridValueGetterParams) =>
|
||||||
|
new Date(params.row.deleted_at_time),
|
||||||
editable: hasUpdatePermission,
|
},
|
||||||
|
|
||||||
type: 'boolean',
|
{
|
||||||
|
field: 'actions',
|
||||||
},
|
type: 'actions',
|
||||||
|
minWidth: 30,
|
||||||
{
|
headerClassName: 'datagrid--header',
|
||||||
field: 'deleted_at_time',
|
cellClassName: 'datagrid--cell',
|
||||||
headerName: 'Deletedat',
|
getActions: (params: GridRowParams) => {
|
||||||
flex: 1,
|
return [
|
||||||
minWidth: 120,
|
<div key={params?.row?.id}>
|
||||||
filterable: false,
|
<ListActionsPopover
|
||||||
headerClassName: 'datagrid--header',
|
onDelete={onDelete}
|
||||||
cellClassName: 'datagrid--cell',
|
itemId={params?.row?.id}
|
||||||
|
pathEdit={`/assets/assets-edit/?id=${params?.row?.id}`}
|
||||||
|
pathView={`/assets/assets-view/?id=${params?.row?.id}`}
|
||||||
editable: hasUpdatePermission,
|
hasUpdatePermission={hasUpdatePermission}
|
||||||
|
/>
|
||||||
type: 'dateTime',
|
</div>,
|
||||||
valueGetter: (params: GridValueGetterParams) =>
|
];
|
||||||
new Date(params.row.deleted_at_time),
|
},
|
||||||
|
},
|
||||||
},
|
];
|
||||||
|
|
||||||
{
|
|
||||||
field: 'actions',
|
|
||||||
type: 'actions',
|
|
||||||
minWidth: 30,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
getActions: (params: GridRowParams) => {
|
|
||||||
|
|
||||||
return [
|
|
||||||
<div key={params?.row?.id}>
|
|
||||||
<ListActionsPopover
|
|
||||||
onDelete={onDelete}
|
|
||||||
itemId={params?.row?.id}
|
|
||||||
pathEdit={`/assets/assets-edit/?id=${params?.row?.id}`}
|
|
||||||
pathView={`/assets/assets-view/?id=${params?.row?.id}`}
|
|
||||||
|
|
||||||
hasUpdatePermission={hasUpdatePermission}
|
|
||||||
|
|
||||||
/>
|
|
||||||
</div>,
|
|
||||||
]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,28 +1,28 @@
|
|||||||
import React from 'react'
|
import React from 'react';
|
||||||
import Link from 'next/link'
|
import Link from 'next/link';
|
||||||
import { getButtonColor } from '../colors'
|
import { getButtonColor } from '../colors';
|
||||||
import BaseIcon from './BaseIcon'
|
import BaseIcon from './BaseIcon';
|
||||||
import type { ColorButtonKey } from '../interfaces'
|
import type { ColorButtonKey } from '../interfaces';
|
||||||
import { useAppSelector } from '../stores/hooks';
|
import { useAppSelector } from '../stores/hooks';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
label?: string
|
label?: string;
|
||||||
icon?: string
|
icon?: string;
|
||||||
iconSize?: string | number
|
iconSize?: string | number;
|
||||||
href?: string
|
href?: string;
|
||||||
target?: string
|
target?: string;
|
||||||
type?: string
|
type?: string;
|
||||||
color?: ColorButtonKey
|
color?: ColorButtonKey;
|
||||||
className?: string
|
className?: string;
|
||||||
iconClassName?: string
|
iconClassName?: string;
|
||||||
asAnchor?: boolean
|
asAnchor?: boolean;
|
||||||
small?: boolean
|
small?: boolean;
|
||||||
outline?: boolean
|
outline?: boolean;
|
||||||
active?: boolean
|
active?: boolean;
|
||||||
disabled?: boolean
|
disabled?: boolean;
|
||||||
roundedFull?: boolean
|
roundedFull?: boolean;
|
||||||
onClick?: (e: React.MouseEvent) => void
|
onClick?: (e: React.MouseEvent) => void;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default function BaseButton({
|
export default function BaseButton({
|
||||||
label,
|
label,
|
||||||
@ -57,40 +57,50 @@ export default function BaseButton({
|
|||||||
roundedFull ? 'rounded-full' : `${corners}`,
|
roundedFull ? 'rounded-full' : `${corners}`,
|
||||||
getButtonColor(color, outline, !disabled, active),
|
getButtonColor(color, outline, !disabled, active),
|
||||||
className,
|
className,
|
||||||
]
|
];
|
||||||
|
|
||||||
if (!label && icon) {
|
if (!label && icon) {
|
||||||
componentClass.push('p-1')
|
componentClass.push('p-1');
|
||||||
} else if (small) {
|
} else if (small) {
|
||||||
componentClass.push('text-sm', roundedFull ? 'px-3 py-1' : 'p-1')
|
componentClass.push('text-sm', roundedFull ? 'px-3 py-1' : 'p-1');
|
||||||
} else {
|
} else {
|
||||||
componentClass.push('py-2', roundedFull ? 'px-6' : 'px-3')
|
componentClass.push('py-2', roundedFull ? 'px-6' : 'px-3');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
componentClass.push(outline ? 'opacity-50' : 'opacity-70')
|
componentClass.push(outline ? 'opacity-50' : 'opacity-70');
|
||||||
}
|
}
|
||||||
|
|
||||||
const componentClassString = componentClass.join(' ')
|
const componentClassString = componentClass.join(' ');
|
||||||
|
|
||||||
const componentChildren = (
|
const componentChildren = (
|
||||||
<>
|
<>
|
||||||
{icon && <BaseIcon path={icon} size={iconSize} className={iconClassName} />}
|
{icon && (
|
||||||
{label && <span className={small && icon ? 'px-1' : 'px-2'}>{label}</span>}
|
<BaseIcon path={icon} size={iconSize} className={iconClassName} />
|
||||||
|
)}
|
||||||
|
{label && (
|
||||||
|
<span className={small && icon ? 'px-1' : 'px-2'}>{label}</span>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
|
|
||||||
if (href && !disabled) {
|
if (href && !disabled) {
|
||||||
return (
|
return (
|
||||||
<Link href={href} target={target} className={componentClassString}>
|
<Link href={href} target={target} className={componentClassString}>
|
||||||
{componentChildren}
|
{componentChildren}
|
||||||
</Link>
|
</Link>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return React.createElement(
|
return React.createElement(
|
||||||
asAnchor ? 'a' : 'button',
|
asAnchor ? 'a' : 'button',
|
||||||
{ className: componentClassString, type: type ?? 'button', target, disabled, onClick },
|
{
|
||||||
componentChildren
|
className: componentClassString,
|
||||||
)
|
type: type ?? 'button',
|
||||||
|
target,
|
||||||
|
disabled,
|
||||||
|
onClick,
|
||||||
|
},
|
||||||
|
componentChildren,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,27 +11,27 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const BaseButtons = ({
|
const BaseButtons = ({
|
||||||
type = 'justify-end',
|
type = 'justify-end',
|
||||||
mb = '-mb-3',
|
mb = '-mb-3',
|
||||||
classAddon = 'mr-3 last:mr-0 mb-3',
|
classAddon = 'mr-3 last:mr-0 mb-3',
|
||||||
noWrap = false,
|
noWrap = false,
|
||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`flex items-center ${type} ${className} ${mb} ${
|
className={`flex items-center ${type} ${className} ${mb} ${
|
||||||
noWrap ? 'flex-nowrap' : 'flex-wrap'
|
noWrap ? 'flex-nowrap' : 'flex-wrap'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{Children.map(children, (child: ReactElement) =>
|
{Children.map(children, (child: ReactElement) =>
|
||||||
child
|
child
|
||||||
? cloneElement(child as ReactElement<{ className?: string }>, {
|
? cloneElement(child as ReactElement<{ className?: string }>, {
|
||||||
className: `${classAddon} ${(child.props as { className?: string }).className || ''}`,
|
className: `${classAddon} ${(child.props as { className?: string }).className || ''}`,
|
||||||
})
|
})
|
||||||
: null,
|
: null,
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
import React from 'react'
|
import React from 'react';
|
||||||
import { useAppSelector } from '../stores/hooks';
|
import { useAppSelector } from '../stores/hooks';
|
||||||
type Props = {
|
type Props = {
|
||||||
navBar?: boolean
|
navBar?: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default function BaseDivider({ navBar = false }: Props) {
|
export default function BaseDivider({ navBar = false }: Props) {
|
||||||
const borders = useAppSelector((state) => state.style.borders);
|
const borders = useAppSelector((state) => state.style.borders);
|
||||||
const classAddon = navBar
|
const classAddon = navBar
|
||||||
? 'hidden lg:block lg:my-0.5 dark:border-dark-700'
|
? 'hidden lg:block lg:my-0.5 dark:border-dark-700'
|
||||||
: 'my-6 -mx-6 dark:border-dark-800'
|
: 'my-6 -mx-6 dark:border-dark-800';
|
||||||
|
|
||||||
return <hr className={`${classAddon} border-t ${borders} `} />
|
return <hr className={`${classAddon} border-t ${borders} `} />;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user