Multi-user login webpage with time recorder using JS - javascript

I have been working on a personal project of user check In/Out time recorder. I created the multi user login and time recorder using JS. I faced an issue to record the time of each logged in user. The code I created is only able to record the time of single user. I used localStorage command to store time because it need to be displayed every users time data on admin page. I am using single JS file for login, user page recorder and also for admin page loader. Plz help me out if anyone has any solution. I can't use server based code right now. I only have to write this web-app code in html,css and javascript.
var users= [
{user : 'user1', pass: 'pass1'},
{user : 'user2', pass: 'pass2'},
{user : 'user3', pass: 'pass3'},
{user : 'admin', pass: 'admin'}
];
function login()
{
//login page
var username = document.getElementById('uname').value;
var password = document.getElementById('psw').value;
for (var i = 0; i < users.length; i++)
{
console.log('enter the loop');
console.log("current user: ", i+1);
if (username == users[i].user && password == users[i].pass)
{
window.location.href = 'user.html';
alert("Login Successful");
break;
}
else if (i == (users.length-1))
{
alert('Login failed! Try Again');
console.log(i,'-times wrong');
}
else if (username == users[3].user && password == users[3].pass)
{
console.log('admin login');
window.location.href = 'admin.html';
break;
}
else
{
console.log('else statement');
}
}
var userId = i;
console.log("current user: ", userId);
}
//Date & Time Display
setInterval(myTimer,1000);
function myTimer()
{
const d = new Date();
document.getElementById('date').innerHTML = d.toLocaleDateString();
document.getElementById('time').innerHTML = d.toLocaleTimeString();
}
let date = document.getElementById('date');
let time = document.getElementById('time');
let newDate = new Date();
let year = newDate.getFullYear();
let month = newDate.getMonth();
let todaysDate = newDate.getDate();
let hours = newDate.getHours();
let minutes = newDate.getMinutes();
let seconds = newDate.getSeconds();
var cal = {
data : null,
sMth : 0,
sYear : 0,
init : () => {
let newDate = new Date();
cal.sDay = newDate.getDate();
cal.sMth = newDate.getMonth();
cal.hour = newDate.getHours();
cal.minutes = newDate.getMinutes();
cal.date = document.getElementById('date');
cal.data = localStorage.getItem("cal-" + cal.sDay + "-" + cal.sMth);
if (cal.data == null)
{
localStorage.setItem("cal-" + cal.sDay + "-" + cal.sMth, "{}");
cal.data = {};
console.log("cal.data: null-",cal.data);
}
else
{
cal.data = JSON.parse(cal.data);
console.log("cal.data: JSON-",cal.data);
}
},
checkIn : () => {
cal.data[cal.sDay] = cal.hour + ":" + cal.minutes;
localStorage.setItem('cal-${cal.sDay}-${cal.sMth}',JSON.stringify(cal.data));
console.log('Time:', cal.data);
}
}
window.onload = cal.init;

Related

Creating a Reminder Discord Bot (Discord.js)

I am writing my first Discord bot and I am fairly new to JavaScript, especially dealing with libraries such as Discord.JS. My project here is a Reminder Discord bot, which takes a user input by prefix, stores and checks data based on time, then outputs a user inputted message when the user time set is the same as current time (to alert).
My current issue is that I don't know how to send a message to a discord channel using the client outside of the two specificed scopes. Ideally, I'd like to send a message between
if (userTime === machineTime) {
console.log("Reminder!");
clearInterval();
}
Thank you
const { Client, GatewayIntentBits, EmbedBuilder, PermissionsBitField, Permissions } = require(`discord.js`);
const { type } = require("os");
const prefix = '!';
const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent] });
var machineTime = null;
var userTime = null;
// Discord Client Ready Check
client.on("ready", () => {
console.log("Bot is online!")
})
// Message Listener
client.on("messageCreate", (message) => {
if (message.author.bot) return;
//Split input into array & get current date
var content = message.content.split(" ");
console.log(content);
// Output
if (content[0] === prefix + 'set-reminder'){
//Start timer
setInterval(checkTime, 1000);
//Convert user time
var inputTime = content[2].split(':');
var inputDate = content[1].split('/');
//Change store metrics and format date
var convertMinutes = parseInt(inputTime[1]);
var convertHours = parseInt(inputTime[0]);
var convertMonth = parseInt(inputDate[0]);
var convertDay = parseInt(inputDate[1]);
var formatDate = convertMonth + "/" + convertDay + "/" + inputDate[2];
//If PM add 12 hours to time input
if (content[3].toLowerCase() === "pm") {
convertHours += 12;
}
userTime = formatDate + " " + convertHours + " " + convertMinutes;
//Send reminder confirmation
message.channel.send("Members will be alerted at " + content[1] + ":white_check_mark:");
}
// Input Array: 0 = prefix, 1 = date, 2 = time, 3 = am/pm, 4 = channel, 5 = message
})
//Current Time Check
const checkTime = () => {
var machineOutput = new Date();
var machineDate = machineOutput.toLocaleDateString();
var machineMinutes = machineOutput.getMinutes();
var machineHours = machineOutput.getHours();
machineTime = machineDate + " " + machineHours + " " + machineMinutes;
if (userTime === machineTime) {
console.log("Reminder!");
clearInterval();
}
console.log(machineTime);
}
client.login("MY_LOGIN_KEY");```
As long as you have access to the client, you can send a message to any channel.
if (userTime === machineTime) {
console.log("Reminder!");
clearInterval();
const channel = await client.channels.fetch('channel id');
channel.send('...');
}

disable button while retrieving data from local storage and updating the date input

I am trying to implement a function that checks if the date and time I choose have already been chosen before, if so, it gives an error, if not it lets me carry on with adding the ticket. The current function does save options to local storage, however it looks like it doesn't retrieve them for me and allows me to choose the same date twice.
var count = 0;
function store() {
let clickCounter = localStorage.getItem("clickCount");
if (!clickCounter) {
localStorage.setItem("clickCount", 0);
clickCounter = "0";
}
clickCounter = parseInt(clickCounter);
document.getElementById('inc').value = ++count;
if (clickCounter == 100) {
console.log("Limit reached");
return;
} else {
localStorage.setItem("clickCount", clickCounter + 1);
}
console.log("Saving");
var e = document.getElementById("time");
var time = e.options[e.selectedIndex].text;
var date = document.querySelector("input").value;
localStorage.setItem(JSON.stringify(time), date);
console.log(localStorage);
if (!localStorage.getItem("history")) {
localStorage.setItem("history", "[]");
}
const history = JSON.parse(localStorage.getItem("history"));
history.push({ [JSON.stringify(time)]: date });
localStorage.setItem("history", JSON.stringify(history));
console.log(localStorage.getItem("history"));
}
function myDate(date) {
var today = new Date();
var newDate = new Date(date);
var nextWeek = new Date();
var pastWeek = new Date();
nextWeek.setDate(nextWeek.getDate() + 7);
pastWeek.setDate(pastWeek.getDate() - 7);
const dateInput = document.getElementById('date');
if (newDate < pastWeek || newDate > nextWeek) {
document.getElementById("time").disabled = true;
console.log("error")
return;
} else {
document.getElementById("time").disabled = false;
}
}

Updating multiple Firebase nodes from multiple Google Calendar inserts with a callback functions inside a loop

this is my first post on Stack, and I am new to creating web apps. I've done some searching and I think my issue has to do closures/forEach/let...
Found here - JavaScript closure inside loops – simple practical example
But I am struggling on incorporating that into my app and need some help please.
I am using Firebase Realtime DB where I am pushing some data and pulling the uID of that push, then I use that same data to create a Google Calendar entry. I then retrieve that eventID from Calendar and then update the corresponding database node. So this works when I create a single entry at a time. What I then did, was I added the option to send multiple entries at once (this depends on a datetime-local input). So I have put these multiple datetimes into an array and they send correctly to Firebase and to Calendar, but where my bug is, is that only the last Calendar eventID is being updated in Firebase. It seems that the for loop over the array of date runs through before calendar can get the eventID and update Firebase. This was seen due to only my last date in the array having the associated calendar eventID. So yeah I think the issue is the global variable newPushId, but I am not sure at the moment how to fix it. All this is new and struggling to understand.
Sorry it's long, I would rather leave my code in there in case someone has any tips. If people would prefer me to shorten it, I will. Thank you in advance for the assistance.
Here's my main function that runs on submit.
function sendInstantBook() {
// checkBookForm listed in services
if (checkInstantBookForm()) {
// Get variables from the form.
var address = $('#instant-book-change-address').val();
var instructor = $("#instant-book-instructor").children(":selected").attr("id");
var transmission = $("#instant-book-transmission").children(":selected").attr("id");
var duration = $("#instant-book-duration").children(":selected").attr("id");
var start0 = $('#instant-book-start0').val();
var multipleLessons;
if (getLessonTimes() !== false) {
multipleLessons = getLessonTimes();
}
multipleLessons = multipleLessons.split(',');
// var recurring, interval, frequency, count;
// if ($('#recurring-checkbox').is(":checked")) {
// recurring = true;
// interval = $('#instant-recurring-interval').val();
// frequency = $("#instant-recurring-freq").children(":selected").attr("id");
// count = $('#instant-recurring-count').val();
// } else {
// recurring = false;
// interval = false;
// frequency = false;
// count = false;
// }
var sortAsc = new Date(start0).getTime();
// var sortDes = 9999999999999 - sortAsc;
var date0 = start0.split('T')[0];
var timeStart0 = start0.split('T')[1];
var timeFinish0 = addTimes(timeStart0, duration);
var paymentType = $('input[name="instantPayment"]:checked').val();
var paid = $('input[name="instantPaymentCheck"]:checked').val();
var paymentNumber = getPaymentNumber(paymentType);
var paymentDate = getPaymentDate(paid, date0);
var email = adminStudentDetails.email;
var phoneNumber = adminStudentDetails.phoneNumber;
phoneNumber = phoneNumber.replace(/\s/g, "");
var firstName = adminStudentDetails.firstName;
var lastName = adminStudentDetails.lastName;
var studentName = firstName + ' ' + lastName;
var amount = getAmount(duration);
var tracking = getTracking(duration);
if (multipleLessons.length == 1) {
// Create JSON object With the request's details and push to server
var data = {
"address" : address,
"amount" : amount,
"booked" : true,
"calID" : false,
"cancelled" : false,
"date" : date0,
"dateSortAsc" : sortAsc,
// "dateSortDes" : sortDes,
"duration" : duration,
"email" : email,
"firstName" : firstName,
"instructor" : instructor,
"lastName" : lastName,
// "newStudent" : newStudent,
"paymentDate" : paymentDate,
"paymentType" : paymentType,
"paymentNumber" : paymentNumber,
"phoneNumber" : phoneNumber,
"prepaid" : paid,
// "recurring" : recurring,
"studentName": studentName,
"time": timeStart0 + ' - ' + timeFinish0,
"tracking": tracking,
"transmission" : transmission,
"type" : "Lesson",
};
// var recurringData = {
// "interval" : interval,
// "frequency" : frequency,
// "count" : count,
// };
// push data to firebase
dbrefLessons.push(data).then((snap) => {
newPushUid = snap.key;
// this is a global variable
});
insertCalEvent(data, updCalIdCallback);
showSnackbar();
}
else if (multipleLessons.length > 1) {
for (var i = 0; i < multipleLessons.length; i++) {
eachDate = multipleLessons[i].split('T')[0];
eachDateSortAsc = new Date(i).getTime();
eachStart = multipleLessons[i].split('T')[1];
eachFinish = addTimes(eachStart, duration);
// Create JSON object With the request's details and push to server
var dataMultiple = {
"address" : address,
"amount" : amount,
"booked" : true,
"calID" : false,
"cancelled" : false,
"date" : eachDate,
"dateSortAsc" : eachDateSortAsc,
// "dateSortDes" : sortDes,
"duration" : duration,
"email" : email,
"firstName" : firstName,
"instructor" : instructor,
"lastName" : lastName,
// "newStudent" : newStudent,
"paymentDate" : paymentDate,
"paymentType" : paymentType,
"paymentNumber" : paymentNumber,
"phoneNumber" : phoneNumber,
"prepaid" : paid,
"studentName": studentName,
"time": eachStart + ' - ' + eachFinish,
"tracking": tracking,
"transmission" : transmission,
"type" : "Lesson",
};
// push data to firebase
dbrefLessons.push(dataMultiple).then((snap) => {
newPushUid = snap.key;
});
// push to calendar
insertCalEvent(dataMultiple, updCalIdCallback);
}
}
showSnackbar();
}
}
And the calendar insert code.
function insertCalEvent(linfo, updCalIdCallback) {
// function insertCalEvent(linfo, linfoRecur, updCalIdCallback) {
// THIS WILL NEED TO CHANGE TO LOGGED IN USER RATHER THAN STUDENT DETAILS
// or change it over to organizer
var loggedInFirstName = studentDetails.firstName;
var loggedInLastName = studentDetails.lastName;
var today = new Date().toISOString();
var todayDate = today.split('T')[0];
var todayTime = today.split('T')[1].split('.')[0];
// var interval = linfoRecur.interval;
// var frequency = linfoRecur.frequency;
// var count = linfoRecur.count;
// if (interval == false) {
// interval = 0;
// frequency = 0;
// count = 0;
// }
var address = linfo.address;
var amount = linfo.amount;
var cancelled = linfo.cancelled;
var date = linfo.date;
var duration = linfo.duration;
var email = linfo.email;
var firstName = linfo.firstName;
var lastName = linfo.lastName;
var location;
var newStudent;
var instructor = linfo.instructor;
var paymentType = linfo.paymentType;
var paid = linfo.prepaid;
var transmission = linfo.transmission;
var type = linfo.type;
var phoneNumber = linfo.phoneNumber;
var time = linfo.time;
var time1 = time.split(' - ')[0];
var time2 = time.split(' - ')[1];
if (linfo.location == undefined) {
} else {
location = linfo.location;
}
if (linfo.newStudent == true){
newStudent = "NEW ";
} else if (linfo.newStudent == undefined || linfo.newStudent == false) {
newStudent = "";
}
if (paid == "Yes") {
paid = "PD ";
} else {
paid = "Owes ";
}
if (paymentType == "Instructor") {
paymentType = "Instructor ";
} else if (paymentType == "Office") {
paymentType = "Office ";
} else if (paymentType == "Pack") {
paymentType = "(input pack) ";
}
var event = {
'summary': paid + paymentType + amount + ' - ' + newStudent + transmission + ' ' + type + ' - ' + firstName + ' ' + lastName + ' - ' + address + ' - ' + phoneNumber,
'location': address,
'description': 'Lesson generated by XLR8 app. \nInstructor - ' + instructor + '\nBooked by ' + loggedInFirstName + ' ' + loggedInLastName + ' at ' + todayDate + ' - ' + todayTime + '.\nStudent email - ' + email,
'start': {
'dateTime': date + 'T' + time1 + ':00+10:00',
'timeZone': 'Australia/Brisbane'
},
'end': {
'dateTime': date + 'T' + time2 + ':00+10:00',
'timeZone': 'Australia/Brisbane'
},
// 'attendees': [
// {'email': 'simon.curran.89#gmail.com'},
// ],
'reminders': {
'useDefault': false,
'overrides': [
{'method': 'popup', 'minutes': 30}
]
},
// "recurrence": [
// "RRULE:FREQ="+ frequency + ";COUNT=" + count + ";INTERVAL=" + interval + ";"
// ],
// 'originalStartTime': date + 'T' + time1 + ':00+10:00',
// 'recurringEventId': 'recurringEventId',
// 'colourId': 10,
};
gapi.client.load('calendar', 'v3', function() {
var request = gapi.client.calendar.events.insert({
"calendarId": "primary",
"resource": event
}, function(err, event) {
if (err) {
console.log("There was an error contacting the Calendar service: " + err);
return;
} else {
console.log("Event created: %s", event.htmlLink);
}
});
request.execute(function(resp) {
// console.log(resp);
// var calID = resp.id;
return updCalIdCallback(resp.id);
});
});
}
And the callback function:
function updCalIdCallback(calID) {
var updatedCalID = {
"calID" : calID,
};
dbrefLessons.child(newPushUid).update(updatedCalID);
console.log(calID);
console.log(newPushUid);
newPushUid = '';
}

Instant Chat on Web Application Using Firebase Database JavaScript

In my website I am creating a instant messaging service using Firebase data base. I have got the functionality of the chat working so users can send a message to the chat which will display in the display box.
The problem I'm having is, when a new chat is created and users begin a conversation, the messages appear in order of the conversation they're having as they should As seen below:
but when the page is refreshed and the messages are pulled from the database is displays as follows.
My db structure for the chat is as follows:
And my JS code is for the chat is:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
var db = firebase.database();
var currentProperty = localStorage.getItem("prop");
db.ref('addresses/'+currentProperty+'/chat/group').on("child_added", function(data){
//Set Local Variables
var message = data.child("message").val();
var date = data.child("date").val();
var sender = data.child("uid").val();
var time = data.child("time").val();
var who;
var getCurrentDate = new Date;
day = getCurrentDate.getDate();
month = getCurrentDate.getMonth() + 1;
year = getCurrentDate.getFullYear();
var newDate = [day, month, year].join('/');
var title = document.getElementById("chatTitle");
db.ref('addresses/'+currentProperty+'/firstLine').once("value", function(snapshot){
title.innerHTML = "<i class='fas fa-home' style='font-size:150%;margin-right:10px'></i>Group chat with all persons involved with " + capitalLetter(snapshot.val());
});
if(sender == user.uid){who = 'boxCurrent currentUser';}
else
{who = 'boxOther otherUser';}
if(date == newDate){date = 'Today'}
db.ref('users/'+sender+'/firstName').on('value', function(data){
var name = data.val();
if(who == 'boxCurrent currentUser'){
var messageD = "<div id='userMessageDisplay' style='width:100%;text-align:end;'><span class='message-data-time'>"+time+", "+date+" </span><span id='userName'>"+name+"</span><div id='hello' class='"+who+"' style= height:100%;'>"+message+"</div></div>";
$('#displayBox').append(messageD);
}
else{
var messageD = "<div id='userMessageDisplay' style='width:100%;'><span class='message-name'>"+name+"</span><span class='message-data-time'> "+time+", "+date+"</span><div id='hello' class='"+who+"' style='width:70%; height:100%;'>"+message+"</div></div>";
$('#displayBox').append(messageD);
}
});
});
db.ref('addresses/'+currentProperty+'/tenant').orderByKey().once("value", function(snapshot){
snapshot.forEach(function(child){
var key = child.key;
console.log(key);
db.ref('users/'+key+'/firstName').once("value", function(data){
var first = data.val();
var appendFirst = "<li style='padding: 5px 10px 0 10px; height:75px;'><i class='fas fa-user-circle' style='font-size:400%; float:left;color:#6a6c75;'></i><div class='about' style='height:100%;padding: 10px 0 0 70px;'><div id='append2"+key+"' class='profileName' style='color:#fff;'>"+first;
$('#peopleList').append(appendFirst);
});
db.ref('users/'+key+'/lastName').once("value", function(data){
var last = data.val();
var appendLast = " "+last+"</div>"
$('#append2'+key).append(appendLast);
});
db.ref('users/'+key+'/onlineStatus').once("value", function(data){
var onlineStatus = data.val();
console.log(onlineStatus);
if(onlineStatus == 'Online'){
var appendStatus = "<div class='status' style='color:#a8aac3;'><i class='fa fa-circle' online style='color:#86BB71; margin-right:10px;font-size:80%;border:1px solid #fff;border-radius:50%;'></i>Online</div></div></li>"
$('#append2'+key).append(appendStatus);
}
else{
appendStatus = "<div class='status' style='color:#a8aac3;'><i class='fa fa-circle offline' style='color:#E38968;margin-right:10px;font-size:80%;border:1px solid #fff;border-radius:50%;'></i>Offline</div></div></li>"
$('#append2'+key).append(appendStatus);
}
});
});
});
} else {
// No user is signed in.
location = 'index.html'
}
});
function sendMessage(){
var theDiv = document.getElementById('displayBox');
var message = document.getElementById("messageInput").value;
var currentProperty = localStorage.getItem("prop");
var user = firebase.auth().currentUser;
//date
var date = new Date;
day = date.getDate();
month = date.getMonth() + 1;
year = date.getFullYear();
var newDate = [day, month, year].join('/');
var db = firebase.database();
//time
hours = date.getHours(); // => 9
mins = date.getMinutes(); // => 30
var time = [hours, mins].join(':');
console.log(time);
var messageDetails = {
"uid": user.uid,
"message": message,
"date": newDate,
"time": time
}
if(message == ''){
document.getElementById("messageInput").style.border = '1px solid red';
}
else{
db.ref('addresses/'+currentProperty+'/chat/group').push(messageDetails).then(function(){
document.getElementById("messageInput").value = '';
theDiv.scrollTop = '99999';
});
}
}
Apologies for the long post but does anyone know why when the page is refreshed, the messages are clustered buy the user who sent the message?
Also any solutions to resolved the problem will be extremely helpful.
Thanks in advance.
I would recommend changing the way you store your message timestamps. I would store them as firebase timestamps like this: https://firebase.google.com/docs/reference/js/firebase.database.ServerValue
and then when you pull them, you want to use orderByChild and then startAt from the retrieve data information found here: https://firebase.google.com/docs/database/admin/retrieve-data
This will then order the messages based on their timestamp instead of their keys.

Stop iterating and return true when a match is found between two arrays

I have two datasets, one in indexedDB and one in PouchDB (yes I know PouchDB is an implementation of indexedDB).
The one in indexedDB is a list of rooms, stored in indexedDB via a previous page, and displayed on the current page.
The one in PouchDB is the log of room usage recorded by a room auditor. I want to iterate through the first list, and check if each item appears in the list of audited rooms. If it does appear, I want to set a flag to indicate that.
Here's my Javascript. (I have run this in a browser and it does return true at some point in the process, because the console log output shows that, but the flag doesn't get set against the list item.)
I am wondering if it continues to loop through the audit records and overwrites the "true" value?
this is the function that queries indexedDB and calls the function that queries PouchDB:
function getRoomsInRoute() {
var routeNumber = $.jStorage.get('currentRoute', '');
var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB;
openRequest = window.indexedDB.open("rooms", 1);
openRequest.onupgradeneeded = function() {
var db = openRequest.result;
var itemStore = db.createObjectStore("rooms", {keyPath: "room_id"});
var index = itemStore.createIndex("rooms", ["route_number"]);
};
openRequest.onerror = function(event) {
console.error(event);
};
openRequest.onsuccess = function (event) {
var db = openRequest.result;
db.onerror = function(event) {
// Generic error handler for all errors targeted at this database's requests
console.error(event.target);
console.log("Database error: " + event.target.error.name || event.target.error || event.target.errorCode);
};
var transaction = db.transaction(['rooms'], "readwrite");
var itemStore = transaction.objectStore("rooms");
var index = itemStore.index("rooms", ["route_number"]);
console.log('DB opened');
var intRouteNumber = parseInt(routeNumber);
//var range = IDBKeyRange.only(intRouteNumber);
itemStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
if(cursor) {
var audited;
if(cursor.value.route_number == routeNumber) {
if (checkIfAudited(cursor.value.room_seq)) {
var audited = ' <span class="checked"><i class="fa fa-check"></i></span>';
} else {
var audited = "";
}
$('#mylist').append("<li id="+ cursor.value.room_id +" rel="+ cursor.value.room_seq +"> " + '<small>'+ cursor.value.room_seq + '. </small>' + cursor.value.room_name + ''+audited+'</li> ');
}
cursor.continue();
} else {
console.log('Entries all displayed.');
if(!($.jStorage.get('reverseroute', ''))) {
reverseroute = 'asc';
} else {
reverseroute = $.jStorage.get('reverseroute', '');
}
appendHref(reverseroute);
}
};
// Close the db when the transaction is done
transaction.oncomplete = function() {
db.close();
};
};
}
and this is the function that queries PouchDB to see if it has been audited:
function checkIfAudited(roomseq) {
var today = new Date();
if(is_BST(today) == true) {
var currentHour = today.getHours()+1;
} else {
var currentHour = today.getHours();
}
var currentDay = today.getDate();
var currentMonth = today.getMonth();
options = {},
that = this,
pdb = new PouchDB('pouchroomusage');
options.include_docs = true;
var pouchOpts = {
skipSetup: true
};
var opts = {live: true};
pdb.allDocs(options, function (error, response) {
response.rows.some(function(row){
var auditTime = new Date(row.doc.timestamp);
var auditHour = auditTime.getUTCHours();
var auditDay = auditTime.getDate();
var auditMonth = auditTime.getMonth();
if(row.doc.sequence == roomseq && currentHour == auditHour && currentDay == auditDay && currentMonth == auditMonth) {
var isAudited = true;
console.log('RoomSeq: ' + roomseq + '; auditHour: ' + auditHour + '; currentHour: ' + currentHour + '; auditDay: ' + auditDay);
console.log('currentDay: ' + currentDay + '; auditMonth: ' + auditMonth + '; currentMonth: ' + currentMonth + '; isAudited: ' + isAudited);
} else {
var isAudited = false;
console.log('No matches');
}
return isAudited;
});
});
}
I have read a number of other questions and answers about comparing two arrays.
I don't know how to use a for loop with pdb.allDocs though :(
Here is the output from console.log:
49 No matches
RoomSeq: 1; auditHour: 14; currentHour: 14; auditDay: 16
currentDay: 16; auditMonth: 0; currentMonth: 0; isAudited: true
2300 No matches
So how do I get the second function to stop and return true when it hits a matching record in PouchDB?
First, I wouldn't get too fancy with exploiting the short-circuiting behavior of Array.prototype.some. Use the native functionality available to you. indexedDB provides a built in way to stop advancing a cursor, or load only a limited number of objects from a store.
Second, you probably want to avoid loading all objects from a store when you are only interested a in a few of those objects. Use a cursor to walk the store. Since you appear to want to stop iterating when meeting some condition, simply do not call cursor.continue at that point.
Third, is that even if decide to load all objects from the store first, it would be far better to use a for loop than exploit some. By exploit I mean use the function in a way other than it was intended. I bet that if you revert to using a for loop with a break statement, the code will be clearer and therefore it will be simpler to understand why the loop does not break when you expect it to do so.
Fourth, is that I would take the time to append results of an indexedDB query to an intermediate data structure, like an array, rather than immediately interacting with the DOM. It will separate things more, and you will find the code simpler to debug.
Fifth is that you should be very careful when mixing async calls together with indexedDB. indexedDB is known to have problems when you interleave calls to other promises.
It seems to me that the pouchdb method alldocs is asynchronous.
But you test audition in a synchronous way. Therefore whatever the pdb.alldocs callback function returns will be returned after the checkIfAudited is already returned. Therefore checkIfAudited always returns undefined.
In my opinion, you should create the pouchdb instance only once in temStore.openCursor().onsuccess. Then you need to properly return audit state in checkIfAudited function.
For example, you could do something like the following:
itemStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
if (cursor.value.route_number == routeNumber) {
var audited;
options = {},
pdb = new PouchDB('pouchroomusage');
options.include_docs = true;
pdb.allDocs(options, function (error, allDocsResponse) {
if (checkIfAudited(allDocsResponse, cursor.value.room_seq)) audited = ' <span class="checked"><i class="fa fa-check"></i></span>'
else audited = "";
$('#mylist').append("<li id="+ cursor.value.room_id +" rel="+ cursor.value.room_seq +"> " + '<small>'+ cursor.value.room_seq + '. </small>' + cursor.value.room_name + ''+audited+'</li> ');
});
};
cursor.continue();
} else {
console.log('Entries all displayed.');
if(!($.jStorage.get('reverseroute', ''))) reverseroute = 'asc'
else reverseroute = $.jStorage.get('reverseroute', '');
appendHref(reverseroute);
};
};
And for checkIfAudited:
function checkIfAudited(allDocs, roomseq) {
var today = new Date();
if(is_BST(today) == true) {
var currentHour = today.getHours()+1;
} else {
var currentHour = today.getHours();
}
var currentDay = today.getDate();
var currentMonth = today.getMonth();
for (i=0; i<allDocs.rows.length; i++) {
var row = allDocs.rows[i];
var auditTime = new Date(row.doc.timestamp);
var auditHour = auditTime.getUTCHours();
var auditDay = auditTime.getDate();
var auditMonth = auditTime.getMonth();
if(row.doc.sequence == roomseq && currentHour == auditHour && currentDay == auditDay && currentMonth == auditMonth) {
console.log('RoomSeq: ' + roomseq + '; auditHour: ' + auditHour + '; currentHour: ' + currentHour + '; auditDay: ' + auditDay);
console.log('currentDay: ' + currentDay + '; auditMonth: ' + auditMonth + '; currentMonth: ' + currentMonth + '; isAudited: ' + isAudited);
return true; ///// <---- return that it is audited
} else {
console.log('No matches');
};
});
return false ///// <---- return false if no iteration has matched
}
This is what I ended up with after much tweaking.
Now it adds <span class="checked"><i class="fa fa-check"></i></span> more than once per <li> but at least it adds to every <li>.
So I did a little hack to the CSS to only display one span.checked:
.checked {
color: #fff;
background-color: #006338;
border-radius: 50%;
padding: 2px 3px;
}
/* only display the first instance of checked */
li > span.checked ~ .checked {
display: none;
}
(I also found and fixed another error in my script, where I wasn't setting route_number or room_id.)
function getRoomsInRoute() {
var routeNumber = $.jStorage.get('currentRoute', '');
var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB;
openRequest = window.indexedDB.open("rooms", 1);
openRequest.onupgradeneeded = function() {
var db = openRequest.result;
var itemStore = db.createObjectStore("rooms", {keyPath: "room_id"});
var index = itemStore.createIndex("rooms", ["route_number"]);
};
openRequest.onerror = function(event) {
console.error(event);
};
openRequest.onsuccess = function (event) {
var db = openRequest.result;
db.onerror = function(event) {
// Generic error handler for all errors targeted at this database's requests
console.error(event.target);
console.log("Database error: " + event.target.error.name || event.target.error || event.target.errorCode);
};
var transaction = db.transaction(['rooms'], "readwrite");
var itemStore = transaction.objectStore("rooms");
var index = itemStore.index("rooms", ["route_number"]);
console.log('DB opened');
var intRouteNumber = parseInt(routeNumber);
//var range = IDBKeyRange.only(intRouteNumber);
itemStore.openCursor().onsuccess = function(event) {
var cursor = event.target.result;
var audited = "";
if(cursor) {
if(cursor.value.route_number == routeNumber) {
$('#mylist').append("<li id="+ cursor.value.room_id +" rel="+ cursor.value.room_seq +"> " + '<small>'+ cursor.value.room_seq + '. </small>' + cursor.value.room_name + '</li> ');
}
cursor.continue();
} else {
console.log('Entries all displayed.');
if(!($.jStorage.get('reverseroute', ''))) {
reverseroute = 'asc';
} else {
reverseroute = $.jStorage.get('reverseroute', '');
}
appendHref(reverseroute);
asyncCallToPouchDb();
}
};
// Close the db when the transaction is done
transaction.oncomplete = function() {
db.close();
};
};
}
function asyncCallToPouchDb() {
$('#mylist li').each(function(){
var audited = "";
var room_id = $(this).attr('id');
var thisLi = $(this);
audited = callPouchDb(room_id, thisLi);
});
}
function callPouchDb(room_id, thisLi) {
options = {},
pdb = new PouchDB('pouchroomusage');
options.include_docs = true;
var audited = "";
//return new Promise(resolve => {
pdb.allDocs(options, function (error, response) {
result = response.rows;
for (i = 0; i < result.length; i++) {
if (checkIfAudited(result[i], room_id)) {
audited = ' <span class="checked"><i class="fa fa-check"></i></span>';
}
thisLi.append(audited);
}
//thisLi.append(audited);
/*end pdb.allDocs*/
}).then(function (result) {
// handle result
console.log(result);
}).catch(function (err) {
console.log(err);
});
// });
}
function checkIfAudited(row, room_id) {
var today = new Date();
if(is_BST(today) == true) {
var currentHour = today.getHours()+1;
} else {
var currentHour = today.getHours();
}
var currentDay = today.getDate();
var currentMonth = today.getMonth();
var currentYear = today.getYear();
var isAudited = false; ///// <---- define isAudited outside of db iteration scope
var auditTime = new Date(row.doc.timestamp);
var auditHour = auditTime.getUTCHours();
var auditDay = auditTime.getDate();
var auditMonth = auditTime.getMonth();
var auditYear = auditTime.getYear();
if(row.doc.room_id == room_id && currentHour == auditHour && currentDay == auditDay && currentMonth == auditMonth && currentYear == auditYear) {
isAudited = true;
// debug
// console.log('RoomSeq: ' + roomseq + '; auditHour: ' + auditHour + '; currentHour: ' + currentHour + '; auditDay: ' + auditDay);
// console.log('currentDay: ' + currentDay + '; auditMonth: ' + auditMonth + '; currentMonth: ' + currentMonth + '; isAudited: ' + isAudited);
} else {
console.log('No matches');
};
return isAudited
}

Categories