diff --git a/invenio/base/static/js/settings.js b/invenio/base/static/js/settings.js
index 532f79a56..1f3c99535 100644
--- a/invenio/base/static/js/settings.js
+++ b/invenio/base/static/js/settings.js
@@ -1,83 +1,106 @@
 /*
  * This file is part of Invenio.
  * Copyright (C) 2014 CERN.
  *
  * Invenio is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
  *
  * Invenio is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with Invenio; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  */
 
 require.config({
   baseUrl: "/",
   paths: {
     jquery: "vendors/jquery/dist/jquery",
     ui: "vendors/jquery-ui/ui",
     "jqueryui-timepicker": "vendors/jqueryui-timepicker-addon/dist",
     "jquery-form": "vendors/jquery-form/jquery.form",
     hgn: "vendors/requirejs-hogan-plugin/hgn",
     hogan: "vendors/hogan/web/builds/3.0.2/hogan-3.0.2.amd",
     text: "vendors/requirejs-hogan-plugin/text",
     flight: "vendors/flight/lib",
     typeahead: "vendors/typeahead.js/dist/typeahead.bundle",
     "bootstrap-select": "js/bootstrap-select",
     "jquery-caret": "vendors/jquery.caret/dist/jquery.caret-1.5.2",
     "jquery-tokeninput": "vendors/jquery-tokeninput/src/jquery.tokeninput",
     "jquery-jeditable": "vendors/jquery.jeditable/index",
     "moment": "vendors/moment/moment",
+    "datatables": "vendors/datatables/media/js/jquery.dataTables",
+    "datatables-plugins": "vendors/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap",
+    "datatables-tabletools": "vendors/datatables-tabletools/js/dataTables.tableTools",
     "bootstrap-datetimepicker": "vendors/eonasdan-bootstrap-datetimepicker/src/js/bootstrap-datetimepicker",
+    "bootstrap-tagsinput": "vendors/bootstrap-tagsinput/src/bootstrap-tagsinput",
     bootstrap: "vendors/bootstrap/dist/js/bootstrap",
+    prism: "vendors/prism/prism",
   },
   shim: {
     jquery: {
       exports: "$"
     },
     "jqueryui-timepicker/jquery-ui-sliderAccess": {
       deps: ["jquery"]
     },
     "jqueryui-timepicker/jquery-ui-timepicker-addon": {
       deps: ["jquery",
         "ui/slider"
       ]
     },
     "jqueryui-timepicker/i18n/jquery-ui-timepicker-addon-i18n": {
       deps: ["jqueryui-timepicker/jquery-ui-timepicker-addon"]
     },
     typeahead: {
       deps: ["jquery"],
       exports: "Bloodhound"
     },
     "bootstrap-select": {
       deps: ["jquery"],
       exports: "$.fn.buttonSelect"
     },
     "jquery-caret": {
       deps: ["jquery"],
       exports: "$.fn.caret"
     },
     "jquery-tokeninput": {
       deps: ["jquery"],
       exports: "$.fn.tokenInput"
     },
     "jquery-jeditable": {
       deps: ["jquery"],
       exports: "$.fn.editable"
     },
+    "bootstrap-tagsinput": {
+      deps: ["jquery"],
+      exports: "$.fn.tagsinput"
+    },
+    "datatables": {
+      deps: ["jquery"],
+      exports: "$.fn.dataTable"
+    },
     bootstrap: {
       deps: ["jquery"]
     },
+    "datatables-plugins": {
+      deps: ["jquery", "bootstrap", "datatables"]
+    },
+    "datatables-tabletools": {
+      deps: ["jquery", "datatables"],
+      exports: "$.fn.dataTable.TableTools"
+    },
     "bootstrap-datetimepicker": {
       deps: ["jquery", "bootstrap", "moment"],
       exports: "$.fn.datetimepicker"
     },
+    prism: {
+      exports: "Prism"
+    },
   }
 })
diff --git a/invenio/modules/workflows/actions/approval.py b/invenio/modules/workflows/actions/approval.py
index b92c1b989..fd44c476b 100644
--- a/invenio/modules/workflows/actions/approval.py
+++ b/invenio/modules/workflows/actions/approval.py
@@ -1,72 +1,78 @@
 # -*- coding: utf-8 -*-
 ##
 ## This file is part of Invenio.
 ## Copyright (C) 2012, 2013, 2014 CERN.
 ##
 ## Invenio is free software; you can redistribute it and/or
 ## modify it under the terms of the GNU General Public License as
 ## published by the Free Software Foundation; either version 2 of the
 ## License, or (at your option) any later version.
 ##
 ## Invenio is distributed in the hope that it will be useful, but
 ## WITHOUT ANY WARRANTY; without even the implied warranty of
 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 ## General Public License for more details.
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with Invenio; if not, write to the Free Software Foundation, Inc.,
 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 
 """Generic Approval action."""
 
 from invenio.base.i18n import _
 from flask import render_template, url_for
 
 
 class approval(object):
     """Class representing the approval action."""
     name = _("Approve")
     url = url_for("holdingpen.resolve_action")
 
     def render_mini(self, obj):
         """Method to render the minified action."""
         return render_template(
             'workflows/actions/approval_mini.html',
             message=obj.get_action_message(),
             object=obj,
             resolve_url=self.url,
         )
 
     def render(self, obj):
         """Method to render the action."""
         return {
             "side": render_template('workflows/actions/approval_side.html',
                                     message=obj.get_action_message(),
                                     object=obj,
                                     resolve_url=self.url,),
             "main": render_template('workflows/actions/approval_main.html',
                                     message=obj.get_action_message(),
                                     object=obj,
                                     resolve_url=self.url,)
         }
 
     def resolve(self, bwo):
         """Resolve the action taken in the approval action."""
         from flask import request
         value = request.form.get("value", None)
 
+        bwo.remove_action()
+        extra_data = bwo.get_extra_data()
+
         if value == 'accept':
-            bwo.remove_action()
+            extra_data["approved"] = True
+            bwo.set_extra_data(extra_data)
             bwo.save()
             bwo.continue_workflow(delayed=True)
             return {
                 "message": "Record has been accepted!",
-                "category": "primary",
+                "category": "success",
             }
         elif value == 'reject':
-            from invenio.modules.workflows.models import BibWorkflowObject
-            BibWorkflowObject.delete(bwo.id)
+            extra_data["approved"] = False
+            bwo.set_extra_data(extra_data)
+            bwo.save()
+            bwo.continue_workflow(delayed=True)
             return {
                 "message": "Record has been rejected (deleted)",
                 "category": "warning",
             }
diff --git a/invenio/modules/workflows/bundles.py b/invenio/modules/workflows/bundles.py
index c7795294b..8ca88388e 100644
--- a/invenio/modules/workflows/bundles.py
+++ b/invenio/modules/workflows/bundles.py
@@ -1,83 +1,61 @@
 # -*- coding: utf-8 -*-
 #
 ## This file is part of Invenio.
 ## Copyright (C) 2014 CERN.
 ##
 ## Invenio is free software; you can redistribute it and/or
 ## modify it under the terms of the GNU General Public License as
 ## published by the Free Software Foundation; either version 2 of the
 ## License, or (at your option) any later version.
 ##
 ## Invenio is distributed in the hope that it will be useful, but
 ## WITHOUT ANY WARRANTY; without even the implied warranty of
 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 ## General Public License for more details.
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with Invenio; if not, write to the Free Software Foundation, Inc.,
 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 
 """Workflows bundles."""
 
-from invenio.ext.assets import Bundle
+from invenio.ext.assets import Bundle, RequireJSFilter
+from invenio.base.bundles import jquery as _j, invenio as _i
+
 
 js = Bundle(
-    'js/workflows/entry_details.js',
-    'js/workflows/hp_details.js',
-    'js/workflows/hp_maintable.js',
-    'js/workflows/hp_selection.js',
-    'js/workflows/hp_tags.js',
-    'js/workflows/hp_utilities.js',
-    'js/workflows/utilities.js',
-    'js/workflows/workflows.js',
-    filters="uglifyjs",
+    'js/workflows/init.js',
+    filters=RequireJSFilter(exclude=[_j, _i]),
     output='workflows.js',
     weight=50,
-)
-
-actions = Bundle(
-    'js/workflows/actions/approval.js',
-    filters="uglifyjs",
-    output='actions.js',
-    weight=50
-)
-
-vendors_js = Bundle(
-    'vendors/bootstrap-tagsinput/dist/bootstrap-tagsinput.js',
-    'vendors/prism/prism.js',
-    filters="uglifyjs",
-    output='vendors.js',
-    weight=40,
     bower={
+        "bootstrap-tagsinput": "git://github.com/inspirehep/bootstrap-tagsinput.git#master",
+        "datatables": "latest",
+        "datatables-plugins": "latest",
+        "datatables-tabletools": "latest",
         "prism": "gh-pages",
-        "bootstrap-tagsinput": "latest"
+        "flight": "latest"
     }
 )
 
-vendors_css = Bundle(
+css = Bundle(
     'vendors/prism/themes/prism.css',
-    filters="cleancss",
-    output='vendors.css',
-    weight=40
-)
-
-dataTables_css = Bundle(
+    'vendors/bootstrap-tagsinput/src/'
+    'bootstrap-tagsinput.css',
+    'vendors/datatables/media/css/'
+    'jquery.dataTables.css',
     'vendors/datatables-plugins/integration/bootstrap/3'
     '/dataTables.bootstrap.css',
+    'vendors/datatables-tabletools/css/dataTables.tableTools.css',
+    'css/workflows/workflows.css',
     filters="less,cleancss",
-    output='datatables.css',
-    weight=30
-)
-
-dataTables_js = Bundle(
-    'vendors/datatables/media/js/jquery.dataTables.js',
-    'vendors/datatables-plugins/integration/bootstrap/3'
-    '/dataTables.bootstrap.js',
-    filters="uglifyjs",
-    output='datatables.js',
+    output='workflows.css',
     weight=30,
     bower={
-        "datatables": "~1.10",
-        "datatables-plugins": "https://github.com/greut/Plugins.git#amdify"
+        "bootstrap-tagsinput": "git://github.com/inspirehep/bootstrap-tagsinput.git#master",
+        "datatables": "latest",
+        "datatables-plugins": "latest",
+        "datatables-tabletools": "latest",
+        "prism": "gh-pages"
     }
 )
diff --git a/invenio/modules/workflows/static/css/workflows/workflows.css b/invenio/modules/workflows/static/css/workflows/workflows.css
new file mode 100644
index 000000000..dfa5514b5
--- /dev/null
+++ b/invenio/modules/workflows/static/css/workflows/workflows.css
@@ -0,0 +1,66 @@
+/*
+* -*- mode: text; coding: utf-8; -*-
+
+   This file is part of Invenio.
+   Copyright (C) 2014 CERN.
+
+   Invenio is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   Invenio is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with Invenio; if not, write to the Free Software Foundation, Inc.,
+   59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* Add nice looking Font Awesome checkboxes in main table */
+
+#maintable tr td:first-child {
+  text-align: center;
+}
+
+#maintable tr td:first-child:before {
+  content: "\f096"; /* fa-square-o */
+  font-family: FontAwesome;
+}
+
+#maintable tr.selected td:first-child:before {
+  content: "\f046"; /* fa-check-square-o */
+}
+
+
+/* Override default DataTables TableTools selection color */
+
+#maintable tr:hover {
+  background-color: #ffa;
+}
+
+table.dataTable tr.DTTT_selected td.sorting_1 {
+  background-color: #ffa;
+}
+
+table.dataTable tr.DTTT_selected {
+  background-color: #ffa;
+}
+
+table.dataTable tr.DTTT_selected.even td.sorting_1 {
+  background-color: #ffa;
+}
+
+table.dataTable tr.DTTT_selected.odd td.sorting_1 {
+  background-color: #ffa;
+}
+
+table.dataTable tr.DTTT_selected.even {
+  background-color: #ffa;
+}
+
+table.dataTable tr.DTTT_selected.odd {
+  background-color: #ffa;
+}
diff --git a/invenio/modules/workflows/static/js/workflows/actions/approval.js b/invenio/modules/workflows/static/js/workflows/actions/approval.js
index 01cfd4c35..e5f482f20 100644
--- a/invenio/modules/workflows/static/js/workflows/actions/approval.js
+++ b/invenio/modules/workflows/static/js/workflows/actions/approval.js
@@ -1,90 +1,96 @@
 /*
  * This file is part of Invenio.
  * Copyright (C) 2013, 2014 CERN.
  *
  * Invenio is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
  *
  * Invenio is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with Invenio; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  */
 
-var approval = (function ($, holdingpen, utilities) {
-    "use strict";
+'use strict';
 
-    $(document).ready(function(){
-        subscribe();
-    });
+define(
+  [
+    'jquery',
+    'flight/component',
+  ],
+  function(
+    $,
+    defineComponent) {
 
+    return defineComponent(ApprovalAction);
 
-    var get_action_values = function(elem) {
+    /**
+    * .. js:class:: ApprovalAction()
+    *
+    * Handles the events from the UI button elements for acceping/rejecting
+    * records by sending the selected action to the server.
+    *
+    * The actionGroupSelector is required for handling display of any action
+    * elements to be hidden or shown. It should be wrapped around every action
+    * UI component.
+    *
+    * :param string actionResolveSelector: DOM selector of elements resolving actions.
+    * :param string actionGroupSelector: DOM selector for wrapping display elements
+    * :param string action_url: URL for resolving the action.
+    *
+    */
+    function ApprovalAction() {
+
+      this.attributes({
+        actionResolveSelector: ".approval-action-resolve",
+        actionGroupSelector: ".approval-action",
+        action_url: ""
+      });
+
+      this.get_action_values = function (elem) {
         return {
-            "url": elem.attr("data-url"),
-            "value": elem.attr("data-value"),
-            "objectid": elem.attr("data-objectid"),
+          "value": elem.data("value"),
+          "objectid": elem.data("objectid"),
         }
-    };
-
-    var post_request = function(data) {
-        utilities.bootstrap_alert(data.message, data.category)
-    };
+      };
 
-    var subscribe = function () {
+      this.post_request = function(data, element) {
+        console.log(data.message);
+        var parent = element.parents(".approval-action");
+        if (typeof parent !== 'undefined') {
+          parent.fadeOut();
+        }
+        $(document).trigger("");
+      };
 
-        /*
-        * Approval action click event for mini maintable view.
-        *
-        * Binds the click event to every element with class
-        * "approval-action" to handle the resolution of the
-        * action..
-        */
-        $("#maintable").on("click", ".approval-action", function (event) {
-            var data = get_action_values($(this));
+      this.onActionClick = function (ev, data) {
+        var element = $(data.el);
+        var payload = this.get_action_values(element);
+        var $this = this;
 
-            jQuery.ajax({
-                type: "POST",
-                url: data.url,
-                data: {"objectid": data.objectid,
-                       "value": data.value},
-                success: function(data) {
-                    post_request(data);
-                    holdingpen.oTable.fnDraw(false);
-                }
-            });
+        jQuery.ajax({
+          type: "POST",
+          url: $this.attr.action_url,
+          data: payload,
+          success: function(data) {
+            $this.post_request(data, element);
+          }
         });
+      };
 
-        /*
-        * Approval action click event details page view.
-        *
-        * Binds the click event to every element with class
-        * "approval-action" to handle the resolution of the
-        * action..
-        */
-        $("#approval-widget").on("click", ".approval-action", function (event) {
-            var data = get_action_values($(this));
-
-            jQuery.ajax({
-                type: "POST",
-                url: data.url,
-                data: {"objectid": data.objectid,
-                       "value": data.value},
-                success: post_request,
-            });
+      this.after('initialize', function() {
+        // Custom handlers
+        this.on("click", {
+          actionResolveSelector: this.onActionClick
         });
-
-
-    };
-
-    return {
-        subscribe: subscribe,
-    };
-})(window.jQuery, window.WORKFLOWS_HOLDINGPEN, window.WORKFLOWS_UTILITIES);
-
+        console.log("Approval init");
+      });
+    }
+  }
+);
diff --git a/invenio/modules/workflows/static/js/workflows/utilities.js b/invenio/modules/workflows/static/js/workflows/details.js
similarity index 56%
copy from invenio/modules/workflows/static/js/workflows/utilities.js
copy to invenio/modules/workflows/static/js/workflows/details.js
index 29d6707e4..50c8bda64 100644
--- a/invenio/modules/workflows/static/js/workflows/utilities.js
+++ b/invenio/modules/workflows/static/js/workflows/details.js
@@ -1,32 +1,48 @@
 /*
  * This file is part of Invenio.
  * Copyright (C) 2014 CERN.
  *
  * Invenio is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
  *
  * Invenio is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with Invenio; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  */
 
-var WORKFLOWS_UTILITIES = (function ($) {
+"use strict"
 
-    return {
-        bootstrap_alert: function (message, category) {
-            $("#alert-message").html(
-                '<div class="alert alert-' + category + ' alert-dismissable">' +
-                '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' +
-                '<span>' + message + '</span></div>'
-            );
-        }
-    };
+define(
+  [
+     "js/workflows/details_preview",
+     "js/workflows/details_preview_menu",
+     "js/workflows/actions/approval"
+  ],
+  function(
+    DetailsPreview,
+    DetailsPreviewMenu,
+    ApprovalAction) {
 
-})(window.jQuery);
\ No newline at end of file
+    function initialize(context) {
+      DetailsPreview.attachTo(document, {
+        preview_url: context.preview_url,
+        id_object: context.id_object,
+      });
+      DetailsPreviewMenu.attachTo("#object-preview");
+
+      // Actions init
+      ApprovalAction.attachTo(document, {
+        action_url: context.action_url
+      });
+    }
+
+    return initialize;
+  }
+);
diff --git a/invenio/modules/workflows/static/js/workflows/details_preview.js b/invenio/modules/workflows/static/js/workflows/details_preview.js
new file mode 100644
index 000000000..d5b5b081b
--- /dev/null
+++ b/invenio/modules/workflows/static/js/workflows/details_preview.js
@@ -0,0 +1,90 @@
+/*
+ * This file is part of Invenio.
+ * Copyright (C) 2014 CERN.
+ *
+ * Invenio is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Invenio is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Invenio; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+'use strict';
+
+define(
+  [
+    'jquery',
+    'flight/component',
+    'prism'
+  ],
+  function(
+    $,
+    defineComponent,
+    Prism) {
+
+    return defineComponent(DetailsPreview);
+
+    /**
+    * .. js:class:: DetailsPreview()
+    *
+    * Handles the calls to the server for getting and displaying formatted data
+    * chosen by the user via the preview menu and uses Prism to syntax
+    * highlighting when required.
+    *
+    * :param string preview_url: URL for getting the formatted content.
+    * :param string id_object: ID of the BibWorkflowObject being displayed.
+    *
+    */
+    function DetailsPreview() {
+      this.attributes({
+        // URL
+        preview_url: "",
+
+        // BibWorkflowObject id
+        id_object: "",
+      });
+
+      this.renderPreviewByFormat = function (ev, data) {
+        var $this = this;
+        var container_selector = 'div[id="object_preview_container' + $this.attr.id_object + '"]';
+        $.ajax({
+            url: $this.attr.preview_url,
+            data: {'objectid': $this.attr.id_object,
+                   'of': data.format},
+            success: function (json) {
+                if (data.format === "xm" || data.format === "xo") {
+                    if (json.data === "") {
+                        json.data = "Preview not available";
+                    }
+                    $(container_selector).empty();
+                    $(container_selector).append(
+                      "<pre><code id='object_preview' class='language-markup'></code></pre>"
+                    );
+                    $('code[id="object_preview"]').text(json.data);
+                    Prism.highlightElement($('code[id="object_preview"]')[0]);
+                } else {
+                    if (json.data === "") {
+                        json.data = "Preview not available";
+                    }
+                    $(container_selector).empty();
+                    $(container_selector).append(json.data);
+                }
+            }
+        });
+      };
+
+      this.after('initialize', function() {
+        this.on(document, "setPreviewByFormat", this.renderPreviewByFormat)
+        console.log("Details init");
+      });
+    }
+  }
+);
diff --git a/invenio/modules/workflows/static/js/workflows/details_preview_menu.js b/invenio/modules/workflows/static/js/workflows/details_preview_menu.js
new file mode 100644
index 000000000..b38ac2b29
--- /dev/null
+++ b/invenio/modules/workflows/static/js/workflows/details_preview_menu.js
@@ -0,0 +1,59 @@
+/*
+ * This file is part of Invenio.
+ * Copyright (C) 2014 CERN.
+ *
+ * Invenio is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Invenio is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Invenio; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+'use strict';
+
+define(
+  [
+    'jquery',
+    'flight/component',
+  ],
+  function(
+    $,
+    defineComponent) {
+
+    return defineComponent(DetailsPreviewMenu);
+
+    /**
+    * .. js:class:: DetailsPreviewMenu()
+    *
+    * UI component for handling the preview menu buttons for the object data.
+    *
+    * :param string previewMenuItemSelector: DOM selector for each menu item
+    *
+    */
+    function DetailsPreviewMenu() {
+      this.attributes({
+        previewMenuItemSelector: ".preview"
+      });
+
+      this.setPreviewByFormat = function(ev, data) {
+        this.trigger(document, "setPreviewByFormat", {
+          format: data.el.name,
+        });
+      }
+
+      this.after('initialize', function() {
+        this.on("click", {
+          previewMenuItemSelector: this.setPreviewByFormat,
+        });
+        console.log("Details preview menu init");
+      });
+    }
+});
diff --git a/invenio/modules/workflows/static/js/workflows/holdingpen.js b/invenio/modules/workflows/static/js/workflows/holdingpen.js
new file mode 100644
index 000000000..4858063a9
--- /dev/null
+++ b/invenio/modules/workflows/static/js/workflows/holdingpen.js
@@ -0,0 +1,118 @@
+/*
+ * This file is part of Invenio.
+ * Copyright (C) 2014 CERN.
+ *
+ * Invenio is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Invenio is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Invenio; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+'use strict';
+
+define(
+  [
+    'jquery',
+    'flight/component',
+    'datatables',
+    'datatables-plugins',
+    'datatables-tabletools'
+  ],
+  function(
+    $,
+    defineComponent) {
+
+    return defineComponent(HoldingPen);
+
+    /**
+    * .. js:class:: HoldingPen()
+    *
+    * Holding Pen table using DataTables (+ plugins)
+    *
+    * :param string load_url: URL to asynchronously load table rows.
+    * :param object oSettings: configuration of DataTables.
+    *
+    */
+    function HoldingPen() {
+      this.attributes({
+        // URLs
+        load_url: "",
+        oSettings: {
+          dom: 'T<"clear">lfrtip',
+          bFilter: false,
+          bProcessing: true,
+          bServerSide: true,
+          bDestroy: true,
+          aoColumnDefs: [
+            {'bSortable': false, 'defaultContent': "", 'aTargets': [0]},
+            {'bSearchable': false, 'bVisible': false, 'aTargets': [1]},
+            {'sWidth': "25%", 'aTargets': [2]},
+            {'sWidth': "25%", 'aTargets': [3]}
+          ],
+          tableTools: {
+            "sRowSelect": "multi",
+            "sRowSelector": 'td:first-child',
+            "aButtons": [
+              {
+                "sExtends": "select_all",
+                "sButtonClass": "btn btn-default"
+              },
+              {
+                "sExtends": "select_none",
+                "sButtonClass": "btn btn-danger"
+              }
+            ]
+          },
+          deferRender: true,
+        }
+      });
+
+      this.init_datatables = function(ev, data) {
+        // DataTables ajax settings
+        this.attr.oSettings["sAjaxSource"] = this.attr.load_url;
+        this.$node.DataTable(this.attr.oSettings);
+        // Bootstrap TableTools
+        var tt = $.fn.dataTable.TableTools.fnGetInstance(this.$node.attr("id"));
+        $(tt.fnContainer()).insertBefore('div.dataTables_wrapper');
+      }
+
+      this.reloadTable = function (ev, data) {
+        var $node = this.$node;
+        $.ajax({
+            type: "POST",
+            url: this.attr.load_url,
+            data: JSON.stringify(data),
+            contentType: "application/json;charset=UTF-8",
+            traditional: true,
+            success: function(result) {
+                $node.dataTable().fnDraw(false);
+            }
+        });
+      };
+
+      this.holdingPenKeyCodes = function(ev) {
+        var keycodes = {
+          escape: 27,
+        }
+
+        console.log(ev.keyCode);
+        console.log(keycodes.escape);
+      }
+
+      this.after('initialize', function() {
+        this.on(document, "initHoldingPenTable", this.init_datatables);
+        this.on(document, "reloadHoldingPenTable", this.reloadTable);
+        this.on(document, "keyup", this.holdingPenKeyCodes);
+        console.log("HP init");
+      });
+    }
+});
diff --git a/invenio/modules/workflows/static/js/workflows/hp_details.js b/invenio/modules/workflows/static/js/workflows/hp_details.js
index 71ac2ab9f..9abdd0af5 100644
--- a/invenio/modules/workflows/static/js/workflows/hp_details.js
+++ b/invenio/modules/workflows/static/js/workflows/hp_details.js
@@ -1,129 +1,129 @@
  /*
  * This file is part of Invenio.
  * Copyright (C) 2013, 2014 CERN.
  *
  * Invenio is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
  *
  * Invenio is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with Invenio; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  */
 
-var WORKFLOWS_HP_DETAILS = (function ($) {
+define(['jquery', 'prism', "js/workflows/hp_utilities"], function($, Prism, utilities) {
     var context = {},
         format = "hd",
         bwoid;
 
     function data_preview(url_preview, bwoid, format) {
         $.ajax({
             url: url_preview,
             data: {'objectid': bwoid,
                    'of': format},
             success: function (json) {
                 if (format === "xm" || format === "xo") {
                     if (json.data === "") {
                         json.data = "Preview not available";
                     }
                     $('div[id="object_preview_container' + bwoid + '"]').empty();
                     $('div[id="object_preview_container' + bwoid + '"]').append("<pre><code id='object_preview' class='language-markup'></code></pre>");
                     $('code[id="object_preview"]').append(json.data);
                     Prism.highlightElement($('code[id="object_preview"]')[0]);
                 } else {
                     if (json.data === "") {
                         json.data = "Preview not available";
                     }
                     $('div[id="object_preview_container' + bwoid + '"]').empty();
                     $('div[id="object_preview_container' + bwoid + '"]').append(json.data);
                 }
             }
         });
     }
 
     return {
         bwoid: bwoid,
         data_preview: data_preview,
         init: function (context, bwoid) {
             if (window.addEventListener) {
                 $("div.btn-group[name='data_version']").bind('click', function(event){
                     version = event.target.name;
                 });
             }
 
             this.bwoid = bwoid;
             this.data_preview(context.holdingpen.url_preview,
                               bwoid,
                               format);
 
             $('button.preview').click(function () {
                 var format = $(this).attr('name');
                 data_preview(context.holdingpen.url_preview, bwoid, format);
                 $('button.preview').each(function () {
                     $(this).removeClass('active');
                 });
                 $(this).addClass('active');
             });
 
             $('#restart_button').on('click', function () {
                 $.ajax({
                     url: context.holdingpen.url_restart_record,
                     data: {'objectid': this.bwoid},
                     success: function (json) {
-                        WORKFLOWS_UTILITIES.bootstrap_alert('Object restarted', 'info');
+                        utilities.bootstrap_alert('Object restarted', 'info');
                     }
                 });
             });
 
             $('#restart_button_prev').on('click', function () {
                 $.ajax({
                     url: context.holdingpen.url_restart_record_prev,
                     data: {'objectid': this.bwoid},
                     success: function (json) {
-                        WORKFLOWS_UTILITIES.bootstrap_alert('Object restarted from previous task', 'info');
+                        utilities.bootstrap_alert('Object restarted from previous task', 'info');
                     }
                 });
             });
 
             $('#continue_button').on('click', function () {
                 $.ajax({
                     url: context.holdingpen.url_continue,
                     data: {'objectid': this.bwoid},
                     success: function (json) {
-                        WORKFLOWS_UTILITIES.bootstrap_alert('Object continued from next task', 'info');
+                        utilities.bootstrap_alert('Object continued from next task', 'info');
                     }
                 });
             });
 
             $('#edit_form').on('submit', function (event) {
                 event.preventDefault();
                 var form_data = {};
                 $("#edit_form input").each(function () {
                     if ($(this)[0].name !== 'submitButton') {
                         if ($(this)[0].name === 'core') {
                             form_data[$(this)[0].name] = $(this)[0].checked;
                         } else {
                             form_data[$(this)[0].name] = $(this)[0].value;
                         }
                     }
                 });
 
                 $.ajax({
                     type: 'POST',
                     url: context.holdingpen.url_resolve_edit,
                     data: {'objectid': this.bwoid,
                            'data': form_data},
                     success: function (json) {
-                        WORKFLOWS_UTILITIES.bootstrap_alert('Record successfully edited', 'info');
+                        utilities.bootstrap_alert('Record successfully edited', 'info');
                     }
                 });
             });
         }
     };
-})(window.jQuery);
\ No newline at end of file
+});
diff --git a/invenio/modules/workflows/static/js/workflows/hp_maintable.js b/invenio/modules/workflows/static/js/workflows/hp_maintable.js
index 61bde05fd..fde50059e 100644
--- a/invenio/modules/workflows/static/js/workflows/hp_maintable.js
+++ b/invenio/modules/workflows/static/js/workflows/hp_maintable.js
@@ -1,111 +1,110 @@
 /*
  * This file is part of Invenio.
  * Copyright (C) 2013, 2014 CERN.
  *
  * Invenio is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
  *
  * Invenio is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with Invenio; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  */
 
-var WORKFLOWS_HOLDINGPEN = (function ($) {
+define(["jquery"], function ($) {
     var oTable,
         oSettings,
         selectedRow,
         rowList = [],
         rowIndexList = [],
         recordsToApprove = [],
         defaultcss = "#example tbody tr.even:hover, #example tbody tr.odd:hover {background-color: #FFFFCC;}",
         context = {},
         datatable = {},
         tag = {},
         utilities = {},
         actions = [];
 
     return {
         oTable: oTable,
         oSettings: oSettings,
         selectedRow: selectedRow,
         rowList: rowList,
         rowIndexList: rowIndexList,
         recordsToApprove: recordsToApprove,
         defaultcss: defaultcss,
         context: context,
         datatable: datatable,
         tag: tag,
         actions: actions,
         utilities: utilities,
 
-        init: function (data) {
+        init: function (data, selection, tags, utilities) {
             this.context = data;
-            this.tag = window.WORKFLOWS_HP_TAGS;
+            this.tag = tags;
             this.tag.init();
-            this.datatable = window.WORKFLOWS_HP_SELECTION;
-            this.utilities = window.WORKFLOWS_HP_UTILITIES;
+            this.datatable = selection;
+            this.utilities = utilities;
             this.datatable.init(this.oTable, this.oSettings);
             this.utilities.autorefresh();
         },
 
         init_datatable: function (datatable) {
             oSettings = {
                 "dom": '<"top"iflp<"clear">>rt<"bottom"iflp<"clear">>',
                 "bFilter": false,
                 "bJQueryUI": true,
                 "bProcessing": true,
                 "bServerSide": true,
                 "bDestroy": true,
                 "sAjaxSource": this.context.holdingpen.url_load,
                 "oColVis": {
                     "buttonText": "Select Columns",
                     "bRestore": true,
                     "sAlign": "left",
                     "iOverlayFade": 1
                 },
                 "aoColumnDefs": [{'bSortable': false, 'aTargets': [1]},
                                  {'bSearchable': false, 'bVisible': false, 'aTargets': [0]},
                                  {'sWidth': "25%", 'aTargets': [2]},
                                  {'sWidth': "25%", 'aTargets': [3]}],
                 "fnRowCallback": function (nRow, aData, iDisplayIndex, iDisplayIndexFull) {
                     var id = aData[0];
                     datatable.rememberSelected(nRow, id);
                     nRow.row_id = id;
                     nRow.checkbox = nRow.cells[0].firstChild;
                     $(nRow).on("click", "td", function (event) {
                         console.log(event);
                         if(event.target.nodeName != "INPUT") {
                             datatable.selectRow(nRow, event, oTable.fnSettings());
                         }
                     });
                 },
                 "fnDrawCallback": function () {
                     $('table#maintable td').bind('mouseenter', function () {
                         $(this).parent().children().each(function () {
                             $(this).addClass('maintablerowhover');
                         });
                     });
                     $('table#maintable td').bind('mouseleave', function () {
                         $(this).parent().children().each(function () {
                             $(this).removeClass('maintablerowhover');
                         });
                     });
                     $('#select-all')[0].checked = false;
                 }
             };
             oTable = $('#maintable').dataTable(oSettings);
             $('.dropdown-toggle').dropdown();
             this.oSettings = oTable.fnSettings();
             this.oTable = oTable;
 
         }
     };
-})(window.jQuery);
-
+});
diff --git a/invenio/modules/workflows/static/js/workflows/hp_selection.js b/invenio/modules/workflows/static/js/workflows/hp_selection.js
index 495614673..63622a1ba 100644
--- a/invenio/modules/workflows/static/js/workflows/hp_selection.js
+++ b/invenio/modules/workflows/static/js/workflows/hp_selection.js
@@ -1,308 +1,304 @@
 /*
  * This file is part of Invenio.
  * Copyright (C) 2013, 2014 CERN.
  *
  * Invenio is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
  *
  * Invenio is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with Invenio; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  */
 
-
-// DataTables row selection functions
-//***********************************
-var WORKFLOWS_HP_SELECTION = function ($, holdingpen) {
+define(['jquery', 'js/workflows/hp_maintable'], function ($, holdingpen) {
     var oTable = {},
         oSettings = {},
         hoveredRow = -1;
 
     function init(_oTable, _oSettings) {
         oTable = _oTable;
         oSettings = _oSettings;
     }
 
     function selectAll() {
         var fromPos = holdingpen.oSettings._iDisplayStart,
             toPos = holdingpen.oSettings._iDisplayLength - 1 + fromPos,
             current_row,
             j,
             i;
 
         current_row = null;
         for (i = fromPos; i <= toPos; i++) {
             j = i % holdingpen.oSettings._iDisplayLength;
             current_row = holdingpen.oSettings.aoData[holdingpen.oSettings.aiDisplay[j]].nTr;
             if ($.inArray(current_row.row_id, holdingpen.rowList) <= -1) {
                 holdingpen.rowIndexList.push(i);
                 holdingpen.rowList.push(current_row.row_id);
                 current_row.style.background = "#ffa";
                 current_row.cells[0].firstChild.checked = true;
             }
         }
     }
 
     function selectCellByTitle(row, title) {
         var i,
             text_to_process,
             trimmed_title;
         for (i = 0; i < holdingpen.oSettings.aoHeader[0].length; i++) {
             text_to_process = holdingpen.oSettings.aoHeader[0][i].cell.textContent || holdingpen.oSettings.aoHeader[0][i].cell.innerText;
             trimmed_title = $.trim(text_to_process);
             if (trimmed_title === title) {
                 return $(row).children()[i - 1];
             }
         }
     }
 
     function selectCellByTitle_content(row, title) {
         var A = selectCellByTitle(row, title);
         A = A.innerText || A.textContent;
         return A;
     }
 
     function deselectAllFromPage(event) {
         var fromPos = holdingpen.oSettings._iDisplayStart,
             toPos = holdingpen.oSettings._iDisplayLength - 1 + fromPos,
             j,
             i,
             current_row = null;
 
         for (i = fromPos; i <= toPos; i++) {
             j = i % holdingpen.oSettings._iDisplayLength;
             current_row = holdingpen.oSettings.aoData[holdingpen.oSettings.aiDisplay[j]].nTr;
             if ($.inArray(current_row.row_id, holdingpen.rowList) > -1) {
                 holdingpen.rowList.splice(holdingpen.rowList.indexOf(current_row.row_id), 1);
                 holdingpen.rowIndexList.splice(holdingpen.rowIndexList.indexOf(current_row._DT_RowIndex + holdingpen.oSettings._iDisplayStart), 1);
                 current_row.style.background = "white";
                 current_row.checkbox.checked = false;
             }
         }
     }
 
     function selectRow(row, e, oSettings) {
         if (e.shiftKey === true) {
             this.selectRange(row);
         } else {
             if ($.inArray(row.row_id, holdingpen.rowList) <= -1) {
                 // Select row
                 holdingpen.rowList.push(row.row_id);
                 holdingpen.rowIndexList.push(row._DT_RowIndex + oSettings._iDisplayStart);
                 row.style.background = "#ffa";
                 row.checkbox.checked = true;
             } else {
                 $('#select-all')[0].checked = false;
                 // De-Select
                 holdingpen.rowList.splice(holdingpen.rowList.indexOf(row.row_id), 1);
                 holdingpen.rowIndexList.splice(holdingpen.rowIndexList.indexOf(row._DT_RowIndex + holdingpen.oSettings._iDisplayStart), 1);
                 row.style.background = "white";
                 row.checkbox.checked = false;
             }
         }
     }
 
     function removeSelection() {
         var range;
         if (window.getSelection) {  // all browsers, except IE before version 9
             var selection = window.getSelection();
             selection.removeAllRanges();
         } else {
             if (document.selection.createRange) {        // Internet Explorer
                 range = document.selection.createRange();
                 document.selection.empty();
             }
         }
     }
 
     function deselectAll() {
         holdingpen.rowList = [];
         holdingpen.rowIndexList = [];
         holdingpen.oTable.fnDraw(false);
         window.getSelection().removeAllRanges();
     }
 
     function hoverRow(row) {
         row.style.background = "#FFFFEE";
     }
 
     function unhoverRow (row) {
         if ($.inArray(row.row_id, holdingpen.rowList) > -1) {
             row.style.background = "#ffa";
         } else {
             row.style.cssText = defaultcss;
         }
     }
 
     $("#select-all").on("click", function (event) {
         if ($(this)[0].checked === true) {
             selectAll();
         } else {
             deselectAllFromPage(event.originalEvent);
         }
     });
 
     window.addEventListener("keydown", function (e) {
         var currentRowIndex,
             current_row,
             row_index,
             rowToAdd,
             rowList_out;
 
         if ([37, 38, 39, 40].indexOf(e.keyCode) > -1) {
             e.preventDefault();
         }
         if (e.keyCode === 40) {
             if (e.shiftKey === true) {
                 currentRowIndex =  holdingpen.rowIndexList[holdingpen.rowIndexList.length - 1];
                 if (currentRowIndex < 9) {
                     row_index = currentRowIndex + 1;
                     current_row = holdingpen.oSettings.aoData[holdingpen.oSettings.aiDisplay[row_index]].nTr;
                     if ($.inArray(current_row.row_id, holdingpen.rowList) <= -1) {
                         holdingpen.rowIndexList.push(row_index);
                         holdingpen.rowList.push(current_row.row_id);
                         current_row.style.background = "#ffa";
                         current_row.checkbox.checked = true;
                     }
                 }
             } else {
                 if (hoveredRow < 9) {
                     if (hoveredRow !== -1) {
                         unhoverRow(holdingpen.oSettings.aoData[holdingpen.oSettings.aiDisplay[hoveredRow]].nTr);
                     }
                     hoveredRow++;
                     hoverRow(holdingpen.oSettings.aoData[holdingpen.oSettings.aiDisplay[hoveredRow]].nTr);
                 }
             }
         } else if (e.keyCode === 38) {
             if (e.shiftKey === true) {
                 currentRowIndex = holdingpen.rowIndexList[holdingpen.rowIndexList.length - 1];
                 if (currentRowIndex > 0) {
                     rowToAdd = currentRowIndex - 1;
                     current_row = holdingpen.oSettings.aoData[holdingpen.oSettings.aiDisplay[rowToAdd]].nTr;
                     if ($.inArray(current_row.row_id, holdingpen.rowList) <= -1) {
                         holdingpen.rowIndexList.push(rowToAdd);
                         holdingpen.rowList.push(current_row.row_id);
                         current_row.style.background = "#ffa";
                         current_row.checkbox.checked = true;
                     }
                 }
             } else {
                 if (hoveredRow > 0) {
                     unhoverRow(holdingpen.oSettings.aoData[holdingpen.oSettings.aiDisplay[hoveredRow]].nTr);
                     hoveredRow--;
                     hoverRow(holdingpen.oSettings.aoData[holdingpen.oSettings.aiDisplay[hoveredRow]].nTr);
                 }
             }
         } else if (e.keyCode === 37) {
             holdingpen.oTable.fnPageChange('previous');
         } else if (e.keyCode === 39) {
             holdingpen.oTable.fnPageChange('next');
         } else if (e.keyCode === 65 && e.ctrlKey === true) {
             $("#select-all").click();
             e.preventDefault();
         } else if (e.keyCode === 13 && hoveredRow !== -1) {
             selectCellByTitle(holdingpen.oSettings.aoData[holdingpen.oSettings.aiDisplay[hoveredRow]].nTr, 'Title').click();
         } else if (e.keyCode === 46) {
             if (holdingpen.rowList.length >= 1) {
                 rowList_out = JSON.stringify(holdingpen.rowList);
                 deleteRecords(rowList_out);
                 holdingpen.rowList = [];
                 holdingpen.rowIndexList = [];
             }
         }
     });
 
     $(document).keyup(function (e) {
         if (e.keyCode === 27) {  // esc
             deselectAll();
         }
     });
 
     return {
         init: init,
         selectRow: selectRow,
         deselectAll: deselectAll,
         hoverRow: hoverRow,
         unhoverRow: unhoverRow,
         removeSelection : removeSelection,
 
         selectRange: function (row) {
             var toPos = holdingpen.oTable.fnGetPosition(row) + holdingpen.oSettings._iDisplayStart,
                 fromPos = holdingpen.rowIndexList[holdingpen.rowIndexList.length - 1],
                 i,
                 j,
                 current_row = null;
 
             if ((fromPos !== undefined) && (toPos !== undefined) && (row.checkbox.checked)) {
                 if (toPos > fromPos) {
                     for (i = fromPos + 1; i <= toPos; i++) {
                         j = i % holdingpen.oSettings._iDisplayLength;
                         if ($.inArray(i, holdingpen.rowIndexList) <= -1) {
                             current_row = holdingpen.oSettings.aoData[holdingpen.oSettings.aiDisplay[j]].nTr;
                             holdingpen.rowIndexList.push(i);
                             holdingpen.rowList.push(current_row.row_id);
                             current_row.style.background = "#ffa";
                             current_row.checkbox.checked = true;
                         }
                     }
                 } else {
                     for (i = fromPos - 1; i >= toPos; i--) {
                         j = i % holdingpen.oSettings._iDisplayLength;
                         if ($.inArray(i, holdingpen.rowIndexList) <= -1) {
                             current_row = holdingpen.oSettings.aoData[holdingpen.oSettings.aiDisplay[j]].nTr;
                             holdingpen.rowIndexList.push(i);
                             holdingpen.rowList.push(current_row.row_id);
                             current_row.style.background = "#ffa";
                             current_row.checkbox.checked = true;
                         }
                     }
                 }
                 document.getSelection().removeAllRanges();
             } else {
                 if ($.inArray(holdingpen.oTable.fnGetPosition(row), holdingpen.rowIndexList) <= -1) {
                     holdingpen.rowIndexList.push(holdingpen.oTable.fnGetPosition(row));
                     holdingpen.rowList.push(row.row_id);
                     row.style.background = "#ffa";
                     row.checkbox.checked = true;
                 } else {
                     $('#select-all')[0].checked = false;
                     holdingpen.rowList.splice(holdingpen.rowList.indexOf(row.row_id), 1);
                     holdingpen.rowIndexList.splice( holdingpen.rowIndexList.indexOf(row._DT_RowIndex + holdingpen.oSettings._iDisplayStart), 1);
                     row.style.background = "white";
                     row.checkbox.checked = false;
                 }
             }
         },
 
         rememberSelected: function (row, id) {
             if ($.inArray(id, holdingpen.rowList) > -1) {
                 row.style.background = "#ffa";
                 row.cells[0].firstChild.checked = true;
             }
         },
 
         getCellIndex: function (row, title) {
             var i,
                 temp_cell,
                 temp_cell_value,
                 trimmed_title;
             for (i = 0; i < holdingpen.oSettings.aoHeader[0].length; i++) {
                 temp_cell =  holdingpen.oSettings.aoHeader[0][i].cell;
                 temp_cell_value = temp_cell.innerText || temp_cell.textContent;
                 trimmed_title = $.trim(temp_cell_value);
                 if (trimmed_title === title) {
                     return i;
                 }
             }
         }
     };
-}($, WORKFLOWS_HOLDINGPEN);
-//***********************************
+});
diff --git a/invenio/modules/workflows/static/js/workflows/hp_tags.js b/invenio/modules/workflows/static/js/workflows/hp_tags.js
index 4ae2a2746..b9f6ae061 100644
--- a/invenio/modules/workflows/static/js/workflows/hp_tags.js
+++ b/invenio/modules/workflows/static/js/workflows/hp_tags.js
@@ -1,97 +1,96 @@
 /*
  * This file is part of Invenio.
  * Copyright (C) 2013, 2014 CERN.
  *
  * Invenio is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
  *
  * Invenio is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with Invenio; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  */
 
 // Tags functions
 //***********************************
-var WORKFLOWS_HP_TAGS = function ($, holdingpen) {
+define(["jquery", "js/workflows/hp_maintable", "js/workflows/hp_utilities"], function ($, holdingpen, utilities) {
     "use strict";
     var tagList = [];
 
     $("#tags").tagsinput({
         tagClass: function (item) {
             switch (item) {
             case 'In process':
                 return 'label label-warning';
             case 'Need action':
                 return 'label label-danger';
             case 'Waiting':
                 return 'label label-warning';
             case 'Done':
                 return 'label label-success';
             case 'New':
                 return 'label label-info';
             case 'Error':
                 return 'label label-danger';
             default:
                 return 'badge badge-warning';
             }
         }
     });
 
     var init = function () {
         $('.task-btn').on('click', function () {
             if ($.inArray($(this)[0].name, tagList) <= -1) {
                 var widget_name = $(this)[0].name;
                 $("#tags").tagsinput('add', $(this)[0].text);
-                WORKFLOWS_HP_UTILITIES.requestNewObjects();
+                utilities.requestNewObjects();
             } else {
                 closeTag(widget_name);
                 holdingpen.oTable.fnFilter('^$', 4, true, false);
                 holdingpen.oTable.fnDraw(false);
             }
         });
 
         $('#option-autorefresh').on('click', function () {
              console.log($('#option-autorefresh').hasClass("btn-danger"));
              if($('#option-autorefresh').hasClass("btn-danger")) {
                 $('#option-autorefresh').removeClass("btn-danger");
              } else {
                 $('#option-autorefresh').addClass("btn-danger");
              }
         });
 
         $('.version-selection').on('click', function () {
             if ($.inArray($(this)[0].name, tagList) <= -1) {
                 $('#tags').tagsinput('add', $(this)[0].text);
             }
         });
 
         $("#tags").on('itemRemoved', function (event) {
             tagList = $("#tags").val().split(',');
-            WORKFLOWS_HP_UTILITIES.requestNewObjects();
+            utilities.requestNewObjects();
         });
 
         $("#tags").on('itemAdded', function (event) {
             tagList =  $("#tags").val().split(',');
-            WORKFLOWS_HP_UTILITIES.requestNewObjects();
+            utilities.requestNewObjects();
         });
     };
 
     var closeTag = function (tag_name) {
         tagList.splice(tagList.indexOf(tag_name), 1);
         $('#tags').tagsinput('remove', tag_name);
     };
 
     return {
         init: init,
         tagList: function () { return tagList; },
         closeTag: closeTag
     };
-}($, WORKFLOWS_HOLDINGPEN);
-//***********************************
+});
diff --git a/invenio/modules/workflows/static/js/workflows/hp_utilities.js b/invenio/modules/workflows/static/js/workflows/hp_utilities.js
index 6861d691a..37dca76c7 100644
--- a/invenio/modules/workflows/static/js/workflows/hp_utilities.js
+++ b/invenio/modules/workflows/static/js/workflows/hp_utilities.js
@@ -1,77 +1,84 @@
 /*
  * This file is part of Invenio.
  * Copyright (C) 2013, 2014 CERN.
  *
  * Invenio is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
  *
  * Invenio is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with Invenio; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  */
 
 //Utility functions
 //***********************************
-var WORKFLOWS_HP_UTILITIES = function ($, holdingpen) {
+define(['jquery', 'js/workflows/hp_maintable'], function($, holdingpen) {
 
     $.fn.exists = function () {
         return this.length !== 0;
     };
 
     var _requestNewObjects = function () {
         my_data = JSON.stringify({'tags': holdingpen.tag.tagList()});
         $.ajax({
             type : "POST",
             url : holdingpen.context.holdingpen.url_load,
             data: my_data,
             contentType: "application/json;charset=UTF-8",
             traditional: true,
             success: function(result) {
                 holdingpen.oTable.fnDraw(false);
             }
         });
     };
 
     var utilities =  {
         requestNewObjects: _requestNewObjects,
 
         fnGetSelected: function (oTableLocal) {
             var aReturn = [],
                 aTrs = oTableLocal.fnGetNodes(),
                 i;
 
             for (i = 0; i < aTrs.length; i++) {
                 if ($(aTrs[i]).hasClass("row_selected")) {
                     aReturn.push(aTrs[i]);
                 }
             }
             return aReturn;
         },
 
         isInt: function (n) {
             return typeof n === "number" && n % 1 === 0;
         },
 
         emptyLists: function () {
             holdingpen.rowList = [];
             holdingpen.rowIndexList = [];
         },
 
         autorefresh: function () {
             window.setInterval( function() {
                 if($('#option-autorefresh').hasClass("btn-danger")) {
-                    WORKFLOWS_HP_UTILITIES.requestNewObjects();
+                    _requestNewObjects.requestNewObjects();
                 }}, 3000);
         },
+
+        bootstrap_alert: function (message, category) {
+            $("#alert-message").html(
+                '<div class="alert alert-' + category + ' alert-dismissable">' +
+                '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' +
+                '<span>' + message + '</span></div>'
+            );
+        },
     };
 
     return utilities;
-}($, WORKFLOWS_HOLDINGPEN);
-//***********************************
+});
diff --git a/invenio/modules/workflows/static/js/workflows/utilities.js b/invenio/modules/workflows/static/js/workflows/init.js
similarity index 54%
copy from invenio/modules/workflows/static/js/workflows/utilities.js
copy to invenio/modules/workflows/static/js/workflows/init.js
index 29d6707e4..625be26ec 100644
--- a/invenio/modules/workflows/static/js/workflows/utilities.js
+++ b/invenio/modules/workflows/static/js/workflows/init.js
@@ -1,32 +1,43 @@
 /*
  * This file is part of Invenio.
  * Copyright (C) 2014 CERN.
  *
  * Invenio is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
  *
  * Invenio is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with Invenio; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  */
 
-var WORKFLOWS_UTILITIES = (function ($) {
-
-    return {
-        bootstrap_alert: function (message, category) {
-            $("#alert-message").html(
-                '<div class="alert alert-' + category + ' alert-dismissable">' +
-                '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' +
-                '<span>' + message + '</span></div>'
-            );
-        }
-    };
-
-})(window.jQuery);
\ No newline at end of file
+require(
+  [
+    "jquery",
+    "datatables",
+    "datatables-plugins",
+    "datatables-tabletools",
+    "bootstrap-tagsinput",
+    "prism",
+    "js/workflows/maintable",
+    "js/workflows/holdingpen",
+    "js/workflows/tags",
+    "js/workflows/tags_menu",
+    "js/workflows/details",
+    "js/workflows/details_preview_menu",
+    "js/workflows/actions/approval",
+  ],
+  function() {
+    // This file is simply here to make sure the above dependencies are
+    // properly loaded and ready to be used by inline scripts.
+    //
+    // Without it, we have to rely on non-anonymous modules.
+    console.info("js/workflows/init is loaded")
+  }
+)
diff --git a/invenio/modules/workflows/static/js/workflows/utilities.js b/invenio/modules/workflows/static/js/workflows/maintable.js
similarity index 53%
rename from invenio/modules/workflows/static/js/workflows/utilities.js
rename to invenio/modules/workflows/static/js/workflows/maintable.js
index 29d6707e4..657e8af5a 100644
--- a/invenio/modules/workflows/static/js/workflows/utilities.js
+++ b/invenio/modules/workflows/static/js/workflows/maintable.js
@@ -1,32 +1,52 @@
 /*
  * This file is part of Invenio.
  * Copyright (C) 2014 CERN.
  *
  * Invenio is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
  *
  * Invenio is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with Invenio; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  */
 
-var WORKFLOWS_UTILITIES = (function ($) {
+'use strict';
 
-    return {
-        bootstrap_alert: function (message, category) {
-            $("#alert-message").html(
-                '<div class="alert alert-' + category + ' alert-dismissable">' +
-                '<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>' +
-                '<span>' + message + '</span></div>'
-            );
-        }
-    };
+define(
+  [
+    "js/workflows/holdingpen",
+    "js/workflows/tags",
+    "js/workflows/tags_menu",
+    "js/workflows/actions/approval"
+  ],
+  function(
+    HoldingPen,
+    HoldingPenTags,
+    HoldingPenTagsMenu,
+    ApprovalAction) {
 
-})(window.jQuery);
\ No newline at end of file
+    function initialize(context) {
+      HoldingPen.attachTo("#maintable", {
+        load_url: context.load_table_url,
+      });
+      HoldingPenTags.attachTo("#tags", {
+        tags: context.tags,
+      });
+      HoldingPenTagsMenu.attachTo("#tags-menu");
+
+      // Actions init
+      ApprovalAction.attachTo("#maintable", {
+        action_url: context.action_url
+      });
+    }
+
+    return initialize;
+  }
+);
diff --git a/invenio/modules/workflows/static/js/workflows/tags.js b/invenio/modules/workflows/static/js/workflows/tags.js
new file mode 100644
index 000000000..f492598d1
--- /dev/null
+++ b/invenio/modules/workflows/static/js/workflows/tags.js
@@ -0,0 +1,115 @@
+/*
+ * This file is part of Invenio.
+ * Copyright (C) 2014 CERN.
+ *
+ * Invenio is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Invenio is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Invenio; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+'use strict';
+
+define(
+  [
+    'jquery',
+    'flight/component',
+  ],
+  function(
+    $,
+    defineComponent) {
+
+    return defineComponent(HoldingPenTags);
+
+    /**
+    * .. js:class:: HoldingPenTags()
+    *
+    * Component for handling the filter/search available through the
+    * bootstrap-tagsinput element.
+    *
+    * :param Array tags: list of tags to add from the beginning.
+    * :param string versionMenuItemSelector: selector for HoldingPenTagsMenu.
+    *
+    */
+    function HoldingPenTags() {
+      this.attributes({
+        // URLs
+        tags: [],
+        versionMenuItemSelector: ".version-selection"
+      });
+
+      this.init_tags = function() {
+        var $node = this.$node;
+        $node.tagsinput({
+            tagClass: function (item) {
+                switch (item.value) {
+                  case 'In process':
+                    return 'label label-warning';
+                  case 'Need action':
+                    return 'label label-danger';
+                  case 'Waiting':
+                    return 'label label-warning';
+                  case 'Done':
+                    return 'label label-success';
+                  case 'New':
+                    return 'label label-info';
+                  case 'Error':
+                    return 'label label-danger';
+                  default:
+                    return 'badge badge-warning';
+                }
+            },
+            itemValue: 'value',
+            itemText: 'text'
+        });
+        // Add any existing tags
+        this.attr.tags.map(function(item) {
+          $node.tagsinput('add', item);
+        });
+      }
+
+      this.addTagFromMenu = function(ev, data) {
+        // Tagsinput already deal with existing tags.
+        this.$node.tagsinput('add', data);
+      }
+
+      this.addTagFromFreetext = function(ev) {
+        // ev.item is the freeinput text
+        if (ev.item.length != 0){
+          ev.item = {text: ev.item, value: ev.item};
+          ev.cancel = false;
+        }
+      }
+
+      this.onTagsUpdate = function() {
+        // Extract first only the "real" value (ignore translated ones)
+        var tags = this.$node.tagsinput("items").map(function(currentValue, index, array) {
+          return currentValue.value;
+        })
+
+        var data = {
+          'tags': tags
+        };
+        this.trigger(document, "reloadHoldingPenTable", data);
+      }
+
+
+      this.after('initialize', function() {
+        this.on(document, "initHoldingPenTable", this.init_tags);
+        this.on(document, "addTagFromMenu", this.addTagFromMenu);
+        this.on(document, "itemAdded", this.onTagsUpdate);
+        this.on(document, "itemRemoved", this.onTagsUpdate);
+        this.on(document, 'beforeFreeInputItemAdd', this.addTagFromFreetext);
+        console.log("Tags init");
+      });
+    }
+});
diff --git a/invenio/modules/workflows/static/js/workflows/tags_menu.js b/invenio/modules/workflows/static/js/workflows/tags_menu.js
new file mode 100644
index 000000000..68541dbc9
--- /dev/null
+++ b/invenio/modules/workflows/static/js/workflows/tags_menu.js
@@ -0,0 +1,61 @@
+/*
+ * This file is part of Invenio.
+ * Copyright (C) 2014 CERN.
+ *
+ * Invenio is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Invenio is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Invenio; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+'use strict';
+
+define(
+  [
+    'jquery',
+    'flight/component',
+  ],
+  function(
+    $,
+    defineComponent) {
+
+    return defineComponent(HoldingPenTagsMenu);
+
+    /**
+    * .. js:class:: HoldingPenTagsMenu()
+    *
+    * UI Component for the dropdown menu for selecting specifially the
+    * version/status of an object.
+    *
+    * :param string versionMenuItemSelector: DOM selector for each menu item.
+    *
+    */
+    function HoldingPenTagsMenu() {
+      this.attributes({
+        versionMenuItemSelector: ".version-selection"
+      });
+
+      this.addTagFromMenu = function(ev, data) {
+        this.trigger(document, "addTagFromMenu", {
+          value: data.el.name,
+          text: data.el.text,
+        });
+      }
+
+      this.after('initialize', function() {
+        this.on("click", {
+          versionMenuItemSelector: this.addTagFromMenu,
+        });
+        console.log("Tags menu init");
+      });
+    }
+});
diff --git a/invenio/modules/workflows/templates/workflows/actions/approval_main.html b/invenio/modules/workflows/templates/workflows/actions/approval_main.html
index f7d12cd7c..587b8d062 100644
--- a/invenio/modules/workflows/templates/workflows/actions/approval_main.html
+++ b/invenio/modules/workflows/templates/workflows/actions/approval_main.html
@@ -1,27 +1,27 @@
 {#
 ## This file is part of Invenio.
 ## Copyright (C) 2014 CERN.
 ##
 ## Invenio is free software; you can redistribute it and/or
 ## modify it under the terms of the GNU General Public License as
 ## published by the Free Software Foundation; either version 2 of the
 ## License, or (at your option) any later version.
 ##
 ## Invenio is distributed in the hope that it will be useful, but
 ## WITHOUT ANY WARRANTY; without even the implied warranty of
 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 ## General Public License for more details.
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with Invenio; if not, write to the Free Software Foundation, Inc.,
 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 #}
 
-<div class="alert alert-warning alert-dismissible" role="alert">
+<div class="alert alert-warning alert-dismissible approval-action" role="alert">
 	<button type="button" class="close" data-dismiss="alert">
 		<span aria-hidden="true">&times;</span>
 		<span class="sr-only">{{ _('Close') }}</span>
 	</button>
 	{{ _('Click on %(x_opening_tag)sAccept%(x_closing_tag)s to allow the record to continue.',
      x_opening_tag='<strong>'|safe, x_closing_tag='</strong>'|safe) }}
 </div>
diff --git a/invenio/modules/workflows/templates/workflows/actions/approval_mini.html b/invenio/modules/workflows/templates/workflows/actions/approval_mini.html
index ccd4b3349..1992bfdd5 100644
--- a/invenio/modules/workflows/templates/workflows/actions/approval_mini.html
+++ b/invenio/modules/workflows/templates/workflows/actions/approval_mini.html
@@ -1,34 +1,34 @@
 {#
 ## This file is part of Invenio.
 ## Copyright (C) 2014 CERN.
 ##
 ## Invenio is free software; you can redistribute it and/or
 ## modify it under the terms of the GNU General Public License as
 ## published by the Free Software Foundation; either version 2 of the
 ## License, or (at your option) any later version.
 ##
 ## Invenio is distributed in the hope that it will be useful, but
 ## WITHOUT ANY WARRANTY; without even the implied warranty of
 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 ## General Public License for more details.
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with Invenio; if not, write to the Free Software Foundation, Inc.,
 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 #}
 
 {% block approval_action %}
-
-  <p><a class="btn btn-success approval-action"
+<div class="approval-action">
+  <p><a class="btn btn-success approval-action-resolve"
         role="button"
         data-objectid="{{object.id}}"
         data-value="accept"
         data-url="{{resolve_url}}">{{_("Accept")}}</a></p>
   <p><a href="#"
-        class="approval-action"
+        class="approval-action-resolve"
         data-url="{{resolve_url}}"
         data-objectid="{{object.id}}"
         data-value="reject"
         role="button">{{_("Delete")}}</a></p>
-
+</div>
 {% endblock %}
diff --git a/invenio/modules/workflows/templates/workflows/actions/approval_side.html b/invenio/modules/workflows/templates/workflows/actions/approval_side.html
index f09b76f77..8802df527 100644
--- a/invenio/modules/workflows/templates/workflows/actions/approval_side.html
+++ b/invenio/modules/workflows/templates/workflows/actions/approval_side.html
@@ -1,37 +1,37 @@
 {#
 ## This file is part of Invenio.
 ## Copyright (C) 2014 CERN.
 ##
 ## Invenio is free software; you can redistribute it and/or
 ## modify it under the terms of the GNU General Public License as
 ## published by the Free Software Foundation; either version 2 of the
 ## License, or (at your option) any later version.
 ##
 ## Invenio is distributed in the hope that it will be useful, but
 ## WITHOUT ANY WARRANTY; without even the implied warranty of
 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 ## General Public License for more details.
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with Invenio; if not, write to the Free Software Foundation, Inc.,
 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 #}
 
 {% block approval_action %}
 
-<div id="approval-widget" class="jumbotron">
+<div class="approval-action jumbotron">
   <p>{{message}}</p>
-  <p><a class="btn btn-success btn-lg approval-action"
+  <p><a class="btn btn-success btn-lg approval-action-resolve"
         role="button"
         data-objectid="{{object.id}}"
         data-value="accept"
         data-url="{{resolve_url}}">{{_("Accept")}}</a></p>
-  <p><a class="btn btn-danger approval-action"
+  <p><a class="btn btn-danger approval-action-resolve"
         data-url="{{resolve_url}}"
         data-objectid="{{object.id}}"
         data-value="reject"
         role="button">{{_("Delete")}}</a></p>
 
 </div>
 {% endblock %}
 
diff --git a/invenio/modules/workflows/templates/workflows/hp_details.html b/invenio/modules/workflows/templates/workflows/hp_details.html
index e353718d6..40b3de094 100644
--- a/invenio/modules/workflows/templates/workflows/hp_details.html
+++ b/invenio/modules/workflows/templates/workflows/hp_details.html
@@ -1,323 +1,284 @@
 {#
 ## This file is part of Invenio.
 ## Copyright (C) 2012, 2013, 2014 CERN.
 ##
 ## Invenio is free software; you can redistribute it and/or
 ## modify it under the terms of the GNU General Public License as
 ## published by the Free Software Foundation; either version 2 of the
 ## License, or (at your option) any later version.
 ##
 ## Invenio is distributed in the hope that it will be useful, but
 ## WITHOUT ANY WARRANTY; without even the implied warranty of
 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 ## General Public License for more details.
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with Invenio; if not, write to the Free Software Foundation, Inc.,
 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 #}
 
 {% extends "workflows/hp_base.html" %}
 {% import 'workflows/utils.html' as utils %}
 
 {% block header%}
   {{ super() }}
-  {% bundles "workflows.js", "vendors.js", "vendors.css", "actions.js", "jquery.js" %}
+  {% bundles "workflows.js", "workflows.css", "jquery.js" %}
 {% endblock header %}
 
 {% block javascript %}
   {{ super() }}
+
   <script type="text/javascript">
-    $(document).ready(function(){
-      var context_url = "{{ url_for('holdingpen.get_context')|safe }}";
-      window.jQuery.ajax({
-        url: context_url,
-        success: function(data) {
-          WORKFLOWS_HP_DETAILS.init(data, {{ bwobject.id }});
-        }
-      })
+    require(["jquery",
+             "js/workflows/details"],
+            function($,
+                     initialize) {
+      var context = {
+        preview_url: "{{ url_for('holdingpen.entry_data_preview')|safe }}",
+        action_url: "{{ url_for('holdingpen.resolve_action')|safe }}",
+        id_object: "{{ bwobject.id }}"
+      }
+      initialize(context);
     });
   </script>
 {%- endblock javascript %}
 
 {% block hpbody %}
 
   {% block hp_navbar %}
-    <nav class="navbar navbar-default navbar-static-top" role="navigation">
+    <nav class="navbar navbar-default" role="navigation">
       <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
+      {% block top_left %}
         <ul class="nav navbar-nav">
           <li><a href="{{url_for('holdingpen.maintable')}}" class="navbar-btn-sm"><span class="glyphicon glyphicon-hand-left"></span> {{ _('Back') }}</a>
           </li>
-          <li class="dropdown">
-            <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ _('Actions') }}<b class="caret"></b></a>
-            <ul class="dropdown-menu" role="menu">
-              <li>
-                <button id="restart_button" class="btn btn-sm btn-primary btn-block" rel="popover" name="{{ bwobject.id }}"/>
-                  <i class="icon-repeat"></i>
-                  {{ _('Restart workflow from beginning') }}
-                </button>
-              </li>
-              <li>
-                <button id="restart_button_prev" class="btn btn-sm btn-block" rel="popover" name="{{ bwobject.id }}"/>
-                  <i class="icon-step-backward"></i>
-                  {{ _('Restart current task') }}
-                </button>
-              </li>
-              <li>
-                <button id="continue_button" class="btn btn-sm btn-block" rel="popover" name="{{ bwobject.id }}"/>
-                  <i class="icon-step-forward"></i>
-                  {{ _('Skip this task') }}
-                </button>
-              </li>
-              <li>
-                <button id="delete_btn" class="btn btn-sm btn-block btn-danger" data-toggle="modal" data-target="#confirmationModal" role="button">
-                  <i class="icon-trash"></i>
-                  {{ _('Delete this record') }}
-                </button>
-              </li>
-            </ul>
-          </li>
-          <div id="confirmationModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
-            <div class="modal-dialog">
-              <div class="modal-content">
-                <div class="modal-header">
-                  <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
-                  <h3 id="myModalLabel">{{ _('Please confirm') }}</h3>
-                </div>
-                <div class="modal-body">
-                  <p>{{ _('Are you sure you want to delete this record?') }}</p>
-                </div>
-                <div class="modal-footer">
-                  <button class="btn" data-dismiss="modal" aria-hidden="true">{{ _('Cancel') }}</button>
-                  <a class="btn btn-danger" href="{{ url_for('holdingpen.delete', objectid=bwobject.id) }}" >{{ _('Yes, delete this record') }}</a>
-                </div>
-              </div>
-            </div>
-          </div>
         </ul>
-      {% block previous_next %}
+      {% endblock %}
+      {% block top_right %}
         <div class="navbar-form navbar-right">
           <a href="{{ url_for('holdingpen.details', objectid=previous_object)}}"
              class="btn btn-default"
              {% if previous_object == None %}disabled="disabled"{% endif %}>
               <span class="glyphicon glyphicon-circle-arrow-left"></span>
               <strong>{{ _('Previous') }}</strong>
           </a>
 
           <a href="{{ url_for('holdingpen.details', objectid=next_object)}}"
              class="btn btn-default"
              {% if next_object == None %}disabled="disabled"{% endif %}>
                 <span class="glyphicon glyphicon-circle-arrow-right"></span>
                 <strong>{{ _('Next') }}</strong>
           </a>
 
         </div>
       {% endblock %}
       </div>
     </nav>
   {% endblock %}
 
   <div class="container" style="padding-left:0px;">
     <div class="row">
       <div class="col-md-3">
 
         {% block hpbody_details %}
 
           {% if "side" in rendered_actions %}
             {{ rendered_actions["side"]|safe }}
           {% endif %}
 
           <div class="panel panel-info">
             <div class="panel-heading">
               <h3 class="panel-title">{{ _('Workflow status') }}</h3>
             </div>
             <div class="panel-body">
               <p data-toggle="tooltip" data-placement="top" title="{{ workflow.name }}">{{ workflow.name|truncate(25, True) }}</p>
               {% if task_history %}
               <h6 class="pull-left">
                 <a role="button" style="cursor: pointer" data-toggle="collapse" data-target="#completed-tasks">
                   {{ _('Completed tasks') }}
                   <span class="caret"></span>
                 </a>
               </h6>
               {% endif %}
               <h6 class="pull-right">
                 <a role="button" style="cursor: pointer" data-toggle="collapse" data-target="#workflow-definition">
                   {{ _('Definition') }}
                   <span class="caret"></span>
                 </a>
               </h6>
               <div class="table table-striped">
                 <div class="row"></div>
                 {% set id = [] %}
                 {% if task_history %}
                   <div id="completed-tasks" class="collapse">
                     <div class="muted"><strong>{{ _('Completed tasks') }}:</strong></div>
                     <div class="list-group">
                       {% for item in task_history %}
                         {{ utils.display_task_history(item.get("nicename"), item.get("doc"), item.get("parameters"), item.get("name"), id|length) }}
                         {% do id.append(1) %}
                       {% endfor %}
                     </div>
                   </div>
                 {% endif %}
                 <div id="workflow-definition" class="collapse">
                   <div class="muted"><strong>{{ _('Workflow definition') }}:</strong></div>
                   {{ utils.display_workflow_definition(workflow_definition, id) }}
                 </div>
               </div>
             </div>
           </div>
           {% if bwobject.get_error_message() %}
           <div class="panel panel-danger">
             <div class="panel-heading">
               <h3 class="panel-title">{{ _('Error occurred') }}</h3>
             </div>
             <div class="panel-body">
               <h5>{{ bwobject.get_extra_data()['_last_task_name'] }}</h5>
               <div class="text-right">
                 <h6 id="show-more" class="text-right">
                   <a role="button" data-toggle="modal" style="cursor: pointer" data-target="#error_details_modal" class="float-right">
                     {{ _('Open details') }}</a>
                 </h6>
               </div>
 
               <div class="modal fade" id="error_details_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
                 <div class="modal-dialog">
                   <div class="modal-content">
                     <div class="modal-header">
                       <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
                       <h4 class="modal-title" id="myModalLabel">{{ _('Problem with') }}: {{ bwobject.get_extra_data()['_last_task_name'] }}</h4>
                     </div>
                     <div class="modal-body">
                       <p>{{ bwobject.get_error_message()[0] }}</p>
                       <p>{{ bwobject.get_error_message()[1] }}</p>
                     </div>
                     <div class="modal-footer">
                       <button type="button" class="btn btn-default" data-dismiss="modal">{{ _('Close') }}</button>
                     </div>
                   </div>
                 </div>
               </div>
             </div>
           </div>
 
           {% endif %}
 
           <div class="panel panel-info">
             <div class="panel-heading">
               <h3 class="panel-title">{{ _('Other information') }}</h3>
             </div>
             <div class="panel-body">
               <h6 class="pull-right">
               <a role="button" style="cursor: pointer" data-toggle="collapse" data-target="#record-metadata-table">
                 {{ _('More') }}
                 <span class="caret"></span>
               </a>
               </h6>
               <div class="row"></div>
               <div id="record-metadata-table" class="collapse">
                 <div class="table table-striped">
                     {% for key, value in info.items() %}
                       <b>{{ key }}</b> = {{ value }}
                       <hr>
                     {% endfor %}
                     <span class="label label-{{ bwobject._class}}">{{ bwobject.message }}</span>
                 </div>
               </div>
             </div>
           </div>
 
           {% if history_objects %}
             <div class="panel panel-info">
               <div class="panel-heading">
                 <h3 class="panel-title">{{ _('History') }}</h3>
               </div>
               <div class="panel-body">
                 <h6 class="pull-right">
                   <a role="button" style="cursor: pointer" data-toggle="collapse" data-target="#History">{{ _('More') }}<span class="caret"></span></a>
                 </h6>
                 <div class="row"></div>
                 <div id="History" class="collapse">
                   <div class="table table-striped">
                     {% for object in history_objects %}
                       {% if  object.id == bwobject.id %}
                         <a href="#">{{ _('current') }} </a> -
                         {% else %}
                         <a href="{{ url_for('holdingpen.details', objectid=object.id) }}" >{{ object.id }}</a> -
                       {% endif %}
                       <span class="label label-{{ object._class }}">{{ object.message }}</span>
                      {{ pretty_date(object.modified) }}
                     <hr>
                     {% endfor %}
                   </div>
                 </div>
               </div>
             </div>
           {% endif %}
         {% endblock %}
       </div>
       <div class="col-md-9">
         {% block hp_action_main %}
           {% if "main" in rendered_actions %}
             {{ rendered_actions["main"]|safe }}
           {% endif %}
         {% endblock %}
 
         {% if 'message' in bwobject.get_extra_data() and bwobject.get_action() != None %}
           <div id="usermessage" class="alert alert-warning alert-dismissible">
             {{ bwobject.get_extra_data()['_message'] }}
             <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
           </div>
         {% endif %}
         {% if bwobject.version == 1 %}
           <div id="successmessage" class="alert alert-success">
             {{ _('Workflow completed with success') }}
             <a class="close" data-dismiss="alert">×</a>
           </div>
         {% endif %}
 
         {% block hp_preview %}
           {{ _('Display:') }}
-          <div class="btn-group" name="object_preview_btn" data-toggle="buttons-radio">
-            <button class="preview btn btn-xs btn-primary active"
+          <div id="object-preview"
+               class="btn-group btn-group-xs"
+               name="object_preview_btn"
+               data-toggle="buttons-radio">
+            <button class="btn btn-primary preview"
+                    type="button"
                     data-id="{{ bwobject.id }}"
                     name="hd">HTML</button>
-            <button class="preview btn btn-xs btn-primary"
-                    data-id="{{ bwobject.id }}"
-                    name="xo">RAW</button>
-            <button class="preview btn btn-xs btn-primary"
+            <button class="btn btn-primary preview"
+                    type="button"
                     data-id="{{ bwobject.id }}"
                     name="xm">MARC</button>
           </div>
           <div id="object_preview_container{{bwobject.id}}" class="object_preview_container">
             {{ data_preview|safe }}
           </div>
         {% endblock %}
 
         {% block hp_task_results %}
           {% if task_results %}
             {% for template in task_results %}
               {{ template|safe }}
             {% endfor %}
           {% endif %}
         {% endblock %}
 
         {% block hp_task_logs %}
         <div class="panel panel-warning">
           <div class="panel-heading">
             {{ _("Task logs") }}
           </div>
           <div class="panel-body">
             <div class="list-group">
               {% for entry in bwobject.get_log() %}
                 <a href="#" class="list-group-item">{{ entry.created }}: {{ entry.message }}</a>
               {% endfor %}
             </div>
           </div>
         </div>
         {% endblock %}
       </div>
     </div>
   </div>
 {% endblock %}
diff --git a/invenio/modules/workflows/templates/workflows/hp_maintable.html b/invenio/modules/workflows/templates/workflows/hp_maintable.html
index 15587547f..9ce4a7913 100644
--- a/invenio/modules/workflows/templates/workflows/hp_maintable.html
+++ b/invenio/modules/workflows/templates/workflows/hp_maintable.html
@@ -1,109 +1,114 @@
 {#
 ## This file is part of Invenio.
 ## Copyright (C) 2014 CERN.
 ##
 ## Invenio is free software; you can redistribute it and/or
 ## modify it under the terms of the GNU General Public License as
 ## published by the Free Software Foundation; either version 2 of the
 ## License, or (at your option) any later version.
 ##
 ## Invenio is distributed in the hope that it will be useful, but
 ## WITHOUT ANY WARRANTY; without even the implied warranty of
 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 ## General Public License for more details.
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with Invenio; if not, write to the Free Software Foundation, Inc.,
 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 #}
 {% extends "workflows/hp_base.html" %}
 {% import 'workflows/utils.html' as utils %}
 
-{% block header%}
+{% block header %}
   {{ super() }}
-  {% bundles "workflows.js", "vendors.js", "datatables.js", "vendors.css", "actions.js", "jquery.js" %}
+  {% bundles "workflows.js", "workflows.css", "jquery.js" %}
 {% endblock header %}
 
 {% block javascript %}
   {{ super() }}
 
-
   <script type="text/javascript">
-    $(document).ready(function(){
-      var context_url = "{{ url_for('holdingpen.get_context')|safe }}";
-      window.jQuery.ajax({
-        url: context_url,
-        success: function(data) {
-          WORKFLOWS_HOLDINGPEN.init(data);
-          WORKFLOWS_HOLDINGPEN.init_datatable(WORKFLOWS_HP_SELECTION);
-        }
-      });
+    require(["jquery",
+             "js/workflows/maintable"],
+            function($,
+                     initialize) {
+      var context = {
+        load_table_url: "{{ url_for('holdingpen.load_table')|safe }}",
+        tags: JSON.parse('{{tags|safe}}'),
+        action_url: "{{ url_for('holdingpen.resolve_action')|safe }}"
+      }
+      initialize(context);
+      $(document).trigger("initHoldingPenTable");
     });
   </script>
+
 {% endblock javascript %}
 
 {% block hpbody %}
   <nav class="navbar navbar-default" role="navigation">
     <div id="bs-example-navbar-collapse-1" class="collapse navbar-collapse">
       <ul class="nav navbar-nav">
         <p class="navbar-text" style="margin-right:0px; color:light gray;">{{ _('Show Records by') }}:</p>
         <li class="dropdown">
           <a class="dropdown-toggle dropdown-headline" data-toggle="dropdown" href="#">{{ _('Actions') }}<b class="caret"></b></a>
           <ul class="dropdown-menu">
-            {% if user_list %}
+            {% if action_list %}
               {% set i = 0 %}
               {% for task, object_count in action_list.items() %}
                 <li><a id="task{{i}}" class="task-btn" tabindex="-1" name="{{task}}">{{ task }}: {{ object_count }}</a></li>
                 {% set i = i + 1 %}
               {% endfor %}
             {% else %}
-              <li><a class="task-btn">{{ _('No actions left') }}</a></li>
+              <li><a class="task-btn">{{ _('No actions') }}</a></li>
             {% endif %}
           </ul>
         </li>
         <li class="dropdown">
           <a href="#" class="dropdown-toggle dropdown-headline" data-toggle="dropdown">{{ _('Status') }}<b class="caret"></b></a>
-          <ul class="dropdown-menu" role="menu">
+          <ul id="tags-menu" class="dropdown-menu" role="menu">
             <li><a id="version-halted" class="version-selection" name="Need action">{{ _('Need action') }}</a></li>
             <li><a id="version-halted" class="version-selection" name="Waiting">{{ _('Waiting') }}</a></li>
             <li><a id="version-completed" class="version-selection" name="Done">{{ _('Done') }}</a></li>
             <li><a id="version-running" class="version-selection" name="In process">{{ _('In process') }}</a></li>
             <li><a id="version-initial" class="version-selection" name="New">{{ _('New') }}</a></li>
             <li><a id="version-error" class="version-selection" name="Error">{{ _('Error') }}</a></li>
           </ul>
         </li>
-        <li class="dropdown">
-          <a href="#" class="dropdown-toggle dropdown-headline" data-toggle="dropdown">{{ _('Options') }}<b class="caret"></b></a>
-          <ul class="dropdown-menu" role="menu">
-            <li><a id="option-autorefresh" name="autorefresh-option">{{ _('Auto-refresh') }}</a></li>
-          </ul>
-        </li>
       </ul>
       <ul id="navbar-right" class="nav navbar-nav navbar-right">
       </ul>
     </div>
   </nav>
-  <input class="tags" id="tags" type="text" placeholder="{{ _("Add to search") }}" value="{{tags}}"/>
+
+  <input class="tags"
+         id="tags"
+         type="text"
+         placeholder="{{ _("Add to search") }}"
+         value="" />
 
   <div class="container">
     <div class="row">
-      <table id="maintable" cellpadding="0" cellspacing="0" border="0" class="table table-bordered">
+      <table id="maintable"
+             cellpadding="0"
+             cellspacing="0"
+             border="0"
+             class="table table-bordered">
         <thead>
           <tr>
+            <th></th>
             <th>{{ _('Id') }}</th>
-            <th><input id="select-all" type="checkbox"></th>
             <th>{{ _('Title') }}</th>
             <th>{{ _('Description') }}</th>
             <th>{{ _('Created') }}</th>
             <th>{{ _('Status') }}</th>
             <th>{{ _('Type') }}</th>
             <th>{{ _('Actions') }}</th>
           </tr>
         </thead>
         <tbody>
 
         </tbody>
       </table>
     </div>
   </div>
 {% endblock %}
diff --git a/invenio/modules/workflows/templates/workflows/row_formatter.html b/invenio/modules/workflows/templates/workflows/row_formatter.html
index 99d18783f..fd2d333d3 100644
--- a/invenio/modules/workflows/templates/workflows/row_formatter.html
+++ b/invenio/modules/workflows/templates/workflows/row_formatter.html
@@ -1,40 +1,39 @@
 {#
 ## This file is part of Invenio.
 ## Copyright (C) 2014 CERN.
 ##
 ## Invenio is free software; you can redistribute it and/or
 ## modify it under the terms of the GNU General Public License as
 ## published by the Free Software Foundation; either version 2 of the
 ## License, or (at your option) any later version.
 ##
 ## Invenio is distributed in the hope that it will be useful, but
 ## WITHOUT ANY WARRANTY; without even the implied warranty of
 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 ## General Public License for more details.
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with Invenio; if not, write to the Free Software Foundation, Inc.,
 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 #}
 
-{{ object.id }}
 <!--sep-->
-<input type="checkbox" class="hp-check">
+{{ object.id }}
 <!--sep-->
 <a href="{{url_for('holdingpen.details', objectid=object.id)}}">
   {{ title }}
 </a>
 <!--sep-->
 {{ description|safe }}
 <!--sep-->
 {{ pretty_date(object.created) }}
 <!--sep-->
 <span class="label label-{{object._class}}">{{ object.message }}</span>
 <!--sep-->
 {{ object.data_type }}
 <!--sep-->
 {% if mini_action != None %}
   {% set action = action() %}
   {{ action.render_mini(object)|safe }}
 {% endif %}
 
diff --git a/invenio/modules/workflows/views/holdingpen.py b/invenio/modules/workflows/views/holdingpen.py
index 63040f7a7..280a50897 100644
--- a/invenio/modules/workflows/views/holdingpen.py
+++ b/invenio/modules/workflows/views/holdingpen.py
@@ -1,442 +1,447 @@
 # -*- coding: utf-8 -*-
 ##
 ## This file is part of Invenio.
 ## Copyright (C) 2013, 2014 CERN.
 ##
 ## Invenio is free software; you can redistribute it and/or
 ## modify it under the terms of the GNU General Public License as
 ## published by the Free Software Foundation; either version 2 of the
 ## License, or (at your option) any later version.
 ##
 ## Invenio is distributed in the hope that it will be useful, but
 ## WITHOUT ANY WARRANTY; without even the implied warranty of
 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 ## General Public License for more details.
 ##
 ## You should have received a copy of the GNU General Public License
 ## along with Invenio; if not, write to the Free Software Foundation, Inc.,
 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 """
 Holding Pen is a web interface overlay for all BibWorkflowObject's.
 
 This area is targeted to catalogers and administrators for inspecting
 and reacting to workflows executions. More importantly, allowing users to deal
 with halted workflows.
 
 For example, accepting submissions or other tasks.
 """
+
 import os
+import json
 
 from six import text_type
 
 from flask import (render_template, Blueprint, request, jsonify,
                    url_for, flash, session, send_from_directory)
 from flask.ext.login import login_required
 from flask.ext.breadcrumbs import default_breadcrumb_root, register_breadcrumb
 from flask.ext.menu import register_menu
 
 from invenio.base.decorators import templated, wash_arguments
 from invenio.base.i18n import _
 from invenio.ext.principal import permission_required
 from invenio.utils.date import pretty_date
 
 from ..models import BibWorkflowObject, Workflow, ObjectVersion
 from ..registry import actions
 from ..utils import (sort_bwolist, extract_data, get_action_list,
                      get_formatted_holdingpen_object,
                      get_holdingpen_objects,
                      get_rendered_task_results,
                      get_previous_next_objects)
 from ..engine import WorkflowStatus
 from ..api import continue_oid_delayed, start_delayed
 from ..acl import viewholdingpen
 
 blueprint = Blueprint('holdingpen', __name__, url_prefix="/admin/holdingpen",
                       template_folder='../templates',
                       static_folder='../static')
 
 default_breadcrumb_root(blueprint, '.holdingpen')
 HOLDINGPEN_WORKFLOW_STATES = {
     ObjectVersion.HALTED: {'message': _('Need Action'), 'class': 'danger'},
     ObjectVersion.WAITING: {'message': _('Waiting'), 'class': 'warning'},
     ObjectVersion.ERROR: {'message': _('Error'), 'class': 'danger'},
     ObjectVersion.FINAL: {'message': _('Done'), 'class': 'success'},
     ObjectVersion.INITIAL: {'message': _('New'), 'class': 'info'},
     ObjectVersion.RUNNING: {'message': _('In process'), 'class': 'warning'}
 }
 
 
 @blueprint.route('/', methods=['GET', 'POST'])
 @blueprint.route('/index', methods=['GET', 'POST'])
 @login_required
 @register_menu(blueprint, 'personalize.holdingpen', _('Your Pending Actions'))
 @register_breadcrumb(blueprint, '.', _('Holdingpen'))
 @templated('workflows/hp_index.html')
 def index():
     """
     Display main interface of Holdingpen.
 
     Acts as a hub for catalogers (may be removed)
     """
     # FIXME: Add user filtering
     bwolist = get_holdingpen_objects()
     action_list = get_action_list(bwolist)
 
     return dict(tasks=action_list)
 
 
 @blueprint.route('/maintable', methods=['GET', 'POST'])
 @register_breadcrumb(blueprint, '.records', _('Records'))
 @login_required
 @permission_required(viewholdingpen.name)
 @templated('workflows/hp_maintable.html')
 def maintable():
     """Display main table interface of Holdingpen."""
     bwolist = get_holdingpen_objects()
     action_list = get_action_list(bwolist)
     tags = session.get("holdingpen_tags", list())
 
     if 'version' in request.args:
         for key, value in ObjectVersion.MAPPING.items():
             if value == int(request.args.get('version')):
                 if key not in tags:
                     tags.append(key)
 
-    tags_to_print = ""
+    tags_to_print = []
     for tag in tags:
         if tag:
-            tags_to_print += tag + ','
+            tags_to_print.append({
+                "text": str(_(tag)),
+                "value": tag,
+            })
     return dict(bwolist=bwolist,
                 action_list=action_list,
-                tags=tags_to_print)
+                tags=json.dumps(tags_to_print))
 
 
 @blueprint.route('/details/<int:objectid>', methods=['GET', 'POST'])
 @register_breadcrumb(blueprint, '.details', _("Record Details"))
 @login_required
 @permission_required(viewholdingpen.name)
 def details(objectid):
     """Display info about the object."""
     from ..utils import get_workflow_info
     from invenio.ext.sqlalchemy import db
     from itertools import groupby
 
     of = "hd"
     bwobject = BibWorkflowObject.query.get(objectid)
     if 'holdingpen_current_ids' in session:
         objects = session['holdingpen_current_ids']
     else:
         bwobject_list = get_holdingpen_objects([str(ObjectVersion.HALTED)])
         objects = []
         for obj in bwobject_list:
             version = extract_data(obj)['w_metadata'].status
             if version == WorkflowStatus.HALTED:
                 objects.append(obj.id)
 
     previous_object, next_object = get_previous_next_objects(objects, objectid)
     formatted_data = bwobject.get_formatted_data(of)
     extracted_data = extract_data(bwobject)
 
     action_name = bwobject.get_action()
     if action_name:
         action = actions[action_name]
         rendered_actions = action().render(bwobject)
     else:
         rendered_actions = {}
 
     if bwobject.id_parent:
         history_objects_db_request = BibWorkflowObject.query.filter(
             db.or_(BibWorkflowObject.id_parent == bwobject.id_parent,
                    BibWorkflowObject.id == bwobject.id_parent,
                    BibWorkflowObject.id == bwobject.id)).all()
     else:
         history_objects_db_request = BibWorkflowObject.query.filter(
             db.or_(BibWorkflowObject.id_parent == bwobject.id,
                    BibWorkflowObject.id == bwobject.id)).all()
 
     history_objects = {}
     temp = groupby(history_objects_db_request,
                    lambda x: x.version)
     for key, value in temp:
         if key != ObjectVersion.RUNNING:
             value = list(value)
             value.sort(key=lambda x: x.modified, reverse=True)
             history_objects[key] = value
 
     history_objects = sum(history_objects.values(), [])
     for obj in history_objects:
         obj._class = HOLDINGPEN_WORKFLOW_STATES[obj.version]["class"]
         obj.message = HOLDINGPEN_WORKFLOW_STATES[obj.version]["message"]
     results = get_rendered_task_results(bwobject)
 
     workflow_definition = get_workflow_info(extracted_data['workflow_func'])
     task_history = bwobject.get_extra_data().get('_task_history', [])
     return render_template('workflows/hp_details.html',
                            bwobject=bwobject,
                            rendered_actions=rendered_actions,
                            history_objects=history_objects,
                            bwparent=extracted_data['bwparent'],
                            info=extracted_data['info'],
                            log=extracted_data['logtext'],
                            data_preview=formatted_data,
                            workflow=extracted_data['w_metadata'],
                            task_results=results,
                            previous_object=previous_object,
                            next_object=next_object,
                            task_history=task_history,
                            workflow_definition=workflow_definition,
                            versions=ObjectVersion,
                            pretty_date=pretty_date,
                            )
 
 
 @blueprint.route('/files/<int:object_id>/<path:filename>',
                  methods=['POST', 'GET'])
 @login_required
 @permission_required(viewholdingpen.name)
 def get_file_from_task_result(object_id=None, filename=None):
     """Send the requested file to user from a workflow task result.
 
     Expects a certain file meta-data structure in task result:
 
     .. code-block:: python
 
         {
             "type": "Fulltext",
             "filename": "file.pdf",
             "full_path": "/path/to/file",
         }
 
     """
     bwobject = BibWorkflowObject.query.get(object_id)
     task_results = bwobject.get_tasks_results()
     if filename in task_results and task_results[filename]:
         fileinfo = task_results[filename][0].get("result", dict())
         directory = os.path.split(fileinfo.get("full_path", ""))[0]
         return send_from_directory(directory, filename)
 
 
 @blueprint.route('/restart_record', methods=['GET', 'POST'])
 @login_required
 @permission_required(viewholdingpen.name)
 @wash_arguments({'objectid': (int, 0)})
 def restart_record(objectid, start_point='continue_next'):
     """Restart the initial object in its workflow."""
     bwobject = BibWorkflowObject.query.get(objectid)
 
     workflow = Workflow.query.filter(
         Workflow.uuid == bwobject.id_workflow).first()
 
     start_delayed(workflow.name, [bwobject.get_data()])
     return 'Record Restarted'
 
 
 @blueprint.route('/continue_record', methods=['GET', 'POST'])
 @login_required
 @permission_required(viewholdingpen.name)
 @wash_arguments({'objectid': (int, 0)})
 def continue_record(objectid):
     """Continue workflow for current object."""
     continue_oid_delayed(oid=objectid, start_point='continue_next')
     return 'Record continued workflow'
 
 
 @blueprint.route('/restart_record_prev', methods=['GET', 'POST'])
 @login_required
 @permission_required(viewholdingpen.name)
 @wash_arguments({'objectid': (int, 0)})
 def restart_record_prev(objectid):
     """Restart the last task for current object."""
     continue_oid_delayed(oid=objectid, start_point="restart_task")
     return 'Record restarted current task'
 
 
 @blueprint.route('/delete', methods=['GET', 'POST'])
 @login_required
 @permission_required(viewholdingpen.name)
 @wash_arguments({'objectid': (int, 0)})
 def delete_from_db(objectid):
     """Delete the object from the db."""
     BibWorkflowObject.delete(objectid)
     return 'Record Deleted'
 
 
 @blueprint.route('/delete_multi', methods=['GET', 'POST'])
 @login_required
 @permission_required(viewholdingpen.name)
 @wash_arguments({'bwolist': (text_type, "")})
 def delete_multi(bwolist):
     """Delete list of objects from the db."""
     from ..utils import parse_bwids
 
     bwolist = parse_bwids(bwolist)
     for objectid in bwolist:
         delete_from_db(objectid)
     return 'Records Deleted'
 
 
 @blueprint.route('/resolve', methods=['GET', 'POST'])
 @login_required
 @permission_required(viewholdingpen.name)
 @wash_arguments({'objectid': (text_type, '-1')})
 def resolve_action(objectid):
     """Resolve the action taken.
 
     Will call the resolve() function of the specific action.
     """
     bwobject = BibWorkflowObject.query.get(int(objectid))
     action_name = bwobject.get_action()
     action_form = actions[action_name]
     res = action_form().resolve(bwobject)
     return jsonify(res)
 
 
 @blueprint.route('/entry_data_preview', methods=['GET', 'POST'])
 @login_required
 @permission_required(viewholdingpen.name)
 @wash_arguments({'objectid': (text_type, '0'),
                  'of': (text_type, None)})
 def entry_data_preview(objectid, of):
     """Present the data in a human readble form or in xml code."""
     bwobject = BibWorkflowObject.query.get(int(objectid))
     if not bwobject:
         flash("No object found for %s" % (objectid,))
         return jsonify(data={})
     formatted_data = bwobject.get_formatted_data(of)
     return jsonify(data=formatted_data)
 
 
 @blueprint.route('/get_context', methods=['GET', 'POST'])
 @login_required
 @permission_required(viewholdingpen.name)
 def get_context():
     """Return the a JSON structure with URL maps and actions."""
     context = {}
     context['url_prefix'] = blueprint.url_prefix
     context['holdingpen'] = {
         "url_load": url_for('holdingpen.load_table'),
         "url_preview": url_for('holdingpen.entry_data_preview'),
         "url_restart_record": url_for('holdingpen.restart_record'),
         "url_restart_record_prev": url_for('holdingpen.restart_record_prev'),
         "url_continue_record": url_for('holdingpen.continue_record'),
     }
 
     return jsonify(context)
 
 
 @blueprint.route('/load_table', methods=['GET', 'POST'])
 @login_required
 @permission_required(viewholdingpen.name)
 @templated('workflows/hp_maintable.html')
 def load_table():
     """Get JSON data for the Holdingpen table.
 
     Function used for the passing of JSON data to DataTables:
 
     1. First checks for what record version to show
     2. Then the sorting direction.
     3. Then if the user searched for something.
 
     :return: JSON formatted str from dict of DataTables args.
     """
     tags = session.setdefault("holdingpen_tags", list())
     if request.method == "POST":
         if request.json and "tags" in request.json:
             tags = request.json["tags"]
             session["holdingpen_tags"] = tags
         # This POST came from tags-input.
         # We return here as DataTables will call a GET here after.
         return None
 
     i_sortcol_0 = request.args.get('iSortCol_0',
                                    session.get('iSortCol_0', 0))
     s_sortdir_0 = request.args.get('sSortDir_0',
                                    session.get('sSortDir_0', None))
 
     session["holdingpen_iDisplayStart"] = int(request.args.get(
         'iDisplayStart', session.get('iDisplayLength', 10))
     )
     session["holdingpen_iDisplayLength"] = int(
         request.args.get('iDisplayLength', session.get('iDisplayLength', 0))
     )
     session["holdingpen_sEcho"] = int(
         request.args.get('sEcho', session.get('sEcho', 0))
     ) + 1
 
     bwobject_list = get_holdingpen_objects(tags)
 
     if (i_sortcol_0 and s_sortdir_0)\
             or ("holdingpen_iSortCol_0" in session
                 and "holdingpen_sSortDir_0" in session):
         if i_sortcol_0:
             i_sortcol = int(str(i_sortcol_0))
         else:
             i_sortcol = session["holdingpen_iSortCol_0"]
 
         if not ('holdingpen_iSortCol_0' in session
                 and "holdingpen_sSortDir_0" in session):
             bwobject_list = sort_bwolist(bwobject_list, i_sortcol, s_sortdir_0)
         elif i_sortcol != session['holdingpen_iSortCol_0']\
                 or s_sortdir_0 != session['holdingpen_sSortDir_0']:
             bwobject_list = sort_bwolist(bwobject_list, i_sortcol, s_sortdir_0)
         else:
             bwobject_list = sort_bwolist(bwobject_list,
                                          session["holdingpen_iSortCol_0"],
                                          session["holdingpen_sSortDir_0"])
 
     session["holdingpen_iSortCol_0"] = i_sortcol_0
     session["holdingpen_sSortDir_0"] = s_sortdir_0
 
     table_data = {'aaData': [],
                   'iTotalRecords': len(bwobject_list),
                   'iTotalDisplayRecords': len(bwobject_list),
                   'sEcho': session["holdingpen_sEcho"]}
 
     # Add current ids in table for use by previous/next
     record_ids = [o.id for o in bwobject_list]
     session['holdingpen_current_ids'] = record_ids
 
     records_showing = 0
     display_start = session["holdingpen_iDisplayStart"]
     display_end = display_start + session["holdingpen_iDisplayLength"]
     for bwo in bwobject_list[display_start:display_end]:
         records_showing += 1
         action_name = bwo.get_action()
         action_message = bwo.get_action_message()
         if not action_message:
             action_message = ""
 
         preformatted = get_formatted_holdingpen_object(bwo)
 
         action = actions.get(action_name, None)
         mini_action = None
         if action:
             mini_action = getattr(action, "render_mini", None)
 
         extra_data = bwo.get_extra_data()
         record = bwo.get_data()
 
         if not hasattr(record, "get"):
             try:
                 record = dict(record)
             except (ValueError, TypeError):
                 record = {}
         bwo._class = HOLDINGPEN_WORKFLOW_STATES[bwo.version]["class"]
         bwo.message = HOLDINGPEN_WORKFLOW_STATES[bwo.version]["message"]
         row = render_template('workflows/row_formatter.html',
                               title=preformatted["title"],
                               object=bwo,
                               record=record,
                               extra_data=extra_data,
                               description=preformatted["description"],
                               action=action,
                               mini_action=mini_action,
                               action_message=action_message,
                               pretty_date=pretty_date,
                               version=ObjectVersion,
                               )
 
         row = row.split("<!--sep-->")
 
         table_data['aaData'].append(row)
     return jsonify(table_data)