Babel traverse to the first JSXElement - babeljs

I need to add a custom attribute to components of a ReactJS app, for testing purposes. I have tried to use 2 different plugins, however, they apply the attribute to all JSXElements within that component and I want to apply it to just the first, otherwise, I end up with unnecessary duplication of the attribute which makes writing the tests even harder and I'm trying to save fragility.
I have gone through the docs and cannot find how to traverse to the first JSXElement, so have tried a couple of things myself and failed, these are
The below never adds the attribute
visitor: {
JSXElement( path, state ) {
if ( path.key === 0 )
{
path.node.openingElement.attributes.push(
t.jSXAttribute(
t.jSXIdentifier( 'data-e2e' ),
t.stringLiteral( `${someValue}` )
)
);
}
}
}
The below throughs error that firstElem in undefined
visitor: {
Program( path, state ) {
let arr = [];
path.traverse( {
enter( jsxPath )
{
if ( jsxPath.node.type === 'JSXElement' )
{
arr.push( jsxPath );
}
}
} );
let firstElem = arr[ 0 ]; <<< undefined
firstElem.node.openingElement.attributes.push(
t.jSXAttribute(
t.jSXIdentifier( 'data-e2e' ),
t.stringLiteral( `${someValue}` )
)
);
}
}
}
Can anyone suggest how to get just the first JSXElement.

So I found the answer by pure luck. I should have added in a stop() immediately after traversing the JSXElement
JSXElement( jsxPath )
{
jsxPath.stop();
...
The stop() function is not that will documented, in fact, none of BabelJS is that will documented for a beginner. Found this by looking at a someone's plugin and wondering what it was doing there and by trial and error, found it resolved the above propblem.

Related

Check Eloquent wasChanged on hasMany/belongsTo Model relationship

I want to check the wasChanged() status of my child/detail models, just as I do with the parent/header model in the hasMany(parent) :: belongsTo (child) relationship.
I've got code that looks like this:
$parent = Parent::updateOrCreate([ ... ], [ ... ]);
if ($parent->wasChanged()) {
// do something useful
}
foreach ($contents as $child) {
$parent->children()->updateOrCreate([ keys ],[ data ]);
// Now I want to check if the Child model named Contents was changed.
// if ($parents->children()->wasChanged()) { ... // does not work
}
How can I accomplish this?
Not sure what $contents does, but, you could always do something like this to accomplish the idea of what you want done:
$parent = Parent::updateOrCreate([ keys ],[ data ]);
$parent->load('children');
if ($parent->wasChanged()) {
// do something useful
}
$parent->children()->updateOrCreate([ keys ],[ data ]);
foreach($parent->children() as $child) {
if ($child->wasChanged()) {
// do something useful
}
}
I'm not even sure this is a correct answer, but what I ended up doing and seems to be working is adding save() calls after each createOrUpdate() call. The Laravel documentation suggests this is not how it is supposed to work, but it's hard to argue with empirical evidence.
$parent = Parent::updateOrCreate([ keys ],[ data ]);
if ($header->wasChanged() || $header->wasRecentlyCreated) {
// Do interesting work
}
$parent->save();
foreach ($myInterestingData as $newChildData) {
$child = $header->children()
->updateOrCreate( ... keys/values from $newChildData ...);
if ($child->wasChanged() || $child->wasRecentlyCreated) {
// Do boring work
}
$child->save();
}

Meteor observeChanges changed fires more than once

This Meteor server code needs to invoke myFunc() only once when myArray.length === 3 but it gets fired more than once. How can it be fixed? thx
let name = 'john';
myCol.find({name: name}).observeChanges({
changed: function (id, fields) {
if (fields.myArr) {
if (fields.myArr.length === 3) {
console.log('setting time out for: ' + name); // <--- prints more than once
let doc = myCol.find({name: name});
setTimeout(Meteor.bindEnvironment(function () {
ddpCall(doc);
}), 15000);
} else if (fields.myArr.length === 4) {
ddpCall(doc);
}
}
});
let dppCall = function (doc) {
if (doc.search === 'required') {
myCol.update({_id: doc._id}, {$unset: {search: ''}});
ddpConn.call('myFunc', doc);
}
}
// some where else in the ddp call code
'myFunc': function () {
// some logic here which changes the myArr
myCol.update({name: name}, {$set: myObj, $addToSet: {myArr: myLabel}}); // push myLabel
});
I am not sure you would really need an observer for this. If you have a method writing into this array, why don't you do the whole thing inside the method. If there is any blocking actions like sending sms or email you can use the Meteor this.unblock(). I mention the unblocking because I see you use a long timeout there.
When you avail of the variable with the same name you can skip the declaration:
const name = 'john';
myCol.find({name})....
the method would be like:
'meteormethod' with simple schema or validation etc and inside the method:
myCol.update({name}, {$set: myObj, $addToSet: {myArr: myLabel}})
const myArr = myCol.findOne({name}).myArr // hope 'name' is unique
if( myArr && myArr.length === 3 ) { fire what you need (with unblock if required) }
end of your method
If your required action is server side, your method can call a server side method (which is the typical case for emailing).
Just to keep in mind that $addToSet will not change the length of your array if the value exists in the array Mongo $addToSet
I personally prefer to do many things like in the electronic circuits, kind of if this...that just to make sure I do not have to many different logics implemented in a project. I am not sure if the "wireframe" principle may apply to you here.
Also you can simplify your code above by merging the 2 'if' functions:
if (fields && fields.myArr && fields.myArr.length === 3 ) { ... }
Regards,
Paul

Coffeescript best way to var

I was poking around trying to figure a good way to do var, and here's one.. is this intentionally in cs, because it's not documented?
me=;
fetchUser()
.then((_me) =>
me = _me
fetchFriend()
)
.then((_you) =>
me.friend(_you)
)
.then(done)
.otherwise(=>
console.log ':('
)
compiles correctly to
var me;
me = fetchUser().then((function(_this) {
return function(_me) {
me = _me;
return fetchFriend();
};
})(this)).then((function(_this) {
return function(_you) {
return me.friend(_you);
};
})(this)).then(done).otherwise((function(_this) {
return function() {
return console.log(':(');
};
})(this));
Edit: it's not compiling correctly.
I wouldn't expect me = fetchUser() either, but I didn't see that before
https://github.com/jashkenas/coffee-script/issues/3098
I think it's just a quirk of the parser. The normal way variables are declared in order to establish scoping is just by defining them with some default value (e.g. null).

Codemirror adding keywords on the fly for syntax highlight

I am currently adding a new language mode in CodeMirror for my current project. This is a proprietary language in which user can create a new keyword. Basically I am trying to update existing keyword list at the runtime and my syntax highlighter can pick this new keyword.
var mode = editor.doc.modeOption;
if(mode === "dmsrl") mode = "text/dmsrl";
var keyWords = CodeMirror.resolveMode(mode).keywords;
keyWords[x]=true;
I am currently trying to add new keyword like above, but somehow the list is not getting updated and new keyword is unavailable in my tokebase() method.
Any help would be appreciated.
You can try to redefine hintOptions object, that pass to Codemirror's init function and than building hints in your specific hint addon with this data. Just try this
cm.setOption("hintOptions", { "keywords" : ["k1", "k2"] });
Look at first in sql-hint for example (link):
cm.setOption("hintOptions", { "tables" : ["k1", "k2"] });
For sql-mode this is not heavy operation
I wanted to reach the same goal as yours but with some more degree of freedom, consisting in inputting a container, which I can re-define along the run.
1) Put the following code into a file custom.mode.js, to be loaded from your web page
var _glob_keywords = [ [ "key1", "keyword1" ],
[ "key2", "keyword2" ]
] ;
var cm_custom_check_stream_fn = function( stream )
{
for( var _i = 0 ; _i < _glob_keywords.length ; _i++ )
{
if ( stream.match( _glob_keywords[_i][0] ) ) return _glob_keywords[_i][1] ;
}
return "" ;
}
CodeMirror.defineMode("custom.mode", function()
{
return {
token: function(stream,state)
{
var _ret = cm_custom_check_stream_fn( stream ) ;
if ( _ret.length > 0 ) return _ret ;
else { stream.next(); return null; }
}
};
});
This code will be automatically embedded into the Codemirror object to dynamically handle the input in the textbox.
Example: if "key1" is found, then "keyword1" is returned.
We assume that "keyword1", "keyword2" refer to entries inside a custom css definitions file, as explained in the codemirror documentation, that is,
.cm-keyword1 { color:#8BA8C4; }
.cm-keyword2 { color:lime; }
Hope it helps!

Jira: How to obtain the previous value for a custom field in a custom IssueEventListener

So how does one obtain the previous value of a custom field in a Jira IssueEventListener? I am writing a custom handler for the issueUpdated(IssueEvent) event and I would like to alter the handler's behavior if a certain custom field has changed. To detect the type of change I would like to compare the previous and current values.
(I'm am not asking about how to obtain its current value - I know how to get that from the related Issue)
I am developing against Jira 4.0.2 on Windows.
Is the best way to scan the change history for the last known value?
List changes = changeHistoryManager.getChangeHistoriesForUser(issue, user);
I'm assuming the original poster is writing a JIRA plugin with Java. I cannot be certain of how to accomplish this task in JIRA v4.0.2, but here is how I managed to do so with JIRA v5.0.2 (the solutions may very well be the same):
public void workflowEvent( IssueEvent event )
{
Long eventTypeId = event.getEventTypeId();
if( eventTypeId.equals( EventType.ISSUE_UPDATED_ID ) )
{
List<GenericValue> changeItemList = null;
try
{
changeItemList = event.getChangeLog().getRelated( "ChildChangeItem" );
}
catch( GenericEntityException e )
{
// Error or do what you need to do here.
e.printStackTrace();
}
if( changeItemList == null )
{
// Same deal here.
return;
}
Iterator<GenericValue> changeItemListIterator = changeItemList.iterator();
while( changeItemListIterator.hasNext() )
{
GenericValue changeItem = ( GenericValue )changeItemListIterator.next();
String fieldName = changeItem.get( "field" ).toString();
if( fieldName.equals( customFieldName ) ) // Name of custom field.
{
Object oldValue = changeItem.get( "oldvalue" );
Object newValue = changeItem.get( "newvalue" );
}
}
}
}
Some possible key values for changeItem are:
newvalue
oldstring
field
id
fieldtype
newstring
oldvalue
group
For many of the custom field types Object oldValue is probably just a String. But I don't think that's true for every case.
Try this example :
String codeProjetOldValue= "";
List<GenericValue> changeItemList = issueEvent.getChangeLog().getRelated("ChildChangeItem");
for (GenericValue genericValue : changeItemList) {
if(champCodeProjet.equals(genericValue.get("field"))){
codeProjetOldValue=genericValue.getString("oldstring");
break;
}
}
Note that : champCodeProjet is the name of customfield.