This is my code and in this the data displayed in chart is hole project data but in rally dashboard there is release filter at the top of your page. and i want my chart to show data of the the release selected by that filter and my sdk version in code is 1.33
<!DOCTYPE HTML\>
<script
src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js">
var WORKSPACE_OID = "__WORKSPACE_OID__";
var PROJECT_OID = "__PROJECT_OID__";
var PROJECT_SCOPING_UP = "__PROJECT_SCOPING_UP__";
var PROJECT_SCOPING_DOWN = "__PROJECT_SCOPING_DOWN__";
var MILS_IN_DAY = 86400000;
var DAYS_BACK = 30;
var filterChart;
var currentProjectDataSource;
var fromDate = new Date(new Date().getTime() - (MILS_IN_DAY * DAYS_BACK));
var allDefects = [];
// var currentRelease;
var onLoadAllIssues = function (result) {
// var defects = result.defects.filter(function (defect) {
// return defect.Release && defect.Release.\_refObjectName === currentRelease.Name;
// });
var labels = [];
var openDefects = [];
var closedDefects = [];
var defects = result.defects;
for (var count = 0; count < defects.length; count++) {
allDefects[allDefects.length] = defects[count];
var defect = defects[count];
labels.push(defect.CreationDate.split('T')[0]);
if (defect.ClosedDate !==null) {
closedDefects.push(defect.ClosedDate.split('T')[0]);
}
}
closedDefects.sort();
const counts = {};
labels.forEach(function (x) { counts[x] = (counts[x] || 0) + 1; });
const closedcounts = {};
closedDefects.forEach(function (x) { closedcounts[x] = (closedcounts[x] || 0) + 1; });
mychart(counts,closedcounts,labels)
};
var createCharts = function () {
var loadAllDefectsQuery = {
type: 'defect',
key: 'defects',
fetch: 'CreationDate,ClosedDate,ObjectID,FormattedID,Name,State,Priority',
order: 'CreationDate',
query: '((CreationDate != "null") OR (CreationDate > "' + dojo.date.stamp.toISOString(fromDate, { zulu: true }) +
'"))'
};
currentProjectDataSource.findAll(loadAllDefectsQuery, onLoadAllIssues);
};
var initPage = function () {
currentProjectDataSource = new rally.sdk.data.RallyDataSource(WORKSPACE_OID, PROJECT_OID, PROJECT_SCOPING_UP,
PROJECT_SCOPING_DOWN);
createCharts();
};
rally.addOnLoad(initPage);
function mychart(counts,closedcounts,labels) {
const pielable = labels;
const piedata = counts;
const closedcountsdata = closedcounts;
const data = {
datasets: [
{
label: 'Number of opened defects',
data: piedata,
},
{
label: 'Number of closed defects',
data: closedcountsdata,
}
]
};
const config = {
type: 'line',
data: data,
options: {
scales: {
x: {
min:"2022-01-01",
max:"2022-12-31",
type: 'time',
time:{
unit:'day',
},
},
y: {
beginAtZero: true,
grace: 5,
ticks: {
stepSize: 1,
},
},
},
plugins: {
legend: {
position: 'top',
},
title: {
display: true,
text: 'Defect Burndown Chart'
},
tooltip: {
yAlign: 'bottom',
titleMarginBottom: 0,
callbacks: {
title: function (context) {
return( `${context[0].label.slice(0, -13).replace(/,/g, " ")}`)
},
}
}
}
}
};
const myChart = new Chart(
document.getElementById('myChart'),
config
)
filterChart= function filterChart(date){
const year = date.value.substring(0,4);
const month = date.value.substring(5);
const lastday = (y,m)=>{
return new Date(y,m,0).getDate();
}
const startDate = `${date.value}-01`;
const endDate = `${date.value}-${lastday(year,month)}`;
myChart.config.options.scales.x.min=startDate;
myChart.config.options.scales.x.ma`your text`x=endDate;
myChart.update();
}}
</script>
I have a database of uploaded files , each file can have one of 4 stages; recieved, converting, done and failed. need to bring a count of each stage for each. The date is stored in the "ReceivedAt" column in ms.
this is my code. it works, but it takes a long time to get all the information out.
const dates = await Job.aggregate("recievedAt", "DISTINCT", { plain: false });
const dates_sorted = dates.sort((a, b) => a - b);
const rev_date = dates_sorted.reverse();
let day;
const summery_by_date = [];
try {
await Promise.all(
rev_date.map(async (date) => {
const string_d = new Date(Number(date.DISTINCT)).toDateString();
if (!(day === string_d)) {
day = string_d;
const d_num = new Date(Number(date.DISTINCT));
const date_midnight = d_num.toISOString().split("T")[0];
const beaging_date = Number(new Date(date_midnight).getTime());
const end_date = Number(beaging_date + 86400000);
const total = await Job.count({
where: {
recievedAt: {
[Op.between]: [beaging_date, end_date],
},
},
});
const failed = await Job.count({
where: {
[Op.and]: [
{
recievedAt: {
[Op.between]: [beaging_date, end_date],
},
},
{ stage: "failed" },
],
},
});
const converting = await Job.count({
where: {
[Op.and]: [
{
recievedAt: {
[Op.between]: [beaging_date, end_date],
},
},
{ stage: "converting" },
],
},
});
const recieved = await Job.count({
where: {
[Op.and]: [
{
recievedAt: {
[Op.between]: [beaging_date, end_date],
},
},
{ stage: "recieved" },
],
},
});
const done = await Job.count({
where: {
[Op.and]: [
{
recievedAt: {
[Op.between]: [beaging_date, end_date],
},
},
{ stage: "done" },
],
},
});
summery_by_date.push({
date: beaging_date,
total: total,
failed: failed,
converting: converting,
recieved: recieved,
done: done,
});`
thanks in advance
I was trying to export data from two tables into one excel sheet, I already export two table in to two sheets, how can I get all data in to sheet.
exportAsExcel(excelObj: ExcelExport,excelObjHeader: ExcelExport): void {
let wb: XLSX.WorkBook;
let header = excelObj.header
const ws: XLSX.WorkSheet = XLSXUtils.json_to_sheet(excelObj.data);
const ws1: XLSX.WorkSheet = XLSXUtils.json_to_sheet(excelObjHeader.data);
wb = XLSXUtils.book_new();
XLSXUtils.book_append_sheet(wb, ws, excelObj.sheetName);
XLSXUtils.book_append_sheet(wb, ws1, excelObjHeader.sheetName);
writeFile(wb, `${excelObj.fileName.trim()}${this.fileExtension}`);}
I am try to ger this format
I used exceljs module and I remodelled my problem using that module.
exportExcelReport(result)
{
this.sName = 'tsetName';
this.excelFileName = 'Teat_Excel.xlsx';
this.cols =['ID','ItemCode','ItemName','Quantity','Price','LineTotal']
var excelItem = [];
for (let index = 0; index < result.Details.length; index++) {
const element = result.Details[index].ID;
console.log(element);
excelItem.push({
ID: result.Details[index].ID,
ItemCode: result.Details[index].ItemCode,
ItemName: result.Details[index].ItemName,
Quantity: result.Details[index].Quantity,
Price: result.Details[index].Price,
LineTotal: result.Details[index].LineTotal
}); }
this.data=excelItem
var workbook = new Excel.Workbook();
workbook.creator = 'Web';
workbook.lastModifiedBy ='Web';
workbook.created = new Date();
workbook.modified = new Date();
workbook.addWorksheet(this.sName, { views: [{ state: 'frozen', ySplit: 4, activeCell: 'A1', showGridLines: true }] })
var sheet = workbook.getWorksheet(1);
var head1 = ["Document No.",result.Code , " Status" , result.Name, " Date Range",this.datePipe.transform( result.FromDate,'yyyy/mm/dd') +" - "+this.datePipe.transform( result.ToDate,'yyyy/mm/dd') ];
sheet.addRow("");
sheet.addRow(head1);
sheet.addRow("");
sheet.getRow(4).values = this.cols;
sheet.columns = [
{ key: 'ID' },
{ key: 'ItemCode' },
{ key: 'ItemName' },
{ key: 'Quantity' },
{ key: 'Price' },
{ key: 'LineTotal' },
];
sheet.addRows(this.data);
workbook.xlsx.writeBuffer().then(data => {
var blob = new Blob([data], { type: this.blobType });
var url = window.URL.createObjectURL(blob);
var a = document.createElement("a");
document.body.appendChild(a);
a.href = url;
a.download = this.excelFileName;
a.click();
});
}
refrense1
refrense2
I have a Mongoose schema/model with a property of completedSetup that is a Date type.
Project repo: https://github.com/rmgreenstreet/custom-forms
const mongoose = require('mongoose');
const passportLocalMongoose = require('passport-local-mongoose');
const Schema = mongoose.Schema;
const Location = require('./location');
const Response = require('./response');
const sgMail = require('#sendgrid/mail');
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
const crypto = require('crypto');
const forbiddenWords = ['realtor', 'realty', 'realestate', 'agent', 'broker', 'admin'];
const userSchema = new Schema({
firstname: {
type: String,
required: true
},
lastname: {
type: String,
required: true
},
username: String,
personalEmail:{
type:String,
required:true,
unique:true
},
role:{
type:String,
default:'User'
},
isCompanyAdmin: {
type:Boolean,
default: false
},
company: {
type:Schema.Types.ObjectId,
ref: 'Company'
},
location: {
type:Schema.Types.ObjectId,
ref: 'Location'
},
image: {
url: {
type:String,
default:'https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png'
},
public_id: String
},
isExpedited: {
type:Boolean,
default:false
},
isHidden: {
type:Boolean,
default:false
},
formAccessToken: {
type: String,
default: crypto.randomBytes(16).toString('hex')
},
completedSetup: Date,
responses: [
{
type:Schema.Types.ObjectId,
ref:'Response'
}
],
createAccountToken : {
type: String,
default: crypto.randomBytes(16).toString('hex')
},
resetPasswordToken : String,
resetPasswordExpires: Date,
created:{
type:Date,
default:Date.now()
}
});
userSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model('User',userSchema);
Querying by createdDate:
let beginDate = new Date();
beginDate.setMonth(beginDate.getMonth() - 6);
if (req.body.beginDate) {
beginDate = new Date(req.body.beginDate);
}
let endDate = new Date();
if (req.body.endDate) {
endDate = new Date(req.body.endDate);
}
const recentSetups = await User.find({completedSetup: {$gt: beginDate, $lte: endDate}});
This returns all Users, not just ones with the completedSetup between beginDate and endDate.
The strange thing is that the same query returns correctly on other schemas/models, but their dates are set differently.
On some models I have a created property that is set by default to Date.now(), that is set at creation, and the query returns those fine.
However seeding data for the completedSetup uses a pickaADate function that I've defined to choose a date sometime in the previous year, or in the current year up to the current month (this is a portfolio project still in development):
const fs = require('fs');
const faker = require('faker');
const crypto = require('crypto');
const Company = require('./models/company');
const Location = require('./models/location');
const User = require('./models/user');
const Form = require('./models/form');
const Question = require('./models/question');
const Response = require('./models/response');
const sampleImages = fs.readdirSync('./public/images/seeds');
function flipACoin() {
const yesOrNo = Math.floor(Math.random() *2);
// console.log(yesOrNo);
return yesOrNo;
}
async function pickADate() {
return new Promise((resolve, reject) => {
try {
const today = new Date();
const day = Math.ceil(Math.random() * 27);
// const thisOrLastYear = flipACoin();
const month = Math.ceil(Math.random() * today.getMonth())
const returnDate = new Date(today.getFullYear() - flipACoin(),month,day);
resolve(returnDate);
return;
} catch (err) {
console.log(`Error creating random date: ${err.message}`);
reject(Date.now());
return;
}
});
};
async function seedDefaultQuestions() {
try {
console.log('clearing all default questions from database')
await Question.deleteMany({});
} catch (err) {
console.log(err.message);
}
try {
console.log('adding default questions to database')
const defaultQuestionsJSON = await JSON.parse(await fs.readFileSync('./private/defaultQuestions.json'));
for (let question of defaultQuestionsJSON) {
// console.log(question);
await Question.create(question);
}
console.log(`${defaultQuestionsJSON.length} default questions added to database`);
} catch (err) {
console.log(err.message);
}
};
async function clearDatabase() {
console.log('Clearing database \n Clearing Companies');
await Company.deleteMany({});
console.log('All Companies deleted \n Clearing Locations');
await Location.deleteMany({});
console.log('All Locations deleted \n Clearing Users');
await User.deleteMany({role: {$ne:'owner'}});
console.log('All Users deleted \n Clearing Forms');
await Form.deleteMany({});
console.log('All forms deleted \n Clearing responses');
await Response.deleteMany({});
console.log('Database cleared');
};
async function seedDatabase() {
// const companyCount = Math.ceil(Math.random() * 200);
const companyCount = 10;
const defaultQuestions = await Question.find({isDefault:true});
async function createLocations(companyId) {
const locationCount = Math.ceil(Math.random() * 5);
let locationsArr = [];
for (let i = 0; i < locationCount; i++) {
let isPrimary = false;
if (i=== 0) {
isPrimary = true;
}
const randomImageIndex = Math.ceil(Math.random() * sampleImages.length);
const newLocation = await Location.create({
primary: isPrimary,
officeNumber: Math.ceil(Math.random() * 1000).toString(),
name: faker.company.companyName(),
phone: faker.phone.phoneNumber(),
fax: faker.phone.phoneNumber(),
address: {
streetNumber: Math.random(Math.ceil() * 1000),
streetName: faker.address.streetName(),
secondary: `Ste ${faker.random.alphaNumeric()}`,
city: faker.address.city(),
state: faker.address.stateAbbr(),
postal: faker.address.zipCode(),
country: 'USA'
},
website: faker.internet.url(),
images: [
{
secure_url:`/images/seeds/${sampleImages[randomImageIndex]}`
}
],
company: companyId,
created: await pickADate()
});
await newLocation.save();
newLocation.contacts = await createUsers(newLocation._id, companyId, 'Admin', (Math.ceil(Math.random() * 5)));
await newLocation.save();
console.log(`Location ${newLocation.name} created with ${newLocation.contacts.length} contacts`)
await createUsers(newLocation._id, companyId, 'User', (Math.ceil(Math.random() * 30)));
locationsArr.push(newLocation._id);
await newLocation.addDefaultForm();
}
return locationsArr;
};
async function createUsers(locationId, companyId, role, count) {
let contactsArr = [];
for (let i = 0; i < count; i++) {
const newFirstName = await faker.name.firstName();
const newLastName = await faker.name.lastName();
let newUser;
try {
newUser = await User.register({
firstname: newFirstName,
lastname: newLastName,
username: newFirstName+newLastName,
personalEmail: newFirstName+newLastName+'#test.com',
role: role,
company: companyId,
location: locationId,
formAccessToken: crypto.randomBytes(16).toString('hex'),
createAccountToken: crypto.randomBytes(16).toString('hex'),
created: await pickADate()
},'password');
} catch (err) {
if (err.message.includes('UserExistsError')) {
continue;
}
}
if(role === 'User');{
if(flipACoin()) {
newUser.responses.push(await createResponse(newUser));
await newUser.save();
} else {
continue;
}
if(flipACoin()) {
newUser.completedSetup = await pickADate();
await newUser.save();
} else {
continue;
}
};
contactsArr.push(newUser._id);
console.log(`${role} ${newUser.firstname} ${newUser.lastname} created`);
};
return contactsArr;
};
async function createResponse(user) {
return new Promise(async (resolve, reject) => {
console.log(`Creating a response for ${user.firstname}`)
const makeString = (charLimit) => {
let str = faker.lorem.paragraph()
if (str.length > charLimit) {
str = str.slice(0, charLimit - 1)
}
return str
}
let response = await Response.create({owner:user._id, created:await pickADate()});
try {
for (let question of defaultQuestions) {
const answer = {
questionId: question._id
}
if(question.inputType == 'Checkbox') {
answer.value = true;
}
if(question.inputType == 'Email') {
answer.value = faker.internet.email();
}
if(question.inputType == 'File') {
continue;
}
if(question.inputType == 'Image') {
continue;
}
if(question.inputType == 'Number') {
answer.value = Math.ceil(Math.random() * 99);
}
if(question.inputType == 'Password') {
answer.value = 'Pa55w0rd123';
}
if(question.inputType == 'Radio') {
question.value = 'No';
}
if(question.inputType == 'Select') {
question.value = "At&t";
}
if(question.inputType == 'Tel') {
answer.value = faker.phone.phoneNumber();
}
if (question.inputType == 'Text') {
if(question.maxLength) {
answer.value = makeString(question.maxLength);
} else {
answer.value = faker.lorem.words()
}
}
if(question.inputType == 'Textarea') {
answer.value = faker.lorem.paragraph();
}
if(question.inputType == 'Url') {
answer.value = faker.internet.url();
}
response.answers.push(answer);
}
await response.save();
resolve(response._id);
return;
} catch (err) {
console.log(`Error creating random response: ${err.message}.`);
reject(response);
return;
}
});
}
console.log(`Creating ${companyCount} companies`)
for(let i = 0; i < companyCount; i++) {
const newCompany = await Company.create({
name: faker.company.companyName(),
created: await pickADate()
});
newCompany.locations = await createLocations(newCompany._id);
await newCompany.save();
console.log(`${newCompany.name} created with ${newCompany.locations.length} locations`)
}
console.log('database seeded')
};
module.exports = {seedDatabase, clearDatabase, seedDefaultQuestions};
I'm thinking the issue is in that function generating a random date from the beginning of last year up to the current date, but I honestly can't see how new Date(yyyy(integer),monthIndex,day) would be any different from the date created by Date.now(), according to MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date under "Individual Date and Time Component Values"
Here is how the User data looks in MongoDB, the completedSetup property is the last one, and it looks to be formatted correctly:
Lastly, here is the log of some of what the query returns (hit the character limit with all of it):
[
{
image: {
url: 'https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png'
},
role: 'Admin',
isCompanyAdmin: false,
isExpedited: false,
isHidden: false,
formAccessToken: 'de5459c2cbf3ca1cbdb0a5daceb6ab61',
responses: [ 5e8b71b7e75a0726242637b9 ],
createAccountToken: 'a826054b8055243c52247a656eed9340',
created: 2020-03-04T06:00:00.000Z,
_id: 5e8b71b6e75a0726242637b8,
firstname: 'Larue',
lastname: 'Armstrong',
username: 'LarueArmstrong',
personalEmail: 'LarueArmstrong#test.com',
company: 5e8b71abe75a072624263688,
location: 5e8b71b6e75a0726242637b5,
__v: 1,
completedSetup: 2020-03-07T06:00:00.000Z
},
{
image: {
url: 'https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png'
},
role: 'User',
isCompanyAdmin: false,
isExpedited: false,
isHidden: false,
formAccessToken: '7bf9d040c0009691191f3122c14d3d51',
responses: [ 5e8b71c2e75a07262426392a ],
createAccountToken: 'b284c3f43fad0081f967f06926ee1d6d',
created: 2019-11-25T06:00:00.000Z,
_id: 5e8b71c1e75a072624263929,
firstname: 'Lance',
lastname: 'Wolff',
username: 'LanceWolff',
personalEmail: 'LanceWolff#test.com',
company: 5e8b71bfe75a0726242638dd,
location: 5e8b71bfe75a0726242638de,
__v: 1,
completedSetup: 2020-03-02T06:00:00.000Z
},
{
image: {
url: 'https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png'
},
role: 'User',
isCompanyAdmin: false,
isExpedited: false,
isHidden: false,
formAccessToken: '319cd6d626a48617c012be6c25fe66a8',
responses: [ 5e8b71c5e75a072624263977 ],
createAccountToken: '43e9161a30f7ebd672315c761da9e3d7',
created: 2019-06-03T05:00:00.000Z,
_id: 5e8b71c5e75a072624263976,
firstname: 'Kailey',
lastname: 'Ruecker',
username: 'KaileyRuecker',
personalEmail: 'KaileyRuecker#test.com',
company: 5e8b71bfe75a0726242638dd,
location: 5e8b71bfe75a0726242638de,
__v: 1,
completedSetup: 2020-02-23T06:00:00.000Z
},
{
image: {
url: 'https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png'
},
role: 'User',
isCompanyAdmin: false,
isExpedited: false,
isHidden: false,
formAccessToken: 'ccb5fc2c6ff671a8cb5bdcf432cbcb1b',
responses: [ 5e8b71c7e75a0726242639bd ],
createAccountToken: '8d3aa2ecd6e0da797d8cbf9846c78c9b',
created: 2019-04-20T05:00:00.000Z,
_id: 5e8b71c6e75a0726242639bc,
firstname: 'Skyla',
lastname: 'Dicki',
username: 'SkylaDicki',
personalEmail: 'SkylaDicki#test.com',
company: 5e8b71bfe75a0726242638dd,
location: 5e8b71bfe75a0726242638de,
__v: 1,
completedSetup: 2019-10-22T05:00:00.000Z
},
{
image: {
url: 'https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png'
},
role: 'User',
isCompanyAdmin: false,
isExpedited: false,
isHidden: false,
formAccessToken: '0641d2cf09459724ffea35d5cc96e2f1',
responses: [ 5e8b71c7e75a0726242639e0 ],
createAccountToken: '0f5e1bfd23df18835378c314efbcb206',
created: 2019-12-02T06:00:00.000Z,
_id: 5e8b71c7e75a0726242639df,
firstname: 'Rasheed',
lastname: 'Walsh',
username: 'RasheedWalsh',
personalEmail: 'RasheedWalsh#test.com',
company: 5e8b71bfe75a0726242638dd,
location: 5e8b71bfe75a0726242638de,
__v: 1,
completedSetup: 2020-02-16T06:00:00.000Z
},
{
image: {
url: 'https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_960_720.png'
},
role: 'User',
isCompanyAdmin: false,
isExpedited: false,
isHidden: false,
formAccessToken: '7f584ded07bfe5b20e95ef72ed2a7749',
responses: [ 5e8b71cae75a072624263a2b ],
createAccountToken: '0934cd5e7ccb75d476ecc23624e491f1',
created: 2020-02-27T06:00:00.000Z,
_id: 5e8b71cae75a072624263a2a,
firstname: 'Leanna',
lastname: 'Kuphal',
username: 'LeannaKuphal',
personalEmail: 'LeannaKuphal#test.com',
company: 5e8b71bfe75a0726242638dd,
location: 5e8b71bfe75a0726242638de,
__v: 1,
completedSetup: 2019-11-02T05:00:00.000Z
}
]
In the full list (something like 60+ results) several are before 11/2019, like the one in this snippet that is from 10/2019.
As usual, I feel dumb now that I've found the issue.
The problem was in the getPoints function.
It was treating every item in every sub-array it received as a point, and creating a point for it. So if the graphDatasets looked like:
[
['Invitations','Completions','Setups'],
[/* actual points data */]
]
And the points data had 7 months worth in it, it was adding 3 more points to the points array, extending the number of points.
I had to completely rewrite the structure of graphDatasets and update the renderCanvas function accordingly:
/* Don't know why I didn't have this as arrays of objects before, it's so much simpler */
const graphDatasets = [
[
{label:'Invitations',payload:recentInvitations,searchProperty:'created'},
{label:'Completions',payload:recentCompletions,searchProperty:'created'},
{label:'Setups',payload:recentSetups,searchProperty:'completedSetup'}
],
[
{label:'Companies',payload:recentCompanies,searchProperty:'created'},
{label:'Locations',payload:recentLocations,searchProperty:'created'}
]
];
//converts full object data from server into {month: String, count: Number} objects
//Add searchProperty argument
function getPoints(items, searchProperty) {
let points = [];
//access the data to be turned into points using the value at the .payload property
items.payload.forEach((item) => {
/* find the date to compare against using the searchProperty provided */
const workingDate = new Date(item[searchProperty])
const monthYear = `${workingDate.getMonth() + 1}/${workingDate.getFullYear()}`;
let existingPoint = points.find(point => point.x === monthYear);
if (existingPoint) {
existingPoint.y ++;
} else {
points.push({x:monthYear, y: 1});
}
});
return points;
};
// Returns the max Y value in our data list
function getMaxY(data) {
var max = 0;
for(var i = 0; i < data.length; i ++) {
if(data[i].y > max) {
max = data[i].y;
}
}
max += 10 - max % 10;
return max;
}
/* Removes objects from combined data where month matches, in order to draw only one copy of that
month on the X axis */
function removeDuplicates(originalArray, objKey) {
var trimmedArray = [];
var values = [];
var value;
for(var i = 0; i < originalArray.length; i++) {
value = originalArray[i][objKey];
if(values.indexOf(value) === -1) {
trimmedArray.push(originalArray[i]);
values.push(value);
}
}
return trimmedArray;
};
/* compare two arrays and if there are any missing months in either array, add them with a y value of 0, then sortby month/year */
function equalize(arr1, arr2) {
let newArr = arr2.reduce(function (result, obj2) {
if (arr1.some(obj1 => obj1['x'] === obj2['x'])) {
return result;
}
return [...result, {'x' : obj2['x'], 'y':0}];
}, arr1);
newArr.sort(function (a, b) {
a = a.x.split('/');
b = b.x.split('/')
return new Date(a[1], a[0], 1) - new Date(b[1], b[0], 1)
});
return newArr;
};
function renderCanvas(canvas, data) {
console.log('drawing on canvas');
const colors = ['indigo','blue','green','orange','purple','teal','fuschia'];
if(canvas.getContext) {
var xPadding = 30;
var yPadding = 30;
var xLength = canvas.width - yPadding;
var yLength = canvas.height - xPadding;
var pointsArr = [];
data.forEach(function (obj) {
pointsArr.push(getPoints(obj, obj.searchProperty));
});
for (let i = 0; i < pointsArr.length -1 ; i++) {
pointsArr[i] = equalize(pointsArr[i], pointsArr[i+1]);
};
var combinedData = Array.prototype.concat.apply([], pointsArr);
combinedData.sort(function(a,b) {
return new Date(a.created) - new Date(b.created)
});
var filteredPoints = removeDuplicates(combinedData, 'x');
/* cuts X axis into a number of sections double the number of points */
var xSpacing = xLength / (filteredPoints.length * 2);
var yMax = getMaxY(combinedData);
var ctx = canvas.getContext('2d');
ctx.font = 'italic 8pt sans-serif';
ctx.beginPath();
ctx.lineWidth = 6;
ctx.moveTo(yPadding,0);
ctx.lineTo(yPadding,yLength);
ctx.lineTo(canvas.width,yLength);
ctx.stroke();
ctx.closePath();
// Return the y pixel for a graph point
function getYPixel(val) {
return yLength - ((yLength / yMax) * (val));
}
// Return the y pixel for a graph point
function getXPixel(val) {
return ((xSpacing + yPadding) + (xSpacing * (2 * val)))
}
function drawLine(points, color, legendVal) {
/* move one xSpacing out from y Axis */
ctx.moveTo(yPadding + xSpacing, getYPixel(points[0].y));
ctx.beginPath();
ctx.fillStyle=color;
ctx.strokeStyle=color;
points.forEach((point) => {
const x = getXPixel(points.indexOf(point));
const y = (getYPixel(point.y)) ;
ctx.lineWidth = 2;
ctx.lineTo(x,y);
ctx.closePath();
ctx.stroke();
ctx.beginPath();
ctx.arc(x,y,5,0,360,false);
ctx.fillText(point.y, x + 2, y - 15);
ctx.closePath();
ctx.fill();
ctx.moveTo(x,y);
});
/* will need to update this (and other stuff) but use the label property of the data to label the line on the graph */
ctx.moveTo(canvas.width - yPadding, getYPixel(points[points.length-1].y));
ctx.fillText(legendVal, canvas.width - 20, getYPixel(points[points.length-1].y));
}
// Draw the X value texts
for(var i = 0; i < filteredPoints.length; i ++) {
if (i===0) {
ctx.fillText(filteredPoints[i].x, yPadding, yLength +20);
}else {
ctx.fillText(filteredPoints[i].x, (yPadding) + (xSpacing * (2 * i)), yLength + 20);
}
}
// Draw the Y value texts
ctx.textAlign = "right"
ctx.textBaseline = "middle";
for(var i = 0; i <= yMax; i += 10) {
if (i === yMax) {
ctx.fillText(i, xPadding - 10, getYPixel(i-1));
} else {
ctx.fillText(i, xPadding - 10, getYPixel(i));
}
};
pointsArr.forEach(async function (points) {
drawLine(points, colors[pointsArr.indexOf(points)], data[pointsArr.indexOf(points)].label);
});
}
};
NodeList.prototype.indexOf = Array.prototype.indexOf
canvases.forEach((canvas) => {
renderCanvas(
canvas,
graphDatasets[canvases.indexOf(canvas)]
);
});
I need a create an one excel file with 3 worksheets. For now I wrote a function which create worksheet and workbook. I have problem because I need write data into workshet in some executed async function. Maybe some code will describe what I have to do.
var Excel = require('exceljs');
const workbook = new Excel.Workbook({
useStyles: true
})
const headers = [
{ header: 'Plik', key: 'path', width: 40 },
{ header: 'Zwierze', key: 'name', width: 12 },
{ header: 'Prawdopodobienstwo(%)', key: 'confidence', width: 24 },
{ header: 'Czas odpowiedzi(s)', key: 'responseTime', width: 20 }
];
workbook.xlsx.writeFile("./excel/Wyniki.xlsx");
setWorkSheet = (name, responses, filename) => {
workbook.xlsx.readFile(filename)
.then(function () {
const worksheet = workbook.addWorksheet(name);
worksheet.columns = headers;
for (let i = 0; i < responses.length; i++) {
worksheet.addRow(responses[i]);
}
worksheet.getRow(1).style.font = { size: 12, name: 'Bahnschrift SemiBold SemiConden' }
worksheet.getRow(1).eachCell((cell) => {
cell.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: '993399' }
},
cell.style.font = {
color: {
argb: 'ffffff'
},
size: 14,
}
})
worksheet.eachRow((Row, rowNumber) => {
Row.alignment = {
horizontal: 'center',
}
Row.eachCell((Cell, cellNumber) => {
Cell.alignment = {
vertical: 'middle',
horizontal: 'center'
},
Cell.border = {
top: { style: 'double', color: { argb: 'black' } },
left: { style: 'double', color: { argb: 'black' } },
bottom: { style: 'double', color: { argb: 'black' } },
right: { style: 'double', color: { argb: 'black' } }
}
})
})
worksheet.views = [
{ state: 'frozen', xSplit: 1, ySplit: 1, activeCell: 'B2' },
];
return workbook.xlsx.writeFile(`${filename}`)
})
.then(function () {
console.log("Done");
})
.catch(function (err) {
console.log(err)
});
}
And this function for now create a new file with special defined name worksheet. I need execute this function 3 times and after this operations I need to have one file and 3 worksheets. Here are places where I executed this function:
async function Cognitive() {
let tab = [];
for (let i = 0; i < arrayOfFiles.length; i++) {
let x = await cognitive.cognitiveDetectLabels(arrayOfFiles[i]);
tab.push(x)
}
setWorkSheet('Cognitive', tab, "./excel/Wyniki.xlsx");
}
exports.Cognitive = Cognitive;
async function Rekognition() {
let tab = [];
const path = "./csv/Rekognition.csv";
for (let i = 0; i < arrayOfFiles.length; i++) {
let x = await rekognitionFile.callaws(arrayOfFiles[i]);
tab.push(x)
}
setWorkSheet("Rekognition", tab, "./excel/Wyniki.xlsx");
}
exports.Rekognition = Rekognition;
async function Vision() {
let tab = [];
for (let i = 0; i < arrayOfFiles.length; i++) {
let x = await vision.callVision(arrayOfFiles[i]);
tab.push(x)
}
setWorkSheet("Vision", tab, "./excel/Wyniki.xlsx");
}
exports.Vision = Vision;
When I execute one of this async function. File with worksheet always is overwritten.
However, I need to add sheets to one file (3 sheets). Anyone have some ideas about this problem ? Thank you