How do you update Task Labels? - podio

I need to update Task labels.
I get the task, I can step through the PodioCollection of labels ($task->labels)
I remove a label
$this->labels->remove($labelToRemove->label_id);
I add a label
$newLabel = new PodioTaskLabel();
$newLabel->text = $labelText;
$task->labels[] = $newLabel;
I then save the $task
$task->save();
The $task is saved, but the updated Task Labels are not.
The documentation here makes no sense:
https://developers.podio.com/doc/tasks/update-task-labels-151769
It says "Updates the task with new labels" at the top.
It also says you call it with:
/task/{task_id}/label/
But you call it with:
PodioTaskLabel::update( $label_id, $attributes = array() );
Huh? Why does it say in one place it is called with {task_id} but then down below, say it is called with $label_id.
In the PHP code it links to, it has this:
return Podio::put("/task/label/{$label_id}", $attributes);
Which causes me to believe the documentation is wrong.
Where in that ::update() call do I pass the task_id of the Task I want to update?
Or is there some other way to update task labels that is just undocumented?
-- Andrew.

It seems to be a bug in php client. Same code for Ruby works just great:
Podio::Task.update_labels(task_id, ['test label'])
Feel free to fix php client and submit pull request with fix.

Related

SubmitForm then Patch results in "The data returned by the service was invalid"

I'm building a PowerApps app on Azure SQL
The requirement
I have a form which has "Save" and "Confirm" buttons.
Both buttons should save the form data. The Commit button should also set database column "Confirm" to 1
I've read at length about how I can programatically override the update value of a hidden control for this. But I'm not satisfied with the level of complexity (maintenance) required to get this working, i.e.
Populate a variable with the current db value
In the button code set the variable value
In the form field, set the update property to the variable
What I'm Trying
So I'm trying a different approach: SubmitForm then Patch. Even though this requires an extra database call, I'd like to understand if this will work. This is the code for OnSelect in the commit button:
// Save the record
SubmitForm(frmEdit);
// Update confirmed to 1
Patch('[dbo].[Comments]',cRecord,{Confirmed:1});
Some Complexities
Note that my record is a variable, cRecord. In short I want this app to be able to upsert based on URL parameters.
This is my App.OnStart which captures URL values, inserts a record if required. Regardless, the result of this event is that cRecord is set to the record to be edited.
// Cache employees and store lookups (as they are in a different db)
Concurrent(Collect(cEmployees, Filter('[dbo].[SalesPerson]', Status = "A")),Collect(cStores, '[dbo].[Store]'));
// Check for parameters in the URL. If found, set to Edit/Add mode
Set(bURLRecord,If((!IsBlank(Param("PersonId")) && !IsBlank(Param("Date"))),true,false));
// If URL Parameters were passed, create the record if it doesn't exist
If(bURLRecord,
Set(pPersonId,Value(Param("PersonId")));
Set(pDate,DateValue(Param("Date")));
// Try and find the record
Set(cRecord,LookUp('[dbo].[Comments]',SalesPersonId=pPersonId && TransactionDate = pDate));
If(IsBlank(cRecord),
// If the record doesn't exist, create it with Patch and capture the resulting record
Set(cRecord,Patch('[dbo].[Comments]',Defaults('[dbo].[Comments]'),{SalesPersonId:pPersonId,TransactionDate:pDate}))
);
// Navigate to the data entry screen. This screen uses cRecord as its item
Navigate(scrEdit);
)
frmEdit.Item is set to cRecord. As an aside I also have a gallery that sets this variable value when clicked so we can also navigate here from a gallery.
The navigating using new and existing URL parameters works. Navigating from the gallery works.
The problem
When I press the Commit button against a record which has Confirmed=0 I get this popup error:
The data returned by the service is invalid
When I run this code against a record which already has Confirmed=1 I don't get an error
If I run the PowerApps monitor it doesn't show any errors but it does show some counts being run after the update. I can paste it here if required.
I also tried wrapping the Path in a Set in case it's result was confusing the button event but it didn't make a difference.
What I want
So can anyone offer me any of the following info:
How can I get more info about "The data returned by the service is invalid"?
How can I get this to run without erroring?
Is there a simpler way to do the initial upsert? I was hoping a function called Patch could upsert in one call but it seems it can't
With regards to the setting field beforehand approach, I'm happy to try this again but I had some issues implementing it - understanding which control where to edit.
Any assistance appreciated.
Edit
As per recommendations in the answer, I moved the patch code into OnSuccess
If(Confirmed=1,Patch('[dbo].[CoachingComments]',cRecord,{Confirmed:1}));
But now I get the same error there. Worse I cleared out OnSucces and just put SubmitForm(frmEdit); into the OnSelect event and it is saving data but still saying
The data returned by the service was invalid
First things first,
Refactoring has multiple steps,
I can t type all out at once...
The submitform and patch issue:
Never use the submitforn with extra conplexity
Submitform is only the trigger to send the form out,
The form handler will work with your data...
If you hsven t filled out the form correctly, u don t want to trigger your patch action...
So:
On your form, you have an OnSucces property,
Place your patch code there...
Change your cRecord in your patch statement:
YourForm.LastSubmit

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"

PsychoPy Builder - How to I take a rest part way through a set of trials?

In PsychoPy builder, I have a lot of trials and I want to let the participant take a rest/break part way through and then press SPACE to continue when they're ready.
Any suggestions about how best to do this?
PsychoPy Builder uses the TrialHandler class and you can make use of its attributes to do control when you want to take a rest.
Assuming you're trial loop is utilising an Excel/csv file to get the trial data then make use of trialHandler's attribute : thisTrialN
e.g.
1/ Add a routine containing a text component into your loop (probably at the beginning) with your 'now take a rest...' message and a keyboard component to take the response when they are ready to continue.
2/ Add a custom code component as well and place something similar to this code into its "Begin Routine" tab:
if trials.thisTrialN not in [ int(trials.nTotal / 2) ]:
continueRoutine=False
where 'trials' is the 'name' of your trial loop.
The above will put a rest in the middle of the current set of trials but you could replace it with something like this
if trials.thisTrialN not in [10,20]:
continueRoutine=False
if you wanted to stop after 10 and again after 20 trials.
Note, if you're NOT using an Excel file but are simply using the 'repeat' feature of a simple trial loop, then you'll need to replace thisTrialN with thisRepN
If you're using an Excel file AND reps you'll need to factor in both when working out when you want to rest.
This works by using one of Builder's own variables - continueRoutine and sets it false for most trials so that most of the time it doesn't display the 'take a rest' message.
If you want to understand more, then use the 'compile script' button (or F5) and take a look at the python code that Builder generates for you.

Maximo - Adding elements to a CustomMboSet using scripting

Is it possible to add to a CustomMboSet in Maximo using scripting? I am writing a custom application using a custom object called TIMESHEET. As part of the application I am writing a (Jython) script that needs to dynamically build up an MboSet (a set of TIMESHEETs). The code retrieves an existing CustomMboSet and attempts to add elements to it. It works when using an out of box MboSet, but when I try to run the same code on a custom MboSet it does not seem to work. No error is thrown, but code below the offending line is not run.
In other words, this works (LABTRANS is an out of box MBO):
myMboSet = mbo.getMboSet("LABTRANS")
newMbo = myMboSet.add()
# Set attributes on newMbo, everything is happy
But this does not (TIMESHEET is a custom MBO):
myMboSet = mbo.getMboSet("TIMESHEET")
newMbo = myMboSet.add()
# Code does not execute after the above line
Anyone have any insight as to why I am seeing this behavior? Does the Maximo scripting framework simply not support the dynamic building up of CustomMboSets? Any help is appreciated. Thanks.
You need to make sure that the relationship exists between the Current MBO and the Custom MBO in the database configuration otherwise it will not work.
Alternatively you can use the following code to create an new mboSet on the fly:
timeSheetMboSet = mxServer.getMboSet("TIMESHEET", userInfo)
mbo.getMboSet(RELATIONSHIPNAME).
LABTRANS and TIMESHEET must be the relationship names to the object in auto script.
If you want to get/add records in any object, use
mxServer.getMboSet(OBJECTNAME, userInfo)
A bit more explanation. You can create your own custom relationship from within your automation script. The trick is to make sure it's not already existing. That's why I use a dollar sign for mine.
variable = mbo.getMboSet(tempRelationshipName,Object,where clause)
previousPhaseSet = mbo.getMboSet("$wophasetranstemp1", "exitdate is null")

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?