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 = {
admin_pass: "df170051",
admin_pass: "<%= @app_admin_password %>",
admin_email: "admin@flatlogic.com",
schema_encryption_key: process.env.SCHEMA_ENCRYPTION_KEY || '',
project_uuid: 'df170051-a138-4641-ad0d-a5ac07a19601',
<% if @schema['project']['@project_uuid'] %>
project_uuid: '<%= @schema['project']['@project_uuid'] %>',
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_username: process.env.GITEA_USERNAME || 'admin',
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 initRepo() {
const projectId = '34916';
const projectId = '<%= @schema['project']['project_id'] %>';
return VCS.initRepo(projectId);
}
@ -51,4 +51,4 @@ startServer();
// Now perform Git check
runGitCheck();
module.exports = app;
module.exports = app;

View File

@ -19,8 +19,6 @@ module.exports = class Archival_itemsDBApi {
description: data.description || null,
isPublished: data.isPublished || false,
period_from: data.period_from || null,
period_to: data.period_to || null,
importHash: data.importHash || null,
createdById: currentUser.id,
updatedById: currentUser.id,
@ -57,8 +55,6 @@ module.exports = class Archival_itemsDBApi {
description: item.description || null,
isPublished: item.isPublished || false,
period_from: item.period_from || null,
period_to: item.period_to || null,
importHash: item.importHash || null,
createdById: currentUser.id,
updatedById: currentUser.id,
@ -108,11 +104,6 @@ module.exports = class Archival_itemsDBApi {
if (data.isPublished !== undefined)
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;
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) {
where = {
...where,

View File

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

View File

@ -5,8 +5,8 @@ const bcrypt = require('bcrypt');
const moment = require('moment');
module.exports = function (sequelize, DataTypes) {
const galleries = sequelize.define(
'galleries',
const periods = sequelize.define(
'periods',
{
id: {
type: DataTypes.UUID,
@ -18,6 +18,14 @@ module.exports = function (sequelize, DataTypes) {
type: DataTypes.TEXT,
},
period_from: {
type: DataTypes.DATE,
},
period_to: {
type: DataTypes.DATE,
},
importHash: {
type: DataTypes.STRING(255),
allowNull: true,
@ -31,47 +39,37 @@ module.exports = function (sequelize, DataTypes) {
},
);
galleries.associate = (db) => {
db.galleries.belongsToMany(db.archival_items, {
periods.associate = (db) => {
db.periods.belongsToMany(db.archival_items, {
as: 'archival_items',
foreignKey: {
name: 'galleries_archival_itemsId',
name: 'periods_archival_itemsId',
},
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',
foreignKey: {
name: 'galleries_archival_itemsId',
name: 'periods_archival_itemsId',
},
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
//end loop
db.galleries.hasMany(db.file, {
as: 'background_image',
foreignKey: 'belongsToId',
constraints: false,
scope: {
belongsTo: db.galleries.getTableName(),
belongsToColumn: 'background_image',
},
});
db.galleries.belongsTo(db.users, {
db.periods.belongsTo(db.users, {
as: 'createdBy',
});
db.galleries.belongsTo(db.users, {
db.periods.belongsTo(db.users, {
as: 'updatedBy',
});
};
return galleries;
return periods;
};

View File

@ -72,7 +72,7 @@ module.exports = {
const entities = [
'users',
'archival_items',
'galleries',
'periods',
'tags',
'roles',
'permissions',
@ -164,25 +164,25 @@ primary key ("roles_permissionsId", "permissionId")
createdAt,
updatedAt,
roles_permissionsId: getId('User'),
permissionId: getId('CREATE_GALLERIES'),
permissionId: getId('CREATE_PERIODS'),
},
{
createdAt,
updatedAt,
roles_permissionsId: getId('User'),
permissionId: getId('READ_GALLERIES'),
permissionId: getId('READ_PERIODS'),
},
{
createdAt,
updatedAt,
roles_permissionsId: getId('User'),
permissionId: getId('UPDATE_GALLERIES'),
permissionId: getId('UPDATE_PERIODS'),
},
{
createdAt,
updatedAt,
roles_permissionsId: getId('User'),
permissionId: getId('DELETE_GALLERIES'),
permissionId: getId('DELETE_PERIODS'),
},
{
@ -271,25 +271,25 @@ primary key ("roles_permissionsId", "permissionId")
createdAt,
updatedAt,
roles_permissionsId: getId('Administrator'),
permissionId: getId('CREATE_GALLERIES'),
permissionId: getId('CREATE_PERIODS'),
},
{
createdAt,
updatedAt,
roles_permissionsId: getId('Administrator'),
permissionId: getId('READ_GALLERIES'),
permissionId: getId('READ_PERIODS'),
},
{
createdAt,
updatedAt,
roles_permissionsId: getId('Administrator'),
permissionId: getId('UPDATE_GALLERIES'),
permissionId: getId('UPDATE_PERIODS'),
},
{
createdAt,
updatedAt,
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 galleriesRoutes = require('./routes/galleries');
const periodsRoutes = require('./routes/periods');
const tagsRoutes = require('./routes/tags');
@ -107,9 +107,9 @@ app.use(
);
app.use(
'/api/galleries',
'/api/periods',
passport.authenticate('jwt', { session: false }),
galleriesRoutes,
periodsRoutes,
);
app.use(

View File

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

View File

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

View File

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

View File

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

View File

@ -127,28 +127,6 @@ const CardArchival_items = ({
</dd>
</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'>
<dt className=' text-gray-500 dark:text-dark-600'>Tags</dt>
<dd className='flex items-start gap-x-2'>

View File

@ -89,18 +89,6 @@ const ListArchival_items = ({
</p>
</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'}>
<p className={'text-xs text-gray-500 '}>Tags</p>
<p className={'line-clamp-2'}>

View File

@ -96,34 +96,6 @@ export const loadColumns = async (
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',
headerName: 'Tags',

View File

@ -11,7 +11,7 @@ import Link from 'next/link';
import { hasPermission } from '../../helpers/userPermissions';
type Props = {
galleries: any[];
periods: any[];
loading: boolean;
onDelete: (id: string) => void;
currentPage: number;
@ -19,8 +19,8 @@ type Props = {
onPageChange: (page: number) => void;
};
const CardGalleries = ({
galleries,
const CardPeriods = ({
periods,
loading,
onDelete,
currentPage,
@ -36,7 +36,7 @@ const CardGalleries = ({
const focusRing = useAppSelector((state) => state.style.focusRingColor);
const currentUser = useAppSelector((state) => state.auth.currentUser);
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_GALLERIES');
const hasUpdatePermission = hasPermission(currentUser, 'UPDATE_PERIODS');
return (
<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'
>
{!loading &&
galleries.map((item, index) => (
periods.map((item, index) => (
<li
key={item.id}
className={`overflow-hidden ${
@ -56,27 +56,21 @@ const CardGalleries = ({
}`}
>
<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
href={`/galleries/galleries-view/?id=${item.id}`}
className={'cursor-pointer'}
href={`/periods/periods-view/?id=${item.id}`}
className='text-lg font-bold leading-6 line-clamp-1'
>
<ImageField
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>
{item.id}
</Link>
<div className='ml-auto md:absolute md:top-0 md:right-0 '>
<div className='ml-auto '>
<ListActionsPopover
onDelete={onDelete}
itemId={item.id}
pathEdit={`/galleries/galleries-edit/?id=${item.id}`}
pathView={`/galleries/galleries-view/?id=${item.id}`}
pathEdit={`/periods/periods-edit/?id=${item.id}`}
pathView={`/periods/periods-view/?id=${item.id}`}
hasUpdatePermission={hasUpdatePermission}
/>
</div>
@ -104,22 +98,29 @@ const CardGalleries = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>
Background Image
Period From
</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium'>
<ImageField
name={'Avatar'}
image={item.background_image}
className='mx-auto w-8 h-8'
/>
<div className='font-medium line-clamp-4'>
{dataFormatter.dateTimeFormatter(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'>
{dataFormatter.dateTimeFormatter(item.period_to)}
</div>
</dd>
</div>
</dl>
</li>
))}
{!loading && galleries.length === 0 && (
{!loading && periods.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p>
</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';
type Props = {
galleries: any[];
periods: any[];
loading: boolean;
onDelete: (id: string) => void;
currentPage: number;
@ -20,8 +20,8 @@ type Props = {
onPageChange: (page: number) => void;
};
const ListGalleries = ({
galleries,
const ListPeriods = ({
periods,
loading,
onDelete,
currentPage,
@ -29,7 +29,7 @@ const ListGalleries = ({
onPageChange,
}: Props) => {
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 bgColor = useAppSelector((state) => state.style.cardsColor);
@ -39,23 +39,14 @@ const ListGalleries = ({
<div className='relative overflow-x-auto p-4 space-y-4'>
{loading && <LoadingSpinner />}
{!loading &&
galleries.map((item) => (
periods.map((item) => (
<div key={item.id}>
<CardBox hasTable isList className={'rounded shadow-none'}>
<div
className={`flex rounded dark:bg-dark-900 border border-stone-300 items-center overflow-hidden`}
>
<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
href={`/galleries/galleries-view/?id=${item.id}`}
href={`/periods/periods-view/?id=${item.id}`}
className={
'flex-1 px-4 py-6 h-24 flex divide-x-2 divide-stone-300 items-center overflow-hidden`}> dark:divide-dark-700 overflow-x-auto'
}
@ -77,28 +68,31 @@ const ListGalleries = ({
</div>
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>
Background Image
<p className={'text-xs text-gray-500 '}>Period From</p>
<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>
<ImageField
name={'Avatar'}
image={item.background_image}
className='mx-auto w-8 h-8'
/>
</div>
</Link>
<ListActionsPopover
onDelete={onDelete}
itemId={item.id}
pathEdit={`/galleries/galleries-edit/?id=${item.id}`}
pathView={`/galleries/galleries-view/?id=${item.id}`}
pathEdit={`/periods/periods-edit/?id=${item.id}`}
pathView={`/periods/periods-view/?id=${item.id}`}
hasUpdatePermission={hasUpdatePermission}
/>
</div>
</CardBox>
</div>
))}
{!loading && galleries.length === 0 && (
{!loading && periods.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p>
</div>
@ -115,4 +109,4 @@ const ListGalleries = ({
);
};
export default ListGalleries;
export default ListPeriods;

View File

@ -10,19 +10,19 @@ import {
deleteItem,
setRefetch,
deleteItemsByIds,
} from '../../stores/galleries/galleriesSlice';
} from '../../stores/periods/periodsSlice';
import { useAppDispatch, useAppSelector } from '../../stores/hooks';
import { useRouter } from 'next/router';
import { Field, Form, Formik } from 'formik';
import { DataGrid, GridColDef } from '@mui/x-data-grid';
import { loadColumns } from './configureGalleriesCols';
import { loadColumns } from './configurePeriodsCols';
import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter';
import { dataGridStyles } from '../../styles';
const perPage = 10;
const TableSampleGalleries = ({
const TableSamplePeriods = ({
filterItems,
setFilterItems,
filters,
@ -47,12 +47,12 @@ const TableSampleGalleries = ({
]);
const {
galleries,
periods,
loading,
count,
notify: galleriesNotify,
notify: periodsNotify,
refetch,
} = useAppSelector((state) => state.galleries);
} = useAppSelector((state) => state.periods);
const { currentUser } = useAppSelector((state) => state.auth);
const focusRing = useAppSelector((state) => state.style.focusRingColor);
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
@ -73,13 +73,10 @@ const TableSampleGalleries = ({
};
useEffect(() => {
if (galleriesNotify.showNotification) {
notify(
galleriesNotify.typeNotification,
galleriesNotify.textNotification,
);
if (periodsNotify.showNotification) {
notify(periodsNotify.typeNotification, periodsNotify.textNotification);
}
}, [galleriesNotify.showNotification]);
}, [periodsNotify.showNotification]);
useEffect(() => {
if (!currentUser) return;
@ -184,7 +181,7 @@ const TableSampleGalleries = ({
useEffect(() => {
if (!currentUser) return;
loadColumns(handleDeleteModalAction, `galleries`, currentUser).then(
loadColumns(handleDeleteModalAction, `periods`, currentUser).then(
(newCols) => setColumns(newCols),
);
}, [currentUser]);
@ -218,7 +215,7 @@ const TableSampleGalleries = ({
sx={dataGridStyles}
className={'datagrid--table'}
getRowClassName={() => `datagrid--row`}
rows={galleries ?? []}
rows={periods ?? []}
columns={columns}
initialState={{
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 [
{
@ -70,23 +70,35 @@ export const loadColumns = async (
},
{
field: 'background_image',
headerName: 'Background Image',
field: 'period_from',
headerName: 'Period From',
flex: 1,
minWidth: 120,
filterable: false,
headerClassName: 'datagrid--header',
cellClassName: 'datagrid--cell',
editable: false,
sortable: false,
renderCell: (params: GridValueGetterParams) => (
<ImageField
name={'Avatar'}
image={params?.row?.background_image}
className='w-24 h-24 mx-auto lg:w-6 lg:h-6'
/>
),
editable: hasUpdatePermission,
type: 'dateTime',
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,
type: 'dateTime',
valueGetter: (params: GridValueGetterParams) =>
new Date(params.row.period_to),
},
{
@ -101,8 +113,8 @@ export const loadColumns = async (
<ListActionsPopover
onDelete={onDelete}
itemId={params?.row?.id}
pathEdit={`/galleries/galleries-edit/?id=${params?.row?.id}`}
pathView={`/galleries/galleries-view/?id=${params?.row?.id}`}
pathEdit={`/periods/periods-edit/?id=${params?.row?.id}`}
pathView={`/periods/periods-view/?id=${params?.row?.id}`}
hasUpdatePermission={hasUpdatePermission}
/>
</div>,

View File

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

View File

@ -44,10 +44,6 @@ const EditArchival_items = () => {
isPublished: false,
period_from: new Date(),
period_to: '',
tags: [],
};
const [initialValues, setInitialValues] = useState(initVals);
@ -135,28 +131,6 @@ const EditArchival_items = () => {
></Field>
</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'>
<Field
name='tags'

View File

@ -44,10 +44,6 @@ const EditArchival_itemsPage = () => {
isPublished: false,
period_from: new Date(),
period_to: '',
tags: [],
};
const [initialValues, setInitialValues] = useState(initVals);
@ -133,28 +129,6 @@ const EditArchival_itemsPage = () => {
></Field>
</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'>
<Field
name='tags'

View File

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

View File

@ -41,11 +41,6 @@ const initialValues = {
isPublished: false,
period_from: '',
datePeriod_from: '',
period_to: '',
tags: [],
};
@ -108,18 +103,6 @@ const Archival_itemsNew = () => {
></Field>
</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'>
<Field
name='tags'

View File

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

View File

@ -88,32 +88,6 @@ const Archival_itemsView = () => {
/>
</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>
<CardBox

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,18 +7,18 @@ import LayoutAuthenticated from '../../layouts/Authenticated';
import SectionMain from '../../components/SectionMain';
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton';
import { getPageTitle } from '../../config';
import TableGalleries from '../../components/Galleries/TableGalleries';
import TablePeriods from '../../components/Periods/TablePeriods';
import BaseButton from '../../components/BaseButton';
import axios from 'axios';
import Link from 'next/link';
import { useAppDispatch, useAppSelector } from '../../stores/hooks';
import CardBoxModal from '../../components/CardBoxModal';
import DragDropFilePicker from '../../components/DragDropFilePicker';
import { setRefetch, uploadCsv } from '../../stores/galleries/galleriesSlice';
import { setRefetch, uploadCsv } from '../../stores/periods/periodsSlice';
import { hasPermission } from '../../helpers/userPermissions';
const GalleriesTablesPage = () => {
const PeriodsTablesPage = () => {
const [filterItems, setFilterItems] = useState([]);
const [csvFile, setCsvFile] = useState<File | null>(null);
const [isModalActive, setIsModalActive] = useState(false);
@ -31,11 +31,14 @@ const GalleriesTablesPage = () => {
const [filters] = useState([
{ 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' },
]);
const hasCreatePermission =
currentUser && hasPermission(currentUser, 'CREATE_GALLERIES');
currentUser && hasPermission(currentUser, 'CREATE_PERIODS');
const addFilter = () => {
const newItem = {
@ -51,9 +54,9 @@ const GalleriesTablesPage = () => {
setFilterItems([...filterItems, newItem]);
};
const getGalleriesCSV = async () => {
const getPeriodsCSV = async () => {
const response = await axios({
url: '/galleries?filetype=csv',
url: '/periods?filetype=csv',
method: 'GET',
responseType: 'blob',
});
@ -61,7 +64,7 @@ const GalleriesTablesPage = () => {
const blob = new Blob([response.data], { type: type });
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'galleriesCSV.csv';
link.download = 'periodsCSV.csv';
link.click();
};
@ -81,12 +84,12 @@ const GalleriesTablesPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Galleries')}</title>
<title>{getPageTitle('Periods')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton
icon={mdiChartTimelineVariant}
title='Galleries'
title='Periods'
main
>
{''}
@ -95,7 +98,7 @@ const GalleriesTablesPage = () => {
{hasCreatePermission && (
<BaseButton
className={'mr-3'}
href={'/galleries/galleries-new'}
href={'/periods/periods-new'}
color='info'
label='New Item'
/>
@ -111,7 +114,7 @@ const GalleriesTablesPage = () => {
className={'mr-3'}
color='info'
label='Download CSV'
onClick={getGalleriesCSV}
onClick={getPeriodsCSV}
/>
{hasCreatePermission && (
@ -127,7 +130,7 @@ const GalleriesTablesPage = () => {
</div>
</CardBox>
<CardBox className='mb-6' hasTable>
<TableGalleries
<TablePeriods
filterItems={filterItems}
setFilterItems={setFilterItems}
filters={filters}
@ -154,12 +157,12 @@ const GalleriesTablesPage = () => {
);
};
GalleriesTablesPage.getLayout = function getLayout(page: ReactElement) {
PeriodsTablesPage.getLayout = function getLayout(page: ReactElement) {
return (
<LayoutAuthenticated permission={'READ_GALLERIES'}>
<LayoutAuthenticated permission={'READ_PERIODS'}>
{page}
</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 { useAppDispatch, useAppSelector } from '../../stores/hooks';
import { useRouter } from 'next/router';
import { fetch } from '../../stores/galleries/galleriesSlice';
import { fetch } from '../../stores/periods/periodsSlice';
import { saveFile } from '../../helpers/fileSaver';
import dataFormatter from '../../helpers/dataFormatter';
import ImageField from '../../components/ImageField';
@ -20,10 +20,10 @@ import { mdiChartTimelineVariant } from '@mdi/js';
import { SwitchField } from '../../components/SwitchField';
import FormField from '../../components/FormField';
const GalleriesView = () => {
const PeriodsView = () => {
const router = useRouter();
const dispatch = useAppDispatch();
const { galleries } = useAppSelector((state) => state.galleries);
const { periods } = useAppSelector((state) => state.periods);
const { id } = router.query;
@ -39,24 +39,24 @@ const GalleriesView = () => {
return (
<>
<Head>
<title>{getPageTitle('View galleries')}</title>
<title>{getPageTitle('View periods')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton
icon={mdiChartTimelineVariant}
title={removeLastCharacter('View galleries')}
title={removeLastCharacter('View periods')}
main
>
<BaseButton
color='info'
label='Edit'
href={`/galleries/galleries-edit/?id=${id}`}
href={`/periods/periods-edit/?id=${id}`}
/>
</SectionTitleLineWithButton>
<CardBox>
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>Name</p>
<p>{galleries?.name}</p>
<p>{periods?.name}</p>
</div>
<>
@ -74,16 +74,12 @@ const GalleriesView = () => {
<th>Description</th>
<th>Is Published</th>
<th>Period From</th>
<th>Period To</th>
</tr>
</thead>
<tbody>
{galleries.archival_items &&
Array.isArray(galleries.archival_items) &&
galleries.archival_items.map((item: any) => (
{periods.archival_items &&
Array.isArray(periods.archival_items) &&
periods.archival_items.map((item: any) => (
<tr
key={item.id}
onClick={() =>
@ -99,42 +95,61 @@ const GalleriesView = () => {
<td data-label='isPublished'>
{dataFormatter.booleanFormatter(item.isPublished)}
</td>
<td data-label='period_from'>
{dataFormatter.dateFormatter(item.period_from)}
</td>
<td data-label='period_to'>{item.period_to}</td>
</tr>
))}
</tbody>
</table>
</div>
{!galleries?.archival_items?.length && (
{!periods?.archival_items?.length && (
<div className={'text-center py-4'}>No data</div>
)}
</CardBox>
</>
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>Background Image</p>
{galleries?.background_image?.length ? (
<ImageField
name={'background_image'}
image={galleries?.background_image}
className='w-20 h-20'
<FormField label='Period From'>
{periods.period_from ? (
<DatePicker
dateFormat='yyyy-MM-dd hh:mm'
showTimeSelect
selected={
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 />
<BaseButton
color='info'
label='Back'
onClick={() => router.push('/galleries/galleries-list')}
onClick={() => router.push('/periods/periods-list')}
/>
</CardBox>
</SectionMain>
@ -142,12 +157,12 @@ const GalleriesView = () => {
);
};
GalleriesView.getLayout = function getLayout(page: ReactElement) {
PeriodsView.getLayout = function getLayout(page: ReactElement) {
return (
<LayoutAuthenticated permission={'READ_GALLERIES'}>
<LayoutAuthenticated permission={'READ_PERIODS'}>
{page}
</LayoutAuthenticated>
);
};
export default GalleriesView;
export default PeriodsView;

View File

@ -7,7 +7,7 @@ import {
} from '../../helpers/notifyStateHandler';
interface MainState {
galleries: any;
periods: any;
loading: boolean;
count: number;
refetch: boolean;
@ -20,7 +20,7 @@ interface MainState {
}
const initialState: MainState = {
galleries: [],
periods: [],
loading: false,
count: 0,
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 result = await axios.get(`galleries${query || (id ? `/${id}` : '')}`);
const result = await axios.get(`periods${query || (id ? `/${id}` : '')}`);
return id
? result.data
: { rows: result.data.rows, count: result.data.count };
});
export const deleteItemsByIds = createAsyncThunk(
'galleries/deleteByIds',
'periods/deleteByIds',
async (data: any, { rejectWithValue }) => {
try {
await axios.post('galleries/deleteByIds', { data });
await axios.post('periods/deleteByIds', { data });
} catch (error) {
if (!error.response) {
throw error;
@ -56,10 +56,10 @@ export const deleteItemsByIds = createAsyncThunk(
);
export const deleteItem = createAsyncThunk(
'galleries/deleteGalleries',
'periods/deletePeriods',
async (id: string, { rejectWithValue }) => {
try {
await axios.delete(`galleries/${id}`);
await axios.delete(`periods/${id}`);
} catch (error) {
if (!error.response) {
throw error;
@ -71,10 +71,10 @@ export const deleteItem = createAsyncThunk(
);
export const create = createAsyncThunk(
'galleries/createGalleries',
'periods/createPeriods',
async (data: any, { rejectWithValue }) => {
try {
const result = await axios.post('galleries', { data });
const result = await axios.post('periods', { data });
return result.data;
} catch (error) {
if (!error.response) {
@ -87,14 +87,14 @@ export const create = createAsyncThunk(
);
export const uploadCsv = createAsyncThunk(
'galleries/uploadCsv',
'periods/uploadCsv',
async (file: File, { rejectWithValue }) => {
try {
const data = new FormData();
data.append('file', file);
data.append('filename', file.name);
const result = await axios.post('galleries/bulk-import', data, {
const result = await axios.post('periods/bulk-import', data, {
headers: {
'Content-Type': 'multipart/form-data',
},
@ -112,10 +112,10 @@ export const uploadCsv = createAsyncThunk(
);
export const update = createAsyncThunk(
'galleries/updateGalleries',
'periods/updatePeriods',
async (payload: any, { rejectWithValue }) => {
try {
const result = await axios.put(`galleries/${payload.id}`, {
const result = await axios.put(`periods/${payload.id}`, {
id: payload.id,
data: payload.data,
});
@ -130,8 +130,8 @@ export const update = createAsyncThunk(
},
);
export const galleriesSlice = createSlice({
name: 'galleries',
export const periodsSlice = createSlice({
name: 'periods',
initialState,
reducers: {
setRefetch: (state, action: PayloadAction<boolean>) => {
@ -150,10 +150,10 @@ export const galleriesSlice = createSlice({
builder.addCase(fetch.fulfilled, (state, action) => {
if (action.payload.rows && action.payload.count >= 0) {
state.galleries = action.payload.rows;
state.periods = action.payload.rows;
state.count = action.payload.count;
} else {
state.galleries = action.payload;
state.periods = action.payload;
}
state.loading = false;
});
@ -165,7 +165,7 @@ export const galleriesSlice = createSlice({
builder.addCase(deleteItemsByIds.fulfilled, (state) => {
state.loading = false;
fulfilledNotify(state, 'Galleries has been deleted');
fulfilledNotify(state, 'Periods has been deleted');
});
builder.addCase(deleteItemsByIds.rejected, (state, action) => {
@ -180,7 +180,7 @@ export const galleriesSlice = createSlice({
builder.addCase(deleteItem.fulfilled, (state) => {
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) => {
@ -199,7 +199,7 @@ export const galleriesSlice = createSlice({
builder.addCase(create.fulfilled, (state) => {
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) => {
@ -208,7 +208,7 @@ export const galleriesSlice = createSlice({
});
builder.addCase(update.fulfilled, (state) => {
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) => {
state.loading = false;
@ -221,7 +221,7 @@ export const galleriesSlice = createSlice({
});
builder.addCase(uploadCsv.fulfilled, (state) => {
state.loading = false;
fulfilledNotify(state, 'Galleries has been uploaded');
fulfilledNotify(state, 'Periods has been uploaded');
});
builder.addCase(uploadCsv.rejected, (state, action) => {
state.loading = false;
@ -231,6 +231,6 @@ export const galleriesSlice = createSlice({
});
// 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 archival_itemsSlice from './archival_items/archival_itemsSlice';
import galleriesSlice from './galleries/galleriesSlice';
import periodsSlice from './periods/periodsSlice';
import tagsSlice from './tags/tagsSlice';
import rolesSlice from './roles/rolesSlice';
import permissionsSlice from './permissions/permissionsSlice';
@ -20,7 +20,7 @@ export const store = configureStore({
users: usersSlice,
archival_items: archival_itemsSlice,
galleries: galleriesSlice,
periods: periodsSlice,
tags: tagsSlice,
roles: rolesSlice,
permissions: permissionsSlice,