SAFE template Elmish redux dev tools message always "UserMsg" - redux

I'm quite new to Elmish. Did a sample template using dotnet new SAFE. When I open the app and use redux dev tools Chrome extension I always get message which is "UserMsg". Is there a way to make it "Increment" or "Decrement" when I click the button "-" or "+"?

The elmish-browser Navigation module wrap all messages in the Parser type which is a union of either Change (for a URL change) or UserMsg (for everything else).
This breaks the reflection in both withDebugger and withConsoleTrace... they are unable to grab the name of the underlying message, and hence display the wrapped name instead.
The work-around is to invoke toNavigable after withDebugger in the program initialization pipeline:
Program.mkProgram init update view
#if DEBUG
|> Program.withConsoleTrace
#endif
|> Program.withReactBatched "elmish-app"
#if DEBUG
|> Program.withDebugger
#endif
|> Program.toNavigable (parseHash route) urlUpdate
|> Program.run
However, by doing this the "Change" messages are no longer sent to the debugger. This could be a problem if your urlUpdate function is updating the model state directly. It may be better for your urlUpdate function to raise a new command with a message to be handled by the main update function.
See https://github.com/elmish/browser/issues/26

Related

Reading JS library from CDN within Mirth

I'm doing some testing around Mirth-Connect. I have a test channel that the datatypes are Raw for the source and one destination. The destination is not doing anything right now. In the source, the connector type is JavaScript Reader, and the code is doing the following...
var url = new java.net.URL('https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.fp.min.js');
var conn = url.openConnection();
conn.setRequestMethod('GET');
if(conn.getResponseCode() === 200) {
var body = org.apache.commons.io.IOUtils.toString(conn.getInputStream(), 'UTF-8');
logger.debug('CONTENT: ' + body);
globalMap.put('_', body);
}
conn.disconnect();
// This code is in source but also tested in destination
logger.debug('FROM GLOBAL: ' + $('_')); // library was found
var arr = [1, 2, 3, 4];
var _ = $('_');
var newArr = _.chunk(arr, 2);
The error I'm getting is: TypeError: Cannot find function chunk in object.
The reason I want to do this is to build custom/internal libraries with unit test and serve them with an internal/company CDN and allow Mirth to consume them.
How can I make the library available to Mirth?
Rhino actually has commonjs support, but mirth doesn't have it enabled by default. Here's how you can use it in your channel.
channel deploy script
with (JavaImporter(
org.mozilla.javascript.Context,
org.mozilla.javascript.commonjs.module.Require,
org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptProvider,
org.mozilla.javascript.commonjs.module.provider.UrlModuleSourceProvider,
java.net.URI
)) {
var require = new Require(
Context.getCurrentContext(),
this,
new SoftCachingModuleScriptProvider(new UrlModuleSourceProvider([
// Search path. You can add multiple URIs to this array
new URI('https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/')
],null)),
null,
null,
true
);
} // end JavaImporter
var _ = require('lodash.min');
require('lodash.fp.min')(_); // convert lodash to fp
$gc('_', _);
Note: There's something funky with the cdnjs lodash fp packages that don't detect the environment correctly and force that weird two stage import. If you use https://cdn.jsdelivr.net/npm/lodash#4.17.15/ instead you only need to do var _ = require('fp'); and it loads everything in one step.
transformer
var _ = $gc('_');
logger.info(JSON.stringify(_.chunk(2)([1,2,3,4])));
Note: This is the correct way to use fp/chunk. In your OP you were calling with the standard chunk syntax.
Additional Commentary
I think it's probably ok to do it this way where you download the library once at deploy time and store it in the globalChannelMap, then retrieve it from the map where needed. It would probably also work to store the require object itself in the map if you wanted to call it elsewhere. It will cache and reuse the object created for future calls to the same resource.
I would not create new Require objects anywhere but the deploy script, or you will be redownloading the resource on every message (or every poll in the case of a Javascript Reader.)
Edit: I guess for an internal webhost, this could be desirable in a Javascript Reader if you intend for it to pick up changes immediately on the next poll without a redeploy, assuming you would be upgrading the library in place instead of incrementing a version
The benefit to using Code Templates, as Vibin suggested is that they get compiled directly into your channel at deploy time and there is no additional fetching step at runtime. Making the library available is as simple as assigning it to your channel.
Even though importing third party libraries could be an option, I was actually looking into this for our team to write our own custom functions, write unit-test for them, and lastly be able to pull that code inside Mirth. I was experimenting with lodash but it was not my end goal to use it, it is. My solution was to do a REST GET call with java in the global script. Your URL would be the GitHub raw URL of the code you want to pull in. Same code of my original question but like I said, the URL is the raw GitHub URL for the function I want to pull in.

Evernote IOS SDK fetchResourceByHashWith throws exception

Working with Evernote IOS SDK 3.0
I would like to retrieve a specific resource from note using
fetchResourceByHashWith
This is how I am using it. Just for this example, to be 100% sure about the hash being correct I first download the note with a single resource using fetchNote and then request this resource using its unique hash using fetchResourceByHashWith (hash looks correct when I print it)
ENSession.shared.primaryNoteStore()?.fetchNote(withGuid: guid, includingContent: true, resourceOptions: ENResourceFetchOption.includeData, completion: { note, error in
if error != nil {
print(error)
seal.reject(error!)
} else {
let hash = note?.resources[0].data.bodyHash
ENSession.shared.primaryNoteStore()?.fetchResourceByHashWith(guid: guid, contentHash: hash, options: ENResourceFetchOption.includeData, completion: { res, error in
if error != nil {
print(error)
seal.reject(error!)
} else {
print("works")
seal.fulfill(res!)
}})
}
})
Call to fetchResourceByHashWith fails with
Optional(Error Domain=ENErrorDomain Code=0 "Unknown error" UserInfo={EDAMErrorCode=0, NSLocalizedDescription=Unknown error})
The equivalent setup works on Android SDK.
Everything else works so far in IOS SDK (chunkSync, auth, getting notebooks etc.. so this is not an issue with auth tokens)
would be great to know if this is an sdk bug or I am still doing something wrong.
Thanks
This is a bug in the SDK's "EDAM" Thrift client stub code. First the analysis and then your workarounds.
Evernote's underlying API transport uses a Thrift protocol with a documented schema. The SDK framework includes a layer of autogenerated stub code that is supposed to marshal input and output params correctly for each request and response. You are invoking the underlying getResourceByHash API method on the note store, which is defined per the docs to accept a string type for the contentHash argument. But it turns out the client is sending the hash value as a purely binary field. The service is failing to parse the request, so you're seeing a generic error on the client. This could reflect evolution in the API definition, but more likely this has always been broken in the iOS SDK (getResourceByHash probably doesn't see a lot of usage). If you dig into the more recent Python version of the SDK, or indeed also the Java/Android version, you can see a different pattern for this method: it says it's going to write a string-type field, and then actually emits a binary one. Weirdly, this works. And if you hack up the iOS SDK to do the same thing, it will work, too.
Workarounds:
Best advice is to report the bug and just avoid this method on the note store. You can get resource data in different ways: First of all, you actually got all the data you needed in the response to your fetchNote call, i.e. let resourceData = note?.resources[0].data.body and you're good! You can also pull individual resources by their own guid (not their hash), using fetchResource (use note?.resources[0].guid as the param). Of course, you may really want to use the access-by-hash pattern. In that case...
You can hack in the correct protocol behavior. In the SDK files, which you'll need to build as part of your project, find the ObjC file called ENTProtocol.m. Find the method +sendMessage:toProtocol:withArguments.
It has one line like this:
[outProtocol writeFieldBeginWithName:field.name type:field.type fieldID:field.index];
Replace that line with:
[outProtocol writeFieldBeginWithName:field.name type:(field.type == TType_BINARY ? TType_STRING : field.type) fieldID:field.index];
Rebuild the project and you should find that your code snippet works as expected. This is a massive hack however and although I don't think any other note store methods will be impacted adversely by it, it's possible that other internal user store or other calls will suddenly start acting funny. Also you'd have to maintain the hack through updates. Probably better to report the bug and don't use the method until Evernote publishes a proper fix.

Robot Framework Getting Keyword failure reason

Trying to implement a listener interface for robot framework in order to collect information about keyword executions like time taken for execution, Pass/Fail status, failure message in case if status is fail. Sample code is given below
import os.path
import tempfile
class PythonListener:
ROBOT_LISTENER_API_VERSION = 2
ROBOT_LIBRARY_SCOPE = 'GLOBAL'
def __init__(self, filename='listen.txt'):
outpath = os.path.join(tempfile.gettempdir(), filename)
self.outfile = open(outpath, 'w')
def end_keyword(self, name, attrs):
self.outfile.write(name + "\n")
self.outfile.write(str(attrs) + "\n")
def close(self):
self.outfile.close()
All the information apart from keyword failure message is available in the attributes which is passed to end_test method from robot framework.
Documentation can be found here. https://github.com/robotframework/robotframework/blob/master/doc/userguide/src/ExtendingRobotFramework/ListenerInterface.rst#id36
The failure message is available in the attributes for end_test() method. But this will not have information if a keyword is run using RunKeywordAndIgnoreError.
I could see that there is a special variable ${KEYWORD MESSAGE} in robot framework, which contains the possible error message of the current keyword Is it possible to access this variable in the listener class.?
https://github.com/robotframework/robotframework/blob/master/doc/userguide/src/CreatingTestData/Variables.rst#automatic-variables
Are there any other ways to collect the failure message information at the end of every keyword?
That's an interesting approach, indeed, end_test will ensure an attributes.message field containing the failure. (so it goes for end_suite if it fails during the suite setup/teardown)
With end_keyword you don't have such message, but at least you can filter for the FAIL status and detect which one failed. Then the message returned by Run Keyword And Ignore Error has to be logged explicitly by you so you can capture such triggering logs with the log_message hook. Otherwise nobody is aware of the message of the exception handled by the wrapper keyword which returns a tuple of (status, message).
There's also the message hook but couldn't manage to get it called from a normal breaking robot:
Called when the framework itself writes a syslog message.
message is a dictionary with the same contents as with log_message method.
Side note: To not expose these hooks as keywords, you can precede the method names with _. Examples:
def _end_test(self, name, attributes): ...
def _log_message(self, message): ...

How to get resourceName for Tridion LocalizableMessage when creating new PublisherException?

I need to stop publishing of a page when a certain condition exists, for example if the page name contains 'one' using the Event System. Also, the other pages should continue to publish.
I am thinking to use a PublisherException instead of a generic exception.
The problem is the I do not know the resourceName of the LocalizableMessage. Any ideas?
if (item.Title.ToString().Contains("one"))
{
Localization.LocalizableMessage errResource = new Localization.LocalizableMessage("error");
throw new PublisherException(errResource, new Exception("Can't get there from here!"));
}
The Event System can stop Publishing, there is no middle ground there though, when you throw an exception, it stops the entire transaction.
Like Puntero mentions, if you want to remove an item from a Publish Transaction, that is where a Custom Resolver comes in. From here you cannot communicate back to the Publish Transaction, but you have access to the Tridion Logger (eventlog):
Tridion.Logging.Logger.Write("your message string", "MyResolver", LoggingCategory.General, TraceEventType.Information);
With regards to your LocalizableMessage in the Event System, you should be able to do the following:
throw new PublisherException(new LocalizableMessage(Properties.Resources.ResourceManager, "PagePublishErrorMessage"));
Where the resourceName is pointing to the name of a String resource you have in your Project.
I agree with #Puntero that if you want other page in a publish action to go through, you should use a Resolver rather than an Event Handler.
I tried to raise a warning to alert users of one item not being resolved, but failed. But there may be some good tips/ideas for you here: Raising a “warning” status during SDL Tridion 2011 publishing
In the end, the only way I could get anything to work was to set "Allow X failures", and then do a check in a template, and raise the error there. That will count as a Render failure, and allow the publisher to move on to the next item in the publish transaction.
As for the message? What message would you like to display?

as3 to .net, not receiving Event.COMPLETE callback

I created an image uploader for an app I am working on. I first used php for the server side script, and everything worked fine. I found out afterwards I had to use .net, so I created new serverside scripts. The problem I am having is that my event.COMPLETE listener is never firing. I can receive data back using a DATAEVENT listener, but then it stops at this error:
Error #2044: Unhandled IOErrorEvent:. text=Error #2036: Load Never Completed.
Here is how I am sending my file.
var fileRefReq:URLRequest = new URLRequest(FILE_UPLOAD_TEMP);
var fileReqVars:URLVariables = new URLVariables();
fileReqVars.subdir = "Temp";
fileRefReq.data = fileReqVars;
fileRefReq.method = URLRequestMethod.POST;
fileRef.upload(fileRefReq);
The file definitely gets uploaded to the first TEMP directory, but then it breaks with the above error.
Has anyone else had a similar problem or point me in the right direction for solving this?
This is an error produced by Flash. The most common causes are:
It could be a 404 Error you are getting somewhere in the Flash.
This error can occur if you close the browser while it is loading something.
By default, the calling SWF file and the URL you load must be in the same domain. For example, a SWF file at www.adobe.com can load data only from sources that are also at www.adobe.com. To load data from a different domain, place a URL policy file on the server hosting the data.
Number 3 is important because a common user problem with Flash is security issues - so it is just something to rule out. Most likely not the cause here.
I would test for these 3 causes and read over the URLRequest: http://livedocs.adobe.com/flex/3/langref/flash/net/URLRequest.html
After some additional thought I think it is timing out but that is just a theory. Add an event listener like so:
urlLoader.addEventListener("httpResponseStatus", function(event:HTTPStatusEvent):void
to see what is actually happening.
You have to handle the event such as:
// add the event listener
urlLoader.addEventListener( IOErrorEvent.IO_ERROR, onErrorHandler );
// handle the error event like this:
private function onErrorHandler( e: IOErrorEvent ): void {
trace( "An io error occurred." );
}
Hope that helps

Resources