how can I get what will be next auto_increment value using Sequelize?
Using mysql query:
SELECT auto_increment
FROM information_schema.tables
WHERE table_schema = 'skolboz'
AND table_name = "cases";
Response is 7 because last inserted row in Cases is 6.
How can I achieve this using Sequelize? Is it even possible?
Thanks
EDIT:
Here is Sequelize model definition:
module.exports = (sequelize, DataTypes) => {
const Case = sequelize.define('Case', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
allowNull: false,
},
caseName: DataTypes.STRING,
constructionSite: DataTypes.STRING,
createdBy: DataTypes.STRING,
dateOfDiscovery: {
type: DataTypes.DATEONLY,
get: function() {
return moment(this.getDataValue('dateOfDiscovery')).format('DD.MM.YYYY')
}},
placeOfDiscovery: DataTypes.STRING,
responsible: DataTypes.STRING,
text: DataTypes.TEXT,
sanction: DataTypes.INTEGER,
forCompany: DataTypes.STRING,
priority: DataTypes.STRING,
isActive: {
type: DataTypes.INTEGER,
defaultValue: 1,
},
wasSended: {
type: DataTypes.INTEGER,
defaultValue: 0,
},
})
Case.associate = (models) => {
Case.hasMany(models.caseimages, {foreignKey: 'id', as: 'images'});
};
return Case
}
Here is controller for creating case and adding photo to it.
async postCaseWithImages(req, res) {
try {
await upload(req, res);
console.log(req.files);
if (req.files.length <= 0) {
return res.send(`Musíte vybrať aspoň 1 fotku`);
}
const uploadsFileNames = [];
const uploadsMimeTypes = [];
const uploadsPath = [];
global.creationDate;
global.koordinatorName;
global.problemName;
global.constructionName;
global.discoveryPlace;
global.responsible;
global.problemText;
global.problemSanction;
global.adressedFor;
global.problemPriority;
global.problemActivity;
global.wasSended;
global.newCaseId;
Case.create({
caseName: req.body.caseName,
constructionSite: req.body.constructionSite,
createdBy: req.body.createdBy,
dateOfDiscovery: req.body.dateOfDiscovery,
placeOfDiscovery: req.body.placeOfDiscovery,
responsible: req.body.responsible,
text: req.body.text,
sanction: req.body.sanction,
forCompany: req.body.forCompany,
priority: req.body.priority,
isActive: req.body.isActive,
})
.then((result) => {
let formatedDate = moment(result.createdAt).format(
"DD.MM.YYYY, HH:mm:ss"
);
creationDate = formatedDate;
koordinatorName = result.createdBy;
problemName = result.caseName;
constructionName = result.constructionSite;
discoveryPlace = result.placeOfDiscovery;
responsible = result.responsible;
problemText = result.text;
problemSanction = result.sanction;
adressedFor = result.forCompany;
problemPriority = result.priority;
problemActivity = result.isActive;
wasSended = result.wasSended;
newCaseId = result.id;
})
.catch((err) => {
console.log(err);
res.status(500).send({
error: "Nepodarilo sa vytvoriť nedostatok z dôvodu: ",
err,
});
})
.then(() => {
const checkId = Case.findOne({ where: {id: newCaseId }});
if (checkId == null) {
res.status(400).send({ message: 'Prípad so zadaným ID sa nenašiel.'});
return;
}
for(let i=0;i<req.files.length;i++){
uploadsFileNames.push(req.files[i].filename);
uploadsMimeTypes.push(req.files[i].mimetype);
uploadsPath.push(req.files[i].destination);
CaseImage.create({
fileName: uploadsFileNames[i],
mimeType: uploadsMimeTypes[i],
caseId: newCaseId,
path: uploadsPath[i],
})
}
let doc = new PDFDocument({ margin: 30, size: "A4", compress:false });
doc.pipe(
fs.createWriteStream(`pdf/${problemName}_${creationDate}` + ".pdf")
);
doc.image('logo.png', 485, 10, {width: 100})
const photosToPdf = [];
let positionX = 30;
let positionY = 240;
for(let j=0;j<uploadsPath.length;j++){
photosToPdf.push(uploadsFileNames[j]);
}
photosToPdf.forEach(img => {
if(positionX == 555){
positionX = 30
positionY = positionY + 160
}
doc.image(`uploads/${img}`, positionX, positionY, {width: 265});
positionX = positionX + 275
});
const table = {
title: "Zápis koordinátora " + koordinatorName + "zo dna " + creationDate + ".",
divider: {
header: { disabled: false },
horizontal: { disabled: false, width: 0.5, opacity: 1 },
padding: 25,
columnSpacing: 20,
},
headers: [
{ label:"Názov", property: 'name', width: 70, renderer: null },
{ label:"Názov staveniska (stavba)", property: 'construction', width: 80, renderer: null },
{ label:"Vytvoril koordinátor BOZP", property: 'createdName', width: 80, renderer: null },
{ label:"Priorita", property: 'priority', width: 50, renderer: null },
{ label:"Dátum zistenia", property: 'date', width: 80, renderer: null },
{ label:"Zodpovedný za vyriešenie zistenia", property: 'responsible', width: 100, renderer: null },
{ label:"Miesto zistenia", property: 'placeOfDiscovery', width: 90, renderer: null },
],
datas: [
{
options: { fontSize: 10, separation: true},
name: problemName,
construction: constructionName,
createdName: koordinatorName,
priority: problemPriority,
date: creationDate,
responsible: responsible,
placeOfDiscovery: discoveryPlace,
},
],
};
doc.table(table, {
columnSpacing: 10,
padding: 10,
columnsSize: [200,220,135],
align: "center",
prepareHeader: () => doc.font("Helvetica-Bold").fontSize(8),
prepareRow: (row, indexColumn, indexRow, rectRow, rectCell) => {
const {x, y, width, height} = rectCell;
if(indexColumn === 0){
doc
.lineWidth(.5)
.moveTo(x, y)
.lineTo(x, y + height)
.stroke();
}
doc
.lineWidth(.5)
.moveTo(x + width, y)
.lineTo(x + width, y + height)
.stroke();
doc.fontSize(8).fillColor('#292929');
},
});
const table2 = {
divider: {
header: { disabled: false },
horizontal: { disabled: false, width: 0.5, opacity: 1 },
padding: 25,
columnSpacing: 20,
},
headers: [
{ label:"Návrh na udelenie sankcie", property: 'sanction', width: 100, renderer: null },
{ label:"Pre spolocnost", property: 'forCompany', width: 100, renderer: null },
{ label:"Popis problému", property: 'text', width: 350, renderer: null},
],
datas: [
{
options: { fontSize: 10, separation: true},
sanction: 50,
forCompany: adressedFor,
text: problemText,
},
],
};
doc.table(table2, {
columnSpacing: 10,
padding: 10,
columnsSize: [200,220,135],
align: "center",
prepareHeader: () => doc.font("Helvetica-Bold").fontSize(8),
prepareRow: (row, indexColumn, indexRow, rectRow, rectCell) => {
const {x, y, width, height} = rectCell;
if(indexColumn === 0){
doc
.lineWidth(.5)
.moveTo(x, y)
.lineTo(x, y + height)
.stroke();
}
doc
.lineWidth(.5)
.moveTo(x + width, y)
.lineTo(x + width, y + height)
.stroke();
doc.fontSize(8).fillColor('#292929');
},
});
doc.end();
})
.catch((err) => {
console.log(err);
res.status(500)
})
await highPriorityEmail();
res.status(200).send({
message: "Nedostatok bol úspešne vytvorený.",
});
} catch (err) {
console.log(err);
res.status(500);
}
},
Here is route:
app.post('/api/v1/cases/:id/images',
CaseImagesController.postCaseWithImages)
Here is Vue.js function:
async submitCaseWithPhotos() {
const id = this.newId;
const bozpCaseImage = new FormData();
bozpCaseImage.append('multi-files', this.file);
bozpCaseImage.append('caseName', this.caseName);
bozpCaseImage.append('constructionSite', this.$store.state.selectedConstruction);
bozpCaseImage.append('createdBy', this.logedUser);
bozpCaseImage.append('dateOfDiscovery', this.date);
bozpCaseImage.append('responsible', this.responsible);
bozpCaseImage.append('placeOfDiscovery', this.placeOfDiscovery);
bozpCaseImage.append('text', this.text);
bozpCaseImage.append('sanction', this.sanction);
bozpCaseImage.append('forCompany', this.forCompany);
bozpCaseImage.append('priority', this.priority);
CaseImagesService.postImageWithCase(id, bozpCaseImage)
.then((response) => {
console.log(response)
this.$router.push({ name: 'Cases' });
})
.catch((error) => {
console.log(error)
this.error = "Failed to submit data - please try again later.";
});
},
And this is function when I get this.newId:
async getNewCaseId(){
CasesService.index()
.then((response) => {
const resData = response.data;
const responseArray = []
responseArray.push(resData);
const arrayLength = responseArray[0].length;
const lastId = responseArray[0][arrayLength - 1].id
const newId = lastId + 1
console.log(newId);
this.newId = newId;
})
}
Here is working, updated function.
async postCaseWithImages(req, res) {
try {
await upload(req, res);
console.log(req.files);
if (req.files.length <= 0) {
return res.send(`Musíte vybrať aspoň 1 fotku`);
}
const uploadsFileNames = [];
const uploadsMimeTypes = [];
const uploadsPath = [];
global.newCaseId;
global.creationDate;
global.koordinatorName;
global.problemName;
global.constructionName;
global.discoveryPlace;
global.responsible;
global.problemText;
global.problemSanction;
global.adressedFor;
global.problemPriority;
global.problemActivity;
global.wasSended;
global.emailGroup;
Case.create({
caseName: req.body.caseName,
constructionSite: req.body.constructionSite,
createdBy: req.body.createdBy,
dateOfDiscovery: req.body.dateOfDiscovery,
placeOfDiscovery: req.body.placeOfDiscovery,
responsible: req.body.responsible,
text: req.body.text,
sanction: req.body.sanction,
forCompany: req.body.forCompany,
priority: req.body.priority,
isActive: req.body.isActive,
mailingListGroup: req.body.mailingListGroup,
})
.then((result) => {
let formatedDate = moment(result.createdAt).format(
"DD.MM.YYYY, HH:mm:ss"
);
newCaseId = result.id;
creationDate = formatedDate;
koordinatorName = result.createdBy;
problemName = result.caseName;
constructionName = result.constructionSite;
discoveryPlace = result.placeOfDiscovery;
responsible = result.responsible;
problemText = result.text;
problemSanction = result.sanction;
adressedFor = result.forCompany;
problemPriority = result.priority;
problemActivity = result.isActive;
wasSended = result.wasSended;
emailGroup = result.mailingListGroup;
})
.catch(() => {
console.log(err);
res.status(500).send({
error: "Nepodarilo sa vytvoriť nedostatok z dôvodu: ",
err,
});
})
.then(async () => {
const checkId = Case.findOne({ where: {id: newCaseId }});
if (checkId == null) {
res.status(400).send({ message: 'Prípad so zadaným ID sa nenašiel.'});
return;
}
for(let i=0;i<req.files.length;i++){
uploadsFileNames.push(req.files[i].filename);
uploadsMimeTypes.push(req.files[i].mimetype);
uploadsPath.push(req.files[i].destination);
CaseImage.create({
fileName: uploadsFileNames[i],
mimeType: uploadsMimeTypes[i],
caseId: newCaseId,
path: uploadsPath[i],
})
}
let doc = new PDFDocument({ margin: 30, size: "A4", compress:false });
doc.pipe(
fs.createWriteStream(`pdf/${problemName}_${creationDate}` + ".pdf")
);
doc.image('Skolboz_bez_pozadia.png', 500, 25, {width: 100})
const photosToPdf = [];
let positionX = 30;
let positionY = 240;
for(let j=0;j<uploadsPath.length;j++){
photosToPdf.push(uploadsFileNames[j]);
}
photosToPdf.forEach(img => {
if(positionX >= 550){
positionX = 30
positionY = positionY + 215
}
doc.image(`uploads/${img}`, positionX, positionY, {width: 265});
positionX = positionX + 275
});
const table = {
title: "Zápis koordinátora " + koordinatorName + " zo dna " + creationDate + ".",
divider: {
header: { disabled: false },
horizontal: { disabled: false, width: 0.5, opacity: 1 },
padding: 25,
columnSpacing: 20,
},
headers: [
{ label:"Názov", property: 'name', width: 70, renderer: null },
{ label:"Názov staveniska (stavba)", property: 'construction', width: 80, renderer: null },
{ label:"Vytvoril koordinátor BOZP", property: 'createdName', width: 80, renderer: null },
{ label:"Priorita", property: 'priority', width: 50, renderer: null },
{ label:"Dátum zistenia", property: 'date', width: 80, renderer: null },
{ label:"Zodpovedný za vyriešenie zistenia", property: 'responsible', width: 100, renderer: null },
{ label:"Miesto zistenia", property: 'placeOfDiscovery', width: 90, renderer: null },
],
datas: [
{
options: { fontSize: 10, separation: true},
name: problemName,
construction: constructionName,
createdName: koordinatorName,
priority: problemPriority,
date: creationDate,
responsible: responsible,
placeOfDiscovery: discoveryPlace,
},
],
};
doc.table(table, {
columnSpacing: 10,
padding: 10,
columnsSize: [200,220,135],
align: "center",
prepareHeader: () => doc.font("Helvetica-Bold").fontSize(8),
prepareRow: (row, indexColumn, indexRow, rectRow, rectCell) => {
const {x, y, width, height} = rectCell;
if(indexColumn === 0){
doc
.lineWidth(.5)
.moveTo(x, y)
.lineTo(x, y + height)
.stroke();
}
doc
.lineWidth(.5)
.moveTo(x + width, y)
.lineTo(x + width, y + height)
.stroke();
doc.fontSize(8).fillColor('#292929');
},
});
const table2 = {
divider: {
header: { disabled: false },
horizontal: { disabled: false, width: 0.5, opacity: 1 },
padding: 25,
columnSpacing: 20,
},
headers: [
{ label:"Návrh na udelenie sankcie", property: 'sanction', width: 100, renderer: null },
{ label:"Pre spolocnost", property: 'forCompany', width: 100, renderer: null },
{ label:"Popis problému", property: 'text', width: 350, renderer: null},
],
datas: [
{
options: { fontSize: 10, separation: true},
sanction: 50,
forCompany: adressedFor,
text: problemText,
},
],
};
doc.table(table2, {
columnSpacing: 10,
padding: 10,
columnsSize: [200,220,135],
align: "center",
prepareHeader: () => doc.font("Helvetica-Bold").fontSize(8),
prepareRow: (row, indexColumn, indexRow, rectRow, rectCell) => {
const {x, y, width, height} = rectCell;
if(indexColumn === 0){
doc
.lineWidth(.5)
.moveTo(x, y)
.lineTo(x, y + height)
.stroke();
}
doc
.lineWidth(.5)
.moveTo(x + width, y)
.lineTo(x + width, y + height)
.stroke();
doc.fontSize(8).fillColor('#292929');
},
});
doc.end();
await highPriorityEmail(emailGroup);
})
.catch((err) => {
console.log(err);
res.status(500)
})
.then(() => {
res.status(200).send({
message: "Nedostatok bol úspešne vytvorený.",
});
})
} catch (err) {
console.log(err);
res.status(500);
}
},
Here is also new HighPriorityEmail() function, which now gets parameter.
function highPriorityEmail(emailGroup){
return new Promise((resolve, reject) => {
setTimeout(async () => {
const emailAdress = await getEmails(emailGroup);
let filePath = path.join(__dirname, `../../pdf/${problemName}_${creationDate}.pdf`);
let attachment = fs.readFileSync(filePath).toString("base64");
let fileName = `${problemName}_${creationDate}.pdf`;
if (problemPriority == "vysoká") {
const msg = {
to: emailAdress, // Change to your recipient
from: "someone#example.com"
subject: "Vytvorenie nového nedostatku: " + problemName,
html: `
Dobrý deň, <br>
<br>
dňa ${creationDate} bol vykonaný dozor koordinátora ${koordinatorName}. <br>
Boli zistené nedostatky s vysokou prioritou, ktoré sú priložené v prílohe tohoto emailu.
<br>
`,
attachments: [
{
content: attachment,
filename: fileName,
type:'application/pdf'
},
],
};
sgMail
.send(msg)
.then(() => {
console.log("Email sent");
})
.catch((error) => {
console.error(error);
});
Case.update(
{ wasSended: 1 },
{ returning: true, where: { caseName: problemName } }
);
}
resolve();
}, 1000)
});
};
And finally here is getEmails() function.
async function getEmails (emailGroup){
const groupResponse = await MailingListGroup.findAll({ where: { mailingListGroup: emailGroup }})
let gropudId = JSON.stringify(groupResponse[0].id);
const emailsResponse = await MailingListEmails.findAll({ where: { mailingListGroup: gropudId }})
const emails = [];
for(let i=0; i<emailsResponse.length; i++){
emails.push(emailsResponse[i].email);
}
return emails;
}
Related
I have react google chart timeline with chartEvents.
I want when clicked on define chart, display modal window.
On first page load it doesnt work (and when I reload page).
But if I going to another tab in my app,then return to my timeline and click on chart its work without problems.
Please give me advice, whats a problem?
P.S.
I have some thoughts about this:
Problems with load of timeline(in first load page doesnt load all data in google-chart)
Problems with useState(Many counts of useState in my component)
My code example:
Modal.setAppElement('#modal')
interface IItem {
name: string,
duration: string,
id: string,
startDate: Date,
endDate: Date
}
export const options = {
timeline: {
groupByRowLabel: true,
colorByRowLabel: true,
showBarLabels: false,
barLabelStyle: { fontSize: 18 },
},
tooltip: {
isHtml: true
}
}
export function NewGantt() {
const [modalIsOpen, setIsOpen] = useState(false)
const [selectedVacation, setselectedVacation] = useState({ fullname: '', duration: '', startDate: new Date(), endDate: new Date(), vacationId: '' })
const [rows, setrows] = useState([['', '', '', new Date(), new Date(), null, 0, null]])
const [projects, setprojects] = useState<IProject[]>([])
const [selected, setSelected] = useState(selectedOptions[0])
const [dataArray, setDataArray] = useState([
[
{ type: 'string', id: 'Name' },
{ type: 'string', id: 'Duration' },
{ type: 'string', role: 'tooltip', div: { html: true } },
{ type: 'string', id: 'style', role: 'style' },
{ type: 'date', id: 'Start' },
{ type: 'date', id: 'End' },
],
[
'User', '01.01.2022-02.01.2022', `
<div style='padding: 10px'>
<b>User:</b> user <br><hr>
<div style='margin-top: 10px'><b>Vacation dates:</b> 01.01.2022-02.01.2022</div>
</div>
`, 'black', new Date('Sun Mar 12 2023 00:00:00 GMT+0700'), new Date('Sun Mar 13 2023 00:00:00 GMT+0700')
]
]) as any
const { isLoading: isLoadingProjects, refetch: refetch } = useQuery(
['projects'],
async () => {
const res = await axios.get(`${SERVER_URI}/rest/workspace/pm/projects`, {
headers: {
Authorization: `${localStorage.getItem('JWT_Token')}`,
},
})
if (res.data) {
setprojects(res.data.map((el: IProject) => ({ ...el, isActive: false })))
}
},
{
refetchOnWindowFocus: false,
},
)
function projectsButton(project: IProject) {
const projectIndex = projects.findIndex(
(pr) => pr.projectId === project.projectId,
)
const arr = [...projects]
arr[projectIndex].isActive = !arr[projectIndex].isActive
setprojects(arr)
}
useEffect(() => {
const activeProjectIds = [...projects]
.filter((pr) => pr.isActive)
.map((pr) => pr.projectId)
.join(',')
if (activeProjectIds.length > 0) {
requestOfStatus(selected.statusType, activeProjectIds)
} else {
requestOfStatus(selected.statusType, '')
}
}, [projects])
const arr: any[][] = []
useEffect(() => {
const arrayObjects: any[] = [
{ type: 'string', id: 'Name' },
{ type: 'string', id: 'Duration' },
{ type: 'string', role: 'tooltip', div: { html: true } },
{ type: 'string', id: 'style', role: 'style' },
{ type: 'date', id: 'Start' },
{ type: 'date', id: 'End' },
]
rows.forEach((vacation: any) => {
const name = vacation[1]
const startDate = new Date(vacation[2])
const endDate = new Date(vacation[3])
const duration = `${startDate.toLocaleDateString()} - ${endDate.toLocaleDateString()} + ${vacation[0].toString()}`
const tooltip = `
<div style='padding: 10px'>
<b>Пользователь:</b> ${name}<br><hr>
<div style='margin-top: 10px'><b>Dates of vacations:</b> ${startDate.toLocaleDateString()} - ${endDate.toLocaleDateString()}</div>
</div>
`
let color: string
if (vacation[7] === 'decisionRejected') {
color = 'red'
} else if (vacation[7] === 'noDecision') {
color = 'blue'
} else if (vacation[7] === 'decisionApproved') {
color = 'green'
} else {
color = 'black'
}
const object = [name, duration, tooltip, color, startDate, endDate]
arr.push(object)
})
const merged = [arrayObjects, ...arr]
setDataArray(merged)
}, [rows])
const requestOfStatus = async (statusType: string, activeProjectIds: string) => {
const requests = []
const output: any[][] = []
if (statusType === 'all') {
requests.push(await axios.get(`${SERVER_URI}/rest/workspace/pm/vacations?stringProjectIds=${activeProjectIds}&approveType=noDecision`, {
headers: {
Authorization: `${localStorage.getItem('JWT_Token')}`,
},
}))
requests.push(await axios.get(`${SERVER_URI}/rest/workspace/pm/vacations?stringProjectIds=${activeProjectIds}&approveType=decisionApproved`, {
headers: {
Authorization: `${localStorage.getItem('JWT_Token')}`,
},
}))
requests.push(await axios.get(`${SERVER_URI}/rest/workspace/pm/vacations?stringProjectIds=${activeProjectIds}&approveType=decisionRejected`, {
headers: {
Authorization: `${localStorage.getItem('JWT_Token')}`,
},
}))
} else {
requests.push(await axios.get(`${SERVER_URI}/rest/workspace/pm/vacations?stringProjectIds=${activeProjectIds}&approveType=${statusType}`, {
headers: {
Authorization: `${localStorage.getItem('JWT_Token')}`,
},
}))
}
axios.all(requests).then(axios.spread((...res) => {
const rows: any[][] = []
for (let i = 0; i < res.length; i++) {
const merged = [...res[i].data]
const urls = res[i].config.url
merged.forEach((vacation: any) => {
const startDate = new Date(vacation.vacationStartDate)
startDate.setDate(startDate.getDate() - 1)
rows.push([
vacation.vacationId, // index
vacation.user.userDetails.fullName, // user fullname
startDate, // start date
new Date(vacation.vacationEndDate), // end date
++vacation.duration, // duration
100, // progress
null, // dependencies
urls?.split('approveType=')[1].trim()
])
})
}
const flags: never[] = [], l = rows?.length
let i
// eslint-disable-next-line #typescript-eslint/no-explicit-any, #typescript-eslint/ban-ts-comment
// #ts-ignore
for (i = 0; i < l; i++) {
// eslint-disable-next-line #typescript-eslint/no-explicit-any, #typescript-eslint/ban-ts-comment
// #ts-ignore
if (flags[rows[i][3]]) continue;
// eslint-disable-next-line #typescript-eslint/no-explicit-any, #typescript-eslint/ban-ts-comment
// #ts-ignore
flags[rows[i][3]] = true;
// eslint-disable-next-line #typescript-eslint/no-explicit-any, #typescript-eslint/ban-ts-comment
// #ts-ignore
output.push(rows[i]);
}
setrows(output)
}))
}
const openModal = () => {
setIsOpen(()=>{
return true
})
}
return (
<>
<Header />
<div className='flex flex-col justify-center w-10/12 p-6 m-auto'>
<div className='flex flex-row items-center'>
<div className='flex flex-row'>
{!isLoadingProjects &&
projects &&
(projects as [])?.map((project: IProject) => (
<button
key={project.projectId}
onClick={() => {
projectsButton(project)
}}
className={`px-4 py-2 pt-0 mt-5 mr-5 font-bold text-white rounded hover:bg-gray-700 ${!project.isActive
? 'bg-white border-2 text-gray-500 border-gray-500/50'
: 'text-white bg-gray-500'
}`}
>
{project.projectName}
</button>
))}
</div>
<ApproveTypeMenu onSelected={(item: { id: number, name: string, statusType: string }) => { setSelected(item) }} selected={selected} />
<button className='px-4 py-2 pt-0 mt-5 mr-5 font-bold text-white rounded hover:bg-gray-700 bg-white border-2 text-gray-500 border-gray-500/50'>Применить фильтры</button>
</div>
<Chart
chartType="Timeline"
data={dataArray}
width='100%'
height="600px"
options={options}
chartLanguage='ru'
chartEvents={[
{
eventName: 'ready',
callback: (params) => {
const { chartWrapper, google } = params
const chart: any = chartWrapper.getChart()
google.visualization.events.addListener(chart, 'select', () => {
const [fullname, duration, , , startDate, endDate] = dataArray[chart.getSelection()[0].row + 1]
const vacationId = duration.split('+')[1].trim()
setselectedVacation({ fullname: `${fullname}`, duration: `${duration}`, startDate: startDate, endDate: endDate, vacationId: `${vacationId}` })
openModal()
})
},
},
]}
controls={[
{
controlType: 'CategoryFilter',
options: {
filterColumnIndex: 0,
ui: {
allowTyping: true,
allowMultiple: true,
orientation: 'horizontal',
caption: 'Choose colleague',
showRangeValues: false,
label: 'Filter by colleagues',
labelSeparator: ' ',
},
filterColumnLabel: 'Column Label'
},
controlPosition: 'top',
}
]}
/>
</div>
{selectedVacation.vacationId?.length > 0 && (
<PMModal
vacation={selectedVacation}
isModalOpen={modalIsOpen}
setIsModalOpen={setIsOpen}
refetch={refetch}
/>
)}
</>
);
}
My chartEvents code example without 'ready' event
chartEvents={[
{
eventName: 'select',
callback: (params) => {
const { chartWrapper, google } = params
const chart: any = chartWrapper.getChart()
const [fullname, duration, , , startDate, endDate] = dataArray[chart.getSelection()[0].row + 1]
const vacationId = duration.split('+')[1].trim()
setselectedVacation({ fullname: `${fullname}`, duration: `${duration}`, startDate: startDate, endDate: endDate, vacationId: `${vacationId}` })
openModal()
},
},
]}
i tried loop images from array data into excel using excel js, but the images doesn't show at all.
this this my looping code:
async testAja() {
const workbook = new excelJS.Workbook();
const worksheet = workbook.addWorksheet("My Sheet");
worksheet.columns = [
{ header: 'Date', key: 'date', width: 15, style: { numFmt: 'dd/mm/yyyy' } },
{ header: 'Title', key: 'title', width: 100 },
{ header: 'Confirmation', key: 'confirmation', width: 15 },
{ header: 'Location', key: 'location', width: 15 },
{ header: 'Remark', key: 'remark', width: 15 },
{ header: 'Photo', key: 'photo', width: 20 },
];
let num = 1;
this.state.dataInspection.forEach(async (val, idx) => {
if (val.label_id === null && val.label_id === '') {
const imageBuffer = await axios.get(`https://toqrikyppyhsmwwiabyc.supabase.co/storage/v1/object/public/inspection/photos/${val.photo}`, { responseType: 'arraybuffer' });
const imageId = workbook.addImage({
buffer: imageBuffer.data,
});
worksheet.addImage(imageId, `A${num + 1}:A${num + 5}`);
num += 1;
}
});
workbook.xlsx.writeBuffer().then(function (buffer) {
const blob = new Blob([buffer], { type: "applicationi/xlsx" });
saveAs(blob, "inspection.xlsx");
});
}
and here is my array data
enter image description here
I am using pdf.js to extract text from the pdf but the font name appears as g_d0_f6 etc. I need the font name to use the appropriate table for converting to Unicode. Here is the code derived from pdf2svg.js sample:-
var fs = require('fs');
var util = require('util');
var path = require('path');
var stream = require('stream');
// HACK few hacks to let PDF.js be loaded not as a module in global space.
require('./domstubs.js').setStubs(global);
var pdfjsLib = require('pdfjs-dist');
var pdfPath = process.argv[2] || '../../web/compressed.tracemonkey-pldi-09.pdf';
var data = new Uint8Array(fs.readFileSync(pdfPath));
var loadingTask = pdfjsLib.getDocument({
data: data,
nativeImageDecoderSupport: pdfjsLib.NativeImageDecoding.DISPLAY,
});
loadingTask.promise.then(function(doc) {
var lastPromise = Promise.resolve(); // will be used to chain promises
var loadPage = function (pageNum) {
return doc.getPage(pageNum).then(function (page) {
return page.getTextContent().then(function (textContent) {
console.log(textContent);
});
});
};
for (var i = 1; i <= doc.numPages; i++) {
lastPromise = lastPromise.then(loadPage.bind(null, i));
}
return lastPromise;
}).then(function () {
console.log('# End of Document');
}, function (err) {
console.error('Error: ' + err);
});
Sample output:-
{ items:
[ { str: 'bl fp=k osQ ckjs esa cPpksa ls ckrphr djsa & ;g LowQy esa fdl le; dk n`\'; gS\\ cPps',
dir: 'ltr',
width: 396.2250000000001,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 'D;k dj jgs gSa\\ cPps dkSu&dkSu ls [ksy] [ksy j',
dir: 'ltr',
width: 216.1650000000001,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 'g',
dir: 'ltr',
width: 6.42,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 's gSa\\ fp=k esa fdrus cPps gSa vkSj fdrus',
dir: 'ltr',
width: 173.865,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 'cM+s gSa\\ vkil esa dkSu D;k ckr dj jgk gksxk\\ cPpksa ls fp=k esa lcosQ fy, uke lkspus',
dir: 'ltr',
width: 396.54000000000013,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 'dks dgasaA',
dir: 'ltr',
width: 40.74,
height: 15,
transform: [Array],
fontName: 'g_d0_f1' },
{ str: 'csVh cpkvks',
dir: 'ltr',
width: 66.725,
height: 17,
transform: [Array],
fontName: 'g_d0_f2' },
{ str: 'csVh i<+kvksA',
dir: 'ltr',
width: 66.75899999999999,
height: 17,
transform: [Array],
fontName: 'g_d0_f2' },
{ str: '2018-19',
dir: 'ltr',
width: 36.690000000000005,
height: 10,
transform: [Array],
fontName: 'g_d0_f3' } ],
styles:
{ g_d0_f1:
{ fontFamily: 'sans-serif',
ascent: 0.837,
descent: -0.216,
vertical: false },
g_d0_f2:
{ fontFamily: 'sans-serif',
ascent: 0.786,
descent: -0.181,
vertical: false },
g_d0_f3:
{ fontFamily: 'sans-serif',
ascent: 0.9052734375,
descent: -0.2119140625,
vertical: false } } }
And here is the pdf that uses embedded fonts: http://ncert.nic.in/textbook/pdf/ahhn101.pdf
Here is a related question but the suggested commonObjs is empty: pdf.js get info about embedded fonts
Note: The answer below does not have anything to do with pdf.js, however it answers the question, Extract Font Name from PDF.
I did not find a solution yet, so I went ahead and grabbed mutool, which has has the following command to get the font information per page.
mutool info -F input.pdf 0-2147483647
Then I grabbed the spawn function, hacked the output through some regex and pattern matching to return the data.
const extractFontData = async str => {
const getMatches = str => {
const regex = /Page (\d+):\nFonts \((\d+)\):/;
const match = str.match(regex);
if (match) {
return { page: match[1], fonts: match[2] };
}
return {};
};
const singleFont = fontData => {
const match = fontData.match(/\+([a-zA-Z0-9_-]+[.,]?[a-zA-Z0-9_-]+)/);
return match && match[1];
};
return str
.split("Page ")
.map(singlePageData => {
const { page, fonts } = getMatches(`Page ` + singlePageData);
if (fonts) {
const split = singlePageData.split("\n").filter(e => e.length);
const fontList = split.slice(2).map(singleFont);
return { page, fonts, fontList };
}
})
.filter(e => e);
};
// Taken and adjusted from: https://stackoverflow.com/a/52611536/6161265
function run(...cmd) {
return new Promise((resolve, reject) => {
var { spawn } = require("child_process");
var command = spawn(...cmd);
var result = "";
command.stdout.on("data", function(data) {
result += data.toString();
});
command.on("close", function(code) {
resolve(result);
});
command.on("error", function(err) {
reject(err);
});
});
}
async function wrapper(filePath) {
const data = await run("mutool", ["info", "-F", filePath, "0-2147483647"]);
return extractFontData(data);
}
Sample usage:
wrapper("ahhn101.pdf").then(data => console.log(data));
Result:
I think you were on the right track: page.commonObjs is where the actual font name is found. However, page.commonObjs only gets populated when the page's text/operators are accessed, so you'll find it empty if you look before that happens.
I have something similar to the JSFiddle mentioned here. The JSFiddle works fine, however, I am seeing a strange behaviour in my code. The description of very first
cell is always empty even though I am seeing that in the returned data (in JSON format) from the webservice, the description is present for each record. Please
take a look at the code below and let me know if I am missing anything:
this.processEmployees = function (data_, textStatus_, jqXHR_) {
var collection = data_.employees;
// A helper function used for employee codes below.
var isUsedKey = function (arrayOfObject, key) {
for (var i = 0; i < arrayOfObject.length; i += 1) {
if (arrayOfObject[i].key == key) {
return true;
}
}
return false;
};
var employeeCodes = [];
for (var i = 0; i < collection.length; i++) {
if (i == 0) {
var newItem = {};
newItem.key = collection[i].code_value;
newItem.dates = [collection[i].code_assignment_date];
newItem.description = collection[i].code_description;
newItem.hiringCriterion = collection[i].hiring_criteria;
newItem.name = collection[i].name;
console.log("Would like to check code_description for first item:",collection[i].code_description);
//debugger;
employeeCodes.push(newItem);
} else {
var item = collection[i];
var itemName = item.code_value;
var itemDate = item.code_assignment_date;
var itemDescription = item.code_description;
var hiringCriterion = item.hiring_criteria;
var itemCodeName = item.name;
if (isUsedKey(employeeCodes, itemName)) {
for (var j = 0; j < employeeCodes.length; j++) {
if (employeeCodes[j].key == itemName) {
var index = employeeCodes[j].dates.length;
employeeCodes[j].dates[index] = itemDate;
}
}
} else {
var nextNewItem = {};
nextNewItem.key = itemName;
nextNewItem.dates = [itemDate];
nextNewItem.code_description = itemDescription;
nextNewItem.hiring_criteria = hiringCriterion;
nextNewItem.name = itemCodeName;
employeeCodes.push(nextNewItem);
}
}
}
var newSource = {
localdata: employeeCodes,
datafields: [{
name: 'code_value',
type: 'string',
map: 'key'
},
{
name: 'code_assignment_date',
type: 'date',
map: 'dates>0'
},
{
name: 'name',
type: 'string'
},
{
name: 'code_description',
type: 'string'
},
{
name: 'hiring_criteria',
type: 'string'
}
],
datatype: "array"
};
var newAdapter = new $_.jqx.dataAdapter(newSource);
var iconrenderer = function (row, columnfield, value, defaulthtml, columnproperties) {
var icon = '';
if (employeeCodes[row].dates.length > 1) {
icon = '<img src="images/icon-down.png" style="position: absolute; right: 5px;" />';
}
return '<span style="position: relative; width: 100%; margin: 4px; float: ' + columnproperties.cellsalign + ';">' + newAdapter.formatDate(value, 'd') + icon + '</span>';
};
$_(self.gridSelector).jqxGrid({
source: newAdapter,
editable: true,
width: '600',
pageable: true,
sortable: true,
autoheight: true,
theme: 'classic',
height: '170',
columnsResize: true,
columns: [
{
text: 'Employee Name',
datafield: 'name',
width: 85,
},
{
text: 'Code Value',
datafield: 'code_value',
width: 75,
editable: false
},
{
text: 'Latest Date(s)',
datafield: 'code_assignment_date',
cellsformat: 'd',
columntype: 'combobox',
width: 100
createeditor: function (row, column, editor) {
var info = $_(self.gridSelector).jqxGrid('getrowdata', row);
console.log("length of info: " + info);
var groupName = info.code_value;
console.log("Contents of groupName: " + groupName);
var dates = [];
for (var i = 0; i < employeeCodes.length; i++) {
if (employeeCodes[i].key == groupName) {
dates = employeeCodes[i].dates;
}
}
editor.jqxComboBox({ autoDropDownHeight: false, source: dates, promptText: "Previous Date(s):", scrollBarSize: 10 });
},
initeditor: function (row, column, editor) {
var info = $_(self.gridSelector).jqxGrid('getrowdata', row);
var groupName = info.code_value;
var dates = [];
for (var i = 0; i < employeeCodes.length; i++) {
if (employeeCodes[i].key == groupName) {
dates = employeeCodes[i].dates;
}
}
editor.jqxComboBox({
autoDropDownHeight: false,
source: dates,
promptText: "Dates:",
width: 100,
scrollBarSize: 10,
renderer: function (index_, label_, value_) {
return formatDateString(value_);
},
renderSelectedItem: function (index, item) {
var records = editor.jqxComboBox('getItems');
var currentRecord = records[index].label;
return formatDateString(currentRecord);;
}
});
},
cellvaluechanging: function (row, column, columntype, oldvalue, newvalue) {
// return the old value, if the new value is empty.
if (newvalue == "") return oldvalue;
}
},
{
text: 'Description',
datafield: 'code_description'
},
{
text: 'Hiring Criterion',
datafield: 'hiring_criteria',
editable: false,
hidden: true
}
],
});
}; // End of processEmployees
For Example, if my JSON is the following:
{
"employees": [{
"code_value": "B1",
"code_assignment_date": "2016-12-13 23:04:00.0",
"code_type": 7,
"code_description": "This employee has received his salary",
"name": "Peter",
"hiring_criteria": null
}, {
"code_value": "A1",
"code_assignment_date": "2016-05-20 05:00:00.0",
"code_type": 7,
"code_description": "Employee has 5 vacation days left",
"name": "Jack",
"hiring_criteria": null
}],
"webServiceStatus": {
"status": "SUCCESS",
"message": "2 results"
}
}
I am not seeing the very first code_description value which is This employee has received his salary in the above JSON response whereas the following
line mentioned in the above code clearly shows it in the console panel:
console.log("Would like to check code_description for first item:",collection[i].code_description);
newItem.description = collection[i].code_description;
---Replace newItem.description to newItem.code_description in First object condition
newItem.hiringCriterion = collection[i].hiring_criteria;
---Replace newItem.hiringCriterion to newItem.hiring_criteria in First object condition
I'm currently working on an input with mask in react-native, however I'd like to avoid input of non-numeric characters. I did, however I'd like to avoid the behavior below:
enter image description here
'use strict';
import React, { Component, PropTypes } from 'react';
import { styles, cleanStyle, dirtyStyle } from './styles';
import { colors } from '../../config/styles';
import {
Animated,
Easing,
Platform,
StyleSheet,
Text,
TextInput,
View,
Keyboard,
} from 'react-native';
const textPropTypes = Text.propTypes || View.propTypes;
const textInputPropTypes = TextInput.propTypes || textPropTypes;
const propTypes = {
...textInputPropTypes,
inputStyle: textInputPropTypes.style,
labelStyle: textPropTypes.style,
disabled: PropTypes.bool,
style: View.propTypes.style,
};
const SMInput = React.createClass({
propTypes,
getDefaultProps() {
return {
editable: true,
onlyNumbers: false,
underlineColorAndroid: 'transparent'
};
},
getInitialState() {
Keyboard.addListener('keyboardDidChangeFrame', () => {
console.log('keyboardDidChangeFrame');
});
const state = {
text: (this.props.value) ? this.props.value.toString() : '',
dirty: !!this.props.value,
borderColor: new Animated.Value(0),
labelColor: new Animated.Value(0),
maxLength: this.props.maxLength,
placeHolder: '',
};
const style = state.dirty ? dirtyStyle : cleanStyle;
state.labelStyle = {
fontSize: new Animated.Value(style.fontSize),
top: new Animated.Value(style.top),
position: new Animated.Value(style.position),
}
return state;
},
_animate(dirty) {
const animateTime = 150;
const nextStyle = dirty ? dirtyStyle : cleanStyle;
const labelStyle = this.state.labelStyle;
const anims = Object.keys(nextStyle).map(prop => {
return Animated.timing(
labelStyle[prop],
{
toValue: nextStyle[prop],
duration: animateTime,
},
Easing.ease
)
});
setTimeout(() => {
if (this.props.placeholder && dirty) {
this.setState({
placeHolder: this.props.placeholder
});
}
}, 120);
anims.push(
Animated.timing (
this.state.borderColor, {
toValue: dirty ? 1 : 0,
duration: animateTime,
}
)
);
anims.push(
Animated.timing (
this.state.labelColor, {
toValue: dirty ? 1 : 0,
duration: animateTime,
}
)
);
Animated.parallel(anims).start();
},
_onFocus() {
this._animate(true);
this.setState({ dirty: true });
if (this.props.onFocus) {
this.props.onFocus(arguments);
}
},
_onBlur() {
if (!this.state.text) {
this._animate(false);
this.setState({ dirty: false });
}
if (this.props.onBlur) {
this.props.onBlur(arguments);
}
if (this.props.placeholder) {
this.setState({
placeHolder: ''
});
}
},
onChangeText(text) {
this.setMask(text);
if (this.props.onChangeText) {
this.props.onChangeText(text);
}
},
setMask(text) {
//function mask(inputName, mask) {
var mask = '00/00/0000';
this.setState({
maxLength: mask.length
});
var value = text;
var literalPattern = /[0\*]/;
var numberPattern = /[0-9]/;
var newValue = '';
for (var vId = 0, mId = 0 ; mId < mask.length ; ) {
if (mId >= value.length) {
break;
}
// Number expected but got a different value, store only the valid portion
if (mask[mId] == '0' && value[vId].match(numberPattern) == null) {
break;
}
// Found a literal
while (mask[mId].match(literalPattern) == null) {
if (value[vId] == mask[mId]) {
break;
}
newValue += mask[mId++];
}
newValue += value[vId++];
mId++;
}
this.setState({
text: newValue
})
},
updateText(event) {
const text = event.nativeEvent.text;
this.setState({ text })
if (this.props.onEndEditing) {
this.props.onEndEditing(event);
}
},
_renderLabel() {
const labelColor = this.state.labelColor.interpolate({
inputRange: [ 0, 1 ],
outputRange: [ colors.darkPurple50, colors.purple100 ]
});
return (
<View style={ styles.wrapper }>
<Animated.Text
ref='label'
style={ [this.state.labelStyle, styles.label, this.props.labelStyle, { color: labelColor } ] }
>
{this.props.children}
</Animated.Text>
</View>
)
},
render() {
const borderColor = this.state.borderColor.interpolate({
inputRange: [ 0, 1 ],
outputRange: [ colors.gray80, colors.purple100 ]
});
const props = {
autoCapitalize: this.props.autoCapitalize,
autoCorrect: this.props.autoCorrect,
autoFocus: this.props.autoFocus,
bufferDelay: this.props.bufferDelay,
clearButtonMode: this.props.clearButtonMode,
clearTextOnFocus: this.props.clearTextOnFocus,
controlled: this.props.controlled,
editable: this.props.editable,
enablesReturnKeyAutomatically: this.props.enablesReturnKeyAutomatically,
keyboardType: this.props.keyboardType,
multiline: this.props.multiline,
onBlur: this._onBlur,
onChange: this.props.onChange,
onChangeText: this.onChangeText,
onEndEditing: this.updateText,
onFocus: this._onFocus,
onSubmitEditing: this.props.onSubmitEditing,
password: this.props.password,
returnKeyType: this.props.returnKeyType,
selectTextOnFocus: this.props.selectTextOnFocus,
selectionState: this.props.selectionState,
style: [styles.input],
maxLength: this.state.maxLength,
underlineColorAndroid: this.props.underlineColorAndroid, // android TextInput will show the default bottom border
onKeyPress: this.props.onKeyPress,
spellCheck: this.props.spellCheck,
mask: this.props.mask,
placeholder: this.state.placeHolder,
placeholderTextColor: colors.darkPurple50,
value: this.state.text,
};
const elementStyles = [styles.element];
if (this.props.inputStyle) {
props.style.push(this.props.inputStyle);
}
if (this.props.style) {
elementStyles.push(this.props.style);
}
if (!this.props.editable) {
elementStyles.push(styles.elementNotEditable);
props.style.push(styles.inputNotEditable);
}
return (
<Animated.View style={ [elementStyles, { borderColor: borderColor }] }>
{ this._renderLabel() }
<TextInput
{ ...props }
>
</TextInput>
</Animated.View>
);
},
});
SMInput.propTypes = {
disabled: PropTypes.bool,
style: Text.propTypes.style,
};
export default SMInput;