Permalink
Browse files

Update core.tasks - Temporary SQL implementation not in a separate pl…

…ugin.
  • Loading branch information...
1 parent fd2f929 commit bc5c0f905e993b2de650b173c8692b6c33bf1928 @cdujeu cdujeu committed May 19, 2016
@@ -3,6 +3,7 @@ CREATE TABLE IF NOT EXISTS `ajxp_tasks` (
`userId` varchar(255) NOT NULL,
`wsId` varchar(32) NOT NULL,
`status` int(11) NOT NULL,
+ `progress` int(11) NOT NULL,
`schedule` text NOT NULL,
`action` text NOT NULL,
`parameters` mediumtext NOT NULL,
@@ -0,0 +1,206 @@
+(function(global){
+
+ class Task{
+
+ constructor(data){
+ this._internal = data;
+ }
+
+ isStoppable(){
+ return this._internal['flags'] & Task.FLAG_STOPPABLE;
+ }
+
+ isResumable(){
+ return this._internal['flags'] & Task.FLAG_RESUMABLE;
+ }
+
+ hasProgress(){
+ return this._internal['flags'] & Task.FLAG_HAS_PROGRESS;
+ }
+
+ getLabel(){
+ return this._internal['label'];
+ }
+
+ getStatus(){
+ return this._internal['status'];
+ }
+
+ getStatusMessage(){
+ return this._internal['statusMessage'];
+ }
+
+ getData(){
+ return this._internal;
+ }
+
+ pause(){
+ TaskAPI.updateTaskStatus(this, Task.STATUS_PAUSED);
+ }
+
+ }
+
+ Task.STATUS_PENDING = 1;
+ Task.STATUS_RUNNING = 2;
+ Task.STATUS_COMPLETE = 4;
+ Task.STATUS_FAILED = 8;
+ Task.STATUS_PAUSED = 16;
+
+ Task.FLAG_STOPPABLE = 1;
+ Task.FLAG_RESUMABLE = 2;
+ Task.FLAG_HAS_PROGRESS = 4;
+
+ class TaskAPI{
+
+ static createTask(task){
+ PydioApi.getClient().request({
+ "get_action":"task_create",
+ "task":JSON.stringify(task.getData())
+ });
+ }
+
+ static loadTasks(callback){
+ PydioApi.getClient().request({
+ "get_action":"tasks_list"
+ }, function(transport){
+ if(transport.responseJSON){
+ let tasks = transport.responseJSON.map(function(taskData){
+ return new Task(taskData);
+ });
+ callback(tasks);
+ }
+ }.bind(this));
+
+ }
+
+ static updateTaskStatus(task, status){
+ PydioApi.getClient().request({
+ "get_action":"task_toggle_status",
+ "taskId":task.getData()['id'],
+ "status": status
+ });
+
+ }
+
+ }
+
+ var STORE_INSTANCE = null;
+
+ class TaskStore extends Observable{
+
+ static getInstance(){
+ if (!STORE_INSTANCE) STORE_INSTANCE = new TaskStore();
+ return STORE_INSTANCE;
+ }
+
+ constructor(){
+ super();
+ // Start listening to server messages
+ global.pydio.observe("server_message", function(xml){
+ var task = XMLUtils.XPathSelectSingleNode(xml, 'tree/task');
+ if(task){
+ let data = task.getAttribute("data");
+ let t = JSON.parse(data);
+ if( t instanceof Object && t.id){
+ let taskObject = new Task(t);
+ this._tasksList.set(t.id, taskObject);
+ this.notify("tasks_updated", taskObject);
+ }
+ }
+ }.bind(this));
+ }
+
+ static enqueueActionTask(label, action, parameters = {}, nodes = [], flags = Task.FLAG_STOPPABLE){
+ let task = {
+ label: label,
+ flags: flags,
+ status: 1,
+ statusMessage : '',
+ action: action,
+ parameters: parameters,
+ nodes: nodes
+ };
+ TaskAPI.createTask(new Task(task));
+ }
+
+
+ getTasks(){
+ if(this._tasksList == undefined){
+ var taskMap = new Map();
+ TaskAPI.loadTasks(function(tasks){
+ tasks.map(function(t){taskMap.set(t.id, t)});
+ });
+ this._tasksList = taskMap;
+ this.notify("tasks_updated");
+ }
+ return this._tasksList;
+ }
+
+ }
+
+ var TasksPanel = React.createClass({
+
+ refreshTasks: function(){
+ if(!this.isMounted()){
+ return;
+ }
+ this.setState({
+ tasks: TaskStore.getInstance().getTasks()
+ });
+ },
+
+ getInitialState(){
+ return {
+ tasks: TaskStore.getInstance().getTasks()
+ };
+ },
+
+ componentDidMount: function(){
+ TaskStore.getInstance().observe("tasks_updated", this.refreshTasks.bind(this));
+ },
+
+ componentWillUnmount: function(){
+ TaskStore.getInstance().stopObserving("tasks_updated");
+ },
+
+ render: function(){
+ let tasks = [];
+ this.state.tasks.forEach(function(t){
+ if(t.getStatus() == Task.STATUS_COMPLETE) return;
+ let actions;
+ if(t.isStoppable()){
+ actions = (<span className="icon-stop" onClick={t.pause.bind(t)}/>);
+ }
+ tasks.push(
+ <div className="task">
+ <div className="task_texts">
+ <div className="task_label">{t.getLabel()}</div>
+ <div className="status_message">{t.getStatusMessage()}</div>
+ </div>
+ <div className="task_actions">{actions}</div>
+ </div>
+ );
+ });
+ let className = "pydio-tasks-panel";
+ let heightStyle;
+ if(!tasks.length){
+ className += " invisible";
+ }else{
+ heightStyle = {height: Math.min(tasks.length * 60, 180)};
+ }
+ return (
+ <div className={className} style={heightStyle}>
+ {tasks}
+ </div>
+ );
+ }
+ });
+
+ // Export TaskStore
+ var ns = global.PydioTasks || {};
+ ns.Store = TaskStore;
+ ns.Task = Task;
+ ns.Panel = TasksPanel;
+ global.PydioTasks = ns;
+
+})(window);
@@ -2,6 +2,11 @@
<ajxp_plugin label="CONF_MESSAGE[Tasks Service]" description="CONF_MESSAGE[Centralize background tasks and scheduling]" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="file:../core.ajaxplorer/ajxp_registry.xsd">
<class_definition classname="Pydio\Tasks\TaskController" filename="plugins/core.tasks/src/TaskController.php"/>
+ <client_settings>
+ <resources>
+ <js className="PydioTasks" file="plugins/core.tasks/js/build/PydioTasks.js" depends="React,ReactPydio"/>
+ </resources>
+ </client_settings>
<registry_contributions>
<actions>
<action name="tasks_list">
@@ -24,6 +29,11 @@
<serverCallback methodName="route"/>
</processing>
</action>
+ <action name="task_toggle_status">
+ <processing>
+ <serverCallback methodName="route"/>
+ </processing>
+ </action>
<action name="task_delete">
<processing>
<serverCallback methodName="route"/>
@@ -33,5 +43,10 @@
<hooks>
<serverCallback methodName="attachTasksToNode" hookName="node.info"/>
</hooks>
+ <client_configs>
+ <template name="pydio-tasks-panel" element="ajxp_desktop" position="bottom"><![CDATA[
+ <div id="tasks_panel" class="react-mui-context" ajxpClass="AjxpReactComponent" ajxpOptions='{"componentNamespace":"PydioTasks","componentName":"Panel"}'></div>
+ ]]></template>
+ </client_configs>
</registry_contributions>
</ajxp_plugin>
@@ -47,14 +47,7 @@ public function getTaskById($taskId);
* @return Task
*/
public function updateTask(Task $task);
-
- /**
- * @param string $taskId
- * @param int $status
- * @return Task
- */
- public function updateTaskStatus($taskId, $status);
-
+
/**
* @param string $taskId
* @return bool
@@ -70,9 +63,10 @@ public function getPendingTasks();
/**
* @param AJXP_Node $node
+ * @param $active
* @return Task[]
*/
- public function getTasksForNode(AJXP_Node $node);
+ public function getActiveTasksForNode(AJXP_Node $node);
/**
* @param AbstractAjxpUser $user
@@ -21,6 +21,7 @@
namespace Pydio\Tasks\Providers;
+use Pydio\Access\Core\Model\AJXP_Node;
use Pydio\Tasks\Task;
use Pydio\Tasks\Schedule;
@@ -62,19 +63,7 @@ public function updateTask(Task $task)
{
return $task;
}
-
- /**
- * @param string $taskId
- * @param int $status
- * @return Task
- */
- public function updateTaskStatus($taskId, $status)
- {
- $fakeTask = new Task();
- $fakeTask->setId($taskId);
- $fakeTask->setStatus($status);
- }
-
+
/**
* @param string $taskId
* @return bool
@@ -97,9 +86,9 @@ public function getPendingTasks()
/**
* @param \Pydio\Access\Core\Model\AJXP_Node $node
- * @return Task[]
+ * @return \Pydio\Tasks\Task[]
*/
- public function getTasksForNode(\Pydio\Access\Core\Model\AJXP_Node $node)
+ public function getActiveTasksForNode(AJXP_Node $node)
{
$t1 = new Task();
$t1->setAction("fake-task-action");
@@ -37,9 +37,13 @@ class SqlTasksProvider implements ITasksProvider
protected function taskToDBValues(Task $task, $removeId = false){
$values = [
+ "flags" => $task->getFlags(),
+ "label" => $task->getLabel(),
"userId" => $task->getUserId(),
"wsId" => $task->getWsId(),
"status" => $task->getStatus(),
+ "status_msg"=> $task->getStatusMessage(),
+ "progress" => $task->getProgress(),
"schedule" => json_encode($task->getSchedule()),
"action" => $task->getAction(),
"parameters"=> json_encode($task->getParameters()),
@@ -58,9 +62,13 @@ protected function taskToDBValues(Task $task, $removeId = false){
protected function taskFromDBValues(\DibiRow $values){
$task = new Task();
$task->setId($values["uid"]);
+ $task->setFlags($values["flags"]);
+ $task->setLabel($values["label"]);
$task->setUserId($values["userId"]);
$task->setWsId($values["wsId"]);
$task->setStatus($values["status"]);
+ $task->setStatusMessage($values["status_msg"]);
+ $task->setProgress($values["progress"]);
$task->setSchedule(Schedule::fromJson($values["schedule"]));
$task->setAction($values["action"]);
$task->setParameters(json_decode($values["parameters"], true));
@@ -103,19 +111,7 @@ public function updateTask(Task $task)
$sql = $ex->getSql();
}
}
-
- /**
- * @param string $taskId
- * @param int $status
- * @return Task
- */
- public function updateTaskStatus($taskId, $status)
- {
- $task = $this->getTaskById($taskId);
- $task->setStatus($status);
- \dibi::query("UPDATE [ajxp_tasks] SET ", $this->taskToDBValues($task, true), " WHERE [uid] =%s", $taskId);
- }
-
+
/**
* @param string $taskId
* @return bool
@@ -135,13 +131,14 @@ public function getPendingTasks()
/**
* @param AJXP_Node $node
- * @return Task[]
+ * @param $active
+ * @return \Pydio\Tasks\Task[]
*/
- public function getTasksForNode(AJXP_Node $node)
+ public function getActiveTasksForNode(AJXP_Node $node)
{
$tasks = [];
try{
- $res = \dibi::query('SELECT * FROM [ajxp_tasks] WHERE [nodes] LIKE %s', "%|||".$node->getUrl()."|||%");
+ $res = \dibi::query('SELECT * FROM [ajxp_tasks] WHERE [nodes] LIKE %s AND [status] NOT IN (1,4,8)', "%|||".$node->getUrl()."|||%");
foreach ($res->fetchAll() as $row) {
$tasks[] = $this->taskFromDBValues($row);
}
@@ -49,6 +49,10 @@ public function __construct($type, $value = ""){
$this->value = $value;
}
+ public function shouldRunNow(){
+ return $this->type === self::TYPE_ONCE_NOW;
+ }
+
public static function scheduleNow(){
return new Schedule(self::TYPE_ONCE_NOW);
}
Oops, something went wrong.

0 comments on commit bc5c0f9

Please sign in to comment.