MomentJS - how to determine if current locale uses AM/PM - momentjs

I'm using Ant Design Timepicker to set event times (which are moment objects) and to display it correctly I need to determine whether current locale uses AM/PM or 24-hours time format.
Now my functions are using moment.localeData().longDateFormat('LT') to display just the time.

Well, it's a pretty straightforward solution:
export const use12Hours = ():boolean => {
const LTformat = moment.localeData().longDateFormat('LT');
if(LTformat.split(' ').length > 1 && LTformat.split(' ').pop() === 'A') {
return true;
}
return false;
}
Let me know, if there's something to be impoved.

Related

Crossfilter for Date for string values

I've a JSON model that contains strings instead of dates (the model is generated via T4TS, so I cannot change that).
The code is currently using an expanded model extending the original json, where the dates are recalculated on new fields.
I was wondering if it would be possible to apply the filters on the fields being string without adding that additional step of extending the model.
private makeNumeric(label: string, property: string) {
return {
label: label,
key: property,
prepareDimension: (crossfilter) => (CrossfilterUtils.makeNumeric(crossfilter, property)),
prepareGroup: (dimension) => {
if (!this.values[property]) {
var group = CrossfilterUtils.makeNumericGroup(dimension);
this.values[property] = group;
}
return this.values[property];
},
valuesAreOrdinal: false
};
}
I haven't used the crossfilter library much before and by looking at the documentation I can't seem to reconcile it with the code (heritage code, to put it that way).
The incoming date format looks like this: "2020-10-22T07:26:00Z"
The typescript model I'm working with is like this:
interface MyModel {
...
CreatedDate?: string;
}
Any idea?
The usual pattern in JavaScript is to loop through the data and do any conversions you need:
data.forEach(function(d) {
d.date = new Date(d.date);
d.number = +d.number;
});
const cf = crossfilter(data);
However, if this is not allowed due to TS, you can also make the conversions when creating your dimensions and groups:
const cf = crossfilter(data);
const dateDim = cf.dimension(d => new Date(d.date));
const monthGroup = dateDim.group(date => d3.timeMonth(date))
.reduceSum(d => +d.number);
I find this a little less robust because you have to remember to do this everywhere. It's a little harder to reason about the efficiency since you have to trust that crossfilter uses the accessors sparingly, but I don't recall seeing this be a problem in practice.

Enhanced ecommerce don't recognize internal promotion view object

I've been implementing all the enhanced eCommerce tracks for the past few weeks and I could do most of the job successfully thanks to Simo Ahava's blog. But now I'm struggling with the internal promotion view tracking.
I choose to implement the view tracking with the concept of True View Impressions also with a base on Simo's work and for products it was ok. So I modified the customTasks from the link to track internal promotion but, for some reason, the enhanced eCommerce isn't recognizing the promoView object. But it's recognizing the promoClick (?).
I've made a test: I substitute the promoClick for a impression object and it works! So, my strong guest, it's that the problem it's really on my object. My object's format can be seen here.
And to illustrate the way the object it's being constructed:
var targetElement = {{Click Element}},
event = {{Event}},
batch = window[promoBatchVariableName],
impressions = google_tag_manager[{{Container ID}}].dataLayer.get('ecommerce.promoView.promotions'),
ecomObj = { };
if (event === 'gtm.click') {
while (!targetElement.getAttribute(promoIdAttribute) && targetElement.tagName !== 'BODY') {
targetElement = targetElement.parentElement;
}
}
var latestPromoImpression = impressions.filter(function(impression) {
return impression.id === targetElement.getAttribute(promoIdAttribute);
}).shift();
var promoImpressionsArr = batch.map(function(id) {
return impressions.filter(function(impression) {
return impression.id === id;
}).shift();
});
if (event === 'gtm.elementVisibility'){
promoImpressionsArr[maxPromoBatch - 1] = latestPromoImpression;
}
console.log(ecomObj)
ecomObj.promoView = { promotions: promoImpressionsArr};
if (event === 'gtm.click') {
ecomObj.promoClick = {
promotions: [latestPromoImpression]
};
console.log("click")
}
return {
ecommerce: ecomObj
};
}
Could someone help me with some ideas?
This answer is just to close the question! As I pointed in the comments:
" I found the problem. And it's not on my object itself only. xD The problem is the undefined elements as you pointed at the beginning of our talk. I'm waiting for the dev team to change the data-attributes of the elements on our site's pages because sometimes we don't get any individual identifier variable. So, in the meantime, I've implemented a way to get always a product id even in these cases but as the identifier doesn't exist in the CSS selector if the element has an id in the 'entrance object', the element is set as undefined. "

i need to get the system time & store it as a child value in firebase

I need to add current system time into child data field.
I'm using TypeScript, but this might still give you and idea how you could do it.
My code uses the event.timestamp property to get date and time:
export const onWrite = functions.database.ref('/{databaseName}/{tableName}/{key}').onCreate((event) => {
let ref = event.data.ref;
let isCreate = event.eventType == 'providers/google.firebase.database/eventTypes/ref.create';
ref.once('value').then(e => {
// Cloud functions are sometimes executed with a delay and the record might not exist anymore.
if (e.val() === null) {
return;
}
if (isCreate) {
return ref.update({
'createdDateTime': event.timestamp
});
}
});
});
The created events for clients won't include this added data yet, only a later change event does.
I'm haven't investigated yet if this can be fixed (perhaps by making use of transaction).
I saw your image description and understood u want to add system time into firebase.
If you want to do you can do that by , like below
var fb_db=firebase.database().ref('treeName');
var key=fb_db.push().key;
var updatenode={}
updatenode[key+"\"]= new Date();
fb_db.update(updatenode).then(function(){
alert("Success")
})

Why Flow still complains about null values for document.getElementById

Why even with an IF check, Flow still complains about a possibly null value
if(document && document.getElementById("myID") && document.getElementById("myID").offsetWidth){
console.log(document.getElementById("myID").offsetWidth);
}
Gives this error
^ property `offsetWidth`. Property cannot be accessed on possibly null value
Flow has no way to know that the success of first call to getElementById means that the later ones will also succeed. For all it knows, reading the offsetWidth property could cause getElementById to start returning null the next time it is called.
You'll need to store the value, e.g.
const myIdEl = document && document.getElementById("myID");
if(myIdEl && myIdEl.offsetWidth) {
console.log(myIdEl.offsetWidth);
}
this way there is no way for myIdEl to become null after it has been referenced.
For HTMLElement (and extensions of HTMLElement like VideoHTMLElement) in FlowType, I'd recommend using instanceof to validate the Type and to validate that it's not null.
Also, I don't believe you need to check if document exists, that is defined globally in flow (1)*
<HTMLElement> Example
const myIdEl: ?HTMLElement = document.getElementById('myID');
if (myIdEl instanceof HTMLElement) {
// continue
console.log(myIdEl.offsetWidth);
}
<HTMLSelectElement> Example
const selectEl: ?HTMLElement = document.getElementById('someSelectElement');
// Checks correct type (!null !undefined come for free)
if (selectEl instanceof HTMLSelectElement) {
const selectedVal = selectEl.options[selectEl.selectedIndex].value;
}
<HTMLVideoElement> Example using invariant
import invariant from 'invariant';
const videoContent = document.getElementById('video-player');
invariant(videoContent instanceof HTMLVideoElement, 'No video element');
// do stuff with video api
videoContent.volume = 0;
videoContent.plause();
https://github.com/facebook/flow/blob/f3f29f7fd8c5aa73ac5a8a546ccfbc29cd7505fe/lib/dom.js#L1288

Fullcalendar permit selectOverlap for one day

I'm using Fullcalendar and I need to allow event overlap for one day: the last still event day can overlap on the first new event day.
For resizing and drop I resolved in this way:
eventOverlap: function(stillEvent, movingEvent) {
var a = movingEvent.start.startOf('day');
var b = stillEvent.end.startOf('day');
if(a.unix() == b.unix()){
return true;
}
return false;
}
Now I need to do the same on selecting, according to documentation, I have to use selectOverlap option by define a function, but differently of eventOverlap, this function not have an argument that include the current selection period, then I don't know how to make the check.
Somebody can say me how to do so?
UPDATE 19/05/2017:
I opened an issue on github's project repository here

Resources