Friday, December 5, 2014

Use dropdowns for easier data entry, better searching, and increased data integrity

Gallery Server Pro supports 75 pre-defined properties for your media assets, such as title, caption, and more. There are also 20 custom properties you can use for any purpose you desire. You can make any of these editable on the Metadata page in the site admin area. When you do, Gallery Server gives you a text box where you can edit the property. For example, here I’ve given one of the custom properties the name ‘Color’:

dd1

When I am logged in as a user with edit permission, I can edit the value by clicking on it:

dd2

This works well for many situations, but wouldn’t it be nice to restrict the entry to a list of pre-defined choices? For example, what if the only colors you want to allow are black, gray, brown, red, green, and blue? A dropdown would be perfect:

dd3

We can achieve this effect with a little editing of the right pane UI template. No changes to the source code are required, and your customization is preserved during upgrades to newer versions of Gallery Server. The only required skills are HTML and JavaScript. Let’s look at how to do it.

Start by logging in to your gallery as an admin and going to the Metadata page in the site admin area. Scroll down to the custom properties section, pick one and give it a name. In this example I’m calling it ‘Color’. I enabled it for media objects but not albums, gave it a blank default value, and made it editable. Save your changes, then hit the rebuild button. Gallery Server will add the property for every media asset in your gallery, which behind the scenes means a new record is added to the Metadata table for each item. It can take a while for large galleries, so look in the event log for an entry to indicate it’s finished.

dd4

When it’s done, you’ll see the new property when you view a media asset. As we saw earlier, the default behavior is to edit the value in a free-form text field.

dd5

Now we’d like to turn this into a dropdown list to enforce a set of color choices. We’ll do this by modifying the right pane template to include the new HTML dropdown. We’ll also add custom JavaScript so that when a new choice is made, the changes are automatically persisted to the server.

Go to the UI templates page in the site admin area and select the right pane template. Beginning in 3.2.1 changes are not allowed to the default template, so if you haven’t done so yet, copy it, give it a name and save it. To make this template the active one, go back to the default template and uncheck the albums, thus making the copy the only one with active albums selected.

On the HTML tab, find this line:

{{else MTypeId == 26}}

Insert this HTML just before it:

{{else MTypeId == 2005}}
<tr class='gsp_m2Row' data-id='{{:Id}}' data-iseditable='{{:IsEditable}}'>
  <td class='gsp_k'>{{:Desc}}:</td>
  <td class='gsp_dd'>
{{if ~root.Album.Permissions.EditMediaObject}}
   <select>
    <option value='Black' {{if Value=='Black'}}selected='selected'{{/if}}>Black</option>
    <option value='Gray' {{if Value=='Gray'}}selected='selected'{{/if}}>Gray</option>
    <option value='Brown' {{if Value=='Brown'}}selected='selected'{{/if}}>Brown</option>
    <option value='Red' {{if Value=='Red'}}selected='selected'{{/if}}>Red</option>
    <option value='Green' {{if Value=='Green'}}selected='selected'{{/if}}>Green</option>
    <option value='Blue' {{if Value=='Blue'}}selected='selected'{{/if}}>Blue</option>
   </select>
{{else}}
  {{:Value}}
{{/if}}
  </td></tr>

Change the ‘2005’ in the first line to the ID of your property. The IDs are shown on the Metadata page. And modify the option tags in the HTML to match the choices you want to display.

Then, on the JavaScript tab, add this script after the existing script:

var configDropDown = function() {
var data = {{:Settings.ClientId}}.gspData;

var getMetaItem = function (id) {
// Find the meta item with the specified ID.
return $.grep(data.ActiveMetaItems, function (mi) { return mi.Id === id; })[0];
};

// When this code runs the right pane may not yet be built, so we use the overload of on() that takes a selector
$('#{{:Settings.RightPaneClientId}}').on('change', '.gsp_meta tr[data-iseditable=true] td.gsp_dd select', function (e) {
$('#{{:Settings.RightPaneClientId}}').addClass('gsp_wait');
var metaTypeId = getMetaItem($(e.target).closest('.gsp_m2Row').data('id')).MTypeId;
var galleryItemMeta = { GalleryItems: data.ActiveGalleryItems, MetaItem: { MTypeId: metaTypeId, Value: $(this).val() } };

Gsp.DataService.saveMeta(galleryItemMeta,
  function () { $('#{{:Settings.RightPaneClientId}}').removeClass('gsp_wait'); },
  function (gim) {
   // Data is updated on the server, so now update the local data
   for (var i = 0; i < gim.GalleryItems.length; i++) {
    var gNew = gim.GalleryItems[i];
    var gCurrent = Gsp.findGalleryItem(data, gNew.Id, gNew.ItemType);

    if (gCurrent == null)
     gCurrent = Gsp.findMediaItem(data, gNew.Id, gNew.ItemType);

    if (gCurrent.MetaItems != null) {
     var mi = Gsp.findMetaItem(gCurrent.MetaItems, gim.MetaItem.MTypeId);
     if (mi != null) mi.Value = gim.MetaItem.Value;
    }
   }
  },
   function (response) { $.gspShowMsg("Cannot Save Changes", response.responseText, { msgType: 'error', autoCloseDelay: 0 }); }
);
});
};

$('#{{:Settings.ThumbnailClientId}}').on('select.{{:Settings.ClientId}}', function() {
configDropDown();
});

$('#{{:Settings.MediaClientId}}').on('next.{{:Settings.ClientId}} previous.{{:Settings.ClientId}}', function() {
configDropDown();
});

configDropDown();

It’s kind of a lot to absorb, but all it really does is detect the change event of the dropdown, persist the changes to the server, and update the client data model. There is also code to reconfigure the dropdown each time the right pane is rendered, which happens when the user navigates forward and backward in an album and when selecting a thumbnail on the album view page.

Save your changes, then take a look at one of your media assets in the gallery. You should see a dropdown for the property, just like one of the earlier screenshots. Users without edit permission see plain text, just like with the other properties.

Notice it also works on the thumbnail view in an album. You can use drag-select or CTRL-select several thumbnails, then select a color from the dropdown to update all of them at once. Super efficient.

This is a pretty slick feature that is usually available only in high-end digital asset management systems. Feel free to adapt this sample code to your own requirements. For example, you may want to get a list of choices from a web service or use a datetime picker for a date property. You have full control over the rendering through the power of the UI templates.