Here's how I ended up doing it.
Let's assume my dataflow pge is accessed via vendor/module/dataflow
My controller has got the following:
public function dataflowAction()
{
$this->loadLayout();
$this->renderLayout();
}
Then in my adminhtml layout file I have:
<adminhtml_module_dataflow>
<remove name="root"/>
<block type="adminhtml/page" name="convert_root" output="toHtml" template="page.phtml">
<block type="adminhtml/page_head" name="convert_root_head" as="head" template="page/head.phtml">
<action method="addJs"><script>prototype/prototype.js</script></action>
<action method="addJs"><script>prototype/validation.js</script></action>
<action method="addJs"><script>varien/js.js</script></action>
<action method="addJs"><script>mage/translate.js</script></action>
<action method="addJs"><script>mage/adminhtml/tools.js</script></action>
</block>
<block type="adminhtml/template" name="dataflow" template="vendor/module/dataflow.phtml" output="toHtml"/>
</block>
</adminhtml_module_dataflow>
In my vendor/module/dataflow.phtml
I implemented the following:
<style type="text/css" >
ul { list-style-type:none; padding:0; margin:0; }
li { margin-left:0; border:1px solid #ccc; margin:2px; padding:2px 2px 2px 2px; font:normal 12px sans-serif; }
img { margin-right:5px; }
</style>
<ul id="processRows"></ul>
<script type="text/javascript">
tplRowSuccess = new Template('<li style="background-color:#DDF;"><img src="<?php echo $this->getSkinUrl('images/fam_bullet_success.gif');?>" class="v-middle" /> #{text}</li>');
tplRowWait = '<li class="wait"><img src="<?php echo $this->getSkinUrl('images/rule-ajax-loader.gif');?>" class="v-middle" /></li>';
tplRowDone = '<li class="wait"><img src="<?php echo $this->getSkinUrl('images/note_msg_icon.gif');?>" class="v-middle" /> <?php echo $this->__('Done, redirecting in 5 seconds') ?></li>';
function runProcess(data) {
$$('.wait').each(function(el) {
el.remove();
});
Element.insert($("processRows"), tplRowSuccess.evaluate(data));
if (data.redirect) {
Element.insert($("processRows"), tplRowDone);
window.scrollTo(0,9000);
window.setTimeout(function(){
window.location = data.url;
},5000);
return true;
}
Element.insert($("processRows"), tplRowWait);
window.scrollTo(0,9000);
var url = "";
if (data.url.indexOf("form_key") != -1) {
url = data.url;
} else {
url = data.url + "&form_key=" + window.FORM_KEY;
}
new Ajax.Request(url, {
method: "get",
onSuccess: function(transport) {
if (transport.responseText.isJSON()) {
runProcess(transport.responseText.evalJSON());
}
}
}
);
}
runProcess({'text':'<?php echo $this->__('Starting catalog refresh...') ?>', 'url':'<?php echo $this->getUrl('*/*/refresh/', array('id' => $this->getRequest()->getParam('id'))) ?>?isAjax=true'});
</script>
Finally, in order to be able to get the results I implemented the following in my controller:
public function refreshAction()
{
try {
// The code here should process 100 entities and return an array with the number of entities processed at the 'current' key as well as the total number of entities at the 'total' key
// Response array
$response = array();
if (array_key_exists('total', $result)
&& $result['total']
&& array_key_exists('current', $result)
&& $result['current']
) {
// Processing the results
$response['text'] = $this->__('Total %1$s, processed %2$s records (%3$s%%)...', $result['total'], $result['current'], round($result['current']*100/$result['total'], 2));
if ($result['current'] < $result['total']) {
// We keep refreshing while we didn't reach the total
$response['url'] = $this->getUrl('*/*/refresh/', $result) . "?isAjax=true";
} else {
// We redirect when it's done
$response['url'] = $this->getUrl('*/*/edit/', array('id' => $id));
$response['redirect'] = true;
}
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($response));
return $this;
}
}
catch(Exception $e)
{
Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
}
$response['url'] = $this->getUrl('*/*/edit/', array('id' => $this->getRequest()->getParam('id')));
$response['redirect'] = true;
$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($response));
return $this;
}