Auto commit: 2025-09-18T16:05:59.956Z
This commit is contained in:
parent
f0ac3b80cd
commit
9658341031
File diff suppressed because one or more lines are too long
258
backend/src/db/api/books.js
Normal file
258
backend/src/db/api/books.js
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
const db = require('../models');
|
||||||
|
const FileDBApi = require('./file');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const Utils = require('../utils');
|
||||||
|
|
||||||
|
const Sequelize = db.Sequelize;
|
||||||
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
|
module.exports = class BooksDBApi {
|
||||||
|
static async create(data, options) {
|
||||||
|
const currentUser = (options && options.currentUser) || { id: null };
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
const books = await db.books.create(
|
||||||
|
{
|
||||||
|
id: data.id || undefined,
|
||||||
|
|
||||||
|
name: data.name || null,
|
||||||
|
importHash: data.importHash || null,
|
||||||
|
createdById: currentUser.id,
|
||||||
|
updatedById: currentUser.id,
|
||||||
|
},
|
||||||
|
{ transaction },
|
||||||
|
);
|
||||||
|
|
||||||
|
return books;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async bulkImport(data, options) {
|
||||||
|
const currentUser = (options && options.currentUser) || { id: null };
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
// Prepare data - wrapping individual data transformations in a map() method
|
||||||
|
const booksData = data.map((item, index) => ({
|
||||||
|
id: item.id || undefined,
|
||||||
|
|
||||||
|
name: item.name || null,
|
||||||
|
importHash: item.importHash || null,
|
||||||
|
createdById: currentUser.id,
|
||||||
|
updatedById: currentUser.id,
|
||||||
|
createdAt: new Date(Date.now() + index * 1000),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Bulk create items
|
||||||
|
const books = await db.books.bulkCreate(booksData, { transaction });
|
||||||
|
|
||||||
|
// For each item created, replace relation files
|
||||||
|
|
||||||
|
return books;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async update(id, data, options) {
|
||||||
|
const currentUser = (options && options.currentUser) || { id: null };
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
const books = await db.books.findByPk(id, {}, { transaction });
|
||||||
|
|
||||||
|
const updatePayload = {};
|
||||||
|
|
||||||
|
if (data.name !== undefined) updatePayload.name = data.name;
|
||||||
|
|
||||||
|
updatePayload.updatedById = currentUser.id;
|
||||||
|
|
||||||
|
await books.update(updatePayload, { transaction });
|
||||||
|
|
||||||
|
return books;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async deleteByIds(ids, options) {
|
||||||
|
const currentUser = (options && options.currentUser) || { id: null };
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
const books = await db.books.findAll({
|
||||||
|
where: {
|
||||||
|
id: {
|
||||||
|
[Op.in]: ids,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.sequelize.transaction(async (transaction) => {
|
||||||
|
for (const record of books) {
|
||||||
|
await record.update({ deletedBy: currentUser.id }, { transaction });
|
||||||
|
}
|
||||||
|
for (const record of books) {
|
||||||
|
await record.destroy({ transaction });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return books;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async remove(id, options) {
|
||||||
|
const currentUser = (options && options.currentUser) || { id: null };
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
const books = await db.books.findByPk(id, options);
|
||||||
|
|
||||||
|
await books.update(
|
||||||
|
{
|
||||||
|
deletedBy: currentUser.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
transaction,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
await books.destroy({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
return books;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async findBy(where, options) {
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
const books = await db.books.findOne({ where }, { transaction });
|
||||||
|
|
||||||
|
if (!books) {
|
||||||
|
return books;
|
||||||
|
}
|
||||||
|
|
||||||
|
const output = books.get({ plain: true });
|
||||||
|
|
||||||
|
output.readings_bookref = await books.getReadings_bookref({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
output.readings_book_select = await books.getReadings_book_select({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
output.chapters_book = await books.getChapters_book({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async findAll(filter, options) {
|
||||||
|
const limit = filter.limit || 0;
|
||||||
|
let offset = 0;
|
||||||
|
let where = {};
|
||||||
|
const currentPage = +filter.page;
|
||||||
|
|
||||||
|
offset = currentPage * limit;
|
||||||
|
|
||||||
|
const orderBy = null;
|
||||||
|
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
let include = [];
|
||||||
|
|
||||||
|
if (filter) {
|
||||||
|
if (filter.id) {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
['id']: Utils.uuid(filter.id),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.name) {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
[Op.and]: Utils.ilike('books', 'name', filter.name),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.active !== undefined) {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
active: filter.active === true || filter.active === 'true',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.createdAtRange) {
|
||||||
|
const [start, end] = filter.createdAtRange;
|
||||||
|
|
||||||
|
if (start !== undefined && start !== null && start !== '') {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
['createdAt']: {
|
||||||
|
...where.createdAt,
|
||||||
|
[Op.gte]: start,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end !== undefined && end !== null && end !== '') {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
['createdAt']: {
|
||||||
|
...where.createdAt,
|
||||||
|
[Op.lte]: end,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const queryOptions = {
|
||||||
|
where,
|
||||||
|
include,
|
||||||
|
distinct: true,
|
||||||
|
order:
|
||||||
|
filter.field && filter.sort
|
||||||
|
? [[filter.field, filter.sort]]
|
||||||
|
: [['createdAt', 'desc']],
|
||||||
|
transaction: options?.transaction,
|
||||||
|
logging: console.log,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!options?.countOnly) {
|
||||||
|
queryOptions.limit = limit ? Number(limit) : undefined;
|
||||||
|
queryOptions.offset = offset ? Number(offset) : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { rows, count } = await db.books.findAndCountAll(queryOptions);
|
||||||
|
|
||||||
|
return {
|
||||||
|
rows: options?.countOnly ? [] : rows,
|
||||||
|
count: count,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error executing query:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async findAllAutocomplete(query, limit, offset) {
|
||||||
|
let where = {};
|
||||||
|
|
||||||
|
if (query) {
|
||||||
|
where = {
|
||||||
|
[Op.or]: [
|
||||||
|
{ ['id']: Utils.uuid(query) },
|
||||||
|
Utils.ilike('books', 'name', query),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const records = await db.books.findAll({
|
||||||
|
attributes: ['id', 'name'],
|
||||||
|
where,
|
||||||
|
limit: limit ? Number(limit) : undefined,
|
||||||
|
offset: offset ? Number(offset) : undefined,
|
||||||
|
orderBy: [['name', 'ASC']],
|
||||||
|
});
|
||||||
|
|
||||||
|
return records.map((record) => ({
|
||||||
|
id: record.id,
|
||||||
|
label: record.name,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
315
backend/src/db/api/chapters.js
Normal file
315
backend/src/db/api/chapters.js
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
const db = require('../models');
|
||||||
|
const FileDBApi = require('./file');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const Utils = require('../utils');
|
||||||
|
|
||||||
|
const Sequelize = db.Sequelize;
|
||||||
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
|
module.exports = class ChaptersDBApi {
|
||||||
|
static async create(data, options) {
|
||||||
|
const currentUser = (options && options.currentUser) || { id: null };
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
const chapters = await db.chapters.create(
|
||||||
|
{
|
||||||
|
id: data.id || undefined,
|
||||||
|
|
||||||
|
number: data.number || null,
|
||||||
|
importHash: data.importHash || null,
|
||||||
|
createdById: currentUser.id,
|
||||||
|
updatedById: currentUser.id,
|
||||||
|
},
|
||||||
|
{ transaction },
|
||||||
|
);
|
||||||
|
|
||||||
|
await chapters.setBook(data.book || null, {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
return chapters;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async bulkImport(data, options) {
|
||||||
|
const currentUser = (options && options.currentUser) || { id: null };
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
// Prepare data - wrapping individual data transformations in a map() method
|
||||||
|
const chaptersData = data.map((item, index) => ({
|
||||||
|
id: item.id || undefined,
|
||||||
|
|
||||||
|
number: item.number || null,
|
||||||
|
importHash: item.importHash || null,
|
||||||
|
createdById: currentUser.id,
|
||||||
|
updatedById: currentUser.id,
|
||||||
|
createdAt: new Date(Date.now() + index * 1000),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Bulk create items
|
||||||
|
const chapters = await db.chapters.bulkCreate(chaptersData, {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
// For each item created, replace relation files
|
||||||
|
|
||||||
|
return chapters;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async update(id, data, options) {
|
||||||
|
const currentUser = (options && options.currentUser) || { id: null };
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
const chapters = await db.chapters.findByPk(id, {}, { transaction });
|
||||||
|
|
||||||
|
const updatePayload = {};
|
||||||
|
|
||||||
|
if (data.number !== undefined) updatePayload.number = data.number;
|
||||||
|
|
||||||
|
updatePayload.updatedById = currentUser.id;
|
||||||
|
|
||||||
|
await chapters.update(updatePayload, { transaction });
|
||||||
|
|
||||||
|
if (data.book !== undefined) {
|
||||||
|
await chapters.setBook(
|
||||||
|
data.book,
|
||||||
|
|
||||||
|
{ transaction },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return chapters;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async deleteByIds(ids, options) {
|
||||||
|
const currentUser = (options && options.currentUser) || { id: null };
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
const chapters = await db.chapters.findAll({
|
||||||
|
where: {
|
||||||
|
id: {
|
||||||
|
[Op.in]: ids,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.sequelize.transaction(async (transaction) => {
|
||||||
|
for (const record of chapters) {
|
||||||
|
await record.update({ deletedBy: currentUser.id }, { transaction });
|
||||||
|
}
|
||||||
|
for (const record of chapters) {
|
||||||
|
await record.destroy({ transaction });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return chapters;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async remove(id, options) {
|
||||||
|
const currentUser = (options && options.currentUser) || { id: null };
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
const chapters = await db.chapters.findByPk(id, options);
|
||||||
|
|
||||||
|
await chapters.update(
|
||||||
|
{
|
||||||
|
deletedBy: currentUser.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
transaction,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
await chapters.destroy({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
return chapters;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async findBy(where, options) {
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
const chapters = await db.chapters.findOne({ where }, { transaction });
|
||||||
|
|
||||||
|
if (!chapters) {
|
||||||
|
return chapters;
|
||||||
|
}
|
||||||
|
|
||||||
|
const output = chapters.get({ plain: true });
|
||||||
|
|
||||||
|
output.readings_chapterref = await chapters.getReadings_chapterref({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
output.readings_chapter_select = await chapters.getReadings_chapter_select({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
output.book = await chapters.getBook({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async findAll(filter, options) {
|
||||||
|
const limit = filter.limit || 0;
|
||||||
|
let offset = 0;
|
||||||
|
let where = {};
|
||||||
|
const currentPage = +filter.page;
|
||||||
|
|
||||||
|
offset = currentPage * limit;
|
||||||
|
|
||||||
|
const orderBy = null;
|
||||||
|
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
let include = [
|
||||||
|
{
|
||||||
|
model: db.books,
|
||||||
|
as: 'book',
|
||||||
|
|
||||||
|
where: filter.book
|
||||||
|
? {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
[Op.in]: filter.book
|
||||||
|
.split('|')
|
||||||
|
.map((term) => Utils.uuid(term)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: {
|
||||||
|
[Op.or]: filter.book
|
||||||
|
.split('|')
|
||||||
|
.map((term) => ({ [Op.iLike]: `%${term}%` })),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (filter) {
|
||||||
|
if (filter.id) {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
['id']: Utils.uuid(filter.id),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.numberRange) {
|
||||||
|
const [start, end] = filter.numberRange;
|
||||||
|
|
||||||
|
if (start !== undefined && start !== null && start !== '') {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
number: {
|
||||||
|
...where.number,
|
||||||
|
[Op.gte]: start,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end !== undefined && end !== null && end !== '') {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
number: {
|
||||||
|
...where.number,
|
||||||
|
[Op.lte]: end,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.active !== undefined) {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
active: filter.active === true || filter.active === 'true',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.createdAtRange) {
|
||||||
|
const [start, end] = filter.createdAtRange;
|
||||||
|
|
||||||
|
if (start !== undefined && start !== null && start !== '') {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
['createdAt']: {
|
||||||
|
...where.createdAt,
|
||||||
|
[Op.gte]: start,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end !== undefined && end !== null && end !== '') {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
['createdAt']: {
|
||||||
|
...where.createdAt,
|
||||||
|
[Op.lte]: end,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const queryOptions = {
|
||||||
|
where,
|
||||||
|
include,
|
||||||
|
distinct: true,
|
||||||
|
order:
|
||||||
|
filter.field && filter.sort
|
||||||
|
? [[filter.field, filter.sort]]
|
||||||
|
: [['createdAt', 'desc']],
|
||||||
|
transaction: options?.transaction,
|
||||||
|
logging: console.log,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!options?.countOnly) {
|
||||||
|
queryOptions.limit = limit ? Number(limit) : undefined;
|
||||||
|
queryOptions.offset = offset ? Number(offset) : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { rows, count } = await db.chapters.findAndCountAll(queryOptions);
|
||||||
|
|
||||||
|
return {
|
||||||
|
rows: options?.countOnly ? [] : rows,
|
||||||
|
count: count,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error executing query:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async findAllAutocomplete(query, limit, offset) {
|
||||||
|
let where = {};
|
||||||
|
|
||||||
|
if (query) {
|
||||||
|
where = {
|
||||||
|
[Op.or]: [
|
||||||
|
{ ['id']: Utils.uuid(query) },
|
||||||
|
Utils.ilike('chapters', 'number', query),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const records = await db.chapters.findAll({
|
||||||
|
attributes: ['id', 'number'],
|
||||||
|
where,
|
||||||
|
limit: limit ? Number(limit) : undefined,
|
||||||
|
offset: offset ? Number(offset) : undefined,
|
||||||
|
orderBy: [['number', 'ASC']],
|
||||||
|
});
|
||||||
|
|
||||||
|
return records.map((record) => ({
|
||||||
|
id: record.id,
|
||||||
|
label: record.number,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -191,7 +191,7 @@ module.exports = class NotesDBApi {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
book: {
|
tags: {
|
||||||
[Op.or]: filter.reading
|
[Op.or]: filter.reading
|
||||||
.split('|')
|
.split('|')
|
||||||
.map((term) => ({ [Op.iLike]: `%${term}%` })),
|
.map((term) => ({ [Op.iLike]: `%${term}%` })),
|
||||||
|
|||||||
@ -21,6 +21,7 @@ module.exports = class ReadingsDBApi {
|
|||||||
verses: data.verses || null,
|
verses: data.verses || null,
|
||||||
translation: data.translation || null,
|
translation: data.translation || null,
|
||||||
notes: data.notes || null,
|
notes: data.notes || null,
|
||||||
|
tags: data.tags || null,
|
||||||
importHash: data.importHash || null,
|
importHash: data.importHash || null,
|
||||||
createdById: currentUser.id,
|
createdById: currentUser.id,
|
||||||
updatedById: currentUser.id,
|
updatedById: currentUser.id,
|
||||||
@ -32,6 +33,38 @@ module.exports = class ReadingsDBApi {
|
|||||||
transaction,
|
transaction,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await readings.setBookref(data.bookref || null, {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await readings.setChapterref(data.chapterref || null, {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await readings.setTranslationref(data.translationref || null, {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await readings.setBook_select(data.book_select || null, {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await readings.setChapter_select(data.chapter_select || null, {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await readings.setTranslation_select(data.translation_select || null, {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await readings.setVersesref(data.versesref || [], {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await readings.setVerses_select(data.verses_select || [], {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
return readings;
|
return readings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +82,7 @@ module.exports = class ReadingsDBApi {
|
|||||||
verses: item.verses || null,
|
verses: item.verses || null,
|
||||||
translation: item.translation || null,
|
translation: item.translation || null,
|
||||||
notes: item.notes || null,
|
notes: item.notes || null,
|
||||||
|
tags: item.tags || null,
|
||||||
importHash: item.importHash || null,
|
importHash: item.importHash || null,
|
||||||
createdById: currentUser.id,
|
createdById: currentUser.id,
|
||||||
updatedById: currentUser.id,
|
updatedById: currentUser.id,
|
||||||
@ -86,6 +120,8 @@ module.exports = class ReadingsDBApi {
|
|||||||
|
|
||||||
if (data.notes !== undefined) updatePayload.notes = data.notes;
|
if (data.notes !== undefined) updatePayload.notes = data.notes;
|
||||||
|
|
||||||
|
if (data.tags !== undefined) updatePayload.tags = data.tags;
|
||||||
|
|
||||||
updatePayload.updatedById = currentUser.id;
|
updatePayload.updatedById = currentUser.id;
|
||||||
|
|
||||||
await readings.update(updatePayload, { transaction });
|
await readings.update(updatePayload, { transaction });
|
||||||
@ -98,6 +134,62 @@ module.exports = class ReadingsDBApi {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.bookref !== undefined) {
|
||||||
|
await readings.setBookref(
|
||||||
|
data.bookref,
|
||||||
|
|
||||||
|
{ transaction },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.chapterref !== undefined) {
|
||||||
|
await readings.setChapterref(
|
||||||
|
data.chapterref,
|
||||||
|
|
||||||
|
{ transaction },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.translationref !== undefined) {
|
||||||
|
await readings.setTranslationref(
|
||||||
|
data.translationref,
|
||||||
|
|
||||||
|
{ transaction },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.book_select !== undefined) {
|
||||||
|
await readings.setBook_select(
|
||||||
|
data.book_select,
|
||||||
|
|
||||||
|
{ transaction },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.chapter_select !== undefined) {
|
||||||
|
await readings.setChapter_select(
|
||||||
|
data.chapter_select,
|
||||||
|
|
||||||
|
{ transaction },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.translation_select !== undefined) {
|
||||||
|
await readings.setTranslation_select(
|
||||||
|
data.translation_select,
|
||||||
|
|
||||||
|
{ transaction },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.versesref !== undefined) {
|
||||||
|
await readings.setVersesref(data.versesref, { transaction });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.verses_select !== undefined) {
|
||||||
|
await readings.setVerses_select(data.verses_select, { transaction });
|
||||||
|
}
|
||||||
|
|
||||||
return readings;
|
return readings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,6 +259,38 @@ module.exports = class ReadingsDBApi {
|
|||||||
transaction,
|
transaction,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
output.bookref = await readings.getBookref({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
output.chapterref = await readings.getChapterref({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
output.versesref = await readings.getVersesref({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
output.translationref = await readings.getTranslationref({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
output.book_select = await readings.getBook_select({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
output.chapter_select = await readings.getChapter_select({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
output.verses_select = await readings.getVerses_select({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
output.translation_select = await readings.getTranslation_select({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,6 +332,174 @@ module.exports = class ReadingsDBApi {
|
|||||||
}
|
}
|
||||||
: {},
|
: {},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
model: db.books,
|
||||||
|
as: 'bookref',
|
||||||
|
|
||||||
|
where: filter.bookref
|
||||||
|
? {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
[Op.in]: filter.bookref
|
||||||
|
.split('|')
|
||||||
|
.map((term) => Utils.uuid(term)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: {
|
||||||
|
[Op.or]: filter.bookref
|
||||||
|
.split('|')
|
||||||
|
.map((term) => ({ [Op.iLike]: `%${term}%` })),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
model: db.chapters,
|
||||||
|
as: 'chapterref',
|
||||||
|
|
||||||
|
where: filter.chapterref
|
||||||
|
? {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
[Op.in]: filter.chapterref
|
||||||
|
.split('|')
|
||||||
|
.map((term) => Utils.uuid(term)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
number: {
|
||||||
|
[Op.or]: filter.chapterref
|
||||||
|
.split('|')
|
||||||
|
.map((term) => ({ [Op.iLike]: `%${term}%` })),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
model: db.translations,
|
||||||
|
as: 'translationref',
|
||||||
|
|
||||||
|
where: filter.translationref
|
||||||
|
? {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
[Op.in]: filter.translationref
|
||||||
|
.split('|')
|
||||||
|
.map((term) => Utils.uuid(term)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: {
|
||||||
|
[Op.or]: filter.translationref
|
||||||
|
.split('|')
|
||||||
|
.map((term) => ({ [Op.iLike]: `%${term}%` })),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
model: db.books,
|
||||||
|
as: 'book_select',
|
||||||
|
|
||||||
|
where: filter.book_select
|
||||||
|
? {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
[Op.in]: filter.book_select
|
||||||
|
.split('|')
|
||||||
|
.map((term) => Utils.uuid(term)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: {
|
||||||
|
[Op.or]: filter.book_select
|
||||||
|
.split('|')
|
||||||
|
.map((term) => ({ [Op.iLike]: `%${term}%` })),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
model: db.chapters,
|
||||||
|
as: 'chapter_select',
|
||||||
|
|
||||||
|
where: filter.chapter_select
|
||||||
|
? {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
[Op.in]: filter.chapter_select
|
||||||
|
.split('|')
|
||||||
|
.map((term) => Utils.uuid(term)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
number: {
|
||||||
|
[Op.or]: filter.chapter_select
|
||||||
|
.split('|')
|
||||||
|
.map((term) => ({ [Op.iLike]: `%${term}%` })),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
model: db.translations,
|
||||||
|
as: 'translation_select',
|
||||||
|
|
||||||
|
where: filter.translation_select
|
||||||
|
? {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
[Op.in]: filter.translation_select
|
||||||
|
.split('|')
|
||||||
|
.map((term) => Utils.uuid(term)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: {
|
||||||
|
[Op.or]: filter.translation_select
|
||||||
|
.split('|')
|
||||||
|
.map((term) => ({ [Op.iLike]: `%${term}%` })),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
model: db.verses,
|
||||||
|
as: 'versesref',
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
model: db.verses,
|
||||||
|
as: 'verses_select',
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (filter) {
|
if (filter) {
|
||||||
@ -246,6 +538,13 @@ module.exports = class ReadingsDBApi {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filter.tags) {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
[Op.and]: Utils.ilike('readings', 'tags', filter.tags),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (filter.calendarStart && filter.calendarEnd) {
|
if (filter.calendarStart && filter.calendarEnd) {
|
||||||
where = {
|
where = {
|
||||||
...where,
|
...where,
|
||||||
@ -319,6 +618,70 @@ module.exports = class ReadingsDBApi {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filter.versesref) {
|
||||||
|
const searchTerms = filter.versesref.split('|');
|
||||||
|
|
||||||
|
include = [
|
||||||
|
{
|
||||||
|
model: db.verses,
|
||||||
|
as: 'versesref_filter',
|
||||||
|
required: searchTerms.length > 0,
|
||||||
|
where:
|
||||||
|
searchTerms.length > 0
|
||||||
|
? {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
[Op.in]: searchTerms.map((term) => Utils.uuid(term)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
number: {
|
||||||
|
[Op.or]: searchTerms.map((term) => ({
|
||||||
|
[Op.iLike]: `%${term}%`,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
...include,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.verses_select) {
|
||||||
|
const searchTerms = filter.verses_select.split('|');
|
||||||
|
|
||||||
|
include = [
|
||||||
|
{
|
||||||
|
model: db.verses,
|
||||||
|
as: 'verses_select_filter',
|
||||||
|
required: searchTerms.length > 0,
|
||||||
|
where:
|
||||||
|
searchTerms.length > 0
|
||||||
|
? {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
[Op.in]: searchTerms.map((term) => Utils.uuid(term)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
number: {
|
||||||
|
[Op.or]: searchTerms.map((term) => ({
|
||||||
|
[Op.iLike]: `%${term}%`,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
...include,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
if (filter.createdAtRange) {
|
if (filter.createdAtRange) {
|
||||||
const [start, end] = filter.createdAtRange;
|
const [start, end] = filter.createdAtRange;
|
||||||
|
|
||||||
@ -381,22 +744,22 @@ module.exports = class ReadingsDBApi {
|
|||||||
where = {
|
where = {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ ['id']: Utils.uuid(query) },
|
{ ['id']: Utils.uuid(query) },
|
||||||
Utils.ilike('readings', 'book', query),
|
Utils.ilike('readings', 'tags', query),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const records = await db.readings.findAll({
|
const records = await db.readings.findAll({
|
||||||
attributes: ['id', 'book'],
|
attributes: ['id', 'tags'],
|
||||||
where,
|
where,
|
||||||
limit: limit ? Number(limit) : undefined,
|
limit: limit ? Number(limit) : undefined,
|
||||||
offset: offset ? Number(offset) : undefined,
|
offset: offset ? Number(offset) : undefined,
|
||||||
orderBy: [['book', 'ASC']],
|
orderBy: [['tags', 'ASC']],
|
||||||
});
|
});
|
||||||
|
|
||||||
return records.map((record) => ({
|
return records.map((record) => ({
|
||||||
id: record.id,
|
id: record.id,
|
||||||
label: record.book,
|
label: record.tags,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
267
backend/src/db/api/translations.js
Normal file
267
backend/src/db/api/translations.js
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
const db = require('../models');
|
||||||
|
const FileDBApi = require('./file');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const Utils = require('../utils');
|
||||||
|
|
||||||
|
const Sequelize = db.Sequelize;
|
||||||
|
const Op = Sequelize.Op;
|
||||||
|
|
||||||
|
module.exports = class TranslationsDBApi {
|
||||||
|
static async create(data, options) {
|
||||||
|
const currentUser = (options && options.currentUser) || { id: null };
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
const translations = await db.translations.create(
|
||||||
|
{
|
||||||
|
id: data.id || undefined,
|
||||||
|
|
||||||
|
name: data.name || null,
|
||||||
|
importHash: data.importHash || null,
|
||||||
|
createdById: currentUser.id,
|
||||||
|
updatedById: currentUser.id,
|
||||||
|
},
|
||||||
|
{ transaction },
|
||||||
|
);
|
||||||
|
|
||||||
|
return translations;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async bulkImport(data, options) {
|
||||||
|
const currentUser = (options && options.currentUser) || { id: null };
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
// Prepare data - wrapping individual data transformations in a map() method
|
||||||
|
const translationsData = data.map((item, index) => ({
|
||||||
|
id: item.id || undefined,
|
||||||
|
|
||||||
|
name: item.name || null,
|
||||||
|
importHash: item.importHash || null,
|
||||||
|
createdById: currentUser.id,
|
||||||
|
updatedById: currentUser.id,
|
||||||
|
createdAt: new Date(Date.now() + index * 1000),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Bulk create items
|
||||||
|
const translations = await db.translations.bulkCreate(translationsData, {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
// For each item created, replace relation files
|
||||||
|
|
||||||
|
return translations;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async update(id, data, options) {
|
||||||
|
const currentUser = (options && options.currentUser) || { id: null };
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
const translations = await db.translations.findByPk(
|
||||||
|
id,
|
||||||
|
{},
|
||||||
|
{ transaction },
|
||||||
|
);
|
||||||
|
|
||||||
|
const updatePayload = {};
|
||||||
|
|
||||||
|
if (data.name !== undefined) updatePayload.name = data.name;
|
||||||
|
|
||||||
|
updatePayload.updatedById = currentUser.id;
|
||||||
|
|
||||||
|
await translations.update(updatePayload, { transaction });
|
||||||
|
|
||||||
|
return translations;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async deleteByIds(ids, options) {
|
||||||
|
const currentUser = (options && options.currentUser) || { id: null };
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
const translations = await db.translations.findAll({
|
||||||
|
where: {
|
||||||
|
id: {
|
||||||
|
[Op.in]: ids,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.sequelize.transaction(async (transaction) => {
|
||||||
|
for (const record of translations) {
|
||||||
|
await record.update({ deletedBy: currentUser.id }, { transaction });
|
||||||
|
}
|
||||||
|
for (const record of translations) {
|
||||||
|
await record.destroy({ transaction });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return translations;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async remove(id, options) {
|
||||||
|
const currentUser = (options && options.currentUser) || { id: null };
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
const translations = await db.translations.findByPk(id, options);
|
||||||
|
|
||||||
|
await translations.update(
|
||||||
|
{
|
||||||
|
deletedBy: currentUser.id,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
transaction,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
await translations.destroy({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
return translations;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async findBy(where, options) {
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
const translations = await db.translations.findOne(
|
||||||
|
{ where },
|
||||||
|
{ transaction },
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!translations) {
|
||||||
|
return translations;
|
||||||
|
}
|
||||||
|
|
||||||
|
const output = translations.get({ plain: true });
|
||||||
|
|
||||||
|
output.readings_translationref =
|
||||||
|
await translations.getReadings_translationref({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
output.readings_translation_select =
|
||||||
|
await translations.getReadings_translation_select({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async findAll(filter, options) {
|
||||||
|
const limit = filter.limit || 0;
|
||||||
|
let offset = 0;
|
||||||
|
let where = {};
|
||||||
|
const currentPage = +filter.page;
|
||||||
|
|
||||||
|
offset = currentPage * limit;
|
||||||
|
|
||||||
|
const orderBy = null;
|
||||||
|
|
||||||
|
const transaction = (options && options.transaction) || undefined;
|
||||||
|
|
||||||
|
let include = [];
|
||||||
|
|
||||||
|
if (filter) {
|
||||||
|
if (filter.id) {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
['id']: Utils.uuid(filter.id),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.name) {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
[Op.and]: Utils.ilike('translations', 'name', filter.name),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.active !== undefined) {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
active: filter.active === true || filter.active === 'true',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.createdAtRange) {
|
||||||
|
const [start, end] = filter.createdAtRange;
|
||||||
|
|
||||||
|
if (start !== undefined && start !== null && start !== '') {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
['createdAt']: {
|
||||||
|
...where.createdAt,
|
||||||
|
[Op.gte]: start,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end !== undefined && end !== null && end !== '') {
|
||||||
|
where = {
|
||||||
|
...where,
|
||||||
|
['createdAt']: {
|
||||||
|
...where.createdAt,
|
||||||
|
[Op.lte]: end,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const queryOptions = {
|
||||||
|
where,
|
||||||
|
include,
|
||||||
|
distinct: true,
|
||||||
|
order:
|
||||||
|
filter.field && filter.sort
|
||||||
|
? [[filter.field, filter.sort]]
|
||||||
|
: [['createdAt', 'desc']],
|
||||||
|
transaction: options?.transaction,
|
||||||
|
logging: console.log,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!options?.countOnly) {
|
||||||
|
queryOptions.limit = limit ? Number(limit) : undefined;
|
||||||
|
queryOptions.offset = offset ? Number(offset) : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { rows, count } = await db.translations.findAndCountAll(
|
||||||
|
queryOptions,
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
rows: options?.countOnly ? [] : rows,
|
||||||
|
count: count,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error executing query:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async findAllAutocomplete(query, limit, offset) {
|
||||||
|
let where = {};
|
||||||
|
|
||||||
|
if (query) {
|
||||||
|
where = {
|
||||||
|
[Op.or]: [
|
||||||
|
{ ['id']: Utils.uuid(query) },
|
||||||
|
Utils.ilike('translations', 'name', query),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const records = await db.translations.findAll({
|
||||||
|
attributes: ['id', 'name'],
|
||||||
|
where,
|
||||||
|
limit: limit ? Number(limit) : undefined,
|
||||||
|
offset: offset ? Number(offset) : undefined,
|
||||||
|
orderBy: [['name', 'ASC']],
|
||||||
|
});
|
||||||
|
|
||||||
|
return records.map((record) => ({
|
||||||
|
id: record.id,
|
||||||
|
label: record.name,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
54
backend/src/db/migrations/1758211105293.js
Normal file
54
backend/src/db/migrations/1758211105293.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
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.addColumn(
|
||||||
|
'readings',
|
||||||
|
'book_selectId',
|
||||||
|
{
|
||||||
|
type: Sequelize.DataTypes.UUID,
|
||||||
|
|
||||||
|
references: {
|
||||||
|
model: 'books',
|
||||||
|
key: 'id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ 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.removeColumn('readings', 'book_selectId', {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await transaction.commit();
|
||||||
|
} catch (err) {
|
||||||
|
await transaction.rollback();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
54
backend/src/db/migrations/1758211132842.js
Normal file
54
backend/src/db/migrations/1758211132842.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
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.addColumn(
|
||||||
|
'readings',
|
||||||
|
'chapter_selectId',
|
||||||
|
{
|
||||||
|
type: Sequelize.DataTypes.UUID,
|
||||||
|
|
||||||
|
references: {
|
||||||
|
model: 'chapters',
|
||||||
|
key: 'id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ 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.removeColumn('readings', 'chapter_selectId', {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await transaction.commit();
|
||||||
|
} catch (err) {
|
||||||
|
await transaction.rollback();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
36
backend/src/db/migrations/1758211158025.js
Normal file
36
backend/src/db/migrations/1758211158025.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
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 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 transaction.commit();
|
||||||
|
} catch (err) {
|
||||||
|
await transaction.rollback();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
54
backend/src/db/migrations/1758211187600.js
Normal file
54
backend/src/db/migrations/1758211187600.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
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.addColumn(
|
||||||
|
'readings',
|
||||||
|
'translation_selectId',
|
||||||
|
{
|
||||||
|
type: Sequelize.DataTypes.UUID,
|
||||||
|
|
||||||
|
references: {
|
||||||
|
model: 'translations',
|
||||||
|
key: 'id',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ 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.removeColumn('readings', 'translation_selectId', {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await transaction.commit();
|
||||||
|
} catch (err) {
|
||||||
|
await transaction.rollback();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
47
backend/src/db/migrations/1758211229331.js
Normal file
47
backend/src/db/migrations/1758211229331.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
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.addColumn(
|
||||||
|
'readings',
|
||||||
|
'tags',
|
||||||
|
{
|
||||||
|
type: Sequelize.DataTypes.TEXT,
|
||||||
|
},
|
||||||
|
{ 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.removeColumn('readings', 'tags', { transaction });
|
||||||
|
|
||||||
|
await transaction.commit();
|
||||||
|
} catch (err) {
|
||||||
|
await transaction.rollback();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
73
backend/src/db/models/books.js
Normal file
73
backend/src/db/models/books.js
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
const config = require('../../config');
|
||||||
|
const providers = config.providers;
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const bcrypt = require('bcrypt');
|
||||||
|
const moment = require('moment');
|
||||||
|
|
||||||
|
module.exports = function (sequelize, DataTypes) {
|
||||||
|
const books = sequelize.define(
|
||||||
|
'books',
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
type: DataTypes.UUID,
|
||||||
|
defaultValue: DataTypes.UUIDV4,
|
||||||
|
primaryKey: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
name: {
|
||||||
|
type: DataTypes.TEXT,
|
||||||
|
},
|
||||||
|
|
||||||
|
importHash: {
|
||||||
|
type: DataTypes.STRING(255),
|
||||||
|
allowNull: true,
|
||||||
|
unique: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timestamps: true,
|
||||||
|
paranoid: true,
|
||||||
|
freezeTableName: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
books.associate = (db) => {
|
||||||
|
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
||||||
|
|
||||||
|
db.books.hasMany(db.readings, {
|
||||||
|
as: 'readings_bookref',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'bookrefId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
db.books.hasMany(db.readings, {
|
||||||
|
as: 'readings_book_select',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'book_selectId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
db.books.hasMany(db.chapters, {
|
||||||
|
as: 'chapters_book',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'bookId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
//end loop
|
||||||
|
|
||||||
|
db.books.belongsTo(db.users, {
|
||||||
|
as: 'createdBy',
|
||||||
|
});
|
||||||
|
|
||||||
|
db.books.belongsTo(db.users, {
|
||||||
|
as: 'updatedBy',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return books;
|
||||||
|
};
|
||||||
73
backend/src/db/models/chapters.js
Normal file
73
backend/src/db/models/chapters.js
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
const config = require('../../config');
|
||||||
|
const providers = config.providers;
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const bcrypt = require('bcrypt');
|
||||||
|
const moment = require('moment');
|
||||||
|
|
||||||
|
module.exports = function (sequelize, DataTypes) {
|
||||||
|
const chapters = sequelize.define(
|
||||||
|
'chapters',
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
type: DataTypes.UUID,
|
||||||
|
defaultValue: DataTypes.UUIDV4,
|
||||||
|
primaryKey: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
number: {
|
||||||
|
type: DataTypes.INTEGER,
|
||||||
|
},
|
||||||
|
|
||||||
|
importHash: {
|
||||||
|
type: DataTypes.STRING(255),
|
||||||
|
allowNull: true,
|
||||||
|
unique: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timestamps: true,
|
||||||
|
paranoid: true,
|
||||||
|
freezeTableName: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
chapters.associate = (db) => {
|
||||||
|
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
||||||
|
|
||||||
|
db.chapters.hasMany(db.readings, {
|
||||||
|
as: 'readings_chapterref',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'chapterrefId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
db.chapters.hasMany(db.readings, {
|
||||||
|
as: 'readings_chapter_select',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'chapter_selectId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
//end loop
|
||||||
|
|
||||||
|
db.chapters.belongsTo(db.books, {
|
||||||
|
as: 'book',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'bookId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
db.chapters.belongsTo(db.users, {
|
||||||
|
as: 'createdBy',
|
||||||
|
});
|
||||||
|
|
||||||
|
db.chapters.belongsTo(db.users, {
|
||||||
|
as: 'updatedBy',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return chapters;
|
||||||
|
};
|
||||||
@ -38,6 +38,10 @@ module.exports = function (sequelize, DataTypes) {
|
|||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
tags: {
|
||||||
|
type: DataTypes.TEXT,
|
||||||
|
},
|
||||||
|
|
||||||
importHash: {
|
importHash: {
|
||||||
type: DataTypes.STRING(255),
|
type: DataTypes.STRING(255),
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
@ -52,6 +56,42 @@ module.exports = function (sequelize, DataTypes) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
readings.associate = (db) => {
|
readings.associate = (db) => {
|
||||||
|
db.readings.belongsToMany(db.verses, {
|
||||||
|
as: 'versesref',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'readings_versesrefId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
through: 'readingsVersesrefVerses',
|
||||||
|
});
|
||||||
|
|
||||||
|
db.readings.belongsToMany(db.verses, {
|
||||||
|
as: 'versesref_filter',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'readings_versesrefId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
through: 'readingsVersesrefVerses',
|
||||||
|
});
|
||||||
|
|
||||||
|
db.readings.belongsToMany(db.verses, {
|
||||||
|
as: 'verses_select',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'readings_verses_selectId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
through: 'readingsVerses_selectVerses',
|
||||||
|
});
|
||||||
|
|
||||||
|
db.readings.belongsToMany(db.verses, {
|
||||||
|
as: 'verses_select_filter',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'readings_verses_selectId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
through: 'readingsVerses_selectVerses',
|
||||||
|
});
|
||||||
|
|
||||||
/// 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
|
||||||
|
|
||||||
db.readings.hasMany(db.notes, {
|
db.readings.hasMany(db.notes, {
|
||||||
@ -72,6 +112,54 @@ module.exports = function (sequelize, DataTypes) {
|
|||||||
constraints: false,
|
constraints: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
db.readings.belongsTo(db.books, {
|
||||||
|
as: 'bookref',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'bookrefId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
db.readings.belongsTo(db.chapters, {
|
||||||
|
as: 'chapterref',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'chapterrefId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
db.readings.belongsTo(db.translations, {
|
||||||
|
as: 'translationref',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'translationrefId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
db.readings.belongsTo(db.books, {
|
||||||
|
as: 'book_select',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'book_selectId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
db.readings.belongsTo(db.chapters, {
|
||||||
|
as: 'chapter_select',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'chapter_selectId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
db.readings.belongsTo(db.translations, {
|
||||||
|
as: 'translation_select',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'translation_selectId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
});
|
||||||
|
|
||||||
db.readings.belongsTo(db.users, {
|
db.readings.belongsTo(db.users, {
|
||||||
as: 'createdBy',
|
as: 'createdBy',
|
||||||
});
|
});
|
||||||
|
|||||||
65
backend/src/db/models/translations.js
Normal file
65
backend/src/db/models/translations.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
const config = require('../../config');
|
||||||
|
const providers = config.providers;
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const bcrypt = require('bcrypt');
|
||||||
|
const moment = require('moment');
|
||||||
|
|
||||||
|
module.exports = function (sequelize, DataTypes) {
|
||||||
|
const translations = sequelize.define(
|
||||||
|
'translations',
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
type: DataTypes.UUID,
|
||||||
|
defaultValue: DataTypes.UUIDV4,
|
||||||
|
primaryKey: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
name: {
|
||||||
|
type: DataTypes.TEXT,
|
||||||
|
},
|
||||||
|
|
||||||
|
importHash: {
|
||||||
|
type: DataTypes.STRING(255),
|
||||||
|
allowNull: true,
|
||||||
|
unique: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timestamps: true,
|
||||||
|
paranoid: true,
|
||||||
|
freezeTableName: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
translations.associate = (db) => {
|
||||||
|
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
||||||
|
|
||||||
|
db.translations.hasMany(db.readings, {
|
||||||
|
as: 'readings_translationref',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'translationrefId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
db.translations.hasMany(db.readings, {
|
||||||
|
as: 'readings_translation_select',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'translation_selectId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
//end loop
|
||||||
|
|
||||||
|
db.translations.belongsTo(db.users, {
|
||||||
|
as: 'createdBy',
|
||||||
|
});
|
||||||
|
|
||||||
|
db.translations.belongsTo(db.users, {
|
||||||
|
as: 'updatedBy',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return translations;
|
||||||
|
};
|
||||||
@ -7,6 +7,14 @@ const Progress = db.progress;
|
|||||||
|
|
||||||
const Readings = db.readings;
|
const Readings = db.readings;
|
||||||
|
|
||||||
|
const Books = db.books;
|
||||||
|
|
||||||
|
const Chapters = db.chapters;
|
||||||
|
|
||||||
|
const Verses = db.verses;
|
||||||
|
|
||||||
|
const Translations = db.translations;
|
||||||
|
|
||||||
const NotesData = [
|
const NotesData = [
|
||||||
{
|
{
|
||||||
content: 'Reflecting on the creation story.',
|
content: 'Reflecting on the creation story.',
|
||||||
@ -37,6 +45,16 @@ const NotesData = [
|
|||||||
|
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
content: 'Blessings of the kingdom.',
|
||||||
|
|
||||||
|
tags: 'Beatitudes,blessings',
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const ProgressData = [
|
const ProgressData = [
|
||||||
@ -69,6 +87,16 @@ const ProgressData = [
|
|||||||
|
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
book: 'Matthew',
|
||||||
|
|
||||||
|
chapter: 5,
|
||||||
|
|
||||||
|
read: true,
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const ReadingsData = [
|
const ReadingsData = [
|
||||||
@ -86,6 +114,24 @@ const ReadingsData = [
|
|||||||
notes: 'In the beginning, God created the heavens and the earth.',
|
notes: 'In the beginning, God created the heavens and the earth.',
|
||||||
|
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_many" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_many" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
tags: 'Max Planck',
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -102,6 +148,24 @@ const ReadingsData = [
|
|||||||
notes: 'Moses and the burning bush.',
|
notes: 'Moses and the burning bush.',
|
||||||
|
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_many" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_many" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
tags: 'Francis Galton',
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -118,6 +182,138 @@ const ReadingsData = [
|
|||||||
notes: 'The Lord is my shepherd.',
|
notes: 'The Lord is my shepherd.',
|
||||||
|
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_many" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_many" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
tags: 'Comte de Buffon',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
date: new Date('2023-10-04T08:00:00Z'),
|
||||||
|
|
||||||
|
book: 'Matthew',
|
||||||
|
|
||||||
|
chapter: 5,
|
||||||
|
|
||||||
|
verses: '1-12',
|
||||||
|
|
||||||
|
translation: 'NKJV',
|
||||||
|
|
||||||
|
notes: 'The Beatitudes.',
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_many" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
// type code here for "relation_many" field
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
|
||||||
|
tags: 'Albert Einstein',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const BooksData = [
|
||||||
|
{
|
||||||
|
name: 'Linus Pauling',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: 'Marie Curie',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: 'Alfred Binet',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: 'Konrad Lorenz',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const ChaptersData = [
|
||||||
|
{
|
||||||
|
number: 4,
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
number: 3,
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
number: 9,
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
number: 1,
|
||||||
|
|
||||||
|
// type code here for "relation_one" field
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const VersesData = [
|
||||||
|
{
|
||||||
|
number: 2,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
number: 3,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
number: 5,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
number: 5,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const TranslationsData = [
|
||||||
|
{
|
||||||
|
name: 'Konrad Lorenz',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: 'Enrico Fermi',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: 'Paul Ehrlich',
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: 'Sheldon Glashow',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -156,6 +352,17 @@ async function associateNoteWithReading() {
|
|||||||
if (Note2?.setReading) {
|
if (Note2?.setReading) {
|
||||||
await Note2.setReading(relatedReading2);
|
await Note2.setReading(relatedReading2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const relatedReading3 = await Readings.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Readings.count())),
|
||||||
|
});
|
||||||
|
const Note3 = await Notes.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 3,
|
||||||
|
});
|
||||||
|
if (Note3?.setReading) {
|
||||||
|
await Note3.setReading(relatedReading3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function associateNoteWithUser() {
|
async function associateNoteWithUser() {
|
||||||
@ -191,6 +398,17 @@ async function associateNoteWithUser() {
|
|||||||
if (Note2?.setUser) {
|
if (Note2?.setUser) {
|
||||||
await Note2.setUser(relatedUser2);
|
await Note2.setUser(relatedUser2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const relatedUser3 = await Users.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Users.count())),
|
||||||
|
});
|
||||||
|
const Note3 = await Notes.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 3,
|
||||||
|
});
|
||||||
|
if (Note3?.setUser) {
|
||||||
|
await Note3.setUser(relatedUser3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function associateProgressWithUser() {
|
async function associateProgressWithUser() {
|
||||||
@ -226,6 +444,17 @@ async function associateProgressWithUser() {
|
|||||||
if (Progress2?.setUser) {
|
if (Progress2?.setUser) {
|
||||||
await Progress2.setUser(relatedUser2);
|
await Progress2.setUser(relatedUser2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const relatedUser3 = await Users.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Users.count())),
|
||||||
|
});
|
||||||
|
const Progress3 = await Progress.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 3,
|
||||||
|
});
|
||||||
|
if (Progress3?.setUser) {
|
||||||
|
await Progress3.setUser(relatedUser3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function associateReadingWithUser() {
|
async function associateReadingWithUser() {
|
||||||
@ -261,6 +490,343 @@ async function associateReadingWithUser() {
|
|||||||
if (Reading2?.setUser) {
|
if (Reading2?.setUser) {
|
||||||
await Reading2.setUser(relatedUser2);
|
await Reading2.setUser(relatedUser2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const relatedUser3 = await Users.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Users.count())),
|
||||||
|
});
|
||||||
|
const Reading3 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 3,
|
||||||
|
});
|
||||||
|
if (Reading3?.setUser) {
|
||||||
|
await Reading3.setUser(relatedUser3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function associateReadingWithBookref() {
|
||||||
|
const relatedBookref0 = await Books.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Books.count())),
|
||||||
|
});
|
||||||
|
const Reading0 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 0,
|
||||||
|
});
|
||||||
|
if (Reading0?.setBookref) {
|
||||||
|
await Reading0.setBookref(relatedBookref0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedBookref1 = await Books.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Books.count())),
|
||||||
|
});
|
||||||
|
const Reading1 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 1,
|
||||||
|
});
|
||||||
|
if (Reading1?.setBookref) {
|
||||||
|
await Reading1.setBookref(relatedBookref1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedBookref2 = await Books.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Books.count())),
|
||||||
|
});
|
||||||
|
const Reading2 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 2,
|
||||||
|
});
|
||||||
|
if (Reading2?.setBookref) {
|
||||||
|
await Reading2.setBookref(relatedBookref2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedBookref3 = await Books.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Books.count())),
|
||||||
|
});
|
||||||
|
const Reading3 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 3,
|
||||||
|
});
|
||||||
|
if (Reading3?.setBookref) {
|
||||||
|
await Reading3.setBookref(relatedBookref3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function associateReadingWithChapterref() {
|
||||||
|
const relatedChapterref0 = await Chapters.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Chapters.count())),
|
||||||
|
});
|
||||||
|
const Reading0 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 0,
|
||||||
|
});
|
||||||
|
if (Reading0?.setChapterref) {
|
||||||
|
await Reading0.setChapterref(relatedChapterref0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedChapterref1 = await Chapters.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Chapters.count())),
|
||||||
|
});
|
||||||
|
const Reading1 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 1,
|
||||||
|
});
|
||||||
|
if (Reading1?.setChapterref) {
|
||||||
|
await Reading1.setChapterref(relatedChapterref1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedChapterref2 = await Chapters.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Chapters.count())),
|
||||||
|
});
|
||||||
|
const Reading2 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 2,
|
||||||
|
});
|
||||||
|
if (Reading2?.setChapterref) {
|
||||||
|
await Reading2.setChapterref(relatedChapterref2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedChapterref3 = await Chapters.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Chapters.count())),
|
||||||
|
});
|
||||||
|
const Reading3 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 3,
|
||||||
|
});
|
||||||
|
if (Reading3?.setChapterref) {
|
||||||
|
await Reading3.setChapterref(relatedChapterref3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Similar logic for "relation_many"
|
||||||
|
|
||||||
|
async function associateReadingWithTranslationref() {
|
||||||
|
const relatedTranslationref0 = await Translations.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Translations.count())),
|
||||||
|
});
|
||||||
|
const Reading0 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 0,
|
||||||
|
});
|
||||||
|
if (Reading0?.setTranslationref) {
|
||||||
|
await Reading0.setTranslationref(relatedTranslationref0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedTranslationref1 = await Translations.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Translations.count())),
|
||||||
|
});
|
||||||
|
const Reading1 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 1,
|
||||||
|
});
|
||||||
|
if (Reading1?.setTranslationref) {
|
||||||
|
await Reading1.setTranslationref(relatedTranslationref1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedTranslationref2 = await Translations.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Translations.count())),
|
||||||
|
});
|
||||||
|
const Reading2 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 2,
|
||||||
|
});
|
||||||
|
if (Reading2?.setTranslationref) {
|
||||||
|
await Reading2.setTranslationref(relatedTranslationref2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedTranslationref3 = await Translations.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Translations.count())),
|
||||||
|
});
|
||||||
|
const Reading3 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 3,
|
||||||
|
});
|
||||||
|
if (Reading3?.setTranslationref) {
|
||||||
|
await Reading3.setTranslationref(relatedTranslationref3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function associateReadingWithBook_select() {
|
||||||
|
const relatedBook_select0 = await Books.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Books.count())),
|
||||||
|
});
|
||||||
|
const Reading0 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 0,
|
||||||
|
});
|
||||||
|
if (Reading0?.setBook_select) {
|
||||||
|
await Reading0.setBook_select(relatedBook_select0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedBook_select1 = await Books.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Books.count())),
|
||||||
|
});
|
||||||
|
const Reading1 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 1,
|
||||||
|
});
|
||||||
|
if (Reading1?.setBook_select) {
|
||||||
|
await Reading1.setBook_select(relatedBook_select1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedBook_select2 = await Books.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Books.count())),
|
||||||
|
});
|
||||||
|
const Reading2 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 2,
|
||||||
|
});
|
||||||
|
if (Reading2?.setBook_select) {
|
||||||
|
await Reading2.setBook_select(relatedBook_select2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedBook_select3 = await Books.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Books.count())),
|
||||||
|
});
|
||||||
|
const Reading3 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 3,
|
||||||
|
});
|
||||||
|
if (Reading3?.setBook_select) {
|
||||||
|
await Reading3.setBook_select(relatedBook_select3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function associateReadingWithChapter_select() {
|
||||||
|
const relatedChapter_select0 = await Chapters.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Chapters.count())),
|
||||||
|
});
|
||||||
|
const Reading0 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 0,
|
||||||
|
});
|
||||||
|
if (Reading0?.setChapter_select) {
|
||||||
|
await Reading0.setChapter_select(relatedChapter_select0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedChapter_select1 = await Chapters.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Chapters.count())),
|
||||||
|
});
|
||||||
|
const Reading1 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 1,
|
||||||
|
});
|
||||||
|
if (Reading1?.setChapter_select) {
|
||||||
|
await Reading1.setChapter_select(relatedChapter_select1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedChapter_select2 = await Chapters.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Chapters.count())),
|
||||||
|
});
|
||||||
|
const Reading2 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 2,
|
||||||
|
});
|
||||||
|
if (Reading2?.setChapter_select) {
|
||||||
|
await Reading2.setChapter_select(relatedChapter_select2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedChapter_select3 = await Chapters.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Chapters.count())),
|
||||||
|
});
|
||||||
|
const Reading3 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 3,
|
||||||
|
});
|
||||||
|
if (Reading3?.setChapter_select) {
|
||||||
|
await Reading3.setChapter_select(relatedChapter_select3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Similar logic for "relation_many"
|
||||||
|
|
||||||
|
async function associateReadingWithTranslation_select() {
|
||||||
|
const relatedTranslation_select0 = await Translations.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Translations.count())),
|
||||||
|
});
|
||||||
|
const Reading0 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 0,
|
||||||
|
});
|
||||||
|
if (Reading0?.setTranslation_select) {
|
||||||
|
await Reading0.setTranslation_select(relatedTranslation_select0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedTranslation_select1 = await Translations.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Translations.count())),
|
||||||
|
});
|
||||||
|
const Reading1 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 1,
|
||||||
|
});
|
||||||
|
if (Reading1?.setTranslation_select) {
|
||||||
|
await Reading1.setTranslation_select(relatedTranslation_select1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedTranslation_select2 = await Translations.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Translations.count())),
|
||||||
|
});
|
||||||
|
const Reading2 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 2,
|
||||||
|
});
|
||||||
|
if (Reading2?.setTranslation_select) {
|
||||||
|
await Reading2.setTranslation_select(relatedTranslation_select2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedTranslation_select3 = await Translations.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Translations.count())),
|
||||||
|
});
|
||||||
|
const Reading3 = await Readings.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 3,
|
||||||
|
});
|
||||||
|
if (Reading3?.setTranslation_select) {
|
||||||
|
await Reading3.setTranslation_select(relatedTranslation_select3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function associateChapterWithBook() {
|
||||||
|
const relatedBook0 = await Books.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Books.count())),
|
||||||
|
});
|
||||||
|
const Chapter0 = await Chapters.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 0,
|
||||||
|
});
|
||||||
|
if (Chapter0?.setBook) {
|
||||||
|
await Chapter0.setBook(relatedBook0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedBook1 = await Books.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Books.count())),
|
||||||
|
});
|
||||||
|
const Chapter1 = await Chapters.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 1,
|
||||||
|
});
|
||||||
|
if (Chapter1?.setBook) {
|
||||||
|
await Chapter1.setBook(relatedBook1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedBook2 = await Books.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Books.count())),
|
||||||
|
});
|
||||||
|
const Chapter2 = await Chapters.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 2,
|
||||||
|
});
|
||||||
|
if (Chapter2?.setBook) {
|
||||||
|
await Chapter2.setBook(relatedBook2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const relatedBook3 = await Books.findOne({
|
||||||
|
offset: Math.floor(Math.random() * (await Books.count())),
|
||||||
|
});
|
||||||
|
const Chapter3 = await Chapters.findOne({
|
||||||
|
order: [['id', 'ASC']],
|
||||||
|
offset: 3,
|
||||||
|
});
|
||||||
|
if (Chapter3?.setBook) {
|
||||||
|
await Chapter3.setBook(relatedBook3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
@ -271,6 +837,14 @@ module.exports = {
|
|||||||
|
|
||||||
await Readings.bulkCreate(ReadingsData);
|
await Readings.bulkCreate(ReadingsData);
|
||||||
|
|
||||||
|
await Books.bulkCreate(BooksData);
|
||||||
|
|
||||||
|
await Chapters.bulkCreate(ChaptersData);
|
||||||
|
|
||||||
|
await Verses.bulkCreate(VersesData);
|
||||||
|
|
||||||
|
await Translations.bulkCreate(TranslationsData);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
// Similar logic for "relation_many"
|
// Similar logic for "relation_many"
|
||||||
|
|
||||||
@ -281,6 +855,24 @@ module.exports = {
|
|||||||
await associateProgressWithUser(),
|
await associateProgressWithUser(),
|
||||||
|
|
||||||
await associateReadingWithUser(),
|
await associateReadingWithUser(),
|
||||||
|
|
||||||
|
await associateReadingWithBookref(),
|
||||||
|
|
||||||
|
await associateReadingWithChapterref(),
|
||||||
|
|
||||||
|
// Similar logic for "relation_many"
|
||||||
|
|
||||||
|
await associateReadingWithTranslationref(),
|
||||||
|
|
||||||
|
await associateReadingWithBook_select(),
|
||||||
|
|
||||||
|
await associateReadingWithChapter_select(),
|
||||||
|
|
||||||
|
// Similar logic for "relation_many"
|
||||||
|
|
||||||
|
await associateReadingWithTranslation_select(),
|
||||||
|
|
||||||
|
await associateChapterWithBook(),
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -290,5 +882,13 @@ module.exports = {
|
|||||||
await queryInterface.bulkDelete('progress', null, {});
|
await queryInterface.bulkDelete('progress', null, {});
|
||||||
|
|
||||||
await queryInterface.bulkDelete('readings', null, {});
|
await queryInterface.bulkDelete('readings', null, {});
|
||||||
|
|
||||||
|
await queryInterface.bulkDelete('books', null, {});
|
||||||
|
|
||||||
|
await queryInterface.bulkDelete('chapters', null, {});
|
||||||
|
|
||||||
|
await queryInterface.bulkDelete('verses', null, {});
|
||||||
|
|
||||||
|
await queryInterface.bulkDelete('translations', null, {});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -32,6 +32,9 @@ router.use(checkCrudPermissions('readings'));
|
|||||||
* notes:
|
* notes:
|
||||||
* type: string
|
* type: string
|
||||||
* default: notes
|
* default: notes
|
||||||
|
* tags:
|
||||||
|
* type: string
|
||||||
|
* default: tags
|
||||||
|
|
||||||
* chapter:
|
* chapter:
|
||||||
* type: integer
|
* type: integer
|
||||||
@ -323,6 +326,7 @@ router.get(
|
|||||||
'verses',
|
'verses',
|
||||||
'translation',
|
'translation',
|
||||||
'notes',
|
'notes',
|
||||||
|
'tags',
|
||||||
'chapter',
|
'chapter',
|
||||||
|
|
||||||
'date',
|
'date',
|
||||||
|
|||||||
@ -47,12 +47,20 @@ module.exports = class SearchService {
|
|||||||
|
|
||||||
progress: ['book'],
|
progress: ['book'],
|
||||||
|
|
||||||
readings: ['book', 'verses', 'translation', 'notes'],
|
readings: ['book', 'verses', 'translation', 'notes', 'tags'],
|
||||||
|
|
||||||
|
books: ['name'],
|
||||||
|
|
||||||
|
translations: ['name'],
|
||||||
};
|
};
|
||||||
const columnsInt = {
|
const columnsInt = {
|
||||||
progress: ['chapter'],
|
progress: ['chapter'],
|
||||||
|
|
||||||
readings: ['chapter'],
|
readings: ['chapter'],
|
||||||
|
|
||||||
|
chapters: ['number'],
|
||||||
|
|
||||||
|
verses: ['number'],
|
||||||
};
|
};
|
||||||
|
|
||||||
let allFoundRecords = [];
|
let allFoundRecords = [];
|
||||||
|
|||||||
@ -62,7 +62,7 @@ const CardReadings = ({
|
|||||||
href={`/readings/readings-view/?id=${item.id}`}
|
href={`/readings/readings-view/?id=${item.id}`}
|
||||||
className='text-lg font-bold leading-6 line-clamp-1'
|
className='text-lg font-bold leading-6 line-clamp-1'
|
||||||
>
|
>
|
||||||
{item.book}
|
{item.tags}
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<div className='ml-auto '>
|
<div className='ml-auto '>
|
||||||
@ -140,6 +140,111 @@ const CardReadings = ({
|
|||||||
</div>
|
</div>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
|
Bookref
|
||||||
|
</dt>
|
||||||
|
<dd className='flex items-start gap-x-2'>
|
||||||
|
<div className='font-medium line-clamp-4'>
|
||||||
|
{dataFormatter.booksOneListFormatter(item.bookref)}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
|
Chapterref
|
||||||
|
</dt>
|
||||||
|
<dd className='flex items-start gap-x-2'>
|
||||||
|
<div className='font-medium line-clamp-4'>
|
||||||
|
{dataFormatter.chaptersOneListFormatter(item.chapterref)}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
|
Versesref
|
||||||
|
</dt>
|
||||||
|
<dd className='flex items-start gap-x-2'>
|
||||||
|
<div className='font-medium line-clamp-4'>
|
||||||
|
{dataFormatter
|
||||||
|
.versesManyListFormatter(item.versesref)
|
||||||
|
.join(', ')}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
|
Translationref
|
||||||
|
</dt>
|
||||||
|
<dd className='flex items-start gap-x-2'>
|
||||||
|
<div className='font-medium line-clamp-4'>
|
||||||
|
{dataFormatter.translationsOneListFormatter(
|
||||||
|
item.translationref,
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
|
Book_select
|
||||||
|
</dt>
|
||||||
|
<dd className='flex items-start gap-x-2'>
|
||||||
|
<div className='font-medium line-clamp-4'>
|
||||||
|
{dataFormatter.booksOneListFormatter(item.book_select)}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
|
Chapter_select
|
||||||
|
</dt>
|
||||||
|
<dd className='flex items-start gap-x-2'>
|
||||||
|
<div className='font-medium line-clamp-4'>
|
||||||
|
{dataFormatter.chaptersOneListFormatter(
|
||||||
|
item.chapter_select,
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
|
Verses_select
|
||||||
|
</dt>
|
||||||
|
<dd className='flex items-start gap-x-2'>
|
||||||
|
<div className='font-medium line-clamp-4'>
|
||||||
|
{dataFormatter
|
||||||
|
.versesManyListFormatter(item.verses_select)
|
||||||
|
.join(', ')}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
|
Translation_select
|
||||||
|
</dt>
|
||||||
|
<dd className='flex items-start gap-x-2'>
|
||||||
|
<div className='font-medium line-clamp-4'>
|
||||||
|
{dataFormatter.translationsOneListFormatter(
|
||||||
|
item.translation_select,
|
||||||
|
)}
|
||||||
|
</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'>
|
||||||
|
<div className='font-medium line-clamp-4'>{item.tags}</div>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
</dl>
|
</dl>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -89,6 +89,87 @@ const ListReadings = ({
|
|||||||
{dataFormatter.usersOneListFormatter(item.user)}
|
{dataFormatter.usersOneListFormatter(item.user)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Bookref</p>
|
||||||
|
<p className={'line-clamp-2'}>
|
||||||
|
{dataFormatter.booksOneListFormatter(item.bookref)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Chapterref</p>
|
||||||
|
<p className={'line-clamp-2'}>
|
||||||
|
{dataFormatter.chaptersOneListFormatter(
|
||||||
|
item.chapterref,
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Versesref</p>
|
||||||
|
<p className={'line-clamp-2'}>
|
||||||
|
{dataFormatter
|
||||||
|
.versesManyListFormatter(item.versesref)
|
||||||
|
.join(', ')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>
|
||||||
|
Translationref
|
||||||
|
</p>
|
||||||
|
<p className={'line-clamp-2'}>
|
||||||
|
{dataFormatter.translationsOneListFormatter(
|
||||||
|
item.translationref,
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Book_select</p>
|
||||||
|
<p className={'line-clamp-2'}>
|
||||||
|
{dataFormatter.booksOneListFormatter(item.book_select)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>
|
||||||
|
Chapter_select
|
||||||
|
</p>
|
||||||
|
<p className={'line-clamp-2'}>
|
||||||
|
{dataFormatter.chaptersOneListFormatter(
|
||||||
|
item.chapter_select,
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>
|
||||||
|
Verses_select
|
||||||
|
</p>
|
||||||
|
<p className={'line-clamp-2'}>
|
||||||
|
{dataFormatter
|
||||||
|
.versesManyListFormatter(item.verses_select)
|
||||||
|
.join(', ')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>
|
||||||
|
Translation_select
|
||||||
|
</p>
|
||||||
|
<p className={'line-clamp-2'}>
|
||||||
|
{dataFormatter.translationsOneListFormatter(
|
||||||
|
item.translation_select,
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Tags</p>
|
||||||
|
<p className={'line-clamp-2'}>{item.tags}</p>
|
||||||
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
<ListActionsPopover
|
<ListActionsPopover
|
||||||
onDelete={onDelete}
|
onDelete={onDelete}
|
||||||
|
|||||||
@ -135,6 +135,176 @@ export const loadColumns = async (
|
|||||||
params?.value?.id ?? params?.value,
|
params?.value?.id ?? params?.value,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'bookref',
|
||||||
|
headerName: 'Bookref',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
|
editable: hasUpdatePermission,
|
||||||
|
|
||||||
|
sortable: false,
|
||||||
|
type: 'singleSelect',
|
||||||
|
getOptionValue: (value: any) => value?.id,
|
||||||
|
getOptionLabel: (value: any) => value?.label,
|
||||||
|
valueOptions: await callOptionsApi('books'),
|
||||||
|
valueGetter: (params: GridValueGetterParams) =>
|
||||||
|
params?.value?.id ?? params?.value,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'chapterref',
|
||||||
|
headerName: 'Chapterref',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
|
editable: hasUpdatePermission,
|
||||||
|
|
||||||
|
sortable: false,
|
||||||
|
type: 'singleSelect',
|
||||||
|
getOptionValue: (value: any) => value?.id,
|
||||||
|
getOptionLabel: (value: any) => value?.label,
|
||||||
|
valueOptions: await callOptionsApi('chapters'),
|
||||||
|
valueGetter: (params: GridValueGetterParams) =>
|
||||||
|
params?.value?.id ?? params?.value,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'versesref',
|
||||||
|
headerName: 'Versesref',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
|
editable: false,
|
||||||
|
sortable: false,
|
||||||
|
type: 'singleSelect',
|
||||||
|
valueFormatter: ({ value }) =>
|
||||||
|
dataFormatter.versesManyListFormatter(value).join(', '),
|
||||||
|
renderEditCell: (params) => (
|
||||||
|
<DataGridMultiSelect {...params} entityName={'verses'} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'translationref',
|
||||||
|
headerName: 'Translationref',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
|
editable: hasUpdatePermission,
|
||||||
|
|
||||||
|
sortable: false,
|
||||||
|
type: 'singleSelect',
|
||||||
|
getOptionValue: (value: any) => value?.id,
|
||||||
|
getOptionLabel: (value: any) => value?.label,
|
||||||
|
valueOptions: await callOptionsApi('translations'),
|
||||||
|
valueGetter: (params: GridValueGetterParams) =>
|
||||||
|
params?.value?.id ?? params?.value,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'book_select',
|
||||||
|
headerName: 'Book_select',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
|
editable: hasUpdatePermission,
|
||||||
|
|
||||||
|
sortable: false,
|
||||||
|
type: 'singleSelect',
|
||||||
|
getOptionValue: (value: any) => value?.id,
|
||||||
|
getOptionLabel: (value: any) => value?.label,
|
||||||
|
valueOptions: await callOptionsApi('books'),
|
||||||
|
valueGetter: (params: GridValueGetterParams) =>
|
||||||
|
params?.value?.id ?? params?.value,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'chapter_select',
|
||||||
|
headerName: 'Chapter_select',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
|
editable: hasUpdatePermission,
|
||||||
|
|
||||||
|
sortable: false,
|
||||||
|
type: 'singleSelect',
|
||||||
|
getOptionValue: (value: any) => value?.id,
|
||||||
|
getOptionLabel: (value: any) => value?.label,
|
||||||
|
valueOptions: await callOptionsApi('chapters'),
|
||||||
|
valueGetter: (params: GridValueGetterParams) =>
|
||||||
|
params?.value?.id ?? params?.value,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'verses_select',
|
||||||
|
headerName: 'Verses_select',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
|
editable: false,
|
||||||
|
sortable: false,
|
||||||
|
type: 'singleSelect',
|
||||||
|
valueFormatter: ({ value }) =>
|
||||||
|
dataFormatter.versesManyListFormatter(value).join(', '),
|
||||||
|
renderEditCell: (params) => (
|
||||||
|
<DataGridMultiSelect {...params} entityName={'verses'} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'translation_select',
|
||||||
|
headerName: 'Translation_select',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
|
editable: hasUpdatePermission,
|
||||||
|
|
||||||
|
sortable: false,
|
||||||
|
type: 'singleSelect',
|
||||||
|
getOptionValue: (value: any) => value?.id,
|
||||||
|
getOptionLabel: (value: any) => value?.label,
|
||||||
|
valueOptions: await callOptionsApi('translations'),
|
||||||
|
valueGetter: (params: GridValueGetterParams) =>
|
||||||
|
params?.value?.id ?? params?.value,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'tags',
|
||||||
|
headerName: 'Tags',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
|
editable: hasUpdatePermission,
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
field: 'actions',
|
field: 'actions',
|
||||||
type: 'actions',
|
type: 'actions',
|
||||||
|
|||||||
@ -17,9 +17,9 @@ export default function WebSiteFooter({ projectName }: WebSiteFooterProps) {
|
|||||||
const borders = useAppSelector((state) => state.style.borders);
|
const borders = useAppSelector((state) => state.style.borders);
|
||||||
const websiteHeder = useAppSelector((state) => state.style.websiteHeder);
|
const websiteHeder = useAppSelector((state) => state.style.websiteHeder);
|
||||||
|
|
||||||
const style = FooterStyle.WITH_PROJECT_NAME;
|
const style = FooterStyle.WITH_PAGES;
|
||||||
|
|
||||||
const design = FooterDesigns.DEFAULT_DESIGN;
|
const design = FooterDesigns.DESIGN_DIVERSITY;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -17,9 +17,9 @@ export default function WebSiteHeader({ projectName }: WebSiteHeaderProps) {
|
|||||||
const websiteHeder = useAppSelector((state) => state.style.websiteHeder);
|
const websiteHeder = useAppSelector((state) => state.style.websiteHeder);
|
||||||
const borders = useAppSelector((state) => state.style.borders);
|
const borders = useAppSelector((state) => state.style.borders);
|
||||||
|
|
||||||
const style = HeaderStyle.PAGES_RIGHT;
|
const style = HeaderStyle.PAGES_LEFT;
|
||||||
|
|
||||||
const design = HeaderDesigns.DESIGN_DIVERSITY;
|
const design = HeaderDesigns.DEFAULT_DESIGN;
|
||||||
return (
|
return (
|
||||||
<header id='websiteHeader' className='overflow-hidden'>
|
<header id='websiteHeader' className='overflow-hidden'>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -60,21 +60,21 @@ export default {
|
|||||||
|
|
||||||
readingsManyListFormatter(val) {
|
readingsManyListFormatter(val) {
|
||||||
if (!val || !val.length) return [];
|
if (!val || !val.length) return [];
|
||||||
return val.map((item) => item.book);
|
return val.map((item) => item.tags);
|
||||||
},
|
},
|
||||||
readingsOneListFormatter(val) {
|
readingsOneListFormatter(val) {
|
||||||
if (!val) return '';
|
if (!val) return '';
|
||||||
return val.book;
|
return val.tags;
|
||||||
},
|
},
|
||||||
readingsManyListFormatterEdit(val) {
|
readingsManyListFormatterEdit(val) {
|
||||||
if (!val || !val.length) return [];
|
if (!val || !val.length) return [];
|
||||||
return val.map((item) => {
|
return val.map((item) => {
|
||||||
return { id: item.id, label: item.book };
|
return { id: item.id, label: item.tags };
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
readingsOneListFormatterEdit(val) {
|
readingsOneListFormatterEdit(val) {
|
||||||
if (!val) return '';
|
if (!val) return '';
|
||||||
return { label: val.book, id: val.id };
|
return { label: val.tags, id: val.id };
|
||||||
},
|
},
|
||||||
|
|
||||||
rolesManyListFormatter(val) {
|
rolesManyListFormatter(val) {
|
||||||
@ -114,4 +114,80 @@ export default {
|
|||||||
if (!val) return '';
|
if (!val) return '';
|
||||||
return { label: val.name, id: val.id };
|
return { label: val.name, id: val.id };
|
||||||
},
|
},
|
||||||
|
|
||||||
|
booksManyListFormatter(val) {
|
||||||
|
if (!val || !val.length) return [];
|
||||||
|
return val.map((item) => item.name);
|
||||||
|
},
|
||||||
|
booksOneListFormatter(val) {
|
||||||
|
if (!val) return '';
|
||||||
|
return val.name;
|
||||||
|
},
|
||||||
|
booksManyListFormatterEdit(val) {
|
||||||
|
if (!val || !val.length) return [];
|
||||||
|
return val.map((item) => {
|
||||||
|
return { id: item.id, label: item.name };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
booksOneListFormatterEdit(val) {
|
||||||
|
if (!val) return '';
|
||||||
|
return { label: val.name, id: val.id };
|
||||||
|
},
|
||||||
|
|
||||||
|
chaptersManyListFormatter(val) {
|
||||||
|
if (!val || !val.length) return [];
|
||||||
|
return val.map((item) => item.number);
|
||||||
|
},
|
||||||
|
chaptersOneListFormatter(val) {
|
||||||
|
if (!val) return '';
|
||||||
|
return val.number;
|
||||||
|
},
|
||||||
|
chaptersManyListFormatterEdit(val) {
|
||||||
|
if (!val || !val.length) return [];
|
||||||
|
return val.map((item) => {
|
||||||
|
return { id: item.id, label: item.number };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
chaptersOneListFormatterEdit(val) {
|
||||||
|
if (!val) return '';
|
||||||
|
return { label: val.number, id: val.id };
|
||||||
|
},
|
||||||
|
|
||||||
|
versesManyListFormatter(val) {
|
||||||
|
if (!val || !val.length) return [];
|
||||||
|
return val.map((item) => item.number);
|
||||||
|
},
|
||||||
|
versesOneListFormatter(val) {
|
||||||
|
if (!val) return '';
|
||||||
|
return val.number;
|
||||||
|
},
|
||||||
|
versesManyListFormatterEdit(val) {
|
||||||
|
if (!val || !val.length) return [];
|
||||||
|
return val.map((item) => {
|
||||||
|
return { id: item.id, label: item.number };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
versesOneListFormatterEdit(val) {
|
||||||
|
if (!val) return '';
|
||||||
|
return { label: val.number, id: val.id };
|
||||||
|
},
|
||||||
|
|
||||||
|
translationsManyListFormatter(val) {
|
||||||
|
if (!val || !val.length) return [];
|
||||||
|
return val.map((item) => item.name);
|
||||||
|
},
|
||||||
|
translationsOneListFormatter(val) {
|
||||||
|
if (!val) return '';
|
||||||
|
return val.name;
|
||||||
|
},
|
||||||
|
translationsManyListFormatterEdit(val) {
|
||||||
|
if (!val || !val.length) return [];
|
||||||
|
return val.map((item) => {
|
||||||
|
return { id: item.id, label: item.name };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
translationsOneListFormatterEdit(val) {
|
||||||
|
if (!val) return '';
|
||||||
|
return { label: val.name, id: val.id };
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
236
frontend/src/pages/books/books-view.tsx
Normal file
236
frontend/src/pages/books/books-view.tsx
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
import React, { ReactElement, useEffect } from 'react';
|
||||||
|
import Head from 'next/head';
|
||||||
|
import DatePicker from 'react-datepicker';
|
||||||
|
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/books/booksSlice';
|
||||||
|
import { saveFile } from '../../helpers/fileSaver';
|
||||||
|
import dataFormatter from '../../helpers/dataFormatter';
|
||||||
|
import ImageField from '../../components/ImageField';
|
||||||
|
import LayoutAuthenticated from '../../layouts/Authenticated';
|
||||||
|
import { getPageTitle } from '../../config';
|
||||||
|
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton';
|
||||||
|
import SectionMain from '../../components/SectionMain';
|
||||||
|
import CardBox from '../../components/CardBox';
|
||||||
|
import BaseButton from '../../components/BaseButton';
|
||||||
|
import BaseDivider from '../../components/BaseDivider';
|
||||||
|
import { mdiChartTimelineVariant } from '@mdi/js';
|
||||||
|
import { SwitchField } from '../../components/SwitchField';
|
||||||
|
import FormField from '../../components/FormField';
|
||||||
|
|
||||||
|
const BooksView = () => {
|
||||||
|
const router = useRouter();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { books } = useAppSelector((state) => state.books);
|
||||||
|
|
||||||
|
const { id } = router.query;
|
||||||
|
|
||||||
|
function removeLastCharacter(str) {
|
||||||
|
console.log(str, `str`);
|
||||||
|
return str.slice(0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(fetch({ id }));
|
||||||
|
}, [dispatch, id]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>{getPageTitle('View books')}</title>
|
||||||
|
</Head>
|
||||||
|
<SectionMain>
|
||||||
|
<SectionTitleLineWithButton
|
||||||
|
icon={mdiChartTimelineVariant}
|
||||||
|
title={removeLastCharacter('View books')}
|
||||||
|
main
|
||||||
|
>
|
||||||
|
<BaseButton
|
||||||
|
color='info'
|
||||||
|
label='Edit'
|
||||||
|
href={`/books/books-edit/?id=${id}`}
|
||||||
|
/>
|
||||||
|
</SectionTitleLineWithButton>
|
||||||
|
<CardBox>
|
||||||
|
<div className={'mb-4'}>
|
||||||
|
<p className={'block font-bold mb-2'}>Name</p>
|
||||||
|
<p>{books?.name}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<>
|
||||||
|
<p className={'block font-bold mb-2'}>Readings Bookref</p>
|
||||||
|
<CardBox
|
||||||
|
className='mb-6 border border-gray-300 rounded overflow-hidden'
|
||||||
|
hasTable
|
||||||
|
>
|
||||||
|
<div className='overflow-x-auto'>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Date</th>
|
||||||
|
|
||||||
|
<th>Book</th>
|
||||||
|
|
||||||
|
<th>Chapter</th>
|
||||||
|
|
||||||
|
<th>Verses</th>
|
||||||
|
|
||||||
|
<th>Translation</th>
|
||||||
|
|
||||||
|
<th>Tags</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{books.readings_bookref &&
|
||||||
|
Array.isArray(books.readings_bookref) &&
|
||||||
|
books.readings_bookref.map((item: any) => (
|
||||||
|
<tr
|
||||||
|
key={item.id}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(
|
||||||
|
`/readings/readings-view/?id=${item.id}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<td data-label='date'>
|
||||||
|
{dataFormatter.dateTimeFormatter(item.date)}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td data-label='book'>{item.book}</td>
|
||||||
|
|
||||||
|
<td data-label='chapter'>{item.chapter}</td>
|
||||||
|
|
||||||
|
<td data-label='verses'>{item.verses}</td>
|
||||||
|
|
||||||
|
<td data-label='translation'>{item.translation}</td>
|
||||||
|
|
||||||
|
<td data-label='tags'>{item.tags}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{!books?.readings_bookref?.length && (
|
||||||
|
<div className={'text-center py-4'}>No data</div>
|
||||||
|
)}
|
||||||
|
</CardBox>
|
||||||
|
</>
|
||||||
|
|
||||||
|
<>
|
||||||
|
<p className={'block font-bold mb-2'}>Readings Book_select</p>
|
||||||
|
<CardBox
|
||||||
|
className='mb-6 border border-gray-300 rounded overflow-hidden'
|
||||||
|
hasTable
|
||||||
|
>
|
||||||
|
<div className='overflow-x-auto'>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Date</th>
|
||||||
|
|
||||||
|
<th>Book</th>
|
||||||
|
|
||||||
|
<th>Chapter</th>
|
||||||
|
|
||||||
|
<th>Verses</th>
|
||||||
|
|
||||||
|
<th>Translation</th>
|
||||||
|
|
||||||
|
<th>Tags</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{books.readings_book_select &&
|
||||||
|
Array.isArray(books.readings_book_select) &&
|
||||||
|
books.readings_book_select.map((item: any) => (
|
||||||
|
<tr
|
||||||
|
key={item.id}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(
|
||||||
|
`/readings/readings-view/?id=${item.id}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<td data-label='date'>
|
||||||
|
{dataFormatter.dateTimeFormatter(item.date)}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td data-label='book'>{item.book}</td>
|
||||||
|
|
||||||
|
<td data-label='chapter'>{item.chapter}</td>
|
||||||
|
|
||||||
|
<td data-label='verses'>{item.verses}</td>
|
||||||
|
|
||||||
|
<td data-label='translation'>{item.translation}</td>
|
||||||
|
|
||||||
|
<td data-label='tags'>{item.tags}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{!books?.readings_book_select?.length && (
|
||||||
|
<div className={'text-center py-4'}>No data</div>
|
||||||
|
)}
|
||||||
|
</CardBox>
|
||||||
|
</>
|
||||||
|
|
||||||
|
<>
|
||||||
|
<p className={'block font-bold mb-2'}>Chapters Book</p>
|
||||||
|
<CardBox
|
||||||
|
className='mb-6 border border-gray-300 rounded overflow-hidden'
|
||||||
|
hasTable
|
||||||
|
>
|
||||||
|
<div className='overflow-x-auto'>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Number</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{books.chapters_book &&
|
||||||
|
Array.isArray(books.chapters_book) &&
|
||||||
|
books.chapters_book.map((item: any) => (
|
||||||
|
<tr
|
||||||
|
key={item.id}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(
|
||||||
|
`/chapters/chapters-view/?id=${item.id}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<td data-label='number'>{item.number}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{!books?.chapters_book?.length && (
|
||||||
|
<div className={'text-center py-4'}>No data</div>
|
||||||
|
)}
|
||||||
|
</CardBox>
|
||||||
|
</>
|
||||||
|
|
||||||
|
<BaseDivider />
|
||||||
|
|
||||||
|
<BaseButton
|
||||||
|
color='info'
|
||||||
|
label='Back'
|
||||||
|
onClick={() => router.push('/books/books-list')}
|
||||||
|
/>
|
||||||
|
</CardBox>
|
||||||
|
</SectionMain>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
BooksView.getLayout = function getLayout(page: ReactElement) {
|
||||||
|
return (
|
||||||
|
<LayoutAuthenticated permission={'READ_BOOKS'}>{page}</LayoutAuthenticated>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default BooksView;
|
||||||
207
frontend/src/pages/chapters/chapters-view.tsx
Normal file
207
frontend/src/pages/chapters/chapters-view.tsx
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
import React, { ReactElement, useEffect } from 'react';
|
||||||
|
import Head from 'next/head';
|
||||||
|
import DatePicker from 'react-datepicker';
|
||||||
|
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/chapters/chaptersSlice';
|
||||||
|
import { saveFile } from '../../helpers/fileSaver';
|
||||||
|
import dataFormatter from '../../helpers/dataFormatter';
|
||||||
|
import ImageField from '../../components/ImageField';
|
||||||
|
import LayoutAuthenticated from '../../layouts/Authenticated';
|
||||||
|
import { getPageTitle } from '../../config';
|
||||||
|
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton';
|
||||||
|
import SectionMain from '../../components/SectionMain';
|
||||||
|
import CardBox from '../../components/CardBox';
|
||||||
|
import BaseButton from '../../components/BaseButton';
|
||||||
|
import BaseDivider from '../../components/BaseDivider';
|
||||||
|
import { mdiChartTimelineVariant } from '@mdi/js';
|
||||||
|
import { SwitchField } from '../../components/SwitchField';
|
||||||
|
import FormField from '../../components/FormField';
|
||||||
|
|
||||||
|
const ChaptersView = () => {
|
||||||
|
const router = useRouter();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { chapters } = useAppSelector((state) => state.chapters);
|
||||||
|
|
||||||
|
const { id } = router.query;
|
||||||
|
|
||||||
|
function removeLastCharacter(str) {
|
||||||
|
console.log(str, `str`);
|
||||||
|
return str.slice(0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(fetch({ id }));
|
||||||
|
}, [dispatch, id]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>{getPageTitle('View chapters')}</title>
|
||||||
|
</Head>
|
||||||
|
<SectionMain>
|
||||||
|
<SectionTitleLineWithButton
|
||||||
|
icon={mdiChartTimelineVariant}
|
||||||
|
title={removeLastCharacter('View chapters')}
|
||||||
|
main
|
||||||
|
>
|
||||||
|
<BaseButton
|
||||||
|
color='info'
|
||||||
|
label='Edit'
|
||||||
|
href={`/chapters/chapters-edit/?id=${id}`}
|
||||||
|
/>
|
||||||
|
</SectionTitleLineWithButton>
|
||||||
|
<CardBox>
|
||||||
|
<div className={'mb-4'}>
|
||||||
|
<p className={'block font-bold mb-2'}>Number</p>
|
||||||
|
<p>{chapters?.number || 'No data'}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'mb-4'}>
|
||||||
|
<p className={'block font-bold mb-2'}>Book</p>
|
||||||
|
|
||||||
|
<p>{chapters?.book?.name ?? 'No data'}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<>
|
||||||
|
<p className={'block font-bold mb-2'}>Readings Chapterref</p>
|
||||||
|
<CardBox
|
||||||
|
className='mb-6 border border-gray-300 rounded overflow-hidden'
|
||||||
|
hasTable
|
||||||
|
>
|
||||||
|
<div className='overflow-x-auto'>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Date</th>
|
||||||
|
|
||||||
|
<th>Book</th>
|
||||||
|
|
||||||
|
<th>Chapter</th>
|
||||||
|
|
||||||
|
<th>Verses</th>
|
||||||
|
|
||||||
|
<th>Translation</th>
|
||||||
|
|
||||||
|
<th>Tags</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{chapters.readings_chapterref &&
|
||||||
|
Array.isArray(chapters.readings_chapterref) &&
|
||||||
|
chapters.readings_chapterref.map((item: any) => (
|
||||||
|
<tr
|
||||||
|
key={item.id}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(
|
||||||
|
`/readings/readings-view/?id=${item.id}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<td data-label='date'>
|
||||||
|
{dataFormatter.dateTimeFormatter(item.date)}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td data-label='book'>{item.book}</td>
|
||||||
|
|
||||||
|
<td data-label='chapter'>{item.chapter}</td>
|
||||||
|
|
||||||
|
<td data-label='verses'>{item.verses}</td>
|
||||||
|
|
||||||
|
<td data-label='translation'>{item.translation}</td>
|
||||||
|
|
||||||
|
<td data-label='tags'>{item.tags}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{!chapters?.readings_chapterref?.length && (
|
||||||
|
<div className={'text-center py-4'}>No data</div>
|
||||||
|
)}
|
||||||
|
</CardBox>
|
||||||
|
</>
|
||||||
|
|
||||||
|
<>
|
||||||
|
<p className={'block font-bold mb-2'}>Readings Chapter_select</p>
|
||||||
|
<CardBox
|
||||||
|
className='mb-6 border border-gray-300 rounded overflow-hidden'
|
||||||
|
hasTable
|
||||||
|
>
|
||||||
|
<div className='overflow-x-auto'>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Date</th>
|
||||||
|
|
||||||
|
<th>Book</th>
|
||||||
|
|
||||||
|
<th>Chapter</th>
|
||||||
|
|
||||||
|
<th>Verses</th>
|
||||||
|
|
||||||
|
<th>Translation</th>
|
||||||
|
|
||||||
|
<th>Tags</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{chapters.readings_chapter_select &&
|
||||||
|
Array.isArray(chapters.readings_chapter_select) &&
|
||||||
|
chapters.readings_chapter_select.map((item: any) => (
|
||||||
|
<tr
|
||||||
|
key={item.id}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(
|
||||||
|
`/readings/readings-view/?id=${item.id}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<td data-label='date'>
|
||||||
|
{dataFormatter.dateTimeFormatter(item.date)}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td data-label='book'>{item.book}</td>
|
||||||
|
|
||||||
|
<td data-label='chapter'>{item.chapter}</td>
|
||||||
|
|
||||||
|
<td data-label='verses'>{item.verses}</td>
|
||||||
|
|
||||||
|
<td data-label='translation'>{item.translation}</td>
|
||||||
|
|
||||||
|
<td data-label='tags'>{item.tags}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{!chapters?.readings_chapter_select?.length && (
|
||||||
|
<div className={'text-center py-4'}>No data</div>
|
||||||
|
)}
|
||||||
|
</CardBox>
|
||||||
|
</>
|
||||||
|
|
||||||
|
<BaseDivider />
|
||||||
|
|
||||||
|
<BaseButton
|
||||||
|
color='info'
|
||||||
|
label='Back'
|
||||||
|
onClick={() => router.push('/chapters/chapters-list')}
|
||||||
|
/>
|
||||||
|
</CardBox>
|
||||||
|
</SectionMain>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ChaptersView.getLayout = function getLayout(page: ReactElement) {
|
||||||
|
return (
|
||||||
|
<LayoutAuthenticated permission={'READ_CHAPTERS'}>
|
||||||
|
{page}
|
||||||
|
</LayoutAuthenticated>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ChaptersView;
|
||||||
@ -131,7 +131,7 @@ export default function WebSite() {
|
|||||||
<FeaturesSection
|
<FeaturesSection
|
||||||
projectName={'Bible Reading Tracker'}
|
projectName={'Bible Reading Tracker'}
|
||||||
image={['Icons representing app features']}
|
image={['Icons representing app features']}
|
||||||
withBg={0}
|
withBg={1}
|
||||||
features={features_points}
|
features={features_points}
|
||||||
mainText={`Explore ${projectName} Features`}
|
mainText={`Explore ${projectName} Features`}
|
||||||
subTitle={`Discover the powerful features of ${projectName} designed to enhance your Bible reading experience.`}
|
subTitle={`Discover the powerful features of ${projectName} designed to enhance your Bible reading experience.`}
|
||||||
|
|||||||
@ -114,7 +114,7 @@ const EditNotes = () => {
|
|||||||
component={SelectField}
|
component={SelectField}
|
||||||
options={initialValues.reading}
|
options={initialValues.reading}
|
||||||
itemRef={'readings'}
|
itemRef={'readings'}
|
||||||
showField={'book'}
|
showField={'tags'}
|
||||||
></Field>
|
></Field>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
|
|||||||
@ -112,7 +112,7 @@ const EditNotesPage = () => {
|
|||||||
component={SelectField}
|
component={SelectField}
|
||||||
options={initialValues.reading}
|
options={initialValues.reading}
|
||||||
itemRef={'readings'}
|
itemRef={'readings'}
|
||||||
showField={'book'}
|
showField={'tags'}
|
||||||
></Field>
|
></Field>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
|
|||||||
@ -71,7 +71,7 @@ const NotesView = () => {
|
|||||||
<div className={'mb-4'}>
|
<div className={'mb-4'}>
|
||||||
<p className={'block font-bold mb-2'}>Reading</p>
|
<p className={'block font-bold mb-2'}>Reading</p>
|
||||||
|
|
||||||
<p>{notes?.reading?.book ?? 'No data'}</p>
|
<p>{notes?.reading?.tags ?? 'No data'}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={'mb-4'}>
|
<div className={'mb-4'}>
|
||||||
|
|||||||
@ -49,6 +49,24 @@ const EditReadings = () => {
|
|||||||
notes: '',
|
notes: '',
|
||||||
|
|
||||||
user: null,
|
user: null,
|
||||||
|
|
||||||
|
bookref: null,
|
||||||
|
|
||||||
|
chapterref: null,
|
||||||
|
|
||||||
|
versesref: [],
|
||||||
|
|
||||||
|
translationref: null,
|
||||||
|
|
||||||
|
book_select: null,
|
||||||
|
|
||||||
|
chapter_select: null,
|
||||||
|
|
||||||
|
verses_select: [],
|
||||||
|
|
||||||
|
translation_select: null,
|
||||||
|
|
||||||
|
tags: '',
|
||||||
};
|
};
|
||||||
const [initialValues, setInitialValues] = useState(initVals);
|
const [initialValues, setInitialValues] = useState(initVals);
|
||||||
|
|
||||||
@ -153,6 +171,101 @@ const EditReadings = () => {
|
|||||||
></Field>
|
></Field>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Bookref' labelFor='bookref'>
|
||||||
|
<Field
|
||||||
|
name='bookref'
|
||||||
|
id='bookref'
|
||||||
|
component={SelectField}
|
||||||
|
options={initialValues.bookref}
|
||||||
|
itemRef={'books'}
|
||||||
|
showField={'name'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Chapterref' labelFor='chapterref'>
|
||||||
|
<Field
|
||||||
|
name='chapterref'
|
||||||
|
id='chapterref'
|
||||||
|
component={SelectField}
|
||||||
|
options={initialValues.chapterref}
|
||||||
|
itemRef={'chapters'}
|
||||||
|
showField={'number'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Versesref' labelFor='versesref'>
|
||||||
|
<Field
|
||||||
|
name='versesref'
|
||||||
|
id='versesref'
|
||||||
|
component={SelectFieldMany}
|
||||||
|
options={initialValues.versesref}
|
||||||
|
itemRef={'verses'}
|
||||||
|
showField={'number'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Translationref' labelFor='translationref'>
|
||||||
|
<Field
|
||||||
|
name='translationref'
|
||||||
|
id='translationref'
|
||||||
|
component={SelectField}
|
||||||
|
options={initialValues.translationref}
|
||||||
|
itemRef={'translations'}
|
||||||
|
showField={'name'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Book_select' labelFor='book_select'>
|
||||||
|
<Field
|
||||||
|
name='book_select'
|
||||||
|
id='book_select'
|
||||||
|
component={SelectField}
|
||||||
|
options={initialValues.book_select}
|
||||||
|
itemRef={'books'}
|
||||||
|
showField={'name'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Chapter_select' labelFor='chapter_select'>
|
||||||
|
<Field
|
||||||
|
name='chapter_select'
|
||||||
|
id='chapter_select'
|
||||||
|
component={SelectField}
|
||||||
|
options={initialValues.chapter_select}
|
||||||
|
itemRef={'chapters'}
|
||||||
|
showField={'number'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Verses_select' labelFor='verses_select'>
|
||||||
|
<Field
|
||||||
|
name='verses_select'
|
||||||
|
id='verses_select'
|
||||||
|
component={SelectFieldMany}
|
||||||
|
options={initialValues.verses_select}
|
||||||
|
itemRef={'verses'}
|
||||||
|
showField={'number'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
label='Translation_select'
|
||||||
|
labelFor='translation_select'
|
||||||
|
>
|
||||||
|
<Field
|
||||||
|
name='translation_select'
|
||||||
|
id='translation_select'
|
||||||
|
component={SelectField}
|
||||||
|
options={initialValues.translation_select}
|
||||||
|
itemRef={'translations'}
|
||||||
|
showField={'name'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Tags'>
|
||||||
|
<Field name='tags' placeholder='Tags' />
|
||||||
|
</FormField>
|
||||||
|
|
||||||
<BaseDivider />
|
<BaseDivider />
|
||||||
<BaseButtons>
|
<BaseButtons>
|
||||||
<BaseButton type='submit' color='info' label='Submit' />
|
<BaseButton type='submit' color='info' label='Submit' />
|
||||||
|
|||||||
@ -49,6 +49,24 @@ const EditReadingsPage = () => {
|
|||||||
notes: '',
|
notes: '',
|
||||||
|
|
||||||
user: null,
|
user: null,
|
||||||
|
|
||||||
|
bookref: null,
|
||||||
|
|
||||||
|
chapterref: null,
|
||||||
|
|
||||||
|
versesref: [],
|
||||||
|
|
||||||
|
translationref: null,
|
||||||
|
|
||||||
|
book_select: null,
|
||||||
|
|
||||||
|
chapter_select: null,
|
||||||
|
|
||||||
|
verses_select: [],
|
||||||
|
|
||||||
|
translation_select: null,
|
||||||
|
|
||||||
|
tags: '',
|
||||||
};
|
};
|
||||||
const [initialValues, setInitialValues] = useState(initVals);
|
const [initialValues, setInitialValues] = useState(initVals);
|
||||||
|
|
||||||
@ -151,6 +169,101 @@ const EditReadingsPage = () => {
|
|||||||
></Field>
|
></Field>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Bookref' labelFor='bookref'>
|
||||||
|
<Field
|
||||||
|
name='bookref'
|
||||||
|
id='bookref'
|
||||||
|
component={SelectField}
|
||||||
|
options={initialValues.bookref}
|
||||||
|
itemRef={'books'}
|
||||||
|
showField={'name'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Chapterref' labelFor='chapterref'>
|
||||||
|
<Field
|
||||||
|
name='chapterref'
|
||||||
|
id='chapterref'
|
||||||
|
component={SelectField}
|
||||||
|
options={initialValues.chapterref}
|
||||||
|
itemRef={'chapters'}
|
||||||
|
showField={'number'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Versesref' labelFor='versesref'>
|
||||||
|
<Field
|
||||||
|
name='versesref'
|
||||||
|
id='versesref'
|
||||||
|
component={SelectFieldMany}
|
||||||
|
options={initialValues.versesref}
|
||||||
|
itemRef={'verses'}
|
||||||
|
showField={'number'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Translationref' labelFor='translationref'>
|
||||||
|
<Field
|
||||||
|
name='translationref'
|
||||||
|
id='translationref'
|
||||||
|
component={SelectField}
|
||||||
|
options={initialValues.translationref}
|
||||||
|
itemRef={'translations'}
|
||||||
|
showField={'name'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Book_select' labelFor='book_select'>
|
||||||
|
<Field
|
||||||
|
name='book_select'
|
||||||
|
id='book_select'
|
||||||
|
component={SelectField}
|
||||||
|
options={initialValues.book_select}
|
||||||
|
itemRef={'books'}
|
||||||
|
showField={'name'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Chapter_select' labelFor='chapter_select'>
|
||||||
|
<Field
|
||||||
|
name='chapter_select'
|
||||||
|
id='chapter_select'
|
||||||
|
component={SelectField}
|
||||||
|
options={initialValues.chapter_select}
|
||||||
|
itemRef={'chapters'}
|
||||||
|
showField={'number'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Verses_select' labelFor='verses_select'>
|
||||||
|
<Field
|
||||||
|
name='verses_select'
|
||||||
|
id='verses_select'
|
||||||
|
component={SelectFieldMany}
|
||||||
|
options={initialValues.verses_select}
|
||||||
|
itemRef={'verses'}
|
||||||
|
showField={'number'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
label='Translation_select'
|
||||||
|
labelFor='translation_select'
|
||||||
|
>
|
||||||
|
<Field
|
||||||
|
name='translation_select'
|
||||||
|
id='translation_select'
|
||||||
|
component={SelectField}
|
||||||
|
options={initialValues.translation_select}
|
||||||
|
itemRef={'translations'}
|
||||||
|
showField={'name'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Tags'>
|
||||||
|
<Field name='tags' placeholder='Tags' />
|
||||||
|
</FormField>
|
||||||
|
|
||||||
<BaseDivider />
|
<BaseDivider />
|
||||||
<BaseButtons>
|
<BaseButtons>
|
||||||
<BaseButton type='submit' color='info' label='Submit' />
|
<BaseButton type='submit' color='info' label='Submit' />
|
||||||
|
|||||||
@ -33,11 +33,27 @@ const ReadingsTablesPage = () => {
|
|||||||
{ label: 'Verses', title: 'verses' },
|
{ label: 'Verses', title: 'verses' },
|
||||||
{ label: 'Translation', title: 'translation' },
|
{ label: 'Translation', title: 'translation' },
|
||||||
{ label: 'Notes', title: 'notes' },
|
{ label: 'Notes', title: 'notes' },
|
||||||
|
{ label: 'Tags', title: 'tags' },
|
||||||
{ label: 'Chapter', title: 'chapter', number: 'true' },
|
{ label: 'Chapter', title: 'chapter', number: 'true' },
|
||||||
|
|
||||||
{ label: 'Date', title: 'date', date: 'true' },
|
{ label: 'Date', title: 'date', date: 'true' },
|
||||||
|
|
||||||
{ label: 'User', title: 'user' },
|
{ label: 'User', title: 'user' },
|
||||||
|
|
||||||
|
{ label: 'Bookref', title: 'bookref' },
|
||||||
|
|
||||||
|
{ label: 'Chapterref', title: 'chapterref' },
|
||||||
|
|
||||||
|
{ label: 'Translationref', title: 'translationref' },
|
||||||
|
|
||||||
|
{ label: 'Book_select', title: 'book_select' },
|
||||||
|
|
||||||
|
{ label: 'Chapter_select', title: 'chapter_select' },
|
||||||
|
|
||||||
|
{ label: 'Translation_select', title: 'translation_select' },
|
||||||
|
|
||||||
|
{ label: 'Versesref', title: 'versesref' },
|
||||||
|
{ label: 'Verses_select', title: 'verses_select' },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const hasCreatePermission =
|
const hasCreatePermission =
|
||||||
|
|||||||
@ -46,6 +46,24 @@ const initialValues = {
|
|||||||
notes: '',
|
notes: '',
|
||||||
|
|
||||||
user: '',
|
user: '',
|
||||||
|
|
||||||
|
bookref: '',
|
||||||
|
|
||||||
|
chapterref: '',
|
||||||
|
|
||||||
|
versesref: [],
|
||||||
|
|
||||||
|
translationref: '',
|
||||||
|
|
||||||
|
book_select: '',
|
||||||
|
|
||||||
|
chapter_select: '',
|
||||||
|
|
||||||
|
verses_select: [],
|
||||||
|
|
||||||
|
translation_select: '',
|
||||||
|
|
||||||
|
tags: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
const ReadingsNew = () => {
|
const ReadingsNew = () => {
|
||||||
@ -113,6 +131,93 @@ const ReadingsNew = () => {
|
|||||||
></Field>
|
></Field>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Bookref' labelFor='bookref'>
|
||||||
|
<Field
|
||||||
|
name='bookref'
|
||||||
|
id='bookref'
|
||||||
|
component={SelectField}
|
||||||
|
options={[]}
|
||||||
|
itemRef={'books'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Chapterref' labelFor='chapterref'>
|
||||||
|
<Field
|
||||||
|
name='chapterref'
|
||||||
|
id='chapterref'
|
||||||
|
component={SelectField}
|
||||||
|
options={[]}
|
||||||
|
itemRef={'chapters'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Versesref' labelFor='versesref'>
|
||||||
|
<Field
|
||||||
|
name='versesref'
|
||||||
|
id='versesref'
|
||||||
|
itemRef={'verses'}
|
||||||
|
options={[]}
|
||||||
|
component={SelectFieldMany}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Translationref' labelFor='translationref'>
|
||||||
|
<Field
|
||||||
|
name='translationref'
|
||||||
|
id='translationref'
|
||||||
|
component={SelectField}
|
||||||
|
options={[]}
|
||||||
|
itemRef={'translations'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Book_select' labelFor='book_select'>
|
||||||
|
<Field
|
||||||
|
name='book_select'
|
||||||
|
id='book_select'
|
||||||
|
component={SelectField}
|
||||||
|
options={[]}
|
||||||
|
itemRef={'books'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Chapter_select' labelFor='chapter_select'>
|
||||||
|
<Field
|
||||||
|
name='chapter_select'
|
||||||
|
id='chapter_select'
|
||||||
|
component={SelectField}
|
||||||
|
options={[]}
|
||||||
|
itemRef={'chapters'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Verses_select' labelFor='verses_select'>
|
||||||
|
<Field
|
||||||
|
name='verses_select'
|
||||||
|
id='verses_select'
|
||||||
|
itemRef={'verses'}
|
||||||
|
options={[]}
|
||||||
|
component={SelectFieldMany}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
label='Translation_select'
|
||||||
|
labelFor='translation_select'
|
||||||
|
>
|
||||||
|
<Field
|
||||||
|
name='translation_select'
|
||||||
|
id='translation_select'
|
||||||
|
component={SelectField}
|
||||||
|
options={[]}
|
||||||
|
itemRef={'translations'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Tags'>
|
||||||
|
<Field name='tags' placeholder='Tags' />
|
||||||
|
</FormField>
|
||||||
|
|
||||||
<BaseDivider />
|
<BaseDivider />
|
||||||
<BaseButtons>
|
<BaseButtons>
|
||||||
<BaseButton type='submit' color='info' label='Submit' />
|
<BaseButton type='submit' color='info' label='Submit' />
|
||||||
|
|||||||
@ -33,11 +33,27 @@ const ReadingsTablesPage = () => {
|
|||||||
{ label: 'Verses', title: 'verses' },
|
{ label: 'Verses', title: 'verses' },
|
||||||
{ label: 'Translation', title: 'translation' },
|
{ label: 'Translation', title: 'translation' },
|
||||||
{ label: 'Notes', title: 'notes' },
|
{ label: 'Notes', title: 'notes' },
|
||||||
|
{ label: 'Tags', title: 'tags' },
|
||||||
{ label: 'Chapter', title: 'chapter', number: 'true' },
|
{ label: 'Chapter', title: 'chapter', number: 'true' },
|
||||||
|
|
||||||
{ label: 'Date', title: 'date', date: 'true' },
|
{ label: 'Date', title: 'date', date: 'true' },
|
||||||
|
|
||||||
{ label: 'User', title: 'user' },
|
{ label: 'User', title: 'user' },
|
||||||
|
|
||||||
|
{ label: 'Bookref', title: 'bookref' },
|
||||||
|
|
||||||
|
{ label: 'Chapterref', title: 'chapterref' },
|
||||||
|
|
||||||
|
{ label: 'Translationref', title: 'translationref' },
|
||||||
|
|
||||||
|
{ label: 'Book_select', title: 'book_select' },
|
||||||
|
|
||||||
|
{ label: 'Chapter_select', title: 'chapter_select' },
|
||||||
|
|
||||||
|
{ label: 'Translation_select', title: 'translation_select' },
|
||||||
|
|
||||||
|
{ label: 'Versesref', title: 'versesref' },
|
||||||
|
{ label: 'Verses_select', title: 'verses_select' },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const hasCreatePermission =
|
const hasCreatePermission =
|
||||||
|
|||||||
@ -106,6 +106,117 @@ const ReadingsView = () => {
|
|||||||
<p>{readings?.user?.firstName ?? 'No data'}</p>
|
<p>{readings?.user?.firstName ?? 'No data'}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={'mb-4'}>
|
||||||
|
<p className={'block font-bold mb-2'}>Bookref</p>
|
||||||
|
|
||||||
|
<p>{readings?.bookref?.name ?? 'No data'}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'mb-4'}>
|
||||||
|
<p className={'block font-bold mb-2'}>Chapterref</p>
|
||||||
|
|
||||||
|
<p>{readings?.chapterref?.number ?? 'No data'}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<>
|
||||||
|
<p className={'block font-bold mb-2'}>Versesref</p>
|
||||||
|
<CardBox
|
||||||
|
className='mb-6 border border-gray-300 rounded overflow-hidden'
|
||||||
|
hasTable
|
||||||
|
>
|
||||||
|
<div className='overflow-x-auto'>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Number</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{readings.versesref &&
|
||||||
|
Array.isArray(readings.versesref) &&
|
||||||
|
readings.versesref.map((item: any) => (
|
||||||
|
<tr
|
||||||
|
key={item.id}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(`/verses/verses-view/?id=${item.id}`)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<td data-label='number'>{item.number}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{!readings?.versesref?.length && (
|
||||||
|
<div className={'text-center py-4'}>No data</div>
|
||||||
|
)}
|
||||||
|
</CardBox>
|
||||||
|
</>
|
||||||
|
|
||||||
|
<div className={'mb-4'}>
|
||||||
|
<p className={'block font-bold mb-2'}>Translationref</p>
|
||||||
|
|
||||||
|
<p>{readings?.translationref?.name ?? 'No data'}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'mb-4'}>
|
||||||
|
<p className={'block font-bold mb-2'}>Book_select</p>
|
||||||
|
|
||||||
|
<p>{readings?.book_select?.name ?? 'No data'}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'mb-4'}>
|
||||||
|
<p className={'block font-bold mb-2'}>Chapter_select</p>
|
||||||
|
|
||||||
|
<p>{readings?.chapter_select?.number ?? 'No data'}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<>
|
||||||
|
<p className={'block font-bold mb-2'}>Verses_select</p>
|
||||||
|
<CardBox
|
||||||
|
className='mb-6 border border-gray-300 rounded overflow-hidden'
|
||||||
|
hasTable
|
||||||
|
>
|
||||||
|
<div className='overflow-x-auto'>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Number</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{readings.verses_select &&
|
||||||
|
Array.isArray(readings.verses_select) &&
|
||||||
|
readings.verses_select.map((item: any) => (
|
||||||
|
<tr
|
||||||
|
key={item.id}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(`/verses/verses-view/?id=${item.id}`)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<td data-label='number'>{item.number}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{!readings?.verses_select?.length && (
|
||||||
|
<div className={'text-center py-4'}>No data</div>
|
||||||
|
)}
|
||||||
|
</CardBox>
|
||||||
|
</>
|
||||||
|
|
||||||
|
<div className={'mb-4'}>
|
||||||
|
<p className={'block font-bold mb-2'}>Translation_select</p>
|
||||||
|
|
||||||
|
<p>{readings?.translation_select?.name ?? 'No data'}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={'mb-4'}>
|
||||||
|
<p className={'block font-bold mb-2'}>Tags</p>
|
||||||
|
<p>{readings?.tags}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<>
|
<>
|
||||||
<p className={'block font-bold mb-2'}>Notes Reading</p>
|
<p className={'block font-bold mb-2'}>Notes Reading</p>
|
||||||
<CardBox
|
<CardBox
|
||||||
|
|||||||
205
frontend/src/pages/translations/translations-view.tsx
Normal file
205
frontend/src/pages/translations/translations-view.tsx
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
import React, { ReactElement, useEffect } from 'react';
|
||||||
|
import Head from 'next/head';
|
||||||
|
import DatePicker from 'react-datepicker';
|
||||||
|
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/translations/translationsSlice';
|
||||||
|
import { saveFile } from '../../helpers/fileSaver';
|
||||||
|
import dataFormatter from '../../helpers/dataFormatter';
|
||||||
|
import ImageField from '../../components/ImageField';
|
||||||
|
import LayoutAuthenticated from '../../layouts/Authenticated';
|
||||||
|
import { getPageTitle } from '../../config';
|
||||||
|
import SectionTitleLineWithButton from '../../components/SectionTitleLineWithButton';
|
||||||
|
import SectionMain from '../../components/SectionMain';
|
||||||
|
import CardBox from '../../components/CardBox';
|
||||||
|
import BaseButton from '../../components/BaseButton';
|
||||||
|
import BaseDivider from '../../components/BaseDivider';
|
||||||
|
import { mdiChartTimelineVariant } from '@mdi/js';
|
||||||
|
import { SwitchField } from '../../components/SwitchField';
|
||||||
|
import FormField from '../../components/FormField';
|
||||||
|
|
||||||
|
const TranslationsView = () => {
|
||||||
|
const router = useRouter();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { translations } = useAppSelector((state) => state.translations);
|
||||||
|
|
||||||
|
const { id } = router.query;
|
||||||
|
|
||||||
|
function removeLastCharacter(str) {
|
||||||
|
console.log(str, `str`);
|
||||||
|
return str.slice(0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(fetch({ id }));
|
||||||
|
}, [dispatch, id]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>{getPageTitle('View translations')}</title>
|
||||||
|
</Head>
|
||||||
|
<SectionMain>
|
||||||
|
<SectionTitleLineWithButton
|
||||||
|
icon={mdiChartTimelineVariant}
|
||||||
|
title={removeLastCharacter('View translations')}
|
||||||
|
main
|
||||||
|
>
|
||||||
|
<BaseButton
|
||||||
|
color='info'
|
||||||
|
label='Edit'
|
||||||
|
href={`/translations/translations-edit/?id=${id}`}
|
||||||
|
/>
|
||||||
|
</SectionTitleLineWithButton>
|
||||||
|
<CardBox>
|
||||||
|
<div className={'mb-4'}>
|
||||||
|
<p className={'block font-bold mb-2'}>Name</p>
|
||||||
|
<p>{translations?.name}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<>
|
||||||
|
<p className={'block font-bold mb-2'}>Readings Translationref</p>
|
||||||
|
<CardBox
|
||||||
|
className='mb-6 border border-gray-300 rounded overflow-hidden'
|
||||||
|
hasTable
|
||||||
|
>
|
||||||
|
<div className='overflow-x-auto'>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Date</th>
|
||||||
|
|
||||||
|
<th>Book</th>
|
||||||
|
|
||||||
|
<th>Chapter</th>
|
||||||
|
|
||||||
|
<th>Verses</th>
|
||||||
|
|
||||||
|
<th>Translation</th>
|
||||||
|
|
||||||
|
<th>Tags</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{translations.readings_translationref &&
|
||||||
|
Array.isArray(translations.readings_translationref) &&
|
||||||
|
translations.readings_translationref.map((item: any) => (
|
||||||
|
<tr
|
||||||
|
key={item.id}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(
|
||||||
|
`/readings/readings-view/?id=${item.id}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<td data-label='date'>
|
||||||
|
{dataFormatter.dateTimeFormatter(item.date)}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td data-label='book'>{item.book}</td>
|
||||||
|
|
||||||
|
<td data-label='chapter'>{item.chapter}</td>
|
||||||
|
|
||||||
|
<td data-label='verses'>{item.verses}</td>
|
||||||
|
|
||||||
|
<td data-label='translation'>{item.translation}</td>
|
||||||
|
|
||||||
|
<td data-label='tags'>{item.tags}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{!translations?.readings_translationref?.length && (
|
||||||
|
<div className={'text-center py-4'}>No data</div>
|
||||||
|
)}
|
||||||
|
</CardBox>
|
||||||
|
</>
|
||||||
|
|
||||||
|
<>
|
||||||
|
<p className={'block font-bold mb-2'}>
|
||||||
|
Readings Translation_select
|
||||||
|
</p>
|
||||||
|
<CardBox
|
||||||
|
className='mb-6 border border-gray-300 rounded overflow-hidden'
|
||||||
|
hasTable
|
||||||
|
>
|
||||||
|
<div className='overflow-x-auto'>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Date</th>
|
||||||
|
|
||||||
|
<th>Book</th>
|
||||||
|
|
||||||
|
<th>Chapter</th>
|
||||||
|
|
||||||
|
<th>Verses</th>
|
||||||
|
|
||||||
|
<th>Translation</th>
|
||||||
|
|
||||||
|
<th>Tags</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{translations.readings_translation_select &&
|
||||||
|
Array.isArray(translations.readings_translation_select) &&
|
||||||
|
translations.readings_translation_select.map(
|
||||||
|
(item: any) => (
|
||||||
|
<tr
|
||||||
|
key={item.id}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(
|
||||||
|
`/readings/readings-view/?id=${item.id}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<td data-label='date'>
|
||||||
|
{dataFormatter.dateTimeFormatter(item.date)}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td data-label='book'>{item.book}</td>
|
||||||
|
|
||||||
|
<td data-label='chapter'>{item.chapter}</td>
|
||||||
|
|
||||||
|
<td data-label='verses'>{item.verses}</td>
|
||||||
|
|
||||||
|
<td data-label='translation'>{item.translation}</td>
|
||||||
|
|
||||||
|
<td data-label='tags'>{item.tags}</td>
|
||||||
|
</tr>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{!translations?.readings_translation_select?.length && (
|
||||||
|
<div className={'text-center py-4'}>No data</div>
|
||||||
|
)}
|
||||||
|
</CardBox>
|
||||||
|
</>
|
||||||
|
|
||||||
|
<BaseDivider />
|
||||||
|
|
||||||
|
<BaseButton
|
||||||
|
color='info'
|
||||||
|
label='Back'
|
||||||
|
onClick={() => router.push('/translations/translations-list')}
|
||||||
|
/>
|
||||||
|
</CardBox>
|
||||||
|
</SectionMain>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
TranslationsView.getLayout = function getLayout(page: ReactElement) {
|
||||||
|
return (
|
||||||
|
<LayoutAuthenticated permission={'READ_TRANSLATIONS'}>
|
||||||
|
{page}
|
||||||
|
</LayoutAuthenticated>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TranslationsView;
|
||||||
@ -239,6 +239,8 @@ const UsersView = () => {
|
|||||||
<th>Verses</th>
|
<th>Verses</th>
|
||||||
|
|
||||||
<th>Translation</th>
|
<th>Translation</th>
|
||||||
|
|
||||||
|
<th>Tags</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -264,6 +266,8 @@ const UsersView = () => {
|
|||||||
<td data-label='verses'>{item.verses}</td>
|
<td data-label='verses'>{item.verses}</td>
|
||||||
|
|
||||||
<td data-label='translation'>{item.translation}</td>
|
<td data-label='translation'>{item.translation}</td>
|
||||||
|
|
||||||
|
<td data-label='tags'>{item.tags}</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user