I'm trying to build an Alexa skill that connects to Jira. A while back when I started The interaction model in the Alexa Skills Kit was working fine and picked up multiple slot values in one statement, even if it wasn't asked for. For example, "Open a user story in the BLAH project and assign it to Blah" would work and pick up the {ticketType}, {project}, and {assignee} slot values flawlessly. Now I've started using the Dialog.Delegate directive in ASK to allow the interaction model to figure out what it doesn't yet have and keep asking questions until all required slots are filled. Some time after I implemented this, the interaction model stopped recognizing other slot values in utterances that were intended for just one slot value to be filled. If I open the skill with a request like the above, it then asks me what the ticket type is, like I didn't already give it. I have defined sample utterances for my intent in the interaction model and all start with "Open a {TicketType}", so the fact that it still asks me for the ticket type when it's given in the input makes no sense to me.
My suspicion is that it has something to do with the way I'm returning the Dialog.Delegate directive. In my code linked below, I'm calling a function AddDialogDirective func(dialogType string, intent *Intent) which is in an open source framework I am using called alexa-skills-kit-golang. I can confirm that the Dialog.Delegate directive is actually called correctly because in the response from my lambda function I am seeing the Dialog.Delegate directive set.
{
"body": {
"version": "1.0",
"response": {
"directives": [
{
"type": "Dialog.Delegate"
}
],
"shouldEndSession": false
}
}
}
I've tried modifying the AddDialogDirective function to be func(dialogType string, slotToIllicit *string, slotToConfirm *string, intent *Intent) instead, thinking that the framework was somehow returning empty strings in the SlotToIllicit and SlotToConfirm JSON fields instead of not returning those fields, but no luck. I was thinking that returning empty strings here might be making the interaction model that it should be illiciting only one slot at a time and ignoring the dialog model. Do you think this is the issue or could it be something completely different?
Related
I currently have an action that creates a new link between an object of type A, named OA, and an object of type B, named OB.
Our workflow has a constraint such that any object of type B can at most, be linked to 4 objects of type A. As such, I would like to define a submission criterion in the action such that submission is blocked if OB is already linked to 4 objects of type A.
I couldn't find a straightforward way to do this using the Action configuration UI. How could I accomplish this?
The easiest way to accomplish this would be to turn your action into a function backed action. This would allow you to take the following steps to accomplish the desired functionality:
You can search around to all objects of type A that are linked to OB by writing something like:
// Search around to all objects of type A that are linked to OB
const linkedObjects = OB.objectTypeA.all();
// Now get the number of linked objects
const numLinkedObjects = linkedObjects.length;
Prevent the function from running by throwing a UserFacingError if there are more than 4 linked objects
if (numLinkedObjects >= 4) {
throw new UserFacingError("Objects of type B cannot be linked to more than 4
objects of type A");
}
For reference, here are some relevant pages in Foundry’s documentation:
Creating Function Backed Actions (https://www.palantir.com/docs/foundry/action-types/function-actions-getting-started/#getting-started)
Accessing link types in Functions (https://www.palantir.com/docs/foundry/functions/api-objects-links/#link-types)
Throwing UserFacingErrors from Functions (https://www.palantir.com/docs/foundry/functions/user-facing-error/)
While you can certainly do this in a Function-backed action, the tradeoff is that you won't get up front validation of the criteria, but rather the user will submit the action and then will received a toast showing the UserFacingError text. So while this technically achieves the validation, it is a sub-par user experience compared to disabling the button with a message or otherwise catching the condition upstream of the action itself in the workflow.
An alternative, iff you're using the action exclusively through Workshop, (this won't work if you want the action to "stand alone" in object explorer), you can create an object set variable that holds the result of the search around and pass that in as a hidden parameter to the Action. You can then set up the Action submission criteria as normal to check the length of that parameter and provide a message back to the user. You can also use that information in the app itself to, for example, conditionally show or hide some other workflow for the condition.
If you take this approach, make sure to add the hubble-oe:hide-action typeclass to one of the object parameters in the Action Form configuration so that the Action doesn't show up where users could use it through Object Explorer.
colleagues! We are developing a web application which has functionality to represent the organizational structure of current organization(a bank, for example). Organizational structure is represented as a parent-child relationships where each node has only one parent and each parent may have zero or more children. When the amount of entities(orgUnits) was comparable small, about 500 entities, our old method worked well. Generally, we used recursion to get all parent-child entities and passed it as a JSON document to browser where frontend part parsed this document and rendered it for user. Problems started when we uploaded the organizational structure of another organization(another bank) and had 6000 active orgUnits. Obviously fetching all orgUnits was not an option. We started to use request param depth to control recursion level but it didn't solve the problem of fetching child entities because each parent can have one or more children. For example, we had a parent orgUnit that had 100 children and any of this child could have one or more children. This method also loaded all orgUnits on this level even if it wasn't necessary. Right now i'm looking for solution that will keep number of orgUnits per HTTP request relatively small and browser won't freeze while rendering it. My idea is simple:
Paginate results somehow;
Only return additional child orgUnits when user wants it;
Our OrgUnitDTO looks like this:
{
"id": "a4f51de5-36f3-258c-232d-3d617c07fefc",
"extId": null,
"type": "OrgUnit",
"orgId": "99beadc8-831a-f6ab-fee9-11143d43ccd1",
"parentId": "99beadc8-831a-f6ab-fee9-11143d43ccd1",
"code": "second-level-test-department",
"name": "name",
"note": "note",
"manager": null,
"children": [], // children property has objects of the same type
"createdBy": "userName",
"updatedBy": "userName",
"createdAt": "2020-09-04T06:23:53.793Z",
"updatedAt": "2020-09-04T06:23:53.795Z",
"sortOrder": 0,
"isManager": false
}
That's how it looks in GUI:
screenshot
I'm looking for your suggestions for backend and frontend as well!
In case it matters we use Spring-Boot and Hibernate.
Here is not a matter of framework used or technology.
Your question is more about the solution.
Rule of thumb: A human can interact only with few data at a time, so don't fetch or display a lot of data, is useless and slow.
I've dealt with a similar problem in the past and solved this way, but there may be better solutions of course:
I've created a backend function that a client can call to fill the page the first time is loaded so that you can get the first N levels of depth with an integer parameter (ie. 2 or 3) starting from a node of the tree (null if you want to start from the top).
I've added a search function (both on FE and BE) to let the user jump immediately to a position he already knows (ie. an employee name): the function returns only the JSON of the nodes that are composing the path to the founded node. Other nodes can be expanded with a [+] button or something like that, just to be hyperfast and concise in outputting data. Usually, if you search for a person in an org chart, you want to know immediately who are his bosses and nothing else.
Children for each node were not so many in my case, so I've not optimized here, but in your case, you can implement lazy loading of data with pagination if you have more than X children at the same level. You can use a \/ icon to load more nodes when the user clicks or you can do it automagically when the user scrolls down the page. It is up to you. It is up to you decide also the number of nodes to load after paging. You can make this responsive, you load more nodes if the screen has space to display them.
To open each subsequent node call the function you used at the first-page loading only when the user clicks on the [+] passing the current node id and 1 as parameters to specify you want only one level more.
To implement the FE part I've used jstree and jstreegrid.
General hint: choose the FE part library first, THEN create backend functions, it will be easier and you'll make fewer refactorings.
I am having difficulty accessing all the data returned by my forms in my post function. I notice a significant discrepancy between what is displayed when I print request.POST vs. when my code accesses this data. Hopefully someone can explain this to me.
Output of print(request.POST):
print(request.POST)
<QueryDict: {'csrfmiddlewaretoken': ['AXMPO...'],
'start_date': ['2019-03-01'], 'end_date': ['2019-03-26'],
'reports': ['4', '1']}>
In order to examine the data my code is dealing with I used the json module to view the data. The behavior of my code during debugging conforms to this representation:
json.dumps(request.POST)
'{"csrfmiddlewaretoken": "AXMPO...",
"start_date": "2019-03-01", "end_date": "2019-03-26",
"reports": "1"}'
It all looks pretty similar until you see the "reports" value. The user selects these reports via an MultipleSelect widget on my form and my code is iterating through the id numbers provided. However, no matter how many reports I select I only get one ID. If anyone can explain why this is happening I would sincerely appreciate it.
Turns out this is a really old school issue. I could wish this was more prominent in the documentation though. The explanation by Simon Willson is below:
"""
This is a feature, not a bug. If you want a list of values for a key, use the following:
values = request.POST.getlist('key')
The reasoning behind this is that an API method should consistently return either a string or a list, but never both. The common case in web applications is for a form key to be associated with a single value, so that's what the [] syntax does. getlist() is there for the occasions (like yours) when you intend to use a key multiple times for a single value.
""" - Simon Willson, 13 years ago.
I need a little help with a process we're trying to build that should be able to react dynamically.
The process goes a little something like this.
User will submit a process request against an environment, submitting an array of string values as a runtime value. The process will take these in, as an array in bash, and loop through them, checking them against a predefined string list for validity. Upon finding they are valid, reacting differently based off of which values are in the string.
Example:
User submits a process request with values "abc", "bcd", "cde", "def"
Values "abc", "bcd", and "def" are valid.
We do a bit of manipulation to make them usable:
echo ${p:inputArray}
inputArray="${p:inputArray}"
inputArray=${inputArray//]/}
inputArray=${inputArray//[/}
inputArray=${inputArray//,/}
inputArray=( "${inputArray[#],,}" )
Then loop through each value and react:
for inputValue in $inputArray; do
if [[ "${validInputArray[#]}" =~ "${inputValue}" ]]; then
// Check if value is the outlier case "A"
// Or if the value is normal (but multiple) case "B"
// If case "B" then we'll build a variable for it
// It should be something like ${p:environment/$inputValue.action}
This, ideally, would give me the value of ${p:environment/abc.action} for example. But it does not. It gives me a string. I have no way to evaluate the dynamically created property request, as all properties are evaluated at initialization and not on the fly.
We can handle it via a "case" method - but it's a bit ugly, and will only get uglier as our number of valid inputs grow.
Instead of sending it an array of values, you can configure UCD to prompt them for specific values. You can do this on the application process. That way, when the user kicks off the deployment, there is no guessing on the validity of the input.
On the process page of the application, click on the Application Process Properties link
From there, you can configure it to require a certain pattern (checked via regex), or explicit values from a drop down, raw text, dateTime, etc. Here, I've configured a property with a multi-select to allow specific JVM maximum heap values. By limiting this to specific values, you can avoid typos and failed deployments.
Once configured, when you launch your process, you are presented with the property in the interface:
I´m kind of new to the reactive pattern and now I have my first bigger question.
I have done a few asychronous requests in the reactive way. But what I wan´t to do now is a "Eventlistener".
I have a Session object, at the moment I have an SessionEventListener protocol. The Session has a list of listeners and informs all of them about a successfull login and an logout. This Listeners can subscribe and unsubscribe. This thing I want to create reactive now.
How would you do that?
My Idea is to define a BehaviourSubject:
public let loginEventBehaviourSubject = BehaviorSubject(value: true)
now I can send onNext true if the session logged in, and false if it was logged out:
loginEventBehaviourSubject.onNext(true) // on login
loginEventBehaviourSubject.onNext(false) // on logout
And my "listeners" can subscribe to it.
But I would prefere to have subjects for every event:
public let loginEventBehaviourSubject = BehaviorSubject(value: )
public let logoutEventBehaviourSubject = BehaviorSubject(value: )
But then I wouldn´t need the bool. Can I make a kind of "empty" Subject, that only fire "events" without submitting really data.
And then my last question:
Why do I have to add an instance to the initializer of the Subject. Why can´t I create it like: BehaviourSubject<Bool>()?
You need to give an initial value to behavior subject because of it's API. Indeed, it defines BehaviorSubject<T>.value() method, which returns a T. And it would not make sense to call value without a proper initial value. In the presented case, I think PublishSubject is a better representation of the task at hand. You can find more documentation on the available kinds of subjects on the reactivex website.
If you are only interested in the .next event of your subjects, you can do let loginSubject = PublishSubject<Void>() (using behavior subject, you could have written BehaviorSubject<Void>(value: ())) and will the be able to call loginSubject.onNext().
Note though that using any subject is often an anti-pattern. Indeed, subject are most of the time intended to bridge from the imperative to the reactive world and you can very often create things like loginEventObservable as a combination of other observables. For more information on this, I recommend reading To Use Subject Or Not To Use Subject?. It is written using the .Net implementation of Rx, but the theory stays the same.