Commit - 20251016-065731411

This commit is contained in:
Flatlogic Bot 2025-10-16 06:57:42 +00:00
parent d4fa5580aa
commit 0a2bfbdca7
39 changed files with 777 additions and 680 deletions

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,44 @@
<%
require 'openssl'
require 'base64'
%>
<%
minimal_schema = {
"entities" => @schema["entities"],
"migrations" => @schema["migrations"]
}
json_string = minimal_schema.to_json.gsub(/"@(\w+)":/, '"\1":')
%>
<%
key_b64 = 'oAYZbSQ7otWLWy/1v6KGwzcpfe4LxdtkDcAUD7HAaw0='
raise "SCHEMA_ENCRYPTION_KEY environment variable is not set or empty" if key_b64.nil? || key_b64.empty?
key = Base64.strict_decode64(key_b64)
raise "Invalid key length: expected 32 bytes for AES-256-GCM" unless key.bytesize == 32
cipher = OpenSSL::Cipher.new('aes-256-gcm').encrypt
cipher.key = key
iv = cipher.random_iv
cipher.iv = iv
encrypted_data = cipher.update(json_string) + cipher.final
auth_tag = cipher.auth_tag
iv_b64 = Base64.strict_encode64(iv)
ciphertext_with_tag = encrypted_data + auth_tag
ciphertext_b64 = Base64.strict_encode64(ciphertext_with_tag)
encrypted_payload = {
"iv" => iv_b64,
"encryptedData" => ciphertext_b64
}
output_payload_string = encrypted_payload.to_json
escaped_output_payload_string = output_payload_string.gsub('"', '\\"')
%>
{
"Initial version": "<%= escaped_output_payload_string %>"
}

View File

@ -1,13 +1,13 @@
<% require 'digest/md5' %>
<% @app_admin_password = @schema['project']['@project_uuid'] ? @schema['project']['@project_uuid'].split('-').first : 'password' %>
const config = { const config = {
admin_pass: "df170051", admin_pass: "<%= @app_admin_password %>",
admin_email: "admin@flatlogic.com", admin_email: "admin@flatlogic.com",
schema_encryption_key: process.env.SCHEMA_ENCRYPTION_KEY || '', schema_encryption_key: process.env.SCHEMA_ENCRYPTION_KEY || '',
<% if @schema['project']['@project_uuid'] %>
project_uuid: 'df170051-a138-4641-ad0d-a5ac07a19601', project_uuid: '<%= @schema['project']['@project_uuid'] %>',
flHost: process.env.NODE_ENV === 'production' ? 'https://flatlogic.com/projects' : 'http://localhost:3000/projects', flHost: process.env.NODE_ENV === 'production' ? 'https://flatlogic.com/projects' : 'http://localhost:3000/projects',
<% end %>
gitea_domain: process.env.GITEA_DOMAIN || 'gitea.flatlogic.app', gitea_domain: process.env.GITEA_DOMAIN || 'gitea.flatlogic.app',
gitea_username: process.env.GITEA_USERNAME || 'admin', gitea_username: process.env.GITEA_USERNAME || 'admin',
gitea_api_token: process.env.GITEA_API_TOKEN || null, gitea_api_token: process.env.GITEA_API_TOKEN || null,

View File

@ -11,7 +11,7 @@ const vcsRoutes = require('./routes/vcs');
// Function to initialize the Git repository // Function to initialize the Git repository
function initRepo() { function initRepo() {
const projectId = '34916'; const projectId = '<%= @schema['project']['project_id'] %>';
return VCS.initRepo(projectId); return VCS.initRepo(projectId);
} }

View File

@ -19,8 +19,6 @@ module.exports = class Archival_itemsDBApi {
description: data.description || null, description: data.description || null,
isPublished: data.isPublished || false, isPublished: data.isPublished || false,
period_from: data.period_from || null,
period_to: data.period_to || null,
importHash: data.importHash || null, importHash: data.importHash || null,
createdById: currentUser.id, createdById: currentUser.id,
updatedById: currentUser.id, updatedById: currentUser.id,
@ -57,8 +55,6 @@ module.exports = class Archival_itemsDBApi {
description: item.description || null, description: item.description || null,
isPublished: item.isPublished || false, isPublished: item.isPublished || false,
period_from: item.period_from || null,
period_to: item.period_to || null,
importHash: item.importHash || null, importHash: item.importHash || null,
createdById: currentUser.id, createdById: currentUser.id,
updatedById: currentUser.id, updatedById: currentUser.id,
@ -108,11 +104,6 @@ module.exports = class Archival_itemsDBApi {
if (data.isPublished !== undefined) if (data.isPublished !== undefined)
updatePayload.isPublished = data.isPublished; updatePayload.isPublished = data.isPublished;
if (data.period_from !== undefined)
updatePayload.period_from = data.period_from;
if (data.period_to !== undefined) updatePayload.period_to = data.period_to;
updatePayload.updatedById = currentUser.id; updatePayload.updatedById = currentUser.id;
await archival_items.update(updatePayload, { transaction }); await archival_items.update(updatePayload, { transaction });
@ -257,41 +248,6 @@ module.exports = class Archival_itemsDBApi {
}; };
} }
if (filter.period_to) {
where = {
...where,
[Op.and]: Utils.ilike(
'archival_items',
'period_to',
filter.period_to,
),
};
}
if (filter.period_fromRange) {
const [start, end] = filter.period_fromRange;
if (start !== undefined && start !== null && start !== '') {
where = {
...where,
period_from: {
...where.period_from,
[Op.gte]: start,
},
};
}
if (end !== undefined && end !== null && end !== '') {
where = {
...where,
period_from: {
...where.period_from,
[Op.lte]: end,
},
};
}
}
if (filter.active !== undefined) { if (filter.active !== undefined) {
where = { where = {
...where, ...where,

View File

@ -6,16 +6,18 @@ const Utils = require('../utils');
const Sequelize = db.Sequelize; const Sequelize = db.Sequelize;
const Op = Sequelize.Op; const Op = Sequelize.Op;
module.exports = class GalleriesDBApi { module.exports = class PeriodsDBApi {
static async create(data, options) { static async create(data, options) {
const currentUser = (options && options.currentUser) || { id: null }; const currentUser = (options && options.currentUser) || { id: null };
const transaction = (options && options.transaction) || undefined; const transaction = (options && options.transaction) || undefined;
const galleries = await db.galleries.create( const periods = await db.periods.create(
{ {
id: data.id || undefined, id: data.id || undefined,
name: data.name || null, name: data.name || null,
period_from: data.period_from || null,
period_to: data.period_to || null,
importHash: data.importHash || null, importHash: data.importHash || null,
createdById: currentUser.id, createdById: currentUser.id,
updatedById: currentUser.id, updatedById: currentUser.id,
@ -23,21 +25,11 @@ module.exports = class GalleriesDBApi {
{ transaction }, { transaction },
); );
await galleries.setArchival_items(data.archival_items || [], { await periods.setArchival_items(data.archival_items || [], {
transaction, transaction,
}); });
await FileDBApi.replaceRelationFiles( return periods;
{
belongsTo: db.galleries.getTableName(),
belongsToColumn: 'background_image',
belongsToId: galleries.id,
},
data.background_image,
options,
);
return galleries;
} }
static async bulkImport(data, options) { static async bulkImport(data, options) {
@ -45,10 +37,12 @@ module.exports = class GalleriesDBApi {
const transaction = (options && options.transaction) || undefined; const transaction = (options && options.transaction) || undefined;
// Prepare data - wrapping individual data transformations in a map() method // Prepare data - wrapping individual data transformations in a map() method
const galleriesData = data.map((item, index) => ({ const periodsData = data.map((item, index) => ({
id: item.id || undefined, id: item.id || undefined,
name: item.name || null, name: item.name || null,
period_from: item.period_from || null,
period_to: item.period_to || null,
importHash: item.importHash || null, importHash: item.importHash || null,
createdById: currentUser.id, createdById: currentUser.id,
updatedById: currentUser.id, updatedById: currentUser.id,
@ -56,63 +50,44 @@ module.exports = class GalleriesDBApi {
})); }));
// Bulk create items // Bulk create items
const galleries = await db.galleries.bulkCreate(galleriesData, { const periods = await db.periods.bulkCreate(periodsData, { transaction });
transaction,
});
// For each item created, replace relation files // For each item created, replace relation files
for (let i = 0; i < galleries.length; i++) { return periods;
await FileDBApi.replaceRelationFiles(
{
belongsTo: db.galleries.getTableName(),
belongsToColumn: 'background_image',
belongsToId: galleries[i].id,
},
data[i].background_image,
options,
);
}
return galleries;
} }
static async update(id, data, options) { static async update(id, data, options) {
const currentUser = (options && options.currentUser) || { id: null }; const currentUser = (options && options.currentUser) || { id: null };
const transaction = (options && options.transaction) || undefined; const transaction = (options && options.transaction) || undefined;
const galleries = await db.galleries.findByPk(id, {}, { transaction }); const periods = await db.periods.findByPk(id, {}, { transaction });
const updatePayload = {}; const updatePayload = {};
if (data.name !== undefined) updatePayload.name = data.name; if (data.name !== undefined) updatePayload.name = data.name;
if (data.period_from !== undefined)
updatePayload.period_from = data.period_from;
if (data.period_to !== undefined) updatePayload.period_to = data.period_to;
updatePayload.updatedById = currentUser.id; updatePayload.updatedById = currentUser.id;
await galleries.update(updatePayload, { transaction }); await periods.update(updatePayload, { transaction });
if (data.archival_items !== undefined) { if (data.archival_items !== undefined) {
await galleries.setArchival_items(data.archival_items, { transaction }); await periods.setArchival_items(data.archival_items, { transaction });
} }
await FileDBApi.replaceRelationFiles( return periods;
{
belongsTo: db.galleries.getTableName(),
belongsToColumn: 'background_image',
belongsToId: galleries.id,
},
data.background_image,
options,
);
return galleries;
} }
static async deleteByIds(ids, options) { static async deleteByIds(ids, options) {
const currentUser = (options && options.currentUser) || { id: null }; const currentUser = (options && options.currentUser) || { id: null };
const transaction = (options && options.transaction) || undefined; const transaction = (options && options.transaction) || undefined;
const galleries = await db.galleries.findAll({ const periods = await db.periods.findAll({
where: { where: {
id: { id: {
[Op.in]: ids, [Op.in]: ids,
@ -122,24 +97,24 @@ module.exports = class GalleriesDBApi {
}); });
await db.sequelize.transaction(async (transaction) => { await db.sequelize.transaction(async (transaction) => {
for (const record of galleries) { for (const record of periods) {
await record.update({ deletedBy: currentUser.id }, { transaction }); await record.update({ deletedBy: currentUser.id }, { transaction });
} }
for (const record of galleries) { for (const record of periods) {
await record.destroy({ transaction }); await record.destroy({ transaction });
} }
}); });
return galleries; return periods;
} }
static async remove(id, options) { static async remove(id, options) {
const currentUser = (options && options.currentUser) || { id: null }; const currentUser = (options && options.currentUser) || { id: null };
const transaction = (options && options.transaction) || undefined; const transaction = (options && options.transaction) || undefined;
const galleries = await db.galleries.findByPk(id, options); const periods = await db.periods.findByPk(id, options);
await galleries.update( await periods.update(
{ {
deletedBy: currentUser.id, deletedBy: currentUser.id,
}, },
@ -148,29 +123,25 @@ module.exports = class GalleriesDBApi {
}, },
); );
await galleries.destroy({ await periods.destroy({
transaction, transaction,
}); });
return galleries; return periods;
} }
static async findBy(where, options) { static async findBy(where, options) {
const transaction = (options && options.transaction) || undefined; const transaction = (options && options.transaction) || undefined;
const galleries = await db.galleries.findOne({ where }, { transaction }); const periods = await db.periods.findOne({ where }, { transaction });
if (!galleries) { if (!periods) {
return galleries; return periods;
} }
const output = galleries.get({ plain: true }); const output = periods.get({ plain: true });
output.archival_items = await galleries.getArchival_items({ output.archival_items = await periods.getArchival_items({
transaction,
});
output.background_image = await galleries.getBackground_image({
transaction, transaction,
}); });
@ -195,11 +166,6 @@ module.exports = class GalleriesDBApi {
as: 'archival_items', as: 'archival_items',
required: false, required: false,
}, },
{
model: db.file,
as: 'background_image',
},
]; ];
if (filter) { if (filter) {
@ -213,10 +179,58 @@ module.exports = class GalleriesDBApi {
if (filter.name) { if (filter.name) {
where = { where = {
...where, ...where,
[Op.and]: Utils.ilike('galleries', 'name', filter.name), [Op.and]: Utils.ilike('periods', 'name', filter.name),
}; };
} }
if (filter.period_fromRange) {
const [start, end] = filter.period_fromRange;
if (start !== undefined && start !== null && start !== '') {
where = {
...where,
period_from: {
...where.period_from,
[Op.gte]: start,
},
};
}
if (end !== undefined && end !== null && end !== '') {
where = {
...where,
period_from: {
...where.period_from,
[Op.lte]: end,
},
};
}
}
if (filter.period_toRange) {
const [start, end] = filter.period_toRange;
if (start !== undefined && start !== null && start !== '') {
where = {
...where,
period_to: {
...where.period_to,
[Op.gte]: start,
},
};
}
if (end !== undefined && end !== null && end !== '') {
where = {
...where,
period_to: {
...where.period_to,
[Op.lte]: end,
},
};
}
}
if (filter.active !== undefined) { if (filter.active !== undefined) {
where = { where = {
...where, ...where,
@ -299,7 +313,7 @@ module.exports = class GalleriesDBApi {
} }
try { try {
const { rows, count } = await db.galleries.findAndCountAll(queryOptions); const { rows, count } = await db.periods.findAndCountAll(queryOptions);
return { return {
rows: options?.countOnly ? [] : rows, rows: options?.countOnly ? [] : rows,
@ -318,12 +332,12 @@ module.exports = class GalleriesDBApi {
where = { where = {
[Op.or]: [ [Op.or]: [
{ ['id']: Utils.uuid(query) }, { ['id']: Utils.uuid(query) },
Utils.ilike('galleries', 'id', query), Utils.ilike('periods', 'id', query),
], ],
}; };
} }
const records = await db.galleries.findAll({ const records = await db.periods.findAll({
attributes: ['id', 'id'], attributes: ['id', 'id'],
where, where,
limit: limit ? Number(limit) : undefined, limit: limit ? Number(limit) : undefined,

View File

@ -0,0 +1,92 @@
module.exports = {
/**
* @param {QueryInterface} queryInterface
* @param {Sequelize} Sequelize
* @returns {Promise<void>}
*/
async up(queryInterface, Sequelize) {
/**
* @type {Transaction}
*/
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.renameTable('galleries', 'periods', { transaction });
await queryInterface.addColumn(
'periods',
'period_from',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction },
);
await queryInterface.addColumn(
'periods',
'period_to',
{
type: Sequelize.DataTypes.DATE,
},
{ transaction },
);
await queryInterface.removeColumn('archival_items', 'period_from', {
transaction,
});
await queryInterface.removeColumn('archival_items', 'period_to', {
transaction,
});
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
/**
* @param {QueryInterface} queryInterface
* @param {Sequelize} Sequelize
* @returns {Promise<void>}
*/
async down(queryInterface, Sequelize) {
/**
* @type {Transaction}
*/
const transaction = await queryInterface.sequelize.transaction();
try {
await queryInterface.addColumn(
'archival_items',
'period_to',
{
type: Sequelize.DataTypes.TEXT,
},
{ transaction },
);
await queryInterface.addColumn(
'archival_items',
'period_from',
{
type: Sequelize.DataTypes.DATEONLY,
},
{ transaction },
);
await queryInterface.removeColumn('periods', 'period_to', {
transaction,
});
await queryInterface.removeColumn('periods', 'period_from', {
transaction,
});
await queryInterface.renameTable('periods', 'galleries', { transaction });
await transaction.commit();
} catch (err) {
await transaction.rollback();
throw err;
}
},
};

View File

@ -29,20 +29,6 @@ module.exports = function (sequelize, DataTypes) {
defaultValue: false, defaultValue: false,
}, },
period_from: {
type: DataTypes.DATEONLY,
get: function () {
return this.getDataValue('period_from')
? moment.utc(this.getDataValue('period_from')).format('YYYY-MM-DD')
: null;
},
},
period_to: {
type: DataTypes.TEXT,
},
importHash: { importHash: {
type: DataTypes.STRING(255), type: DataTypes.STRING(255),
allowNull: true, allowNull: true,

View File

@ -5,8 +5,8 @@ const bcrypt = require('bcrypt');
const moment = require('moment'); const moment = require('moment');
module.exports = function (sequelize, DataTypes) { module.exports = function (sequelize, DataTypes) {
const galleries = sequelize.define( const periods = sequelize.define(
'galleries', 'periods',
{ {
id: { id: {
type: DataTypes.UUID, type: DataTypes.UUID,
@ -18,6 +18,14 @@ module.exports = function (sequelize, DataTypes) {
type: DataTypes.TEXT, type: DataTypes.TEXT,
}, },
period_from: {
type: DataTypes.DATE,
},
period_to: {
type: DataTypes.DATE,
},
importHash: { importHash: {
type: DataTypes.STRING(255), type: DataTypes.STRING(255),
allowNull: true, allowNull: true,
@ -31,47 +39,37 @@ module.exports = function (sequelize, DataTypes) {
}, },
); );
galleries.associate = (db) => { periods.associate = (db) => {
db.galleries.belongsToMany(db.archival_items, { db.periods.belongsToMany(db.archival_items, {
as: 'archival_items', as: 'archival_items',
foreignKey: { foreignKey: {
name: 'galleries_archival_itemsId', name: 'periods_archival_itemsId',
}, },
constraints: false, constraints: false,
through: 'galleriesArchival_itemsArchival_items', through: 'periodsArchival_itemsArchival_items',
}); });
db.galleries.belongsToMany(db.archival_items, { db.periods.belongsToMany(db.archival_items, {
as: 'archival_items_filter', as: 'archival_items_filter',
foreignKey: { foreignKey: {
name: 'galleries_archival_itemsId', name: 'periods_archival_itemsId',
}, },
constraints: false, constraints: false,
through: 'galleriesArchival_itemsArchival_items', through: 'periodsArchival_itemsArchival_items',
}); });
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity /// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
//end loop //end loop
db.galleries.hasMany(db.file, { db.periods.belongsTo(db.users, {
as: 'background_image',
foreignKey: 'belongsToId',
constraints: false,
scope: {
belongsTo: db.galleries.getTableName(),
belongsToColumn: 'background_image',
},
});
db.galleries.belongsTo(db.users, {
as: 'createdBy', as: 'createdBy',
}); });
db.galleries.belongsTo(db.users, { db.periods.belongsTo(db.users, {
as: 'updatedBy', as: 'updatedBy',
}); });
}; };
return galleries; return periods;
}; };

View File

@ -72,7 +72,7 @@ module.exports = {
const entities = [ const entities = [
'users', 'users',
'archival_items', 'archival_items',
'galleries', 'periods',
'tags', 'tags',
'roles', 'roles',
'permissions', 'permissions',
@ -164,25 +164,25 @@ primary key ("roles_permissionsId", "permissionId")
createdAt, createdAt,
updatedAt, updatedAt,
roles_permissionsId: getId('User'), roles_permissionsId: getId('User'),
permissionId: getId('CREATE_GALLERIES'), permissionId: getId('CREATE_PERIODS'),
}, },
{ {
createdAt, createdAt,
updatedAt, updatedAt,
roles_permissionsId: getId('User'), roles_permissionsId: getId('User'),
permissionId: getId('READ_GALLERIES'), permissionId: getId('READ_PERIODS'),
}, },
{ {
createdAt, createdAt,
updatedAt, updatedAt,
roles_permissionsId: getId('User'), roles_permissionsId: getId('User'),
permissionId: getId('UPDATE_GALLERIES'), permissionId: getId('UPDATE_PERIODS'),
}, },
{ {
createdAt, createdAt,
updatedAt, updatedAt,
roles_permissionsId: getId('User'), roles_permissionsId: getId('User'),
permissionId: getId('DELETE_GALLERIES'), permissionId: getId('DELETE_PERIODS'),
}, },
{ {
@ -271,25 +271,25 @@ primary key ("roles_permissionsId", "permissionId")
createdAt, createdAt,
updatedAt, updatedAt,
roles_permissionsId: getId('Administrator'), roles_permissionsId: getId('Administrator'),
permissionId: getId('CREATE_GALLERIES'), permissionId: getId('CREATE_PERIODS'),
}, },
{ {
createdAt, createdAt,
updatedAt, updatedAt,
roles_permissionsId: getId('Administrator'), roles_permissionsId: getId('Administrator'),
permissionId: getId('READ_GALLERIES'), permissionId: getId('READ_PERIODS'),
}, },
{ {
createdAt, createdAt,
updatedAt, updatedAt,
roles_permissionsId: getId('Administrator'), roles_permissionsId: getId('Administrator'),
permissionId: getId('UPDATE_GALLERIES'), permissionId: getId('UPDATE_PERIODS'),
}, },
{ {
createdAt, createdAt,
updatedAt, updatedAt,
roles_permissionsId: getId('Administrator'), roles_permissionsId: getId('Administrator'),
permissionId: getId('DELETE_GALLERIES'), permissionId: getId('DELETE_PERIODS'),
}, },
{ {

View File

@ -0,0 +1,103 @@
const { v4: uuid } = require('uuid');
const db = require('../models');
const Sequelize = require('sequelize');
const config = require('../../config');
module.exports = {
/**
* @param{import("sequelize").QueryInterface} queryInterface
* @return {Promise<void>}
*/
async up(queryInterface) {
const createdAt = new Date();
const updatedAt = new Date();
/** @type {Map<string, string>} */
const idMap = new Map();
/**
* @param {string} key
* @return {string}
*/
function getId(key) {
if (idMap.has(key)) {
return idMap.get(key);
}
const id = uuid();
idMap.set(key, id);
return id;
}
/**
* @param {string} name
*/
function createPermissions(name) {
return [
{
id: getId(`CREATE_${name.toUpperCase()}`),
createdAt,
updatedAt,
name: `CREATE_${name.toUpperCase()}`,
},
{
id: getId(`READ_${name.toUpperCase()}`),
createdAt,
updatedAt,
name: `READ_${name.toUpperCase()}`,
},
{
id: getId(`UPDATE_${name.toUpperCase()}`),
createdAt,
updatedAt,
name: `UPDATE_${name.toUpperCase()}`,
},
{
id: getId(`DELETE_${name.toUpperCase()}`),
createdAt,
updatedAt,
name: `DELETE_${name.toUpperCase()}`,
},
];
}
const entities = ['periods'];
const previousValues = ['galleries'];
const createdPreviousPermissions =
previousValues.flatMap(createPermissions);
const namesPreviousPermissions = createdPreviousPermissions.map(
(p) => p.name,
);
const createdPermissions = entities.flatMap(createPermissions);
// Add permissions to database
await queryInterface.bulkInsert('permissions', createdPermissions);
// Get permissions ids
const permissionsIds = createdPermissions.map((p) => p.id);
// Get admin role
const adminRole = await db.roles.findOne({
where: { name: config.roles.admin },
});
if (adminRole) {
// Add permissions to admin role if it exists
await adminRole.addPermissions(permissionsIds);
}
// Remove previous permissions
await db.permissions.destroy({
where: {
name: {
[Sequelize.Op.in]: namesPreviousPermissions,
},
},
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.bulkDelete(
'permissions',
entities.flatMap(createPermissions),
);
},
};

View File

@ -21,7 +21,7 @@ const usersRoutes = require('./routes/users');
const archival_itemsRoutes = require('./routes/archival_items'); const archival_itemsRoutes = require('./routes/archival_items');
const galleriesRoutes = require('./routes/galleries'); const periodsRoutes = require('./routes/periods');
const tagsRoutes = require('./routes/tags'); const tagsRoutes = require('./routes/tags');
@ -107,9 +107,9 @@ app.use(
); );
app.use( app.use(
'/api/galleries', '/api/periods',
passport.authenticate('jwt', { session: false }), passport.authenticate('jwt', { session: false }),
galleriesRoutes, periodsRoutes,
); );
app.use( app.use(

View File

@ -26,9 +26,6 @@ router.use(checkCrudPermissions('archival_items'));
* description: * description:
* type: string * type: string
* default: description * default: description
* period_to:
* type: string
* default: period_to
*/ */
@ -316,7 +313,7 @@ router.get(
currentUser, currentUser,
}); });
if (filetype && filetype === 'csv') { if (filetype && filetype === 'csv') {
const fields = ['id', 'label', 'description', 'period_to', 'period_from']; const fields = ['id', 'label', 'description'];
const opts = { fields }; const opts = { fields };
try { try {
const csv = parse(payload.rows, opts); const csv = parse(payload.rows, opts);

View File

@ -1,7 +1,7 @@
const express = require('express'); const express = require('express');
const GalleriesService = require('../services/galleries'); const PeriodsService = require('../services/periods');
const GalleriesDBApi = require('../db/api/galleries'); const PeriodsDBApi = require('../db/api/periods');
const wrapAsync = require('../helpers').wrapAsync; const wrapAsync = require('../helpers').wrapAsync;
const router = express.Router(); const router = express.Router();
@ -10,13 +10,13 @@ const { parse } = require('json2csv');
const { checkCrudPermissions } = require('../middlewares/check-permissions'); const { checkCrudPermissions } = require('../middlewares/check-permissions');
router.use(checkCrudPermissions('galleries')); router.use(checkCrudPermissions('periods'));
/** /**
* @swagger * @swagger
* components: * components:
* schemas: * schemas:
* Galleries: * Periods:
* type: object * type: object
* properties: * properties:
@ -29,17 +29,17 @@ router.use(checkCrudPermissions('galleries'));
/** /**
* @swagger * @swagger
* tags: * tags:
* name: Galleries * name: Periods
* description: The Galleries managing API * description: The Periods managing API
*/ */
/** /**
* @swagger * @swagger
* /api/galleries: * /api/periods:
* post: * post:
* security: * security:
* - bearerAuth: [] * - bearerAuth: []
* tags: [Galleries] * tags: [Periods]
* summary: Add new item * summary: Add new item
* description: Add new item * description: Add new item
* requestBody: * requestBody:
@ -51,14 +51,14 @@ router.use(checkCrudPermissions('galleries'));
* data: * data:
* description: Data of the updated item * description: Data of the updated item
* type: object * type: object
* $ref: "#/components/schemas/Galleries" * $ref: "#/components/schemas/Periods"
* responses: * responses:
* 200: * 200:
* description: The item was successfully added * description: The item was successfully added
* content: * content:
* application/json: * application/json:
* schema: * schema:
* $ref: "#/components/schemas/Galleries" * $ref: "#/components/schemas/Periods"
* 401: * 401:
* $ref: "#/components/responses/UnauthorizedError" * $ref: "#/components/responses/UnauthorizedError"
* 405: * 405:
@ -73,7 +73,7 @@ router.post(
req.headers.referer || req.headers.referer ||
`${req.protocol}://${req.hostname}${req.originalUrl}`; `${req.protocol}://${req.hostname}${req.originalUrl}`;
const link = new URL(referer); const link = new URL(referer);
await GalleriesService.create( await PeriodsService.create(
req.body.data, req.body.data,
req.currentUser, req.currentUser,
true, true,
@ -90,7 +90,7 @@ router.post(
* post: * post:
* security: * security:
* - bearerAuth: [] * - bearerAuth: []
* tags: [Galleries] * tags: [Periods]
* summary: Bulk import items * summary: Bulk import items
* description: Bulk import items * description: Bulk import items
* requestBody: * requestBody:
@ -103,14 +103,14 @@ router.post(
* description: Data of the updated items * description: Data of the updated items
* type: array * type: array
* items: * items:
* $ref: "#/components/schemas/Galleries" * $ref: "#/components/schemas/Periods"
* responses: * responses:
* 200: * 200:
* description: The items were successfully imported * description: The items were successfully imported
* content: * content:
* application/json: * application/json:
* schema: * schema:
* $ref: "#/components/schemas/Galleries" * $ref: "#/components/schemas/Periods"
* 401: * 401:
* $ref: "#/components/responses/UnauthorizedError" * $ref: "#/components/responses/UnauthorizedError"
* 405: * 405:
@ -126,7 +126,7 @@ router.post(
req.headers.referer || req.headers.referer ||
`${req.protocol}://${req.hostname}${req.originalUrl}`; `${req.protocol}://${req.hostname}${req.originalUrl}`;
const link = new URL(referer); const link = new URL(referer);
await GalleriesService.bulkImport(req, res, true, link.host); await PeriodsService.bulkImport(req, res, true, link.host);
const payload = true; const payload = true;
res.status(200).send(payload); res.status(200).send(payload);
}), }),
@ -134,11 +134,11 @@ router.post(
/** /**
* @swagger * @swagger
* /api/galleries/{id}: * /api/periods/{id}:
* put: * put:
* security: * security:
* - bearerAuth: [] * - bearerAuth: []
* tags: [Galleries] * tags: [Periods]
* summary: Update the data of the selected item * summary: Update the data of the selected item
* description: Update the data of the selected item * description: Update the data of the selected item
* parameters: * parameters:
@ -161,7 +161,7 @@ router.post(
* data: * data:
* description: Data of the updated item * description: Data of the updated item
* type: object * type: object
* $ref: "#/components/schemas/Galleries" * $ref: "#/components/schemas/Periods"
* required: * required:
* - id * - id
* responses: * responses:
@ -170,7 +170,7 @@ router.post(
* content: * content:
* application/json: * application/json:
* schema: * schema:
* $ref: "#/components/schemas/Galleries" * $ref: "#/components/schemas/Periods"
* 400: * 400:
* description: Invalid ID supplied * description: Invalid ID supplied
* 401: * 401:
@ -183,7 +183,7 @@ router.post(
router.put( router.put(
'/:id', '/:id',
wrapAsync(async (req, res) => { wrapAsync(async (req, res) => {
await GalleriesService.update(req.body.data, req.body.id, req.currentUser); await PeriodsService.update(req.body.data, req.body.id, req.currentUser);
const payload = true; const payload = true;
res.status(200).send(payload); res.status(200).send(payload);
}), }),
@ -191,11 +191,11 @@ router.put(
/** /**
* @swagger * @swagger
* /api/galleries/{id}: * /api/periods/{id}:
* delete: * delete:
* security: * security:
* - bearerAuth: [] * - bearerAuth: []
* tags: [Galleries] * tags: [Periods]
* summary: Delete the selected item * summary: Delete the selected item
* description: Delete the selected item * description: Delete the selected item
* parameters: * parameters:
@ -211,7 +211,7 @@ router.put(
* content: * content:
* application/json: * application/json:
* schema: * schema:
* $ref: "#/components/schemas/Galleries" * $ref: "#/components/schemas/Periods"
* 400: * 400:
* description: Invalid ID supplied * description: Invalid ID supplied
* 401: * 401:
@ -224,7 +224,7 @@ router.put(
router.delete( router.delete(
'/:id', '/:id',
wrapAsync(async (req, res) => { wrapAsync(async (req, res) => {
await GalleriesService.remove(req.params.id, req.currentUser); await PeriodsService.remove(req.params.id, req.currentUser);
const payload = true; const payload = true;
res.status(200).send(payload); res.status(200).send(payload);
}), }),
@ -232,11 +232,11 @@ router.delete(
/** /**
* @swagger * @swagger
* /api/galleries/deleteByIds: * /api/periods/deleteByIds:
* post: * post:
* security: * security:
* - bearerAuth: [] * - bearerAuth: []
* tags: [Galleries] * tags: [Periods]
* summary: Delete the selected item list * summary: Delete the selected item list
* description: Delete the selected item list * description: Delete the selected item list
* requestBody: * requestBody:
@ -254,7 +254,7 @@ router.delete(
* content: * content:
* application/json: * application/json:
* schema: * schema:
* $ref: "#/components/schemas/Galleries" * $ref: "#/components/schemas/Periods"
* 401: * 401:
* $ref: "#/components/responses/UnauthorizedError" * $ref: "#/components/responses/UnauthorizedError"
* 404: * 404:
@ -265,7 +265,7 @@ router.delete(
router.post( router.post(
'/deleteByIds', '/deleteByIds',
wrapAsync(async (req, res) => { wrapAsync(async (req, res) => {
await GalleriesService.deleteByIds(req.body.data, req.currentUser); await PeriodsService.deleteByIds(req.body.data, req.currentUser);
const payload = true; const payload = true;
res.status(200).send(payload); res.status(200).send(payload);
}), }),
@ -273,22 +273,22 @@ router.post(
/** /**
* @swagger * @swagger
* /api/galleries: * /api/periods:
* get: * get:
* security: * security:
* - bearerAuth: [] * - bearerAuth: []
* tags: [Galleries] * tags: [Periods]
* summary: Get all galleries * summary: Get all periods
* description: Get all galleries * description: Get all periods
* responses: * responses:
* 200: * 200:
* description: Galleries list successfully received * description: Periods list successfully received
* content: * content:
* application/json: * application/json:
* schema: * schema:
* type: array * type: array
* items: * items:
* $ref: "#/components/schemas/Galleries" * $ref: "#/components/schemas/Periods"
* 401: * 401:
* $ref: "#/components/responses/UnauthorizedError" * $ref: "#/components/responses/UnauthorizedError"
* 404: * 404:
@ -302,9 +302,9 @@ router.get(
const filetype = req.query.filetype; const filetype = req.query.filetype;
const currentUser = req.currentUser; const currentUser = req.currentUser;
const payload = await GalleriesDBApi.findAll(req.query, { currentUser }); const payload = await PeriodsDBApi.findAll(req.query, { currentUser });
if (filetype && filetype === 'csv') { if (filetype && filetype === 'csv') {
const fields = ['id', 'name']; const fields = ['id', 'name', 'period_from', 'period_to'];
const opts = { fields }; const opts = { fields };
try { try {
const csv = parse(payload.rows, opts); const csv = parse(payload.rows, opts);
@ -321,22 +321,22 @@ router.get(
/** /**
* @swagger * @swagger
* /api/galleries/count: * /api/periods/count:
* get: * get:
* security: * security:
* - bearerAuth: [] * - bearerAuth: []
* tags: [Galleries] * tags: [Periods]
* summary: Count all galleries * summary: Count all periods
* description: Count all galleries * description: Count all periods
* responses: * responses:
* 200: * 200:
* description: Galleries count successfully received * description: Periods count successfully received
* content: * content:
* application/json: * application/json:
* schema: * schema:
* type: array * type: array
* items: * items:
* $ref: "#/components/schemas/Galleries" * $ref: "#/components/schemas/Periods"
* 401: * 401:
* $ref: "#/components/responses/UnauthorizedError" * $ref: "#/components/responses/UnauthorizedError"
* 404: * 404:
@ -348,7 +348,7 @@ router.get(
'/count', '/count',
wrapAsync(async (req, res) => { wrapAsync(async (req, res) => {
const currentUser = req.currentUser; const currentUser = req.currentUser;
const payload = await GalleriesDBApi.findAll(req.query, null, { const payload = await PeriodsDBApi.findAll(req.query, null, {
countOnly: true, countOnly: true,
currentUser, currentUser,
}); });
@ -359,22 +359,22 @@ router.get(
/** /**
* @swagger * @swagger
* /api/galleries/autocomplete: * /api/periods/autocomplete:
* get: * get:
* security: * security:
* - bearerAuth: [] * - bearerAuth: []
* tags: [Galleries] * tags: [Periods]
* summary: Find all galleries that match search criteria * summary: Find all periods that match search criteria
* description: Find all galleries that match search criteria * description: Find all periods that match search criteria
* responses: * responses:
* 200: * 200:
* description: Galleries list successfully received * description: Periods list successfully received
* content: * content:
* application/json: * application/json:
* schema: * schema:
* type: array * type: array
* items: * items:
* $ref: "#/components/schemas/Galleries" * $ref: "#/components/schemas/Periods"
* 401: * 401:
* $ref: "#/components/responses/UnauthorizedError" * $ref: "#/components/responses/UnauthorizedError"
* 404: * 404:
@ -383,7 +383,7 @@ router.get(
* description: Some server error * description: Some server error
*/ */
router.get('/autocomplete', async (req, res) => { router.get('/autocomplete', async (req, res) => {
const payload = await GalleriesDBApi.findAllAutocomplete( const payload = await PeriodsDBApi.findAllAutocomplete(
req.query.query, req.query.query,
req.query.limit, req.query.limit,
req.query.offset, req.query.offset,
@ -394,11 +394,11 @@ router.get('/autocomplete', async (req, res) => {
/** /**
* @swagger * @swagger
* /api/galleries/{id}: * /api/periods/{id}:
* get: * get:
* security: * security:
* - bearerAuth: [] * - bearerAuth: []
* tags: [Galleries] * tags: [Periods]
* summary: Get selected item * summary: Get selected item
* description: Get selected item * description: Get selected item
* parameters: * parameters:
@ -414,7 +414,7 @@ router.get('/autocomplete', async (req, res) => {
* content: * content:
* application/json: * application/json:
* schema: * schema:
* $ref: "#/components/schemas/Galleries" * $ref: "#/components/schemas/Periods"
* 400: * 400:
* description: Invalid ID supplied * description: Invalid ID supplied
* 401: * 401:
@ -427,7 +427,7 @@ router.get('/autocomplete', async (req, res) => {
router.get( router.get(
'/:id', '/:id',
wrapAsync(async (req, res) => { wrapAsync(async (req, res) => {
const payload = await GalleriesDBApi.findBy({ id: req.params.id }); const payload = await PeriodsDBApi.findBy({ id: req.params.id });
res.status(200).send(payload); res.status(200).send(payload);
}), }),

View File

@ -1,5 +1,5 @@
const db = require('../db/models'); const db = require('../db/models');
const GalleriesDBApi = require('../db/api/galleries'); const PeriodsDBApi = require('../db/api/periods');
const processFile = require('../middlewares/upload'); const processFile = require('../middlewares/upload');
const ValidationError = require('./notifications/errors/validation'); const ValidationError = require('./notifications/errors/validation');
const csv = require('csv-parser'); const csv = require('csv-parser');
@ -7,11 +7,11 @@ const axios = require('axios');
const config = require('../config'); const config = require('../config');
const stream = require('stream'); const stream = require('stream');
module.exports = class GalleriesService { module.exports = class PeriodsService {
static async create(data, currentUser) { static async create(data, currentUser) {
const transaction = await db.sequelize.transaction(); const transaction = await db.sequelize.transaction();
try { try {
await GalleriesDBApi.create(data, { await PeriodsDBApi.create(data, {
currentUser, currentUser,
transaction, transaction,
}); });
@ -44,7 +44,7 @@ module.exports = class GalleriesService {
.on('error', (error) => reject(error)); .on('error', (error) => reject(error));
}); });
await GalleriesDBApi.bulkImport(results, { await PeriodsDBApi.bulkImport(results, {
transaction, transaction,
ignoreDuplicates: true, ignoreDuplicates: true,
validate: true, validate: true,
@ -61,19 +61,19 @@ module.exports = class GalleriesService {
static async update(data, id, currentUser) { static async update(data, id, currentUser) {
const transaction = await db.sequelize.transaction(); const transaction = await db.sequelize.transaction();
try { try {
let galleries = await GalleriesDBApi.findBy({ id }, { transaction }); let periods = await PeriodsDBApi.findBy({ id }, { transaction });
if (!galleries) { if (!periods) {
throw new ValidationError('galleriesNotFound'); throw new ValidationError('periodsNotFound');
} }
const updatedGalleries = await GalleriesDBApi.update(id, data, { const updatedPeriods = await PeriodsDBApi.update(id, data, {
currentUser, currentUser,
transaction, transaction,
}); });
await transaction.commit(); await transaction.commit();
return updatedGalleries; return updatedPeriods;
} catch (error) { } catch (error) {
await transaction.rollback(); await transaction.rollback();
throw error; throw error;
@ -84,7 +84,7 @@ module.exports = class GalleriesService {
const transaction = await db.sequelize.transaction(); const transaction = await db.sequelize.transaction();
try { try {
await GalleriesDBApi.deleteByIds(ids, { await PeriodsDBApi.deleteByIds(ids, {
currentUser, currentUser,
transaction, transaction,
}); });
@ -100,7 +100,7 @@ module.exports = class GalleriesService {
const transaction = await db.sequelize.transaction(); const transaction = await db.sequelize.transaction();
try { try {
await GalleriesDBApi.remove(id, { await PeriodsDBApi.remove(id, {
currentUser, currentUser,
transaction, transaction,
}); });

View File

@ -43,9 +43,9 @@ module.exports = class SearchService {
const tableColumns = { const tableColumns = {
users: ['firstName', 'lastName', 'phoneNumber', 'email'], users: ['firstName', 'lastName', 'phoneNumber', 'email'],
archival_items: ['label', 'description', 'period_to'], archival_items: ['label', 'description'],
galleries: ['name'], periods: ['name'],
tags: ['name'], tags: ['name'],
}; };

View File

@ -127,28 +127,6 @@ const CardArchival_items = ({
</dd> </dd>
</div> </div>
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>
Period From
</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{dataFormatter.dateFormatter(item.period_from)}
</div>
</dd>
</div>
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>
Period To
</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{item.period_to}
</div>
</dd>
</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'>Tags</dt> <dt className=' text-gray-500 dark:text-dark-600'>Tags</dt>
<dd className='flex items-start gap-x-2'> <dd className='flex items-start gap-x-2'>

View File

@ -89,18 +89,6 @@ const ListArchival_items = ({
</p> </p>
</div> </div>
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>Period From</p>
<p className={'line-clamp-2'}>
{dataFormatter.dateFormatter(item.period_from)}
</p>
</div>
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>Period To</p>
<p className={'line-clamp-2'}>{item.period_to}</p>
</div>
<div className={'flex-1 px-3'}> <div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>Tags</p> <p className={'text-xs text-gray-500 '}>Tags</p>
<p className={'line-clamp-2'}> <p className={'line-clamp-2'}>

View File

@ -96,34 +96,6 @@ export const loadColumns = async (
type: 'boolean', type: 'boolean',
}, },
{
field: 'period_from',
headerName: 'Period From',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
type: 'date',
valueGetter: (params: GridValueGetterParams) =>
new Date(params.row.period_from),
},
{
field: 'period_to',
headerName: 'Period To',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
},
{ {
field: 'tags', field: 'tags',
headerName: 'Tags', headerName: 'Tags',

View File

@ -11,7 +11,7 @@ import Link from 'next/link';
import { hasPermission } from '../../helpers/userPermissions'; import { hasPermission } from '../../helpers/userPermissions';
type Props = { type Props = {
galleries: any[]; periods: any[];
loading: boolean; loading: boolean;
onDelete: (id: string) => void; onDelete: (id: string) => void;
currentPage: number; currentPage: number;
@ -19,8 +19,8 @@ type Props = {
onPageChange: (page: number) => void; onPageChange: (page: number) => void;
}; };
const CardGalleries = ({ const CardPeriods = ({
galleries, periods,
loading, loading,
onDelete, onDelete,
currentPage, currentPage,
@ -36,7 +36,7 @@ const CardGalleries = ({
const focusRing = useAppSelector((state) => state.style.focusRingColor); const focusRing = useAppSelector((state) => state.style.focusRingColor);
const currentUser = useAppSelector((state) => state.auth.currentUser); const currentUser = useAppSelector((state) => state.auth.currentUser);
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_GALLERIES'); const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_PERIODS');
return ( return (
<div className={'p-4'}> <div className={'p-4'}>
@ -46,7 +46,7 @@ const CardGalleries = ({
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 && {!loading &&
galleries.map((item, index) => ( periods.map((item, index) => (
<li <li
key={item.id} key={item.id}
className={`overflow-hidden ${ className={`overflow-hidden ${
@ -56,27 +56,21 @@ const CardGalleries = ({
}`} }`}
> >
<div <div
className={`flex items-center ${bgColor} p-6 md:p-0 md:block 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 <Link
href={`/galleries/galleries-view/?id=${item.id}`} href={`/periods/periods-view/?id=${item.id}`}
className={'cursor-pointer'} className='text-lg font-bold leading-6 line-clamp-1'
> >
<ImageField {item.id}
name={'Avatar'}
image={item.background_image}
className='w-12 h-12 md:w-full md:h-44 rounded-lg md:rounded-b-none overflow-hidden ring-1 ring-gray-900/10'
imageClassName='h-full w-full flex-none rounded-lg md:rounded-b-none bg-white object-cover'
/>
<p className={'px-6 py-2 font-semibold'}>{item.id}</p>
</Link> </Link>
<div className='ml-auto md:absolute md:top-0 md:right-0 '> <div className='ml-auto '>
<ListActionsPopover <ListActionsPopover
onDelete={onDelete} onDelete={onDelete}
itemId={item.id} itemId={item.id}
pathEdit={`/galleries/galleries-edit/?id=${item.id}`} pathEdit={`/periods/periods-edit/?id=${item.id}`}
pathView={`/galleries/galleries-view/?id=${item.id}`} pathView={`/periods/periods-view/?id=${item.id}`}
hasUpdatePermission={hasUpdatePermission} hasUpdatePermission={hasUpdatePermission}
/> />
</div> </div>
@ -104,22 +98,29 @@ const CardGalleries = ({
<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'> <dt className=' text-gray-500 dark:text-dark-600'>
Background Image Period From
</dt> </dt>
<dd className='flex items-start gap-x-2'> <dd className='flex items-start gap-x-2'>
<div className='font-medium'> <div className='font-medium line-clamp-4'>
<ImageField {dataFormatter.dateTimeFormatter(item.period_from)}
name={'Avatar'} </div>
image={item.background_image} </dd>
className='mx-auto w-8 h-8' </div>
/>
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>
Period To
</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{dataFormatter.dateTimeFormatter(item.period_to)}
</div> </div>
</dd> </dd>
</div> </div>
</dl> </dl>
</li> </li>
))} ))}
{!loading && galleries.length === 0 && ( {!loading && periods.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>
</div> </div>
@ -136,4 +137,4 @@ const CardGalleries = ({
); );
}; };
export default CardGalleries; export default CardPeriods;

View File

@ -12,7 +12,7 @@ import Link from 'next/link';
import { hasPermission } from '../../helpers/userPermissions'; import { hasPermission } from '../../helpers/userPermissions';
type Props = { type Props = {
galleries: any[]; periods: any[];
loading: boolean; loading: boolean;
onDelete: (id: string) => void; onDelete: (id: string) => void;
currentPage: number; currentPage: number;
@ -20,8 +20,8 @@ type Props = {
onPageChange: (page: number) => void; onPageChange: (page: number) => void;
}; };
const ListGalleries = ({ const ListPeriods = ({
galleries, periods,
loading, loading,
onDelete, onDelete,
currentPage, currentPage,
@ -29,7 +29,7 @@ const ListGalleries = ({
onPageChange, onPageChange,
}: Props) => { }: Props) => {
const currentUser = useAppSelector((state) => state.auth.currentUser); const currentUser = useAppSelector((state) => state.auth.currentUser);
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_GALLERIES'); const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_PERIODS');
const corners = useAppSelector((state) => state.style.corners); const corners = useAppSelector((state) => state.style.corners);
const bgColor = useAppSelector((state) => state.style.cardsColor); const bgColor = useAppSelector((state) => state.style.cardsColor);
@ -39,23 +39,14 @@ const ListGalleries = ({
<div className='relative overflow-x-auto p-4 space-y-4'> <div className='relative overflow-x-auto p-4 space-y-4'>
{loading && <LoadingSpinner />} {loading && <LoadingSpinner />}
{!loading && {!loading &&
galleries.map((item) => ( periods.map((item) => (
<div key={item.id}> <div key={item.id}>
<CardBox hasTable isList className={'rounded shadow-none'}> <CardBox hasTable isList className={'rounded shadow-none'}>
<div <div
className={`flex rounded dark:bg-dark-900 border border-stone-300 items-center overflow-hidden`} className={`flex rounded dark:bg-dark-900 border border-stone-300 items-center overflow-hidden`}
> >
<ImageField
name={'Avatar'}
image={item.background_image}
className='w-24 h-24 rounded-l overflow-hidden hidden md:block'
imageClassName={
'rounded-l rounded-r-none h-full object-cover'
}
/>
<Link <Link
href={`/galleries/galleries-view/?id=${item.id}`} href={`/periods/periods-view/?id=${item.id}`}
className={ 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' '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'
} }
@ -77,28 +68,31 @@ const ListGalleries = ({
</div> </div>
<div className={'flex-1 px-3'}> <div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}> <p className={'text-xs text-gray-500 '}>Period From</p>
Background Image <p className={'line-clamp-2'}>
{dataFormatter.dateTimeFormatter(item.period_from)}
</p>
</div>
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>Period To</p>
<p className={'line-clamp-2'}>
{dataFormatter.dateTimeFormatter(item.period_to)}
</p> </p>
<ImageField
name={'Avatar'}
image={item.background_image}
className='mx-auto w-8 h-8'
/>
</div> </div>
</Link> </Link>
<ListActionsPopover <ListActionsPopover
onDelete={onDelete} onDelete={onDelete}
itemId={item.id} itemId={item.id}
pathEdit={`/galleries/galleries-edit/?id=${item.id}`} pathEdit={`/periods/periods-edit/?id=${item.id}`}
pathView={`/galleries/galleries-view/?id=${item.id}`} pathView={`/periods/periods-view/?id=${item.id}`}
hasUpdatePermission={hasUpdatePermission} hasUpdatePermission={hasUpdatePermission}
/> />
</div> </div>
</CardBox> </CardBox>
</div> </div>
))} ))}
{!loading && galleries.length === 0 && ( {!loading && periods.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>
</div> </div>
@ -115,4 +109,4 @@ const ListGalleries = ({
); );
}; };
export default ListGalleries; export default ListPeriods;

View File

@ -10,19 +10,19 @@ import {
deleteItem, deleteItem,
setRefetch, setRefetch,
deleteItemsByIds, deleteItemsByIds,
} from '../../stores/galleries/galleriesSlice'; } from '../../stores/periods/periodsSlice';
import { useAppDispatch, useAppSelector } from '../../stores/hooks'; import { useAppDispatch, useAppSelector } from '../../stores/hooks';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { Field, Form, Formik } from 'formik'; import { Field, Form, Formik } from 'formik';
import { DataGrid, GridColDef } from '@mui/x-data-grid'; import { DataGrid, GridColDef } from '@mui/x-data-grid';
import { loadColumns } from './configureGalleriesCols'; import { loadColumns } from './configurePeriodsCols';
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter'; import dataFormatter from '../../helpers/dataFormatter';
import { dataGridStyles } from '../../styles'; import { dataGridStyles } from '../../styles';
const perPage = 10; const perPage = 10;
const TableSampleGalleries = ({ const TableSamplePeriods = ({
filterItems, filterItems,
setFilterItems, setFilterItems,
filters, filters,
@ -47,12 +47,12 @@ const TableSampleGalleries = ({
]); ]);
const { const {
galleries, periods,
loading, loading,
count, count,
notify: galleriesNotify, notify: periodsNotify,
refetch, refetch,
} = useAppSelector((state) => state.galleries); } = useAppSelector((state) => state.periods);
const { currentUser } = useAppSelector((state) => state.auth); const { currentUser } = useAppSelector((state) => state.auth);
const focusRing = useAppSelector((state) => state.style.focusRingColor); const focusRing = useAppSelector((state) => state.style.focusRingColor);
const bgColor = useAppSelector((state) => state.style.bgLayoutColor); const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
@ -73,13 +73,10 @@ const TableSampleGalleries = ({
}; };
useEffect(() => { useEffect(() => {
if (galleriesNotify.showNotification) { if (periodsNotify.showNotification) {
notify( notify(periodsNotify.typeNotification, periodsNotify.textNotification);
galleriesNotify.typeNotification,
galleriesNotify.textNotification,
);
} }
}, [galleriesNotify.showNotification]); }, [periodsNotify.showNotification]);
useEffect(() => { useEffect(() => {
if (!currentUser) return; if (!currentUser) return;
@ -184,7 +181,7 @@ const TableSampleGalleries = ({
useEffect(() => { useEffect(() => {
if (!currentUser) return; if (!currentUser) return;
loadColumns(handleDeleteModalAction, `galleries`, currentUser).then( loadColumns(handleDeleteModalAction, `periods`, currentUser).then(
(newCols) => setColumns(newCols), (newCols) => setColumns(newCols),
); );
}, [currentUser]); }, [currentUser]);
@ -218,7 +215,7 @@ const TableSampleGalleries = ({
sx={dataGridStyles} sx={dataGridStyles}
className={'datagrid--table'} className={'datagrid--table'}
getRowClassName={() => `datagrid--row`} getRowClassName={() => `datagrid--row`}
rows={galleries ?? []} rows={periods ?? []}
columns={columns} columns={columns}
initialState={{ initialState={{
pagination: { pagination: {
@ -481,4 +478,4 @@ const TableSampleGalleries = ({
); );
}; };
export default TableSampleGalleries; export default TableSamplePeriods;

View File

@ -35,7 +35,7 @@ export const loadColumns = async (
} }
} }
const hasUpdatePermission = hasPermission(user, 'UPDATE_GALLERIES'); const hasUpdatePermission = hasPermission(user, 'UPDATE_PERIODS');
return [ return [
{ {
@ -70,23 +70,35 @@ export const loadColumns = async (
}, },
{ {
field: 'background_image', field: 'period_from',
headerName: 'Background Image', headerName: 'Period From',
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: false, editable: hasUpdatePermission,
sortable: false,
renderCell: (params: GridValueGetterParams) => ( type: 'dateTime',
<ImageField valueGetter: (params: GridValueGetterParams) =>
name={'Avatar'} new Date(params.row.period_from),
image={params?.row?.background_image} },
className='w-24 h-24 mx-auto lg:w-6 lg:h-6'
/> {
), field: 'period_to',
headerName: 'Period To',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: hasUpdatePermission,
type: 'dateTime',
valueGetter: (params: GridValueGetterParams) =>
new Date(params.row.period_to),
}, },
{ {
@ -101,8 +113,8 @@ export const loadColumns = async (
<ListActionsPopover <ListActionsPopover
onDelete={onDelete} onDelete={onDelete}
itemId={params?.row?.id} itemId={params?.row?.id}
pathEdit={`/galleries/galleries-edit/?id=${params?.row?.id}`} pathEdit={`/periods/periods-edit/?id=${params?.row?.id}`}
pathView={`/galleries/galleries-view/?id=${params?.row?.id}`} pathView={`/periods/periods-view/?id=${params?.row?.id}`}
hasUpdatePermission={hasUpdatePermission} hasUpdatePermission={hasUpdatePermission}
/> />
</div>, </div>,

View File

@ -25,12 +25,12 @@ const menuAside: MenuAsideItem[] = [
permissions: 'READ_ARCHIVAL_ITEMS', permissions: 'READ_ARCHIVAL_ITEMS',
}, },
{ {
href: '/galleries/galleries-list', href: '/periods/periods-list',
label: 'Galleries', label: 'Periods',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
icon: icon.mdiTable ?? icon.mdiTable, icon: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_GALLERIES', permissions: 'READ_PERIODS',
}, },
{ {
href: '/tags/tags-list', href: '/tags/tags-list',

View File

@ -44,10 +44,6 @@ const EditArchival_items = () => {
isPublished: false, isPublished: false,
period_from: new Date(),
period_to: '',
tags: [], tags: [],
}; };
const [initialValues, setInitialValues] = useState(initVals); const [initialValues, setInitialValues] = useState(initVals);
@ -135,28 +131,6 @@ const EditArchival_items = () => {
></Field> ></Field>
</FormField> </FormField>
<FormField label='Period From'>
<DatePicker
dateFormat='yyyy-MM-dd'
selected={
initialValues.period_from
? new Date(
dayjs(initialValues.period_from).format(
'YYYY-MM-DD hh:mm',
),
)
: null
}
onChange={(date) =>
setInitialValues({ ...initialValues, period_from: date })
}
/>
</FormField>
<FormField label='Period To'>
<Field name='period_to' placeholder='Period To' />
</FormField>
<FormField label='Tags' labelFor='tags'> <FormField label='Tags' labelFor='tags'>
<Field <Field
name='tags' name='tags'

View File

@ -44,10 +44,6 @@ const EditArchival_itemsPage = () => {
isPublished: false, isPublished: false,
period_from: new Date(),
period_to: '',
tags: [], tags: [],
}; };
const [initialValues, setInitialValues] = useState(initVals); const [initialValues, setInitialValues] = useState(initVals);
@ -133,28 +129,6 @@ const EditArchival_itemsPage = () => {
></Field> ></Field>
</FormField> </FormField>
<FormField label='Period From'>
<DatePicker
dateFormat='yyyy-MM-dd'
selected={
initialValues.period_from
? new Date(
dayjs(initialValues.period_from).format(
'YYYY-MM-DD hh:mm',
),
)
: null
}
onChange={(date) =>
setInitialValues({ ...initialValues, period_from: date })
}
/>
</FormField>
<FormField label='Period To'>
<Field name='period_to' placeholder='Period To' />
</FormField>
<FormField label='Tags' labelFor='tags'> <FormField label='Tags' labelFor='tags'>
<Field <Field
name='tags' name='tags'

View File

@ -34,7 +34,6 @@ const Archival_itemsTablesPage = () => {
const [filters] = useState([ const [filters] = useState([
{ label: 'Label', title: 'label' }, { label: 'Label', title: 'label' },
{ label: 'Description', title: 'description' }, { label: 'Description', title: 'description' },
{ label: 'Period To', title: 'period_to' },
{ label: 'Tags', title: 'tags' }, { label: 'Tags', title: 'tags' },
]); ]);

View File

@ -41,11 +41,6 @@ const initialValues = {
isPublished: false, isPublished: false,
period_from: '',
datePeriod_from: '',
period_to: '',
tags: [], tags: [],
}; };
@ -108,18 +103,6 @@ const Archival_itemsNew = () => {
></Field> ></Field>
</FormField> </FormField>
<FormField label='Period From'>
<Field
type='date'
name='period_from'
placeholder='Period From'
/>
</FormField>
<FormField label='Period To'>
<Field name='period_to' placeholder='Period To' />
</FormField>
<FormField label='Tags' labelFor='tags'> <FormField label='Tags' labelFor='tags'>
<Field <Field
name='tags' name='tags'

View File

@ -34,7 +34,6 @@ const Archival_itemsTablesPage = () => {
const [filters] = useState([ const [filters] = useState([
{ label: 'Label', title: 'label' }, { label: 'Label', title: 'label' },
{ label: 'Description', title: 'description' }, { label: 'Description', title: 'description' },
{ label: 'Period To', title: 'period_to' },
{ label: 'Tags', title: 'tags' }, { label: 'Tags', title: 'tags' },
]); ]);

View File

@ -88,32 +88,6 @@ const Archival_itemsView = () => {
/> />
</FormField> </FormField>
<FormField label='Period From'>
{archival_items.period_from ? (
<DatePicker
dateFormat='yyyy-MM-dd'
showTimeSelect
selected={
archival_items.period_from
? new Date(
dayjs(archival_items.period_from).format(
'YYYY-MM-DD hh:mm',
),
)
: null
}
disabled
/>
) : (
<p>No Period From</p>
)}
</FormField>
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>Period To</p>
<p>{archival_items?.period_to}</p>
</div>
<> <>
<p className={'block font-bold mb-2'}>Tags</p> <p className={'block font-bold mb-2'}>Tags</p>
<CardBox <CardBox

View File

@ -30,7 +30,7 @@ const Dashboard = () => {
const [users, setUsers] = React.useState(loadingMessage); const [users, setUsers] = React.useState(loadingMessage);
const [archival_items, setArchival_items] = React.useState(loadingMessage); const [archival_items, setArchival_items] = React.useState(loadingMessage);
const [galleries, setGalleries] = React.useState(loadingMessage); const [periods, setPeriods] = React.useState(loadingMessage);
const [tags, setTags] = React.useState(loadingMessage); const [tags, setTags] = React.useState(loadingMessage);
const [roles, setRoles] = React.useState(loadingMessage); const [roles, setRoles] = React.useState(loadingMessage);
const [permissions, setPermissions] = React.useState(loadingMessage); const [permissions, setPermissions] = React.useState(loadingMessage);
@ -47,7 +47,7 @@ const Dashboard = () => {
const entities = [ const entities = [
'users', 'users',
'archival_items', 'archival_items',
'galleries', 'periods',
'tags', 'tags',
'roles', 'roles',
'permissions', 'permissions',
@ -55,7 +55,7 @@ const Dashboard = () => {
const fns = [ const fns = [
setUsers, setUsers,
setArchival_items, setArchival_items,
setGalleries, setPeriods,
setTags, setTags,
setRoles, setRoles,
setPermissions, setPermissions,
@ -235,8 +235,8 @@ const Dashboard = () => {
</Link> </Link>
)} )}
{hasPermission(currentUser, 'READ_GALLERIES') && ( {hasPermission(currentUser, 'READ_PERIODS') && (
<Link href={'/galleries/galleries-list'}> <Link href={'/periods/periods-list'}>
<div <div
className={`${ className={`${
corners !== 'rounded-full' ? corners : 'rounded-3xl' corners !== 'rounded-full' ? corners : 'rounded-3xl'
@ -245,10 +245,10 @@ const Dashboard = () => {
<div className='flex justify-between align-center'> <div className='flex justify-between align-center'>
<div> <div>
<div className='text-lg leading-tight text-gray-500 dark:text-gray-400'> <div className='text-lg leading-tight text-gray-500 dark:text-gray-400'>
Galleries Periods
</div> </div>
<div className='text-3xl leading-tight font-semibold'> <div className='text-3xl leading-tight font-semibold'>
{galleries} {periods}
</div> </div>
</div> </div>
<div> <div>

View File

@ -25,14 +25,14 @@ import { SelectFieldMany } from '../../components/SelectFieldMany';
import { SwitchField } from '../../components/SwitchField'; import { SwitchField } from '../../components/SwitchField';
import { RichTextField } from '../../components/RichTextField'; import { RichTextField } from '../../components/RichTextField';
import { update, fetch } from '../../stores/galleries/galleriesSlice'; import { update, fetch } from '../../stores/periods/periodsSlice';
import { useAppDispatch, useAppSelector } from '../../stores/hooks'; import { useAppDispatch, useAppSelector } from '../../stores/hooks';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { saveFile } from '../../helpers/fileSaver'; import { saveFile } from '../../helpers/fileSaver';
import dataFormatter from '../../helpers/dataFormatter'; import dataFormatter from '../../helpers/dataFormatter';
import ImageField from '../../components/ImageField'; import ImageField from '../../components/ImageField';
const EditGalleries = () => { const EditPeriods = () => {
const router = useRouter(); const router = useRouter();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const initVals = { const initVals = {
@ -40,50 +40,50 @@ const EditGalleries = () => {
archival_items: [], archival_items: [],
background_image: [], period_from: new Date(),
period_to: new Date(),
}; };
const [initialValues, setInitialValues] = useState(initVals); const [initialValues, setInitialValues] = useState(initVals);
const { galleries } = useAppSelector((state) => state.galleries); const { periods } = useAppSelector((state) => state.periods);
const { galleriesId } = router.query; const { periodsId } = router.query;
useEffect(() => { useEffect(() => {
dispatch(fetch({ id: galleriesId })); dispatch(fetch({ id: periodsId }));
}, [galleriesId]); }, [periodsId]);
useEffect(() => { useEffect(() => {
if (typeof galleries === 'object') { if (typeof periods === 'object') {
setInitialValues(galleries); setInitialValues(periods);
} }
}, [galleries]); }, [periods]);
useEffect(() => { useEffect(() => {
if (typeof galleries === 'object') { if (typeof periods === 'object') {
const newInitialVal = { ...initVals }; const newInitialVal = { ...initVals };
Object.keys(initVals).forEach( Object.keys(initVals).forEach((el) => (newInitialVal[el] = periods[el]));
(el) => (newInitialVal[el] = galleries[el]),
);
setInitialValues(newInitialVal); setInitialValues(newInitialVal);
} }
}, [galleries]); }, [periods]);
const handleSubmit = async (data) => { const handleSubmit = async (data) => {
await dispatch(update({ id: galleriesId, data })); await dispatch(update({ id: periodsId, data }));
await router.push('/galleries/galleries-list'); await router.push('/periods/periods-list');
}; };
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Edit galleries')}</title> <title>{getPageTitle('Edit periods')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton <SectionTitleLineWithButton
icon={mdiChartTimelineVariant} icon={mdiChartTimelineVariant}
title={'Edit galleries'} title={'Edit periods'}
main main
> >
{''} {''}
@ -110,20 +110,42 @@ const EditGalleries = () => {
></Field> ></Field>
</FormField> </FormField>
<FormField> <FormField label='Period From'>
<Field <DatePicker
label='Background Image' dateFormat='yyyy-MM-dd hh:mm'
color='info' showTimeSelect
icon={mdiUpload} selected={
path={'galleries/background_image'} initialValues.period_from
name='background_image' ? new Date(
id='background_image' dayjs(initialValues.period_from).format(
schema={{ 'YYYY-MM-DD hh:mm',
size: undefined, ),
formats: undefined, )
}} : null
component={FormImagePicker} }
></Field> onChange={(date) =>
setInitialValues({ ...initialValues, period_from: date })
}
/>
</FormField>
<FormField label='Period To'>
<DatePicker
dateFormat='yyyy-MM-dd hh:mm'
showTimeSelect
selected={
initialValues.period_to
? new Date(
dayjs(initialValues.period_to).format(
'YYYY-MM-DD hh:mm',
),
)
: null
}
onChange={(date) =>
setInitialValues({ ...initialValues, period_to: date })
}
/>
</FormField> </FormField>
<BaseDivider /> <BaseDivider />
@ -135,7 +157,7 @@ const EditGalleries = () => {
color='danger' color='danger'
outline outline
label='Cancel' label='Cancel'
onClick={() => router.push('/galleries/galleries-list')} onClick={() => router.push('/periods/periods-list')}
/> />
</BaseButtons> </BaseButtons>
</Form> </Form>
@ -146,12 +168,12 @@ const EditGalleries = () => {
); );
}; };
EditGalleries.getLayout = function getLayout(page: ReactElement) { EditPeriods.getLayout = function getLayout(page: ReactElement) {
return ( return (
<LayoutAuthenticated permission={'UPDATE_GALLERIES'}> <LayoutAuthenticated permission={'UPDATE_PERIODS'}>
{page} {page}
</LayoutAuthenticated> </LayoutAuthenticated>
); );
}; };
export default EditGalleries; export default EditPeriods;

View File

@ -25,14 +25,14 @@ import { SelectFieldMany } from '../../components/SelectFieldMany';
import { SwitchField } from '../../components/SwitchField'; import { SwitchField } from '../../components/SwitchField';
import { RichTextField } from '../../components/RichTextField'; import { RichTextField } from '../../components/RichTextField';
import { update, fetch } from '../../stores/galleries/galleriesSlice'; import { update, fetch } from '../../stores/periods/periodsSlice';
import { useAppDispatch, useAppSelector } from '../../stores/hooks'; import { useAppDispatch, useAppSelector } from '../../stores/hooks';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { saveFile } from '../../helpers/fileSaver'; import { saveFile } from '../../helpers/fileSaver';
import dataFormatter from '../../helpers/dataFormatter'; import dataFormatter from '../../helpers/dataFormatter';
import ImageField from '../../components/ImageField'; import ImageField from '../../components/ImageField';
const EditGalleriesPage = () => { const EditPeriodsPage = () => {
const router = useRouter(); const router = useRouter();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const initVals = { const initVals = {
@ -40,11 +40,13 @@ const EditGalleriesPage = () => {
archival_items: [], archival_items: [],
background_image: [], period_from: new Date(),
period_to: new Date(),
}; };
const [initialValues, setInitialValues] = useState(initVals); const [initialValues, setInitialValues] = useState(initVals);
const { galleries } = useAppSelector((state) => state.galleries); const { periods } = useAppSelector((state) => state.periods);
const { id } = router.query; const { id } = router.query;
@ -53,35 +55,33 @@ const EditGalleriesPage = () => {
}, [id]); }, [id]);
useEffect(() => { useEffect(() => {
if (typeof galleries === 'object') { if (typeof periods === 'object') {
setInitialValues(galleries); setInitialValues(periods);
} }
}, [galleries]); }, [periods]);
useEffect(() => { useEffect(() => {
if (typeof galleries === 'object') { if (typeof periods === 'object') {
const newInitialVal = { ...initVals }; const newInitialVal = { ...initVals };
Object.keys(initVals).forEach( Object.keys(initVals).forEach((el) => (newInitialVal[el] = periods[el]));
(el) => (newInitialVal[el] = galleries[el]),
);
setInitialValues(newInitialVal); setInitialValues(newInitialVal);
} }
}, [galleries]); }, [periods]);
const handleSubmit = async (data) => { const handleSubmit = async (data) => {
await dispatch(update({ id: id, data })); await dispatch(update({ id: id, data }));
await router.push('/galleries/galleries-list'); await router.push('/periods/periods-list');
}; };
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Edit galleries')}</title> <title>{getPageTitle('Edit periods')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton <SectionTitleLineWithButton
icon={mdiChartTimelineVariant} icon={mdiChartTimelineVariant}
title={'Edit galleries'} title={'Edit periods'}
main main
> >
{''} {''}
@ -108,20 +108,42 @@ const EditGalleriesPage = () => {
></Field> ></Field>
</FormField> </FormField>
<FormField> <FormField label='Period From'>
<Field <DatePicker
label='Background Image' dateFormat='yyyy-MM-dd hh:mm'
color='info' showTimeSelect
icon={mdiUpload} selected={
path={'galleries/background_image'} initialValues.period_from
name='background_image' ? new Date(
id='background_image' dayjs(initialValues.period_from).format(
schema={{ 'YYYY-MM-DD hh:mm',
size: undefined, ),
formats: undefined, )
}} : null
component={FormImagePicker} }
></Field> onChange={(date) =>
setInitialValues({ ...initialValues, period_from: date })
}
/>
</FormField>
<FormField label='Period To'>
<DatePicker
dateFormat='yyyy-MM-dd hh:mm'
showTimeSelect
selected={
initialValues.period_to
? new Date(
dayjs(initialValues.period_to).format(
'YYYY-MM-DD hh:mm',
),
)
: null
}
onChange={(date) =>
setInitialValues({ ...initialValues, period_to: date })
}
/>
</FormField> </FormField>
<BaseDivider /> <BaseDivider />
@ -133,7 +155,7 @@ const EditGalleriesPage = () => {
color='danger' color='danger'
outline outline
label='Cancel' label='Cancel'
onClick={() => router.push('/galleries/galleries-list')} onClick={() => router.push('/periods/periods-list')}
/> />
</BaseButtons> </BaseButtons>
</Form> </Form>
@ -144,12 +166,12 @@ const EditGalleriesPage = () => {
); );
}; };
EditGalleriesPage.getLayout = function getLayout(page: ReactElement) { EditPeriodsPage.getLayout = function getLayout(page: ReactElement) {
return ( return (
<LayoutAuthenticated permission={'UPDATE_GALLERIES'}> <LayoutAuthenticated permission={'UPDATE_PERIODS'}>
{page} {page}
</LayoutAuthenticated> </LayoutAuthenticated>
); );
}; };
export default EditGalleriesPage; export default EditPeriodsPage;

View File

@ -7,18 +7,18 @@ import LayoutAuthenticated from '../../layouts/Authenticated';
import SectionMain from '../../components/SectionMain'; import SectionMain from '../../components/SectionMain';
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'; import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton';
import { getPageTitle } from '../../config'; import { getPageTitle } from '../../config';
import TableGalleries from '../../components/Galleries/TableGalleries'; import TablePeriods from '../../components/Periods/TablePeriods';
import BaseButton from '../../components/BaseButton'; import BaseButton from '../../components/BaseButton';
import axios from 'axios'; import axios from 'axios';
import Link from 'next/link'; import Link from 'next/link';
import { useAppDispatch, useAppSelector } from '../../stores/hooks'; import { useAppDispatch, useAppSelector } from '../../stores/hooks';
import CardBoxModal from '../../components/CardBoxModal'; import CardBoxModal from '../../components/CardBoxModal';
import DragDropFilePicker from '../../components/DragDropFilePicker'; import DragDropFilePicker from '../../components/DragDropFilePicker';
import { setRefetch, uploadCsv } from '../../stores/galleries/galleriesSlice'; import { setRefetch, uploadCsv } from '../../stores/periods/periodsSlice';
import { hasPermission } from '../../helpers/userPermissions'; import { hasPermission } from '../../helpers/userPermissions';
const GalleriesTablesPage = () => { const PeriodsTablesPage = () => {
const [filterItems, setFilterItems] = useState([]); const [filterItems, setFilterItems] = useState([]);
const [csvFile, setCsvFile] = useState<File | null>(null); const [csvFile, setCsvFile] = useState<File | null>(null);
const [isModalActive, setIsModalActive] = useState(false); const [isModalActive, setIsModalActive] = useState(false);
@ -31,11 +31,14 @@ const GalleriesTablesPage = () => {
const [filters] = useState([ const [filters] = useState([
{ label: 'Name', title: 'name' }, { label: 'Name', title: 'name' },
{ label: 'Period From', title: 'period_from', date: 'true' },
{ label: 'Period To', title: 'period_to', date: 'true' },
{ label: 'Archival Items', title: 'archival_items' }, { label: 'Archival Items', title: 'archival_items' },
]); ]);
const hasCreatePermission = const hasCreatePermission =
currentUser && hasPermission(currentUser, 'CREATE_GALLERIES'); currentUser && hasPermission(currentUser, 'CREATE_PERIODS');
const addFilter = () => { const addFilter = () => {
const newItem = { const newItem = {
@ -51,9 +54,9 @@ const GalleriesTablesPage = () => {
setFilterItems([...filterItems, newItem]); setFilterItems([...filterItems, newItem]);
}; };
const getGalleriesCSV = async () => { const getPeriodsCSV = async () => {
const response = await axios({ const response = await axios({
url: '/galleries?filetype=csv', url: '/periods?filetype=csv',
method: 'GET', method: 'GET',
responseType: 'blob', responseType: 'blob',
}); });
@ -61,7 +64,7 @@ const GalleriesTablesPage = () => {
const blob = new Blob([response.data], { type: type }); const blob = new Blob([response.data], { type: type });
const link = document.createElement('a'); const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob); link.href = window.URL.createObjectURL(blob);
link.download = 'galleriesCSV.csv'; link.download = 'periodsCSV.csv';
link.click(); link.click();
}; };
@ -81,12 +84,12 @@ const GalleriesTablesPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Galleries')}</title> <title>{getPageTitle('Periods')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton <SectionTitleLineWithButton
icon={mdiChartTimelineVariant} icon={mdiChartTimelineVariant}
title='Galleries' title='Periods'
main main
> >
{''} {''}
@ -95,7 +98,7 @@ const GalleriesTablesPage = () => {
{hasCreatePermission && ( {hasCreatePermission && (
<BaseButton <BaseButton
className={'mr-3'} className={'mr-3'}
href={'/galleries/galleries-new'} href={'/periods/periods-new'}
color='info' color='info'
label='New Item' label='New Item'
/> />
@ -111,7 +114,7 @@ const GalleriesTablesPage = () => {
className={'mr-3'} className={'mr-3'}
color='info' color='info'
label='Download CSV' label='Download CSV'
onClick={getGalleriesCSV} onClick={getPeriodsCSV}
/> />
{hasCreatePermission && ( {hasCreatePermission && (
@ -128,7 +131,7 @@ const GalleriesTablesPage = () => {
</CardBox> </CardBox>
<CardBox className='mb-6' hasTable> <CardBox className='mb-6' hasTable>
<TableGalleries <TablePeriods
filterItems={filterItems} filterItems={filterItems}
setFilterItems={setFilterItems} setFilterItems={setFilterItems}
filters={filters} filters={filters}
@ -155,12 +158,12 @@ const GalleriesTablesPage = () => {
); );
}; };
GalleriesTablesPage.getLayout = function getLayout(page: ReactElement) { PeriodsTablesPage.getLayout = function getLayout(page: ReactElement) {
return ( return (
<LayoutAuthenticated permission={'READ_GALLERIES'}> <LayoutAuthenticated permission={'READ_PERIODS'}>
{page} {page}
</LayoutAuthenticated> </LayoutAuthenticated>
); );
}; };
export default GalleriesTablesPage; export default PeriodsTablesPage;

View File

@ -27,7 +27,7 @@ import { SelectField } from '../../components/SelectField';
import { SelectFieldMany } from '../../components/SelectFieldMany'; import { SelectFieldMany } from '../../components/SelectFieldMany';
import { RichTextField } from '../../components/RichTextField'; import { RichTextField } from '../../components/RichTextField';
import { create } from '../../stores/galleries/galleriesSlice'; import { create } from '../../stores/periods/periodsSlice';
import { useAppDispatch } from '../../stores/hooks'; import { useAppDispatch } from '../../stores/hooks';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import moment from 'moment'; import moment from 'moment';
@ -37,16 +37,18 @@ const initialValues = {
archival_items: [], archival_items: [],
background_image: [], period_from: '',
period_to: '',
}; };
const GalleriesNew = () => { const PeriodsNew = () => {
const router = useRouter(); const router = useRouter();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const handleSubmit = async (data) => { const handleSubmit = async (data) => {
await dispatch(create(data)); await dispatch(create(data));
await router.push('/galleries/galleries-list'); await router.push('/periods/periods-list');
}; };
return ( return (
<> <>
@ -81,20 +83,20 @@ const GalleriesNew = () => {
></Field> ></Field>
</FormField> </FormField>
<FormField> <FormField label='Period From'>
<Field <Field
label='Background Image' type='datetime-local'
color='info' name='period_from'
icon={mdiUpload} placeholder='Period From'
path={'galleries/background_image'} />
name='background_image' </FormField>
id='background_image'
schema={{ <FormField label='Period To'>
size: undefined, <Field
formats: undefined, type='datetime-local'
}} name='period_to'
component={FormImagePicker} placeholder='Period To'
></Field> />
</FormField> </FormField>
<BaseDivider /> <BaseDivider />
@ -106,7 +108,7 @@ const GalleriesNew = () => {
color='danger' color='danger'
outline outline
label='Cancel' label='Cancel'
onClick={() => router.push('/galleries/galleries-list')} onClick={() => router.push('/periods/periods-list')}
/> />
</BaseButtons> </BaseButtons>
</Form> </Form>
@ -117,12 +119,12 @@ const GalleriesNew = () => {
); );
}; };
GalleriesNew.getLayout = function getLayout(page: ReactElement) { PeriodsNew.getLayout = function getLayout(page: ReactElement) {
return ( return (
<LayoutAuthenticated permission={'CREATE_GALLERIES'}> <LayoutAuthenticated permission={'CREATE_PERIODS'}>
{page} {page}
</LayoutAuthenticated> </LayoutAuthenticated>
); );
}; };
export default GalleriesNew; export default PeriodsNew;

View File

@ -7,18 +7,18 @@ import LayoutAuthenticated from '../../layouts/Authenticated';
import SectionMain from '../../components/SectionMain'; import SectionMain from '../../components/SectionMain';
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton'; import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton';
import { getPageTitle } from '../../config'; import { getPageTitle } from '../../config';
import TableGalleries from '../../components/Galleries/TableGalleries'; import TablePeriods from '../../components/Periods/TablePeriods';
import BaseButton from '../../components/BaseButton'; import BaseButton from '../../components/BaseButton';
import axios from 'axios'; import axios from 'axios';
import Link from 'next/link'; import Link from 'next/link';
import { useAppDispatch, useAppSelector } from '../../stores/hooks'; import { useAppDispatch, useAppSelector } from '../../stores/hooks';
import CardBoxModal from '../../components/CardBoxModal'; import CardBoxModal from '../../components/CardBoxModal';
import DragDropFilePicker from '../../components/DragDropFilePicker'; import DragDropFilePicker from '../../components/DragDropFilePicker';
import { setRefetch, uploadCsv } from '../../stores/galleries/galleriesSlice'; import { setRefetch, uploadCsv } from '../../stores/periods/periodsSlice';
import { hasPermission } from '../../helpers/userPermissions'; import { hasPermission } from '../../helpers/userPermissions';
const GalleriesTablesPage = () => { const PeriodsTablesPage = () => {
const [filterItems, setFilterItems] = useState([]); const [filterItems, setFilterItems] = useState([]);
const [csvFile, setCsvFile] = useState<File | null>(null); const [csvFile, setCsvFile] = useState<File | null>(null);
const [isModalActive, setIsModalActive] = useState(false); const [isModalActive, setIsModalActive] = useState(false);
@ -31,11 +31,14 @@ const GalleriesTablesPage = () => {
const [filters] = useState([ const [filters] = useState([
{ label: 'Name', title: 'name' }, { label: 'Name', title: 'name' },
{ label: 'Period From', title: 'period_from', date: 'true' },
{ label: 'Period To', title: 'period_to', date: 'true' },
{ label: 'Archival Items', title: 'archival_items' }, { label: 'Archival Items', title: 'archival_items' },
]); ]);
const hasCreatePermission = const hasCreatePermission =
currentUser && hasPermission(currentUser, 'CREATE_GALLERIES'); currentUser && hasPermission(currentUser, 'CREATE_PERIODS');
const addFilter = () => { const addFilter = () => {
const newItem = { const newItem = {
@ -51,9 +54,9 @@ const GalleriesTablesPage = () => {
setFilterItems([...filterItems, newItem]); setFilterItems([...filterItems, newItem]);
}; };
const getGalleriesCSV = async () => { const getPeriodsCSV = async () => {
const response = await axios({ const response = await axios({
url: '/galleries?filetype=csv', url: '/periods?filetype=csv',
method: 'GET', method: 'GET',
responseType: 'blob', responseType: 'blob',
}); });
@ -61,7 +64,7 @@ const GalleriesTablesPage = () => {
const blob = new Blob([response.data], { type: type }); const blob = new Blob([response.data], { type: type });
const link = document.createElement('a'); const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob); link.href = window.URL.createObjectURL(blob);
link.download = 'galleriesCSV.csv'; link.download = 'periodsCSV.csv';
link.click(); link.click();
}; };
@ -81,12 +84,12 @@ const GalleriesTablesPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Galleries')}</title> <title>{getPageTitle('Periods')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton <SectionTitleLineWithButton
icon={mdiChartTimelineVariant} icon={mdiChartTimelineVariant}
title='Galleries' title='Periods'
main main
> >
{''} {''}
@ -95,7 +98,7 @@ const GalleriesTablesPage = () => {
{hasCreatePermission && ( {hasCreatePermission && (
<BaseButton <BaseButton
className={'mr-3'} className={'mr-3'}
href={'/galleries/galleries-new'} href={'/periods/periods-new'}
color='info' color='info'
label='New Item' label='New Item'
/> />
@ -111,7 +114,7 @@ const GalleriesTablesPage = () => {
className={'mr-3'} className={'mr-3'}
color='info' color='info'
label='Download CSV' label='Download CSV'
onClick={getGalleriesCSV} onClick={getPeriodsCSV}
/> />
{hasCreatePermission && ( {hasCreatePermission && (
@ -127,7 +130,7 @@ const GalleriesTablesPage = () => {
</div> </div>
</CardBox> </CardBox>
<CardBox className='mb-6' hasTable> <CardBox className='mb-6' hasTable>
<TableGalleries <TablePeriods
filterItems={filterItems} filterItems={filterItems}
setFilterItems={setFilterItems} setFilterItems={setFilterItems}
filters={filters} filters={filters}
@ -154,12 +157,12 @@ const GalleriesTablesPage = () => {
); );
}; };
GalleriesTablesPage.getLayout = function getLayout(page: ReactElement) { PeriodsTablesPage.getLayout = function getLayout(page: ReactElement) {
return ( return (
<LayoutAuthenticated permission={'READ_GALLERIES'}> <LayoutAuthenticated permission={'READ_PERIODS'}>
{page} {page}
</LayoutAuthenticated> </LayoutAuthenticated>
); );
}; };
export default GalleriesTablesPage; export default PeriodsTablesPage;

View File

@ -5,7 +5,7 @@ import 'react-datepicker/dist/react-datepicker.css';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useAppDispatch, useAppSelector } from '../../stores/hooks'; import { useAppDispatch, useAppSelector } from '../../stores/hooks';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { fetch } from '../../stores/galleries/galleriesSlice'; import { fetch } from '../../stores/periods/periodsSlice';
import { saveFile } from '../../helpers/fileSaver'; import { saveFile } from '../../helpers/fileSaver';
import dataFormatter from '../../helpers/dataFormatter'; import dataFormatter from '../../helpers/dataFormatter';
import ImageField from '../../components/ImageField'; import ImageField from '../../components/ImageField';
@ -20,10 +20,10 @@ import { mdiChartTimelineVariant } from '@mdi/js';
import { SwitchField } from '../../components/SwitchField'; import { SwitchField } from '../../components/SwitchField';
import FormField from '../../components/FormField'; import FormField from '../../components/FormField';
const GalleriesView = () => { const PeriodsView = () => {
const router = useRouter(); const router = useRouter();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { galleries } = useAppSelector((state) => state.galleries); const { periods } = useAppSelector((state) => state.periods);
const { id } = router.query; const { id } = router.query;
@ -39,24 +39,24 @@ const GalleriesView = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('View galleries')}</title> <title>{getPageTitle('View periods')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton <SectionTitleLineWithButton
icon={mdiChartTimelineVariant} icon={mdiChartTimelineVariant}
title={removeLastCharacter('View galleries')} title={removeLastCharacter('View periods')}
main main
> >
<BaseButton <BaseButton
color='info' color='info'
label='Edit' label='Edit'
href={`/galleries/galleries-edit/?id=${id}`} href={`/periods/periods-edit/?id=${id}`}
/> />
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
<div className={'mb-4'}> <div className={'mb-4'}>
<p className={'block font-bold mb-2'}>Name</p> <p className={'block font-bold mb-2'}>Name</p>
<p>{galleries?.name}</p> <p>{periods?.name}</p>
</div> </div>
<> <>
@ -74,16 +74,12 @@ const GalleriesView = () => {
<th>Description</th> <th>Description</th>
<th>Is Published</th> <th>Is Published</th>
<th>Period From</th>
<th>Period To</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{galleries.archival_items && {periods.archival_items &&
Array.isArray(galleries.archival_items) && Array.isArray(periods.archival_items) &&
galleries.archival_items.map((item: any) => ( periods.archival_items.map((item: any) => (
<tr <tr
key={item.id} key={item.id}
onClick={() => onClick={() =>
@ -99,42 +95,61 @@ const GalleriesView = () => {
<td data-label='isPublished'> <td data-label='isPublished'>
{dataFormatter.booleanFormatter(item.isPublished)} {dataFormatter.booleanFormatter(item.isPublished)}
</td> </td>
<td data-label='period_from'>
{dataFormatter.dateFormatter(item.period_from)}
</td>
<td data-label='period_to'>{item.period_to}</td>
</tr> </tr>
))} ))}
</tbody> </tbody>
</table> </table>
</div> </div>
{!galleries?.archival_items?.length && ( {!periods?.archival_items?.length && (
<div className={'text-center py-4'}>No data</div> <div className={'text-center py-4'}>No data</div>
)} )}
</CardBox> </CardBox>
</> </>
<div className={'mb-4'}> <FormField label='Period From'>
<p className={'block font-bold mb-2'}>Background Image</p> {periods.period_from ? (
{galleries?.background_image?.length ? ( <DatePicker
<ImageField dateFormat='yyyy-MM-dd hh:mm'
name={'background_image'} showTimeSelect
image={galleries?.background_image} selected={
className='w-20 h-20' periods.period_from
? new Date(
dayjs(periods.period_from).format('YYYY-MM-DD hh:mm'),
)
: null
}
disabled
/> />
) : ( ) : (
<p>No Background Image</p> <p>No Period From</p>
)} )}
</div> </FormField>
<FormField label='Period To'>
{periods.period_to ? (
<DatePicker
dateFormat='yyyy-MM-dd hh:mm'
showTimeSelect
selected={
periods.period_to
? new Date(
dayjs(periods.period_to).format('YYYY-MM-DD hh:mm'),
)
: null
}
disabled
/>
) : (
<p>No Period To</p>
)}
</FormField>
<BaseDivider /> <BaseDivider />
<BaseButton <BaseButton
color='info' color='info'
label='Back' label='Back'
onClick={() => router.push('/galleries/galleries-list')} onClick={() => router.push('/periods/periods-list')}
/> />
</CardBox> </CardBox>
</SectionMain> </SectionMain>
@ -142,12 +157,12 @@ const GalleriesView = () => {
); );
}; };
GalleriesView.getLayout = function getLayout(page: ReactElement) { PeriodsView.getLayout = function getLayout(page: ReactElement) {
return ( return (
<LayoutAuthenticated permission={'READ_GALLERIES'}> <LayoutAuthenticated permission={'READ_PERIODS'}>
{page} {page}
</LayoutAuthenticated> </LayoutAuthenticated>
); );
}; };
export default GalleriesView; export default PeriodsView;

View File

@ -7,7 +7,7 @@ import {
} from '../../helpers/notifyStateHandler'; } from '../../helpers/notifyStateHandler';
interface MainState { interface MainState {
galleries: any; periods: any;
loading: boolean; loading: boolean;
count: number; count: number;
refetch: boolean; refetch: boolean;
@ -20,7 +20,7 @@ interface MainState {
} }
const initialState: MainState = { const initialState: MainState = {
galleries: [], periods: [],
loading: false, loading: false,
count: 0, count: 0,
refetch: false, refetch: false,
@ -32,19 +32,19 @@ const initialState: MainState = {
}, },
}; };
export const fetch = createAsyncThunk('galleries/fetch', async (data: any) => { export const fetch = createAsyncThunk('periods/fetch', async (data: any) => {
const { id, query } = data; const { id, query } = data;
const result = await axios.get(`galleries${query || (id ? `/${id}` : '')}`); const result = await axios.get(`periods${query || (id ? `/${id}` : '')}`);
return id return id
? result.data ? result.data
: { rows: result.data.rows, count: result.data.count }; : { rows: result.data.rows, count: result.data.count };
}); });
export const deleteItemsByIds = createAsyncThunk( export const deleteItemsByIds = createAsyncThunk(
'galleries/deleteByIds', 'periods/deleteByIds',
async (data: any, { rejectWithValue }) => { async (data: any, { rejectWithValue }) => {
try { try {
await axios.post('galleries/deleteByIds', { data }); await axios.post('periods/deleteByIds', { data });
} catch (error) { } catch (error) {
if (!error.response) { if (!error.response) {
throw error; throw error;
@ -56,10 +56,10 @@ export const deleteItemsByIds = createAsyncThunk(
); );
export const deleteItem = createAsyncThunk( export const deleteItem = createAsyncThunk(
'galleries/deleteGalleries', 'periods/deletePeriods',
async (id: string, { rejectWithValue }) => { async (id: string, { rejectWithValue }) => {
try { try {
await axios.delete(`galleries/${id}`); await axios.delete(`periods/${id}`);
} catch (error) { } catch (error) {
if (!error.response) { if (!error.response) {
throw error; throw error;
@ -71,10 +71,10 @@ export const deleteItem = createAsyncThunk(
); );
export const create = createAsyncThunk( export const create = createAsyncThunk(
'galleries/createGalleries', 'periods/createPeriods',
async (data: any, { rejectWithValue }) => { async (data: any, { rejectWithValue }) => {
try { try {
const result = await axios.post('galleries', { data }); const result = await axios.post('periods', { data });
return result.data; return result.data;
} catch (error) { } catch (error) {
if (!error.response) { if (!error.response) {
@ -87,14 +87,14 @@ export const create = createAsyncThunk(
); );
export const uploadCsv = createAsyncThunk( export const uploadCsv = createAsyncThunk(
'galleries/uploadCsv', 'periods/uploadCsv',
async (file: File, { rejectWithValue }) => { async (file: File, { rejectWithValue }) => {
try { try {
const data = new FormData(); const data = new FormData();
data.append('file', file); data.append('file', file);
data.append('filename', file.name); data.append('filename', file.name);
const result = await axios.post('galleries/bulk-import', data, { const result = await axios.post('periods/bulk-import', data, {
headers: { headers: {
'Content-Type': 'multipart/form-data', 'Content-Type': 'multipart/form-data',
}, },
@ -112,10 +112,10 @@ export const uploadCsv = createAsyncThunk(
); );
export const update = createAsyncThunk( export const update = createAsyncThunk(
'galleries/updateGalleries', 'periods/updatePeriods',
async (payload: any, { rejectWithValue }) => { async (payload: any, { rejectWithValue }) => {
try { try {
const result = await axios.put(`galleries/${payload.id}`, { const result = await axios.put(`periods/${payload.id}`, {
id: payload.id, id: payload.id,
data: payload.data, data: payload.data,
}); });
@ -130,8 +130,8 @@ export const update = createAsyncThunk(
}, },
); );
export const galleriesSlice = createSlice({ export const periodsSlice = createSlice({
name: 'galleries', name: 'periods',
initialState, initialState,
reducers: { reducers: {
setRefetch: (state, action: PayloadAction<boolean>) => { setRefetch: (state, action: PayloadAction<boolean>) => {
@ -150,10 +150,10 @@ export const galleriesSlice = createSlice({
builder.addCase(fetch.fulfilled, (state, action) => { builder.addCase(fetch.fulfilled, (state, action) => {
if (action.payload.rows && action.payload.count >= 0) { if (action.payload.rows && action.payload.count >= 0) {
state.galleries = action.payload.rows; state.periods = action.payload.rows;
state.count = action.payload.count; state.count = action.payload.count;
} else { } else {
state.galleries = action.payload; state.periods = action.payload;
} }
state.loading = false; state.loading = false;
}); });
@ -165,7 +165,7 @@ export const galleriesSlice = createSlice({
builder.addCase(deleteItemsByIds.fulfilled, (state) => { builder.addCase(deleteItemsByIds.fulfilled, (state) => {
state.loading = false; state.loading = false;
fulfilledNotify(state, 'Galleries has been deleted'); fulfilledNotify(state, 'Periods has been deleted');
}); });
builder.addCase(deleteItemsByIds.rejected, (state, action) => { builder.addCase(deleteItemsByIds.rejected, (state, action) => {
@ -180,7 +180,7 @@ export const galleriesSlice = createSlice({
builder.addCase(deleteItem.fulfilled, (state) => { builder.addCase(deleteItem.fulfilled, (state) => {
state.loading = false; state.loading = false;
fulfilledNotify(state, `${'Galleries'.slice(0, -1)} has been deleted`); fulfilledNotify(state, `${'Periods'.slice(0, -1)} has been deleted`);
}); });
builder.addCase(deleteItem.rejected, (state, action) => { builder.addCase(deleteItem.rejected, (state, action) => {
@ -199,7 +199,7 @@ export const galleriesSlice = createSlice({
builder.addCase(create.fulfilled, (state) => { builder.addCase(create.fulfilled, (state) => {
state.loading = false; state.loading = false;
fulfilledNotify(state, `${'Galleries'.slice(0, -1)} has been created`); fulfilledNotify(state, `${'Periods'.slice(0, -1)} has been created`);
}); });
builder.addCase(update.pending, (state) => { builder.addCase(update.pending, (state) => {
@ -208,7 +208,7 @@ export const galleriesSlice = createSlice({
}); });
builder.addCase(update.fulfilled, (state) => { builder.addCase(update.fulfilled, (state) => {
state.loading = false; state.loading = false;
fulfilledNotify(state, `${'Galleries'.slice(0, -1)} has been updated`); fulfilledNotify(state, `${'Periods'.slice(0, -1)} has been updated`);
}); });
builder.addCase(update.rejected, (state, action) => { builder.addCase(update.rejected, (state, action) => {
state.loading = false; state.loading = false;
@ -221,7 +221,7 @@ export const galleriesSlice = createSlice({
}); });
builder.addCase(uploadCsv.fulfilled, (state) => { builder.addCase(uploadCsv.fulfilled, (state) => {
state.loading = false; state.loading = false;
fulfilledNotify(state, 'Galleries has been uploaded'); fulfilledNotify(state, 'Periods has been uploaded');
}); });
builder.addCase(uploadCsv.rejected, (state, action) => { builder.addCase(uploadCsv.rejected, (state, action) => {
state.loading = false; state.loading = false;
@ -231,6 +231,6 @@ export const galleriesSlice = createSlice({
}); });
// Action creators are generated for each case reducer function // Action creators are generated for each case reducer function
export const { setRefetch } = galleriesSlice.actions; export const { setRefetch } = periodsSlice.actions;
export default galleriesSlice.reducer; export default periodsSlice.reducer;

View File

@ -6,7 +6,7 @@ import openAiSlice from './openAiSlice';
import usersSlice from './users/usersSlice'; import usersSlice from './users/usersSlice';
import archival_itemsSlice from './archival_items/archival_itemsSlice'; import archival_itemsSlice from './archival_items/archival_itemsSlice';
import galleriesSlice from './galleries/galleriesSlice'; import periodsSlice from './periods/periodsSlice';
import tagsSlice from './tags/tagsSlice'; import tagsSlice from './tags/tagsSlice';
import rolesSlice from './roles/rolesSlice'; import rolesSlice from './roles/rolesSlice';
import permissionsSlice from './permissions/permissionsSlice'; import permissionsSlice from './permissions/permissionsSlice';
@ -20,7 +20,7 @@ export const store = configureStore({
users: usersSlice, users: usersSlice,
archival_items: archival_itemsSlice, archival_items: archival_itemsSlice,
galleries: galleriesSlice, periods: periodsSlice,
tags: tagsSlice, tags: tagsSlice,
roles: rolesSlice, roles: rolesSlice,
permissions: permissionsSlice, permissions: permissionsSlice,