Long time browser, first time questioner.
So for an in and out board I need employees to click the "out button" and with a Vue.js v-on:click() next to it I want to to display "Out at 3:55pm".
Here is the button -
<button class="btn btn-smaller btn-out" v-show="user.in" v-on:click="updateOut(user)">out</button>
Which in turn updates the usersRef timeOut status in the Firebase DB like this -
updateOut: function (user) {usersRef.child(user['.key']).child('in').set(false)
usersRef.child(user['.key']).child('timeOut').set(Date())
},
Which updates this with the actual date stamp -
{{ user.timeOut }}
The problem I am getting is that I can not format this inside the updateOut function to simply show "out at 3:55pm". I can only get it to show "Wed Mar 29 2017 10:55:02 GMT-0600 (MDT)"
Srinivas - I can't get this to work. I tried this -
methods: {
addUser: function () {
if (this.newUserName) {
usersRef.push({
name: this.newUserName,
in: false,
returnTime: ''
})
this.newUserName = ''
},
},
getTime: function(user) {
const outTime = new Date(this.user.timeOut)
const hours = outTime.getHours()
let minutes = outTime.getMinutes()
if (minutes < 10) minutes = "0" + minutes // prepend 0
return (hours + ":" + minutes)
},
updateReturnTime: function (user, newText) {
usersRef.child(user['.key']).child('returnTime').set(newText)
},
updateIn: function (user) {
usersRef.child(user['.key']).child('in').set(true)
usersRef.child(user['.key']).child('timeOut').set('')
},
updateOut: function (user) {
usersRef.child(user['.key']).child('in').set(false)
usersRef.child(user['.key']).child('timeOut').set(Date.now())
},
You can create a method to convert date into required format.
methods: {
getTime() {
const outTime = new Date(this.user.timeOut)
const hours = outTime.getHours()
let minutes = outTime.getMinutes()
if (minutes < 10) minutes = "0" + minutes // prepend 0
return (hours + ":" + minutes)
}
}
If you are using this method in multiple places, you can create a filter.
Vue.filter('getTime', function(date) {
const outTime = new Date(date)
const hours = outTime.getHours()
let minutes = outTime.getMinutes()
if (minutes < 10) minutes = "0" + minutes // prepend 0
return (hours + ":" + minutes)
})
You can use it template like this.
{{ user.timeOut | getTime }}
Related
So bootstrap datepicker return blank date if I click the same date again. However, how I know which date is again clicked by the user?
For example in below calendar, I clicked on 24th of April. Then changeDate event will return me below the array. Which is fine for me:
So anyone has any idea on how to know which date is again clicked by the user? Like how I can detect that the user is reclicked on the 24th?
My code:
Init of datepicker:
var DatePicker = {
hideOldDays: function(){ // hide days for previous month
var x = $('.datepicker .datepicker-days tr td.old');
if(x.length > 0){
x.css('visibility', 'hidden');
if(x.length === 7){
x.parent().hide();
}
}
},
hideNewDays: function(){ // hide days for next month
var x = $('.datepicker .datepicker-days tr td.new');
if(x.length > 0){
x.hide();
}
},
hideOtherMonthDays: function(){ // hide days not for current month
DatePicker.hideOldDays();
DatePicker.hideNewDays();
}
};
var arrows;
if (KTUtil.isRTL()) {
arrows = {
leftArrow: '<i class="la la-angle-right"></i>',
rightArrow: '<i class="la la-angle-left"></i>'
}
} else {
arrows = {
leftArrow: '<i class="la la-angle-left"></i>',
rightArrow: '<i class="la la-angle-right"></i>'
}
}
var date = new Date();
var active_dates_1 = ['13/3/2020','14/3/2020','15/3/2020','16/3/2020','17/3/2020','18/3/2020','20/3/2020','21/3/2020','22/3/2020','23/3/2020','24/3/2020','25/3/2020','26/3/2020','27/3/2020','28/3/2020','29/3/2020','30/3/2020','31/3/2020','2/4/2020','3/4/2020','5/4/2020','16/4/2020','17/4/2020',];
var active_dates_2 = ['1/4/2020','6/4/2020','7/4/2020','8/4/2020','9/4/2020','10/4/2020','11/4/2020','12/4/2020','15/4/2020','20/4/2020',];
var active_dates_3 = ['4/4/2020','13/4/2020','14/4/2020','24/4/2020','24/4/2020',];
date.setDate(date.getDate()+1);
$('#manage_datepicker_1').datepicker({
rtl: KTUtil.isRTL(),
todayHighlight: true,
templates: arrows,
startDate: date, //disable all old dates
setDate: date, //tomorrow's date allowed
multidate: true,
format: 'dd/mm/yyyy',
endDate: "25/04/2020",
beforeShowDay: function(date){
var d = date;
var curr_date = d.getDate();
var curr_month = d.getMonth() + 1; //Months are zero based
var curr_year = d.getFullYear();
var formattedDate = curr_date + "/" + curr_month + "/" + curr_year
if ($.inArray(formattedDate, active_dates_1) != -1){
return {
classes: 'disabled bookedDates1'
};
}
if ($.inArray(formattedDate, active_dates_2) != -1){
return {
classes: 'disabled bookedDates2'
};
}
if ($.inArray(formattedDate, active_dates_3) != -1){
return {
classes: 'disabled bookedDates3'
};
}
return;
}
//maxDate: '28/12/2019'
});
$('#manage_datepicker_1').datepicker().on('show', function(event) {
DatePicker.hideOtherMonthDays(); //hide other months days from current month view.
}).on('changeDate', function(event) {
var storage = new Array();
console.log(event);
for (var i = 0; i < event.dates.length; i++) {
var formatted_date = moment(event.dates[i]).format('DD/MM/YYYY');
storage.push(formatted_date);
}
});
I think that having the clicked date is a reasonable requirement, that worth introducing a change into the source code of bootstrap-datepicker.
So, assuming you're using the minified version, there's a part that goes (ctrl+f for element.trigger):
this.element.trigger({
type: b,
date: e,
viewMode: this.viewMode,
dates: a.map(this.dates, this._utc_to_local),
...
})
Just add a clickedDate property:
this.element.trigger({
type: b,
date: e,
clickedDate: this.viewDate, // <-- added
viewMode: this.viewMode,
dates: a.map(this.dates, this._utc_to_local),
...
})
So that now, inside your changeDate handler, you could access event.dates as well as event.clickedDate.
I am trying to schedule 7 different notification on a daily basis with the following code.
const interval = 1440;
for (let i = 0; i < 7; i++) {
const notification = new firebase.notifications.Notification()
.setNotificationId(notifyId + i.toString())
.setTitle('Quote of the Day')
.setBody('today is a beautiful day')
.setData({
dailyQuote:'today is a beautiful day'
});
const date = new Date();
date.setMinutes(date.getMinutes() + (i * interval));
const schedule = {
fireDate: date.getTime(),
repeatInterval: 'day',
};
firebase.notifications().scheduleNotification(notification, schedule);
}
However, the notifications fire all at once at the same time even though fireDate is set exactly 1440 minutes (1 day) later.
Can anyone help? Thanks!
Changing the repeatInterval to 'week' did the trick for me.
const schedule = {
fireDate: date.getTime(),
repeatInterval: 'week',
};
I was wondering how to make a simple countdown timer that would countdown on the server, but show how long was left on the client.
Server:
timeToClear.remove({}); //Removes the previous time calls
Meteor.setInterval(function(){ //The Actual Countdown
Messages.insert({
name: "[Server]",
message: "<div class='animated infinite flash'>Attention! Chat will be cleared in 15 seconds!<br>Note: Chat is cleared every 12 hours</div>",
time: moment().format('MMMM Do , h:mm a'),
uid: Messages.find().fetch().length + 1,
email: "Server Function"
});
Meteor.setTimeout(function () {
Messages.remove({});
}, 15000);
}, 28800000);
time = 28000000; //Sets the ammount of time to countdown
uid = 0;
Meteor.setInterval(function(){ //The part that allows the client to see it
console.log(uid);
timeToClear.insert({
time: time,
uid: uid
})
time = time - 1000;
uid = uid + 1;
if(time === 0){
time = 28000000; //Resets time after countdown is complete
uid = 0;
timeToClear.remove({}); //Removes all previous time calls
}
}, 1000)
Client:
Template.countdown.helpers({
timer: function (){
x = timeToClear.find({}, { sort: { uid: -1}}).fetch()[0].time; //Gets the highest (newest) uid, and gets the time from it
var tempTime = moment.duration(x); //Converts it into a nicer format using moment
var hours = tempTime.hours();
var minutes = tempTime.minutes();
var seconds = tempTime.seconds();
return "Time till messages are cleared: " +hours + ":" + minutes + ":" + seconds; //Returns it to helper
}
})
Then simply call the helper on the client in a template called countdown!
I am using the jQuery's full calendar with my sharepoint calendar list. I want to filter the events with multiple checkbox selection. I want to filter the events based on the Rooms Selected in the checkboxes.
For this I am using the following script.
Script :
<link rel="stylesheet" type="text/css" href="http://bisp2013-04:1000/sites/Exercise2/Style%20Library/FullCalendar/fullcalendar.css" />
<link rel="stylesheet" type="text/css" href="http://bisp2013-04:1000/sites/Exercise2/Style%20Library/FullCalendar/jquery-ui-1.8.16.custom.css" />
<script type="text/javascript" src="http://bisp2013-04:1000/sites/Exercise2/Style%20Library/FullCalendar/jquery-2.1.4.js"></script>
<script type="text/javascript" src="http://bisp2013-04:1000/sites/Exercise2/Style%20Library/FullCalendar/jquery-ui-1.8.16.custom.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery.SPServices/0.7.1a/jquery.SPServices-0.7.1a.min.js"></script>
<script type="text/javascript" src="http://bisp2013-04:1000/sites/Exercise2/Style%20Library/FullCalendar/moment.min.js"></script>
<script type="text/javascript" src="http://bisp2013-04:1000/sites/Exercise2/Style%20Library/FullCalendar/fullcalendar.js"></script>
<script type=text/javascript">
</script>
<script type="text/javascript">
// Format UTC dates as local date/time strings.
var rooms = [];
var selectedRooms = [];
var events = [];
var filteredSource = [];
var RoomSelection = [];
var date = new Date();
function closeDialog(result) {
SP.UI.ModalDialog.RefreshPage(result);
}
function formatDateToLocal( date ) {
var dateUTC;
if ( typeof date === "string" ) {
// Convert UTC string to date object
var d = new Date();
var year = date.split('-')[0];
var month = date.split('-')[1] - 1;
var day;
var hour;
var minute;
var second;
day = date.split('-')[2].split('T')[0];
hour = date.split('T')[1].split(':')[0];
minute = date.split('T')[1].split(':')[1].split(':')[0];
second = date.split('T')[1].split(':')[2].split('Z')[0];
dateUTC = new Date( Date.UTC( year, month, day, hour, minute, second ) );
}
else if ( typeof date === "object" ) {
dateUTC = date;
}
else {
alert( "Date is not a valid string or date object." );
}
// Create local date strings from UTC date object
var year = "" + dateUTC.getFullYear();
var month = "" + ( dateUTC.getMonth() + 1 ); // Add 1 to month because months are zero-indexed.
var day = "" + dateUTC.getDate();
var hour = "" + dateUTC.getHours();
var minute = "" + dateUTC.getMinutes();
var second = "" + dateUTC.getSeconds();
// Add leading zeros to single-digit months, days, hours, minutes, and seconds
if ( month.length < 2 ) {
month = "0" + month;
}
if ( day.length < 2 ) {
day = "0" + day;
}
if ( hour.length < 2 ) {
hour = "0" + hour;
}
if ( minute.length < 2 ) {
minute = "0" + minute;
}
if ( second.length < 2 ) {
second = "0" + second;
}
var localDateString = year + "-" + month + "-" + day + "T" + hour + ":" + minute + ":" + second;
return localDateString;
}
$(document).ready( function() {
$().SPServices({
operation: "GetListItems",
async: false,
listName: "Training Rooms",
completefunc: function (xData, Status) {
if(Status == 'success' )
{
$(xData.responseXML).SPFilterNode("z:row").each(function()
{
var value= $(this).attr("ows_ID");
var text = $(this).attr("ows_Title");
var roomColor = $(this).attr("ows_bifctpEventColor")
rooms.push({
title: text,
id: value,
Color: roomColor
});
$("#filterBox").append ( "<input id='chk_" + value + "' type='checkbox' value='" + value + "' style='background:"+roomColor+"' onchange='FilterCalendar(" + value + ",this)'/><label for='chk_" + value + "'>" + text + "</label>" );
});
}
}
});
$( '#calendar' ).fullCalendar({
// Assign buttons to the header of the calendar. See FullCalendar documentation for details.
header: {
left:'prev,next today',
center: 'title',
right: 'month, agendaWeek, agendaDay'
},
dayClick: function (date, jsEvent, view) {
var now = new Date();
if (date.setHours(0,0,0,0) < now.setHours(0,0,0,0))
{
alert('You Can Not add Event on this date');
}
else
{
var siteUrl = window.location.protocol + "//" + window.location.host + _spPageContextInfo.siteServerRelativeUrl;
var myLinksUrl = siteUrl + "/Lists/RoomReservation/NewForm.aspx";
var options = {
url: myLinksUrl,
title: "Room Reservation",
dialogReturnValueCallback: closeDialog
};
SP.SOD.execute('sp.ui.dialog.js', 'SP.UI.ModalDialog.showModalDialog', options);
}
},
defaultView: "month", // Set the default view to month
/*
when user select timeslot this option code will execute.
It has three arguments. Start,end and allDay.
Start means starting time of event.
End means ending time of event.
allDay means if events is for entire day or not.
*/
selectable: true,
selectHelper: true,
select: function(start, end, allDay)
{
if(start < date)
{
// Do whatever you want here.
alert('Cannot select this dates.');
return;
}
var title = prompt('Event Title:');
if (title) {
$( '#calendar' ).fullCalendar('renderEvent', {
title: title,
start: start,
end: end,
allDay: allDay
},
true // make the event "stick"
);
}
$( '#calendar' ).fullCalendar('unselect');
},
editable: true,
// Add events to the calendar.
events: function( start, end, callback ) {
// Create an array to hold the events.
events = [];
// Set the date from which to pull events based on the first visible day in the current calendar view. For a month view, this will usually be several days into the previous month. We can use FullCalendar's built-in getView method along with the formatDate utility function to create a date string in the format that SharePoint requires. It must be in the format YYYY-MM-DDTHH:MM:SSZ. Due to time zone differences, we will omit everything after the day.
var startDate = moment().format($('#calendar').fullCalendar('getView').intervalstart, "u").split("T")[0];
// Get the current view of the calendar (agendaWeek, agendaDay, month, etc.). Then set the camlView to the appropriate value to pass to the web service. This way we will only retrieve events needed by the current view (e.g. the agendaWeek view will only retrieve events during the current week rather than getting all events for the current month).
var calView = $( '#calendar' ).fullCalendar( 'getView' ).title;
var camlView = "";
switch( calView ) {
case "agendaWeek":
camlView = "<Week />";
break;
case "agendaDay":
camlView = "<Week />";
break;
default: // Default to month view
camlView = "<Month />";
}
// Set the camlFields, camlQuery, and camlOptions to the appropriate values to pass to the web service. You can add additional <ViewFields /> or adjust the CAML query if you have some custom columns that you want to filter by or display data from. The values below are the pretty much the minimum you'll want to start from to get it working.
var camlFields = "<ViewFields><FieldRef Name='Title' /><FieldRef Name='EventDate' /><FieldRef Name='EndDate' /><FieldRef Name='Location' /><FieldRef Name='Description' /><FieldRef Name='fRecurrence' /><FieldRef Name='RecurrenceData' /><FieldRef Name='RecurrenceID' /><FieldRef Name='fAllDayEvent' /></ViewFields>";
var camlQuery = "<Query><Where><And><Geq><FieldRef Name='EventDate' /><Value IncludeTimeValue='TRUE' Type='DateTime'>"+moment(start).toISOString()+"</Value></Geq><Leq><FieldRef Name='EndDate' /><Value IncludeTimeValue='TRUE' Type='DateTime'>"+moment(end).toISOString()+"</Value></Leq></And></Where></Query>";
var camlOptions = "<QueryOptions><CalendarDate>" + startDate + "</CalendarDate><RecurrencePatternXMLVersion>v3</RecurrencePatternXMLVersion><ExpandRecurrence>TRUE</ExpandRecurrence><DateInUtc>TRUE</DateInUtc></QueryOptions>";
// Make the web service call to retrieve events.
$().SPServices({
operation: "GetListItems",
async: false,
listName: "Room Reservation", // Change this to the GUID or display name of your calendar. If the calendar is on a different site, you can use the display name with the webURL option (see SPServices.CodePlex.com for more information).
CAMLViewFields: camlFields,
CAMLQuery: camlQuery,
CAMLQueryOptions: camlOptions,
completefunc: function( xData, Status ) {
$( xData.responseXML ).find( "z\\:row, row" ).each( function() {
// Check for all day events
var fADE = $( this ).attr( 'ows_fAllDayEvent' );
var thisADE = false;
var thisStart;
var thisEnd;
if ( typeof fADE !== "undefined" && fADE !== "0" ) {
thisADE = true;
// Get the start and end date/time of the event. FullCalendar will parse date strings in local time automagically, and we don't need to do any local time conversions for all day events, so we can use the UTC date strings from SharePoint without converting them to local time.
var thisStart = $( this ).attr( 'ows_EventDate' );
var thisEnd = $( this ).attr( 'ows_EndDate' );
}
else {
// Get the start and end date/time of the event. FullCalendar will parse date strings in local time automagically, so we need to convert the UTC date strings from SharePoint into local time. The formatDateToLocal() function above will take care of this. See comments in that function for more information.
var thisStart = formatDateToLocal( $( this ).attr( 'ows_EventDate' ) );
var thisEnd = formatDateToLocal( $( this ).attr( 'ows_EndDate' ) );
}
// Get the list item ID and recurrence date if present. This will be used to generate the ID query string parameter to link to the event (or the specific instance of a recurring event). The ID query string parameter must be in the format "ID.0.yyyy-MM-ddTHH:mm:ssZ" for recurring events (where "ID" is the list item ID for the event). Event ID's are returned as just a number (for non-recurring events) or several numbers separated by ";#" in 2007 or "." in 2010 to indicate individual instances of recurring events. By splitting and joining the ID this way, thisID will be set to a valid query string parameter whether an event is recurring or not for both versions of SharePoint.
var thisID = $( this ).attr( 'ows_ID' ).split( ';#' ).join( '.' );
var thisRoom = $(this).attr('ows_bifctpTrainingRoom').split(';#')[0];
// FullCalendar documentation specifies that recurring events should all have the same id value when building the events array (the id is optional, but I'm including it for completeness). We can get the list item ID (which is the same for all instances of recurring events) without the recurrence information by simply splitting thisID.
var eventID = thisID.split( '.' )[0];
// Get the event title. This is displayed on the calendar along with the start time of the event.
var thisTitle = $( this ).attr( 'ows_Title' );
// Get the event description. I don't use it in this example, but you could use it for something, perhaps as a tooltip when hovering over the event.
var thisDesc = $( this ).attr( 'ows_Description' );
// Add the event information to the events array so FullCalendar can display it.
events.push({
title: thisTitle,
id: eventID,
start: thisStart,
end: thisEnd,
allDay: thisADE,
room:thisRoom,
// Adjust this URL to link to the display form for your calendar events. You can include a Source parameter to allow users to easily return to the FullCalendar page.
url: _spPageContextInfo.siteAbsoluteUrl + '/Lists/RoomReservation/DispForm.aspx?ID=' + thisID + '&Source=' + window.location,
description: 'Check Calendar Events'
});
});
callback( events );
}
});
},
eventRender: function eventRender( event, element, view ) {
var isFound = false;
var backgroundColor = "";
for (var roomID in rooms) {
var currentRoom = rooms[roomID];
if (currentRoom.id == event.room) {
backgroundColor = currentRoom.Color;
element.find(".fc-event-time").html(event.start.format("HH:mm") + "-" + event.end.format("HH:mm"));
element.find(".fc-title").parent().attr("title", event.title);
element.css('color','black');
element.find('.fc-event-skin').css('background-color', backgroundColor);
element.css('background-color', backgroundColor);
isFound = true;
break;
}
}
return isFound;
}
});
})
</script>
<style type="text/css">
#calendar
{
width: 900px;
margin: 0 auto;
}
</style>
<div id="filterBox">
</div>
<div id="calendar">
<!-- Calendar will be added here -->
</div><!-- #calendar -->
This is how my screen looks at present:
What i want to do is on change event of the each of the checkbox. I want to filter the calendar events and show events only for the selected rooms.
You need to use event source, so you can split your events in different sources (rooms in your case).
Then, you can easily show / hide your events with add Event Source and remove Event Source.
So your code will be something like:
$('#calendar').fullCalendar({
// put your options and callbacks here
eventSources: [source1, source2]
})
And bound to your checkbox:
$('#calendar').fullCalendar( 'addEventSource', source1 ); //Show it
$('#calendar').fullCalendar( 'removeEventSource', source1 ); //Hide it
I did a plunker where you can reproduce it.
This is my code when I insert multi record into my Collection first time it work well but when i insert second time it say duplicate _id, how to fix it.
//Save Journal Detail
$("#item-list tr").each(function (e) {
//debugger;
var yearMonth = $('#journalDate').val();
var date = moment(yearMonth).format("YYMM");
var prefix = curBranch + "-" + date;
var chartAccountId = $(this).find(".chart-account-id option:selected").val();
if (chartAccountId == "" || chartAccountId == null) {
return;
}
var journalDetailId = idGenerator.genWithPrefix(Acc.Collection.JournalDetail, prefix, 8);
var debit = parseFloat($(this).find(".debit").val());
var credit = parseFloat($(this).find(".credit").val());
if (debit > 0) {
Acc.Collection.JournalDetail.insert({
_id: journalDetailId,
journalId: doc._id,
chartAccountId: chartAccountId,
drCr: debit,
split: "Hello"
});
} else {
Acc.Collection.JournalDetail.insert({
_id: journalDetailId,
journalId: doc._id,
chartAccountId: chartAccountId,
drCr: -credit,
split: "Hello"
});
}
});
return doc;
The problem is likely to be that your $.each() iterations do not wait for your insert calls to finish, therefore the last id in the collection stays the same, and therefore idGenerator.genWithPrefix gives you the same id for multiple successive insert calls.
In the Meteor client, "insert never blocks". So you would have to wait on each insert call before getting the next id via idGenerator.genWithPrefix, or else your next generated id will end up being the same as the previous one you started to insert.
One easy solution could be to transfer that logic to the server (where insert calls are blocking) using a method call, by only giving it the list of documents you wish for it to insert.
On the client:
//Save Journal Detail
var listToInsert = [];
var yearMonth = $('#journalDate').val();
var date = moment(yearMonth).format("YYMM");
var prefix = curBranch + "-" + date;
$("#item-list tr").each(function (e) {
//debugger;
var chartAccountId = $(this).find(".chart-account-id option:selected").val();
if (chartAccountId == "" || chartAccountId == null) {
return;
}
var debit = parseFloat($(this).find(".debit").val());
var credit = parseFloat($(this).find(".credit").val());
listToInsert.push({
journalId: doc._id,
chartAccountId: chartAccountId,
drCr: debit > 0 ? debit : -credit, // simplified with a ternary operator
split: "Hello"
});
});
Meteor.call("insertEntries", listToInsert, prefix, function () {
//done!
});
return doc;
On the server:
Meteor.methods({
'insertEntries': function (listToInsert, prefix) {
for (var i = 0; i < listToInsert.length; i++) {
listToInsert[i]._id = idGenerator.genWithPrefix(Acc.Collection.JournalDetail, prefix, 8);
// Since we're on the server, this insert will be blocking
Acc.Collection.JournalDetail.insert(listToInsert[i]);
}
}
});