r2956 - in branches/ng-jtimer: . src/main/go src/main/webapp src/main/webapp/css src/main/webapp/js
Author: echatellier Date: 2014-04-14 21:13:31 +0200 (Mon, 14 Apr 2014) New Revision: 2956 Url: http://forge.chorem.org/projects/jtimer/repository/revisions/2956 Log: Simplify project. Keep only server module Added: branches/ng-jtimer/run.sh branches/ng-jtimer/src/ branches/ng-jtimer/src/main/go/readme.txt branches/ng-jtimer/src/main/webapp/css/ branches/ng-jtimer/src/main/webapp/css/app.css branches/ng-jtimer/src/main/webapp/js/ branches/ng-jtimer/src/main/webapp/js/app.js branches/ng-jtimer/src/main/webapp/js/controllers.js branches/ng-jtimer/src/main/webapp/js/entities.js branches/ng-jtimer/src/main/webapp/js/filters.js Removed: branches/ng-jtimer/jtimer-client/ branches/ng-jtimer/jtimer-server/ branches/ng-jtimer/src/main/go/readme.txt branches/ng-jtimer/src/main/webapp/css/ branches/ng-jtimer/src/main/webapp/css/app.css branches/ng-jtimer/src/main/webapp/js/ branches/ng-jtimer/src/main/webapp/js/app.js branches/ng-jtimer/src/main/webapp/js/controllers.js branches/ng-jtimer/src/main/webapp/js/entities.js branches/ng-jtimer/src/main/webapp/js/filters.js Modified: branches/ng-jtimer/ branches/ng-jtimer/pom.xml Property changes on: branches/ng-jtimer ___________________________________________________________________ Modified: svn:ignore - .settings target .project + .settings target .project .classpath Modified: branches/ng-jtimer/pom.xml =================================================================== --- branches/ng-jtimer/pom.xml 2014-03-18 16:32:26 UTC (rev 2955) +++ branches/ng-jtimer/pom.xml 2014-04-14 19:13:31 UTC (rev 2956) @@ -6,23 +6,19 @@ <parent> <groupId>org.nuiton</groupId> <artifactId>mavenpom4redmine</artifactId> - <version>5.0.1</version> + <version>5.0.5</version> </parent> <groupId>org.chorem</groupId> <artifactId>jtimer</artifactId> <version>2.0.0-SNAPSHOT</version> - <packaging>pom</packaging> + <packaging>war</packaging> <name>jTimer</name> <description>jTimer - Time tracking tool.</description> <url>http://maven-site.chorem.org/jtimer</url> <inceptionYear>2007</inceptionYear> - <modules> - <module>jtimer-server</module> - </modules> - <licenses> <license> <name>General Public License (GPL)</name> @@ -38,12 +34,11 @@ </properties> <build> - <pluginManagement> <plugins> <plugin> <groupId>ro.isdc.wro4j</groupId> <artifactId>wro4j-maven-plugin</artifactId> - <version>1.7.3</version> + <version>1.7.5</version> <dependencies> <dependency> <groupId>org.nuiton.js</groupId> @@ -53,7 +48,7 @@ <dependency> <groupId>org.nuiton.js</groupId> <artifactId>nuiton-js-angularjs</artifactId> - <version>1.3.0-beta.2-1-SNAPSHOT</version> + <version>1.3.0-beta.4-1</version> </dependency> <dependency> <groupId>org.nuiton.js</groupId> @@ -78,37 +73,126 @@ <dependency> <groupId>ro.isdc.wro4j</groupId> <artifactId>wro4j-extensions</artifactId> - <version>1.7.3</version> + <version>1.7.5</version> </dependency> </dependencies> + <executions> + <execution> + <phase>generate-resources</phase> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + + <configuration> + <targetGroups>jtimer</targetGroups> + <contextFolder>${basedir}/src/main/webapp/web/</contextFolder> + <!-- hack during devel, otherwize tomcat don't find generated file + (perhaps it's not the good place ?) + <cssDestinationFolder>${basedir}/target/${projectId}-${project.version}/css</cssDestinationFolder> + <jsDestinationFolder>${basedir}/target/${projectId}-${project.version}/js</jsDestinationFolder> --> + <cssDestinationFolder>${basedir}/src/main/webapp/css</cssDestinationFolder> + <jsDestinationFolder>${basedir}/src/main/webapp/js</jsDestinationFolder> + <!-- end devel hack --> + <wroManagerFactory>org.nuiton.js.wro.NuitonJsMavenWroManagerFactory</wroManagerFactory> + <wroFile>${basedir}/src/main/config/wro.xml</wroFile> + <extraConfigFile>${basedir}/src/main/config/wro.properties</extraConfigFile> + </configuration> </plugin> + <plugin> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-maven-plugin</artifactId> + <version>9.1.4.v20140401</version> + </plugin> + <plugin> + <artifactId>maven-war-plugin</artifactId> + <executions> + <execution> + <id>generate-runnable-war</id> + <goals> + <goal>war</goal> + </goals> + <configuration> + <warName>${project.build.finalName}-standalone</warName> + <archive> + <manifest> + <mainClass>org.chorem.jtimer.war.JettyRunner</mainClass> + </manifest> + </archive> + <webResources> + <resource> + <directory>${project.build.directory}/classes</directory> + <targetPath>WEB-INF/..</targetPath> + <includes> + <include>**/war/*</include> + </includes> + <filtering>false</filtering> + </resource> + </webResources> + <overlays> + <overlay> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-runner</artifactId> + <type>jar</type> + </overlay> + </overlays> + </configuration> + </execution> + </executions> + </plugin> </plugins> - </pluginManagement> </build> - <dependencyManagement> - <dependencies> - <dependency> - <groupId>com.h2database</groupId> - <artifactId>h2</artifactId> - <version>1.3.175</version> - </dependency> - </dependencies> - </dependencyManagement> - + <dependencies> + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + <version>1.1.3</version> + </dependency> + <dependency> + <groupId>com.h2database</groupId> + <artifactId>h2</artifactId> + <version>1.4.177</version> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.2.4</version> + </dependency> + <dependency> + <groupId>org.restlet.jee</groupId> + <artifactId>org.restlet</artifactId> + <version>2.2.0</version> + </dependency> + <dependency> + <groupId>org.restlet.jee</groupId> + <artifactId>org.restlet.ext.servlet</artifactId> + <version>2.2.0</version> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-runner</artifactId> + <version>9.1.4.v20140401</version> + <scope>provided</scope> + </dependency> + </dependencies> + <repositories> <repository> <id>sonatype</id> <url>https://oss.sonatype.org/content/groups/public/</url> </repository> + <repository> + <id>maven-restlet</id> + <name>Public online Restlet repository</name> + <url>http://maven.restlet.org</url> + </repository> </repositories> <pluginRepositories> <pluginRepository> - <id>chorem</id> + <id>nuiton</id> <url>http://nexus.nuiton.org/nexus/content/groups/public</url> - <releases> - <enabled>false</enabled> - </releases> </pluginRepository> </pluginRepositories> </project> Added: branches/ng-jtimer/run.sh =================================================================== --- branches/ng-jtimer/run.sh (rev 0) +++ branches/ng-jtimer/run.sh 2014-04-14 19:13:31 UTC (rev 2956) @@ -0,0 +1,15 @@ +#!/bin/sh + +if [ -z "$GOPATH" ]; then + echo "Please define \$GOPATH first" + exit 1; +fi + +go get github.com/BurntSushi/xgb/screensaver +go get code.google.com/p/go.net/websocket +go get github.com/mattn/go-gtk/gtk +go get github.com/BurntSushi/xgbutil + +pushd src/main/go &>/dev/null +go run [^j]*.go jtimer.go +popd Deleted: branches/ng-jtimer/src/main/go/readme.txt =================================================================== --- branches/ng-jtimer/jtimer-server/src/main/go/readme.txt 2013-11-10 09:33:13 UTC (rev 2951) +++ branches/ng-jtimer/src/main/go/readme.txt 2014-04-14 19:13:31 UTC (rev 2956) @@ -1,18 +0,0 @@ -Compilation do client go -======================== - -Packages necessaires --------------------- -go get github.com/BurntSushi/xgb/screensaver -go get code.google.com/p/go.net/websocket -go get github.com/mattn/go-gtk/gtk -go get github.com/BurntSushi/xgbutil - -Lancement ---------- -go run [^j]*.go jtimer.go - - -Compilation ------------ -go build -o jtimer [^j]*.go jtimer.go Copied: branches/ng-jtimer/src/main/go/readme.txt (from rev 2952, branches/ng-jtimer/jtimer-server/src/main/go/readme.txt) =================================================================== --- branches/ng-jtimer/src/main/go/readme.txt (rev 0) +++ branches/ng-jtimer/src/main/go/readme.txt 2014-04-14 19:13:31 UTC (rev 2956) @@ -0,0 +1,20 @@ +Compilation do client go +======================== + +export GOPATH=$HOME/gocode + +Packages necessaires +-------------------- +go get github.com/BurntSushi/xgb/screensaver +go get code.google.com/p/go.net/websocket +go get github.com/mattn/go-gtk/gtk +go get github.com/BurntSushi/xgbutil + +Lancement +--------- +go run [^j]*.go jtimer.go + + +Compilation +----------- +go build -o jtimer [^j]*.go jtimer.go Deleted: branches/ng-jtimer/src/main/webapp/css/app.css =================================================================== --- branches/ng-jtimer/jtimer-server/src/main/webapp/css/app.css 2014-02-06 20:44:47 UTC (rev 2952) +++ branches/ng-jtimer/src/main/webapp/css/app.css 2014-04-14 19:13:31 UTC (rev 2956) @@ -1,258 +0,0 @@ - -body{ - margin:0; - padding: 60px 0 20px 0; -} -div#header { - position:absolute; - top:0; - left:0; - width:100%; - height: 35px; - z-index: 1000; - - background:black; - color:graytext; -} -div#alerts{ - position:absolute; - bottom:20px; - left:0; - width:100%; - z-index: 1000; -} -.alert { - margin-bottom: 0; -} - -div#footer{ - position:absolute; - bottom:0; - left:0; - width:100%; - height:20px; - z-index: 1000; - - background:black; - color:graytext; -} -#footer>.left, #header>.left { - text-align: left; - position: absolute; - left: 0px; - top: 0px; - z-index: 10; -} -#footer>.center, #header>.center { - width: 100%; - height: 100%; - text-align: center; - display: block; - z-index: 5; -} -#footer>.right, #header>.right { - text-align: right; - position: absolute; - right: 0px; - top: 0px; - z-index: 10; -} - -.menu-show { - display: block; - left: -170px -} - -@media screen{ - body div#header{ - position:fixed; - } - body div#subheader{ - position:fixed; - } - body div#footer{ - position:fixed; - } -} -* html body{ - overflow:hidden; -} -* html div#content{ - height:100%; - overflow:auto; -} - -.table { - display: table; -} - -.table .tbody { - display: table-row-group; -} - -.table .tr { - display: table-row; -} - -.table .th { - display: table-cell; - font-weight: bold; - text-align: center; -} - -.table .td { - display: table-cell; - position: relative; - overflow: hidden; - white-space: nowrap; - text-wrap: none; -} - -.spacer.level1 {padding-left: 10px;} -.spacer.level2 {padding-left: 20px;} -.spacer.level3 {padding-left: 30px;} -.spacer.level4 {padding-left: 40px;} -.spacer.level5 {padding-left: 50px;} -.spacer.level6 {padding-left: 60px;} -.spacer.level7 {padding-left: 70px;} -.spacer.level8 {padding-left: 80px;} -.spacer.level9 {padding-left: 90px;} - -.th.name { - -} - -.th.today, .td.today, .th.global, .td.global { - width: 4em; - border-right: 1px #0088cc solid; -} - -.td.today, .td.global { - text-align: right; -} - -.th.tags { - -} - - - -/* -body { - position: relative; - padding-top: 60px; -} -*/ - -ul.tasks { - display : block; - width : 100%; - list-style: none; -} - -li.task { - display : block; - width : 100%; - height: 32px; -} - -li.task.title { - font-weight: bold; - font-size: medium; -} - -li.task div { - width : 25%; - height: 32px; - float: left; -} - -.names li.task div { - width : 100%; -} - -.details li.task div { - width : 30%; -} - -.names ul.tasks { - margin: 0 0 0 15px; -} - -.details ul.tasks { - margin: 0 0 0 0; -} - -form { - display : inline-block; - margin : 0px; -} - -.filtering-enter { - -webkit-transition : all linear 0.2s; - -moz-transition : all linear 0.2s; - -o-transition : all linear 0.2s; - transition : all linear 0.2s; - - /* The animation preparation code */ - opacity : 0; - height : 0; -} - -.filtering-enter.filtering-enter-active { - /* The animation code itself */ - opacity : 1; - height : 42px; -} - -.filtering-leave { - -webkit-transition : all linear 0.2s; - -moz-transition : all linear 0.2s; - -o-transition : all linear 0.2s; - transition : all linear 0.2s; - - /* The animation preparation code */ - opacity : 1; - height : 42px; -} - -.filtering-leave.filtering-leave-active { - /* The animation code itself */ - opacity : 0; - height : 0; -} - -.btn-group.action { - display: none; - position: absolute; - right: 0; -} - -div:hover > .btn-group.action { - display: inline; -} - -.current-row { - background-color: #3a87ad; - color: white; -} - -.selected-row { - background-color: #5ca9cf; -} - -.tr:hover { - background-color: #7ecbef; -} - -.online { - color: greenyellow; -} - -.offline { - color: red; -} - -.idleModal { - width: 400px; -} \ No newline at end of file Copied: branches/ng-jtimer/src/main/webapp/css/app.css (from rev 2951, branches/ng-jtimer/jtimer-server/src/main/webapp/css/app.css) =================================================================== --- branches/ng-jtimer/src/main/webapp/css/app.css (rev 0) +++ branches/ng-jtimer/src/main/webapp/css/app.css 2014-04-14 19:13:31 UTC (rev 2956) @@ -0,0 +1,258 @@ + +body{ + margin:0; + padding: 60px 0 20px 0; +} +div#header { + position:absolute; + top:0; + left:0; + width:100%; + height: 35px; + z-index: 1000; + + background:black; + color:graytext; +} +div#alerts{ + position:absolute; + bottom:20px; + left:0; + width:100%; + z-index: 1000; +} +.alert { + margin-bottom: 0; +} + +div#footer{ + position:absolute; + bottom:0; + left:0; + width:100%; + height:20px; + z-index: 1000; + + background:black; + color:graytext; +} +#footer>.left, #header>.left { + text-align: left; + position: absolute; + left: 0px; + top: 0px; + z-index: 10; +} +#footer>.center, #header>.center { + width: 100%; + height: 100%; + text-align: center; + display: block; + z-index: 5; +} +#footer>.right, #header>.right { + text-align: right; + position: absolute; + right: 0px; + top: 0px; + z-index: 10; +} + +.menu-show { + display: block; + left: -170px +} + +@media screen{ + body div#header{ + position:fixed; + } + body div#subheader{ + position:fixed; + } + body div#footer{ + position:fixed; + } +} +* html body{ + overflow:hidden; +} +* html div#content{ + height:100%; + overflow:auto; +} + +.table { + display: table; +} + +.table .tbody { + display: table-row-group; +} + +.table .tr { + display: table-row; +} + +.table .th { + display: table-cell; + font-weight: bold; + text-align: center; +} + +.table .td { + display: table-cell; + position: relative; + overflow: hidden; + white-space: nowrap; + text-wrap: none; +} + +.spacer.level1 {padding-left: 10px;} +.spacer.level2 {padding-left: 20px;} +.spacer.level3 {padding-left: 30px;} +.spacer.level4 {padding-left: 40px;} +.spacer.level5 {padding-left: 50px;} +.spacer.level6 {padding-left: 60px;} +.spacer.level7 {padding-left: 70px;} +.spacer.level8 {padding-left: 80px;} +.spacer.level9 {padding-left: 90px;} + +.th.name { + +} + +.th.today, .td.today, .th.global, .td.global { + width: 4em; + border-right: 1px #0088cc solid; +} + +.td.today, .td.global { + text-align: right; +} + +.th.tags { + +} + + + +/* +body { + position: relative; + padding-top: 60px; +} +*/ + +ul.tasks { + display : block; + width : 100%; + list-style: none; +} + +li.task { + display : block; + width : 100%; + height: 32px; +} + +li.task.title { + font-weight: bold; + font-size: medium; +} + +li.task div { + width : 25%; + height: 32px; + float: left; +} + +.names li.task div { + width : 100%; +} + +.details li.task div { + width : 30%; +} + +.names ul.tasks { + margin: 0 0 0 15px; +} + +.details ul.tasks { + margin: 0 0 0 0; +} + +form { + display : inline-block; + margin : 0px; +} + +.filtering-enter { + -webkit-transition : all linear 0.2s; + -moz-transition : all linear 0.2s; + -o-transition : all linear 0.2s; + transition : all linear 0.2s; + + /* The animation preparation code */ + opacity : 0; + height : 0; +} + +.filtering-enter.filtering-enter-active { + /* The animation code itself */ + opacity : 1; + height : 42px; +} + +.filtering-leave { + -webkit-transition : all linear 0.2s; + -moz-transition : all linear 0.2s; + -o-transition : all linear 0.2s; + transition : all linear 0.2s; + + /* The animation preparation code */ + opacity : 1; + height : 42px; +} + +.filtering-leave.filtering-leave-active { + /* The animation code itself */ + opacity : 0; + height : 0; +} + +.btn-group.action { + display: none; + position: absolute; + right: 0; +} + +div:hover > .btn-group.action { + display: inline; +} + +.current-row { + background-color: #3a87ad; + color: white; +} + +.selected-row { + background-color: #5ca9cf; +} + +.tr:hover { + background-color: #7ecbef; +} + +.online { + color: greenyellow; +} + +.offline { + color: red; +} + +.idleModal { + width: 400px; +} \ No newline at end of file Deleted: branches/ng-jtimer/src/main/webapp/js/app.js =================================================================== --- branches/ng-jtimer/jtimer-server/src/main/webapp/js/app.js 2014-02-06 20:44:47 UTC (rev 2952) +++ branches/ng-jtimer/src/main/webapp/js/app.js 2014-04-14 19:13:31 UTC (rev 2956) @@ -1,275 +0,0 @@ -/** - * Cette directive permet de parcourir un Arbre, pour chaque noeud de l'arbre - * un l'element DOM est duplique. - * Il est possible - * - de filtrer les noeuds lors de la definition de l'arbre (wtTreeRepeat) - * (ex: wt-tree-repeat="tree | filter:query | orderBy:'task.name'") - * - d'afficher le noeud root ou non (wtDisplayRoot) - * - de forcer l'ouverture de tout les noeuds (wtForceOpen) - * - * Lors du parcours pour chaque noeud un nouveau scope est cree permettant - * d'utilise les variables: - * - $node le noeud courant de l'arbre - * - $index l'index de parcours de ce noeud (0 pour le root) - * - $level la profondeur de ce noeud (0 pour le root) - * - $state l'etat de ce noeud ('empty', 'open', 'close') - * - $path le chemin pour arriver a ce noeud (tous ces noeuds parents) - * - $pathIndex le chemin pour arriver a ce noeud par index dans le tableau children du pere - * - $toggleState une fonction qui permet de changer l'etat d'un noeud ('open' <-> 'close') - - * - * @param {ngAnimate} $animator permet l'ajout, suppression des noeuds dans le DOM - * @param {ngFilter} $filter permet de filtrer les elements de l'arbre a afficher (filtre, tri, ...) - * @param {ngParse} $parse permet de parser des expressions qui doivent etre evaluer regulierement sur une scope - */ -var wtTreeRepeatDirective = ['$animate', '$filter', '$parse', function($animate, $filter, $parse) { - return { - transclude: 'element', - priority: 1000, - terminal: true, - compile: function(element, attr, linker) { - return function($scope, $element, $attr){ - - // sert a surveiller les changements sur la donnee ou les filtres - // qui engendrerait un besoin de rafraichissement. - // (ce tableau contient les fonctions permettant leur desenregistrement) - var watchers = []; - // element genere HTML et scope du dernier arbre represente - var cache = new Cache($animate); - // indique si l'element root doit etre affiche ou non (faux par defaut) - var displayRoot = $parse($attr.wtDisplayRoot || 'false'); - // indique si l'arbre doit etre ouvert de facon forcee ou non (faux par defaut) - var forceOpen = $parse($attr.wtForceOpen || 'false'); - // l'expression permettant de recuperer l'arbre et les filtres - var expression = $attr.wtTreeRepeat; - - // les differents filtres a applique aux noeuds enfants - var filters = []; - var filterStrings = expression.split('|'); - // l'expression pour la recuperation de arbre - var tree = filterStrings.shift(); - // add tree as watcher - watchers.push(tree); - // add forceOpen as watcher - watchers.push($attr.wtForceOpen||'false'); - - // Recuperation des filtres et preparation pour etre pret - // a l'utilisation - angular.forEach(filterStrings, function(filterString) { - var argStrings = filterString.split(":"); - var filterName = argStrings.shift().trim(); - var argGetters = argStrings.map(function(e) { - // add all args as watcher - watchers.push(e); - var result = $parse(e); - return result; - }); - var filter = function(children) { - var f = $filter(filterName); - var args = argGetters.map(function(a) { - return a($scope); - }); - var result = f.apply(null, [children].concat(args)); - return result; - }; - filters.push(filter); - }); - - // met a jour l'affichage de l'arbre - var update = function(tree) { - // les objets HTML et scope utilise durant cette mise a jour - // qui pourront etre reutilise durant la mis a jour suivante - var newCache = new Cache($animate); - - // l'index de parcours du noeud, on met dans un tableau - // pour avoir une reference lors du passage en argument - // et non pas une valeur lors des appels recursifs - var index = [0]; - // le niveau du noeud - var level = 0; - var path = []; - var pathIndex = []; - // le dernier element HTML ajoute (il faut mettre le suivant apres celui-ci) - var lastElement = $element; - - /** - * Genere un noeud et appel la fonction pour chaque noeud - * fils a affiche - */ - var generate = function(node, index, level, path, pathIndex) { - var state = 'open'; // init to open, if root is not display - - // on affiche le root que si demande - if (index[0] !== 0 || displayRoot($scope)) { - // try to find already created element - var cacheEntry = cache.get(node) || {node: node, scope:$scope.$new()}; - node.copyState(cacheEntry.node); // copy les etats, les noeuds ouvert doivent rester ouvert - var isNewElement = !cacheEntry.element; - - // new item which we don't know about - var childScope = cacheEntry.scope; - - if (node.children.length === 0) { - state = 'empty'; - } else { - if (node.$$open || forceOpen($scope)) { - state = 'open'; - } else { - state = 'close'; - } - } - - childScope.$node = node; - childScope.$index = index[0]; - childScope.$level = level; - childScope.$state = state; - childScope.$path = path; - childScope.$pathIndex = pathIndex; - childScope.$toggleState = function() { - node.$$open = !node.$$open; - }; - isNewElement && childScope.$watch("$node.$$open", function (newValue, oldValue, scope) { - if (newValue !== oldValue) { - update(tree); - } - }); - isNewElement && childScope.$watch("$node.children.length", function (newValue, oldValue, scope) { - if (newValue !== oldValue) { - update(tree); - } - }); - - if (!isNewElement) { - $animate.move(cacheEntry.element, null, lastElement); - lastElement = cacheEntry.element; - newCache.put(node, cacheEntry.element, cacheEntry.scope); - } else { - linker(childScope, function(clone) { - $animate.enter(clone, null, lastElement); - lastElement = clone; - newCache.put(node, clone, childScope); - }); - } - } - index[0]++; - - if (state == 'open') { - var children = node.children; - filters.forEach(function(e) { - children = e(children); - }); - for (var i = 0, length = children.length; i < length; i++) { - var child = children[i]; - generate(child, index, level+1, path.concat([child]), pathIndex.concat([i])); - } - } - }; - - generate(tree, index, level, path, pathIndex); - - // on nettoie les anciens noeud non reutilise - cache.clear(); - // on met les nouveaux noeuds dans le cache pour la prochaine maj - cache = newCache; - }; - - // expression permettant de recupere facilement l'arbre - var treeGetter = $parse(tree); - - // on enregistre chaque watcher sur le scope - angular.forEach(watchers, function (watcher) { - $scope.$watch(watcher, function(newValue, oldValue, scope){ - if (newValue !== oldValue) { - var tree = treeGetter($scope); - update(tree); - } - }); - }); - // FIXME echatellier 20130901 for root children not being updated - $scope.$watchCollection("tree.children", function(newValue, oldValue, scope){ - if (newValue !== oldValue) { - var tree = treeGetter($scope); - update(tree); - } - }); - - // on force un premier appel pour que l'arbre s'affiche - update(treeGetter($scope)); - }; - } - }; -}]; - -var wtWebSocketService = [function() { - var service = {}; - - service.connect = function() { - if(service.ws) { return; } - - var ws = new WebSocket("ws://localhost:12345/jtimer"); - - ws.onopen = function() { - console.log('Websocket open'); - service.callback.status(true); - }; - - ws.onerror = function() { - console.log('Websocket error'); - }; - - ws.onclose = function() { - service.callback.status(false); - }; - - ws.onmessage = function(message) { - service.callback.message(message.data); - }; - - service.ws = ws; - }; - - service.send = function(message) { - service.ws.send(message); - }; - - service.subscribe = function(callback) { - service.callback = callback; - }; - - return service; -}]; - - -angular.module('webtimer', ['webtimerFilters', 'ngRoute', 'ngAnimate', 'ui.bootstrap']) - .config(['$routeProvider', function($routeProvider) { - $routeProvider. - when('/tasks', {templateUrl: 'partials/tasks.html', controller: TasksCtrl}). - when('/about', {templateUrl: 'partials/about.html'}). - when('/contact', {templateUrl: 'partials/contact.html'}). - otherwise({redirectTo: '/tasks'}); - }]) - - .factory("$localStorage", function() { - // Encapsule l'acces au localStorage pour - // - ajouter un prefix au variable sauvee pour les differencier des autres ("WebTimer-") - var webtimerPrefix = "WebTimer-"; - return { - set: function(key, value) { - key = webtimerPrefix + key; - // add version, to check version during read (get) - var item = value.toJson(); - window.localStorage.setItem(key, item); - }, - get: function(key) { - key = webtimerPrefix + key; - var item = window.localStorage.getItem(key); - var result = new WebTimerData(); - result.fromJson(item); - - return result; - } - }; - }) - - .directive('wtTreeRepeat', wtTreeRepeatDirective) - .service('wtWebsocket', wtWebSocketService); Copied: branches/ng-jtimer/src/main/webapp/js/app.js (from rev 2951, branches/ng-jtimer/jtimer-server/src/main/webapp/js/app.js) =================================================================== --- branches/ng-jtimer/src/main/webapp/js/app.js (rev 0) +++ branches/ng-jtimer/src/main/webapp/js/app.js 2014-04-14 19:13:31 UTC (rev 2956) @@ -0,0 +1,275 @@ +/** + * Cette directive permet de parcourir un Arbre, pour chaque noeud de l'arbre + * un l'element DOM est duplique. + * Il est possible + * - de filtrer les noeuds lors de la definition de l'arbre (wtTreeRepeat) + * (ex: wt-tree-repeat="tree | filter:query | orderBy:'task.name'") + * - d'afficher le noeud root ou non (wtDisplayRoot) + * - de forcer l'ouverture de tout les noeuds (wtForceOpen) + * + * Lors du parcours pour chaque noeud un nouveau scope est cree permettant + * d'utilise les variables: + * - $node le noeud courant de l'arbre + * - $index l'index de parcours de ce noeud (0 pour le root) + * - $level la profondeur de ce noeud (0 pour le root) + * - $state l'etat de ce noeud ('empty', 'open', 'close') + * - $path le chemin pour arriver a ce noeud (tous ces noeuds parents) + * - $pathIndex le chemin pour arriver a ce noeud par index dans le tableau children du pere + * - $toggleState une fonction qui permet de changer l'etat d'un noeud ('open' <-> 'close') + + * + * @param {ngAnimate} $animator permet l'ajout, suppression des noeuds dans le DOM + * @param {ngFilter} $filter permet de filtrer les elements de l'arbre a afficher (filtre, tri, ...) + * @param {ngParse} $parse permet de parser des expressions qui doivent etre evaluer regulierement sur une scope + */ +var wtTreeRepeatDirective = ['$animate', '$filter', '$parse', function($animate, $filter, $parse) { + return { + transclude: 'element', + priority: 1000, + terminal: true, + compile: function(element, attr, linker) { + return function($scope, $element, $attr){ + + // sert a surveiller les changements sur la donnee ou les filtres + // qui engendrerait un besoin de rafraichissement. + // (ce tableau contient les fonctions permettant leur desenregistrement) + var watchers = []; + // element genere HTML et scope du dernier arbre represente + var cache = new Cache($animate); + // indique si l'element root doit etre affiche ou non (faux par defaut) + var displayRoot = $parse($attr.wtDisplayRoot || 'false'); + // indique si l'arbre doit etre ouvert de facon forcee ou non (faux par defaut) + var forceOpen = $parse($attr.wtForceOpen || 'false'); + // l'expression permettant de recuperer l'arbre et les filtres + var expression = $attr.wtTreeRepeat; + + // les differents filtres a applique aux noeuds enfants + var filters = []; + var filterStrings = expression.split('|'); + // l'expression pour la recuperation de arbre + var tree = filterStrings.shift(); + // add tree as watcher + watchers.push(tree); + // add forceOpen as watcher + watchers.push($attr.wtForceOpen||'false'); + + // Recuperation des filtres et preparation pour etre pret + // a l'utilisation + angular.forEach(filterStrings, function(filterString) { + var argStrings = filterString.split(":"); + var filterName = argStrings.shift().trim(); + var argGetters = argStrings.map(function(e) { + // add all args as watcher + watchers.push(e); + var result = $parse(e); + return result; + }); + var filter = function(children) { + var f = $filter(filterName); + var args = argGetters.map(function(a) { + return a($scope); + }); + var result = f.apply(null, [children].concat(args)); + return result; + }; + filters.push(filter); + }); + + // met a jour l'affichage de l'arbre + var update = function(tree) { + // les objets HTML et scope utilise durant cette mise a jour + // qui pourront etre reutilise durant la mis a jour suivante + var newCache = new Cache($animate); + + // l'index de parcours du noeud, on met dans un tableau + // pour avoir une reference lors du passage en argument + // et non pas une valeur lors des appels recursifs + var index = [0]; + // le niveau du noeud + var level = 0; + var path = []; + var pathIndex = []; + // le dernier element HTML ajoute (il faut mettre le suivant apres celui-ci) + var lastElement = $element; + + /** + * Genere un noeud et appel la fonction pour chaque noeud + * fils a affiche + */ + var generate = function(node, index, level, path, pathIndex) { + var state = 'open'; // init to open, if root is not display + + // on affiche le root que si demande + if (index[0] !== 0 || displayRoot($scope)) { + // try to find already created element + var cacheEntry = cache.get(node) || {node: node, scope:$scope.$new()}; + node.copyState(cacheEntry.node); // copy les etats, les noeuds ouvert doivent rester ouvert + var isNewElement = !cacheEntry.element; + + // new item which we don't know about + var childScope = cacheEntry.scope; + + if (node.children.length === 0) { + state = 'empty'; + } else { + if (node.$$open || forceOpen($scope)) { + state = 'open'; + } else { + state = 'close'; + } + } + + childScope.$node = node; + childScope.$index = index[0]; + childScope.$level = level; + childScope.$state = state; + childScope.$path = path; + childScope.$pathIndex = pathIndex; + childScope.$toggleState = function() { + node.$$open = !node.$$open; + }; + isNewElement && childScope.$watch("$node.$$open", function (newValue, oldValue, scope) { + if (newValue !== oldValue) { + update(tree); + } + }); + isNewElement && childScope.$watch("$node.children.length", function (newValue, oldValue, scope) { + if (newValue !== oldValue) { + update(tree); + } + }); + + if (!isNewElement) { + $animate.move(cacheEntry.element, null, lastElement); + lastElement = cacheEntry.element; + newCache.put(node, cacheEntry.element, cacheEntry.scope); + } else { + linker(childScope, function(clone) { + $animate.enter(clone, null, lastElement); + lastElement = clone; + newCache.put(node, clone, childScope); + }); + } + } + index[0]++; + + if (state == 'open') { + var children = node.children; + filters.forEach(function(e) { + children = e(children); + }); + for (var i = 0, length = children.length; i < length; i++) { + var child = children[i]; + generate(child, index, level+1, path.concat([child]), pathIndex.concat([i])); + } + } + }; + + generate(tree, index, level, path, pathIndex); + + // on nettoie les anciens noeud non reutilise + cache.clear(); + // on met les nouveaux noeuds dans le cache pour la prochaine maj + cache = newCache; + }; + + // expression permettant de recupere facilement l'arbre + var treeGetter = $parse(tree); + + // on enregistre chaque watcher sur le scope + angular.forEach(watchers, function (watcher) { + $scope.$watch(watcher, function(newValue, oldValue, scope){ + if (newValue !== oldValue) { + var tree = treeGetter($scope); + update(tree); + } + }); + }); + // FIXME echatellier 20130901 for root children not being updated + $scope.$watchCollection("tree.children", function(newValue, oldValue, scope){ + if (newValue !== oldValue) { + var tree = treeGetter($scope); + update(tree); + } + }); + + // on force un premier appel pour que l'arbre s'affiche + update(treeGetter($scope)); + }; + } + }; +}]; + +var wtWebSocketService = [function() { + var service = {}; + + service.connect = function() { + if(service.ws) { return; } + + var ws = new WebSocket("ws://localhost:12345/jtimer"); + + ws.onopen = function() { + console.log('Websocket open'); + service.callback.status(true); + }; + + ws.onerror = function() { + console.log('Websocket error'); + }; + + ws.onclose = function() { + service.callback.status(false); + }; + + ws.onmessage = function(message) { + service.callback.message(message.data); + }; + + service.ws = ws; + }; + + service.send = function(message) { + service.ws.send(message); + }; + + service.subscribe = function(callback) { + service.callback = callback; + }; + + return service; +}]; + + +angular.module('webtimer', ['webtimerFilters', 'ngRoute', 'ngAnimate', 'ui.bootstrap']) + .config(['$routeProvider', function($routeProvider) { + $routeProvider. + when('/tasks', {templateUrl: 'partials/tasks.html', controller: TasksCtrl}). + when('/about', {templateUrl: 'partials/about.html'}). + when('/contact', {templateUrl: 'partials/contact.html'}). + otherwise({redirectTo: '/tasks'}); + }]) + + .factory("$localStorage", function() { + // Encapsule l'acces au localStorage pour + // - ajouter un prefix au variable sauvee pour les differencier des autres ("WebTimer-") + var webtimerPrefix = "WebTimer-"; + return { + set: function(key, value) { + key = webtimerPrefix + key; + // add version, to check version during read (get) + var item = value.toJson(); + window.localStorage.setItem(key, item); + }, + get: function(key) { + key = webtimerPrefix + key; + var item = window.localStorage.getItem(key); + var result = new WebTimerData(); + result.fromJson(item); + + return result; + } + }; + }) + + .directive('wtTreeRepeat', wtTreeRepeatDirective) + .service('wtWebsocket', wtWebSocketService); Deleted: branches/ng-jtimer/src/main/webapp/js/controllers.js =================================================================== --- branches/ng-jtimer/jtimer-server/src/main/webapp/js/controllers.js 2014-02-06 20:44:47 UTC (rev 2952) +++ branches/ng-jtimer/src/main/webapp/js/controllers.js 2014-04-14 19:13:31 UTC (rev 2956) @@ -1,397 +0,0 @@ -function TasksCtrl($scope, $timeout, $localStorage, $window, $document, $modal, wtWebsocket) { - - /** - * {Boolean} vrai si on est online - */ - $scope.online = $window.navigator.onLine; - - // {WebTimerData} toutes les donnees - $scope.data = $localStorage.get("data"); - // {TreeNode} l'arbre regenere automatiquement lorsque les donnees changent - $scope.tree; - // {Array of Function} les listeners qui surveille l'ajout de nouveau temps, et qui les ajoutes dans l'arbre - $scope.treeWatcher = []; - // {String} le nom de la nouvelle tache a creer - $scope.name = ""; - // {Task} la derniere tache selectionnee - $scope.selectedTask = null; - // {Task} la tache en cours de timing - $scope.currentTask = null; - // {Date in millis} le temps pour la tache en cours de timing - $scope.currentTaskDate = null; - // {String} le filtre d'affichage des noeuds (permet la recherche d'un noeud) - $scope.query = ""; - // {boolean} boolean qui permet de force le depliage complet de l'arbre s'il est vrai - $scope.forceExpanded = false; - - // {boolean} boolean qui indique si la colonne NAME doit etre affichee - $scope.showName = true; - // {boolean} boolean qui indique si la colonne TODAY doit etre affichee - $scope.showToday = true; - // {boolean} boolean qui indique si la colonne TOTAL doit etre affichee - $scope.showGlobal = true; - // {boolean} boolean qui indique si la colonne TAGS doit etre affichee - $scope.showTags = true; - - // {boolean} etat du client local (le serveur websocket) - $scope.webSocketClientOnline = false; - // {boolean} boolean qui indique si une inactivité a été détectée - $scope.webSocketClientIdle = false; - - /** - * Met a jour la tache selectionne, si la tache selectionnee est la courante - * alors on met la selection a null - * @param {Task} task - */ - $scope.setSelectedTask = function(task) { - if ($scope.selectedTask === task) { - $scope.selectedTask = null; - } else { - $scope.selectedTask = task; - } - }; - - /** - * Permet de faire des actions sur la tache selectionne en fonction - * des touches pressees - * @param {type} e - * @returns {undefined} - */ - $document[0].onkeydown = function(e){ - console.log(e); - // i = 73; d = 68; F2 = 113 - if ($scope.selectedTask) { - var taskTime = $scope.getTodayTaskTime($scope.selectedTask); - if (e.keyCode === 113) { - // edit task, time, note - } else if (e.keyCode === 73 && e.ctrlKey && e.shiftKey) { - // increment by 30min - taskTime.addTime(30*60*1000); - } else if (e.keyCode === 68 && e.ctrlKey && e.shiftKey) { - // decrement by 30min - taskTime.addTime(-30*60*1000); - } else if (e.keyCode === 73 && e.ctrlKey) { - // increment by 5min - taskTime.addTime(5*60*1000); - } else if (e.keyCode === 68 && e.ctrlKey) { - // decrement by 5min - taskTime.addTime(-5*60*1000); - } - } - }; - - $window.addEventListener("offline", function(e) { - $scope.online = false; - }, false); - $window.addEventListener("online", function(e) { - $scope.online = true; - }, false); - - /** - * Force la sauvegarde des datas - * @returns {undefined} - */ - var save = function() { - $localStorage.set("data", $scope.data); - }; - - /** - * Timer qui mais les temps a jour toutes les secondes si une tache est - * active - * @returns {undefined} - */ - var refresh = function() { - $timeout(function() { - if ($scope.currentTask) { - var now = Date.now(); - var taskTime = $scope.getTodayTaskTime($scope.currentTask); - taskTime.addTime(now - $scope.currentTaskDate); - $scope.currentTaskDate = now; - save(); - } - refresh(); - }, 1000); - }; - refresh(); - - /** - * Ajoute une tache root - */ - $scope.addTask = function() { - var newTask = new Task($scope.name); - $scope.data.tasks.push(newTask); - $scope.name = ""; - save(); - if ($scope.tree) { - $scope.tree.addChild($scope.createTreeNode(newTask)); - } - }; - - /** - * Ajoute une sous tache a la tache du noeud passe en parametre - * @param {type} node - */ - $scope.addSubTask = function(node) { - var task = node.task; - var newTask = new Task("New task", task.taskId); - $scope.data.tasks.push(newTask); - node.$$open = true; - save(); - node.addChild($scope.createTreeNode(newTask)); - }; - - /** - * Supprime une tache (et ces sous taches recursivement) - * @param {type} task - */ - $scope.removeTask = function(node) { - // methode pour faire la suppression recursivement - var removeRecurse = function(tasks) { - angular.forEach(tasks, function(task) { - task.remove(); - var children = $scope.getChildren(task); - removeRecurse(children); - }); - }; - // mark all task as removed - removeRecurse([node.task]); - // remove node in tree - node.remove(); - save(); - }; - - /** - * met a jour la variable $scope.tree par recreation de l'arbre - * Tous les listeners de l'ancien arbre sont enleves - */ - $scope.createTree = function() { - // on supprime tous les watchers de l'arbre courant - angular.forEach($scope.treeWatcher, function(deregisterFuntion) { - // la methode stocker dans treeWatcher permet de desenregistrer le watcher - deregisterFuntion(); - }); - $scope.treeWatcher = []; - - var nodes = []; - angular.forEach($scope.getRootTask(), function(t) { - var node = $scope.createTreeNode(t); - nodes.push(node); - }); - - var result = new TreeNode(new Task("root"), null, null, nodes); - $scope.tree = result; - }; - - /** - * Retourne la liste des enfants non supprime d'un noeud. Les sous taches - * retourne peuvent etre modifiee via encapsulationFuntion si elle existe - * @param {Task} task la tache dont on recherche les enfants - * @param {Funciton} encapsulationFuntion une methode appelee pour chaque enfant, - * qui peut retourner un autre objet que l'enfant - * @returns {Array of Task or other if encapsulationFuntion used} - */ - $scope.getChildren = function (task, encapsulationFuntion) { - var result = []; - angular.forEach($scope.data.tasks, function (t) { - if (!t.isRemoved() && task.isParentOf(t)) { - var node = t; - if (encapsulationFuntion) { - node = encapsulationFuntion(node); - } - result.push(node); - } - }); - - return result; - }; - - /** - * Encapsule une tache dans un TreeNode. On ajoute un watcher sur les temps - * pour cette tache qui pousse les nouvelles donnes dans le noeud lorsqu'ils - * sont modifies - * - * @param {Task} task - * @returns {TreeNode} - */ - $scope.createTreeNode = function(task) { - var globalTime = $scope.data.globalTimes[task.taskId] || new GlobalTime(); - var localTimes = $scope.data.times[task.taskId] || []; - var children = $scope.getChildren(task, $scope.createTreeNode); - var node = new TreeNode(task, globalTime, localTimes, children); - - var watcher = $scope.$watch("data.times['"+task.taskId+"']", function(localtimes) { - node.setTaskTimes(localtimes); - }, true); - $scope.treeWatcher.push(watcher); - - return node; - }; - - /** - * Retourne la liste des taches root actif (non supprime) - * @returns {result} - */ - $scope.getRootTask = function () { - var result = []; - angular.forEach($scope.data.tasks, function (t) { - if (t.isRoot() && !t.isRemoved()) { - result.push(t); - } - }); - return result; - }; - - /** - * Retourne l'objet TaskTime d'aujourd'hui pour la tache demandee - * Si cet objet n'existait pas, il est cree et ajouter a la liste - * des objets temps existant - * @param {type} task - * @returns {nodes} - */ - $scope.getTodayTaskTime = function(task) { - var times = $scope.data.times[task.taskId]; - if (!times) { - times = []; - $scope.data.times[task.taskId]= times; - } - - var result; - angular.forEach(times, function (t) { - if (!result && t.isToday()) { - result = t; - } - }); - - if (!result) { - result = new TaskTime(task); - times.push(result); - } - - return result; - }; - - /** - * Lance l'edition du nom d'une tache - * @param {TreeNode} node - * @param {String} type le type d'action - */ - $scope.editTask = function(node, type) { - node.edit = type; - save(); - }; - - /** - * Sauve la modification de la tache - * @param {TreeNode} node - */ - $scope.saveTask = function(node) { - node.edit = null; - save(); - }; - - /** - * Active/desactive le comptage de temps pour une tache - * @param {type} task - * @param {type} element - */ - $scope.timeTask = function(task, element) { - var now = Date.now(); - if ($scope.currentTask) { - var taskTime = $scope.getTodayTaskTime($scope.currentTask); - taskTime.addTime(now - $scope.currentTaskDate); - } - - if ($scope.currentTask !== task) { - $scope.currentTask = task; - $scope.currentTaskDate = now; - } else { - $scope.currentTask = null; - $scope.currentTaskDate = null; - } - save(); - }; - - /** - * Retourne la date et heure courant - * @returns {String} - */ - $scope.currentDate = function() { - return moment().format("HH:mm DD/MM/YYYY"); - }; - - /** - * Subscribe to websocket messages queue. - */ - wtWebsocket.subscribe({ - message: function(data) { - var jsData = JSON.parse(data); - //$scope.messages.push(message); - //$scope.$apply(); - //console.log(jsData); - if (jsData.idle) { - if (jsData.idle > 30000 && !$scope.webSocketClientIdle) { //30s - console.log("Idle detected"); - idleDetected(); - $scope.$apply(); - $scope.webSocketClientIdle = true; - } - } - }, - status: function(status) { - $scope.webSocketClientOnline = status; - } - }); - - /** - * Called on idle detect. - */ - var idleDetected = function() { - // for systray to update rendering - wtWebsocket.send(JSON.stringify({idleStatus:true})); - var modalInstance = $modal.open({ - templateUrl: 'idleModalTemplate.html', - windowClass: 'idleModal', - controller: IdleModalCtrl, - backdropFade: true, - dialogFade: true, - keyboard: false // for cancel to not work - }); - modalInstance.result.then($scope.restartFromIdleness); - }; - - /** - * Called by modal dialog to resume from idle. - * - * @param {string} restart option ('stop', 'continue', 'resume') - */ - $scope.restartFromIdleness = function(restartOption) { - switch(restartOption) { - case 'stop': - break; - case 'continue': - break; - case 'resume': - break; - } - // for systray to update rendering - wtWebsocket.send(JSON.stringify({idleStatus:false})); - $scope.webSocketClientIdle = false; - }; - - // force the first tree creation - $scope.createTree(); - // connect to webscocket server (go client) - wtWebsocket.connect(); -} - -/** - * Controller de pour la modal d'inactivité. - * - * @param $scope - * @param $modalInstance - */ -function IdleModalCtrl($scope, $modalInstance) { - $scope.close = function(restartOption) { - $modalInstance.close(restartOption); - }; -} \ No newline at end of file Copied: branches/ng-jtimer/src/main/webapp/js/controllers.js (from rev 2951, branches/ng-jtimer/jtimer-server/src/main/webapp/js/controllers.js) =================================================================== --- branches/ng-jtimer/src/main/webapp/js/controllers.js (rev 0) +++ branches/ng-jtimer/src/main/webapp/js/controllers.js 2014-04-14 19:13:31 UTC (rev 2956) @@ -0,0 +1,397 @@ +function TasksCtrl($scope, $timeout, $localStorage, $window, $document, $modal, wtWebsocket) { + + /** + * {Boolean} vrai si on est online + */ + $scope.online = $window.navigator.onLine; + + // {WebTimerData} toutes les donnees + $scope.data = $localStorage.get("data"); + // {TreeNode} l'arbre regenere automatiquement lorsque les donnees changent + $scope.tree; + // {Array of Function} les listeners qui surveille l'ajout de nouveau temps, et qui les ajoutes dans l'arbre + $scope.treeWatcher = []; + // {String} le nom de la nouvelle tache a creer + $scope.name = ""; + // {Task} la derniere tache selectionnee + $scope.selectedTask = null; + // {Task} la tache en cours de timing + $scope.currentTask = null; + // {Date in millis} le temps pour la tache en cours de timing + $scope.currentTaskDate = null; + // {String} le filtre d'affichage des noeuds (permet la recherche d'un noeud) + $scope.query = ""; + // {boolean} boolean qui permet de force le depliage complet de l'arbre s'il est vrai + $scope.forceExpanded = false; + + // {boolean} boolean qui indique si la colonne NAME doit etre affichee + $scope.showName = true; + // {boolean} boolean qui indique si la colonne TODAY doit etre affichee + $scope.showToday = true; + // {boolean} boolean qui indique si la colonne TOTAL doit etre affichee + $scope.showGlobal = true; + // {boolean} boolean qui indique si la colonne TAGS doit etre affichee + $scope.showTags = true; + + // {boolean} etat du client local (le serveur websocket) + $scope.webSocketClientOnline = false; + // {boolean} boolean qui indique si une inactivité a été détectée + $scope.webSocketClientIdle = false; + + /** + * Met a jour la tache selectionne, si la tache selectionnee est la courante + * alors on met la selection a null + * @param {Task} task + */ + $scope.setSelectedTask = function(task) { + if ($scope.selectedTask === task) { + $scope.selectedTask = null; + } else { + $scope.selectedTask = task; + } + }; + + /** + * Permet de faire des actions sur la tache selectionne en fonction + * des touches pressees + * @param {type} e + * @returns {undefined} + */ + $document[0].onkeydown = function(e){ + console.log(e); + // i = 73; d = 68; F2 = 113 + if ($scope.selectedTask) { + var taskTime = $scope.getTodayTaskTime($scope.selectedTask); + if (e.keyCode === 113) { + // edit task, time, note + } else if (e.keyCode === 73 && e.ctrlKey && e.shiftKey) { + // increment by 30min + taskTime.addTime(30*60*1000); + } else if (e.keyCode === 68 && e.ctrlKey && e.shiftKey) { + // decrement by 30min + taskTime.addTime(-30*60*1000); + } else if (e.keyCode === 73 && e.ctrlKey) { + // increment by 5min + taskTime.addTime(5*60*1000); + } else if (e.keyCode === 68 && e.ctrlKey) { + // decrement by 5min + taskTime.addTime(-5*60*1000); + } + } + }; + + $window.addEventListener("offline", function(e) { + $scope.online = false; + }, false); + $window.addEventListener("online", function(e) { + $scope.online = true; + }, false); + + /** + * Force la sauvegarde des datas + * @returns {undefined} + */ + var save = function() { + $localStorage.set("data", $scope.data); + }; + + /** + * Timer qui mais les temps a jour toutes les secondes si une tache est + * active + * @returns {undefined} + */ + var refresh = function() { + $timeout(function() { + if ($scope.currentTask) { + var now = Date.now(); + var taskTime = $scope.getTodayTaskTime($scope.currentTask); + taskTime.addTime(now - $scope.currentTaskDate); + $scope.currentTaskDate = now; + save(); + } + refresh(); + }, 1000); + }; + refresh(); + + /** + * Ajoute une tache root + */ + $scope.addTask = function() { + var newTask = new Task($scope.name); + $scope.data.tasks.push(newTask); + $scope.name = ""; + save(); + if ($scope.tree) { + $scope.tree.addChild($scope.createTreeNode(newTask)); + } + }; + + /** + * Ajoute une sous tache a la tache du noeud passe en parametre + * @param {type} node + */ + $scope.addSubTask = function(node) { + var task = node.task; + var newTask = new Task("New task", task.taskId); + $scope.data.tasks.push(newTask); + node.$$open = true; + save(); + node.addChild($scope.createTreeNode(newTask)); + }; + + /** + * Supprime une tache (et ces sous taches recursivement) + * @param {type} task + */ + $scope.removeTask = function(node) { + // methode pour faire la suppression recursivement + var removeRecurse = function(tasks) { + angular.forEach(tasks, function(task) { + task.remove(); + var children = $scope.getChildren(task); + removeRecurse(children); + }); + }; + // mark all task as removed + removeRecurse([node.task]); + // remove node in tree + node.remove(); + save(); + }; + + /** + * met a jour la variable $scope.tree par recreation de l'arbre + * Tous les listeners de l'ancien arbre sont enleves + */ + $scope.createTree = function() { + // on supprime tous les watchers de l'arbre courant + angular.forEach($scope.treeWatcher, function(deregisterFuntion) { + // la methode stocker dans treeWatcher permet de desenregistrer le watcher + deregisterFuntion(); + }); + $scope.treeWatcher = []; + + var nodes = []; + angular.forEach($scope.getRootTask(), function(t) { + var node = $scope.createTreeNode(t); + nodes.push(node); + }); + + var result = new TreeNode(new Task("root"), null, null, nodes); + $scope.tree = result; + }; + + /** + * Retourne la liste des enfants non supprime d'un noeud. Les sous taches + * retourne peuvent etre modifiee via encapsulationFuntion si elle existe + * @param {Task} task la tache dont on recherche les enfants + * @param {Funciton} encapsulationFuntion une methode appelee pour chaque enfant, + * qui peut retourner un autre objet que l'enfant + * @returns {Array of Task or other if encapsulationFuntion used} + */ + $scope.getChildren = function (task, encapsulationFuntion) { + var result = []; + angular.forEach($scope.data.tasks, function (t) { + if (!t.isRemoved() && task.isParentOf(t)) { + var node = t; + if (encapsulationFuntion) { + node = encapsulationFuntion(node); + } + result.push(node); + } + }); + + return result; + }; + + /** + * Encapsule une tache dans un TreeNode. On ajoute un watcher sur les temps + * pour cette tache qui pousse les nouvelles donnes dans le noeud lorsqu'ils + * sont modifies + * + * @param {Task} task + * @returns {TreeNode} + */ + $scope.createTreeNode = function(task) { + var globalTime = $scope.data.globalTimes[task.taskId] || new GlobalTime(); + var localTimes = $scope.data.times[task.taskId] || []; + var children = $scope.getChildren(task, $scope.createTreeNode); + var node = new TreeNode(task, globalTime, localTimes, children); + + var watcher = $scope.$watch("data.times['"+task.taskId+"']", function(localtimes) { + node.setTaskTimes(localtimes); + }, true); + $scope.treeWatcher.push(watcher); + + return node; + }; + + /** + * Retourne la liste des taches root actif (non supprime) + * @returns {result} + */ + $scope.getRootTask = function () { + var result = []; + angular.forEach($scope.data.tasks, function (t) { + if (t.isRoot() && !t.isRemoved()) { + result.push(t); + } + }); + return result; + }; + + /** + * Retourne l'objet TaskTime d'aujourd'hui pour la tache demandee + * Si cet objet n'existait pas, il est cree et ajouter a la liste + * des objets temps existant + * @param {type} task + * @returns {nodes} + */ + $scope.getTodayTaskTime = function(task) { + var times = $scope.data.times[task.taskId]; + if (!times) { + times = []; + $scope.data.times[task.taskId]= times; + } + + var result; + angular.forEach(times, function (t) { + if (!result && t.isToday()) { + result = t; + } + }); + + if (!result) { + result = new TaskTime(task); + times.push(result); + } + + return result; + }; + + /** + * Lance l'edition du nom d'une tache + * @param {TreeNode} node + * @param {String} type le type d'action + */ + $scope.editTask = function(node, type) { + node.edit = type; + save(); + }; + + /** + * Sauve la modification de la tache + * @param {TreeNode} node + */ + $scope.saveTask = function(node) { + node.edit = null; + save(); + }; + + /** + * Active/desactive le comptage de temps pour une tache + * @param {type} task + * @param {type} element + */ + $scope.timeTask = function(task, element) { + var now = Date.now(); + if ($scope.currentTask) { + var taskTime = $scope.getTodayTaskTime($scope.currentTask); + taskTime.addTime(now - $scope.currentTaskDate); + } + + if ($scope.currentTask !== task) { + $scope.currentTask = task; + $scope.currentTaskDate = now; + } else { + $scope.currentTask = null; + $scope.currentTaskDate = null; + } + save(); + }; + + /** + * Retourne la date et heure courant + * @returns {String} + */ + $scope.currentDate = function() { + return moment().format("HH:mm DD/MM/YYYY"); + }; + + /** + * Subscribe to websocket messages queue. + */ + wtWebsocket.subscribe({ + message: function(data) { + var jsData = JSON.parse(data); + //$scope.messages.push(message); + //$scope.$apply(); + //console.log(jsData); + if (jsData.idle) { + if (jsData.idle > 30000 && !$scope.webSocketClientIdle) { //30s + console.log("Idle detected"); + idleDetected(); + $scope.$apply(); + $scope.webSocketClientIdle = true; + } + } + }, + status: function(status) { + $scope.webSocketClientOnline = status; + } + }); + + /** + * Called on idle detect. + */ + var idleDetected = function() { + // for systray to update rendering + wtWebsocket.send(JSON.stringify({idleStatus:true})); + var modalInstance = $modal.open({ + templateUrl: 'idleModalTemplate.html', + windowClass: 'idleModal', + controller: IdleModalCtrl, + backdropFade: true, + dialogFade: true, + keyboard: false // for cancel to not work + }); + modalInstance.result.then($scope.restartFromIdleness); + }; + + /** + * Called by modal dialog to resume from idle. + * + * @param {string} restart option ('stop', 'continue', 'resume') + */ + $scope.restartFromIdleness = function(restartOption) { + switch(restartOption) { + case 'stop': + break; + case 'continue': + break; + case 'resume': + break; + } + // for systray to update rendering + wtWebsocket.send(JSON.stringify({idleStatus:false})); + $scope.webSocketClientIdle = false; + }; + + // force the first tree creation + $scope.createTree(); + // connect to webscocket server (go client) + wtWebsocket.connect(); +} + +/** + * Controller de pour la modal d'inactivité. + * + * @param $scope + * @param $modalInstance + */ +function IdleModalCtrl($scope, $modalInstance) { + $scope.close = function(restartOption) { + $modalInstance.close(restartOption); + }; +} \ No newline at end of file Deleted: branches/ng-jtimer/src/main/webapp/js/entities.js =================================================================== --- branches/ng-jtimer/jtimer-server/src/main/webapp/js/entities.js 2014-02-06 20:44:47 UTC (rev 2952) +++ branches/ng-jtimer/src/main/webapp/js/entities.js 2014-04-14 19:13:31 UTC (rev 2956) @@ -1,368 +0,0 @@ -/** - * Genere un UUID - * @returns {String} - */ -function generateUUID(){ - var d = Date.now(); - var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - var r = (d + Math.random()*16)%16 | 0; - d = Math.floor(d/16); - return (c==='x' ? r : (r&0x7|0x8)).toString(16); - }); - return uuid; -}; - -/** - * Retourne la date d'aujourd'hui sous la forme "2013-O7-25" - * @returns {String} - */ -function today() { - var result = moment().format("YYYY-MM-DD"); - return result; -} - -/** - * permet de gerer les elements HTML et scope creer pour chaque - * noeud et les reutilisers plutot que de les recreer a chaque mise a jour - * - * @param {ngAnimator} animate l'objet permettant de supprimer un noeud dans le DOM - * @returns {Cache} - */ -var Cache = function(animate) { - this.animate = animate; -}; -Cache.prototype.put = function(node, element, scope) { - var id = node.task.taskId; - this[id] = {node: node, element: element, scope: scope}; -}; -Cache.prototype.get = function(nodeOrId) { - var id = nodeOrId; - if (!angular.isString(nodeOrId)) { - id = nodeOrId.task.taskId; - } - var result = this[id]; - delete this[id]; - return result; -}; - -Cache.prototype.clear = function() { - for (var key in this) { - if (this.hasOwnProperty(key) && key !== "animate") { - var entry = this[key]; - this.animate.leave(entry.element); - entry.scope.$destroy(); - } - } -}; - - -/** - * Toutes les donnees qui sont a stocker entre 2 sessions - * @returns {WebTimerData} - */ -var WebTimerData = function() { - // la version des donnees - this.dataVersion = 1; - - this.tasks = []; // Array of Task - this.globalTimes = {}; // key: taskId, value: GlobalTime - this.times = {}; // key: taskId, value: Array of TaskTime - this.notes = {}; // key: taskId, value: Array of TaskNote -}; - -/** - * Migre les donnees d'une version a une autre - * @param {Number} oldVersion - * @param {Number} newVersion - * @param {JSON} data - * @returns {JSON} - */ -WebTimerData.prototype.migrate = function(oldVersion, newVersion, data) { - return data; -}; - -/** - * Converti l'objet WebTimerData en Json en ajoutant - * @returns {JSON} - */ -WebTimerData.prototype.toJson = function() { - var result = angular.toJson(this); - return result; -}; - -/** - * Charge des donnees au format JSON les convertit dans le bon type d'objet, - * fait la migration des data si necessaire - * @param {JSON or JsonString} json - * @returns {WebTimerData} retourne lui meme - */ -WebTimerData.prototype.fromJson = function(json) { - if (angular.isString(json)) { - json = angular.fromJson(json); - } - if (json) { - if (json.dataVersion !== this.dataVersion) { - json = this.migrate(json.dataVersion, this.dataVersion, json); - } - if (json) { - angular.forEach(json.tasks, function (t) { - t = jQuery.extend(new Task(), t); - this.tasks.push(t); - }, this); - - angular.forEach(json.globalTimes, function (t, k) { - t = jQuery.extend(new GlobalTime(), t); - this.globalTimes[k] = t; - }, this); - - angular.forEach(json.times, function (times, k) { - this.times[k] = []; - angular.forEach(times, function (t) { - t = jQuery.extend(new TaskTime(), t); - this.times[k].push(t); - }, this); - }, this); - - angular.forEach(json.notes, function (notes, k) { - this.notes[k] = []; - angular.forEach(notes, function (n, k) { - n = jQuery.extend(new TaskNote(), n); - this.notes[k].push(n); - }, this); - }, this); - } - } - return this; -}; - -/** - * Un noeud de l'arbre. - * - * @param {Task} task la tache a encapsuler - * @param {GlobalTime} globalTime les temps totaux provenant du serveur - * @param {Array of TaskTime} localTimes les temps crees localement - * @param {Array of TreeNode} children les enfants de ce noeud - * @returns {TreeNode} - */ -var TreeNode = function (task, globalTime, localTimes, children) { - this.task = task || new Task("root"); - this.globalTime = globalTime || new GlobalTime(); - this.localTimes = localTimes || []; - children = angular.forEach(children, function(child) { - child.parent = this; - }, this); - this.children = children || []; -}; - -/** - * Ce retire de l'arbre - * @returns {undefined} - */ -TreeNode.prototype.remove = function() { - if (this.parent) { - var brothers = this.parent.children; - var match = brothers.indexOf(this); - - if (match > -1 ) { - brothers.splice(match, 1); - delete this.parent; - } - } -}; - -TreeNode.prototype.addChild = function(node) { - node.parent = this; - this.children.push(node); -}; - -/** - * Copie toutes les donnees d'etat d'une noeud - * @param {TreeNode} node - * @returns {undefined} - */ -TreeNode.prototype.copyState = function(node) { - this.$$open = node.$$open; -}; - -/** - * Met a jour les temps locaux - * - * @param {Array of TaskTime} taskTimes - * @returns {undefined} - */ -TreeNode.prototype.setTaskTimes = function(taskTimes) { - this.localTimes = taskTimes; -}; - -/** - * Retourne le temps consolide pour ce noeud (temps glocal + locaux + enfant) - * @returns {GlobalTime} - */ -TreeNode.prototype.getTime = function() { - var result = new GlobalTime(); - result.addGlobalTime(this.globalTime); - result.addTaskTimes(this.localTimes); - angular.forEach(this.children, function(node) { - var nodeTime = node.getTime(); - result.addGlobalTime(nodeTime); - }); - return result; -}; - -/** - * Objet permettant de stocke le temps total et le temps de la journee actuelle - * - * @param {Task} task - * @returns {GlobalTime} - */ -var GlobalTime = function (task) { - this.taskId = task && task.taskId; - this.today = 0; - this.global = 0; -}; - -/** - * Fait une copie de l'objet - * @returns {GlobalTime} - */ -GlobalTime.prototype.clone = function() { - var result = new GlobalTime(); - result.add(this); - return result; -}; - -/** - * Ajoute les temps d'un GlobalTime - * @param {GlobalTime} globalTime - * @returns {GlobalTime} this - */ -GlobalTime.prototype.addGlobalTime = function(globalTime) { - this.global += globalTime.global; - this.today += globalTime.today; - return this; -}; - -/** - * 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 - * @returns {GlobalTime} this - */ -GlobalTime.prototype.addTaskTimes = function(taskTimes) { - angular.forEach(taskTimes, function(taskTime) { - this.global += taskTime.time; - if (taskTime.isToday()) { - this.today += taskTime.time; - } - }, this); - return this; -}; - -/** - * Represente une tache - * @param {type} name le nom de la tache - * @param {type} parentTaskId l'identifiant de la tache parente - * @returns {Task} - */ -var Task = function (name, parentTaskId) { - this.taskId = generateUUID(); - this.creationDate = Date.now(); - this.modificationDate = this.creationDate; - this.removed = 0; - this.parentTaskId = parentTaskId; - this.name = name; - this.description = ""; - this.tags = []; - this.syncOptions = {}; -}; - -/** - * Marque la tache comme supprimee - * @returns {undefined} - */ -Task.prototype.remove = function() { - this.removed = Date.now(); -}; - -/** - * return vrai si la tache est supprimee - * @returns {boolean} - */ -Task.prototype.isRemoved = function() { - return !!this.removed; -}; - -/** - * Retourne vrai si la tache est parent de la sous tache passee en parametre - * @param {Task} subtask - * @returns {Boolean} - */ -Task.prototype.isParentOf = function(subtask) { - var result = subtask.parentTaskId === this.taskId; - return result; -}; - -/** - * Indique si la tache est une tache root (pas de parent) - * @returns {unresolved} - */ -Task.prototype.isRoot = function() { - var result = !this.parentTaskId; - return result; -}; - -/** - * Permet de conserve une temps cree localement - * @param {Task} task - * @returns {TaskTime} - */ -var TaskTime = function (task) { - this.taskId = task && task.taskId; - this.timeId = generateUUID(); - this.date = today(); - this.time = 0; -}; - -/** - * Retourne vrai si ce temps est pour aujourd'hui - * @returns {Boolean} - */ -TaskTime.prototype.isToday = function() { - var result = this.date === today(); - return result; -}; - -/** - * ajoute du temps - * @param {Number} t - * @returns {TaskTime} this - */ -TaskTime.prototype.addTime = function(t) { - this.time += t; - if (this.time < 0) { - this.time = 0; - } - return this; -}; - -/** - * Represente une note pour une tache - * @param {Task} task - * @returns {TaskNote} - */ -var TaskNote = function (task) { - this.taskId = task && task.taskId; - this.noteId = generateUUID(); - this.date = today(); - this.text = ""; -}; - -/** - * Retourne vrai si cette note est pour aujourd'hui - * @returns {Boolean} - */ -TaskNote.prototype.isToday = function() { - var result = this.date === today(); - return result; -}; - Copied: branches/ng-jtimer/src/main/webapp/js/entities.js (from rev 2951, branches/ng-jtimer/jtimer-server/src/main/webapp/js/entities.js) =================================================================== --- branches/ng-jtimer/src/main/webapp/js/entities.js (rev 0) +++ branches/ng-jtimer/src/main/webapp/js/entities.js 2014-04-14 19:13:31 UTC (rev 2956) @@ -0,0 +1,368 @@ +/** + * Genere un UUID + * @returns {String} + */ +function generateUUID(){ + var d = Date.now(); + var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = (d + Math.random()*16)%16 | 0; + d = Math.floor(d/16); + return (c==='x' ? r : (r&0x7|0x8)).toString(16); + }); + return uuid; +}; + +/** + * Retourne la date d'aujourd'hui sous la forme "2013-O7-25" + * @returns {String} + */ +function today() { + var result = moment().format("YYYY-MM-DD"); + return result; +} + +/** + * permet de gerer les elements HTML et scope creer pour chaque + * noeud et les reutilisers plutot que de les recreer a chaque mise a jour + * + * @param {ngAnimator} animate l'objet permettant de supprimer un noeud dans le DOM + * @returns {Cache} + */ +var Cache = function(animate) { + this.animate = animate; +}; +Cache.prototype.put = function(node, element, scope) { + var id = node.task.taskId; + this[id] = {node: node, element: element, scope: scope}; +}; +Cache.prototype.get = function(nodeOrId) { + var id = nodeOrId; + if (!angular.isString(nodeOrId)) { + id = nodeOrId.task.taskId; + } + var result = this[id]; + delete this[id]; + return result; +}; + +Cache.prototype.clear = function() { + for (var key in this) { + if (this.hasOwnProperty(key) && key !== "animate") { + var entry = this[key]; + this.animate.leave(entry.element); + entry.scope.$destroy(); + } + } +}; + + +/** + * Toutes les donnees qui sont a stocker entre 2 sessions + * @returns {WebTimerData} + */ +var WebTimerData = function() { + // la version des donnees + this.dataVersion = 1; + + this.tasks = []; // Array of Task + this.globalTimes = {}; // key: taskId, value: GlobalTime + this.times = {}; // key: taskId, value: Array of TaskTime + this.notes = {}; // key: taskId, value: Array of TaskNote +}; + +/** + * Migre les donnees d'une version a une autre + * @param {Number} oldVersion + * @param {Number} newVersion + * @param {JSON} data + * @returns {JSON} + */ +WebTimerData.prototype.migrate = function(oldVersion, newVersion, data) { + return data; +}; + +/** + * Converti l'objet WebTimerData en Json en ajoutant + * @returns {JSON} + */ +WebTimerData.prototype.toJson = function() { + var result = angular.toJson(this); + return result; +}; + +/** + * Charge des donnees au format JSON les convertit dans le bon type d'objet, + * fait la migration des data si necessaire + * @param {JSON or JsonString} json + * @returns {WebTimerData} retourne lui meme + */ +WebTimerData.prototype.fromJson = function(json) { + if (angular.isString(json)) { + json = angular.fromJson(json); + } + if (json) { + if (json.dataVersion !== this.dataVersion) { + json = this.migrate(json.dataVersion, this.dataVersion, json); + } + if (json) { + angular.forEach(json.tasks, function (t) { + t = jQuery.extend(new Task(), t); + this.tasks.push(t); + }, this); + + angular.forEach(json.globalTimes, function (t, k) { + t = jQuery.extend(new GlobalTime(), t); + this.globalTimes[k] = t; + }, this); + + angular.forEach(json.times, function (times, k) { + this.times[k] = []; + angular.forEach(times, function (t) { + t = jQuery.extend(new TaskTime(), t); + this.times[k].push(t); + }, this); + }, this); + + angular.forEach(json.notes, function (notes, k) { + this.notes[k] = []; + angular.forEach(notes, function (n, k) { + n = jQuery.extend(new TaskNote(), n); + this.notes[k].push(n); + }, this); + }, this); + } + } + return this; +}; + +/** + * Un noeud de l'arbre. + * + * @param {Task} task la tache a encapsuler + * @param {GlobalTime} globalTime les temps totaux provenant du serveur + * @param {Array of TaskTime} localTimes les temps crees localement + * @param {Array of TreeNode} children les enfants de ce noeud + * @returns {TreeNode} + */ +var TreeNode = function (task, globalTime, localTimes, children) { + this.task = task || new Task("root"); + this.globalTime = globalTime || new GlobalTime(); + this.localTimes = localTimes || []; + children = angular.forEach(children, function(child) { + child.parent = this; + }, this); + this.children = children || []; +}; + +/** + * Ce retire de l'arbre + * @returns {undefined} + */ +TreeNode.prototype.remove = function() { + if (this.parent) { + var brothers = this.parent.children; + var match = brothers.indexOf(this); + + if (match > -1 ) { + brothers.splice(match, 1); + delete this.parent; + } + } +}; + +TreeNode.prototype.addChild = function(node) { + node.parent = this; + this.children.push(node); +}; + +/** + * Copie toutes les donnees d'etat d'une noeud + * @param {TreeNode} node + * @returns {undefined} + */ +TreeNode.prototype.copyState = function(node) { + this.$$open = node.$$open; +}; + +/** + * Met a jour les temps locaux + * + * @param {Array of TaskTime} taskTimes + * @returns {undefined} + */ +TreeNode.prototype.setTaskTimes = function(taskTimes) { + this.localTimes = taskTimes; +}; + +/** + * Retourne le temps consolide pour ce noeud (temps glocal + locaux + enfant) + * @returns {GlobalTime} + */ +TreeNode.prototype.getTime = function() { + var result = new GlobalTime(); + result.addGlobalTime(this.globalTime); + result.addTaskTimes(this.localTimes); + angular.forEach(this.children, function(node) { + var nodeTime = node.getTime(); + result.addGlobalTime(nodeTime); + }); + return result; +}; + +/** + * Objet permettant de stocke le temps total et le temps de la journee actuelle + * + * @param {Task} task + * @returns {GlobalTime} + */ +var GlobalTime = function (task) { + this.taskId = task && task.taskId; + this.today = 0; + this.global = 0; +}; + +/** + * Fait une copie de l'objet + * @returns {GlobalTime} + */ +GlobalTime.prototype.clone = function() { + var result = new GlobalTime(); + result.add(this); + return result; +}; + +/** + * Ajoute les temps d'un GlobalTime + * @param {GlobalTime} globalTime + * @returns {GlobalTime} this + */ +GlobalTime.prototype.addGlobalTime = function(globalTime) { + this.global += globalTime.global; + this.today += globalTime.today; + return this; +}; + +/** + * 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 + * @returns {GlobalTime} this + */ +GlobalTime.prototype.addTaskTimes = function(taskTimes) { + angular.forEach(taskTimes, function(taskTime) { + this.global += taskTime.time; + if (taskTime.isToday()) { + this.today += taskTime.time; + } + }, this); + return this; +}; + +/** + * Represente une tache + * @param {type} name le nom de la tache + * @param {type} parentTaskId l'identifiant de la tache parente + * @returns {Task} + */ +var Task = function (name, parentTaskId) { + this.taskId = generateUUID(); + this.creationDate = Date.now(); + this.modificationDate = this.creationDate; + this.removed = 0; + this.parentTaskId = parentTaskId; + this.name = name; + this.description = ""; + this.tags = []; + this.syncOptions = {}; +}; + +/** + * Marque la tache comme supprimee + * @returns {undefined} + */ +Task.prototype.remove = function() { + this.removed = Date.now(); +}; + +/** + * return vrai si la tache est supprimee + * @returns {boolean} + */ +Task.prototype.isRemoved = function() { + return !!this.removed; +}; + +/** + * Retourne vrai si la tache est parent de la sous tache passee en parametre + * @param {Task} subtask + * @returns {Boolean} + */ +Task.prototype.isParentOf = function(subtask) { + var result = subtask.parentTaskId === this.taskId; + return result; +}; + +/** + * Indique si la tache est une tache root (pas de parent) + * @returns {unresolved} + */ +Task.prototype.isRoot = function() { + var result = !this.parentTaskId; + return result; +}; + +/** + * Permet de conserve une temps cree localement + * @param {Task} task + * @returns {TaskTime} + */ +var TaskTime = function (task) { + this.taskId = task && task.taskId; + this.timeId = generateUUID(); + this.date = today(); + this.time = 0; +}; + +/** + * Retourne vrai si ce temps est pour aujourd'hui + * @returns {Boolean} + */ +TaskTime.prototype.isToday = function() { + var result = this.date === today(); + return result; +}; + +/** + * ajoute du temps + * @param {Number} t + * @returns {TaskTime} this + */ +TaskTime.prototype.addTime = function(t) { + this.time += t; + if (this.time < 0) { + this.time = 0; + } + return this; +}; + +/** + * Represente une note pour une tache + * @param {Task} task + * @returns {TaskNote} + */ +var TaskNote = function (task) { + this.taskId = task && task.taskId; + this.noteId = generateUUID(); + this.date = today(); + this.text = ""; +}; + +/** + * Retourne vrai si cette note est pour aujourd'hui + * @returns {Boolean} + */ +TaskNote.prototype.isToday = function() { + var result = this.date === today(); + return result; +}; + Deleted: branches/ng-jtimer/src/main/webapp/js/filters.js =================================================================== --- branches/ng-jtimer/jtimer-server/src/main/webapp/js/filters.js 2014-02-06 20:44:47 UTC (rev 2952) +++ branches/ng-jtimer/src/main/webapp/js/filters.js 2014-04-14 19:13:31 UTC (rev 2956) @@ -1,8 +0,0 @@ -var wtFilter = function(input) { - var date = moment(input).utc(); - return date.diff(moment(0), 'hours') + ":" +date.format("mm:ss"); -}; - -angular.module('webtimerFilters', []).filter('time', function() { - return wtFilter; -}); Copied: branches/ng-jtimer/src/main/webapp/js/filters.js (from rev 2951, branches/ng-jtimer/jtimer-server/src/main/webapp/js/filters.js) =================================================================== --- branches/ng-jtimer/src/main/webapp/js/filters.js (rev 0) +++ branches/ng-jtimer/src/main/webapp/js/filters.js 2014-04-14 19:13:31 UTC (rev 2956) @@ -0,0 +1,8 @@ +var wtFilter = function(input) { + var date = moment(input).utc(); + return date.diff(moment(0), 'hours') + ":" +date.format("mm:ss"); +}; + +angular.module('webtimerFilters', []).filter('time', function() { + return wtFilter; +});
participants (1)
-
echatellier@users.chorem.org