Welcome to Dovetail Software Blogs : Sign in | Join | Help
A few UI Editor Tips & Tricks

Kevin walked past my laptop the other day and noticed an ugly looking hot-dog-inspired-colored window, and asked - what the hell is that?

This is what it was:

form1

Ugly? Absolutely. Useful? I think so. I thought it deserved some explanation, so here goes.

Colors

I purposely use the bright colors to distinguish the different elements, along with the exact space each element takes up, and how each element lines up. This is especially helpful for labels.

This is purely to assist with the design of the form in Clarify's User Interface Editor. These colors are not displayed at runtime in the Clarify Client.

For example, here's the same form, with the same controls, but without the colors. Notice that its hard to tell what's what, and how much space each control takes up.


form3

With everything colored, I can easily see the full position, size, and alignment of each control. This makes designing the form much easier.

I then use a little ClearBasic code to color the elements nicely at runtime. For example:

'Color the titles and summaries
For index = 1 To 10
    'Color the titles
    Set label = Me.GetControlByName ("title" & cstr(index))
    label.ForeColor = "hyperlink"
    If index Mod 2 <> 0 And index <= numberOfResults Then
         label.BackColor = "alternateRow"    
    Else
        label.BackColor = "row"
    End If

    'Color the summaries
    Set label = Me.GetControlByName ("summary" & cstr(index))
    label.BackColor = "row"
    If index Mod 2 <> 0 And index <= numberOfResults Then
         label.BackColor = "alternateRow"    
    End If
Next index

I often do this in web development as well, adding a background-color style to div elements, allowing me to easily see the size and position of each div.

Hiding controls off-screen

A common technique is to "hide" unused controls off-screen. Expand the form, move those controls to the expanded area, and then shrink the form back to its original size. Those controls outside the visible area will not be seen by agents using the Clarify Client.

Uses of this technique include:

  • Baseline controls that are not needed (Deleting these controls could cause runtime errors)
  • Controls used for debugging or testing
  • Additional explanations

Here's my form, expanded, so you can see the "hidden" controls:

form2

Also notice that I've added some additional labels.

One that says "In UI Editor, expand this form to the right for more info -->" This label has its visible property set to False, so its only visible in UI Editor, and will not be seen in the Clarify Client. This clues the next developer that they can expand the form, and see the "hidden" controls, along with some more information.

I've also added a groupbox and a  label that explain what's going on with the form and the colors:

explanation

Not only does it remind me what's going on when I revisit this form, but it also assists the next developer who works on this form.

Stacked Labels

You may notice the gray colored controls, which are behind the red & yellow controls. All 3 of these are labels. I've used the gray label to essentially give a left and right padding to the red and yellow labels.

You may also notice that only every other red/yellow label has a gray label behind it. This is allowing me to give a zebra effect to the results - coloring every other one.

This is how it looks at runtime in the Clarify Client:

zebra_stripes

It's just enough of a subtle color difference to separate each item, without being overbearing.

The Tab Order is important here. The gray background labels must come before the red and yellow labels, otherwise the gray label will render in front of, instead of behind, the red & yellow labels.

 

What are some of your UI Editor tips & tricks?

Impact, Urgency, and Priority of a case

One of the best practices that ITIL brings to the party within Incident (case) Management is prioritization.

ITIL calls out 3 separate attributes: impact, urgency, and priority.

Impact: the measure of how business critical it is.

Urgency: a necessary speed of resolving an incident.

Priority: formulated from the combination of impact and urgency. Some formulate it as Priority = Urgency + Impact. Others use Priority = Urgency * Impact.

They key difference that ITIL presents with the concept of Priority versus the classic usage of Severity is that severity alone does not provide enough context for Prioritization. The urgency factor needs to be added to severity in order to provide an accurate understanding of how to prioritize activity.

 

Example of a priority coding system

priority 

Impact, Urgency, and Priority within Dovetail

Within Dovetail (and Clarify/Amdocs), Severity and Priority are provided, but not Impact. No worries, its easy to add this third attribute.

First, we'll add a custom field for the impact. A little SchemaScript using SchemaEditor does the trick.

<schemaScript xmlns="http://www.dovetailsoftware.com/2006/10/SchemaScript.xsd">
  <addColumn name="x_impact" dataType="String"  table="case">
    <length>40</length>
  </addColumn>
</schemaScript>

Second, we'll create a new User Defined Popup List to hold the Impact values. We'll use the Dovetail Admin UI to do this.

impact_list

Third, we'll add a new drop-down list element to the case.asp page.

<% var x_impact=boCase('x_impact');%>
<%=BuildUserDropDownList("x_impact","x_impact",bReadOnly,x_impact,'')%>    

Finally, we'll add the code to save the value when the case is saved in case2.asp.

fld_list.AppendItem("x_impact");
val_list.AppendItem(Request.Form('x_impact').Item);
type_list.AppendItem("String");

The case page, now with the 3 attributes:

case_3_lists

 

We now have a drop-down for each attribute. But ITIL suggests that the Priority should be set based on the Impact & Urgency. Lets make that happen.

Dynamically set the priority within Dovetail Agent

First, we'll change the priority from a drop-down list to a readonly textbox. Comment out the priority select element, and then add the textbox:

<input type="text" class="clsTxt" name="priority" id="priority" value="<%=lPriority%>" readonly>

Second, we'll add some code to dynamically set the priority based on the impact and urgency. jQuery will help with this. We'll map the string values to a numeric weighting, multiply the 2 numeric weightings together to get the priority weight, and then use this to set the priority string value. We'll do this on page load, and also when either the Impact or the Urgency(Severity) drop-downs change. 

function GetWeight(inputString){
    if (inputString == "Medium") return 2;
    if (inputString == "High") return 3;   
    return 1;
}

function SetPriority(){
    var impact = $("#x_impact").val();
    var urgency = $("#severity").val();   
    var weight = GetWeight(impact) * GetWeight(urgency);

    if (weight > 6){
        $('#priority').val("Critical");return;
    }   
    if (weight > 4){
        $('#priority').val("High");return;
    }
    if (weight > 2){
        $('#priority').val("Medium");return;
    }
    if (weight > 1){
        $('#priority').val("Low");return;
    }
    $('#priority').val("Planning");
}

$(document).ready(function(){
    SetPriority();
    $("#x_impact").change( function() {
        SetPriority();
    });
    $("#severity").change( function() {
        SetPriority();
    });
})

Here's how the page looks now:

case 

And changing either the Urgency or the Impact will dynamically set the Priority.

 

And there you have - an Incident Priority Automation Customization. (yikes, that sounds enterprisey. blurg.)

When Clarify grids go bad

For the most part, Clarify is pretty easy to customize. Occasionally, you run into Clarify forms that just don't behave as you would expect. In particular, the "old" Clarify forms, that were all written in C, long before ClearBasic was considered - those can be problematic. ClearLogistics forms are also typically problematic - the initial ClearLogistics development team seemed to have their own way of doing things back then.

We recently assisted a customer with such an issue, and I'm sharing it here so hopefully it may help others in a similar situation.

Customizing the "Select Inventory Parts" form

The requirement at hand was to exclude inventory parts from a certain inventory location when selecting inventory parts - specifically, on Form 519 (Select Inventory Parts).

Here's the form, showing all inventory parts:

inv_parts_no_filter

Lets say that we want to exclude those inventory parts that exist in location "12345".

Traditional approach

The traditional approach would be to get the list of records out of the grid (or the contextual object itself), loop through them, remove the ones that match, and repopulate the grid with the updated list of records.

Sub SELECT_Click()
    Me.DoDefault
    HideInventoryPartsInLocation "12345"
End Sub

Sub HideInventoryPartsInLocation(locationName As String)
    Dim partsList As List
    Dim origCount As Integer
    Dim partRecord As Record
    Dim index As Integer

    Set partsList = Cobj_part_inst.Contents

    origCount = partsList.Count
    For index = origCount-1 To 0 Step -1
        Set partRecord = partsList.ItemByIndex (index)
        If locationName = partRecord.GetField ("location_name") Then
            partsList.RemoveByIndex index
        End If
    Next index

    cobj_part_inst.Fill partsList
    Cobj_TOTAL_NUM.Fill partsList.Count
End Sub

 

Unfortunately, this yield a Type Mismatch runtime error on this line:

Set partRecord = partsList.ItemByIndex (index)

A little debug code allows us to take a closer look at the the partsList variable:

MsgBox "partsList.ItemType: " & partsList.ItemType

itemtype

The ItemType of this list is "long". We're expecting a list of records, not longs. And these longs aren't objids either. I would guess they're pointers.

No love. Lets try something else.

Another traditional approach

Another way to do this would be to do the query ourselves, excluding the parts we want to exclude, and then simply fill the grid.

Sub HideInventoryPartsInLocation(locationName As String)
    Dim br As New BulkRetrieve
    Dim partsList As List
    Dim gridList As List
    Dim origCount As Integer
    Dim index As Integer
    Dim obj As Record
    Dim recFilter As Record
    Dim str_part_number As String
    Dim str_mod_level As String
    Dim str_part_descr As String
    Dim str_part_serial_no As String
    Dim str_location_name As String
    Dim str_bin_name As String
    Dim str_container_id As String
    Dim ascDescString As String
    Dim ascDesc As Long
    Dim sortBy As String


    Set recFilter = Cobj_NEW_FILTER.Contents
    str_part_number    = Trim(recFilter.GetField("part_number") )
    str_mod_level    = Trim(recFilter.GetField("mod_level"))
    str_part_descr    = Trim(recFilter.GetField("part_descr"))
    str_part_serial_no    = Trim(recFilter.GetField("part_serial_no"))
    str_location_name    = Trim(recFilter.GetField("location_name"))
    str_bin_name    = Trim(recFilter.GetField("bin_name"))
    str_container_id    = Trim(recFilter.GetField("container_id"))


    br.SimpleQuery 0, "parts_view"
    br.AppendFilter 0, "hdr_ind", cbNotEqual, 1
    br.AppendFilter 0, "hdr_ind", cbNotEqual, 3
    br.AppendFilter 0, "location_name", cbNotEqual, locationName

    If (str_part_number <> "") Then
        br.AppendFilter 0, "part_number", cbLike, str_part_number & "%"
    End If
    If (str_mod_level <> "") Then
        br.AppendFilter 0, "mod_level", cbLike, str_mod_level & "%"
    End If
    If (str_part_descr <> "") Then
        br.AppendFilter 0, "part_descr", cbLike, str_part_descr & "%"
    End If
    If (str_part_serial_no <> "") Then
        br.AppendFilter 0, "part_serial_no", cbLike, str_part_serial_no & "%"
    End If
    If (str_location_name <> "") Then
        br.AppendFilter 0, "location_name", cbLike, str_location_name & "%"
    End If
    If (str_bin_name <> "") Then
        br.AppendFilter 0, "bin_name", cbLike, str_bin_name & "%"
    End If
    If (str_container_id <> "") Then
        br.AppendFilter 0, "container_id", cbLike, str_container_id & "%"
    End If


    ascDescString = ASC_DESC.Value
    ascDesc = cbDescending
    If ascDescString = "Ascending" Then
        ascDesc = cbAscending
    End If


    sortBy = GetStringAfterCharacter(SORT_BY_MBT.UserData, ".")
    sortBy = GetStringAfterCharacter(sortBy, ":") 
    br.AppendSort 0, sortBy, ascDesc

    br.RetrieveRecords
    Set partsList = br.GetRecordList(0)
    cobj_part_inst.Fill partsList
    Cobj_TOTAL_NUM.Fill partsList.Count
End Sub

 

The UI doesn't like this approach at all. Notice that there are the right number of records (2) in the grid, but all of the data is empty:

empty_grid

and double-clicking  one of these rows yields this helpful gem:

error

 

Ugh. Still no love. So now what?

Approach #1: RemoveByIndex

Perform the same query as the baseline List button. Same filtering, same sorting. Get the list of inventory parts data from the form (from the contextual object). Loop through the list of records that we retrieved from the database. If this is a record to be hidden, then remove it (by index) from the list of data retrieved from the form. Refresh the form data.

One warning here: the query must match exactly - same query, same filtering, same sort order, everything.

Sub HideInventoryPartsInLocation(locationName As String)
    Dim br As New BulkRetrieve
    Dim partsList As List
    Dim gridList As List
    Dim origCount As Integer
    Dim index As Integer
    Dim obj As Record
    Dim recFilter As Record
    Dim str_part_number As String
    Dim str_mod_level As String
    Dim str_part_descr As String
    Dim str_part_serial_no As String
    Dim str_location_name As String
    Dim str_bin_name As String
    Dim str_container_id As String
    Dim ascDescString As String
    Dim ascDesc As Long
    Dim sortBy As String

    'Get the user's filter criteria
    Set recFilter = Cobj_NEW_FILTER.Contents
    str_part_number    = Trim(recFilter.GetField("part_number") )
    str_mod_level    = Trim(recFilter.GetField("mod_level"))
    str_part_descr    = Trim(recFilter.GetField("part_descr"))
    str_part_serial_no    = Trim(recFilter.GetField("part_serial_no"))
    str_location_name    = Trim(recFilter.GetField("location_name"))
    str_bin_name    = Trim(recFilter.GetField("bin_name"))
    str_container_id    = Trim(recFilter.GetField("container_id"))

    'Perform the same query as the List button's default action
    br.SimpleQuery 0, "parts_view"
    br.AppendFilter 0, "hdr_ind", cbNotEqual, 1
    br.AppendFilter 0, "hdr_ind", cbNotEqual, 3

    If (str_part_number <> "") Then
        br.AppendFilter 0, "part_number", cbLike, str_part_number & "%"
    End If
    If (str_mod_level <> "") Then
        br.AppendFilter 0, "mod_level", cbLike, str_mod_level & "%"
    End If
    If (str_part_descr <> "") Then
        br.AppendFilter 0, "part_descr", cbLike, str_part_descr & "%"
    End If
    If (str_part_serial_no <> "") Then
        br.AppendFilter 0, "part_serial_no", cbLike, str_part_serial_no & "%"
    End If
    If (str_location_name <> "") Then
        br.AppendFilter 0, "location_name", cbLike, str_location_name & "%"
    End If
    If (str_bin_name <> "") Then
        br.AppendFilter 0, "bin_name", cbLike, str_bin_name & "%"
    End If
    If (str_container_id <> "") Then
        br.AppendFilter 0, "container_id", cbLike, str_container_id & "%"
    End If

    'Set up the ascending/descending sort order
    ascDescString = ASC_DESC.Value
    ascDesc = cbDescending
    If ascDescString = "Ascending" Then
        ascDesc = cbAscending
    End If

    'set up the sort by
    sortBy = GetStringAfterCharacter(SORT_BY_MBT.UserData, ".")
    sortBy = GetStringAfterCharacter(sortBy, ":")

    'In my testing, baseline Clarify uses location_name
    'as the sort order for certain sortBy selections
    'Not sure why. This may be data related.
    'More exploratory testing  may be warranted.
    If sortBy = "bin_name" Then sortBy = "location_name"
    If sortBy = "container_id" Then sortBy = "location_name"
    If sortBy = "fixed_bin_name" Then sortBy = "location_name"
    If sortBy = "mod_level" Then sortBy = "location_name"

    'Apply the sorting criteria
    br.AppendSort 0, sortBy, ascDesc

    br.RetrieveRecords
    Set partsList = br.GetRecordList(0)

    'Get the data from the form
    'This will actually be a list of Longs, not a List of records
    'More Clarify weirdness
    Set gridList = cobj_part_inst.Contents

    'Loop through the list of records that we retrieved from the database
    'If this is a record to be hidden, then remove it (by index) from the
    'list of data retrieved from the form
    origCount = partsList.Count
    For index = origCount-1 To 0 Step -1
        Set obj = partsList.ItemByIndex (index)
        If locationName = obj.GetField ("location_name") Then
            gridList.RemoveByIndex index
        End If
    Next index

    'refresh the form data
    Cobj_TOTAL_NUM.Fill gridList.Count
    cobj_part_inst.Refresh

End Sub

 

Now we've excluded inventory parts in location "12345":

inv_parts_with_filter

Success!

Approach #2: A duplicate grid

Here's another approach that should work as well.

  • Setup a 2nd grid that looks like the baseline grid, along with a new LIST button.
  • Add a new text box.
    • Name: FILTER_BY_OBJID
    • Destination COBJ: NEW_FILTER
    • Destination field name: objid
  • Hide this text box in the non visible part of the form.
  • When the user clicks the custom LIST button, perform the same query as the baseline List button (bulkretrieve with the appropriate filters & sorting), and fill the cobj of the 2nd grid.
  • On the click action for the 2nd grid:
    • Get the objid of the selected row.
    • Put this value in the FILTER_BY_OBJID textbox.
    • Programmatically Click the baseline LIST button.
    • Programmatically Click the first (and only) row in the baseline grid
    • Clear the value in the FILTER_BY_OBJID textbox.
  • On the double-click action for the 2nd grid:
    • Programmatically Double-Click the first (and only) row in the baseline grid

We've used this approach in the past, for example on the Dispatch form (form 425).

The code for this is left as an exercise for the reader.

Summary

I hope you don't have to deal with this craziness, but if you do, hopefully you'll find this post helpful.

Sometimes you have to be a little creative, especially when dealing with forms that were written probably 15 years ago.

ITIL certification

I've been diving into ITIL in more detail lately, understanding IT best practices, and how our products and processes match up with the guidance set forth by ITIL.

What is ITIL?

ITIL (IT Infrastructure Library) is a public framework that describes Best Practice in IT service management. It provides a framework for the governance of IT, the "service wrap", and focuses on the continual measurement and improvement of the quality of IT service delivered, from both a business and a customer perspective.

Certification

On occasion, people have mentioned ITIL certification, asking if our products are ITIL certified. So I started doing some exploring of ITIL certifications. The predominant company doing ITIL product certifications is PinkElephant. Their certification program is called PinkVerify.

From their website:

PinkVERIFY is a service Pink Elephant has provided to the IT Service Management (ITSM) community since 1999. The PinkVERIFY assessment criteria are based on several sources of industry knowledge and experience:

  • High level ITIL tool requirements documented in ITIL and various publications from The Stationary Office (TSO - the official ITIL publishers)
  • Practitioner input
  • Software vendor input
  • Pink’s own consulting experience

PinkVERIFY does not measure ITIL compliance. ITIL is not a standard, but rather a set of best practices that are adapted to address the specific needs of an organization. This being said, there are clear tool related practices that ITIL and other industry sources define as good practice; therefore, PinkVERIFY assesses a tool’s compatibility with the ITIL framework and these practices as they are defined within the criteria of this service.

Compatible = The software tool supports the PinkVERIFY criteria and ITIL terminology "out of the box" as part of its standard commercial offering.

ITIL Version 3 (V3)

In 2007, the Office of Government Commerce (OGC) released ITIL version 3 (V3), comprising a new set of five books that follow a Service Lifecycle approach. With the release of ITIL V3, Pink Elephant has developed a new PinkVERIFY certification scheme to reflect support of 14 processes within the Service Lifecycle.

The previous PinkVERIFY model was based on V2; however, all existing PinkVERIFY (V2) vendors with a current license agreement will continue to be recognized because all of the V2 processes are included in V3.

Certified compatibility

There is a set of self-assessments that product vendors can download to determine if a product will be ITIL compliant  certified compatible. As we're a replacement for the Amdocs/Clarify product suite, and Amdocs is PinkVerfied, I expected us to match up as well. And we do. Except for one criteria:

Does the tool's use of terms and definitions align with ITIL terms and definitions?

ITIL terms include Incident, Problem, and Request for Change. We use similar, but not exact, terms such as Case, Solution, and Change Request.

I contacted PinkElephant to get some clarification. The answer from them was clear: the terms used must match exactly. For example, an "incident" must be an "incident". It cannot be a "case", "ticket", or "issue". This means that any system or business that uses the term "case", "issue", or "ticket" instead of "incident" would not pass the PinkVerify certification. This implies that any of these systems or businesses would not be ITIL "compatible".

I asked about Amdocs, since I know that they use "case", not "incident". The reply: This was not requirement in the previous version [ITIL V2] and this is why Amdocs is on this list. Under the new model the term Incident must be used.

So under ITIL V2, Amdocs is compliant  certified compatible. But not under ITIL V3.

If we had gone through a certification process last year, we would be certified. But not now.

<rant>

I find this absurd. It shows that the focus is no longer on best practices, but on stringent following to terminology, independent of the ubiquitous language of the business. This is a great example of the issue with "certification" organizations - they tend to bear out as revenue generation vehicles, and have lost focus on raising the standards of quality for individuals, organizations, products, and the community as a whole.

Companies like Clarify (Amdocs) and Dovetail have been providing products that support (and in many cases lead the way) in best practices, and have been doing so for years. To say that they no longer meet the requirements for best practices (when in many ways we innovated in these best practices) shows the lack of connection from certification organizations to products, and to organizations that have implemented these products and deliver exemplary service on a daily basis.

This whole rant could be another post. Maybe at a later time...

</rant>

Focus on the best practices

Even though we're not ITIL "PinkVerified", our customers can (and many do) use our software to put in place and ensure the best practices that are at the heart of ITIL. More posts with specific details and examples on this will be coming soon.

App.ShowSolution in ClearBasic

I'm sure most of the ClearBasic brainiacs already know this (and I may have at one point), but the parameter to App.ShowSolution is a record of type "workaround", not a record of type "probdesc".

I probably knew this at one time, but its been a long time since I've done ClearBasic coding. I'm blogging this so that I can find it again in the future, with Google's help, of course.

 

If you call App.ShowSolution with a probdesc record, you get this ever-so-helpful pile of joy:

error

Cannot map specific relation (type 1 with relation -3).

Uh, yeah. Thanks. No, really. That was a helpful message. I'm in awe of your ability to render something so utterly useless. Freakin' programmers.

 

Working code example:

Sub ShowObject(objectType As String, idNumber As String)
    If objectType = "solution" Then objectType = "probdesc"

    Dim br As New BulkRetrieve
    br.SimpleQuery 0, objectType
    br.AppendFilter 0, "id_number", cbEqual, idNumber

    'For solutions, we need to get the related workaround (the first one will do)
    If objectType = "probdesc" Then
        br.TraverseFromParent 1, "probdesc2workaround", 0
    End If

    br.RetrieveRecords

    Dim listOfRecords As List
    Set listOfRecords = br.GetRecordList(0)

    If listOfRecords.Count = 0 Then
        App.MsgBox "Unable to locate '" & objectType & "' with id of " & idNumber
        Exit Sub
    End If

    Dim recObject As Record
    Set recObject = listOfRecords.ItemByIndex(0)

    If objectType = "case" Then
        App.ShowCase recObject
        Exit Sub
    End If

    If objectType = "probdesc" Then
        Set listOfRecords = br.GetRecordList(1)
        Set recObject = listOfRecords.ItemByIndex(0)    
        App.ShowSolution recObject
        Exit Sub
    End If

End Sub

Fun with Wordle

Fun with Wordle, based on my tags.

wordle

Highlighting Priority Cases

A common customization within Clarify is to highlight priority cases in a wipBin or queue by setting their color. For example, make High Priority cases really stand out by coloring them red.

Clarify Classic Client

The ClearBasic Customization Guide has a couple of examples on how to do this with the Clarify Classic Client.

However, the customization was commonly applied to the Queue and wipBin forms - not the console.

As a reminder: to view the wipBin form, simply double-click a wipBin from the list in the left side of the console. Similarly, for the Queue form.

However, since about Clarify version 4, no one typically used these forms - the new console form was what was used. However, the console form can't be customized. I did a search on this to confirm my memory, and found my own post from 7 years ago. I hate when that happens.

Dovetail Agent

Highlighting rows in the console is really easy to do within Dovetail Agent.

  1. Add a CSS class to the case rows
  2. Add this class to the stylesheet, setting whatever styles/colors you want.

 

1. Add a CSS class to the case rows

Looking at $dovetailAgent/pages/console/console_main.asp, you'll see where the list of cases is looped over, writing out each one:

<%
  while(boCaseView.EOF != true) {
%>
  <tr  id="...

Simply modify that, adding a new class to each row.

<%
  while(boCaseView.EOF != true) {
%>
  <tr class="casePriority<% =boCaseView('priority') %>" id="...

I've called mine casePriority + the priority. So if you have defined case priorities of High, Medium, and Low, then your class names will be casePriorityHigh, casePriorityMedium, and casePriorityLow.

 

2. Add this class to the stylesheet, setting whatever color you want.

Here, we'll simply modify $dovetailAgent/pages/stylesheets/webagent.css, and set the color of High priority cases to red. Notice that we're also setting any children anchors to the same color.

.casePriorityHigh, .casePriorityHigh a{
    color:red;
}

And here's what it looks like:

highlighted_cases

 

How about a different style?

Lets set the background color and the font color to make it stand out even more:

.casePriorityHigh, .casePriorityHigh a{
    color:#fff;
    background-color:#f00;
}

highlighted_cases2

 

You can use this same technique to color based on age, severity, condition, status, etc.

Remember to use color diligently, otherwise your application will end up looking like a 5th graders MySpace page.

Hope this helps.

Interesting post on Case Types and Case Severity

Over on the 37signals blog, they're talking about some of their design decisions in tweaking their support request form.

In Clarify/Dovetail parlance, we have a Case Type and a Case Severity.

It seems 37signals have gone back and forth between the two, trying to capture both pieces of data in one element.support

I do think there are 2 distinct values - the type of issue (billing, feature request, bug, etc.) and the severity/urgency of the issue (high, low, urgent, etc.), and I think their post shows the struggle when trying to combine them into one.

I do, however, appreciate that they are focused on keeping the submission form as streamlined, tight, quick, and as easy to use as possible.

I also like the fact that the Severity is focused on how the user feels, and uses natural language. For example, "Not a big deal, just need some help" is much better than "Low". Something to consider for Clarify/Dovetail implementations.

There's some interesting comments on that thread as well:

Check Dreamhost support form, they also have very funny dropdown with things like “OMG! Things are broken, people are dying” for really urgent matters etc…

 

I love the idea of the using emotional responses

 

Think about saying something like “Teach me. I’m not sure how this works… Rather than “I’m confused.” Selecting an option that says “I’m confused”, although it may be correct, just makes me feel dumb.

 

I also agree that Radio Buttons, generally, are a much better solution that Drop Downs. ESPECIALLY when the drop down is more verbose than, say, a State or Open/Closed/Cancelled state. Radio’s let me see all options at once without having to click. And drop-downs are HORRIBLE for people without good mousing ability. If the drop-down has a scroll bar, that’s about 1/2 dozen precise mouse-clicks for one selection. Ugh.

Good topic!

DeleteById in Dovetail SDK

deleteIn the Dovetail SDK, there is a DeleteById method on the ClarifyGeneric object. This is useful when you know the objid of the record you want to delete. Perhaps the objid is posted to a web page, or you've pulled it out of a relation column from a different record.

DeleteById is available via the .NET interface. It is not available on an fcGeneric object via the COM interface.

How can we DeleteById in COM?

Simply use the AddForUpdate method, then do the Delete.

Example:

var objid = 268435459;

var modem = FCSession.CreateGeneric('modem');
modem.AddForUpdate(objid);
modem.Delete();
modem.UpdateAll();

A handful of presentations on JavaScript and jQuery

jqueryJohn Resig (creator of jQuery) recently posted a bunch of his presentations online, focused on JavaScript and jQuery. Check 'em out.

I'm fast becoming a huge fan of jQuery, and we're now using it a lot more within Dovetail Agent.

Not only is the library itself cool - but the plethora of available plugins really make it rock.

More Posts Next page »