ChaplinJS collection syncing issue - chaplinjs

so I have a collection which I fetch in application start like so
module.exports = class Application extends Chaplin.Application
start: ->
# # You can fetch some data here and start app
# # (by calling `super`) after that.
Chaplin.mediator.styleCollection.fetch().then super
After this home controller takes over and takes the user to the appropriate page like so
module.exports = class HomeController extends Controller
beforeAction: ->
super
#reuse 'header', HeaderView, region: 'header'
#reuse 'nav', NavView, region: 'nav'
#reuse 'price', PriceView, region: 'price'
#reuse 'frame', FrameView, region: 'frame'
piece: ->
#view = new PieceView
region: 'main'
nextPage: "style"
#subscribeEvent "click:continue-btn", ()->
#redirectTo {url:"style"}
#publishEvent "update:progress", 25
, #
Now when I get to the PieceView via my HomeController, I am expecting that Chaplin.mediator.styleCollection should have already synced, yet a few times during reload clearly the collection is not ready. So I put in some console.logs and here is what I see
console.log Chaplin.mediator.styleCollection outputs (all is well so far)
StyleCollection
_byId: Object
_events: Object
_previousSync: "syncing"
_syncState: "synced"
escape: function (value) {
length: 3
models: Array[3]
safe: function (value) {
__proto__: ctor
console.log Chaplin.mediator.styleCollection.toJSON() (this is where things break)
Array[0] <<<< the collection has nothing in it. I first thought the collection could still be syncing but that is not the case because the previous log showd _syncState: "synced"
Any thoughts?

Ok this was a dumb fix.
in Application code I did the following
Chaplin.mediator.styleCollection.fetch().then => super

Related

Redux toolkit serializableMiddleware doesn't work

I encountered with an issue of serializableMiddleware in redux toolkit. I need to store firestore timestamps inside my redux store and don't want that serializableMiddleware logged this text:
A non-serializable value was detected in the state, in the path: path to timestamp. Value: nt {seconds: > 1675422816, nanoseconds: 106000000}
Take a look at the reducer(s) handling this action.
So i take a look at the serializableMiddleware in redux toolkit docs and find out that there is an option isSerializable?: (value: any) => boolean. When I return true from this method, value should consider serializable, but still logs error out even if I always return true.
I wrote function but it didn't work:
const isSerializable = (value: any) =>
value instanceof Timestamp || isPlain(value);
const serializableMiddleware = createSerializableStateInvariantMiddleware({
isSerializable
})
Here is how I setup my store:
export const setupStore = () => {
return configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware()
.concat(serializableMiddleware)
})
}
The problem here is that getDefaultMiddleware() already adds the serializable middleware as part of the default setup. You're creating a second instance of the middleware, but that doesn't change the first instance.
Instead, you need to customize the first instance by passing the right options to getDefaultMiddleware():
export const setupStore = () => {
return configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
isSerializable: myCustomIsSerializableFunction
}
})
})
}

[vscode extension API]: How to create communication channel between javascript included in `vscode.previewHtml` and outside thread?

The thing is, i am trying to create a tool with vscode.previewHtml command, I need some javascript in it listening on user's action, and send a signal to outside thread, so that i can do few high cost "native" job in background, and refresh the previewHtml with new content.
Is it possible?
I assume by "outside thread" you actually mean the hosting environment (VS code). There is no direct way (e.g. a listener/callback/method) to communicate, but you can use postMessage like so:
/* This is in a .js file you include in previewHTML. */
function exportToSVG(type) {
let html = document.querySelectorAll('html')[0];
let svg = document.querySelectorAll('svg')[0];
const args = { name: objectName, type: type, svg: svg.outerHTML, html: html.outerHTML };
window.parent.postMessage({
command: "did-click-link",
data: `command:_antlr.saveSVG?${encodeURIComponent(JSON.stringify(args))}`
}, "file://");
}
In vscode only a few commands are handled. One is that did-click-link command. You then can register to that command in your extension and do the actual work:
// This is in your extension code (usually the activate() method).
context.subscriptions.push(commands.registerCommand('_antlr.saveSVG', (args: { name: string, type: string, svg: string, html: string }) => {
window.showInputBox({
value: workspace.getConfiguration("antlr4." + args.type)["saveDir"] + "/" + args.name + ".svg",
placeHolder: "<Enter full file name here>",
prompt: "Enter the name to an svg file."
}).then((value: string) => {
...
You can use the same approach for the other direction. See for instance the markdown preview extension how to do that.

How to create static parameters for use in data stores with rest proxy

I have an ExtJS 5.1.2 app that utilizes throughout the app a global config set of parameters defined in app_dir/app/Application.js, that looks like:
launch: function () {
Ext.Loader.setConfig({enabled: true});
// Static parameters
cardioCatalogQT.config = {
mode: 'test', // switch to control use of staging or production server
//protocol: 'https://',
protocol: 'http://',
//host: 'production_server',
//host: 'test_server,
host: '127.0.0.1:5000',
apiGetQ: '/get_query/',
//apiGetQ: '/api/get_query/',
apiWriteQ: '/remote_query_put',
apiReadQ: '/remote_query_get',
//apiMedsMenu: '/api/meds',
//apiMedsMenu: '/meds',
remove: 'none'
};
// TODO - Launch the application
Ext.onReady(function () {
});
}
This way, I only have one place to change the parameters that make up the url in Ajax calls, (in this case protocol, host and apiGetQ, for example give mr the ability to set url = cardioCatalogQT.config.protocol + cardioCatalogQT.config.host + cardioCatalogQT.config.apiGetQ), in one place to change the server address from development -> testing -> production, instead of having to find all references throughout the app.
However, due to the way that the ExtJs loads, I cannot use these config parameters in data stores that use rest proxies, since these stores seem to load before items in the Ext.Loader.
For example, I have the following store:
Ext.define('cardioCatalogQT.store.Diagnoses', {
extend: 'Ext.data.Store',
alias: 'store.Diagnoses',
config:{
model: 'cardioCatalogQT.model.Diagnosis',
storeId: 'Diagnoses',
autoLoad: true,
proxy: {
type: 'rest',
url: 'http://127.0.0.1:5000/menu/diagnoses',
//url: 'http://test_server/menu/diagnoses',
//url: 'https://prod_server/api/menu/diagnoses',
reader: {
type: 'json',
rootProperty: 'menu_test'
}
}
}
});
So, when I change from testing to development environments, for example, I have to explicitly change the n different references for url in my n stores that have rest proxies.
Is there a way to define a config object so that I can use it for these stores? I looked at some examples of a preloader, but this did not seem to have any use cases documented for a global config object, also I had tried implementing a loadmask in a preloader, but it really screwed with the behavior of my app.
I use to do like #Alexander propose, however I'll prefer the singleton way. More ExtJs/MVC like.
So just to complete, I share my version:
/**
* #class
*/
Ext.define("MyApp.config.Config", {
alternateClassName: [
'MyApp.config'
],
singleton: true,
constant: {
// ... whatever constant you need to put here
},
constructor: function() {
var constant = this.constant;
//
// here, if you need to process some stuff
// for example calculate some constant
// which depend of other constant
//
return constant;
}
});
Require in your app
// Be sure to require your class prior
// to your app classes
Ext.define('MyApp.Application', {
extend: 'Ext.app.Application',
requires: [
'Ext.app.*',
// ext stuff ...
'MyApp.config.Config',
// myApp stuff ...
]
// ...
});
Example usage:
Ext.define('MyApp.store.MyStore', {
// ...
proxy: {
type: 'rest',
url: MyApp.config.remoteUrl
}
})
We had similar issues, so we have put our global ConnectionSettings object into a script tag that is in index.html, before Ext.
<script type="text/javascript">
ConnectionSettings = {
...
...
};
</script>
<!-- The line below must be kept intact for Sencha Cmd to build your application -->
<script id="microloader" ...
That way, the object is available wherever we need it in our Ext code.

ember-cli - Ember Data get request failed TypeError - undefined is not a function

I'm porting the ember portion of an ember-rails app to Ember CLI. So far so good, but I'm having trouble with a get request that's blowing up in RESTSerializer.
The Application Controller attempts to grab a list of widgets
`import Ember from 'ember'`
ApplicationController = Ember.Controller.extend
widgets: (->
#store.find('unfinishedWidgets', id: #get('currentId'))
).property()
`export default ApplicationController`
I can see the API Request fire off, the JSON comes back, everything looks just like it did in the Ember Rails stack. Except then instead of updating the property and displaying in the view, it blows up:
TypeError: undefined is not a function
at Object.func (http://localhost:4200/myapp/assets/vendor.js:49473:18)
at Object.Cache.get (http://localhost:4200/myapp/assets/vendor.js:25091:38)
at decamelize (http://localhost:4200/myapp/assets/vendor.js:49515:31)
at RESTSerializer.extend.keyForAttribute (http://localhost:4200/myapp/assets/vendor.js:66565:16)
at apply (http://localhost:4200/myapp/assets/vendor.js:32821:27)
at superWrapper [as keyForAttribute] (http://localhost:4200/myapp/assets/vendor.js:32393:15)
at null.<anonymous> (http://localhost:4200/myapp/assets/vendor.js:69024:31)
at null.<anonymous> (http://localhost:4200/myapp/assets/vendor.js:71513:20)
at cb (http://localhost:4200/myapp/assets/vendor.js:29067:22)
at OrderedSet.forEach (http://localhost:4200/myapp/assets/vendor.js:28865:13) vendor.js:28532logToConsole vendor.js:28532RSVP.onerrorDefault vendor.js:42608__exports__.default.trigger vendor.js:61072Promise._onerror vendor.js:62084publishRejection vendor.js:60315(anonymous function) vendor.js:42583DeferredActionQueues.invoke vendor.js:13853DeferredActionQueues.flush vendor.js:13923Backburner.end vendor.js:13309Backburner.run vendor.js:13364run vendor.js:31375hash.success vendor.js:68006fire vendor.js:3237self.fireWith vendor.js:3349done vendor.js:9393callback
I put in a breakpoint at decamelize, which stopped so I could inspect what was going on:
function decamelize(str) {
return DECAMELIZE_CACHE.get(str);
}
str at this point isn't a string, it's:
Object {type: undefined, isAttribute: true, options: Object, parentType: function, name: "bundleId"}
isAttribute: true
name: "otherId"
options: Object
parentType: (subclass of DS.Model)
type: undefined__proto__: Object
So this is the first DS.attr() in my Model:
`import DS from 'ember-data'`
unfinishedWidgets = DS.Model.extend
otherId: DS.attr()
# other attrs
`export default UnsubmittedRequest`
I'm using a ActiveModelAdapter by default, and I've also made an empty ActiveModelSerializer.
`import DS from 'ember-data'`
ApplicationAdapter = DS.ActiveModelAdapter.extend
namespace: 'api/myapp/v1'
`export default ApplicationAdapter`
`import DS from 'ember-data'`
ApplicationSerializer = DS.ActiveModelSerializer.extend()
`export default ApplicationSerializer`
EDIT:
I ended up fixing it with:
ApplicationSerializer = DS.ActiveModelSerializer.extend
keyForAttribute: (type, name) ->
name
Though I'm still not clear on why it was necessary in Ember CLI when it was fine in Ember-rails
This happens when your server returns an invalid json response. In this case it's not returning with a root object.
You're server is likely returning something like this
{
other_id: 1
// ...
}
and it needs to be
{
unfinished_widget: {
other_id: 1
// ...
}
}
The ActiveModelAdapter/Serializer expects it in that style. Honestly this error is terrible and should be reported as a bug in ember-data. I've hit it before and it's super hard to debug and track down.
So, as it turns out, it was simply a bug in EmberData 1.0.0.beta.10. I updated to beta 12 and everything worked.

Get a server method result before executing a Collection transform

Working on CoinsManager, I have a model directory with a class per file, and I want to read and list all those files in my collection transform method, to initialize my doc with the correct class.
server/methods.coffee:
Meteor.methods
implemented_coins: ->
"""
Returns a list of coins that have been implemented
"""
files = fs.readdirSync './app/models/cryptos/'
file.replace(".coffee.js", "") for file in files.filter (file) ->
file.search("(base_crypto*)|(js.map)") == -1
collections/addresses.coffee:
if Meteor.isReady
#implementedCoins = Meteor.call "implemented_coins"
#Addresses = new Meteor.Collection "addresses",
transform: (doc) ->
# Retrieve class from code, and pass it the address
if doc.code in #implementedCoins
new #[doc.code] doc.address
else doc
client/views/addresses/addresses_list.coffee
Template.userAddresses.helpers
userAddresses: ->
addresses = Addresses.find
userId: Meteor.user()._id
address.set_balance() for address in addresses
return addresses
Right now, I'm getting the following error on the client console:
Exception from Deps recompute: TypeError: Array.prototype.indexOf called on null or undefined
at indexOf (native)
at Addresses.Meteor.Collection.transform
Which means that in my collection transform, the #implementedCoins variable is undefined, because I didn't implement it correctly.
Any idea how to solve this problem ?
I'm pretty sure that this is wrong:
if Meteor.isReady
#implementedCoins = Meteor.call "implemented_coins"
I don't think there is a field in Meteor with that name, and even if it was, then it would get executed on startup, but at that time isReady is probably false and so your variable doesn't get set. Did you mean Meteor.startup? Secondly, on the client you need to use a callback for call, since there are no fibers on the client.
Would this work instead?
Meteor.startup(function () {
Meteor.call("implemented_coins", function(err, res) {
implementedCoins = res;
});
});