• Rajan Davis

    How should this list be set up? Is this a nested list or a flat list?

    I don't think this is 100% possible as even the default 'Categories' report does not display the categories in sequential order.

    You might be able to do something with some custom scripts; however, I would need to better understand how the list of categories needs to look before advising.

  • Rajan Davis

    I think you should be able to stringify the object literal without pushing it into an array.

    Also, I think your issue comes from setting the address type to an id of 0. If you POST the JSON without it being in an array, I think this problem will go away.

    Try this:

    function createContactRecord(sessionToken,email,fname,lname,custid,Brand)
        var obj = {
            name : {
                first: fname,
                last: lname
                    id: 0
                        lookupName: Brand
                        lookupName: SessionMarket
        return $.ajax({
              url: globalContext.getInterfaceServiceUrl('rest')+'/connect/v1.3/contacts',
              method: "POST",
              headers:{'Authorization':'Session '+sessionToken},
              data: JSON.stringify(obj),
              dataType: "json"
  • Rajan Davis

    Unfortunately, you have to have the page there for it to be redirected.

    Typically you would update a .htaccess file, but because we don't have direct access to this, you need to have the redirect code in the page.

    This how I have done redirects in the past to same effect; however, I would try Daniel's suggestion if you want to keep things consistent with CP framework code (if that is something you care about).

  • Rajan Davis

     I have 2 ideas of what might be a happier path:

    1. Load your bundled scripts into the CP assets folder. The publicPath could then be set as "./euf/assets/themes/<theme-name>/" which avoids some magic timestamp.

    2. Use something like Parcel which requires 0 additional configuration.

    I strongly feel as though relying on some timestamp is a smell... There is probably a much simpler way to accomplish what you're trying to do.

    If you want to talk about this off the boards, send a PM and I can take a look to give better practical advice.

    Kind Regards,


  • Rajan Davis

    If you go to https://<your-site> and login with an account that has CP privileges, there is a button at the top labeled "Deploy".

    You will want to click on "Stage" and will go through a tutorial of files to move to the "Staging Area". This is how your site will function in production except it isn't in production.

    Once you have completed any testing in staging, you should go back to the admin panel, click deploy, and select "Promote". This will move, staged files over into production.

    If  there are any issues between your development and staging environments, the panel will issue some warnings that you will need to fix.

  • Rajan Davis

    Hi Mike,

    I have built a BUI extension with Vue and am kind of perplexed as to what you're trying to accomplish here.

    You probably don't need this build process unless you are building a full on Vue application. If that is the case, I could be mistaken but I believe that this would need to match whatever comes off of the "/AgentWeb/" url for the Browser UI and not the location of where you BUI code resides (according to the Vue docs).

    If you're just building a single component, you can probably avoid this build step and use something like uglify-js to concatenate and compress your files (that's what I did with my example).

    Again, I could be mistaken, but I think what you're doing is really outside of what was envisioned for BUI, but is very common in non-OSvC platforms. With that said, I am not sure if there is a best practice or right way to do what you're accomplishing, so take what I said with a grain of salt.

    Hope this helps,


  • Rajan Davis

    I don't believe your bottle neck will exist in the report but rather on the database itself. If you have millions of incidents or contacts (or whatever object you have enabled quick search for), it will slow down even with some good filtering.

    A few things you can try are:

    1. Using the report database as opposed to the operational database. This will use cached data; however, this won't get around having a large quantity of whatever object you are searching for.

    2. Archiving incidents - this will remove incidents from your incidents table; however, they won't be deleted. It is typically best practice to archive incidents once they get pretty old depending on the size of your database.

    3. Requiring more filters - this will not get around size limitations; however, if you require more filters up front, the amount of data that will get returned will be a lot less assuming the filters are a fair way to group your data.

    4. Push all work in to custom scripting - I have done some custom scripting within the reports where I needed to fetch data for up to 300,000 objects and perform some calculations. This works up until you have a million objects that you need to query through (you will run out of memory for the scripts).

    Hope this helps,


  • Rajan Davis

    I think the biggest issue you will run into is how customized your widgets are.

    The biggest pain point I have seen is having to upgrade a customized widget that extends a standard widget that has dependency changes between portal versions. The widget manager is pretty good about this and well let you know in advance what changes between widget versions.

    Other thing to look out for are changes within standard models. Sometimes methods between versions will get removed, so if you have custom controllers or widgets that depend on standard models, you may need to perform some testing on these to make sure that they function correctly on newer versions.

    As Luuk has mentioned, staging your files in the newer version and testing the functionality is a good place to start. If there are issues, you will typically run into them while staging.

  • Rajan Davis

    The documentation is pretty comprehensive about the different types of mailbox configurations you can set up.

    Hope this helps,


  • Rajan Davis

    You can delete file attachments via the REST API if you send a DELETE HTTP request to either of the following URL's:

    incidents/<incident ID>/fileAttachments // Deletes all file attachments


    incidents/<incident ID>/fileAttachments/<fileAttachmentID> // Deletes specific file attachment

    There is in example in the ConnectPHP of how to delete file attachments in the update section; you unset the desired attachment from the FileAttachmentArray.

  • Rajan Davis

    One thing you should note is that in your controlworksAudit function, you are calling the save method twice. You only need to save once.

    In your query, try adding a "USE OPERATIONAL;" in the front of the query.

    My hypothesis is that your query is using the report database and might be using some sort of cached results. Specifying the operational database for queries should give you the freshest data; however, you database takes a hit every time it's run.

    If you get the same issue, I would make sure that the controlworksAudit function has a return statement. I don't think a lack of a return statement is your issue; however, it typically is used to terminate a function.

  • Rajan Davis

    I would consider looking at using the REST API for a connector. I have written a few wrapper libraries, but it looks like my Node wrapper would be a good fit for a Tableau connector. Will look at building a connector when I get some time in the next few days.

    Just out of curiosity, are you using Tableau server, desktop, or online?

    4/23 EDIT: After doing some research, it looks like the above linked connector has some dependencies that have some security issues. I would highly recommend to either export reports to CSV or to create a schedule to email CSV reports for Tableau users.

    I can definitely demonstrate how to work with the data in jupyter notebooks with pandas and matplotlib if that works, but I think a direct connector for Tableau is not really feasible at this time...

  • Rajan Davis

    I am not sure how to access the DisplayOrder of a custom object menu (it didn't come up when I checked), but I think if you could, you could modify the above code in the following way:

    function getReasonsReturned(){
    $data = array();
    $menuItemValues = RNCPHP\ConnectAPI::getNamedValues("RightNow\\Connect\\v1_3\\<Your custom object here>\\<menu field name>");
    foreach ($menuItemValues as $key => $value) {
          $index = isset($value->DisplayOrder) ? $value->DisplayOrder : $key;
    $data[$index]['rr_id'] = $value->ID;
    $data[$index]['reason_returned'] = $value->LookupName;
    ksort($data); // sorts array by keys
    echo json_encode($data);
  • Rajan Davis

    I would look at sorting and filtering your reports:

    Sorting options

    Filtering out the values by dates would remove the duplicate values.


  • Rajan Davis

    You might need to create a custom widget with the functionality you are after (this will give you access to the Rightnow Object) 


    create a custom controller method that let's you retrieve the value via AJAX.