Bundle Cover not shown when first - google-mirror-api

I have a bundle with a timeline card inside. The main timeline card which I want to be the cover is set to be the cover(isBundleCover=true). However when the cards are inserted and the user taps to see or looks up to activate the display the inner bundle card(not cover) is shown first. Is there a way to show the cover first? Is this acting as intended? I've tried changing the order of cards inserted and did not make a difference.
Credential credential = AuthUtil.getCredential(id);
Mirror service = MirrorClient.getMirror(credential);
boolean newNotification = false;
TimelineItem timelineItem = null;
TimelineItem notesTimelineItem = null;
List<TimelineItem> oldCards = null;
oldCards = service.timeline().list()
.setBundleId(String.valueOf(call.getId()))
.execute().getItems();
if (oldCards != null)
if (oldCards.size() < 1) {
timelineItem = new TimelineItem();
notesTimelineItem = new TimelineItem();
timelineItem.setId(String.valueOf(call.getId()));
timelineItem.setBundleId(String.valueOf(call.getId()));
notesTimelineItem.setBundleId(String.valueOf(call.getId()));
timelineItem.setIsBundleCover(true);
newNotification = true;
timelineItem.setHtml(TimeLineHTMLFactory.getDispatchCard( call.getType(), call.getAddress(), call.getUnits(),String.valueOf(call.getLat() / 1E6), String.valueOf(call.getLongi() / 1E6)));
if (call.getNotes().contentEquals("")) {
notesTimelineItem.setText("Notes not available");
} else {
notesTimelineItem.setText(call.getNotes());
notesTimelineItem.setTitle("Notes");
}
notesTimelineItem.setSourceItemId("notes");
Location incident = new Location();
incident.setLatitude(call.getLat() / 1E6);
incident.setLongitude(call.getLongi() / 1E6);
notesTimelineItem.setLocation(incident);
List<MenuItem> menuItemList = new ArrayList<MenuItem>();
menuItemList.add(new MenuItem().setAction("NAVIGATE"));
menuItemList.add(new MenuItem().setAction("TOGGLE_PINNED"));
notesTimelineItem.setMenuItems(menuItemList);
} else {
for (int i = 0; i < oldCards.size(); ++i) {
log.log(Level.WARNING, "updating oldCard: "
+ oldCards.get(i).getId());
log.log(Level.WARNING,"sourceItemId: "+oldCards.get(i).getSourceItemId());
boolean isCover=false;
try{
isCover=oldCards.get(i).getIsBundleCover();
}catch(Exception e){
log.log(Level.WARNING,"Exception getting isBundleCover: "+e.getMessage());
}
if (isCover) {
// MAIN DISPATCH CARD
oldCards.get(i)
.setHtml(
TimeLineHTMLFactory.getDispatchCard(
call.getType(), call
.getAddress(), call
.getUnits(),
String.valueOf(call
.getLat() / 1E6),
String.valueOf(call
.getLongi() / 1E6)));
} else if (oldCards.get(i).getSourceItemId()
.contains("notes")) {
if (call.getNotes().contentEquals("")) {
oldCards.get(i).setText("Notes not available");
} else {
oldCards.get(i).setText(call.getNotes());
}
oldCards.get(i).setTitle("Notes");
Location incident = new Location();
incident.setLatitude(call.getLat() / 1E6);
incident.setLongitude(call.getLongi() / 1E6);
if(incident!=null){
oldCards.get(i).setLocation(incident);
}
List<MenuItem> menuItemList = new ArrayList<MenuItem>();
menuItemList.add(new MenuItem()
.setAction("NAVIGATE"));
menuItemList.add(new MenuItem()
.setAction("TOGGLE_PINNED"));
oldCards.get(i).setMenuItems(menuItemList);
}
}
}
if (oldCards.size() > 0) {
for (TimelineItem card : oldCards) {
log.log(Level.WARNING,
"oldCard id: " + card.getId()
+ " bundleid: "
+ card.getBundleId());
service.timeline().update(card.getId(), card)
.execute();
}
} else {
log.log(Level.INFO, "New notification here");
timelineItem.setNotification(new NotificationConfig().setLevel("DEFAULT"));
MirrorClient.insertTimelineItem(credential, notesTimelineItem);
MirrorClient.insertTimelineItem(credential, timelineItem);
}
JSON for Cover card:
{
"kind": "mirror#timelineItem",
"id": "710a9f44-92e7-463e-801d-940b59aebb8e",
"bundleId": "5808701407494144",
"isBundleCover": true,
"created": "2013-10-28T13:30:19.160Z",
"updated": "2013-10-28T13:30:19.160Z",
"etag": "1382967019160",
"html": "\n \n \n\n \n \n \n E M S\n \n741 PARK AVE\n\n \n \n\n",
"notification": {
"level": "DEFAULT"
}
}
JSON for Notes Card:
{
"kind": "mirror#timelineItem",
"id": "cfd7173f-4757-4e2e-9f2e-fbcbba2c0e99",
"bundleId": "5948571312455680",
"created": "2013-10-28T13:30:09.904Z",
"updated": "2013-10-28T13:30:09.904Z",
"etag": "1382967009904",
"title": "Notes",
"text": "Notes go in here...",
"location": {
"kind": "mirror#location",
"latitude": 37.922223,
"longitude": -87.805731
},
"menuItems": [
{
"action": "NAVIGATE"
},
{
"action": "TOGGLE_PINNED"
}
]
}

I think you are halfway there, I would add the bundle cover last and then isBundleCover=True.
See below.
To bundle timeline items, create them with the same value for bundleId. The most recently added item is the bundle's cover card.
Note: To set a specific timeline item as the bundle cover card, set its isBundleCover property to true.

Appears this a bug. Create ticket on tracker:
https://code.google.com/p/google-glass-api/issues/detail?id=233

This is expected behavior. When bundles are inserted you will be displayed the most recently inserted card within the bundle.
If you'd like to display a collection of cards, consider using HTML Pagination instead. Your markup for a card might look something like this:
<article class="cover-only">
<section>
<p>Cover page</p>
</section>
</article>
<article>
<section>
<p>Second page</p>
</section>
</article>
<article>
<section>
<p>Third page</p>
</section>
</article>

Related

this.setState is only pulling last value in array

I'm VERY new to React and not sure how to render this nested array from an external JSON file. remittance is the only array here one that has nested values that I need to access and render. It logs to the console fine, but won't separate on setState. I apologize if this looks terrible.
class App extends Component {
constructor(props){
super(props);
this.state = {
data,
rName: "",
rDescription: "",
}
}
componentDidMount(){
console.log("Mounted!");
this.display();
};
display = () => {
for (var i = 0; i < data.length; i++){
var remittanceList = data[i].Remittance;
// console.log(remittanceList);
for (var x = 0; x < remittanceList.length; x++){
var rName = remittanceList[x].PayorName;
var rDescription = remittanceList[x].Description;
console.log(rName + rDescription);
this.setState({rName, rDescription});
}
}
}
render() {
var { rName, rDescription } = this.state;
return (
<div className="App">
<Title/>
{this.state.data.map((each, index) => (
<PayInfo key={index}
name={each.Payee.Name}
fax={each.Payee.Fax}
pan={each.Payment.PAN}
cvv={each.Payment.CVV}
exp={each.Payment.Exp}
payorName={rName}
description={rDescription}
/>
))}
</div>
);
}
}
export default App;
And the JSON file is something like this. Because the amount of remittances can very, I can't hardcode in an index to look for every time.
[
{
"Payee": {
"Name": "Bob",
"Fax": "5555555555",
},
"Payment": {
"PAN": 123456,
"CVV": 123,
"Exp": "1/2018"
},
"Remittance": [
{
"PayorName": "Me",
"Description": "Hello World.",
},
{
"PayorName": "You",
"Description": "Hey world.",
},
{
"PayorName": "Snoop",
"Description": "Bye world.",
}
]
},
And this is the PayInfo.js file I should've posted initially! Not sure if this changes any of the answer I got before?
import React from "react";
import "./PayInfo.css";
const PayInfo = props => (
<div>
<div id="payee">
<p>Payee</p>
<p>{props.name}</p>
<p>Fax: {props.fax}</p>
</div>
<hr></hr>
<div id="payment">
<p>Payment</p>
<p>PAN: {props.pan}</p>
<p>CVV: {props.cvv}</p>
<p>Exp: {props.exp}</p>
</div>
<hr></hr>
<div id="remittance">
<p><strong>Remittance(s)</strong></p>
<p>Payor: {props.payorName}</p>
<p>Description: {props.description} </p>
</div>
<hr></hr>
<hr></hr>
</div>
);
export default PayInfo;
In your display method, you are setting the state inside for loop. so only the last value being set to the state.
Please try the below code.
display = () => {
let totalRemittanceArray = []
for (var i = 0; i < data.length; i++) {
var remittanceList = data[i].Remittance;
for (var x = 0; x < remittanceList.length; x++) {
var rName = remittanceList[x].PayorName;
var rDescription = remittanceList[x].Description;
console.log(rName + rDescription);
totalRemittanceArray.push({ rName, rDescription })
}
}
this.setState({totalRemittanceArray})
}
What you might want to do is something like this:
https://codesandbox.io/s/p36jlrz7jj
As you can see I extracted another component PayerInfo. Also React works perfect with map within the render method. I hope my example helps!
Currently you call setState in the for loop and thus overwrite the state every time, but I guess you figured that one out already. I use Array.map to loop over elements within JSX a lot. Dunno if one could do this more nicely, but there is always a possibility to improve ^^
A small improvement here: You could loop in a separate function first and then return the complete Array: https://reactjs.org/blog/2017/09/26/react-v16.0.html

Using jQuery to change css in option tags does not work until second click in Angular

I have a edit button that opens a bootstrap modal to edit a record:
<a href="#" ng-click="getAction(action.id, 'edit')"
data-toggle="modal" data-target="#modalEditAction"
class="functionalLinks">
<i class="glyphicon glyphicon-pencil"></i>
EDIT
</a>
getAction(action.id, 'edit') looks like this:
$scope.getAction = function (actionId, populateObject) {
$http.get(actionUrl + '/' + actionId)
.then(function (response) {
// Test front end exception message;
// throw "test exception";
switch (populateObject) {
case "details":
$scope.data.actionDetails = response.data;
break;
case "edit":
$scope.data.editAction = response.data;
$scope.dimAt1EditActionRecommendedByLerSelections();
break;
}
})
.catch(function (error) {
$scope.data.actionDetailsError = error;
});
}
So we are interested in the "edit" case of the switch:
The response data looks like this (Look at the actionsRecommendedByLer property):
{
"caseId": 8,
"case": null,
"actionTypeId": 1,
"actionType": {
"actionTypeName": "Actions Taken By Management",
"caseType": 1,
"id": 1
},
"dateCreated": "2017-05-08T14:55:23.797",
"actionStatus": 3,
"notes": "bngfhfrg455",
"actionType1Id": null,
"actionType1": {
"actionId": 1,
"actionsRecommendedByLer": [
{
"actionType1Id": 1,
"lookUpDetailId": 4,
"name": "Alternative Discipline Agreement in lieu of # day Suspension",
"id": 1
},
{
"actionType1Id": 1,
"lookUpDetailId": 7,
"name": "Arbitration",
"id": 2
},
{
"actionType1Id": 1,
"lookUpDetailId": 13,
"name": "Complaint - EEO Formal",
"id": 3
}
],
"actionProposedBySupervisorId": 4,
"actionProposedBySupervisor": {
"id": 4,
"displayValue": "Alternative Discipline Agreement in lieu of # day Suspension",
"code": "",
"parentId": null,
"externalSystemId": null,
"isInactive": false,
"inactivDate": null,
"sortOrder": null,
"discriminator": "",
"lookupMaster": null,
"lookUpMastersId": 1
},
"actionTakenBySupervisorId": 8,
"actionTakenBySupervisor": {
"id": 8,
"displayValue": "AWOL Letter (CORPS)",
"code": "",
"parentId": null,
"externalSystemId": null,
"isInactive": false,
"inactivDate": null,
"sortOrder": null,
"discriminator": "",
"lookupMaster": null,
"lookUpMastersId": 1
},
"actionCharges": [
{
"actionType1Id": 1,
"lookUpDetailId": 211,
"name": "Creating hostile work environment",
"id": 1
}
],
"actionEffectiveDate": "2017-05-16T04:00:00",
"id": 1
},
"actionType17Id": null,
"actionType17": null,
"id": 1
}
And I use the response data to show a table with detete buttons basically showing which Select Options are chosen like this:
<select class="pull-right" id="editActionRecommendedByLerSelect"
ng-model="data.editAction.actionType1.actionRecommendedByLerId">
#*<option value="0"></option>*#
<option value="{{managmentAction.id}}"
ng-repeat="managmentAction in data.managementActions">
{{managmentAction.displayValue}}
</option>
</select>
<br />
#*{{data.editAction.actionType1.actionRecommendedByLerId}}*#
<table class="table table-condensed table-bordered">
<tr ng-show="data.editAction.actionType1.actionsRecommendedByLer.length == 0">
<td colspan="2" class="noResultText">No Actions Recommended By LER</td>
</tr>
<tr ng-repeat="actionRecommendedByLer in data.editAction.actionType1.actionsRecommendedByLer">
<td>
<a href="#" ng-click="removeAnEditActionRecommendedByLerFromActionType1(actionRecommendedByLer.id)"
class="functionalLinks text-danger">
<i class="glyphicon glyphicon-trash"></i>
DELETE
</a>
</td>
<td>#*{{actionRecommendedByLer.id}} :*# {{actionRecommendedByLer.name}}</td>
</tr>
</table>
The select is populated by an array of choices. The choice ID will match the appropritate lookupDetailId of the actionRecommendedByLer id. in the collection.
This line in the "edit" case of the switch in $scope.getAction(actionId, populateObject):
$scope.dimAt1EditActionRecommendedByLerSelections();
calls this:
$scope.dimAt1EditActionRecommendedByLerSelections = function () {
console.log("In dimAt1EditActionRecommendedByLerSelections");
console.log("Length: " + $scope.data.editAction.actionType1.actionsRecommendedByLer.length);
var element;
for (i = 0; i < $scope.data.editAction.actionType1.actionsRecommendedByLer.length; i++) {
console.log("i: " + i);
console.log("id: " + $scope.data.editAction.actionType1.actionsRecommendedByLer[i].lookUpDetailId);
element = $('#editActionRecommendedByLerSelect option[value = "' + $scope.data.editAction.actionType1.actionsRecommendedByLer[i].lookUpDetailId + '"]');
element.attr('disabled', 'disabled');
element.css('background-color', 'yellow');
}
}
Basically I am using jQuery to make the multiple options already selected in the select drop down yellow and disabled. This was easy from my Add Bootstrap modal.
But loading it all back in for an edit and hightlighting the right ones is proving to be way more difficult.
This works and shows in the Select Drop Down the choice names highlighted in yellow and disabled in the model being rendered in a table next to a delete button. The only problem is it doesn't show the choices hightlighted until I click the edit button again.
How can I get this to hightlight and disable the options on the first edit click?
UPDATE 1 (In response to comment user1120808)
I tried your answer but it is not working. In fact now it does not even work on the second click.
Does this look like correct implementation of your suggestion?
$scope.dimAt1EditActionRecommendedByLerSelections = function () {
console.log("In dimAt1EditActionRecommendedByLerSelections");
console.log("Length: " + $scope.data.editAction.actionType1.actionsRecommendedByLer.length);
var element;
for (i = 0; i < $scope.data.editAction.actionType1.actionsRecommendedByLer.length; i++) {
console.log("i: " + i);
console.log("id: " + $scope.data.editAction.actionType1.actionsRecommendedByLer[i].lookUpDetailId);
// force scope digest.
$scope.$evalAsync(() => {
element = $('#editActionRecommendedByLerSelect option[value = "' + $scope.data.editAction.actionType1.actionsRecommendedByLer[i].lookUpDetailId + '"]');
element.attr('disabled', 'disabled');
element.css('background-color', 'yellow');
});
}
}
The reason you don't see it, is because jquery runs outside of angular and angular doesn't pick it up. It isn't evaluated anymore. But with the second click you trigger a digest cycle, so you see it then. So what you need to do is force a digest cycle. You can use $evalAsync for this.
try the following:
$scope.$evalAsync(() => {
element = $('#editActionRecommendedByLerSelect option[value = "' + $scope.data.editAction.actionType1.actionsRecommendedByLer[i].lookUpDetailId + '"]');
element.attr('disabled', 'disabled');
element.css('background-color', 'yellow');
});
$timeout service solved the problem:
$scope.dimAt1EditActionRecommendedByLerSelections = function () {
console.log("In dimAt1EditActionRecommendedByLerSelections");
console.log("Length: " + $scope.data.editAction.actionType1.actionsRecommendedByLer.length);
$timeout(function() {
var element;
for (i = 0; i < $scope.data.editAction.actionType1.actionsRecommendedByLer.length; i++) {
console.log("i: " + i);
console.log("id: " + $scope.data.editAction.actionType1.actionsRecommendedByLer[i].lookUpDetailId);
element = $('#editActionRecommendedByLerSelect option[value = "' + $scope.data.editAction.actionType1.actionsRecommendedByLer[i].lookUpDetailId + '"]');
element.attr('disabled', 'disabled');
element.css('background-color', 'yellow');
}
}, 1000);
}

React Js select list to have own value

I have rows of selects lists, when I change a list on one row, the lists for the whole table column change, is there a way each select list can have its own selected option?
I an rendering each row component use the following schema:
tableRowScheme: [
{"column":"levelId",
"title":"Level",
"type": "select",
"optionData": this.state.gradeOptions,
"afterChange": this.onLevelSelect,
"className": "col-md-1"},
{"column":"subjectId",
"title":"Subject",
"type": "select",
"optionData": this.state.subjects,
"afterChange": this.onSubjectSelect,
"className": "col-md-1"},
Then Im rendering each select list
case 'select': {
var optionsData = cellData.optionData ? cellData.optionData : [];
if(cellData.isRowInEditMode && !cellData.isNonEditable) {
return (
<div>
<TableDropdown columnName={cellData.column}
staticElements={this.props.staticElements}
optionsData={optionsData}
staticElementId={cellData.selectTypeId}
defaultValue={parseInt(this.state.rowDataStack[cellData.column])}
className="input-sm"
handleSelect={this.onDropdownChange}/>
<Input type="hidden" ref={cellData.column} standalone={true}
defaultValue={parseInt(this.state.rowDataStack[cellData.column])} />
</div>
);
Then each dropdown has this.onDropdownChange :
onDropdownChange: function(data){
var localRowDataStack = _.cloneDeep(this.state.rowDataStack);
localRowDataStack[data.filterName] = data.filterVal;
this.setState({
rowDataStack: localRowDataStack,
isOmitReRender: false
});
for (var i=0; i<this.props.rowScheme.length;i++) {
if(this.props.rowScheme[i].afterChange != undefined && this.props.rowScheme[i].column == data.filterName) {
this.props.rowScheme[i].afterChange(data.filterVal);
break;
}
}
},

AngularJS filter already selected option from dynamic field

I have a form where you can add x number of fields. Each field contains option select. I want to filter out the already chosen option when this option is already chosen in one or multiples field before. Each field has a remove button and the form has 1 add button.
How can I filter out the dynamic fields?
Any help,guidance is most welcome.Thanks in advance. :)
This is how my HTML looks like:
<div data-ng-repeat="choice in choices">
<select data-ng-model="choice.option"
data-ng-options="item as item.Value for item in options">
</select>
<button data-ng-click="removeChoice(choice)">Remove choice</button>
<div>
<button data-ng-show="choices.length <= 4" data-ng-click="addNewChoice()">Add Choice</button>
</div>
</div>
And my controller:
$scope.options = [
{
"Key": "0",
"Value": "Select an option"
},
{
"Key": "Option1",
"Value": "Option1"
},
{
"Key": "Option2",
"Value": "Option2"
},
{
"Key": "Option3",
"Value": "Option3"
},
{
"Key": "Option4",
"Value": "Option4"
},
{
"Key": "Option5",
"Value": "Option5"
}
];
$scope.choices = [{ id: '1' }];
$scope.addNewChoice = function () {
var newItemNo = $scope.choices.length + 1;
$scope.choices.push({ id: newItemNo, option: $scope.option, value: $scope.value });
};
$scope.removeChoice = function () {
var index = $scope.choices.indexOf(choice);
$scope.choices.splice(index, 1);
};
ok
i can give simple recommendation which will be this.
1: add variable $scope.selectedOptions = [];
this will contain list of already selected options from all select elements .
2: create function $scope.AddSelectedOption(item);
this will add the selected object when we change option from any select element because we are going to use for all selects ng-change= "AddSelectedOption(item);"
3: add checkIfSelected(item); this will check if given object value is already selected or not ..
will user in
hope you understand what it will do just check like this
$scope.checkIfSelected = function (item) {
$scope.selectedFound = $scope.selectedOptions.filter(function
(option) {
if(option.value == item.value)
{
return day;
}
});
if($scope.selectedFound.length == 0 ) { return false; } else {
return true; }
}
This will return true if give item found in the options.
if not out.. you can invite me to help again .
This is possible. I'm explaining a basic version of this requirement. See the working example here http://plnkr.co/edit/S9yZpjhY55lXsuifnUAc?p=preview
What wer are doing is maintaining another options which is the copy of the original options. Copying the options will make it to not reference existing options since objects are pass by reference in Javascript.
The main logic is in this function, which modify the options on selection:
$scope.optionSelected = function(choice) {
$scope.availableOptions = $scope.availableOptions || angular.copy($scope.options);
if (choice.option) {
var index = -1;
// See if available options has that key
angular.forEach($scope.availableOptions, function(item, i) {
if (item.Key === choice.option.Key) {
index = i;
}
});
if (index > -1) {
// And then remove it
$scope.availableOptions.splice(index, 1);
}
}
};

How to select objects that have a certain atribute in a json file in an Angular JS project?

I have a link to an API which lists movies, each movie has title,id etc...
API: http://private-5d90c-kevinhiller.apiary-mock.com/angular_challenge/horror_movies
It also has an offers array inside which contains a 'provider_id' property.
I need to show how many movies are available at which provider.
But I dont know how, the best I came up with was:
{{movie.offers[0].provider_id}}
But that only shows the first provider on each movie.
What I want is to extract how many movies each provider has.
My Html:
<div ng-controller="ProviderController as provider">
<div ng-repeat="movie in provider.movies">
{{movie.offers[0].provider_id}}
</div>
</div>
My Main.js:
app.controller('ProviderController', function($http) {
var provider = this;
provider.movies = [];
$http({
url: 'some/path/horror_movies',
method: "GET",
}).success(function(data) {
provider.movies = data;
});
});
Also this is the structire of the json file:
[{
"id": 140524,
"title": "Dracula Untold",
"offers": [{
"provider_id": 2,
"retail_price": 14.99,
//...
}, {
"provider_id": 2,
"retail_price": 14.99,
}, {
"provider_id": 7,
"retail_price": 14.99,
}, ]
},
{
"id": 138993,
"title": "The Purge: Anarchy",
"offers": [
// ...
]
},
]
Any ideas ? Thanks.
You will need to change the structure of your database to have providers at the top level. A function achieving something like this should iterate over every movies offers, something like this:
function getProviders (movies) {
var providers = [],
movie = {},
offer = {};
for (var i = 0, max = movies.length; i < max; i += 1) {
movie = movies[i];
for (var j = 0; j < movies[i].offers.length; j += 1) {
offer = movie.offers[j];
if (typeof providers[offer.provider_id] === 'undefined') {
providers[offer.provider_id] = { movies: [] };
}
providers[offer.provider_id].movies.push(movie);
}
}
return providers;
}
I started a fiddle here: http://jsfiddle.net/d29tu8fg/1/
Before adding a movie to a provider, you might also want to check, if that movie already exists. You only need to do that though, if – like in your data – a movie can have two different offers from the same provider.
Add the providers to the $scope and in your view show the length:
<div ng-repeat="provider in providers track by $index">
{{provider.movies.length}}
</div>

Resources