Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab6c05f494 | ||
|
|
6712d9401a |
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,3 +1,8 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
*/node_modules/
|
*/node_modules/
|
||||||
*/build/
|
*/build/
|
||||||
|
|
||||||
|
**/node_modules/
|
||||||
|
**/build/
|
||||||
|
.DS_Store
|
||||||
|
.env
|
||||||
File diff suppressed because one or more lines are too long
@ -26,6 +26,10 @@ module.exports = class PhotosDBApi {
|
|||||||
transaction,
|
transaction,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await photos.setPhoto_annotation(data.photo_annotation || [], {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
await FileDBApi.replaceRelationFiles(
|
||||||
{
|
{
|
||||||
belongsTo: db.photos.getTableName(),
|
belongsTo: db.photos.getTableName(),
|
||||||
@ -93,6 +97,10 @@ module.exports = class PhotosDBApi {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.photo_annotation !== undefined) {
|
||||||
|
await photos.setPhoto_annotation(data.photo_annotation, { transaction });
|
||||||
|
}
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
await FileDBApi.replaceRelationFiles(
|
||||||
{
|
{
|
||||||
belongsTo: db.photos.getTableName(),
|
belongsTo: db.photos.getTableName(),
|
||||||
@ -176,6 +184,10 @@ module.exports = class PhotosDBApi {
|
|||||||
transaction,
|
transaction,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
output.photo_annotation = await photos.getPhoto_annotation({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,6 +230,12 @@ module.exports = class PhotosDBApi {
|
|||||||
: {},
|
: {},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
model: db.annotations,
|
||||||
|
as: 'photo_annotation',
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.file,
|
model: db.file,
|
||||||
as: 'image',
|
as: 'image',
|
||||||
@ -239,6 +257,38 @@ module.exports = class PhotosDBApi {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filter.photo_annotation) {
|
||||||
|
const searchTerms = filter.photo_annotation.split('|');
|
||||||
|
|
||||||
|
include = [
|
||||||
|
{
|
||||||
|
model: db.annotations,
|
||||||
|
as: 'photo_annotation_filter',
|
||||||
|
required: searchTerms.length > 0,
|
||||||
|
where:
|
||||||
|
searchTerms.length > 0
|
||||||
|
? {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
[Op.in]: searchTerms.map((term) => Utils.uuid(term)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: {
|
||||||
|
[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;
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,6 @@ module.exports = class ReportsDBApi {
|
|||||||
title: data.title || null,
|
title: data.title || null,
|
||||||
created_date: data.created_date || null,
|
created_date: data.created_date || null,
|
||||||
views: data.views || null,
|
views: data.views || null,
|
||||||
annotations: data.annotations || null,
|
|
||||||
address: data.address || null,
|
address: data.address || null,
|
||||||
phone: data.phone || null,
|
phone: data.phone || null,
|
||||||
importHash: data.importHash || null,
|
importHash: data.importHash || null,
|
||||||
@ -32,6 +31,10 @@ module.exports = class ReportsDBApi {
|
|||||||
transaction,
|
transaction,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await reports.setAnnotation(data.Annotation || [], {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
await FileDBApi.replaceRelationFiles(
|
||||||
{
|
{
|
||||||
belongsTo: db.reports.getTableName(),
|
belongsTo: db.reports.getTableName(),
|
||||||
@ -56,7 +59,6 @@ module.exports = class ReportsDBApi {
|
|||||||
title: item.title || null,
|
title: item.title || null,
|
||||||
created_date: item.created_date || null,
|
created_date: item.created_date || null,
|
||||||
views: item.views || null,
|
views: item.views || null,
|
||||||
annotations: item.annotations || null,
|
|
||||||
address: item.address || null,
|
address: item.address || null,
|
||||||
phone: item.phone || null,
|
phone: item.phone || null,
|
||||||
importHash: item.importHash || null,
|
importHash: item.importHash || null,
|
||||||
@ -100,9 +102,6 @@ module.exports = class ReportsDBApi {
|
|||||||
|
|
||||||
if (data.views !== undefined) updatePayload.views = data.views;
|
if (data.views !== undefined) updatePayload.views = data.views;
|
||||||
|
|
||||||
if (data.annotations !== undefined)
|
|
||||||
updatePayload.annotations = data.annotations;
|
|
||||||
|
|
||||||
if (data.address !== undefined) updatePayload.address = data.address;
|
if (data.address !== undefined) updatePayload.address = data.address;
|
||||||
|
|
||||||
if (data.phone !== undefined) updatePayload.phone = data.phone;
|
if (data.phone !== undefined) updatePayload.phone = data.phone;
|
||||||
@ -119,6 +118,10 @@ module.exports = class ReportsDBApi {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.Annotation !== undefined) {
|
||||||
|
await reports.setAnnotation(data.Annotation, { transaction });
|
||||||
|
}
|
||||||
|
|
||||||
await FileDBApi.replaceRelationFiles(
|
await FileDBApi.replaceRelationFiles(
|
||||||
{
|
{
|
||||||
belongsTo: db.reports.getTableName(),
|
belongsTo: db.reports.getTableName(),
|
||||||
@ -198,6 +201,10 @@ module.exports = class ReportsDBApi {
|
|||||||
transaction,
|
transaction,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
output.Annotation = await reports.getAnnotation({
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,6 +247,12 @@ module.exports = class ReportsDBApi {
|
|||||||
: {},
|
: {},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
model: db.annotations,
|
||||||
|
as: 'Annotation',
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
model: db.file,
|
model: db.file,
|
||||||
as: 'image',
|
as: 'image',
|
||||||
@ -261,13 +274,6 @@ module.exports = class ReportsDBApi {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter.annotations) {
|
|
||||||
where = {
|
|
||||||
...where,
|
|
||||||
[Op.and]: Utils.ilike('reports', 'annotations', filter.annotations),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter.address) {
|
if (filter.address) {
|
||||||
where = {
|
where = {
|
||||||
...where,
|
...where,
|
||||||
@ -337,6 +343,38 @@ module.exports = class ReportsDBApi {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filter.Annotation) {
|
||||||
|
const searchTerms = filter.Annotation.split('|');
|
||||||
|
|
||||||
|
include = [
|
||||||
|
{
|
||||||
|
model: db.annotations,
|
||||||
|
as: 'Annotation_filter',
|
||||||
|
required: searchTerms.length > 0,
|
||||||
|
where:
|
||||||
|
searchTerms.length > 0
|
||||||
|
? {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
id: {
|
||||||
|
[Op.in]: searchTerms.map((term) => Utils.uuid(term)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: {
|
||||||
|
[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;
|
||||||
|
|
||||||
|
|||||||
49
backend/src/db/migrations/1753974911313.js
Normal file
49
backend/src/db/migrations/1753974911313.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
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.removeColumn('reports', 'annotations', {
|
||||||
|
transaction,
|
||||||
|
});
|
||||||
|
|
||||||
|
await transaction.commit();
|
||||||
|
} catch (err) {
|
||||||
|
await transaction.rollback();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @param {QueryInterface} queryInterface
|
||||||
|
* @param {Sequelize} Sequelize
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async down(queryInterface, Sequelize) {
|
||||||
|
/**
|
||||||
|
* @type {Transaction}
|
||||||
|
*/
|
||||||
|
const transaction = await queryInterface.sequelize.transaction();
|
||||||
|
try {
|
||||||
|
await queryInterface.addColumn(
|
||||||
|
'reports',
|
||||||
|
'annotations',
|
||||||
|
{
|
||||||
|
type: Sequelize.DataTypes.TEXT,
|
||||||
|
},
|
||||||
|
{ transaction },
|
||||||
|
);
|
||||||
|
|
||||||
|
await transaction.commit();
|
||||||
|
} catch (err) {
|
||||||
|
await transaction.rollback();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
36
backend/src/db/migrations/1754255097593.js
Normal file
36
backend/src/db/migrations/1754255097593.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;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -28,6 +28,24 @@ module.exports = function (sequelize, DataTypes) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
photos.associate = (db) => {
|
photos.associate = (db) => {
|
||||||
|
db.photos.belongsToMany(db.annotations, {
|
||||||
|
as: 'photo_annotation',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'photos_photo_annotationId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
through: 'photosPhoto_annotationAnnotations',
|
||||||
|
});
|
||||||
|
|
||||||
|
db.photos.belongsToMany(db.annotations, {
|
||||||
|
as: 'photo_annotation_filter',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'photos_photo_annotationId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
through: 'photosPhoto_annotationAnnotations',
|
||||||
|
});
|
||||||
|
|
||||||
/// 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.photos.hasMany(db.annotations, {
|
db.photos.hasMany(db.annotations, {
|
||||||
|
|||||||
@ -26,10 +26,6 @@ module.exports = function (sequelize, DataTypes) {
|
|||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
},
|
},
|
||||||
|
|
||||||
annotations: {
|
|
||||||
type: DataTypes.TEXT,
|
|
||||||
},
|
|
||||||
|
|
||||||
address: {
|
address: {
|
||||||
type: DataTypes.TEXT,
|
type: DataTypes.TEXT,
|
||||||
},
|
},
|
||||||
@ -52,6 +48,24 @@ module.exports = function (sequelize, DataTypes) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
reports.associate = (db) => {
|
reports.associate = (db) => {
|
||||||
|
db.reports.belongsToMany(db.annotations, {
|
||||||
|
as: 'Annotation',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'reports_AnnotationId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
through: 'reportsAnnotationAnnotations',
|
||||||
|
});
|
||||||
|
|
||||||
|
db.reports.belongsToMany(db.annotations, {
|
||||||
|
as: 'Annotation_filter',
|
||||||
|
foreignKey: {
|
||||||
|
name: 'reports_AnnotationId',
|
||||||
|
},
|
||||||
|
constraints: false,
|
||||||
|
through: 'reportsAnnotationAnnotations',
|
||||||
|
});
|
||||||
|
|
||||||
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
/// loop through entities and it's fields, and if ref === current e[name] and create relation has many on parent entity
|
||||||
|
|
||||||
//end loop
|
//end loop
|
||||||
|
|||||||
@ -17,7 +17,7 @@ const AnnotationsData = [
|
|||||||
{
|
{
|
||||||
text: 'Point of Interest 1',
|
text: 'Point of Interest 1',
|
||||||
|
|
||||||
color: 'pink',
|
color: 'red',
|
||||||
|
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
},
|
},
|
||||||
@ -25,7 +25,7 @@ const AnnotationsData = [
|
|||||||
{
|
{
|
||||||
text: 'Point of Interest 2',
|
text: 'Point of Interest 2',
|
||||||
|
|
||||||
color: 'yellow',
|
color: 'pink',
|
||||||
|
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
},
|
},
|
||||||
@ -33,7 +33,7 @@ const AnnotationsData = [
|
|||||||
{
|
{
|
||||||
text: 'Point of Interest 3',
|
text: 'Point of Interest 3',
|
||||||
|
|
||||||
color: 'orange',
|
color: 'red',
|
||||||
|
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
},
|
},
|
||||||
@ -69,16 +69,19 @@ const PhotosData = [
|
|||||||
{
|
{
|
||||||
// type code here for "images" field
|
// type code here for "images" 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 "images" field
|
// type code here for "images" 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 "images" field
|
// type code here for "images" field
|
||||||
// type code here for "relation_one" field
|
// type code here for "relation_one" field
|
||||||
|
// type code here for "relation_many" field
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -92,13 +95,13 @@ const ReportsData = [
|
|||||||
|
|
||||||
views: 150,
|
views: 150,
|
||||||
|
|
||||||
annotations: 'Lynn Margulis',
|
address: 'Marcello Malpighi',
|
||||||
|
|
||||||
address: 'Hans Bethe',
|
phone: 'Charles Lyell',
|
||||||
|
|
||||||
phone: 'John Dalton',
|
|
||||||
|
|
||||||
// type code here for "images" field
|
// type code here for "images" field
|
||||||
|
|
||||||
|
// type code here for "relation_many" field
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -110,13 +113,13 @@ const ReportsData = [
|
|||||||
|
|
||||||
views: 200,
|
views: 200,
|
||||||
|
|
||||||
annotations: 'John Dalton',
|
address: 'John Dalton',
|
||||||
|
|
||||||
address: 'Max von Laue',
|
phone: 'Johannes Kepler',
|
||||||
|
|
||||||
phone: 'Paul Ehrlich',
|
|
||||||
|
|
||||||
// type code here for "images" field
|
// type code here for "images" field
|
||||||
|
|
||||||
|
// type code here for "relation_many" field
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -128,33 +131,33 @@ const ReportsData = [
|
|||||||
|
|
||||||
views: 175,
|
views: 175,
|
||||||
|
|
||||||
annotations: 'Rudolf Virchow',
|
address: 'George Gaylord Simpson',
|
||||||
|
|
||||||
address: 'Claude Levi-Strauss',
|
phone: 'Edward Teller',
|
||||||
|
|
||||||
phone: 'Konrad Lorenz',
|
|
||||||
|
|
||||||
// type code here for "images" field
|
// type code here for "images" field
|
||||||
|
|
||||||
|
// type code here for "relation_many" field
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const ImprovementsData = [
|
const ImprovementsData = [
|
||||||
{
|
{
|
||||||
improvement_name: 'Rudolf Virchow',
|
improvement_name: 'Frederick Gowland Hopkins',
|
||||||
|
|
||||||
improvement_status: 'Hermann von Helmholtz',
|
improvement_status: 'Jean Piaget',
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
improvement_name: 'Lucretius',
|
improvement_name: 'Emil Fischer',
|
||||||
|
|
||||||
improvement_status: 'Heike Kamerlingh Onnes',
|
improvement_status: 'Charles Darwin',
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
improvement_name: 'Gertrude Belle Elion',
|
improvement_name: 'Carl Gauss (Karl Friedrich Gauss)',
|
||||||
|
|
||||||
improvement_status: 'Claude Levi-Strauss',
|
improvement_status: 'B. F. Skinner',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -234,6 +237,8 @@ async function associatePhotoWithClient() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Similar logic for "relation_many"
|
||||||
|
|
||||||
async function associateReportWithClient() {
|
async function associateReportWithClient() {
|
||||||
const relatedClient0 = await Clients.findOne({
|
const relatedClient0 = await Clients.findOne({
|
||||||
offset: Math.floor(Math.random() * (await Clients.count())),
|
offset: Math.floor(Math.random() * (await Clients.count())),
|
||||||
@ -269,6 +274,8 @@ async function associateReportWithClient() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Similar logic for "relation_many"
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
up: async (queryInterface, Sequelize) => {
|
up: async (queryInterface, Sequelize) => {
|
||||||
await Annotations.bulkCreate(AnnotationsData);
|
await Annotations.bulkCreate(AnnotationsData);
|
||||||
@ -292,7 +299,11 @@ module.exports = {
|
|||||||
|
|
||||||
await associatePhotoWithClient(),
|
await associatePhotoWithClient(),
|
||||||
|
|
||||||
|
// Similar logic for "relation_many"
|
||||||
|
|
||||||
await associateReportWithClient(),
|
await associateReportWithClient(),
|
||||||
|
|
||||||
|
// Similar logic for "relation_many"
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -23,9 +23,6 @@ router.use(checkCrudPermissions('reports'));
|
|||||||
* title:
|
* title:
|
||||||
* type: string
|
* type: string
|
||||||
* default: title
|
* default: title
|
||||||
* annotations:
|
|
||||||
* type: string
|
|
||||||
* default: annotations
|
|
||||||
* address:
|
* address:
|
||||||
* type: string
|
* type: string
|
||||||
* default: address
|
* default: address
|
||||||
@ -320,7 +317,6 @@ router.get(
|
|||||||
const fields = [
|
const fields = [
|
||||||
'id',
|
'id',
|
||||||
'title',
|
'title',
|
||||||
'annotations',
|
|
||||||
'address',
|
'address',
|
||||||
'phone',
|
'phone',
|
||||||
'views',
|
'views',
|
||||||
|
|||||||
@ -47,7 +47,7 @@ module.exports = class SearchService {
|
|||||||
|
|
||||||
clients: ['name'],
|
clients: ['name'],
|
||||||
|
|
||||||
reports: ['title', 'annotations', 'address', 'phone'],
|
reports: ['title', 'address', 'phone'],
|
||||||
|
|
||||||
improvements: ['improvement_name', 'improvement_status'],
|
improvements: ['improvement_name', 'improvement_status'],
|
||||||
};
|
};
|
||||||
|
|||||||
@ -105,6 +105,19 @@ const CardPhotos = ({
|
|||||||
</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'>
|
||||||
|
Photo Annotation
|
||||||
|
</dt>
|
||||||
|
<dd className='flex items-start gap-x-2'>
|
||||||
|
<div className='font-medium line-clamp-4'>
|
||||||
|
{dataFormatter
|
||||||
|
.annotationsManyListFormatter(item.photo_annotation)
|
||||||
|
.join(', ')}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
</dl>
|
</dl>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -75,6 +75,17 @@ const ListPhotos = ({
|
|||||||
{dataFormatter.clientsOneListFormatter(item.client)}
|
{dataFormatter.clientsOneListFormatter(item.client)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>
|
||||||
|
Photo Annotation
|
||||||
|
</p>
|
||||||
|
<p className={'line-clamp-2'}>
|
||||||
|
{dataFormatter
|
||||||
|
.annotationsManyListFormatter(item.photo_annotation)
|
||||||
|
.join(', ')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
<ListActionsPopover
|
<ListActionsPopover
|
||||||
onDelete={onDelete}
|
onDelete={onDelete}
|
||||||
|
|||||||
@ -78,6 +78,25 @@ export const loadColumns = async (
|
|||||||
params?.value?.id ?? params?.value,
|
params?.value?.id ?? params?.value,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'photo_annotation',
|
||||||
|
headerName: 'Photo Annotation',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
|
editable: false,
|
||||||
|
sortable: false,
|
||||||
|
type: 'singleSelect',
|
||||||
|
valueFormatter: ({ value }) =>
|
||||||
|
dataFormatter.annotationsManyListFormatter(value).join(', '),
|
||||||
|
renderEditCell: (params) => (
|
||||||
|
<DataGridMultiSelect {...params} entityName={'annotations'} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
field: 'actions',
|
field: 'actions',
|
||||||
type: 'actions',
|
type: 'actions',
|
||||||
|
|||||||
@ -118,17 +118,6 @@ const CardReports = ({
|
|||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>
|
|
||||||
Annotations
|
|
||||||
</dt>
|
|
||||||
<dd className='flex items-start gap-x-2'>
|
|
||||||
<div className='font-medium line-clamp-4'>
|
|
||||||
{item.annotations}
|
|
||||||
</div>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='flex justify-between gap-x-4 py-3'>
|
<div className='flex justify-between gap-x-4 py-3'>
|
||||||
<dt className=' text-gray-500 dark:text-dark-600'>
|
<dt className=' text-gray-500 dark:text-dark-600'>
|
||||||
Address
|
Address
|
||||||
@ -159,6 +148,19 @@ const CardReports = ({
|
|||||||
</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'>
|
||||||
|
Annotation
|
||||||
|
</dt>
|
||||||
|
<dd className='flex items-start gap-x-2'>
|
||||||
|
<div className='font-medium line-clamp-4'>
|
||||||
|
{dataFormatter
|
||||||
|
.annotationsManyListFormatter(item.Annotation)
|
||||||
|
.join(', ')}
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
</dl>
|
</dl>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -84,11 +84,6 @@ const ListReports = ({
|
|||||||
<p className={'line-clamp-2'}>{item.views}</p>
|
<p className={'line-clamp-2'}>{item.views}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
|
||||||
<p className={'text-xs text-gray-500 '}>Annotations</p>
|
|
||||||
<p className={'line-clamp-2'}>{item.annotations}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={'flex-1 px-3'}>
|
<div className={'flex-1 px-3'}>
|
||||||
<p className={'text-xs text-gray-500 '}>Address</p>
|
<p className={'text-xs text-gray-500 '}>Address</p>
|
||||||
<p className={'line-clamp-2'}>{item.address}</p>
|
<p className={'line-clamp-2'}>{item.address}</p>
|
||||||
@ -107,6 +102,15 @@ const ListReports = ({
|
|||||||
className='mx-auto w-8 h-8'
|
className='mx-auto w-8 h-8'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={'flex-1 px-3'}>
|
||||||
|
<p className={'text-xs text-gray-500 '}>Annotation</p>
|
||||||
|
<p className={'line-clamp-2'}>
|
||||||
|
{dataFormatter
|
||||||
|
.annotationsManyListFormatter(item.Annotation)
|
||||||
|
.join(', ')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
<ListActionsPopover
|
<ListActionsPopover
|
||||||
onDelete={onDelete}
|
onDelete={onDelete}
|
||||||
|
|||||||
@ -100,18 +100,6 @@ export const loadColumns = async (
|
|||||||
type: 'number',
|
type: 'number',
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
|
||||||
field: 'annotations',
|
|
||||||
headerName: 'Annotations',
|
|
||||||
flex: 1,
|
|
||||||
minWidth: 120,
|
|
||||||
filterable: false,
|
|
||||||
headerClassName: 'datagrid--header',
|
|
||||||
cellClassName: 'datagrid--cell',
|
|
||||||
|
|
||||||
editable: hasUpdatePermission,
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
field: 'address',
|
field: 'address',
|
||||||
headerName: 'Address',
|
headerName: 'Address',
|
||||||
@ -156,6 +144,25 @@ export const loadColumns = async (
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
field: 'Annotation',
|
||||||
|
headerName: 'Annotation',
|
||||||
|
flex: 1,
|
||||||
|
minWidth: 120,
|
||||||
|
filterable: false,
|
||||||
|
headerClassName: 'datagrid--header',
|
||||||
|
cellClassName: 'datagrid--cell',
|
||||||
|
|
||||||
|
editable: false,
|
||||||
|
sortable: false,
|
||||||
|
type: 'singleSelect',
|
||||||
|
valueFormatter: ({ value }) =>
|
||||||
|
dataFormatter.annotationsManyListFormatter(value).join(', '),
|
||||||
|
renderEditCell: (params) => (
|
||||||
|
<DataGridMultiSelect {...params} entityName={'annotations'} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
field: 'actions',
|
field: 'actions',
|
||||||
type: 'actions',
|
type: 'actions',
|
||||||
|
|||||||
@ -19,7 +19,7 @@ export default function WebSiteHeader({ projectName }: WebSiteHeaderProps) {
|
|||||||
|
|
||||||
const style = HeaderStyle.PAGES_LEFT;
|
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
|
||||||
|
|||||||
@ -39,6 +39,25 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
annotationsManyListFormatter(val) {
|
||||||
|
if (!val || !val.length) return [];
|
||||||
|
return val.map((item) => item.text);
|
||||||
|
},
|
||||||
|
annotationsOneListFormatter(val) {
|
||||||
|
if (!val) return '';
|
||||||
|
return val.text;
|
||||||
|
},
|
||||||
|
annotationsManyListFormatterEdit(val) {
|
||||||
|
if (!val || !val.length) return [];
|
||||||
|
return val.map((item) => {
|
||||||
|
return { id: item.id, label: item.text };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
annotationsOneListFormatterEdit(val) {
|
||||||
|
if (!val) return '';
|
||||||
|
return { label: val.text, id: val.id };
|
||||||
|
},
|
||||||
|
|
||||||
clientsManyListFormatter(val) {
|
clientsManyListFormatter(val) {
|
||||||
if (!val || !val.length) return [];
|
if (!val || !val.length) return [];
|
||||||
return val.map((item) => item.name);
|
return val.map((item) => item.name);
|
||||||
|
|||||||
@ -88,8 +88,6 @@ const ClientsView = () => {
|
|||||||
|
|
||||||
<th>Views</th>
|
<th>Views</th>
|
||||||
|
|
||||||
<th>Annotations</th>
|
|
||||||
|
|
||||||
<th>Address</th>
|
<th>Address</th>
|
||||||
|
|
||||||
<th>Phone</th>
|
<th>Phone</th>
|
||||||
@ -113,8 +111,6 @@ const ClientsView = () => {
|
|||||||
|
|
||||||
<td data-label='views'>{item.views}</td>
|
<td data-label='views'>{item.views}</td>
|
||||||
|
|
||||||
<td data-label='annotations'>{item.annotations}</td>
|
|
||||||
|
|
||||||
<td data-label='address'>{item.address}</td>
|
<td data-label='address'>{item.address}</td>
|
||||||
|
|
||||||
<td data-label='phone'>{item.phone}</td>
|
<td data-label='phone'>{item.phone}</td>
|
||||||
@ -176,8 +172,6 @@ const ClientsView = () => {
|
|||||||
|
|
||||||
<th>Views</th>
|
<th>Views</th>
|
||||||
|
|
||||||
<th>Annotations</th>
|
|
||||||
|
|
||||||
<th>Address</th>
|
<th>Address</th>
|
||||||
|
|
||||||
<th>Phone</th>
|
<th>Phone</th>
|
||||||
@ -201,8 +195,6 @@ const ClientsView = () => {
|
|||||||
|
|
||||||
<td data-label='views'>{item.views}</td>
|
<td data-label='views'>{item.views}</td>
|
||||||
|
|
||||||
<td data-label='annotations'>{item.annotations}</td>
|
|
||||||
|
|
||||||
<td data-label='address'>{item.address}</td>
|
<td data-label='address'>{item.address}</td>
|
||||||
|
|
||||||
<td data-label='phone'>{item.phone}</td>
|
<td data-label='phone'>{item.phone}</td>
|
||||||
|
|||||||
@ -39,6 +39,8 @@ const EditPhotos = () => {
|
|||||||
image: [],
|
image: [],
|
||||||
|
|
||||||
client: null,
|
client: null,
|
||||||
|
|
||||||
|
photo_annotation: [],
|
||||||
};
|
};
|
||||||
const [initialValues, setInitialValues] = useState(initVals);
|
const [initialValues, setInitialValues] = useState(initVals);
|
||||||
|
|
||||||
@ -118,6 +120,17 @@ const EditPhotos = () => {
|
|||||||
></Field>
|
></Field>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Photo Annotation' labelFor='photo_annotation'>
|
||||||
|
<Field
|
||||||
|
name='photo_annotation'
|
||||||
|
id='photo_annotation'
|
||||||
|
component={SelectFieldMany}
|
||||||
|
options={initialValues.photo_annotation}
|
||||||
|
itemRef={'annotations'}
|
||||||
|
showField={'text'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
<BaseDivider />
|
<BaseDivider />
|
||||||
<BaseButtons>
|
<BaseButtons>
|
||||||
<BaseButton type='submit' color='info' label='Submit' />
|
<BaseButton type='submit' color='info' label='Submit' />
|
||||||
|
|||||||
@ -39,6 +39,8 @@ const EditPhotosPage = () => {
|
|||||||
image: [],
|
image: [],
|
||||||
|
|
||||||
client: null,
|
client: null,
|
||||||
|
|
||||||
|
photo_annotation: [],
|
||||||
};
|
};
|
||||||
const [initialValues, setInitialValues] = useState(initVals);
|
const [initialValues, setInitialValues] = useState(initVals);
|
||||||
|
|
||||||
@ -116,6 +118,17 @@ const EditPhotosPage = () => {
|
|||||||
></Field>
|
></Field>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Photo Annotation' labelFor='photo_annotation'>
|
||||||
|
<Field
|
||||||
|
name='photo_annotation'
|
||||||
|
id='photo_annotation'
|
||||||
|
component={SelectFieldMany}
|
||||||
|
options={initialValues.photo_annotation}
|
||||||
|
itemRef={'annotations'}
|
||||||
|
showField={'text'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
<BaseDivider />
|
<BaseDivider />
|
||||||
<BaseButtons>
|
<BaseButtons>
|
||||||
<BaseButton type='submit' color='info' label='Submit' />
|
<BaseButton type='submit' color='info' label='Submit' />
|
||||||
|
|||||||
@ -28,7 +28,11 @@ const PhotosTablesPage = () => {
|
|||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const [filters] = useState([{ label: 'Client', title: 'client' }]);
|
const [filters] = useState([
|
||||||
|
{ label: 'Client', title: 'client' },
|
||||||
|
|
||||||
|
{ label: 'Photo Annotation', title: 'photo_annotation' },
|
||||||
|
]);
|
||||||
|
|
||||||
const hasCreatePermission =
|
const hasCreatePermission =
|
||||||
currentUser && hasPermission(currentUser, 'CREATE_PHOTOS');
|
currentUser && hasPermission(currentUser, 'CREATE_PHOTOS');
|
||||||
|
|||||||
@ -36,6 +36,8 @@ const initialValues = {
|
|||||||
image: [],
|
image: [],
|
||||||
|
|
||||||
client: '',
|
client: '',
|
||||||
|
|
||||||
|
photo_annotation: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const PhotosNew = () => {
|
const PhotosNew = () => {
|
||||||
@ -91,6 +93,16 @@ const PhotosNew = () => {
|
|||||||
></Field>
|
></Field>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Photo Annotation' labelFor='photo_annotation'>
|
||||||
|
<Field
|
||||||
|
name='photo_annotation'
|
||||||
|
id='photo_annotation'
|
||||||
|
itemRef={'annotations'}
|
||||||
|
options={[]}
|
||||||
|
component={SelectFieldMany}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
<BaseDivider />
|
<BaseDivider />
|
||||||
<BaseButtons>
|
<BaseButtons>
|
||||||
<BaseButton type='submit' color='info' label='Submit' />
|
<BaseButton type='submit' color='info' label='Submit' />
|
||||||
|
|||||||
@ -28,7 +28,11 @@ const PhotosTablesPage = () => {
|
|||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const [filters] = useState([{ label: 'Client', title: 'client' }]);
|
const [filters] = useState([
|
||||||
|
{ label: 'Client', title: 'client' },
|
||||||
|
|
||||||
|
{ label: 'Photo Annotation', title: 'photo_annotation' },
|
||||||
|
]);
|
||||||
|
|
||||||
const hasCreatePermission =
|
const hasCreatePermission =
|
||||||
currentUser && hasPermission(currentUser, 'CREATE_PHOTOS');
|
currentUser && hasPermission(currentUser, 'CREATE_PHOTOS');
|
||||||
|
|||||||
@ -73,6 +73,47 @@ const PhotosView = () => {
|
|||||||
<p>{photos?.client?.name ?? 'No data'}</p>
|
<p>{photos?.client?.name ?? 'No data'}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<>
|
||||||
|
<p className={'block font-bold mb-2'}>Photo Annotation</p>
|
||||||
|
<CardBox
|
||||||
|
className='mb-6 border border-gray-300 rounded overflow-hidden'
|
||||||
|
hasTable
|
||||||
|
>
|
||||||
|
<div className='overflow-x-auto'>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Text</th>
|
||||||
|
|
||||||
|
<th>Color</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{photos.photo_annotation &&
|
||||||
|
Array.isArray(photos.photo_annotation) &&
|
||||||
|
photos.photo_annotation.map((item: any) => (
|
||||||
|
<tr
|
||||||
|
key={item.id}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(
|
||||||
|
`/annotations/annotations-view/?id=${item.id}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<td data-label='text'>{item.text}</td>
|
||||||
|
|
||||||
|
<td data-label='color'>{item.color}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{!photos?.photo_annotation?.length && (
|
||||||
|
<div className={'text-center py-4'}>No data</div>
|
||||||
|
)}
|
||||||
|
</CardBox>
|
||||||
|
</>
|
||||||
|
|
||||||
<>
|
<>
|
||||||
<p className={'block font-bold mb-2'}>Annotations Photo</p>
|
<p className={'block font-bold mb-2'}>Annotations Photo</p>
|
||||||
<CardBox
|
<CardBox
|
||||||
|
|||||||
@ -44,13 +44,13 @@ const EditReports = () => {
|
|||||||
|
|
||||||
views: '',
|
views: '',
|
||||||
|
|
||||||
annotations: '',
|
|
||||||
|
|
||||||
address: '',
|
address: '',
|
||||||
|
|
||||||
phone: '',
|
phone: '',
|
||||||
|
|
||||||
image: [],
|
image: [],
|
||||||
|
|
||||||
|
Annotation: [],
|
||||||
};
|
};
|
||||||
const [initialValues, setInitialValues] = useState(initVals);
|
const [initialValues, setInitialValues] = useState(initVals);
|
||||||
|
|
||||||
@ -141,10 +141,6 @@ const EditReports = () => {
|
|||||||
<Field type='number' name='views' placeholder='Views' />
|
<Field type='number' name='views' placeholder='Views' />
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
<FormField label='Annotations'>
|
|
||||||
<Field name='annotations' placeholder='Annotations' />
|
|
||||||
</FormField>
|
|
||||||
|
|
||||||
<FormField label='Address'>
|
<FormField label='Address'>
|
||||||
<Field name='address' placeholder='Address' />
|
<Field name='address' placeholder='Address' />
|
||||||
</FormField>
|
</FormField>
|
||||||
@ -169,6 +165,17 @@ const EditReports = () => {
|
|||||||
></Field>
|
></Field>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Annotation' labelFor='Annotation'>
|
||||||
|
<Field
|
||||||
|
name='Annotation'
|
||||||
|
id='Annotation'
|
||||||
|
component={SelectFieldMany}
|
||||||
|
options={initialValues.Annotation}
|
||||||
|
itemRef={'annotations'}
|
||||||
|
showField={'text'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
<BaseDivider />
|
<BaseDivider />
|
||||||
<BaseButtons>
|
<BaseButtons>
|
||||||
<BaseButton type='submit' color='info' label='Submit' />
|
<BaseButton type='submit' color='info' label='Submit' />
|
||||||
|
|||||||
@ -44,13 +44,13 @@ const EditReportsPage = () => {
|
|||||||
|
|
||||||
views: '',
|
views: '',
|
||||||
|
|
||||||
annotations: '',
|
|
||||||
|
|
||||||
address: '',
|
address: '',
|
||||||
|
|
||||||
phone: '',
|
phone: '',
|
||||||
|
|
||||||
image: [],
|
image: [],
|
||||||
|
|
||||||
|
Annotation: [],
|
||||||
};
|
};
|
||||||
const [initialValues, setInitialValues] = useState(initVals);
|
const [initialValues, setInitialValues] = useState(initVals);
|
||||||
|
|
||||||
@ -139,10 +139,6 @@ const EditReportsPage = () => {
|
|||||||
<Field type='number' name='views' placeholder='Views' />
|
<Field type='number' name='views' placeholder='Views' />
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
<FormField label='Annotations'>
|
|
||||||
<Field name='annotations' placeholder='Annotations' />
|
|
||||||
</FormField>
|
|
||||||
|
|
||||||
<FormField label='Address'>
|
<FormField label='Address'>
|
||||||
<Field name='address' placeholder='Address' />
|
<Field name='address' placeholder='Address' />
|
||||||
</FormField>
|
</FormField>
|
||||||
@ -167,6 +163,17 @@ const EditReportsPage = () => {
|
|||||||
></Field>
|
></Field>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Annotation' labelFor='Annotation'>
|
||||||
|
<Field
|
||||||
|
name='Annotation'
|
||||||
|
id='Annotation'
|
||||||
|
component={SelectFieldMany}
|
||||||
|
options={initialValues.Annotation}
|
||||||
|
itemRef={'annotations'}
|
||||||
|
showField={'text'}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
<BaseDivider />
|
<BaseDivider />
|
||||||
<BaseButtons>
|
<BaseButtons>
|
||||||
<BaseButton type='submit' color='info' label='Submit' />
|
<BaseButton type='submit' color='info' label='Submit' />
|
||||||
|
|||||||
@ -30,7 +30,6 @@ const ReportsTablesPage = () => {
|
|||||||
|
|
||||||
const [filters] = useState([
|
const [filters] = useState([
|
||||||
{ label: 'Title', title: 'title' },
|
{ label: 'Title', title: 'title' },
|
||||||
{ label: 'Annotations', title: 'annotations' },
|
|
||||||
{ label: 'Address', title: 'address' },
|
{ label: 'Address', title: 'address' },
|
||||||
{ label: 'Phone', title: 'phone' },
|
{ label: 'Phone', title: 'phone' },
|
||||||
{ label: 'Views', title: 'views', number: 'true' },
|
{ label: 'Views', title: 'views', number: 'true' },
|
||||||
@ -38,6 +37,8 @@ const ReportsTablesPage = () => {
|
|||||||
{ label: 'CreatedDate', title: 'created_date', date: 'true' },
|
{ label: 'CreatedDate', title: 'created_date', date: 'true' },
|
||||||
|
|
||||||
{ label: 'Client', title: 'client' },
|
{ label: 'Client', title: 'client' },
|
||||||
|
|
||||||
|
{ label: 'Annotation', title: 'Annotation' },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const hasCreatePermission =
|
const hasCreatePermission =
|
||||||
|
|||||||
@ -41,13 +41,13 @@ const initialValues = {
|
|||||||
|
|
||||||
views: '',
|
views: '',
|
||||||
|
|
||||||
annotations: '',
|
|
||||||
|
|
||||||
address: '',
|
address: '',
|
||||||
|
|
||||||
phone: '',
|
phone: '',
|
||||||
|
|
||||||
image: [],
|
image: [],
|
||||||
|
|
||||||
|
Annotation: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const ReportsNew = () => {
|
const ReportsNew = () => {
|
||||||
@ -103,10 +103,6 @@ const ReportsNew = () => {
|
|||||||
<Field type='number' name='views' placeholder='Views' />
|
<Field type='number' name='views' placeholder='Views' />
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
<FormField label='Annotations'>
|
|
||||||
<Field name='annotations' placeholder='Annotations' />
|
|
||||||
</FormField>
|
|
||||||
|
|
||||||
<FormField label='Address'>
|
<FormField label='Address'>
|
||||||
<Field name='address' placeholder='Address' />
|
<Field name='address' placeholder='Address' />
|
||||||
</FormField>
|
</FormField>
|
||||||
@ -131,6 +127,16 @@ const ReportsNew = () => {
|
|||||||
></Field>
|
></Field>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
|
||||||
|
<FormField label='Annotation' labelFor='Annotation'>
|
||||||
|
<Field
|
||||||
|
name='Annotation'
|
||||||
|
id='Annotation'
|
||||||
|
itemRef={'annotations'}
|
||||||
|
options={[]}
|
||||||
|
component={SelectFieldMany}
|
||||||
|
></Field>
|
||||||
|
</FormField>
|
||||||
|
|
||||||
<BaseDivider />
|
<BaseDivider />
|
||||||
<BaseButtons>
|
<BaseButtons>
|
||||||
<BaseButton type='submit' color='info' label='Submit' />
|
<BaseButton type='submit' color='info' label='Submit' />
|
||||||
|
|||||||
@ -30,7 +30,6 @@ const ReportsTablesPage = () => {
|
|||||||
|
|
||||||
const [filters] = useState([
|
const [filters] = useState([
|
||||||
{ label: 'Title', title: 'title' },
|
{ label: 'Title', title: 'title' },
|
||||||
{ label: 'Annotations', title: 'annotations' },
|
|
||||||
{ label: 'Address', title: 'address' },
|
{ label: 'Address', title: 'address' },
|
||||||
{ label: 'Phone', title: 'phone' },
|
{ label: 'Phone', title: 'phone' },
|
||||||
{ label: 'Views', title: 'views', number: 'true' },
|
{ label: 'Views', title: 'views', number: 'true' },
|
||||||
@ -38,6 +37,8 @@ const ReportsTablesPage = () => {
|
|||||||
{ label: 'CreatedDate', title: 'created_date', date: 'true' },
|
{ label: 'CreatedDate', title: 'created_date', date: 'true' },
|
||||||
|
|
||||||
{ label: 'Client', title: 'client' },
|
{ label: 'Client', title: 'client' },
|
||||||
|
|
||||||
|
{ label: 'Annotation', title: 'Annotation' },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const hasCreatePermission =
|
const hasCreatePermission =
|
||||||
|
|||||||
@ -89,11 +89,6 @@ const ReportsView = () => {
|
|||||||
<p>{reports?.views || 'No data'}</p>
|
<p>{reports?.views || 'No data'}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={'mb-4'}>
|
|
||||||
<p className={'block font-bold mb-2'}>Annotations</p>
|
|
||||||
<p>{reports?.annotations}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={'mb-4'}>
|
<div className={'mb-4'}>
|
||||||
<p className={'block font-bold mb-2'}>Address</p>
|
<p className={'block font-bold mb-2'}>Address</p>
|
||||||
<p>{reports?.address}</p>
|
<p>{reports?.address}</p>
|
||||||
@ -117,6 +112,47 @@ const ReportsView = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<>
|
||||||
|
<p className={'block font-bold mb-2'}>Annotation</p>
|
||||||
|
<CardBox
|
||||||
|
className='mb-6 border border-gray-300 rounded overflow-hidden'
|
||||||
|
hasTable
|
||||||
|
>
|
||||||
|
<div className='overflow-x-auto'>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Text</th>
|
||||||
|
|
||||||
|
<th>Color</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{reports.Annotation &&
|
||||||
|
Array.isArray(reports.Annotation) &&
|
||||||
|
reports.Annotation.map((item: any) => (
|
||||||
|
<tr
|
||||||
|
key={item.id}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(
|
||||||
|
`/annotations/annotations-view/?id=${item.id}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<td data-label='text'>{item.text}</td>
|
||||||
|
|
||||||
|
<td data-label='color'>{item.color}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{!reports?.Annotation?.length && (
|
||||||
|
<div className={'text-center py-4'}>No data</div>
|
||||||
|
)}
|
||||||
|
</CardBox>
|
||||||
|
</>
|
||||||
|
|
||||||
<BaseDivider />
|
<BaseDivider />
|
||||||
|
|
||||||
<BaseButton
|
<BaseButton
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user