Accessing blocker.BlockedBy - rally

Using Rally SDK 2.0, I am customizing the kanban board app. One of the items I am doing is trying to add who set the story to BLOCKED status.
When debugging it seems ok, but for some reason my blocker.BlockedBy is set to undefined. I am guessing I need to do something a bit different than this?
var blocker = this.getRecord().get("Blocker");
// blocker.BlockedBy is undefined right here
// blocker seems populated, but I am not sure its actually a Blocker object.
I added "Blocker" to the additional fields for the card as well
getAdditionalFetchFields: function () {
return ['Owner', 'FormattedID', 'Blocked', 'Ready', 'Priority', 'DefectStatus', 'Defects', "PlanEstimate", "LastUpdateDate", "TaskStatus", "Blocker"];
In the documentation it says that type Blocker is " non-creatable type", so not sure what this actually means...
Seems like the object coming back from the call has a _type field defining it as "Blocker".
Kinda stuck, I have tried typecasting the result to a Blocker, but still not having much luck. Just want to get who blocked the story :)

By adding Blocker as a fetch field, it's only returning a simple ref object that represents the Blocker object. But you can also tell fetch to fetch Blocker fields. So if you add BlockedBy as another field to fetch, it will grab that for your Blockers. WSAPI does a little magic here to figure out that you mean BlockedBy on the Blocker object.
BlockedBy is a User object, so the easiest way from there to get the user's name is with
var blockerName = this.getRecord().get('Blocker').BlockedBy._refObjectName;

Related

GA4 ecommerce items Array do not show up in debug mode

GA4 ecommerce items Array do not show up in debug mode
i am using the GTM, i am sure i passed the Array for items (using Datalayer or CJS), but GA4 does not recognized it , what i see is missing the items tab in debug mode, i don't know how that could be show up , am i doing something wrong? anyone has the same experience?
Looks like the event name is incorrect here -> View_Items.
Make sure that the event name exactly matches view_item
(stylized as snake_case).
As GA4 only allows ecommerce data collection with a set of pre-defined
event names.
Update :
I saw this checkbox is being checked
As you already set the value currency items in the event parameter. You can uncheck this setting.
I think you can follow Google's document about it
view_item_details
items: [
{
item_id: "SKU_12345",
item_name: "Stan and Friends Tee",
affiliation: "Google Merchandise Store",
coupon: "SUMMER_FUN",
currency: "USD",
discount: 2.22,
index: 0,
item_brand: "Google",
item_category: "Apparel",
item_category2: "Adult",
item_category3: "Shirts",
item_category4: "Crew",
item_category5: "Short sleeve",
item_list_id: "related_products",
item_list_name: "Related Products",
item_variant: "green",
location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
price: 9.99,
quantity: 1
}
]
Make items array only contain 1 item
Google has a list of recommended events suggesting that the items are automatically collected. If your custom event name doesn't match the listed event, GA4 won't take the items data.
Note that even though you can use the GTM preview mode to check whether the data is correctly constructed, the shown data won't necessarily send to GA4.
The reason is that GTM only forwards the requested data instead of sending it to GA4 directly. To see this behavior, you may have a look at the dev tool such as Chrome dev tool. You can examine the forwarded request's payload in the network tab (search /collect.*/). If it's the recommended event, in payload, there's pr1, pr2, etc., representing your items' array data; otherwise, you'll see nothing, and thus the data won't show up in the GA4 debugging mode.
Do you use the same GTM data layer which initially track for GA Universal events ? If yes, then this may be the cause why the items array did not show on debug view since I found this issue also.
The solution is to create the new GTM Container, and name the data layer differently like 'datalayer2' to differentiate those data layers and set up your config again with 'datalayer2'
for instance, datalayer2.push(
{
event : view_promotion
....}

Iterating store in relay optimisticUpdater

Apologies in advance, I'm new to relay and not sure I've got all the terminology here right...
I have a (simplified) graph that looks like:
customer {
summary(id: "ABC123") {
records { // This is an array of Record
tag
}
}
}
Customer, Summary and Record are all objects with global IDs - they show up as records in the Relay DevTools inspector.
I have a mutation that removes a tag by name (from elsewhere in the graph - not shown), from which I need to update the customer summary object to remove the record with associated tag. I have tried two approaches and not gotten very far with either:
Re-request customer.summary as part of the mutation. The problem is I don't know what the ID is at that point. (Maybe I can thread it through some how, but that would be messy.) Also doesn't really solve the problem, since I'd like to do this optimistically.
In an optimistic updater, remove any tag record that matches. This seems like it should work, but the RecordProxy doesn't appear to have a rich enough API to enable me to do this.
First approach, I can't seem to get access to the summary record via the root:
const customer = store.getRoot().getLinkedRecord('customer') // works!
customer.getLinkedRecord("summary") // undefined
customer.getLinkedRecord("summary", {id: "ABC123"}) // undefined
Second approach, if I could ask the store for "all records of type" or even "all records" I could iterate through and find the one I need to edit, but this doesn't seem to be a method that's exposed (even though Relay DevTools must be doing it somehow).

Re-enable load on demand [NativeScript Vue]

I have a Radlistview, where the data switches out based on user query. With loadOnDemandMode="Auto" and when the current query is exhausted, I then call notifyLoadOnDemandFinished(true). However, when a new query is made, I cannot re-enable loadOnDemand, and new items are not loaded.
Is there a way to reactivate loadOnDemand, perhaps with a method on the radListView object? I couldn't find anything in the docs.
Found the mistake, posting here for anyone else that may have the problem.
I was trying to set
listView.loadOnDemandMode = "Auto"
adding _nativeView fixed it
listView._nativeView.loadOnDemandMode = "Auto"

How to prevent DataTables from displaying or hiding columns on the basis of an obsolete saved state

I have a table driven by DataTables 1.10. Filtering is turned on. When I talk about "doing a search" below, I'm talking about using the filtering function of this table.
Description of the Problem
Everything works fine with stateSave off. However, when stateSave is on, the following happens:
Alice logs in as admin. Because admin has all privileges, when she does a search through articles, she can see all articles. Because some articles are published and some are unpublished the table has a column that show which are published and which are not. So far so good.
Bob, a random user, accesses the site. Random users cannot ever see unpublished articles so the table hides the column that shows publication status. So far so good.
Alice logs out. She now accesses the site like a random user. So she should see exactly what Bob sees. However, when she does a search she still sees the column that indicates publication status.
(Note: The issue I'm discussing here is purely one of user interface. The server ensures that unprivileged users cannot ever get a record for an unpublished article. The problem though is that the additional column gives unpriviledged users information that they do not need. They can only see published articles in their search so they don't need to see that every article they get in a search is published.)
The code that configures the datatable hides the publication column by doing something like this:
var columnDefs = [];
if (!privileged) {
columnDefs.push({
targets: [1],
orderable: false,
visible: false
});
}
columnDefs is passed to DataTables as the columnDefs option.
Technical Reason for the Problem
The problem is that DataTables store things like column visibility into the state it saves into localStorage. So when Alice logs out and makes a search again as an unprivileged user, even though the value of columnDefs is correct, it is overwritten by the saved state. That state was stored when Alice was an admin, and it declared the publication column to be visible, so it remains visible even when Alice is accessing the site as an unprivileged user.
What I want is for users to benefit from the saved state but avoid having this state carry over when the user's privileges change.
Caveats:
I don't want to use sessionStorage because I want the state to persist between browser closings, but sessionStorage is cleared when the browser is closed.
I cannot use the session cookie assigned by the server to detect logins and logouts because it is HTTP only. Besides, privileges could change for other reasons.
I do not want to arbitrarily set an expiration time on the saved state.
The solution I've settled on is to use an additional field in the saved data to know when the conditions I care about have changed. This is a field whose value changes depending on the privileges that the user currently has. For instance, because in the case I described here, I decide to hide or show a column on the basis of a variable named priviledged (which is initialized from data provided by the server), it could be as simple as:
var token = privileged;
Then I set stateSaveParams to record the token when the state is saved:
stateSaveParams: function (settings, data) {
data.myapp_token = token;
}
The prefix myapp_ is just there to avoid possible collisions with DataTable's own fields.
I set stateLoadParams so that if the current value of token differs from what has been recorded before, the state is cleared:
stateLoadParams: function (settings, data) {
if (data.myapp_token !== token) {
this.api().state.clear(); // Clears the state.
return false; // Tells DataTables to not use the state that was stored.
}
// This return is here to keep the IDE happy but does not do anything special.
return undefined;
},
I've just set token to the single condition I've shown in my question (privileged) in this example but in production I use a combination of variables plus a local version number so I can bump the value of token as needed if I do something that requires clearing the state but cannot be detected just as a privilege change.

Can I add a promise/unmaterialized record to a hasMany while I wait for it to be retrieved?

Back in the unversioned Ember Data days (e.g. "rev 12" maybe) I'm pretty sure you could do this:
var comment = App.Comment.find(42); // Already exists, but not yet loaded...
post.get('comments').addObject(comment);
Because App.Comment.find(42) would return an App.Comment object, albeit one with no fields populated except it's ID. (I don't remember the details of how you'd then save the App.Post--i.e. if you could or couldn't save it until the comment object was completely loaded…I never got that far.)
Why this was neat is that if your template rendered post.comments, a new row/div would appear immediately that could check isLoaded to display a loading indicator and show instantly that a new record was attached while waiting for the record's data to load. This is/was a selling point of Ember/Ember Data, and one I really like.
But this doesn't work now in 1.0.0-beta.2 beta.4 beta.5:
var comment = controller.get('store').find('comment', 42);
post.get('comments').addObject(comment); // Fails
Because controller.get('store').find('comment', 42) returns a promise, and if I try to add it to the hasMany it complains that I can only add App.Comment objects to the relationship.
Is it still possible to do something like this, so that my template which renders the comments immediately updates with a new record, but asynchronously populates its data?
(Please ignore that it doesn't make sense to add an already existing comment to a post--using the ubiquitous example scenario is easier than posting all my model code. Thanks!)
Okay, I came up with at least one way that does it:
var comment = controller.get('store').find('comment', 42);
var inFlightRecord = controller.get('store').getById('comment', 42);
controller.get('comments').addObject(inFlightRecord);
To be safer, maybe:
var comment = controller.get('store').find('comment', 42);
var inFlightRecord = controller.get('store').getById('comment', 42);
if(inFlightRecord){ // should be null if it isn't in the store
controller.get('comments').addObject(inFlightRecord);
} else {
// add a then block to the promise to make sure it gets added later
}
It seems that getById returns the "unloaded" object like we used to get from App.Comment.find(42), and the object still has an isLoaded property you can check to show loading status in your template.
I'm not sure if this is supposed to be supported behavior that I can rely on going forward (I suppose arguably nothing is, until 1.0 release), but it seems to work. I even checked that the object returned by getById === the object fulfilled in the promise. So this seems to be a good solution.
Anyone see a problem with this, or have a better way?