Dynamic Widgets in Dashing - dashing

I'm new to using ruby and Coffee script but I have managed to get as far as displaying data within a single widget.
I am trying to think logically how would one go about creating a widget for each entry from a collection.
Does anyone know how to go about creating widgets after calling a service and getting a collection of data.
For example:
entries: [
{
name: "bob",
age: 21
},
{
name: "alex",
age: 42
},
{
name: "fred",
age: 35
}
]
I want to be able go through each of these and create a widget for each of these entries. Is this possible?

This is easy enough. From any of the Ruby scripts you have in your jobs folder, you'll typically update a widget with a send_event call, like so:
send_event(widget.to_s, bus_info)
This will update the appropriate widget. A job, however, can make this call as much as is useful, so could update dozens of widgets in its run. You could just loop through your list and run send_event() for each item in your list. Play with it and if you get stuck, let me know and I can put together a bigger example, but hopefully you can use the above to get you going.

Here's a more full example from our zendesk widget set.
def update_dashing(view, value)
puts 'sending ' + view + ' : ' + value.to_s
send_event('zendesk-' + view, current: value, status: 'normal',
service: 'Zendesk')
end
def update_zendesk(views)
counts = zendesk_client.view_counts(ids: views, path: 'views/count_many')
counts.all do |ct|
next unless ct.fresh
update_dashing(ct.view_id.to_s, ct.value.to_i)
end
end
The zendesk_client.view_counts() function returns a list of <view_id>:<count> pairs that we then loop through.

Related

add a map inside map and retrieve it from Firestore - Flutter

The scenario is, am trying to record a history of the challenges that user have participated in, the history only takes name, date, and isWin information from the challenge which will be showed later on "my Challenges" page for each user.
after a while thinking on how to solve this problem i came up with the logic of adding a map to the user model called challengesHistory, inside this map the information of each challenge that user participated in will be stored as another map inside the big map so it will become something like this:
Map challengeHistory = {
"challenge-1": {"name": "", "date": "", "isWin": ""}
}
i have added the map to the user model correctly, now my problem is how to add new map each time user clicks on "participate" so it becomes:
Map challengeHistory = {
"challenge-1": {"name": "", "date": "", "isWin": ""}
"challenge-2": {"name": "", "date": "", "isWin": ""}
}
and each time user participate in a challenge it adds challenge-4 ,5 ,6 ... and so on
code of the button when user clicks on "participate":
FirebaseFirestore.instance.collection("Users").doc(user!.uid).update({
'points': loggedInUser.points! + 3,
'challenges': loggedInUser.challenges! + 1,
'challengeMember': FieldValue.arrayUnion([widget._challengeName]),});
so using this code how can i add a new map inside "challengeHistory" map.
my second question is if i want to retrieve an information like the name of the fourth challenge how can i do that.
last thing how to iterate the whole "challengeHistory" map and print each challenge information.
i would be thankful for help.
Try make challengeHistory a List<Map> so you can simply call challengeHistory.add() to add other challenges (Map).
Then you can also call challengeHistory[3]["name"] to get for example the name of the fourth challenge.
You can also loop through each challenge inside of the list:
for(var c in challengeHistory)
{
print(c["name"]);
print(c["date"]);
print(c["isWin"]);
}

AG Grid Row-Grouping for showing version history of data

I'm a first time user of AG Grid and need some help identifying how to configure Row Grouping for my AG Grid in such a way that allows me to see my data group as a timeline/audit history. Was reading through the docs and haven't found an example on there that resembles what I'm looking for.
I have rowData that contains history and the visual expectation is that, the same base columnDefs assigned to the grid are used for the main "group" row (that contains the expand/collapse chevron) and all the expanded rows as well -- so there is no need for a "group column"
Anyone know how I can achieve this outcome? I have also looked at treeData and masterDetail but those didn't work out for me.
P.S. I don't rule out the possibility that I could be misreading/misunderstanding the AG Grid docs so any help there is appreciated.
EDIT: After fiddling around with things further, I believe I'm looking for a combination of two things:
The isRowMaster to enable expand/collapse on the main parent entry.
The groupDisplayType="groupRows" setting (minus the default row group cell because that would be handled by my master row from Point 1 instead)
After much head banging, turns out the solution was to use treeData. What I ended up creating was treeData containing only one level children.
Parent Node (expand/collapse)
child 1
...
child n
The other key was understanding how to structure your rowData and returning the proper dataPath to feed into the getDataPath handler for treeData. AG Grid expects a flat-list for rowData -- I say this as I was not able to get things working when having a nested tree structure like the following.
const mainRecord = {
id: "abc"
foo: 1,
bar: 2,
history: [
{ foo: 3, bar: 4 },
{ foo: 5, bar: 6 }
]
}
I had to modify my data structure above to return the history items as a flat list alongside the main record that I eventually sent as rowData. The other thing I had to do was add some hierarchy property to my objects to denote its placement in the tree. The hierarchy value is what I supplied to getDataPath
const rowData = [
{ id: "abc", foo: 1, bar: 2, hierarchy: ["abc"] }, // parent
{ foo: 3, bar: 4, hierarchy: ["abc", "34"] }, // child 1
{ foo: 5, bar: 6, hierarchy: ["abc", "56"] }, // child 2
]
After doing the above changes, I was able to get the expected visual outcome I was looking for. I think the big takeaway I got from this is as a first time user of AG Grid is, let it take care of grouping of your data on your behalf (as opposed to doing it yourself via structuring your models with some internal nested children structure)

How to filter an array of object in Mui DataGrid?

I recently changed my tables to Mui-datagrid on Material UI 5, and I have a special use case with an array of objects. I want to enable the phone number filter in this column, but the number is provided as an object list.
phone: [
{ type: "home", number: "795-946-1806" },
{ type: "mobile", number: "850-781-8104" }
]
I was expecting a 'customFilterAndSearch' or an option to customise how to search in this specific field.
customFilterAndSearch: (term, rowData) =>
!!rowData?.suppressedOptions.find(({ description }) =>
description?.toLowerCase().includes(term.toLowerCase())
),
I have made some tries with the filterOperators, but no success yet. I have made a full example here https://codesandbox.io/s/mui-data-grid-vs05fr?file=/demo.js
As far as I can see from the DataGrid documentation I don't see any way to change the filter function for a specific function.
Likely the best workaround for your use case will be converting this to a string be converting the data to a string before you pass it to the datagrid. Though you will lose the styling that you currently do by making the phone type bold.
On second though your best best would probably be to split the phone column into two columns which would probably be the cleanest way of solving your problem
Add helper function.
You could potentially add a helper function to just map all the phone lists to something like mobilePhone or homePhone
const mapPhoneObject = (rows) => {
rows.forEach((row) => {
row.phone.forEach((phone) => {
row[`${phone.type}Phone`] = phone.number;
});
});
return rows
};
I've added a fork of your snippet with my function, it is I think the most viable solution for your problem: https://codesandbox.io/s/mui-data-grid-forked-ppii8y

UI5: get path for new object in model

I often have some kind of master-detail situation where i try to use a single model for both master and detail view.
The detail page is bound directly to an element in the list with .bindElement(path) when you select an item in the list. The path is available from the binding context. Everyone is happy:
//click handler for list item:
var context = this.getBindingContext();
oDetailPage.bindElement(context.getPath());
oApp.toDetail(oDetailPage);
The challenge is when the list page has an "add" button. I create a new object and put that into the model. But how do I find the path? i have no context:
//click handler for "add" button
var newStuff = {
propA: "foo",
propB: 13
};
oModel.setData(oModel.getData().concat(newStuff));
oDetailPage.bindElement(/* What??? */);
oApp.toDetail(oDetailPage);
I've searched for a .findPath(newStuff) method but no such thing exists
Hi, unfortunatly I am unable to test this but I think this should work
The binding path is pretty much pointer to a specific entry in a collection. The path value does depend on a couple of variables, such as how your model is structured.
For example, if the Model data looks like this :
{"results" : [
{propA: "foo",
propB: 13
},
{propA: "ber",
propB: 14
}]
}
And you concat
{propA: "newItem",
propB: 15
}
I believe you binding path would be
"/results/2"
You can also, find the most recent index with something like
this.getModel("yourModel").getObject("results").length;
Edit -
Unless I miss understand your quesitons, your new entry should be at the end of the model.
here are 2 cases
//click handler for "add" button
var newStuff = {
propA: "foo",
propB: 13
};
// case 1: root of model data is an array
var oData = oModel.getProperty("/");
oData.push(newStuff);
oDetailPage.bindElement("/" + oData.length - 1);
// case 2: we appends to /results
var oData = oModel.getProperty("/results");
oData.push(newStuff);
oDetailPage.bindElement("/results/" + oData.length - 1);

Number of items limited to around 100

I've created the following Input field.
var oCityInput = new Input({ // sap/m/Input
showSuggestion: true,
showTableSuggestionValueHelp: true,
suggestionItems:{
path: "/cities",
template: new ListItem({ // sap/ui/core/ListItem
text: "{cname}",
additionalText: "{provi}"
}),
},
});
The "cities" array contains around 8400 record, but when I type some character the suggestion function it seems that is looking for only in the first 100 items of the array.
I've created an example in jsbin. If you try to looking for the first elements it works... but if you try to type the last city the suggestion will not come out.
In newer versions of SAP UI5 the JSONModel also supports the setSizeLimit() method:
model.setSizeLimit(iNumOfYourJsonEntries);
API description: "Set the maximum number of entries which are used for list bindings."
Be careful because it can lead to performance issues.