Author: obruce Date: 2014-05-12 18:17:30 +0200 (Mon, 12 May 2014) New Revision: 2972 Url: http://forge.chorem.org/projects/jtimer/repository/revisions/2972 Log: Storage: correction delete cascade, Serveur: correction des dates, UI: ajout module modification des temps Added: branches/ng-jtimer/src/main/webapp/partials/timeModal.html Modified: branches/ng-jtimer/src/main/java/org/chorem/jtimer/entities/TimerTask.java branches/ng-jtimer/src/main/java/org/chorem/jtimer/storage/Storage.java branches/ng-jtimer/src/main/java/org/chorem/jtimer/web/TaskResource.java branches/ng-jtimer/src/main/java/org/chorem/jtimer/web/TasksResource.java branches/ng-jtimer/src/main/java/org/chorem/jtimer/web/TimeResource.java branches/ng-jtimer/src/main/webapp/js/controllers.js branches/ng-jtimer/src/main/webapp/js/entities.js branches/ng-jtimer/src/main/webapp/partials/tasks.html Modified: branches/ng-jtimer/src/main/java/org/chorem/jtimer/entities/TimerTask.java =================================================================== --- branches/ng-jtimer/src/main/java/org/chorem/jtimer/entities/TimerTask.java 2014-05-07 16:02:47 UTC (rev 2971) +++ branches/ng-jtimer/src/main/java/org/chorem/jtimer/entities/TimerTask.java 2014-05-12 16:17:30 UTC (rev 2972) @@ -86,9 +86,26 @@ this.name = name; this.taskId = UUID.randomUUID().toString(); this.parent = ""; + this.creationDate= new Date(); } /** + * Constructor with name. + * + * @param name task name + */ + public TimerTask(long number, String name, long datetime) { + this(); + this.number = number; + this.name = name; + this.taskId = UUID.randomUUID().toString(); + this.parent = ""; + this.creationDate= new Date(datetime); + } + + + + /** * Get task number. * * @return the number Modified: branches/ng-jtimer/src/main/java/org/chorem/jtimer/storage/Storage.java =================================================================== --- branches/ng-jtimer/src/main/java/org/chorem/jtimer/storage/Storage.java 2014-05-07 16:02:47 UTC (rev 2971) +++ branches/ng-jtimer/src/main/java/org/chorem/jtimer/storage/Storage.java 2014-05-12 16:17:30 UTC (rev 2972) @@ -152,12 +152,12 @@ " note TEXT," + " PRIMARY KEY (id, taskId))"); statement.executeUpdate("CREATE TABLE " + TABLE_TIME + - "(taskid LONG NOT NULL REFERENCES " + TABLE_TASK + "(id)," + + "(taskid LONG NOT NULL," + " date DATE," + " uuid varchar(255) unique," + " duration LONG," + - " PRIMARY KEY (taskid, date, uuid)" + - ", FOREIGN KEY (taskid)" + + " PRIMARY KEY (taskid, date, uuid)," + + " FOREIGN KEY (taskid)" + " REFERENCES " + TABLE_TASK +"(id)" + " ON DELETE CASCADE" + ")"); @@ -280,18 +280,18 @@ PreparedStatement statement = null; try { statement = connection.prepareStatement("UPDATE " + - TABLE_TASK + " SET name=?, parent=?, taskId=?, hidden=?, note=?" + - " WHERE id = ?"); - statement.setString(1, task.getName()); + TABLE_TASK + " SET name=?, parent=?, hidden=?, note=?" + + " WHERE taskId = ?"); + statement.setString(1, task.getName()); //name if (task.getParent() == "") { - statement.setString(2, ""); + statement.setString(2, ""); //parent } else { - statement.setString(2, task.getParent()); + statement.setString(2, task.getParent()); //parent } - statement.setString(3, task.getTaskId()); - statement.setBoolean(4, task.isClosed()); - statement.setString(5, null /*project.getNote()*/); - statement.setLong(6, task.getNumber()); + + statement.setBoolean(3, task.isClosed()); //hidden + statement.setString(4, null /*project.getNote()*/);//note + statement.setString(5, task.getTaskId()); //taskId statement.executeUpdate(); } catch (SQLException ex) { throw new StorageException("Can't modify task", ex); Modified: branches/ng-jtimer/src/main/java/org/chorem/jtimer/web/TaskResource.java =================================================================== --- branches/ng-jtimer/src/main/java/org/chorem/jtimer/web/TaskResource.java 2014-05-07 16:02:47 UTC (rev 2971) +++ branches/ng-jtimer/src/main/java/org/chorem/jtimer/web/TaskResource.java 2014-05-12 16:17:30 UTC (rev 2972) @@ -14,11 +14,21 @@ protected Storage storage; + /** + * Methode qui initialis la resource + * @throws ResourceException + */ @Override protected void doInit() throws ResourceException { storage = (Storage)getContext().getAttributes().get(Storage.class.getName()); } + /** + * Methode qui retourne la représentation d'une tache + * suite d'une requête de type GET + * + * @return une representation de la tache + */ @Get("json") public Representation getTask() { String taskId = (String)getRequest().getAttributes().get("taskId"); @@ -27,6 +37,11 @@ return new StringRepresentation( json , MediaType.APPLICATION_JSON); } + /** + * Methode qui supprime un element de la base + * suite d'une requête de type DELETE + * + */ @Delete public void deleteTask() { @@ -34,10 +49,7 @@ storage.deleteTaskWithId(taskId); } - @Put("json") - public void updateTask(){ - } } Modified: branches/ng-jtimer/src/main/java/org/chorem/jtimer/web/TasksResource.java =================================================================== --- branches/ng-jtimer/src/main/java/org/chorem/jtimer/web/TasksResource.java 2014-05-07 16:02:47 UTC (rev 2971) +++ branches/ng-jtimer/src/main/java/org/chorem/jtimer/web/TasksResource.java 2014-05-12 16:17:30 UTC (rev 2972) @@ -23,7 +23,10 @@ private final static Logger LOGGER = Logger.getLogger(TasksResource.class.getName()); private GsonBuilder builder; - + /** + * Methode qui initialis la resource + * @throws ResourceException + */ @Override protected void doInit() throws ResourceException { storage = (Storage)getContext().getAttributes().get(Storage.class.getName()); @@ -37,6 +40,11 @@ }); } + /** + * Methode qui retourne la representation de la liste de toutes les taches + * Suite a une requete de type GET + * @return + */ @Get("json") public Representation getTasks() { Gson gson = new Gson(); @@ -59,6 +67,10 @@ return new StringRepresentation(json, MediaType.APPLICATION_JSON); } + /** + * Methode qui cree une tache + * suite d'une requête de type POST + */ @Post("json") public void createTask(Representation representation) throws IOException { @@ -67,12 +79,21 @@ TimerTask t = gson.fromJson(repr1, TimerTask.class); LOGGER.log(Level.INFO,"repr1"); - //List<TimerTask> timerTasks = gson.fromJson(repr1, List.class); - - /*for(TimerTask t : timerTasks){ - storage.addTask(t); - }*/ storage.addTask(t); } + /** + * Methode qui met à jour une tache + * suite d'une requête de type PUT + */ + @Put("json") + public void updateTask(Representation representation) throws IOException{ + + Gson gson = builder.create(); + String repr1 = representation.getText(); + TimerTask t = gson.fromJson(repr1, TimerTask.class); + + storage.modifyTask(t); + } + } Modified: branches/ng-jtimer/src/main/java/org/chorem/jtimer/web/TimeResource.java =================================================================== --- branches/ng-jtimer/src/main/java/org/chorem/jtimer/web/TimeResource.java 2014-05-07 16:02:47 UTC (rev 2971) +++ branches/ng-jtimer/src/main/java/org/chorem/jtimer/web/TimeResource.java 2014-05-12 16:17:30 UTC (rev 2972) @@ -19,32 +19,56 @@ public class TimeResource extends ServerResource { private GsonBuilder builder; + protected Storage storage; private final static Logger LOGGER = Logger.getLogger(TasksResource.class.getName()); + /** + * Methode qui initialis la resource + * @throws ResourceException + */ @Override protected void doInit() throws ResourceException { + //GSON builder to format dates builder = new GsonBuilder(); + builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() { public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { return new Date(json.getAsJsonPrimitive().getAsLong()); } }); + builder.registerTypeAdapter(Date.class, new JsonSerializer<Date>() { + @Override + public JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) { + return new JsonPrimitive(date.getTime()); + } + }); storage = (Storage)getContext().getAttributes().get(Storage.class.getName()); } + /** + * Methode qui retourne la représentation d'une liste de periode + * suite d'une requête de type GET + * + * @return la representation de la liste + */ @Get("json") public Representation getTask() { String taskId = (String)getRequest().getAttributes().get("taskId"); List<TimerTime> timerTimes = storage.getTimes(taskId); - Gson gson = new Gson(); + Gson gson = builder.create(); String json = gson.toJson(timerTimes); return new StringRepresentation(json, MediaType.APPLICATION_JSON); } + /** + * Methode qui supprime un element de la base + * suite d'une requête de type DELETE + * + */ @Delete public void deleteTask() { @@ -52,12 +76,16 @@ storage.deleteTimeWithId(timeId); } + /** + * Methode qui cree une periode + * suite d'une requête de type POST + */ @Post("json") public void createTask(Representation representation) throws IOException { String timeId = (String)getRequest().getAttributes().get("taskId"); long number = storage.getTaskNumber(timeId); - Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX").create(); + Gson gson = builder.create(); String repr1 = representation.getText(); TimerTime t = gson.fromJson(repr1, TimerTime.class); Modified: branches/ng-jtimer/src/main/webapp/js/controllers.js =================================================================== --- branches/ng-jtimer/src/main/webapp/js/controllers.js 2014-05-07 16:02:47 UTC (rev 2971) +++ branches/ng-jtimer/src/main/webapp/js/controllers.js 2014-05-12 16:17:30 UTC (rev 2972) @@ -44,11 +44,11 @@ $scope.webSocketClientIdle = false; - - //obruce :Creation de files de temps, de taches // {Array of TaskID} la file de tache attendant la synchronisation avec le serveur + var stockedDeletedTasks = []; + // {Array of Task} var stockedNewTasks = []; - var stockedDeletedTasks = []; + var stockedEditedTasks = []; // {key: taskId, value: Array of TaskTime} la file de temps des taches attendant la synchronisation avec le serveur var stockedNewTimes = {}; @@ -131,7 +131,7 @@ if ($scope.tree) { $scope.tree.addChild($scope.createTreeNode(newTask)); } - console.log("Import projet " + newTask.name); + }else{ //Un noeud avec un parent est ajoute à l'arbre de son parent $scope.data.tasks[newTask.taskId] = newTask; @@ -139,9 +139,6 @@ //Les temps sont recuperes du serveur getTimesFromServer(newTask); - console.log(newTask); - console.log("Import task "+ newTask.name); - console.log($scope.data.times[newTask.taskId]) save(); } } @@ -154,7 +151,7 @@ var getTimesFromServer = function(task){ if(!$scope.data.times[task.taskId]){$scope.data.times[task.taskId] = []} - //On va chercher les temps pour une tacheeditTask + serverTimeAccess.query({taskId : task.taskId}, function (response) { angular.forEach(response, function (item) { @@ -192,6 +189,17 @@ console.log("fail"); }); }); + //On ajoute au serveur les taches stockees pour l'ajout + angular.forEach(stockedEditedTasks, function(task){ + serverTaskAccess.update(angular.toJson(task), + function(){ + console.log("update task success" + task); + stockedEditedTasks.shift(); + }, + function(){ + console.log("fail"); + }); + }); //On ajoute les nouveaux temps au serveur angular.forEach(stockedNewTimes, function(times,task){ @@ -208,6 +216,8 @@ }); } + + /** * Timer qui met les temps a jour toutes les secondes si une tache est * active @@ -228,25 +238,31 @@ refresh(); /** - * Timer qui fait une demande d'envoie de maj toutes les minutes + * Timer qui joue des actions sur un interval donné * @returns {promise} */ var timer = function() { $interval(function() { - //Si en ligne on envoie les donnees - if ( $scope.online == true) { + actionToServ(); + }, 30000); //TODO: for now 10s but for real put at least 2h: 200000000 + }; + timer(); - pushChangesToServ(); - getTasksFromServ(); + /** + *Méthode qui lance les actions à faires sur le serveur + */ + var actionToServ = function(){ + //Si en ligne on envoie les donnees + if ( $scope.online == true) { - //On change la date de dernier acces - $scope.acces = moment().format("DD-MM-YYYY H:mm:ss a"); + pushChangesToServ(); + getTasksFromServ(); - } + //On change la date de dernier acces + $scope.acces = moment().format("DD-MM-YYYY H:mm:ss a"); + } - }, 30000); //TODO: for now 10s but for real put at least 2h: 200000000 - }; - timer(); + } /** * Ajoute une tache root @@ -408,7 +424,7 @@ $scope.data.times[task.taskId]= times; } - var maxDate = new Date(0,0,0,0,0); + var maxDate = new Date(0,0,0,0,0).getTime(); var result; angular.forEach(times, function (t) { @@ -444,7 +460,9 @@ */ $scope.saveTask = function(node) { node.edit = null; + stockedEditedTasks.push(node.task); save(); + console.log(stockedEditedTasks); }; /** @@ -547,9 +565,27 @@ $scope.webSocketClientIdle = false; }; + $scope.popup = function (node){ + + var modalInstance = $modal.open({ + templateUrl: 'partials/timeModal.html', + controller: ModalInstanceCtrl, + resolve: { + taskTimes : function(){ + return $scope.data.times[node.task.taskId]; + } + } + }); + + modalInstance.result.then(function (item) { + console.log(item); + }, function () { + //Dismiss + }); + } + //force the first server connection - pushChangesToServ(); - getTasksFromServ(); + actionToServ(); // force the first tree creation $scope.createTree(); @@ -572,3 +608,64 @@ }; } + + + +var ModalInstanceCtrl = function ($scope, $modalInstance, taskTimes) { + + // Les temps de la tache + $scope.times = taskTimes; + + //La tache courante + $scope.currentTask = null; + + //Le pas des heures et minutes + $scope.hstep = 1; + $scope.mstep = 1; + $scope.aTime = new Date(); + + //La date a modifier + $scope.modifDate= "début"; + + //key:timeId value:Array of time + var stockTime={}; + + + //Pour l'affichage + $scope.getStartTime = function(item){ + return moment(item.creationDate).format("DD-MM-YYYY H:mm:ss"); + } + + $scope.getStopTime = function(item){return item.time;} + + //Pour le timePicker + $scope.select = function(item){ + $scope.currentTask = item; + $scope.aTime = new Date($scope.currentTask.creationDate); + } + + + $scope.changeTime = function(item){ + + } + + $scope.dateDebut = function(){ + $scope.modifDate= "début"; + $scope.aTime = new Date($scope.currentTask.creationDate); + + } + + $scope.dateFin = function(){ + $scope.modifDate= "durée"; + $scope.aTime = new Date($scope.currentTask.creationDate + $scope.currentTask.time ); + } + + $scope.ok = function () { + $modalInstance.close(); + }; + + $scope.cancel = function () { + $modalInstance.dismiss('cancel'); + }; +}; + Modified: branches/ng-jtimer/src/main/webapp/js/entities.js =================================================================== --- branches/ng-jtimer/src/main/webapp/js/entities.js 2014-05-07 16:02:47 UTC (rev 2971) +++ branches/ng-jtimer/src/main/webapp/js/entities.js 2014-05-12 16:17:30 UTC (rev 2972) @@ -256,6 +256,14 @@ }; /** + * Determine si le global time est vide + * @returns {GlobalTime} this + */ +GlobalTime.prototype.estVide = function() { + return (this.global) == 0; +}; + +/** * Ajoute les temps d'un tableau de TaskTime au temps global et a today si * la TaskTime est pour today * @param {Array of TaskTime} taskTimes @@ -360,9 +368,10 @@ } if(date == undefined){ - this.creationDate = new Date(); + this.creationDate = Date.now(); }else{ - this.creationDate = new Date(date); + this.creationDate = date; + } if(time == undefined){ @@ -401,7 +410,29 @@ return this; }; + /** + * change la date de début + * @param {Long} d la date en ms + * @returns {TaskTime} this + */ +TaskTime.prototype.changeCreationDate = function(d) { + this.creationDate = d; + return this; +}; + +/** + * change la duree de la periode + * @param {Long} d la date en ms + * @returns {TaskTime} this + */ +TaskTime.prototype.changeDuration = function(d) { + this.time = d; + return this; +}; + + +/** * Represente une note pour une tache * @param {Task} task * @returns {TaskNote} Modified: branches/ng-jtimer/src/main/webapp/partials/tasks.html =================================================================== --- branches/ng-jtimer/src/main/webapp/partials/tasks.html 2014-05-07 16:02:47 UTC (rev 2971) +++ branches/ng-jtimer/src/main/webapp/partials/tasks.html 2014-05-12 16:17:30 UTC (rev 2972) @@ -50,8 +50,7 @@ <div class="tr" ng-class="{'current-row' : ($node.task === currentTask), 'selected-row' : ($node.task === selectedTask)}" ng-click="setSelectedTask($node.task)" - ng-dblclick="timeTask($node.task)" - ng-keydown="keyPressed($event)"> + ng-keydown="keyPressed($event)"><!--ng-dblclick="timeTask($node.task)"--> <div class="td" ng-show="showName"> <span class="spacer level{{$level}}"></span> @@ -63,7 +62,7 @@ <!--Project name visible and editable --> <form ng-submit="saveTask($node)" ng-show="$node.edit == 'name'"> - <input ng-model="$node.task.name"> + <input ng-model="$node.task.name" ng-blur="$node.edit == ''"> </form> <span ng-click="editTask($node, 'name')" ng-show="$node.edit != 'name'">{{$node.task.name}} </span> @@ -73,9 +72,16 @@ <i class="glyphicon" ng-class="{'glyphicon-play' : ($node.task != currentTask), 'glyphicon-stop' : ($node.task == currentTask)}"></i> </a> <a class="btn btn-default btn-xs" href="" ng-click="addSubTask($node)"><i class="glyphicon glyphicon-plus"></i></a> - <a class="btn btn-default btn-xs" href="" ng-really-message="La suppression de cette tâche nécessite une confirmation. " ng-really-click="removeTask($node)" ng-show="$node.task != currentTask"> + <a class="btn btn-default btn-xs" href="" + ng-really-message="La suppression de cette tâche nécessite une confirmation. " + ng-really-click="removeTask($node)" ng-show="$node.task != currentTask"> <i class="glyphicon glyphicon-minus"></i> </a> + + <a class="btn btn-default btn-xs" href="" ng-click="popup($node)" ng-show="!$node.getTime().estVide()"><i class="glyphicon glyphicon-pencil" ></i></a> + + + </span> </div> Added: branches/ng-jtimer/src/main/webapp/partials/timeModal.html =================================================================== --- branches/ng-jtimer/src/main/webapp/partials/timeModal.html (rev 0) +++ branches/ng-jtimer/src/main/webapp/partials/timeModal.html 2014-05-12 16:17:30 UTC (rev 2972) @@ -0,0 +1,46 @@ +<div> + <h3> Modifier la tâche.</h3> + + <ul> + <li ng-repeat="item in times" > + + <span ng-click="select(item)"> + Date de création : {{getStartTime(item)}} - Durée : {{getStopTime(item)| time}} + </span> + + <!-- Timepicker --> + <div ng-show = "currentTask == item"> + <hr> + + <!-- Choix --> + <div class="btn-group" dropdown is-open="status.isopen"> + <button type="button" class="btn btn-primary dropdown-toggle"> + Changer la date de {{modifDate}} de période. <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + <li ng-click="dateDebut()"><a href="#">Début de la période</a></li> + <li ng-click="dateFin()"><a href="#">Fin de la période</a></li> + + </ul> + </div> + + <timepicker + ng-model="$parent.$parent.aTime" ng-change="changeTime()" hour-step="hstep" minute-step="mstep" show-meridian="ismeridian"> + </timepicker> + </div> + </li> + + </ul> + + + + + <div class="modal-footer"> + <button class="btn btn-primary" ng-click="ok()">OK</button> + <button class="btn btn-warning" ng-click="cancel()">Cancel</button> + </div> + + + +</div> +